diff --git a/src/render/Panels.cpp b/src/render/Panels.cpp index ad9e3ca..4193132 100644 --- a/src/render/Panels.cpp +++ b/src/render/Panels.cpp @@ -34,7 +34,8 @@ static int drawWrapped(const std::string& text, int x, int y, int font, Color co static std::vector cellInfo(const Planet& p, int i, double elev, double age) { const Cell& c = p.cells[i]; double lon, lat; dirToLonLat(c.unit, lon, lat); - const Plate& pl = p.plates[c.plateId]; + static const Plate kUnknownPlate{}; // defensive: a cell should always own a valid plate + const Plate& pl = (c.plateId >= 0 && c.plateId < (int)p.plates.size()) ? p.plates[c.plateId] : kUnknownPlate; const int n = (int)p.cells.size(); auto sized = [&](const std::vector& v) { return (int)v.size() == n; }; std::vector L; diff --git a/src/render/Viewer.cpp b/src/render/Viewer.cpp index dbc1b74..4207e30 100644 --- a/src/render/Viewer.cpp +++ b/src/render/Viewer.cpp @@ -284,6 +284,7 @@ void Viewer::regenWorld() { // after generate(): geometry change buildDriftArrows(planet, driftR, driftArrows, plateLabels); buildMap2D(planet, mapRect, map2D); selectedCell = -1; subgrids.clear(); + mapZoom = 1.0; mapPanX = 0.0; mapPanY = 0.0; // drop any 2D-map zoom/pan from the old world settled = false; settleRun = 0; formAccum = 0.0; stepCount = 0; paused = false; liveWorld = false; followId = 0; wxUndo.clear(); events.clear(); nextEventId = 1; // reseed/regen drops back to World Creation liveInfoTab = 0; eventRowRects.clear(); eventRowIndices.clear(); diff --git a/src/sim/PlanetDrift.cpp b/src/sim/PlanetDrift.cpp index 881c487..1d34361 100644 --- a/src/sim/PlanetDrift.cpp +++ b/src/sim/PlanetDrift.cpp @@ -34,8 +34,12 @@ void Planet::advect(double dtMy) { std::vector vel(n); for (int i = 0; i < n; ++i) { oP[i] = cells[i].plateId; oE[i] = cells[i].elevation; oA[i] = cells[i].geoAge; oO[i] = cells[i].oceanic; - const Plate& p = plates[cells[i].plateId]; - vel[i] = (p.driftAxis * p.angSpeed).cross(cells[i].unit) * R; + if (cells[i].plateId >= 0 && cells[i].plateId < (int)plates.size()) { + const Plate& p = plates[cells[i].plateId]; + vel[i] = (p.driftAxis * p.angSpeed).cross(cells[i].unit) * R; + } else { + vel[i] = Vec3(); // defensive: a cell should always own a valid plate + } } for (int c = 0; c < n; ++c) { diff --git a/src/sim/PlanetIO.cpp b/src/sim/PlanetIO.cpp index eb4df0f..95d5936 100644 --- a/src/sim/PlanetIO.cpp +++ b/src/sim/PlanetIO.cpp @@ -756,6 +756,8 @@ bool Planet::readState(std::istream& is, bool hasBiome, bool hasBiota, bool hasM readPod(is, w.id); readPod(is, w.attacker); readPod(is, w.defender); readPod(is, w.startYear); readPod(is, w.warscore); readPod(is, w.battles); if (!is || !std::isfinite(w.warscore)) return false; + if (w.attacker < 0 || w.attacker >= (int)settlements.size() + || w.defender < 0 || w.defender >= (int)settlements.size()) return false; } readPod(is, sWarRng); readPod(is, sWarNextId); if (!sWarRng) sWarRng = cfg.seed ? (cfg.seed ^ 0x5A7B0A11u) : 0x5A7B0A11u; @@ -771,6 +773,8 @@ bool Planet::readState(std::istream& is, bool hasBiome, bool hasBiota, bool hasM readPod(is, t.truceUntil); uint8_t k = 0; readPod(is, k); t.kind = (k <= (uint8_t)DiploKind::Rival) ? (DiploKind)k : DiploKind::Neutral; if (!is || !std::isfinite(t.attitude)) return false; + if (t.a < 0 || t.a >= (int)settlements.size() + || t.b < 0 || t.b >= (int)settlements.size()) return false; } } computeBiotaDensity(); // derived density scalars for the colour views