screepsmod-map-tool
Version:
# Usage:
847 lines (756 loc) • 26.3 kB
JavaScript
self.terrainCache = {}
self.roomsToBrick = []
const server = ``
const wallChance = 0.25
function getTerrain (room, remote) {
return self.terrainCache[room] || null
}
function refreshSlidersOnPageLoad() {
document.getElementById('wallChanceInput').value = 25;
document.getElementById('sourceChanceInput').value = 75;
document.getElementById('wallChance').innerHTML = 'Walls Chance[25%]';
document.getElementById('sourceChance').innerHTML = '2 Source chance[75%]';
}
function updateSliderText(id, newText) {
document.getElementById(id).innerHTML = newText;
}
async function getAllTerrain () {
const res = await fetch(`${server}/api/maptool/rooms`, { credentials: 'same-origin' })
const { rooms } = await res.json()
rooms.forEach(r => {
self.terrainCache[r.room] = r
})
return rooms
}
const C = {
MINERAL_DENSITY: {
1: 15000,
2: 35000,
3: 70000,
4: 100000
},
MINERAL_DENSITY_PROBABILITY: {
1: 0.1,
2: 0.5,
3: 0.9,
4: 1.0
},
TERRAIN_MASK_WALL: 1,
TERRAIN_MASK_SWAMP: 2,
TERRAIN_MASK_LAVA: 4,
SOURCE_ENERGY_NEUTRAL_CAPACITY: 1500,
ENERGY_REGEN_TIME: 300,
RESOURCE_SILICON: 'silicon',
RESOURCE_METAL: 'metal',
RESOURCE_BIOMASS: 'biomass',
RESOURCE_MIST: 'mist'
}
const common = {
encodeTerrain (terrain) {
var result = ''
for (var y = 0; y < 50; y++) {
for (var x = 0; x < 50; x++) {
var objects = _.filter(terrain, { x, y })
var code = 0
if (_.some(objects, { type: 'wall' })) {
code = code | 1
}
if (_.some(objects, { type: 'swamp' })) {
code = code | 2
}
result = result + code
}
}
return result
},
decodeTerrain (str, room) {
var result = []
for (var y = 0; y < 50; y++) {
for (var x = 0; x < 50; x++) {
var code = str.charAt(y * 50 + x)
if (code & 1) {
result.push({ room, x, y, type: 'wall' })
}
if (code & 2) {
result.push({ room, x, y, type: 'swamp' })
}
}
}
return result
},
checkTerrain (terrain, x, y, mask) {
return (parseInt(terrain.charAt(y * 50 + x)) & mask) > 0
}
}
const utils = {
roomNameFromXY (x, y) {
if (x < 0) {
x = 'W' + (-x - 1)
} else {
x = 'E' + (x)
}
if (y < 0) {
y = 'N' + (-y - 1)
} else {
y = 'S' + (y)
}
return '' + x + y
},
roomNameToXY (name) {
var [match, hor, x, ver, y] = name.match(/^(\w)(\d+)(\w)(\d+)$/)
if (hor == 'W') {
x = -x - 1
} else {
x = +x
// x--;
}
if (ver == 'N') {
y = -y - 1
} else {
y = +y
// y--;
}
return [x, y]
},
writePng (colors, width, height) {
let image = new ImageData(width, height)
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var idx = (width * y + x) << 2
image.data[idx] = colors[y][x][0]
image.data[idx + 1] = colors[y][x][1]
image.data[idx + 2] = colors[y][x][2]
image.data[idx + 3] = colors[y][x][3] === undefined ? 255 : colors[y][x][3]
}
}
return image
},
createTerrainColorsMap (terrain, zoomIn) {
var colors = {}
var width = 50; var height = 50
for (var y = 0; y < height; y++) {
if (zoomIn) {
for (let i = 0; i < zoomIn; i++) {
colors[y * zoomIn + i] = {}
}
} else {
colors[y] = {}
}
for (var x = 0; x < width; x++) {
var color
if (common.checkTerrain(terrain, x, y, C.TERRAIN_MASK_WALL)) {
color = [0, 0, 0]
} else if (common.checkTerrain(terrain, x, y, C.TERRAIN_MASK_SWAMP)) {
color = [35, 37, 19]
} else if (x == 0 || y == 0 || x == 49 || y == 49) {
color = [50, 50, 50]
} else {
color = [43, 43, 43]
}
if (zoomIn) {
for (var dx = 0; dx < zoomIn; dx++) {
for (var dy = 0; dy < zoomIn; dy++) {
colors[y * zoomIn + dy][x * zoomIn + dx] = color
}
}
} else {
colors[y][x] = color
}
}
}
return colors
},
writeTerrainToPng (terrain, zoomIn) {
var colors = this.createTerrainColorsMap(terrain, zoomIn)
return this.writePng(colors, 50 * zoomIn, 50 * zoomIn)
}
}
/** /
`generateRoom(roomName, [opts]) - Generate a new room at the specified location. 'opts' is an object with the following optional properties:\r
* exits - an object with exit coordinates arrays, e.g. {top: [20,21,23], right: [], bottom: [27,28,29,40,41]}, default is random\r
* terrainType - the type of generated landscape, a number from 1 to 28, default is random\r
* swampType - the type of generated swamp configuration, a number from 0 to 14, default is random\r
* sources - the amount of sources in the room, default is random from 1 to 2\r
* mineral - the type of the mineral deposit in this room or false if no mineral, default is random type\r
* controller - whether this room should have the controller, default is true\r
* keeperLairs - whether this room should have source keeper lairs, default is false`,
/**/
function generateRoom (roomName, opts) {
opts = opts || {}
opts.exits = opts.exits || {}
if (!/^[WE]\d+[NS]\d+$/.test(roomName)) {
return q.reject('Invalid room name')
}
function _exitsArray (terrain, x, y) {
var exits = []
for (var i = 0; i < 50; i++) {
if (!common.checkTerrain(terrain, x === undefined ? i : x, y === undefined ? i : y, C.TERRAIN_MASK_WALL)) {
exits.push(i)
}
}
return exits
}
function _genExit () {
var exitLength = Math.floor(Math.random() * 43) + 1
if (opts.hall) exitLength = Math.ceil(Math.random() * 33) + 30
var intervalsCnt = [0, 0, 1, 1, 2][Math.floor(Math.random() * 5)]
var exit = []
var exitStart = Math.floor(Math.random() * (46 - exitLength)) + 2
var intervals = {}
var curStart = exitStart
for (var j = 0; j < intervalsCnt; j++) {
curStart += Math.floor(Math.random() * (exitLength / (intervalsCnt * 2))) + 5
var length = Math.floor(Math.random() * (exitLength / (intervalsCnt * 2))) + 5
if (length + curStart >= exitStart + exitLength - 5) {
length = exitStart + exitLength - curStart - 5
}
intervals[j] = {
start: curStart,
length
}
curStart += length + 1
}
for (var x = exitStart; x <= exitStart + exitLength; x++) {
if (intervalsCnt > 0) {
if (intervals[0].length > 0 && x >= intervals[0].start && x <= intervals[0].start + intervals[0].length) {
continue
}
if (intervalsCnt > 1 && intervals[1].length > 0 && x >= intervals[1].start && x <= intervals[1].start + intervals[1].length) {
continue
}
}
if (x < 2 || x > 47) {
continue
}
exit.push(x)
}
return exit
}
function _matchExitWithNeighbors (exits, dir, neighbor, wallChance) {
var x, y
if (dir == 'top') {
y = 49
}
if (dir == 'right') {
x = 0
}
if (dir == 'bottom') {
y = 0
}
if (dir == 'left') {
x = 49
}
if (exits[dir]) {
if (neighbor) {
var neighborExits = _exitsArray(neighbor.terrain, x, y)
return neighborExits.length == exits[dir].length && _.intersection(neighborExits, exits[dir]).length == neighborExits.length
} else {
return true
}
} else {
if (neighbor) {
exits[dir] = _exitsArray(neighbor.terrain, x, y)
} else {
let sk = !!roomName.match(/^[EW]\d*[4-6][NS]\d*[4-6]$/)
let [_x, _y] = utils.roomNameToXY(roomName)
let hallx = !!roomName.match(/^[EW]\d*[NS]\d*0$/)
let hally = !!roomName.match(/^[EW]\d*0[NS]\d*$/)
let val = Math.random() > (wallChance == undefined ? 0.3 : wallChance)
val |= sk
val |= (dir == 'bottom') && !!utils.roomNameFromXY(_x, _y + 1).match(/^[EW]\d*[4-6][NS]\d*[4-6]$/)
val |= (dir == 'top') && !!utils.roomNameFromXY(_x, _y - 1).match(/^[EW]\d*[4-6][NS]\d*[4-6]$/)
val |= (dir == 'right') && !!utils.roomNameFromXY(_x + 1, _y).match(/^[EW]\d*[4-6][NS]\d*[4-6]$/)
val |= (dir == 'left') && !!utils.roomNameFromXY(_x - 1, _y).match(/^[EW]\d*[4-6][NS]\d*[4-6]$/)
val |= (dir == 'left' || dir == 'right') && hallx
val |= (dir == 'top' || dir == 'bottom') && hally
exits[dir] = val ? _genExit() : []
}
return true
}
}
function _checkFlood (terrain) {
var startX, startY
for (var x = 0; x < 50; x++) {
for (var y = 0; y < 50; y++) {
if (!terrain[y][x].wall) {
startX = x
startY = y
break
}
}
if (startX && startY) {
break
}
}
var visited = {}
for (var y = 0; y < 50; y++) {
visited[y] = {}
for (var x = 0; x < 50; x++) {
visited[y][x] = false
}
}
var list = [[startX, startY]]
do {
var i = list.pop()
var x = i[0]; var y = i[1]
visited[y][x] = true
for (var dx = -1; dx <= 1; dx++) {
for (var dy = -1; dy <= 1; dy++) {
if (!dx && !dy) {
continue
}
if (x + dx >= 0 && x + dx <= 49 && y + dy >= 0 && y + dy <= 49 && !terrain[y + dy][x + dx].wall && !visited[y + dy][x + dx]) {
visited[y + dy][x + dx] = true
list.push([x + dx, y + dy])
}
}
}
}
while (list.length > 0)
for (var y = 0; y < 50; y++) {
for (var x = 0; x < 50; x++) {
if (!terrain[y][x].wall && !visited[y][x]) {
return false
}
}
}
return true
}
function _smoothTerrain (terrain, factor, key) {
var newTerrain = {}
for (var y = 0; y < 50; y++) {
newTerrain[y] = {}
for (var x = 0; x < 50; x++) {
newTerrain[y][x] = _.clone(terrain[y][x])
var cnt = 0
for (var dx = -1; dx <= 1; dx++) {
for (var dy = -1; dy <= 1; dy++) {
if (key == 'wall' && (x + dx < 0 || y + dy < 0 || x + dx > 49 || y + dy > 49) ||
x + dx >= 0 && x + dx <= 49 && y + dy >= 0 && y + dy <= 49 && terrain[y + dy][x + dx][key]) {
cnt++
}
}
}
newTerrain[y][x][key] = cnt >= factor
if (key == 'wall') {
if (x == 0 || x == 49 || y == 0 || y == 49) {
newTerrain[y][x].wall = true
}
if (terrain[y][x].forceOpen) {
newTerrain[y][x].wall = false
}
}
}
}
return newTerrain
}
function _findSourceSpot (terrain, availablePlacements) {
var x, y
var tries = 0
var randomIndex
do {
tries++
randomIndex = Math.floor(Math.random() * availablePlacements.length);
x = Math.floor(Math.random() * (availablePlacements[randomIndex].xMax - availablePlacements[randomIndex].xMin)) + availablePlacements[randomIndex].xMin
y = Math.floor(Math.random() * (availablePlacements[randomIndex].yMax - availablePlacements[randomIndex].yMin)) + availablePlacements[randomIndex].yMin
var passNearby = false
for (var dx = -1; dx <= 1; dx++) {
for (var dy = -1; dy <= 1; dy++) {
if (x + dx < 0 || y + dy < 0 || x + dx > 49 || y + dy > 49) {
continue
}
if (!terrain[y + dy][x + dx].wall) {
passNearby = true
break
}
}
}
if (tries > 1000) {
return [-1, -1]
}
}
while (!terrain[y][x].wall || terrain[y][x].source || !passNearby)
if (availablePlacements.length > 1) {
availablePlacements.splice(randomIndex, 1);
}
return [x, y]
}
function _findKeeperLairSpot (terrain, x, y) {
var lairSpots = []
var list = [[x, y]]
var visited = { [`${x},${y}`]: 0 }
do {
var [cx, cy] = list.pop()
for (var dx = -1; dx <= 1; dx++) {
for (var dy = -1; dy <= 1; dy++) {
if (!dx && !dy || !_.isUndefined(visited[`${cx + dx},${cy + dy}`])) {
continue
}
if (cx + dx < 0 || cy + dy < 0 || cx + dx > 49 || cy + dy > 49) {
continue
}
var distance = visited[`${cx},${cy}`] + 1
visited[`${cx + dx},${cy + dy}`] = distance
if (distance >= 3 && distance <= 5 && terrain[cy + dy][cx + dx].wall && !terrain[cy + dy][cx + dx].source &&
(cx + dx > 0 && cx + dx < 49 && cy + dy > 0 && cy + dy < 49)) {
lairSpots.push([cx + dx, cy + dy])
}
if (!terrain[cy + dy][cx + dx].wall && distance < 5) {
list.push([cx + dx, cy + dy])
}
}
}
}
while (list.length > 0)
if (lairSpots.length > 0) {
lairSpots = _.shuffle(lairSpots)
for (let i = 0; i < lairSpots.length; i++) {
var foundSource = false
for (var dx = -5; dx <= 5; dx++) {
for (var dy = -5; dy <= 5; dy++) {
if (lairSpots[i][0] + dx < 0 || lairSpots[i][1] + dy < 0 || lairSpots[i][0] + dx > 49 || lairSpots[i][1] + dy > 49) {
continue
}
if (lairSpots[i][0] + dx == x && lairSpots[i][1] + dy == y) {
continue
}
if (terrain[lairSpots[i][0] + dx][lairSpots[i][1] + dy].source) {
foundSource = true
}
}
}
if (!foundSource) {
return [lairSpots[i][0], lairSpots[i][1]]
}
}
}
return [-1, -1]
}
function _genTerrain (wallType, swampType, exits, sources, controller, keeperLair, mineral, type) {
var types = {
1: { fill: 0.4, smooth: 10, factor: 5 },
2: { fill: 0.2, smooth: 20, factor: 4 },
3: { fill: 0.2, smooth: 20, factor: 4 },
4: { fill: 0.3, smooth: 18, factor: 4 },
5: { fill: 0.3, smooth: 10, factor: 4 },
6: { fill: 0.3, smooth: 10, factor: 4 },
7: { fill: 0.3, smooth: 10, factor: 4 },
8: { fill: 0.35, smooth: 15, factor: 4 },
9: { fill: 0.3, smooth: 2, factor: 4 },
10: { fill: 0.35, smooth: 2, factor: 4 },
11: { fill: 0.35, smooth: 5, factor: 4 },
12: { fill: 0.35, smooth: 5, factor: 4 },
13: { fill: 0.25, smooth: 5, factor: 4 },
14: { fill: 0.4, smooth: 3, factor: 5 },
15: { fill: 0.5, smooth: 3, factor: 5 },
16: { fill: 0.45, smooth: 4, factor: 5 },
17: { fill: 0.45, smooth: 6, factor: 5 },
18: { fill: 0.45, smooth: 10, factor: 5 },
19: { fill: 0.5, smooth: 10, factor: 5 },
20: { fill: 0.4, smooth: 3, factor: 5 },
21: { fill: 0.5, smooth: 2, factor: 5 },
22: { fill: 0.45, smooth: 4, factor: 5 },
23: { fill: 0.45, smooth: 6, factor: 5 },
24: { fill: 0.45, smooth: 10, factor: 5 },
25: { fill: 0.5, smooth: 10, factor: 5 },
26: { fill: 0.45, smooth: 10, factor: 5 },
27: { fill: 0.45, smooth: 6, factor: 5 },
28: { fill: 0.2, smooth: 20, factor: 4 }
}
var swampTypes = {
1: { fill: 0.3, smooth: 3, factor: 5 },
2: { fill: 0.35, smooth: 3, factor: 5 },
3: { fill: 0.45, smooth: 3, factor: 5 },
4: { fill: 0.25, smooth: 1, factor: 5 },
5: { fill: 0.25, smooth: 30, factor: 4 },
6: { fill: 0.52, smooth: 30, factor: 5 },
7: { fill: 0.45, smooth: 3, factor: 5 },
// 7: {fill: 0.60, smooth: 3, factor: 5},
8: { fill: 0.3, smooth: 1, factor: 5 },
9: { fill: 0.3, smooth: 1, factor: 4 },
10: { fill: 0.3, smooth: 3, factor: 5 },
11: { fill: 0.3, smooth: 3, factor: 5 },
12: { fill: 0.3, smooth: 1, factor: 5 },
13: { fill: 0.25, smooth: 1, factor: 5 },
14: { fill: 0.35, smooth: 3, factor: 5 }
}
var terrain; var tries = 0
do {
terrain = {}
tries++
if (tries > 100) {
wallType = Math.floor(Math.random() * 27) + 1
tries = 0
}
for (var y = 0; y < 50; y++) {
terrain[y] = {}
for (var x = 0; x < 50; x++) {
terrain[y][x] = {}
}
}
for (var y = 0; y < 50; y++) {
for (var x = 0; x < 50; x++) {
if (y == 0 && _.isArray(exits.top) && _.includes(exits.top, x)) {
terrain[y][x].forceOpen = true
terrain[y + 1][x].forceOpen = true
terrain[y][x].exit = true
continue
}
if (y == 49 && _.isArray(exits.bottom) && _.includes(exits.bottom, x)) {
terrain[y][x].forceOpen = true
terrain[y - 1][x].forceOpen = true
terrain[y][x].exit = true
continue
}
if (x == 0 && _.isArray(exits.left) && _.includes(exits.left, y)) {
terrain[y][x].forceOpen = true
terrain[y][x + 1].forceOpen = true
terrain[y][x].exit = true
continue
}
if (x == 49 && _.isArray(exits.right) && _.includes(exits.right, y)) {
terrain[y][x].forceOpen = true
terrain[y][x - 1].forceOpen = true
terrain[y][x].exit = true
continue
}
terrain[y][x].wall = Math.random() < types[wallType].fill
terrain[y][x].swamp = swampType ? Math.random() < swampTypes[swampType].fill : false
}
}
for (var i = 0; i < types[wallType].smooth; i++) {
terrain = _smoothTerrain(terrain, types[wallType].factor, 'wall')
}
}
while (!_checkFlood(terrain))
if (swampType) {
for (var i = 0; i < swampTypes[swampType].smooth; i++) {
terrain = _smoothTerrain(terrain, swampTypes[swampType].factor, 'swamp')
}
}
var availablePlacements = [];
if (type == 'sk' || type == 'center') {
availablePlacements.push({xMin: 2, xMax: 19, yMin: 2, yMax: 19})
availablePlacements.push({xMin: 29, xMax: 47, yMin: 2, yMax: 19})
availablePlacements.push({xMin: 2, xMax: 19, yMin: 29, yMax: 47})
availablePlacements.push({xMin: 29, xMax: 47, yMin: 29, yMax: 47})
} else {
availablePlacements.push({xMin: 2, xMax: 47, yMin: 2, yMax: 47})
}
for (var i = 0; i < sources; i++) {
let [x, y] = _findSourceSpot(terrain, availablePlacements)
if (x == -1 && y == -1) {
return _genTerrain(Math.floor(Math.random() * 27) + 1, swampType, exits, sources, controller, keeperLair, mineral, type)
}
terrain[y][x].source = true
if (keeperLair) {
[x, y] = _findKeeperLairSpot(terrain, x, y)
if (x == -1 && y == -1) {
return _genTerrain(Math.floor(Math.random() * 27) + 1, swampType, exits, sources, controller, keeperLair, mineral, type)
}
terrain[y][x].keeperLair = true
}
}
if (true) { // mineral
let [x, y] = _findSourceSpot(terrain, availablePlacements)
if (x == -1 && y == -1) {
return _genTerrain(Math.floor(Math.random() * 27) + 1, swampType, exits, sources, controller, keeperLair, mineral, type)
}
terrain[y][x].mineral = true
if (keeperLair) {
[x, y] = _findKeeperLairSpot(terrain, x, y)
if (x == -1 && y == -1) {
return _genTerrain(Math.floor(Math.random() * 27) + 1, swampType, exits, sources, controller, keeperLair, mineral, type)
}
terrain[y][x].keeperLair = true
}
}
if (controller) {
var x, y
do {
x = Math.floor(Math.random() * 40) + 5
y = Math.floor(Math.random() * 40) + 5
var passNearby = false
for (var dx = -1; dx <= 1; dx++) {
for (var dy = -1; dy <= 1; dy++) {
if (x + dx < 0 || y + dy < 0 || x + dx > 49 || y + dy > 49) {
continue
}
if (!terrain[y + dy][x + dx].wall) {
passNearby = true
break
}
}
}
}
while (!terrain[y][x].wall || !passNearby || terrain[y][x].source || terrain[y][x].mineral || terrain[y][x].keeperLair)
terrain[y][x].controller = true
}
return terrain
}
var [x, y] = utils.roomNameToXY(roomName)
return q.all([
getTerrain(utils.roomNameFromXY(x, y - 1)),
getTerrain(utils.roomNameFromXY(x + 1, y)),
getTerrain(utils.roomNameFromXY(x, y + 1)),
getTerrain(utils.roomNameFromXY(x - 1, y))
])
.then(neighborRooms => {
if (!_matchExitWithNeighbors(opts.exits, 'top', neighborRooms[0], opts.wallChance)) {
opts.exits.top = []
// return q.reject(`Exits in room ${neighborRooms[0].room} don't match`);
}
if (!_matchExitWithNeighbors(opts.exits, 'right', neighborRooms[1], opts.wallChance)) {
opts.exits.right = []
// return q.reject(`Exits in room ${neighborRooms[1].room} don't match`);
}
if (!_matchExitWithNeighbors(opts.exits, 'bottom', neighborRooms[2], opts.wallChance)) {
opts.exits.bottom = []
// return q.reject(`Exits in room ${neighborRooms[2].room} don't match`);
}
if (!_matchExitWithNeighbors(opts.exits, 'left', neighborRooms[3], opts.wallChance)) {
opts.exits.left = []
// return q.reject(`Exits in room ${neighborRooms[3].room} don't match`);
}
opts.exits.top = opts.exits.top || []
opts.exits.left = opts.exits.left || []
opts.exits.bottom = opts.exits.bottom || []
opts.exits.right = opts.exits.right || []
if (opts.terrainType === undefined) {
opts.terrainType = Math.floor(Math.random() * 27) + 1
}
if (opts.swampType === undefined) {
opts.swampType = Math.floor(Math.random() * 14)
}
if (opts.sources === undefined) {
opts.sources = Math.random() > 0.5 ? 1 : 2
}
if (opts.controller === undefined) {
opts.controller = true
}
if (opts.keeperLairs === undefined) {
opts.keeperLairs = false
}
var roomData = _genTerrain(opts.terrainType, opts.swampType, opts.exits, opts.sources, opts.controller, opts.keeperLairs, opts.mineral, opts.type)
var objects = []; var terrain = []; var x; var y; var sourceKeepers = false
for (var y in roomData) {
y = parseInt(y)
for (var x in roomData[y]) {
x = parseInt(x)
if (roomData[y][x].wall) {
terrain.push({ type: 'wall', x, y })
}
if (roomData[y][x].source) {
objects.push({
room: roomName,
type: 'source',
x,
y,
'energy': C.SOURCE_ENERGY_NEUTRAL_CAPACITY,
'energyCapacity': C.SOURCE_ENERGY_NEUTRAL_CAPACITY,
'ticksToRegeneration': C.ENERGY_REGEN_TIME
})
}
if (roomData[y][x].controller) {
objects.push({ room: roomName, type: 'controller', x, y, level: 0 })
}
if (roomData[y][x].keeperLair) {
objects.push({ room: roomName, type: 'keeperLair', x, y })
sourceKeepers = true
}
if (roomData[y][x].swamp) {
var flag = false
for (var dx = -1; dx <= 1; dx++) {
for (var dy = -1; dy <= 1; dy++) {
if (x + dx >= 0 && y + dy >= 0 && x + dx <= 49 && y + dy <= 49 && !roomData[y + dy][x + dx].wall) {
flag = true
break
}
}
if (flag) {
break
}
}
if (flag) {
terrain.push({ type: 'swamp', x, y })
}
}
if (roomData[y][x].mineral) {
if (opts.mineral === undefined) {
var types = ['H', 'H', 'H', 'H', 'H', 'H', 'O', 'O', 'O', 'O', 'O', 'O', 'Z', 'Z', 'Z', 'K', 'K', 'K', 'U', 'U', 'U', 'L', 'L', 'L', 'X']
opts.mineral = types[Math.floor(Math.random() * types.length)]
}
if (opts.mineral) {
var random = Math.random(); var density
for (var d in C.MINERAL_DENSITY_PROBABILITY) {
if (random <= C.MINERAL_DENSITY_PROBABILITY[d]) {
density = +d
break
}
}
objects.push({ room: roomName, type: 'mineral', x, y, mineralType: opts.mineral, density: density, mineralAmount: C.MINERAL_DENSITY[density] })
if (!opts.controller || opts.keeperLairs) {
objects.push({
type: 'extractor',
x: x,
y: y,
room: roomName
})
}
}
}
}
}
terrain = common.encodeTerrain(terrain)
/*
if (opts.mineral) {
var mx, my, isWall, hasSpot, hasObjects
do {
mx = 4 + Math.floor(Math.random() * 42)
my = 4 + Math.floor(Math.random() * 42)
isWall = common.checkTerrain(terrain, mx, my, C.TERRAIN_MASK_WALL)
hasSpot = false
for (var dx = -1; dx <= 1; dx++) {
for (var dy = -1; dy <= 1; dy++) {
if (!common.checkTerrain(terrain, mx + dx, my + dy, C.TERRAIN_MASK_WALL)) {
hasSpot = true
}
}
}
hasObjects = _.some(objects, i => (i.type == 'source' || i.type == 'controller') && Math.abs(i.x - mx) < 5 && Math.abs(i.y - my) < 5)
}
while (!isWall || !hasSpot || hasObjects)
objects.push({
type: 'mineral',
mineralType: opts.mineral,
density,
mineralAmount: C.MINERAL_DENSITY[density],
x: mx,
y: my,
room: roomName
})
if (!opts.controller || opts.keeperLairs) {
objects.push({
type: 'extractor',
x: mx,
y: my,
room: roomName
})
}
} */
{
let [x, y] = utils.roomNameToXY(roomName)
return {
room: roomName,
x,
y,
terrain,
objects,
opts,
sourceKeepers: opts.keeperLairs,
depositType: opts.depositType,
bus: !opts.sources && !opts.mineral
}
}
})
}