test: expand slay-the-spire-like map generator tests
This commit is contained in:
parent
43bb246ab9
commit
3840c3d739
|
|
@ -1,19 +1,26 @@
|
|||
import { describe, it, expect } from 'vitest';
|
||||
import { generatePointCrawlMap, hasPath } from '@/samples/slay-the-spire-like/system/map/generator';
|
||||
import { MapNodeType, MapLayerType } from '@/samples/slay-the-spire-like/system/map/types';
|
||||
import { createRNG } from '@/utils/rng';
|
||||
import { encounters } from '@/samples/slay-the-spire-like/data/desert';
|
||||
import { describe, it, expect } from "vitest";
|
||||
import {
|
||||
generatePointCrawlMap,
|
||||
hasPath,
|
||||
} from "@/samples/slay-the-spire-like/system/map/generator";
|
||||
import {
|
||||
MapNodeType,
|
||||
MapLayerType,
|
||||
} from "@/samples/slay-the-spire-like/system/map/types";
|
||||
import { createRNG } from "@/utils/rng";
|
||||
import { getEncounters } from "@/samples/slay-the-spire-like/data/desert";
|
||||
const encounters = getEncounters();
|
||||
|
||||
describe('generatePointCrawlMap', () => {
|
||||
it('should generate a map with 10 layers', () => {
|
||||
describe("generatePointCrawlMap", () => {
|
||||
it("should generate a map with 10 layers", () => {
|
||||
const map = generatePointCrawlMap(createRNG(123), encounters);
|
||||
expect(map.layers.length).toBe(10);
|
||||
});
|
||||
|
||||
it('should have correct layer structure', () => {
|
||||
it("should have correct layer structure", () => {
|
||||
const map = generatePointCrawlMap(createRNG(123), encounters);
|
||||
const expectedStructure = [
|
||||
'start',
|
||||
"start",
|
||||
MapLayerType.Wild,
|
||||
MapLayerType.Wild,
|
||||
MapLayerType.Settlement,
|
||||
|
|
@ -22,7 +29,7 @@ describe('generatePointCrawlMap', () => {
|
|||
MapLayerType.Settlement,
|
||||
MapLayerType.Wild,
|
||||
MapLayerType.Wild,
|
||||
'end',
|
||||
"end",
|
||||
];
|
||||
|
||||
for (let i = 0; i < expectedStructure.length; i++) {
|
||||
|
|
@ -30,7 +37,7 @@ describe('generatePointCrawlMap', () => {
|
|||
}
|
||||
});
|
||||
|
||||
it('should have correct node counts per layer', () => {
|
||||
it("should have correct node counts per layer", () => {
|
||||
const map = generatePointCrawlMap(createRNG(123), encounters);
|
||||
const expectedCounts = [1, 3, 3, 4, 3, 3, 4, 3, 3, 1];
|
||||
|
||||
|
|
@ -39,19 +46,23 @@ describe('generatePointCrawlMap', () => {
|
|||
}
|
||||
});
|
||||
|
||||
it('should have Start and End nodes with correct types', () => {
|
||||
it("should have Start and End nodes with correct types", () => {
|
||||
const map = generatePointCrawlMap(createRNG(123), encounters);
|
||||
const startNode = map.nodes.get('node-0-0');
|
||||
const endNode = map.nodes.get('node-9-0');
|
||||
const startNode = map.nodes.get("node-0-0");
|
||||
const endNode = map.nodes.get("node-9-0");
|
||||
|
||||
expect(startNode?.type).toBe(MapNodeType.Start);
|
||||
expect(endNode?.type).toBe(MapNodeType.End);
|
||||
});
|
||||
|
||||
it('should have wild layers with minion/elite/event types', () => {
|
||||
it("should have wild layers with minion/elite/event types", () => {
|
||||
const map = generatePointCrawlMap(createRNG(123), encounters);
|
||||
const wildLayerIndices = [1, 2, 4, 5, 7, 8];
|
||||
const validWildTypes = new Set([MapNodeType.Minion, MapNodeType.Elite, MapNodeType.Event]);
|
||||
const validWildTypes = new Set([
|
||||
MapNodeType.Minion,
|
||||
MapNodeType.Elite,
|
||||
MapNodeType.Event,
|
||||
]);
|
||||
|
||||
for (const layerIdx of wildLayerIndices) {
|
||||
const layer = map.layers[layerIdx];
|
||||
|
|
@ -63,13 +74,13 @@ describe('generatePointCrawlMap', () => {
|
|||
}
|
||||
});
|
||||
|
||||
it('should have settlement layers with at least 1 camp, 1 shop, 1 curio', () => {
|
||||
it("should have settlement layers with at least 1 camp, 1 shop, 1 curio", () => {
|
||||
const map = generatePointCrawlMap(createRNG(123), encounters);
|
||||
const settlementLayerIndices = [3, 6];
|
||||
|
||||
for (const layerIdx of settlementLayerIndices) {
|
||||
const layer = map.layers[layerIdx];
|
||||
const nodeTypes = layer.nodeIds.map(id => map.nodes.get(id)!.type);
|
||||
const nodeTypes = layer.nodeIds.map((id) => map.nodes.get(id)!.type);
|
||||
|
||||
expect(nodeTypes).toContain(MapNodeType.Camp);
|
||||
expect(nodeTypes).toContain(MapNodeType.Shop);
|
||||
|
|
@ -78,16 +89,18 @@ describe('generatePointCrawlMap', () => {
|
|||
}
|
||||
});
|
||||
|
||||
it('should have Start connected to all 3 wild nodes', () => {
|
||||
it("should have Start connected to all 3 wild nodes", () => {
|
||||
const map = generatePointCrawlMap(createRNG(42), encounters);
|
||||
const startNode = map.nodes.get('node-0-0');
|
||||
const startNode = map.nodes.get("node-0-0");
|
||||
const wildLayer = map.layers[1];
|
||||
|
||||
expect(startNode?.childIds.length).toBe(3);
|
||||
expect(startNode?.childIds).toEqual(expect.arrayContaining(wildLayer.nodeIds));
|
||||
expect(startNode?.childIds).toEqual(
|
||||
expect.arrayContaining(wildLayer.nodeIds),
|
||||
);
|
||||
});
|
||||
|
||||
it('should have each wild node connect to 1 wild node in wild→wild layers', () => {
|
||||
it("should have each wild node connect to 1 wild node in wild→wild layers", () => {
|
||||
const map = generatePointCrawlMap(createRNG(42), encounters);
|
||||
const wildToWildTransitions = [
|
||||
{ src: 1, tgt: 2 },
|
||||
|
|
@ -106,7 +119,7 @@ describe('generatePointCrawlMap', () => {
|
|||
}
|
||||
});
|
||||
|
||||
it('should have each wild node connect to 2 settlement nodes in wild→settlement layers', () => {
|
||||
it("should have each wild node connect to 2 settlement nodes in wild→settlement layers", () => {
|
||||
const map = generatePointCrawlMap(createRNG(42), encounters);
|
||||
const wildToSettlementTransitions = [
|
||||
{ src: 2, tgt: 3 },
|
||||
|
|
@ -126,7 +139,7 @@ describe('generatePointCrawlMap', () => {
|
|||
}
|
||||
});
|
||||
|
||||
it('should have settlement nodes connect correctly (1-2-2-1 pattern)', () => {
|
||||
it("should have settlement nodes connect correctly (1-2-2-1 pattern)", () => {
|
||||
const map = generatePointCrawlMap(createRNG(42), encounters);
|
||||
const settlementToWildTransitions = [
|
||||
{ src: 3, tgt: 4 },
|
||||
|
|
@ -154,10 +167,10 @@ describe('generatePointCrawlMap', () => {
|
|||
}
|
||||
});
|
||||
|
||||
it('should have all 3 wild nodes connect to End', () => {
|
||||
it("should have all 3 wild nodes connect to End", () => {
|
||||
const map = generatePointCrawlMap(createRNG(42), encounters);
|
||||
const lastWildLayer = map.layers[8];
|
||||
const endNode = map.nodes.get('node-9-0');
|
||||
const endNode = map.nodes.get("node-9-0");
|
||||
|
||||
for (const wildId of lastWildLayer.nodeIds) {
|
||||
const wildNode = map.nodes.get(wildId);
|
||||
|
|
@ -165,10 +178,10 @@ describe('generatePointCrawlMap', () => {
|
|||
}
|
||||
});
|
||||
|
||||
it('should have all nodes reachable from Start and can reach End', () => {
|
||||
it("should have all nodes reachable from Start and can reach End", () => {
|
||||
const map = generatePointCrawlMap(createRNG(123), encounters);
|
||||
const startId = 'node-0-0';
|
||||
const endId = 'node-9-0';
|
||||
const startId = "node-0-0";
|
||||
const endId = "node-9-0";
|
||||
|
||||
for (const nodeId of map.nodes.keys()) {
|
||||
if (nodeId === startId || nodeId === endId) continue;
|
||||
|
|
@ -177,7 +190,7 @@ describe('generatePointCrawlMap', () => {
|
|||
}
|
||||
});
|
||||
|
||||
it('should not have crossing edges in wild→wild transitions', () => {
|
||||
it("should not have crossing edges in wild→wild transitions", () => {
|
||||
const map = generatePointCrawlMap(createRNG(12345), encounters);
|
||||
const wildToWildTransitions = [
|
||||
{ src: 1, tgt: 2 },
|
||||
|
|
@ -215,7 +228,7 @@ describe('generatePointCrawlMap', () => {
|
|||
}
|
||||
});
|
||||
|
||||
it('should not have crossing edges in wild→settlement transitions', () => {
|
||||
it("should not have crossing edges in wild→settlement transitions", () => {
|
||||
const map = generatePointCrawlMap(createRNG(12345), encounters);
|
||||
const wildToSettlementTransitions = [
|
||||
{ src: 2, tgt: 3 },
|
||||
|
|
@ -252,7 +265,7 @@ describe('generatePointCrawlMap', () => {
|
|||
}
|
||||
});
|
||||
|
||||
it('should not have crossing edges in settlement→wild transitions', () => {
|
||||
it("should not have crossing edges in settlement→wild transitions", () => {
|
||||
const map = generatePointCrawlMap(createRNG(12345), encounters);
|
||||
const settlementToWildTransitions = [
|
||||
{ src: 3, tgt: 4 },
|
||||
|
|
@ -289,7 +302,7 @@ describe('generatePointCrawlMap', () => {
|
|||
}
|
||||
});
|
||||
|
||||
it('should assign encounters to all non-Start/End nodes', () => {
|
||||
it("should assign encounters to all non-Start/End nodes", () => {
|
||||
const map = generatePointCrawlMap(createRNG(456), encounters);
|
||||
|
||||
for (const node of map.nodes.values()) {
|
||||
|
|
@ -298,14 +311,17 @@ describe('generatePointCrawlMap', () => {
|
|||
expect(node.encounter).toBeUndefined();
|
||||
} else {
|
||||
// All other nodes (minion/elite/event/camp/shop/curio) must have encounters
|
||||
expect(node.encounter, `Node ${node.id} (${node.type}) should have encounter data`).toBeDefined();
|
||||
expect(
|
||||
node.encounter,
|
||||
`Node ${node.id} (${node.type}) should have encounter data`,
|
||||
).toBeDefined();
|
||||
expect(node.encounter!.name).toBeTruthy();
|
||||
expect(node.encounter!.description).toBeTruthy();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('should assign encounters to all nodes across multiple seeds', () => {
|
||||
it("should assign encounters to all nodes across multiple seeds", () => {
|
||||
// Test multiple seeds to ensure no random failure
|
||||
for (let seed = 0; seed < 20; seed++) {
|
||||
const map = generatePointCrawlMap(createRNG(seed), encounters);
|
||||
|
|
@ -314,14 +330,17 @@ describe('generatePointCrawlMap', () => {
|
|||
if (node.type === MapNodeType.Start || node.type === MapNodeType.End) {
|
||||
continue;
|
||||
}
|
||||
expect(node.encounter, `Seed ${seed}: Node ${node.id} (${node.type}) missing encounter`).toBeDefined();
|
||||
expect(
|
||||
node.encounter,
|
||||
`Seed ${seed}: Node ${node.id} (${node.type}) missing encounter`,
|
||||
).toBeDefined();
|
||||
expect(node.encounter!.name).toBeTruthy();
|
||||
expect(node.encounter!.description).toBeTruthy();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('should minimize same-layer repetitions in wild layer pairs', () => {
|
||||
it("should minimize same-layer repetitions in wild layer pairs", () => {
|
||||
// Test that wild layers in pairs (1-2, 4-5, 7-8) have minimal duplicate types within each layer
|
||||
const map = generatePointCrawlMap(createRNG(12345), encounters);
|
||||
const wildPairIndices = [
|
||||
|
|
@ -335,12 +354,12 @@ describe('generatePointCrawlMap', () => {
|
|||
const layer2 = map.layers[layer2Idx];
|
||||
|
||||
// Count repetitions in layer 1
|
||||
const layer1Types = layer1.nodeIds.map(id => map.nodes.get(id)!.type);
|
||||
const layer1Types = layer1.nodeIds.map((id) => map.nodes.get(id)!.type);
|
||||
const layer1Unique = new Set(layer1Types).size;
|
||||
const layer1Repetitions = layer1Types.length - layer1Unique;
|
||||
|
||||
// Count repetitions in layer 2
|
||||
const layer2Types = layer2.nodeIds.map(id => map.nodes.get(id)!.type);
|
||||
const layer2Types = layer2.nodeIds.map((id) => map.nodes.get(id)!.type);
|
||||
const layer2Unique = new Set(layer2Types).size;
|
||||
const layer2Repetitions = layer2Types.length - layer2Unique;
|
||||
|
||||
|
|
@ -351,7 +370,7 @@ describe('generatePointCrawlMap', () => {
|
|||
}
|
||||
});
|
||||
|
||||
it('should minimize adjacent repetitions in wild→wild connections', () => {
|
||||
it("should minimize adjacent repetitions in wild→wild connections", () => {
|
||||
// Test that wild nodes connected by wild→wild edges have different types
|
||||
const map = generatePointCrawlMap(createRNG(12345), encounters);
|
||||
const wildToWildPairs = [
|
||||
|
|
|
|||
Loading…
Reference in New Issue