progress
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { mustBe, mustBeString } from "../utils/mustbe.js";
|
import { mustBe } from "../utils/mustbe.js";
|
||||||
import shallowCopy from "../utils/shallowCopy.js";
|
import shallowCopy from "../utils/shallowCopy.js";
|
||||||
import { TileOptions } from "../utils/tileOptionsParser.js";
|
import { TileOptions } from "../utils/tileOptionsParser.js";
|
||||||
import { Orientation } from "./ascii_types.js";
|
import { Orientation } from "./ascii_types.js";
|
||||||
@@ -22,9 +22,64 @@ export const TileChars = Object.freeze({
|
|||||||
PLAYER_START_POINT: "P",
|
PLAYER_START_POINT: "P",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Properties whose value matches one of these constants
|
||||||
|
* must have their actual value supplied by the creator
|
||||||
|
* of the Tile object.
|
||||||
|
*
|
||||||
|
* For instance, if a Tile has a textureId = PropertyPlaceholder.ID, then
|
||||||
|
* the creature of that Tile MUST supply the textureId before the tile can
|
||||||
|
* be used. Such values SHOULD be provided in the constructor, but CAN be
|
||||||
|
* provided later, as long as they are provided before the tile is used
|
||||||
|
* in the actual game.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Properties with this value must be valid ID values. */
|
||||||
const REQUIRED_ID = Symbol("REQUIRED_ID");
|
const REQUIRED_ID = Symbol("REQUIRED_ID");
|
||||||
const REQUIRED_ORIENTATION = Symbol("REQUIRED_ORIENTATION");
|
const REQUIRED_ORIENTATION = Symbol("REQUIRED_ORIENTATION");
|
||||||
|
|
||||||
|
function mustBeId(value) {
|
||||||
|
if ((value | 0) === value) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof value !== "string") {
|
||||||
|
throw new Error("Value id not a valid id", { value });
|
||||||
|
}
|
||||||
|
|
||||||
|
value = value.trim();
|
||||||
|
|
||||||
|
if (value === "") {
|
||||||
|
throw new Error("Value id not a valid id", { value });
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
function mustBeOrientation(value) {
|
||||||
|
const result = Orientation.normalize(value);
|
||||||
|
|
||||||
|
if (result === undefined) {
|
||||||
|
throw new Error("Value is not a valid orientation", { value });
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function mustBeSingleGrapheme(value) {
|
||||||
|
if (typeof value !== "string") {
|
||||||
|
throw new Error("Value is not a one-grapheme string", { value });
|
||||||
|
}
|
||||||
|
|
||||||
|
const seg = new Intl.Segmenter(undefined, { granularity: "grapheme" });
|
||||||
|
|
||||||
|
if ([...seg.segment(value)].length !== 1) {
|
||||||
|
throw new Error("Value is not a one-grapheme string", { value });
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
/** @type {Record<TileTypeId,Tile>} */
|
/** @type {Record<TileTypeId,Tile>} */
|
||||||
export const TileTypes = {
|
export const TileTypes = {
|
||||||
[TileChars.FLOOR]: {
|
[TileChars.FLOOR]: {
|
||||||
@@ -138,26 +193,15 @@ export class Tile {
|
|||||||
//
|
//
|
||||||
for (const [key, val] of Object.entries(properties)) {
|
for (const [key, val] of Object.entries(properties)) {
|
||||||
//
|
//
|
||||||
// Ensure that we do not have placeholder symbols in the incoming properties
|
// Skip empty properties.
|
||||||
// Placeolder symbols indicate that the data must be supplied externally by
|
if (val === undefined) {
|
||||||
// the creator of the tile
|
continue;
|
||||||
//
|
|
||||||
if (typeof val === "symbol" && val.description.startsWith("REQUIRED_")) {
|
|
||||||
console.error(
|
|
||||||
[
|
|
||||||
"REQUIRED_ symbol encountered in Tile constructor. ",
|
|
||||||
"REQUIRED_ is a placeholder, and cannot be used as a value directly",
|
|
||||||
].join("\n"),
|
|
||||||
{ key, val, properties },
|
|
||||||
);
|
|
||||||
throw new Error("Incomplete data in constructor. Args may not contain a data placeholder");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Object.hasOwn(this, key) /* Object.prototype.hasOwnProperty.call(this, key) */) {
|
if (!Object.hasOwn(this, key) /* Object.prototype.hasOwnProperty.call(this, key) */) {
|
||||||
console.warn("Unknown tile property", { key, val, properties });
|
console.warn("Unknown tile property", { key, val, properties });
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
this[key] = val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -169,7 +213,7 @@ export class Tile {
|
|||||||
// bump event, spell, or other method for discovering secrets
|
// bump event, spell, or other method for discovering secrets
|
||||||
//
|
//
|
||||||
if (this.disguiseAs !== undefined) {
|
if (this.disguiseAs !== undefined) {
|
||||||
this.revealed = false;
|
this.revealed ??= false;
|
||||||
|
|
||||||
const other = shallowCopy(TileTypes[this.disguiseAs]);
|
const other = shallowCopy(TileTypes[this.disguiseAs]);
|
||||||
for (const [pKey, pVal] of Object.entries(other)) {
|
for (const [pKey, pVal] of Object.entries(other)) {
|
||||||
@@ -198,43 +242,22 @@ export class Tile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Normalize Orientation.
|
// Populate derivable values that have not yet been set.
|
||||||
if (this.orientation !== undefined && typeof this.orientation === "string") {
|
this.minimapChar ??= this.typeId;
|
||||||
const valueMap = {
|
this.revealedMinimapChar ??= this.minimapChar;
|
||||||
north: Orientation.NORTH,
|
this.revealedMinimapColo ??= this.minimapColor;
|
||||||
south: Orientation.SOUTH,
|
|
||||||
east: Orientation.EAST,
|
|
||||||
west: Orientation.WEST,
|
|
||||||
};
|
|
||||||
this.orientation = mustBeString(valueMap[this.orientation.toLowerCase()]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Tiles are not required to have IDs, but IDs must be numbers or strings
|
// Sanitize and normalize
|
||||||
if (this.id !== undefined) {
|
|
||||||
mustBe(this.id, "number", "string");
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// If a tile has a texture, the texture id must be string or number
|
this.id ??= mustBeId(this.id);
|
||||||
if (this.textureId !== undefined) {
|
this.textureId ??= mustBeId(this.textureId);
|
||||||
mustBe(this.textureId, "number", "string");
|
this.portalTargetId ??= mustBeId(this.portalTargetId);
|
||||||
}
|
this.orientation ??= mustBeOrientation(this.orientation);
|
||||||
|
|
||||||
//
|
mustBeSingleGrapheme(this.typeId);
|
||||||
// If a tile is a portal with a portal target, that target id must be a number or string.
|
mustBeSingleGrapheme(this.minimapChar);
|
||||||
if (this.portalTargetId !== undefined) {
|
mustBeSingleGrapheme(this.revealedMinimapChar);
|
||||||
mustBe(this.portalTargetId, "number", "string");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.minimapChar === undefined) {
|
|
||||||
console.debug("minimap = typeid", { ...this });
|
|
||||||
this.minimapChar = this.typeId;
|
|
||||||
}
|
|
||||||
if (this.revealedMinimapChar === undefined) {
|
|
||||||
console.debug("reveaked = minimap", { ...this });
|
|
||||||
this.revealedMinimapChar = this.minimapChar;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @returns {Tile} */
|
/** @returns {Tile} */
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export class Orientation {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} str
|
* @param {string} str
|
||||||
* @returns {Orientation}
|
* @returns {Orientation|undefined}
|
||||||
*/
|
*/
|
||||||
static fromString(str) {
|
static fromString(str) {
|
||||||
if (typeof str !== "string") {
|
if (typeof str !== "string") {
|
||||||
@@ -35,14 +35,16 @@ export class Orientation {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string|number} val
|
* @param {string|number} val
|
||||||
* @returns {Orientation}
|
* @returns {Orientation|undefined}
|
||||||
*/
|
*/
|
||||||
static normalize(val) {
|
static normalize(val) {
|
||||||
if (typeof val === "string") {
|
if (typeof val === "string") {
|
||||||
return Orientation.fromString(val);
|
return Orientation.fromString(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
return val % 4;
|
if ((val | 0) === val) {
|
||||||
|
return (val | 0) % 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ class DungeonGenerator {
|
|||||||
this.addPillarsToBigRooms();
|
this.addPillarsToBigRooms();
|
||||||
this.addFeatures();
|
this.addFeatures();
|
||||||
this.addPlayerStart();
|
this.addPlayerStart();
|
||||||
// this.addPortals();
|
this.addPortals();
|
||||||
return this.map.toString(CharType.MINIMAP_REVEALED);
|
return this.map.toString(CharType.TYPE_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
generateRooms() {
|
generateRooms() {
|
||||||
|
|||||||
Reference in New Issue
Block a user