lpc-forge 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/CREDITS.csv +22985 -0
  2. package/LICENSE +674 -0
  3. package/README.md +281 -0
  4. package/assets/music/.gitkeep +0 -0
  5. package/dist/character/batch.d.ts +17 -0
  6. package/dist/character/batch.js +48 -0
  7. package/dist/character/batch.js.map +1 -0
  8. package/dist/character/composer.d.ts +3 -0
  9. package/dist/character/composer.js +164 -0
  10. package/dist/character/composer.js.map +1 -0
  11. package/dist/character/definitions.d.ts +16 -0
  12. package/dist/character/definitions.js +116 -0
  13. package/dist/character/definitions.js.map +1 -0
  14. package/dist/character/presets.d.ts +6 -0
  15. package/dist/character/presets.js +246 -0
  16. package/dist/character/presets.js.map +1 -0
  17. package/dist/character/slicer.d.ts +8 -0
  18. package/dist/character/slicer.js +66 -0
  19. package/dist/character/slicer.js.map +1 -0
  20. package/dist/character/types.d.ts +48 -0
  21. package/dist/character/types.js +32 -0
  22. package/dist/character/types.js.map +1 -0
  23. package/dist/cli.d.ts +2 -0
  24. package/dist/cli.js +938 -0
  25. package/dist/export/frames.d.ts +5 -0
  26. package/dist/export/frames.js +15 -0
  27. package/dist/export/frames.js.map +1 -0
  28. package/dist/export/godot.d.ts +17 -0
  29. package/dist/export/godot.js +464 -0
  30. package/dist/export/godot.js.map +1 -0
  31. package/dist/export/types.d.ts +11 -0
  32. package/dist/export/types.js +2 -0
  33. package/dist/export/types.js.map +1 -0
  34. package/dist/license.d.ts +49 -0
  35. package/dist/license.js +271 -0
  36. package/dist/map/cellular.d.ts +3 -0
  37. package/dist/map/cellular.js +191 -0
  38. package/dist/map/cellular.js.map +1 -0
  39. package/dist/map/dungeon.d.ts +3 -0
  40. package/dist/map/dungeon.js +238 -0
  41. package/dist/map/dungeon.js.map +1 -0
  42. package/dist/map/multifloor.d.ts +20 -0
  43. package/dist/map/multifloor.js +57 -0
  44. package/dist/map/multifloor.js.map +1 -0
  45. package/dist/map/overworld.d.ts +3 -0
  46. package/dist/map/overworld.js +205 -0
  47. package/dist/map/overworld.js.map +1 -0
  48. package/dist/map/town.d.ts +7 -0
  49. package/dist/map/town.js +181 -0
  50. package/dist/map/town.js.map +1 -0
  51. package/dist/map/types.d.ts +65 -0
  52. package/dist/map/types.js +16 -0
  53. package/dist/map/types.js.map +1 -0
  54. package/dist/map/wfc.d.ts +18 -0
  55. package/dist/map/wfc.js +192 -0
  56. package/dist/map/wfc.js.map +1 -0
  57. package/dist/tileset/atlas.d.ts +15 -0
  58. package/dist/tileset/atlas.js +55 -0
  59. package/dist/tileset/atlas.js.map +1 -0
  60. package/dist/tileset/registry.d.ts +12 -0
  61. package/dist/tileset/registry.js +71 -0
  62. package/dist/tileset/registry.js.map +1 -0
  63. package/dist/tileset/terrain.d.ts +3 -0
  64. package/dist/tileset/terrain.js +110 -0
  65. package/dist/tileset/terrain.js.map +1 -0
  66. package/dist/utils/credits.d.ts +11 -0
  67. package/dist/utils/credits.js +74 -0
  68. package/dist/utils/credits.js.map +1 -0
  69. package/dist/utils/image.d.ts +17 -0
  70. package/dist/utils/image.js +94 -0
  71. package/dist/utils/image.js.map +1 -0
  72. package/dist/utils/rng.d.ts +18 -0
  73. package/dist/utils/rng.js +48 -0
  74. package/dist/utils/rng.js.map +1 -0
  75. package/package.json +77 -0
@@ -0,0 +1,181 @@
1
+ import { SeededRNG } from '../utils/rng.js';
2
+ import { TileType as TT } from './types.js';
3
+ const DEFAULT_BUILDINGS = 6;
4
+ const DEFAULT_MARKET_SIZE = 8;
5
+ export function generateTown(config) {
6
+ const { width, height, seed = Date.now(), buildings = DEFAULT_BUILDINGS, hasWall = false, marketSize = DEFAULT_MARKET_SIZE, } = config;
7
+ const rng = new SeededRNG(seed);
8
+ const numBuildings = Math.max(4, Math.min(8, buildings));
9
+ // Initialize grid with grass
10
+ const tiles = Array.from({ length: height }, () => Array(width).fill(TT.GRASS));
11
+ // Place trees around the perimeter
12
+ for (let y = 0; y < height; y++) {
13
+ for (let x = 0; x < width; x++) {
14
+ if (y < 3 || y >= height - 3 || x < 3 || x >= width - 3) {
15
+ if (rng.random() < 0.6)
16
+ tiles[y][x] = TT.TREE;
17
+ }
18
+ }
19
+ }
20
+ // Town wall (optional)
21
+ if (hasWall) {
22
+ const wMargin = 5;
23
+ for (let x = wMargin; x < width - wMargin; x++) {
24
+ tiles[wMargin][x] = TT.WALL;
25
+ tiles[height - wMargin - 1][x] = TT.WALL;
26
+ }
27
+ for (let y = wMargin; y < height - wMargin; y++) {
28
+ tiles[y][wMargin] = TT.WALL;
29
+ tiles[y][width - wMargin - 1] = TT.WALL;
30
+ }
31
+ // Gate openings
32
+ const midX = Math.floor(width / 2);
33
+ const midY = Math.floor(height / 2);
34
+ tiles[wMargin][midX] = TT.DOOR;
35
+ tiles[wMargin][midX + 1] = TT.DOOR;
36
+ tiles[height - wMargin - 1][midX] = TT.DOOR;
37
+ tiles[height - wMargin - 1][midX + 1] = TT.DOOR;
38
+ tiles[midY][wMargin] = TT.DOOR;
39
+ tiles[midY + 1][wMargin] = TT.DOOR;
40
+ tiles[midY][width - wMargin - 1] = TT.DOOR;
41
+ tiles[midY + 1][width - wMargin - 1] = TT.DOOR;
42
+ }
43
+ // Central town square
44
+ const sqSize = Math.min(marketSize, Math.floor(Math.min(width, height) / 4));
45
+ const sqX = Math.floor(width / 2 - sqSize / 2);
46
+ const sqY = Math.floor(height / 2 - sqSize / 2);
47
+ for (let dy = 0; dy < sqSize; dy++) {
48
+ for (let dx = 0; dx < sqSize; dx++) {
49
+ tiles[sqY + dy][sqX + dx] = TT.STONE;
50
+ }
51
+ }
52
+ // Market stalls in the square (small 2x2 structures)
53
+ const stallCount = Math.min(4, Math.floor(sqSize / 3));
54
+ for (let s = 0; s < stallCount; s++) {
55
+ const sx = sqX + 1 + s * 2 + s;
56
+ const sy = sqY + 1;
57
+ if (sx + 1 < sqX + sqSize - 1 && sy + 1 < sqY + sqSize - 1) {
58
+ tiles[sy][sx] = TT.WALL;
59
+ tiles[sy][sx + 1] = TT.WALL;
60
+ tiles[sy + 1][sx] = TT.FLOOR;
61
+ tiles[sy + 1][sx + 1] = TT.FLOOR;
62
+ }
63
+ }
64
+ // Place buildings around the square
65
+ const rooms = [];
66
+ const buildingPositions = [];
67
+ const zones = [
68
+ { baseX: sqX - 10, baseY: sqY - 10 }, // top-left
69
+ { baseX: sqX + sqSize + 2, baseY: sqY - 10 }, // top-right
70
+ { baseX: sqX - 10, baseY: sqY + sqSize + 2 }, // bottom-left
71
+ { baseX: sqX + sqSize + 2, baseY: sqY + sqSize + 2 }, // bottom-right
72
+ { baseX: sqX - 10, baseY: sqY }, // left
73
+ { baseX: sqX + sqSize + 2, baseY: sqY }, // right
74
+ { baseX: sqX, baseY: sqY - 10 }, // top
75
+ { baseX: sqX, baseY: sqY + sqSize + 2 }, // bottom
76
+ ];
77
+ for (let b = 0; b < numBuildings && b < zones.length; b++) {
78
+ const zone = zones[b];
79
+ const bw = rng.randomInt(4, 7);
80
+ const bh = rng.randomInt(4, 6);
81
+ const bx = Math.max(6, Math.min(width - bw - 3, zone.baseX + rng.randomInt(0, 3)));
82
+ const by = Math.max(6, Math.min(height - bh - 3, zone.baseY + rng.randomInt(0, 3)));
83
+ // Check for overlap
84
+ const overlaps = buildingPositions.some((bp) => bx < bp.x + bp.w + 1 &&
85
+ bx + bw + 1 > bp.x &&
86
+ by < bp.y + bp.h + 1 &&
87
+ by + bh + 1 > bp.y);
88
+ if (overlaps)
89
+ continue;
90
+ buildingPositions.push({ x: bx, y: by, w: bw, h: bh });
91
+ // Draw building: walls on edges, floor inside
92
+ for (let dy = 0; dy < bh; dy++) {
93
+ for (let dx = 0; dx < bw; dx++) {
94
+ const ty = by + dy;
95
+ const tx = bx + dx;
96
+ if (ty >= 0 && ty < height && tx >= 0 && tx < width) {
97
+ if (dy === 0 || dy === bh - 1 || dx === 0 || dx === bw - 1) {
98
+ tiles[ty][tx] = TT.WALL;
99
+ }
100
+ else {
101
+ tiles[ty][tx] = TT.FLOOR;
102
+ }
103
+ }
104
+ }
105
+ }
106
+ // Door on the south wall
107
+ const doorX = bx + Math.floor(bw / 2);
108
+ if (by + bh - 1 < height) {
109
+ tiles[by + bh - 1][doorX] = TT.DOOR;
110
+ }
111
+ rooms.push({
112
+ id: rooms.length,
113
+ x: bx,
114
+ y: by,
115
+ width: bw,
116
+ height: bh,
117
+ connections: [],
118
+ });
119
+ }
120
+ // Roads connecting buildings to the town square center
121
+ const sqCenterX = sqX + Math.floor(sqSize / 2);
122
+ const sqCenterY = sqY + Math.floor(sqSize / 2);
123
+ for (const bp of buildingPositions) {
124
+ const doorX = bp.x + Math.floor(bp.w / 2);
125
+ const doorY = bp.y + bp.h;
126
+ carvePath(tiles, doorX, doorY, sqCenterX, sqCenterY, width, height);
127
+ }
128
+ // Connect rooms sequentially
129
+ for (let i = 0; i < rooms.length - 1; i++) {
130
+ rooms[i].connections.push(rooms[i + 1].id);
131
+ rooms[i + 1].connections.push(rooms[i].id);
132
+ }
133
+ // POIs
134
+ const pois = [];
135
+ pois.push({ x: sqCenterX, y: sqCenterY, type: 'spawn', label: 'Town Square' });
136
+ for (let i = 0; i < rooms.length && i < 3; i++) {
137
+ const r = rooms[i];
138
+ pois.push({
139
+ x: r.x + Math.floor(r.width / 2),
140
+ y: r.y + Math.floor(r.height / 2),
141
+ type: 'npc',
142
+ label: `Shopkeeper ${i + 1}`,
143
+ });
144
+ }
145
+ if (rooms.length > 0) {
146
+ const lastRoom = rooms[rooms.length - 1];
147
+ pois.push({
148
+ x: lastRoom.x + 1,
149
+ y: lastRoom.y + 1,
150
+ type: 'treasure',
151
+ label: 'Town Treasury',
152
+ });
153
+ }
154
+ return {
155
+ width,
156
+ height,
157
+ tiles,
158
+ rooms,
159
+ seed,
160
+ pois,
161
+ spawnPoint: { x: sqCenterX, y: sqCenterY },
162
+ };
163
+ }
164
+ function carvePath(tiles, x1, y1, x2, y2, width, height) {
165
+ let x = x1;
166
+ let y = y1;
167
+ while (x !== x2 || y !== y2) {
168
+ if (x !== x2) {
169
+ x += x < x2 ? 1 : -1;
170
+ }
171
+ else {
172
+ y += y < y2 ? 1 : -1;
173
+ }
174
+ if (y >= 0 && y < height && x >= 0 && x < width) {
175
+ if (tiles[y][x] === TT.GRASS || tiles[y][x] === TT.TREE) {
176
+ tiles[y][x] = TT.PATH;
177
+ }
178
+ }
179
+ }
180
+ }
181
+ //# sourceMappingURL=town.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"town.js","sourceRoot":"","sources":["../../src/map/town.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ export interface MapConfig {
2
+ width: number;
3
+ height: number;
4
+ seed?: string | number;
5
+ }
6
+ export interface DungeonConfig extends MapConfig {
7
+ roomMinSize?: number;
8
+ roomMaxSize?: number;
9
+ maxRooms?: number;
10
+ corridorWidth?: number;
11
+ }
12
+ export interface CellularConfig extends MapConfig {
13
+ birthLimit?: number;
14
+ deathLimit?: number;
15
+ iterations?: number;
16
+ initialDensity?: number;
17
+ }
18
+ export interface OverworldConfig extends MapConfig {
19
+ biomes?: string[];
20
+ temperature?: number;
21
+ }
22
+ export interface PointOfInterest {
23
+ x: number;
24
+ y: number;
25
+ type: 'spawn' | 'treasure' | 'npc' | 'exit' | 'entrance' | 'boss';
26
+ label?: string;
27
+ }
28
+ export declare enum TileType {
29
+ VOID = 0,
30
+ FLOOR = 1,
31
+ WALL = 2,
32
+ DOOR = 3,
33
+ CORRIDOR = 4,
34
+ WATER = 5,
35
+ GRASS = 6,
36
+ TREE = 7,
37
+ PATH = 8,
38
+ SAND = 9,
39
+ STONE = 10,
40
+ BRIDGE = 11
41
+ }
42
+ export interface Room {
43
+ x: number;
44
+ y: number;
45
+ width: number;
46
+ height: number;
47
+ id: number;
48
+ connections: number[];
49
+ }
50
+ export interface GeneratedMap {
51
+ width: number;
52
+ height: number;
53
+ tiles: TileType[][];
54
+ rooms: Room[];
55
+ seed: string | number;
56
+ pois: PointOfInterest[];
57
+ spawnPoint?: {
58
+ x: number;
59
+ y: number;
60
+ };
61
+ exitPoint?: {
62
+ x: number;
63
+ y: number;
64
+ };
65
+ }
@@ -0,0 +1,16 @@
1
+ export var TileType;
2
+ (function (TileType) {
3
+ TileType[TileType["VOID"] = 0] = "VOID";
4
+ TileType[TileType["FLOOR"] = 1] = "FLOOR";
5
+ TileType[TileType["WALL"] = 2] = "WALL";
6
+ TileType[TileType["DOOR"] = 3] = "DOOR";
7
+ TileType[TileType["CORRIDOR"] = 4] = "CORRIDOR";
8
+ TileType[TileType["WATER"] = 5] = "WATER";
9
+ TileType[TileType["GRASS"] = 6] = "GRASS";
10
+ TileType[TileType["TREE"] = 7] = "TREE";
11
+ TileType[TileType["PATH"] = 8] = "PATH";
12
+ TileType[TileType["SAND"] = 9] = "SAND";
13
+ TileType[TileType["STONE"] = 10] = "STONE";
14
+ TileType[TileType["BRIDGE"] = 11] = "BRIDGE";
15
+ })(TileType || (TileType = {}));
16
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/map/types.ts"],"names":[],"mappings":"AAgCA,MAAM,CAAN,IAAY,QAaX;AAbD,WAAY,QAAQ;IAClB,uCAAQ,CAAA;IACR,yCAAS,CAAA;IACT,uCAAQ,CAAA;IACR,uCAAQ,CAAA;IACR,+CAAY,CAAA;IACZ,yCAAS,CAAA;IACT,yCAAS,CAAA;IACT,uCAAQ,CAAA;IACR,uCAAQ,CAAA;IACR,uCAAQ,CAAA;IACR,0CAAU,CAAA;IACV,4CAAW,CAAA;AACb,CAAC,EAbW,QAAQ,KAAR,QAAQ,QAanB"}
@@ -0,0 +1,18 @@
1
+ import type { MapConfig, GeneratedMap } from './types.js';
2
+ import { type TileType } from './types.js';
3
+ export interface WFCTileDef {
4
+ name: string;
5
+ tile: TileType;
6
+ weight: number;
7
+ /** Which tiles are allowed in each direction [up, right, down, left] */
8
+ adjacency: [string[], string[], string[], string[]];
9
+ }
10
+ /** Default terrain adjacency rules */
11
+ export declare const DEFAULT_WFC_TILES: WFCTileDef[];
12
+ interface WFCConfig extends MapConfig {
13
+ tiles?: WFCTileDef[];
14
+ maxRetries?: number;
15
+ }
16
+ /** Generate a map using Wave Function Collapse */
17
+ export declare function generateWFC(config: WFCConfig): GeneratedMap;
18
+ export {};
@@ -0,0 +1,192 @@
1
+ import { SeededRNG } from '../utils/rng.js';
2
+ import { TileType as TT } from './types.js';
3
+ /** Default terrain adjacency rules */
4
+ export const DEFAULT_WFC_TILES = [
5
+ {
6
+ name: 'grass',
7
+ tile: TT.GRASS,
8
+ weight: 4,
9
+ adjacency: [
10
+ ['grass', 'tree', 'path', 'sand'],
11
+ ['grass', 'tree', 'path', 'sand'],
12
+ ['grass', 'tree', 'path', 'sand'],
13
+ ['grass', 'tree', 'path', 'sand'],
14
+ ],
15
+ },
16
+ {
17
+ name: 'tree',
18
+ tile: TT.TREE,
19
+ weight: 2,
20
+ adjacency: [
21
+ ['grass', 'tree'],
22
+ ['grass', 'tree'],
23
+ ['grass', 'tree'],
24
+ ['grass', 'tree'],
25
+ ],
26
+ },
27
+ {
28
+ name: 'water',
29
+ tile: TT.WATER,
30
+ weight: 2,
31
+ adjacency: [
32
+ ['water', 'sand'],
33
+ ['water', 'sand'],
34
+ ['water', 'sand'],
35
+ ['water', 'sand'],
36
+ ],
37
+ },
38
+ {
39
+ name: 'sand',
40
+ tile: TT.SAND,
41
+ weight: 1,
42
+ adjacency: [
43
+ ['grass', 'sand', 'water', 'path'],
44
+ ['grass', 'sand', 'water', 'path'],
45
+ ['grass', 'sand', 'water', 'path'],
46
+ ['grass', 'sand', 'water', 'path'],
47
+ ],
48
+ },
49
+ {
50
+ name: 'path',
51
+ tile: TT.PATH,
52
+ weight: 1,
53
+ adjacency: [
54
+ ['grass', 'path', 'sand', 'stone'],
55
+ ['grass', 'path', 'sand', 'stone'],
56
+ ['grass', 'path', 'sand', 'stone'],
57
+ ['grass', 'path', 'sand', 'stone'],
58
+ ],
59
+ },
60
+ {
61
+ name: 'stone',
62
+ tile: TT.STONE,
63
+ weight: 1,
64
+ adjacency: [
65
+ ['stone', 'grass', 'path'],
66
+ ['stone', 'grass', 'path'],
67
+ ['stone', 'grass', 'path'],
68
+ ['stone', 'grass', 'path'],
69
+ ],
70
+ },
71
+ ];
72
+ /** Generate a map using Wave Function Collapse */
73
+ export function generateWFC(config) {
74
+ const { width, height, seed = Date.now(), tiles: tileDefs = DEFAULT_WFC_TILES, maxRetries = 10, } = config;
75
+ const rng = new SeededRNG(seed);
76
+ const tileNames = tileDefs.map((t) => t.name);
77
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
78
+ const result = tryCollapse(width, height, tileDefs, tileNames, rng);
79
+ if (result) {
80
+ return {
81
+ width,
82
+ height,
83
+ tiles: result,
84
+ rooms: [],
85
+ seed,
86
+ pois: [],
87
+ };
88
+ }
89
+ }
90
+ // Fallback: fill with grass
91
+ const fallback = Array.from({ length: height }, () => Array(width).fill(TT.GRASS));
92
+ return { width, height, tiles: fallback, rooms: [], seed, pois: [] };
93
+ }
94
+ function tryCollapse(width, height, tileDefs, tileNames, rng) {
95
+ // Each cell has a set of possible tile indices
96
+ const grid = Array.from({ length: height }, () => Array.from({ length: width }, () => new Set(tileDefs.map((_, i) => i))));
97
+ const totalCells = width * height;
98
+ for (let step = 0; step < totalCells; step++) {
99
+ // Find cell with lowest entropy (fewest possibilities)
100
+ let minEntropy = Infinity;
101
+ let minCells = [];
102
+ for (let y = 0; y < height; y++) {
103
+ for (let x = 0; x < width; x++) {
104
+ const size = grid[y][x].size;
105
+ if (size <= 1)
106
+ continue;
107
+ if (size < minEntropy) {
108
+ minEntropy = size;
109
+ minCells = [{ x, y }];
110
+ }
111
+ else if (size === minEntropy) {
112
+ minCells.push({ x, y });
113
+ }
114
+ }
115
+ }
116
+ if (minCells.length === 0)
117
+ break; // All collapsed
118
+ // Pick random cell among minimum entropy
119
+ const cell = rng.pick(minCells);
120
+ // Collapse: pick one tile weighted by weight
121
+ const possible = [...grid[cell.y][cell.x]];
122
+ const weights = possible.map((i) => tileDefs[i].weight);
123
+ const totalWeight = weights.reduce((a, b) => a + b, 0);
124
+ let r = rng.randomFloat(0, totalWeight);
125
+ let chosen = possible[0];
126
+ for (let i = 0; i < possible.length; i++) {
127
+ r -= weights[i];
128
+ if (r <= 0) {
129
+ chosen = possible[i];
130
+ break;
131
+ }
132
+ }
133
+ grid[cell.y][cell.x] = new Set([chosen]);
134
+ // Propagate constraints
135
+ if (!propagate(grid, cell.x, cell.y, width, height, tileDefs, tileNames)) {
136
+ return null; // Contradiction
137
+ }
138
+ }
139
+ // Convert to tile types
140
+ const result = Array.from({ length: height }, (_, y) => Array.from({ length: width }, (_, x) => {
141
+ const possible = [...grid[y][x]];
142
+ if (possible.length === 0)
143
+ return TT.VOID;
144
+ return tileDefs[possible[0]].tile;
145
+ }));
146
+ return result;
147
+ }
148
+ function propagate(grid, startX, startY, width, height, tileDefs, tileNames) {
149
+ const stack = [[startX, startY]];
150
+ // Directions: [dy, dx, dirIndex, oppositeIndex]
151
+ const dirs = [
152
+ [-1, 0, 0, 2], // up
153
+ [0, 1, 1, 3], // right
154
+ [1, 0, 2, 0], // down
155
+ [0, -1, 3, 1], // left
156
+ ];
157
+ while (stack.length > 0) {
158
+ const [cx, cy] = stack.pop();
159
+ const currentPossible = grid[cy][cx];
160
+ for (const [dy, dx, dirIdx, oppIdx] of dirs) {
161
+ const nx = cx + dx;
162
+ const ny = cy + dy;
163
+ if (nx < 0 || nx >= width || ny < 0 || ny >= height)
164
+ continue;
165
+ const neighborPossible = grid[ny][nx];
166
+ if (neighborPossible.size <= 1 && grid[ny][nx].size > 0)
167
+ continue;
168
+ // Compute allowed tiles for neighbor based on current cell
169
+ const allowed = new Set();
170
+ for (const tileIdx of currentPossible) {
171
+ const adjNames = tileDefs[tileIdx].adjacency[dirIdx];
172
+ for (const name of adjNames) {
173
+ const idx = tileNames.indexOf(name);
174
+ if (idx !== -1 && neighborPossible.has(idx)) {
175
+ // Also check reverse: neighbor must allow current tile in opposite direction
176
+ if (tileDefs[idx].adjacency[oppIdx].includes(tileDefs[tileIdx].name)) {
177
+ allowed.add(idx);
178
+ }
179
+ }
180
+ }
181
+ }
182
+ if (allowed.size === 0)
183
+ return false; // Contradiction
184
+ if (allowed.size < neighborPossible.size) {
185
+ grid[ny][nx] = allowed;
186
+ stack.push([nx, ny]);
187
+ }
188
+ }
189
+ }
190
+ return true;
191
+ }
192
+ //# sourceMappingURL=wfc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wfc.js","sourceRoot":"","sources":["../../src/map/wfc.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export interface AtlasResult {
2
+ imagePath: string;
3
+ metadataPath: string;
4
+ tilePositions: Record<string, {
5
+ x: number;
6
+ y: number;
7
+ width: number;
8
+ height: number;
9
+ }>;
10
+ columns: number;
11
+ rows: number;
12
+ }
13
+ /** Build a texture atlas from individual tile images */
14
+ export declare function buildAtlas(tiles: Record<string, string>, // tileName → file path
15
+ tileSize: number, outputPath: string): Promise<AtlasResult>;
@@ -0,0 +1,55 @@
1
+ import sharp from 'sharp';
2
+ import { writeFile, mkdir } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ /** Build a texture atlas from individual tile images */
5
+ export async function buildAtlas(tiles, // tileName → file path
6
+ tileSize, outputPath) {
7
+ const tileEntries = Object.entries(tiles);
8
+ const count = tileEntries.length;
9
+ const columns = Math.ceil(Math.sqrt(count));
10
+ const rows = Math.ceil(count / columns);
11
+ const atlasWidth = columns * tileSize;
12
+ const atlasHeight = rows * tileSize;
13
+ const composites = [];
14
+ const positions = {};
15
+ for (let i = 0; i < tileEntries.length; i++) {
16
+ const [name, filePath] = tileEntries[i];
17
+ const col = i % columns;
18
+ const row = Math.floor(i / columns);
19
+ const x = col * tileSize;
20
+ const y = row * tileSize;
21
+ try {
22
+ const buf = await sharp(filePath).resize(tileSize, tileSize).png().toBuffer();
23
+ composites.push({ input: buf, top: y, left: x });
24
+ positions[name] = { x, y, width: tileSize, height: tileSize };
25
+ }
26
+ catch {
27
+ // Skip missing tiles
28
+ }
29
+ }
30
+ await mkdir(join(outputPath, '..'), { recursive: true });
31
+ const atlasBuffer = await sharp({
32
+ create: {
33
+ width: atlasWidth,
34
+ height: atlasHeight,
35
+ channels: 4,
36
+ background: { r: 0, g: 0, b: 0, alpha: 0 },
37
+ },
38
+ })
39
+ .png()
40
+ .composite(composites)
41
+ .toBuffer();
42
+ const imagePath = outputPath.endsWith('.png') ? outputPath : `${outputPath}.png`;
43
+ const metadataPath = imagePath.replace('.png', '.json');
44
+ await writeFile(imagePath, atlasBuffer);
45
+ const metadata = { tileSize, columns, rows, tiles: positions };
46
+ await writeFile(metadataPath, JSON.stringify(metadata, null, 2));
47
+ return {
48
+ imagePath,
49
+ metadataPath,
50
+ tilePositions: positions,
51
+ columns,
52
+ rows,
53
+ };
54
+ }
55
+ //# sourceMappingURL=atlas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atlas.js","sourceRoot":"","sources":["../../src/tileset/atlas.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { TileType } from '../map/types.js';
2
+ export interface TilesetManifest {
3
+ name: string;
4
+ tileSize: number;
5
+ tiles: Record<string, string>;
6
+ }
7
+ /** Generate default placeholder tiles programmatically */
8
+ export declare function generateDefaultTileset(outputDir: string): Promise<TilesetManifest>;
9
+ /** Load a tileset manifest from a directory */
10
+ export declare function loadTileset(tilesetDir: string): Promise<TilesetManifest>;
11
+ /** Map TileType enum to tile name */
12
+ export declare function tileTypeToName(t: TileType): string;