fix(wilderness): add seed diversity to Bloody Foothills obstacle placement
- Apply RNG jitter to obstacle placement coordinates and lengths across frontline zones - Preserve the unblocked central corridor along y=24 - Track procedural walls and roads in siege topography stats - Add unit test in tests/wilderness-siege-strips.test.ts verifying seed-based obstacle variance TAG=agy CONV=2a1934de-30ef-464e-b3f3-fcbcdbbc49f1
This commit is contained in:
parent
53d6cdd08c
commit
6de9fce610
|
|
@ -416,34 +416,34 @@ export function stampAct5SiegeStrips(
|
|||
// Zone 1: West Frontline (x in [0, 80)) - High density (Shenk's stronghold)
|
||||
// -------------------------------------------------------------------------
|
||||
// Trenches (3 trenches)
|
||||
totalTrenchCells += stampTrench(canvas, 18, 8, 10, 'vertical', rng)
|
||||
totalTrenchCells += stampTrench(canvas, 50, 28, 10, 'vertical', rng)
|
||||
totalTrenchCells += stampTrench(canvas, 34, 12, 7, 'horizontal', rng)
|
||||
totalTrenchCells += stampTrench(canvas, 18 + rng.int(-2, 2), 8 + rng.int(-1, 1), 10 + rng.int(-1, 1), 'vertical', rng)
|
||||
totalTrenchCells += stampTrench(canvas, 50 + rng.int(-2, 2), 28 + rng.int(-1, 1), 10 + rng.int(-1, 1), 'vertical', rng)
|
||||
totalTrenchCells += stampTrench(canvas, 34 + rng.int(-2, 2), 12 + rng.int(-1, 1), 7 + rng.int(-1, 1), 'horizontal', rng)
|
||||
westObstacles += 3
|
||||
|
||||
// Breached Barricades (3 barricades)
|
||||
const b1 = stampBreachedBarricade(canvas, 26, 10, 24, 21, 5, rng)
|
||||
const b1 = stampBreachedBarricade(canvas, 26 + rng.int(-2, 2), 10 + rng.int(-1, 1), 24, 21 + rng.int(0, 1), 5, rng)
|
||||
totalBarricadeWalls += b1.wallCount
|
||||
totalTrenchCells += b1.breachFloorCount
|
||||
|
||||
const b2 = stampBreachedBarricade(canvas, 42, 8, 12, 13, 3, rng)
|
||||
const b2 = stampBreachedBarricade(canvas, 42 + rng.int(-2, 2), 8 + rng.int(-1, 1), 12, 13, 3, rng)
|
||||
totalBarricadeWalls += b2.wallCount
|
||||
totalTrenchCells += b2.breachFloorCount
|
||||
|
||||
const b3 = stampBreachedBarricade(canvas, 68, 26, 12, 31, 3, rng)
|
||||
const b3 = stampBreachedBarricade(canvas, 68 + rng.int(-2, 2), 26 + rng.int(-1, 1), 12, 31, 3, rng)
|
||||
totalBarricadeWalls += b3.wallCount
|
||||
totalTrenchCells += b3.breachFloorCount
|
||||
westObstacles += 3
|
||||
|
||||
// Catapult Platforms (2 platforms)
|
||||
stampCatapultPlatform(canvas, 12, 10, 4, 4, rng)
|
||||
stampCatapultPlatform(canvas, 58, 30, 4, 4, rng)
|
||||
stampCatapultPlatform(canvas, 12 + rng.int(-2, 2), 10 + rng.int(-1, 1), 4, 4, rng)
|
||||
stampCatapultPlatform(canvas, 58 + rng.int(-2, 2), 30 + rng.int(-1, 1), 4, 4, rng)
|
||||
catapultPlatformCount += 2
|
||||
westObstacles += 2
|
||||
|
||||
// Fort Ruins (2 ruins)
|
||||
stampFortRuin(canvas, 30, 30, 4, rng)
|
||||
stampFortRuin(canvas, 64, 10, 4, rng)
|
||||
stampFortRuin(canvas, 30 + rng.int(-2, 2), 30 + rng.int(-1, 1), 4, rng)
|
||||
stampFortRuin(canvas, 64 + rng.int(-2, 2), 10 + rng.int(-1, 1), 4, rng)
|
||||
fortRuinCount += 2
|
||||
westObstacles += 2
|
||||
|
||||
|
|
@ -451,27 +451,27 @@ export function stampAct5SiegeStrips(
|
|||
// Zone 2: Mid Field (x in [80, 160)) - Medium density (No-man's land)
|
||||
// -------------------------------------------------------------------------
|
||||
// Trenches (2 trenches)
|
||||
totalTrenchCells += stampTrench(canvas, 98, 10, 10, 'vertical', rng)
|
||||
totalTrenchCells += stampTrench(canvas, 138, 28, 10, 'vertical', rng)
|
||||
totalTrenchCells += stampTrench(canvas, 98 + rng.int(-2, 2), 10 + rng.int(-1, 1), 10 + rng.int(-1, 1), 'vertical', rng)
|
||||
totalTrenchCells += stampTrench(canvas, 138 + rng.int(-2, 2), 28 + rng.int(-1, 1), 10 + rng.int(-1, 1), 'vertical', rng)
|
||||
midObstacles += 2
|
||||
|
||||
// Breached Barricades (2 barricades)
|
||||
const b4 = stampBreachedBarricade(canvas, 114, 10, 24, 21, 5, rng)
|
||||
const b4 = stampBreachedBarricade(canvas, 114 + rng.int(-2, 2), 10 + rng.int(-1, 1), 24, 21 + rng.int(0, 1), 5, rng)
|
||||
totalBarricadeWalls += b4.wallCount
|
||||
totalTrenchCells += b4.breachFloorCount
|
||||
|
||||
const b5 = stampBreachedBarricade(canvas, 146, 8, 12, 13, 3, rng)
|
||||
const b5 = stampBreachedBarricade(canvas, 146 + rng.int(-2, 2), 8 + rng.int(-1, 1), 12, 13, 3, rng)
|
||||
totalBarricadeWalls += b5.wallCount
|
||||
totalTrenchCells += b5.breachFloorCount
|
||||
midObstacles += 2
|
||||
|
||||
// Catapult Platforms (1 platform)
|
||||
stampCatapultPlatform(canvas, 86, 30, 4, 4, rng)
|
||||
stampCatapultPlatform(canvas, 86 + rng.int(-2, 2), 30 + rng.int(-1, 1), 4, 4, rng)
|
||||
catapultPlatformCount += 1
|
||||
midObstacles += 1
|
||||
|
||||
// Fort Ruins (1 ruin)
|
||||
stampFortRuin(canvas, 124, 10, 4, rng)
|
||||
stampFortRuin(canvas, 124 + rng.int(-2, 2), 10 + rng.int(-1, 1), 4, rng)
|
||||
fortRuinCount += 1
|
||||
midObstacles += 1
|
||||
|
||||
|
|
@ -479,11 +479,11 @@ export function stampAct5SiegeStrips(
|
|||
// Zone 3: East Rear (x in [160, 240)) - Low density (Harrogath outskirts)
|
||||
// -------------------------------------------------------------------------
|
||||
// Trenches (1 trench)
|
||||
totalTrenchCells += stampTrench(canvas, 186, 12, 10, 'vertical', rng)
|
||||
totalTrenchCells += stampTrench(canvas, 186 + rng.int(-2, 2), 12 + rng.int(-1, 1), 10 + rng.int(-1, 1), 'vertical', rng)
|
||||
eastObstacles += 1
|
||||
|
||||
// Breached Barricades (1 barricade)
|
||||
const b6 = stampBreachedBarricade(canvas, 202, 10, 24, 21, 5, rng)
|
||||
const b6 = stampBreachedBarricade(canvas, 202 + rng.int(-2, 2), 10 + rng.int(-1, 1), 24, 21 + rng.int(0, 1), 5, rng)
|
||||
totalBarricadeWalls += b6.wallCount
|
||||
totalTrenchCells += b6.breachFloorCount
|
||||
eastObstacles += 1
|
||||
|
|
@ -491,7 +491,7 @@ export function stampAct5SiegeStrips(
|
|||
// Catapult Platforms (0 platforms in rear reserve)
|
||||
|
||||
// Fort Ruins (1 ruin)
|
||||
stampFortRuin(canvas, 170, 30, 4, rng)
|
||||
stampFortRuin(canvas, 170 + rng.int(-2, 2), 30 + rng.int(-1, 1), 4, rng)
|
||||
fortRuinCount += 1
|
||||
eastObstacles += 1
|
||||
|
||||
|
|
@ -510,6 +510,8 @@ export function stampAct5SiegeStrips(
|
|||
}
|
||||
|
||||
stats.siegeTopography = siegeStats
|
||||
stats.proceduralWallCells = (stats.proceduralWallCells ?? 0) + totalBarricadeWalls
|
||||
stats.proceduralRoadCells = (stats.proceduralRoadCells ?? 0) + totalTrenchCells
|
||||
stats.notes.push('generated dynamic siege trenches and fortifications')
|
||||
|
||||
return placed
|
||||
|
|
|
|||
|
|
@ -415,4 +415,59 @@ describe("Act 5 Bloody Foothills Dynamic Siege Generation (DRLGOUTSIEGE)", () =>
|
|||
expect(notes).toContain("generated dynamic siege trenches and fortifications")
|
||||
expect(result.stats.siegeTopography).toBeDefined()
|
||||
})
|
||||
|
||||
test("generates varied obstacle layouts with different seeds (seed diversity)", () => {
|
||||
const pieces = createMockSiegePieces()
|
||||
const result1 = generateWilderness({
|
||||
levelId: 110,
|
||||
levelName: "Bloody Foothills",
|
||||
levelTypeName: "Act 5 - Siege",
|
||||
sizeX: 240,
|
||||
sizeY: 48,
|
||||
subType: -1,
|
||||
subTheme: -1,
|
||||
seed: 11001,
|
||||
pieces,
|
||||
substitutions: [],
|
||||
})
|
||||
|
||||
const result2 = generateWilderness({
|
||||
levelId: 110,
|
||||
levelName: "Bloody Foothills",
|
||||
levelTypeName: "Act 5 - Siege",
|
||||
sizeX: 240,
|
||||
sizeY: 48,
|
||||
subType: -1,
|
||||
subTheme: -1,
|
||||
seed: 11002,
|
||||
pieces,
|
||||
substitutions: [],
|
||||
})
|
||||
|
||||
// Collect obstacle wall coordinates for both seeds
|
||||
const walls1 = new Set<string>()
|
||||
const walls2 = new Set<string>()
|
||||
|
||||
for (let y = 0; y < result1.level.height; y += 1) {
|
||||
for (let x = 0; x < result1.level.width; x += 1) {
|
||||
if (result1.level.cells[y]![x]!.walls.some(w => !w.hidden && w.prop1 !== 0)) {
|
||||
walls1.add(`${x},${y}`)
|
||||
}
|
||||
if (result2.level.cells[y]![x]!.walls.some(w => !w.hidden && w.prop1 !== 0)) {
|
||||
walls2.add(`${x},${y}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Both should have placed walls
|
||||
expect(walls1.size).toBeGreaterThan(0)
|
||||
expect(walls2.size).toBeGreaterThan(0)
|
||||
|
||||
// The obstacle coordinates must differ across different seeds
|
||||
let diffCount = 0
|
||||
for (const coord of walls1) {
|
||||
if (!walls2.has(coord)) diffCount += 1
|
||||
}
|
||||
expect(diffCount).toBeGreaterThan(0)
|
||||
})
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in New Issue