fix(spawn): stop WW/artifact villages colliding on axis tiles [#301] (#308)

generateBase()'s four sector predicates overlapped on the axes: a tile
with x = 0 or y = 0 satisfied two of them (e.g. both "x <= 0" and
"x >= 0" matched x = 0). createWWVillages() and addArtifactVillages()
generate a whole batch in one go and only flip occupied = 0 -> 1 at the
very end (setFieldTaken()), so two sectors could each select the SAME
axis tile and assign its wref to two different villages. The duplicate
addVillage() insert then violated the vdata PRIMARY KEY(wref); under the
PHP 8.1+ mysqli exception mode this threw and aborted generateVillages()
before setFieldTaken()/addResourceFields()/addUnits() ran. The result:
the villages existed in vdata (and showed up under the Natars profile)
but their map tile was never marked occupied and had no resource fields
or troops, so the map still rendered an "abandoned valley" (issue #301).

Make the four sectors mutually exclusive by using a strict bound on one
side of each axis, so every tile belongs to exactly one sector and no
wref can be handed out twice within a batch.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Ferywir
2026-06-29 10:54:23 +02:00
committed by GitHub
parent e1847bc50b
commit 299e3c7338
+16 -4
View File
@@ -1416,11 +1416,23 @@ class MYSQLi_DB implements IDbConnection {
break;
}
// The four sectors must be mutually exclusive: any tile sitting on an
// axis (x = 0 or y = 0) used to satisfy two of the predicates below
// (e.g. "x <= 0" and "x >= 0" both matched x = 0). When a batch was
// spread over several sectors (WW villages, artifact villages),
// occupied = 0 was only flipped at the very end by setFieldTaken(),
// so two sectors could each pick the SAME axis tile and assign its
// wref to two villages. The duplicate addVillage() insert then hit
// the vdata PRIMARY KEY(wref) and aborted generateVillages() before
// setFieldTaken() ran, leaving the villages in vdata (visible in the
// Natars profile) but never marked on the map (issue #301). Using
// strict bounds on one side of each axis partitions the plane so a
// tile belongs to exactly one sector.
switch($sector){
case 1: $newSector = "x <= 0 AND y >= 0"; break; // - | +
case 2: $newSector = "x >= 0 AND y >= 0"; break; // + | +
case 3: $newSector = "x <= 0 AND y <= 0"; break; // - | -
default: $newSector = "x >= 0 AND y <= 0"; // + | -
case 1: $newSector = "x < 0 AND y >= 0"; break; // - | +
case 2: $newSector = "x >= 0 AND y > 0"; break; // + | +
case 3: $newSector = "x <= 0 AND y < 0"; break; // - | -
default: $newSector = "x > 0 AND y <= 0"; // + | -
}
//Choose villages beetween two circumferences, by using their formula (x^2 + y^2 = r^2)