diff --git a/src/game/wilderness-siege.ts b/src/game/wilderness-siege.ts index e223e70..baa12c1 100644 --- a/src/game/wilderness-siege.ts +++ b/src/game/wilderness-siege.ts @@ -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 diff --git a/tests/wilderness-siege-strips.test.ts b/tests/wilderness-siege-strips.test.ts index 204b05f..54751a7 100644 --- a/tests/wilderness-siege-strips.test.ts +++ b/tests/wilderness-siege-strips.test.ts @@ -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() + const walls2 = new Set() + + 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) + }) })