diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 06d3f0a..015a48b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -52,7 +52,7 @@ importers: version: 5.5.4 ultimate-crosscode-typedefs: specifier: github:krypciak/ultimate-crosscode-typedefs - version: https://codeload.github.com/krypciak/ultimate-crosscode-typedefs/tar.gz/62e0891454fa1f01fa883c5bbccda052343a71a9 + version: https://codeload.github.com/krypciak/ultimate-crosscode-typedefs/tar.gz/f227aa0e8de791091c470b325007af7e2e7a90a6 packages: @@ -877,8 +877,8 @@ packages: engines: {node: '>=14.17'} hasBin: true - ultimate-crosscode-typedefs@https://codeload.github.com/krypciak/ultimate-crosscode-typedefs/tar.gz/62e0891454fa1f01fa883c5bbccda052343a71a9: - resolution: {tarball: https://codeload.github.com/krypciak/ultimate-crosscode-typedefs/tar.gz/62e0891454fa1f01fa883c5bbccda052343a71a9} + ultimate-crosscode-typedefs@https://codeload.github.com/krypciak/ultimate-crosscode-typedefs/tar.gz/f227aa0e8de791091c470b325007af7e2e7a90a6: + resolution: {tarball: https://codeload.github.com/krypciak/ultimate-crosscode-typedefs/tar.gz/f227aa0e8de791091c470b325007af7e2e7a90a6} version: 0.0.1 engines: {node: '>=10.0.0'} @@ -1687,7 +1687,7 @@ snapshots: typescript@5.5.4: {} - ultimate-crosscode-typedefs@https://codeload.github.com/krypciak/ultimate-crosscode-typedefs/tar.gz/62e0891454fa1f01fa883c5bbccda052343a71a9: + ultimate-crosscode-typedefs@https://codeload.github.com/krypciak/ultimate-crosscode-typedefs/tar.gz/f227aa0e8de791091c470b325007af7e2e7a90a6: dependencies: '@types/jquery': 1.10.45 '@types/node': 11.15.54 diff --git a/src/dungeon/builder.ts b/src/dungeon/builder.ts index 7d1d3da..a1e5bec 100644 --- a/src/dungeon/builder.ts +++ b/src/dungeon/builder.ts @@ -2,52 +2,53 @@ import { BuildQueue } from '../build-queue/build-queue' import { drawMapArrangeQueue } from '../map-arrange/drawer' import { MapArrange, MapArrangeData } from '../map-arrange/map-arrange' import { MapPicker, mapPickerConfigurable } from '../map-arrange/map-picker/configurable' +import { constructMapsFromMapsArrange } from '../map-construct/map-construct' import { setRandomSeed } from '../util/util' export class DungeonBuilder { - build(seed: string): MapArrange[] { + build(seed: string) { const queue = new BuildQueue(true) - const roomSizeReg = { x: 3, y: 3 } - const tunnelSizeReg = { x: 1, y: 1 } - const roomSizeBranch = { x: 5, y: 5 } - const tunnelSizeBranch = { x: 1, y: 1 } const randomizeDirTryOrder = true - - function tunnel(count: number, followedBy?: MapPicker.ConfigNode): MapPicker.ConfigNode { - return { - type: 'SimpleTunnel', - roomSize: roomSizeReg, - tunnelSize: tunnelSizeReg, - count, - randomizeDirTryOrder, - followedBy, - } - } - function branch( - deep: number, - branchTunnelCount: () => number, - finalTunnelCount: () => number, - branchCount: () => 1 | 2 | 3 - ): MapPicker.ConfigNode { - if (deep == 0) { - return tunnel(finalTunnelCount()) - } - return { - type: 'SimpleBranch', - roomSize: roomSizeBranch, - tunnelSize: tunnelSizeBranch, - branches: [ - ...new Array(branchCount()) - .fill(null) - .map(_ => - tunnel( - branchTunnelCount(), - branch(deep - 1, branchTunnelCount, finalTunnelCount, branchCount) - ) - ), - ] as any, - } - } + const roomSizeReg = { x: 9*16, y: 9*16 } + // const tunnelSizeReg = { x: 1, y: 1 } + // const roomSizeBranch = { x: 5, y: 5 } + // const tunnelSizeBranch = { x: 1, y: 1 } + // + // function tunnel(count: number, followedBy?: MapPicker.ConfigNode): MapPicker.ConfigNode { + // return { + // type: 'SimpleTunnel', + // roomSize: roomSizeReg, + // tunnelSize: tunnelSizeReg, + // count, + // randomizeDirTryOrder, + // followedBy, + // } + // } + // function branch( + // deep: number, + // branchTunnelCount: () => number, + // finalTunnelCount: () => number, + // branchCount: () => 1 | 2 | 3 + // ): MapPicker.ConfigNode { + // if (deep == 0) { + // return tunnel(finalTunnelCount()) + // } + // return { + // type: 'SimpleBranch', + // roomSize: roomSizeBranch, + // tunnelSize: tunnelSizeBranch, + // branches: [ + // ...new Array(branchCount()) + // .fill(null) + // .map(_ => + // tunnel( + // branchTunnelCount(), + // branch(deep - 1, branchTunnelCount, finalTunnelCount, branchCount) + // ) + // ), + // ] as any, + // } + // } const mapPicker: MapPicker = mapPickerConfigurable({ root: { @@ -56,20 +57,26 @@ export class DungeonBuilder { count: 1, randomizeDirTryOrder, - followedBy: branch( - 2, - () => 2, - () => 2, - () => 2 - ), + // followedBy: branch( + // 2, + // () => 2, + // () => 2, + // () => 2 + // ), }, }) setRandomSeed(seed) - const res = queue.begin(mapPicker(-1, queue)) as MapArrange[] + const mapsArrange = queue.begin(mapPicker(-1, queue)) as MapArrange[] // console.dir(queue.queue, { depth: null }) - console.log(drawMapArrangeQueue(queue, false, undefined, false, true)) - if (!res) throw new Error('res null') - return res + console.log(drawMapArrangeQueue(queue, 16, false, undefined, false, true)) + if (!mapsArrange) throw new Error('res null') + + const mapsConstruct = constructMapsFromMapsArrange(mapsArrange, { + id: 'myarea', + title: 'My area', + description: '8th ring of hell', + }) + console.log(mapsConstruct) } } diff --git a/src/map-arrange/drawer.ts b/src/map-arrange/drawer.ts index 5a664a2..9297267 100644 --- a/src/map-arrange/drawer.ts +++ b/src/map-arrange/drawer.ts @@ -9,6 +9,7 @@ const colorMap = ['red', 'green', 'yellow', 'blue', 'magenta', 'cyan'] as const export function drawMapArrangeQueue( queue: BuildQueueAccesor, + scale: number, nonFinished: boolean = false, mapsAdd: MapArrangeData[] = [], keepInTheSamePlace?: boolean, @@ -20,7 +21,7 @@ export function drawMapArrangeQueue( .concat(mapsAdd) .filter(a => a.rects && a.rects.length > 0 && a.id !== undefined) .map(copyMapArrange) - + if (maps.length == 0) return 'drawQueue: no maps' const rects = maps.flatMap(a => a.rects!) const bounds: Rect = Rect.boundsOfArr(rects) @@ -44,7 +45,10 @@ export function drawMapArrangeQueue( for (const map of maps) offsetMapArrange(map, offset) } - const strmap: string[][] = Array2d.empty({ x: bounds.width, y: bounds.height }, ' ') + const strmap: string[][] = Array2d.empty( + { x: (bounds.width / scale).floor(), y: (bounds.height / scale).floor() }, + ' ' + ) for (const map of maps) { for (const rect of map.rects) { let char = (map.id % 10).toString() @@ -54,7 +58,12 @@ export function drawMapArrangeQueue( } try { - Array2d.pasteInto(strmap, Array2d.empty({ x: rect.width, y: rect.height }, char), rect.x, rect.y) + Array2d.pasteInto( + strmap, + Array2d.empty({ x: (rect.width / scale).floor(), y: (rect.height / scale).floor() }, char), + (rect.x / scale).floor(), + (rect.y / scale).floor() + ) } catch (e) { console.error(`error while trying to parse rect ${Rect.toString(rect)} of map ${map.id}`, e) } @@ -68,6 +77,7 @@ let lastPrint: number = 0 export function printMapArrangeQueue( queue: BuildQueueAccesor, + scale: number, nonFinished: boolean = false, mapsAdd: MapArrange[] = [], keepInTheSamePlace?: boolean, @@ -77,7 +87,7 @@ export function printMapArrangeQueue( if (!(lastPrint < Date.now() - 1000 / 10)) return lastPrint = Date.now() - const res = drawMapArrangeQueue(queue, nonFinished, mapsAdd, keepInTheSamePlace, color) + const res = drawMapArrangeQueue(queue, scale, nonFinished, mapsAdd, keepInTheSamePlace, color) const len = res.split('\n')[0].length console.clear() console.log(add + ' ' + '='.repeat(Math.max(1, len - add.length - 1)) + ' ' + '\n' + res + '\n' + '='.repeat(len)) diff --git a/src/map-arrange/map-picker/configurable.spec.ts b/src/map-arrange/map-picker/configurable.spec.ts index edf59b9..aa46802 100644 --- a/src/map-arrange/map-picker/configurable.spec.ts +++ b/src/map-arrange/map-picker/configurable.spec.ts @@ -71,7 +71,7 @@ export class Test_ConfigurableMapPicker { setRandomSeed(seed) queue.begin(mapPicker(-1, queue)) - const res = drawMapArrangeQueue(queue) + const res = drawMapArrangeQueue(queue, 1) const sha = sha256(res) expect.toBeEqual(sha, expected) } diff --git a/src/map-arrange/map-picker/simple.ts b/src/map-arrange/map-picker/simple.ts index baf55ec..07f6bb5 100644 --- a/src/map-arrange/map-picker/simple.ts +++ b/src/map-arrange/map-picker/simple.ts @@ -69,7 +69,7 @@ export function mapPickerSimpleTunnelBranch(branchCount: 1 | 2 | 3) { return lastBranch.createNextBranch! } - printMapArrangeQueue(accesor, true) + printMapArrangeQueue(accesor, 1, true) const lastTpr = last ? (last.restTprs.find(t => t.destId == newId)! as TprArrange) diff --git a/src/map-construct/map-construct.ts b/src/map-construct/map-construct.ts index b1b2b71..b39ebcc 100644 --- a/src/map-construct/map-construct.ts +++ b/src/map-construct/map-construct.ts @@ -1,9 +1,10 @@ -import { assert } from 'console' -import { MapArrange } from '../map-arrange/map-arrange' +import { copyMapArrange, MapArrange } from '../map-arrange/map-arrange' import { MapPicker } from '../map-arrange/map-picker/configurable' +import { Id } from '../build-queue/build-queue' +import { assert } from '../util/util' -interface MapConstruct extends MapArrange { - // +export interface MapConstruct extends MapArrange { + constructed: sc.MapModel.Map } export interface AreaInfo { @@ -12,21 +13,29 @@ export interface AreaInfo { description: string } -type MapConstructor = ( +export type MapConstructFunc = ( map: MapArrange, areaInfo: AreaInfo, - mapsArrange: MapArrange[], - mapsConstruct: MapConstruct[] -) => MapArrange + pathResolver: (id: Id) => string, + mapsArranged: MapArrange[], + mapsConstructed: MapConstruct[] +) => MapConstruct -const constructors: Record = {} as any -export function registerMapConstructor(type: T, constructor: MapConstructor) { +const constructors: Record = {} as any +export function registerMapConstructor(type: T, constructor: MapConstructFunc) { assert(!constructors[type]) constructors[type] = constructor } export function constructMapsFromMapsArrange(maps: MapArrange[], areaInfo: AreaInfo): MapConstruct[] { const mapsConstruct: MapConstruct[] = [] + const pathResolver: (id: Id) => string = id => `${areaInfo.id}/${id}` + + for (const map of maps) { + const constructor = constructors[map.type] + const constructedMap = constructor(copyMapArrange(map), areaInfo, pathResolver, maps, mapsConstruct) + mapsConstruct.push(constructedMap) + } return mapsConstruct } diff --git a/src/maps/simple.spec.ts b/src/maps/simple.spec.ts index c4f4c0a..158b144 100644 --- a/src/maps/simple.spec.ts +++ b/src/maps/simple.spec.ts @@ -28,7 +28,7 @@ export class Test_SimpleMapPicker { return roomGen } queue.begin(mapPicker(-1, queue)) - const res = drawMapArrangeQueue(queue) + const res = drawMapArrangeQueue(queue, 1) const expected = `55\n55\n44\n44\n33\n33\n22\n22\n11\n11\n00\n00` expect.toBeEqual(res, expected) } @@ -53,7 +53,7 @@ export class Test_SimpleMapPicker { } setRandomSeed(seed) queue.begin(mapPicker(-1, queue)) - const res = drawMapArrangeQueue(queue) + const res = drawMapArrangeQueue(queue, 1) expect.toBeEqual(res, expected) } @@ -106,7 +106,7 @@ export class Test_SimpleMapPicker { } setRandomSeed(seed) queue.begin(mapPicker(-1, queue)) - const res = drawMapArrangeQueue(queue) + const res = drawMapArrangeQueue(queue, 1) const hash = sha256(res) expect.toBeEqual(hash, expected) } diff --git a/src/maps/simple.ts b/src/maps/simple.ts index 711d1cb..5660b47 100644 --- a/src/maps/simple.ts +++ b/src/maps/simple.ts @@ -1,9 +1,18 @@ import { Vec2 } from '../util/vec2' import { NextQueueEntryGenerator, QueueEntry } from '../build-queue/build-queue' -import { TprArrange, MapArrangeData, MapArrange, RoomArrange, doesMapArrangeFit } from '../map-arrange/map-arrange' +import { + TprArrange, + MapArrangeData, + MapArrange, + RoomArrange, + doesMapArrangeFit, + offsetMapArrange, +} from '../map-arrange/map-arrange' import { MapPicker, registerMapPickerNodeConfig } from '../map-arrange/map-picker/configurable' import { Dir, DirU, Rect } from '../util/geometry' import { shuffleArray } from '../util/util' +import { registerMapConstructor } from '../map-construct/map-construct' +import { MapTheme } from '../map-construct/theme' declare global { export namespace MapPickerNodeConfigs { @@ -51,7 +60,7 @@ export function simpleMapArrange({ destId: id - 1, } const map: MapArrange = { - type: 'SimpleBranch', + type: 'Simple', rects: [], restTprs: [], id, @@ -113,3 +122,39 @@ export function simpleMapArrange({ return ret } } + +registerMapConstructor('Simple', (map, areaInfo, pathResolver, _mapsArranged, _mapsConstructed) => { + const bounds = Rect.boundsOfArr(map.rects) + const offset = Vec2.mulC(bounds, -1) + offsetMapArrange(map, offset) + + const theme = MapTheme.default + + const c: sc.MapModel.Map = { + name: pathResolver(map.id), + mapWidth: bounds.width, + mapHeight: bounds.height, + levels: [{ height: 0 }], + masterLevel: 0, + attributes: theme.getMapAttributes(areaInfo.id), + screen: { x: 0, y: 0 }, + entities: [], + layer: [], + } + + for (const tpr of [...map.entranceTprs, ...map.restTprs]) { + const entity = { + type: 'DOOR', + x: tpr.x, + y: tpr.y, + level: 0, + settings: {}, + } + c.entities.push(entity) + } + + return { + ...map, + constructed: c, + } +}) diff --git a/src/setup.ts b/src/setup.ts index 89d482b..b369cf3 100644 --- a/src/setup.ts +++ b/src/setup.ts @@ -1,3 +1,8 @@ import './util/modify-prototypes' + import './map-arrange/map-picker/configurable' import './map-construct/map-construct' + +import './maps/simple' +import './maps/simple-branch' +import './maps/simple-tunnel' diff --git a/src/util/modify-prototypes.ts b/src/util/modify-prototypes.ts index 010f320..e8f091e 100644 --- a/src/util/modify-prototypes.ts +++ b/src/util/modify-prototypes.ts @@ -36,13 +36,19 @@ Array.prototype.flatMap ??= function (callback) { Array.prototype.last ??= function () { return this[this.length - 1] } +Array.prototype.random ??= function () { + return this[Math.floor(Math.random() * this.length)] +} Number.prototype.round ??= function (prec) { prec = Math.pow(10, prec || 0) - return Math.round((this as any) * prec) / prec + return Math.round((this as number) * prec) / prec } -Array.prototype.random ??= function () { - return this[Math.floor(Math.random() * this.length)] +Number.prototype.floor ??= function () { + return Math.floor(this as number) +} +Number.prototype.ceil ??= function () { + return Math.ceil(this as number) } export const ObjectKeysT: (object: Record) => K[] = Object.keys as any