UNPKG

axolemma

Version:

A tool to procedurally generate areas compatible with the Ranvier MUD engine.

136 lines (112 loc) 3.08 kB
const ROT = require('rot-js') const Room = require('./room') const {noop} = require('../util') module.exports = class Map2D { constructor (config = {}) { this.config = config const {height, width, zLevel = 0} = config this.height = height this.width = width this.zLevel = zLevel this.map = [] this.fill() } fill () { this.map.length = this.width this.map.fill(null) this.map = this.map.map(row => (new Array(this.height).fill(null))) } getRoomByCoords (...coordinates) { const [x, y] = coordinates return this.map[x][y] } create (mapper) { const creationCallback = this.config.weightedRoomsTable ? this.weightedCreation.bind(this) : this.defaultCreation.bind(this) this._id = 0; mapper.create(creationCallback) } defaultCreation (x, y, value) { if (value) return // Already done. const { title, description } = this.config const room = new Room({ title, description }) this.map[x][y] = room room.setCoordinates(x, y, this.zLevel) room.setId(this._id++) } weightedCreation (x, y, value) { if (value) return // Already done. const pick = ROT.RNG.getWeightedValue(this.getWeightedTable()) const roomDef = this.config.weightedRoomsTable[pick] const { title = this.config.title, description = this.config.description } = roomDef // Handle arbitrary props on room definition. const other = {} for (const [prop, value] of Object.entries(roomDef)) { if (['title', 'description', 'weight'].includes(prop)) { continue; } other[prop] = value; } const room = new Room({ title, description, other }) this.map[x][y] = room room.setCoordinates(x, y, this.zLevel) room.setId(this._id++) } getWeightedTable () { if (!this._weightedTable){ this._weightedTable = {} for (const [id, def] of Object.entries(this.config.weightedRoomsTable)) { if (!def.weight) { console.log('Invalid or missing weight for ', id) continue; } this._weightedTable[id] = def.weight } } return this._weightedTable } iterate (roomCallback = noop, rowCallback = noop) { for (const row of this.map) { for (const room of row) { roomCallback(room) } rowCallback(row) } return this } iterateBreadth (roomCallback = noop, rowCallback = noop) { // draw() this starting with X rather than relying on row recursion, // which flips the map 90 degrees. for(var y = 0; y < this.height; y++) { for(var x = 0; x < this.width; x++) { roomCallback(this.getRoomByCoords(x,y)) } rowCallback() } return this } draw () { let display = '' this.iterateBreadth( room => { display += (room ? '.' : '#') }, () => { display += '\n' } ) return display } getAllRooms () { const rooms = [] this.iterate(room => room ? rooms.push(room) : null) return rooms } }