// If the element has reactions, loop through each one (it is an object), if the value for elem1 or elem2 is not an element and is not null, remove that key
	if (elements[key].reactions) {
		for (var reaction in elements[key].reactions) {
			// If elem1 exists
			if (elements[key].reactions[reaction].elem1) {
				// If elem1 is an array, loop through each element, else check once. Don't delete if it === null
				if (Array.isArray(elements[key].reactions[reaction].elem1)) { 
					for (var i = 0; i < elements[key].reactions[reaction].elem1.length; i++) {
						if (elements[key].reactions[reaction].elem1[i] && !elements[elements[key].reactions[reaction].elem1[i]]) {
							elements[key].reactions[reaction].elem1.splice(i,1);
						}
					}
				}
				else if (elements[key].reactions[reaction].elem1 && !elements[elements[key].reactions[reaction].elem1]) {
					delete elements[key].reactions[reaction].elem1;
				}
			}
			// If elem2 exists
			if (elements[key].reactions[reaction].elem2) {
				// If elem2 is an array, loop through each element, else check once. Don't delete if it === null
				if (Array.isArray(elements[key].reactions[reaction].elem2)) {
					for (var i = 0; i < elements[key].reactions[reaction].elem2.length; i++) {
						if (elements[key].reactions[reaction].elem2[i] && !elements[elements[key].reactions[reaction].elem2[i]]) {
							elements[key].reactions[reaction].elem2.splice(i,1);
						}
					}
				}
				else if (elements[key].reactions[reaction].elem2 && !elements[elements[key].reactions[reaction].elem2]) {
					delete elements[key].reactions[reaction].elem2;
				}
			}
		}
	}

	// If the element's stateHigh or stateLow is not an element, remove it and tempHigh/Low
	if (elements[key].stateHigh) {
		// If it's an array, do it for each item, otherwise, just do it once
		if (Array.isArray(elements[key].stateHigh)) {
			for (var i = 0; i < elements[key].stateHigh.length; i++) {
				if (!elements[elements[key].stateHigh[i]] && elements[key].stateHigh[i] !== null) {
					elements[key].stateHigh.splice(i,1);
				}
			}
			if (elements[key].stateHigh.length == 0) {
				delete elements[key].stateHigh;
				delete elements[key].tempHigh;
			}
		}
		else {
			if (!elements[elements[key].stateHigh] && elements[key].stateHigh !== null) {
				delete elements[key].stateHigh;
				delete elements[key].tempHigh;
			}
		}
	}
	if (elements[key].stateLow) {
		if (Array.isArray(elements[key].stateLow)) {
			for (var i = 0; i < elements[key].stateLow.length; i++) {
				if (!elements[elements[key].stateLow[i]] && elements[key].stateLow[i] !== null) {
					elements[key].stateLow.splice(i,1);
				}
			}
			if (elements[key].stateLow.length == 0) {
				delete elements[key].stateLow;
				delete elements[key].tempLow;
			}
		}
		else {
			if (!elements[elements[key].stateLow] && elements[key].stateLow !== null) {
				delete elements[key].stateLow;
				delete elements[key].tempLow;
			}
		}
	}
	// same for burnInto
	if (elements[key].burnInto) {
		if (Array.isArray(elements[key].burnInto)) {
			for (var i = 0; i < elements[key].burnInto.length; i++) {
				if (!elements[elements[key].burnInto[i]]) {
					delete elements[key].burnInto[i];
				}
			}
			if (elements[key].burnInto.length == 0) {
				delete elements[key].burnInto;
			}
		}
		else {
			if (!elements[elements[key].burnInto]) {
				delete elements[key].burnInto;
			}
		}
	}
	// same for breakInto
	if (elements[key].breakInto) {
		if (Array.isArray(elements[key].breakInto)) {
			for (var i = 0; i < elements[key].breakInto.length; i++) {
				if (elements[key].breakInto[i]!==null && !elements[elements[key].breakInto[i]]) { delete elements[key].breakInto[i]; }
			}
			if (elements[key].breakInto.length == 0) { delete elements[key].breakInto; }
		}
		else {
			if (elements[key].breakInto[i]!==null && !elements[elements[key].breakInto]) { delete elements[key].breakInto; }
		}
	}





let xstart = x-1;
let ystart = y-1;
let xsize = pixelSize3;
let ysize = pixelSize3;
if (!isEmpty(x-1, y)) {
	xstart ++;
	xsize -= pixelSize;
}
if (!isEmpty(x+1, y)) {
	xsize -= pixelSize;
}
if (!isEmpty(x, y-1)) {
	ystart ++;
	ysize -= pixelSize;
}
if (!isEmpty(x, y+1)) {
	ysize -= pixelSize;
}

ctx.fillRect(canvasCoord(xstart), canvasCoord(y), xsize, pixelSize);
ctx.fillRect(canvasCoord(x), canvasCoord(ystart), pixelSize, ysize);



if (Math.random() < 0.5) {
let trapped = true;
for (let i = 0; i < adjacentCoords.length; i++) {
	const coord = adjacentCoords[i];
	const x = pixel.x + coord[0];
	const y = pixel.y + coord[1];
	if (!(y > height-currentSaveData.border || y < currentSaveData.border || x > width-currentSaveData.border || x < currentSaveData.border) &&
		(pixelMap[x][y] === undefined ||
		elements[pixelMap[x][y].element].id !== info.id)
	) {
		trapped = false;
		break;
	}
}
if (trapped === true) {
	pixel.opti = pixelTicks;
	return false;
}
}




function worldGen(worldtype) {
	var complexity = worldtype.complexity || 20;
	var heightVariance = worldtype.heightVariance || 0.5;
	var baseHeight = height-(height*(worldtype.baseHeight || 0.5));
	var layers = worldtype.layers || {0:"rock"};
	var yoffsets = generateTerrainHeights(width,heightVariance,complexity);
	// 2D world vertical generator
	for (var x = 0; x <= width; x++) {
		var yoffset = yoffsets[x];
		var worldHeight = baseHeight+yoffset;
		for (var y = 0; y <= height; y++) {
			// Change element type based on y, from grass > dirt > rock > basalt
			if (y > worldHeight) {
				// distance from the bottom of worldHeight
				var frombottom = worldHeight-(y-worldHeight);
				var element = null;
				for (var i in layers) {
					var layer = layers[i];
					if (layer[0] == 0 && yoffset < 0) {
						layer[0] = yoffset;
					}
					if (frombottom > worldHeight*layer[0] && Math.random() < (layer[2] || 1)) {
						if (elements[layer[1]]) {
							element = layer[1];
							break
						}
					}
				}
				if (y >= height && (currentSaveData.voidY || currentSaveData.loopY)) {
					element = currentSaveData.borderElem ? null : "wall";
				}
				if ((x >= width || x === 0) && (currentSaveData.voidX || currentSaveData.loopX)) {
					element = currentSaveData.borderElem ? null : "wall";
				}
				if (element) {
					createPixel(element,x,y);
					if (worldtype.temperature) {
						pixelMap[x][y].temp = worldtype.temperature;
					}
				}
			}
		}
	}
	// decor
	if (worldtype.decor) {
		for (var i = 0; i < worldtype.decor.length; i++) {
			var decor = worldtype.decor[i];
			var element = decor[0];
			var chance = decor[1];
			for (var x = 1; x < width; x++) {
				var y = decor[2] || 5;
				// add or subtract worldtype.decorVariance from y
				y += Math.round(Math.random()*(worldtype.decorVariance||2) - (worldtype.decorVariance||2)/2);
				if (Math.random() < chance && isEmpty(x,y)) {
					createPixel(element,x,y);
					if (worldtype.temperature) {
						pixelMap[x][y].temp = worldtype.temperature;
					}
					if (decor[3]) {
						pixelMap[x][y].color = pixelColorPick(pixelMap[x][y],decor[3])
					}
				}
			}
		}
	}
}

// Generate worldgen options
// Loop through the worldgentypes object, add the key to the #worldgenselect select as an option with the value of the key and the name of the key capitalized and underscores replaced with spaces
for (var key in worldgentypes) {
	document.getElementById("worldgenselect").innerHTML += "<option value='" + key + "'>" + key.replace(/_/g, " ").replace(/\b\w/g, l => l.toUpperCase()) + "</option>";
}
if (settings["worldgen"] && !worldgentypes[settings["worldgen"]]) {
	settings["worldgen"] = "off";
}