import { random } from "../random_utils.js";
import Model from "./model.js";
/**
* Template for creating location instances. Defines the blueprint for creating location
* instances, including their properties, sub-divisions, material contents, and behavior patterns.
*
* @extends Model
*/
export class LocationTemplate extends Model {
/**
* Creates a new LocationTemplate instance.
*
* @constructor
* @param {Object} [params={}] - Configuration parameters
* @param {String} [params.type] - Unambiguous and unique, human-readable label for the location type. Either `type` or `room` must be provided and they are mutually exclusive.
* @param {String} [params.room] - If present, supplies the type of the location, and also indicates that is a room, which will not be not included in the list of locations from which you can start to build a top-down representation of a location. Either `type` or `room` must be provided and they are mutually exclusive.
* @param {String} [params.name=params.type] - The display name of a location. Can contain alternatives in the string form "{A|B}"
* @param {String[]} [params.tags] - Array of tags to categorize this location template
* @param {Boolean} [params.abstract=false] - Whether this is an abstract template that cannot be instantiated directly
* @param {Object} [params.contents] - Contents configuration to create content of this location in the format defined by the `selectElements` function.
* @param {Object} [params.inventory] - An array of configurations for the inventory of this location, each in the format defined by the `bagSpecParser` function.
* @param {Array|Object} [params.ch] - The child nodes of this location template, either as an array of types, or as an object in the format defined by the `selectElements` function.
* @param {String} [params.descr] - Description of the location, store policies, etc.
* @param {String} [params.owner] - The profession to use when generating an owner of a store
* @param {Array} [params.sequences] - An array of sequence configurations for this location template. Each contains an `id`, and array of sequence naming `options`, from which one will be selected each time a location is instantiated from this template.
*/
constructor({
id, // e.g. House109
type, // e.g. "House"
name, // e.g. "{A|B}"
tags = [],
contents = {},
inventory = {},
ch = [],
description,
image,
owner,
traits = [],
sequences = [],
} = {}) {
super({ tags });
this.id = id || type;
this.type = type;
this.name = name || type;
// this.room = room;
// this.div = div;
// this.abstract = abstract;
this.description = description;
this.image = image;
this.contents = Object.freeze(contents);
this.inventory = Object.freeze(inventory);
this.ch = Object.freeze(ch);
this.owner = owner;
this.traits = Object.freeze(traits);
this.sequences = Object.freeze(sequences);
}
}
/**
* Represents an actual location instance created from a LocationTemplate.
* Contains the runtime state and hierarchical relationships between locations.
*
* @extends Model
*/
export class Location extends Model {
/**
* Creates a new Location instance from a template.
*
* @constructor
* @param {LocationTemplate} template - The template to create this location from
* @param {Location} [parent] - The parent location in the hierarchy
*/
constructor(template, parent) {
super({ tags: template.tags });
this.id = template.id;
this.name = template.name;
this.type = template.type;
this.description = template.description ? [template.description] : [];
this.image = template.image;
// this.room = template.room;
// this.div = template.div;
this.contents = [];
this.inventory = [];
this.children = [];
this.parent = parent;
this.sequences = template.sequences.map((sequence) => {
return {
id: sequence.id,
seqType: random(sequence.options),
// to support defining sequences in place with the "as" syntax, we need to
// carry that actual list over because there's no defined sequence in the data
// file, or the pre-canned types of sequences (e.g. "alpha")
options: sequence.options,
index: 0,
};
});
}
/**
* Adds a child location to this location's hierarchy.
*
* @param {Location} child - The child location to add
* @throws {Error} If the child is not a Location instance
*/
addChild(child) {
if (!(child instanceof Location)) {
throw new Error("Cannot add a template to a location: " + child);
}
child.parent = this;
this.children.push(child);
}
}