This commit is contained in:
slweeb 2023-04-22 10:40:05 -04:00
commit 7108a21791
4 changed files with 493 additions and 9 deletions

View File

@ -1613,6 +1613,32 @@
return !isEmpty(x,y+1,true);
};
//Freeze pixel
function freezePixel(pixel,changetemp=true) {
var info = elements[pixel.element];
var result = info.stateLow;
if (!result) {
return false
};
if(result instanceof Array) {
result = result.filter(elementExists);
if(result.length == 0) {
return false;
};
} else {
if(!(elementExists(result))) {
return false;
};
};
while(result instanceof Array) {
result = randomChoice(result);
};
changePixel(pixel,result,changetemp);
return true;
};
//Logic
function xor(c1,c2) {
@ -1695,3 +1721,30 @@
};
return elements[name];
};
//Fixes
//fix -1-caused ghost pixels
function deletePixel(x,y) {
// remove pixelMap[x][y] from currentPixels
var pixelIndex = currentPixels.indexOf(pixelMap[x][y]);
if(pixelIndex !== -1) {
currentPixels.splice(pixelIndex,1)
};
if (pixelMap[x][y]) {pixelMap[x][y].del = true}
delete pixelMap[x][y];
/*for (var i = 0; i < currentPixels.length; i++) {
if (currentPixels[i].x == x && currentPixels[i].y == y) {
currentPixels.splice(i, 1);
break;
}
}*/
/*if (id != null) {
for (var i = 0; i < currentPixels.length; i++) {
if (currentPixels[i].id == id) {
currentPixels.splice(i, 1);
return;
}
}
}*/
}

View File

@ -1,18 +1,61 @@
var modName = "mods/prompt.js";
var variablesMod = "mods/prop and prompt variables.js";
var promptInputNullishes = ["null","none","","n/a"];
var eightSpaces = " ".repeat(8);
if(enabledMods.includes(variablesMod)) {
commandHelpObject = {
"set": "Sets properties for every pixel of a given type.\nUsage: set [property] [element] [value] <type>\nDon't include framing characters []<>.\nThe element can be \"all\" to set the property for every pixel.\nNote: Strings can't have spaces because spaces are the separator used in the parsing split().\nArguments in [brackets] are required and ones in <angle brackets> are optional.",
"test": "Test.",
"setdimensions": "#This command clears the canvas#\nSets the width and height of the canvas and resets it to regenerate pixelMap.\nThis is offsetted so it doesn't count the OoB area on the top left; a 50x50 save will have a 50x50 usable area.\nUsage: setdimensions [width] [height] <pixel rendering size>.\nDon't include framing characters []<>.\nArguments in [brackets] are required and ones in <angle brackets> are optional.",
"pixelsize": "Sets the size of the pixels on screen. If no size is given, it instead alerts the current pixel size. Usage: pixelsize <pixel rendering size>.\nDon't include framing characters <>.\nArguments in <angle brackets> are optional.",
"dimensions": "Alerts the current dimensions. Usage: dimensions",
"fill": "Fills the screen with the given pixel(s). Usage: fill [Overwrite pixels? (bool)] [element] <additional elements>.\nDon't include framing characters []<>.\nArguments in [brackets] are required and ones in <angle brackets> are optional.\nAdditional elements are separated by spaces.",
"randomfill": "Fills the screen with pixels from randomChoices. Usage: randomfill <overwrite pixels? (bool, default: true)>\nDon't include framing characters []<>.\nArguments in <angle brackets> are optional.",
"count": "Tells you the amount of a specified pixel on the screen. Usage: count [element]\nDon't include framing characters []<>.\nArguments in [brackets] are required.",
"countall": "Logs to console a list of all elements on screen and their amounts. Usage: countall.",
"help": "Usage: help <command>\nDon't include framing characters []<>.\nArguments in <angle brackets> are optional."
"worldgen":
`Names or sets the current world type, lists all world types, or generates a given world type.
Usages:
${eightSpaces}Show the current worldgen setting: worldgen
${eightSpaces}List all available worldgen settings: worldgen list
${eightSpaces}Set the current worldgen setting: worldgen set [setting]
${eightSpaces}Generate a specified worldgen setting: worldgen generate [setting]`,
"defineworldgen":
`Creates or replaces a worldgen preset.
Usage (See below for formats): [name] [layers] <baseHeight> <heightVariance> <complexity> <temperature> <decor>.
Don't include framing characters []<>.
Arguments in [brackets] are required and ones in <angle brackets> are optional.",
(Required) name: String. Cannot have spaces. Example: grass
(Required) layers:
${eightSpaces}Each layer is specified as [RelativeBottomStartPosition:ElementName]<:PixelProbability>
${eightSpaces}Layers are joined with the semicolon ;
${eightSpaces}Layer definitions must not have any spaces.
${eightSpaces}Example full layer definition: 0.85:grass;0.5:dirt;0.05:rock;-0.2:basalt`,
"defineworldgen2":
`(Optional) baseHeight: Number (ideally between 0 and 1). Default: 0.5.
(Optional) heightVariance: Number. Default: 0.5.
(Optional) complexity: Number. Default: 20.
(Optional) temperature: Number. No default value (use null or none to skip).
(Optional) decor:
${eightSpaces}Each decor layer is specified as [ElementName:PixelProbability]<:DistanceFromTop><:ListOfHexColors>
${eightSpaces}Distance from top, if not specified, defaults to 5.
${eightSpaces}The fourth part (optional) is a list of hex codes (like #FFFFFF) separated by commas.
${eightSpaces}Example full decor definition: bird:0.04:10:#FF0000,#FFFF00,#00FF00;diamond:0.3:5`,
"help": "Usage: help <command>\nDon't include framing characters []<>\nArguments in <angle brackets> are optional."
};
if(enabledMods.includes("mods/code_library.js")) {
@ -180,6 +223,23 @@ if(enabledMods.includes(variablesMod)) {
return {h: hue, s: saturation, l: lightness};
}
function rebuildWorldgenList() { //vanilla code
for (var key in worldgentypes) {
document.getElementById("worldgenselect").innerHTML += "<option value='" + key + "'>" + key.replace(/_/g, " ").replace(/\b\w/g, l => l.toUpperCase()) + "</option>";
}
};
function bareClear() {
currentPixels = [];
pixelMap = [];
for (var i = 0; i < width; i++) {
pixelMap[i] = [];
for (var j = 0; j < height; j++) {
pixelMap[i][j] = undefined;
}
}
};
function alertIfError(alertError,text) {
if(alertError) {
alert(text);
@ -198,9 +258,141 @@ if(enabledMods.includes(variablesMod)) {
}
}
function parsefloatFirst(arr) { var array = arr; array[0] = parseFloat(array[0]); return array };
function stringToLayers(string) {
return string.split(";").map(x => x.split(":")).map(y => parsefloatFirst(y));
};
function validateSingleHexCode(hexCode) {
return !!"#FFFFFF".match(/^#[0-9A-F]{6}$/);
};
function validateHexColorArray(colorsArray) {
if(!(colorsArray instanceof Array)) {
return false;
};
if(colorsArray.length == 0) {
return false;
};
var colorsIsValid = 1;
for(var i in colorsArray) {
colorsIsValid *= validateSingleHexCode(colorsArray[i]);
};
return !!colorsIsValid;
};
function validateSingleLayer(layerArray) {
if(layerArray.length < 2) {
return false;
};
if(isNaN(layerArray[0])) {
return false;
};
if(typeof(layerArray[1]) !== "string") {
return false;
};
if(!elements[layerArray[1]]) {
return false;
};
if(typeof(layerArray[2]) !== "undefined") {
if(isNaN(layerArray[2])) {
return false
};
};
return true;
};
function validateLayersStructure(layersArray) {
if(!(layersArray instanceof Array)) {
return false;
};
if(layersArray.length == 0) {
return false;
};
var layersIsValid = 1;
for(var i in layersArray) {
layersIsValid *= validateSingleLayer(layersArray[i]);
};
return !!layersIsValid;
};
function stringToDecor(string) {
decorLayers = string.split(";").map(x => x.split(":"));
for(var q in decorLayers) {
var decorLayer = decorLayers[q];
if(decorLayer[1]) {
decorLayer[1] = parseFloat(decorLayer[1]);
};
if(decorLayer[2]) {
decorLayer[2] = parseInt(decorLayer[2]);
};
if(decorLayer[3]) {
decorLayer[3] = decorLayer[3].split(",");
};
};
return decorLayers;
};
//console.log(stringToDecor("bird:0.025:10:#FF0000,#FFFF00,#00FF00"));
function validateSingleDecorLayer(decorLayer) {
if(decorLayer.length < 2) {
return false;
};
if(!elements[decorLayer[0]]) {
return false;
};
if(isNaN(decorLayer[1])) {
return false;
};
if(typeof(decorLayer[2]) !== "undefined") {
if(isNaN(decorLayer[2])) {
return false;
};
};
if(typeof(decorLayer[3]) !== "undefined") {
if(!(validateHexColorArray(decorLayer[3]))) {
return false;
};
};
return true;
};
function validateDecorStructure(decorArraysArray) {
if(!(decorArraysArray instanceof Array)) {
return false;
};
if(decorArraysArray.length == 0) {
return false;
};
var decorIsValid = 1;
for(var i in decorArraysArray) {
decorIsValid *= validateSingleDecorLayer(decorArraysArray[i]);
};
return !!decorIsValid;
};
function funniPrompt(argument=null,alertOutput=true,alertError=true) {
argument === null ? inputText = prompt("Enter command") : inputText = argument;
// replace spaces with underscores
if(["",null].includes(inputText)) {
console.log("Prompt canceled");
return false;
};
//console.log(inputText);
if(inputText.includes("|")) {
var commands = inputText.split("|");
var results = []; results.length = commands.length;
for(var cmdi in commands) {
commands[cmdi] = commands[cmdi].trim();
try {
results[cmdi] = funniPrompt(commands[cmdi]);
} catch(error) {
results[cmdi] = error;
};
};
console.log(results);
return results;
};
inputAsArray = inputText.split(" ");
var firstItem = inputAsArray[0];
@ -662,6 +854,153 @@ height: ${height}
alertIfOutput(alertOutput,"Elements counts logged to console");
console.log(formattedList);
return listObject;
case "wg":
case "worldgen":
if(inputAsArray.length < 1) {
alertIfError(alertError,commandHelpObject.worldgen);
return false;
};
var action = inputAsArray[1];
if(!action) {
alertIfOutput(`Current worldgen setting: ${settings.worldgen}`);
return settings.worldgen;
};
var worldgenTypesList = Object.keys(worldgentypes).concat(["off"]);
if(["list","lst","ls","l"].includes(action)) {
alertIfOutput(alertOutput,worldgenTypesList.join(", "));
console.log(worldgenTypesList.map(x => " " + x).join("\n"));
return worldgenTypesList;
} else {
var targetPreset = inputAsArray[2];
if(!targetPreset) {
alertIfError(alertError,commandHelpObject.worldgen);
return false;
};
if(!(worldgenTypesList.includes(targetPreset))) {
alertIfError(alertError,`No such preset ${targetPreset}!`);
return false;
};
if(["select","sel","pick","set","s"].includes(action)) {
settings.worldgen = targetPreset;
alertIfOutput(alertOutput,`Worldgen setting set to ${targetPreset}`);
return true;
} else if(["generate","gen","make","worldgen","wg","g","w","world","run","do","world"].includes(action)) {
bareClear();
if(targetPreset == "off") {
alertIfOutput(alertOutput,`Cleared world`);
} else {
console.log(targetPreset,worldgentypes[targetPreset].complexity);
worldGen(worldgentypes[targetPreset]);
alertIfOutput(alertOutput,`Generated preset ${targetPreset}`);
};
return true;
} else {
alertIfError(alertError,commandHelpObject.worldgen);
return false;
};
};
return true;
case "dwg":
case "defineworldgen":
if(inputAsArray.length < 3) {
alertIfError(commandHelpObject.defineworldgen);
alertIfError(commandHelpObject.defineworldgen2);
return false;
};
var presetName = inputAsArray[1];
//overwrite confirm below
var newPreset = {};
var layers = stringToLayers(inputAsArray[2]);
if(!validateLayersStructure(layers)) {
alertIfError(alertError,"Layers definition is invalid or malformed!");
return false;
};
newPreset.layers = layers;
var baseHeight = inputAsArray[3];
if(typeof(baseHeight) !== "undefined") {
if(promptInputNullishes.includes(baseHeight)) {
baseHeight = "0.5";
};
baseHeight = parseFloat(baseHeight);
if(isNaN(baseHeight)) {
alertIfError(alertError,"Invalid baseHeight!");
return false;
};
newPreset.baseHeight = baseHeight;
};
var heightVariance = inputAsArray[4];
if(typeof(heightVariance) !== "undefined") {
if(promptInputNullishes.includes(heightVariance)) {
heightVariance = "0.5";
};
heightVariance = parseFloat(heightVariance);
if(isNaN(heightVariance)) {
alertIfError(alertError,"Invalid heightVariance!");
return false;
};
newPreset.heightVariance = heightVariance;
};
var complexity = inputAsArray[5];
if(typeof(complexity) !== "undefined") {
if(promptInputNullishes.includes(complexity)) {
complexity = "20";
};
complexity = parseFloat(complexity);
if(isNaN(complexity)) {
alertIfError(alertError,"Invalid complexity!");
return false;
};
newPreset.complexity = complexity;
};
var temperature = inputAsArray[6];
if(typeof(temperature) !== "undefined") {
if(promptInputNullishes.includes(temperature.toLowerCase())) {
temperature = null;
} else {
temperature = parseFloat(temperature);
if(isNaN(temperature)) {
alertIfError(alertError,"Invalid temperature!");
return false;
};
newPreset.temperature = temperature;
};
};
var decor = inputAsArray[7];
if(typeof(decor) !== "undefined") {
decor = stringToDecor(decor);
if(!validateDecorStructure(decor)) {
alertIfError(alertError,"Decor definition is invalid or malformed!");
return false;
};
newPreset.decor = decor;
};
if(worldgentypes[presetName]) {
var doOverwrite = confirm(`Overwrite worldgen preset ${presetName}?`);
if(!doOverwrite) {
alertIfError(alertError,"defineworldgen canceled");
return false;
};
};
worldgentypes[presetName] = newPreset;
settings.worldgen = presetName;
rebuildWorldgenList();
alertIfOutput(alertOutput,
`Defined worldgen preset ${presetName}.
Make sure to save your command in a file if you want to add this preset again.`
);
console.log(inputText);
return [presetName,newPreset];
case "stars":
var starDensity = inputAsArray[1];
@ -818,20 +1157,34 @@ height: ${height}
console.log(lastStarSeed);
return lastStarSeed;
case "help":
var commandsWithoutDwg2 = Object.keys(commandHelpObject).filter(function(cmdName) { return cmdName !== "defineworldgen2" });
if(inputAsArray.length < 1) { //somehow
alertIfError(alertError,"Usage: help <command>\nDon't include framing characters []<>.\nArguments in <angle brackets> are optional.");
return false;
};
if(inputAsArray.length < 2) {
alertOutput ? alertIfOutput(alertOutput,"Commands: " + Object.keys(commandHelpObject).join("\n")) : console.log("Commands: " + Object.keys(commandHelpObject).join(", "));
alertOutput ? alertIfOutput(alertOutput,"Commands: " + commandsWithoutDwg2.join("\n")) : console.log("Commands: " + commandsWithoutDwg2.join(", "));
} else {
var command = inputAsArray[1];
if(typeof(commandHelpObject[command]) === "undefined") {
if(typeof(commandHelpObject[command]) === "undefined" || command == "defineworldgen2") {
alertIfError(alertError,"Cound not find help for " + command + ".");
return false;
} else {
alertOutput ? alertIfOutput(alertOutput,commandHelpObject[command]) : console.log(commandHelpObject[command].replace(/\n/g, " "));
if(command == "defineworldgen") {
if(alertOutput) {
alert(commandHelpObject.defineworldgen);
alert(commandHelpObject.defineworldgen2);
} else {
console.log(commandHelpObject.defineworldgen + "\n" + commandHelpObject.defineworldgen2);
};
} else {
if(alertOutput) {
alert(commandHelpObject[command]);
} else {
console.log(commandHelpObject[command]);
};
};
return true;
};
};

View File

@ -5,7 +5,7 @@ var libraryMod = "mods/code_library.js";
if(enabledMods.includes(runAfterAutogenMod) && enabledMods.includes(libraryMod)) {
runAfterAutogen(function() {
snowAndIceCache = Object.keys(elements).filter(function(name) {
return name.endsWith("snow") || name.endsWith("ice")
return name.endsWith("snow") || name.endsWith("ice") || name == "rime"
})
});
lightlikes = ["light","flash","laser","radiation","insulate_flash"];
@ -220,7 +220,7 @@ if(enabledMods.includes(runAfterAutogenMod) && enabledMods.includes(libraryMod))
}
deletePixel(pixel.x, pixel.y);
},
temp: -200,
temp: 20,
category: "energy",
state: "gas",
excludeRandom: true,
@ -257,7 +257,7 @@ if(enabledMods.includes(runAfterAutogenMod) && enabledMods.includes(libraryMod))
continue;
};
if (otherInfo.id === elements.heat_ray.id) { break }
if (otherInfo.id === elements[pixel.element].id) { break }
if(Math.random() > ((otherInfo.hardness ?? 0) ** 2)) { breakPixel(otherPixel,false,false) };
if(hasVelocity && otherPixel) {
var vels = [randomIntegerBetweenTwoValues(-9,9),randomIntegerBetweenTwoValues(-7,0)];
@ -273,7 +273,67 @@ if(enabledMods.includes(runAfterAutogenMod) && enabledMods.includes(libraryMod))
}
deletePixel(pixel.x, pixel.y);
},
temp: -200,
temp: 4000,
category: "energy",
state: "gas",
excludeRandom: true,
noMix: true
};
elements.annihilation_ray = {
color: ["#220c0c", "#c11515"],
tick: function(pixel) {
var x = pixel.x;
for (var y = pixel.y; y < height; y++) {
if (outOfBounds(x, y)) {
break;
}
if (isEmpty(x, y)) {
if (Math.random() > 0.05) { continue }
createPixel("insulate_flash", x, y);
pixelMap[x][y].color = "#292929";
}
else {
var otherPixel = pixelMap[x][y];
var otherInfo = elements[otherPixel?.element];
if(otherPixel) {
otherPixel.temp += 2500 * (shiftDown + 1);
if(otherPixel.del || !otherPixel) { continue };
if (otherPixel && grbBreakIntos.includes(otherPixel.element)) {
if(Math.random() < 0.01 && otherPixel) {
deletePixel(otherPixel.x,otherPixel.y);
};
continue;
} else if(otherPixel) {
breakPixel(otherPixel,false,false);
if(otherPixel.del || !otherPixel) {
continue
};
if(otherPixel && hasVelocity) {
var vels = [randomIntegerBetweenTwoValues(-8,8),randomIntegerBetweenTwoValues(-6,0)];
otherPixel.vx = vels[0];
otherPixel.vy = vels[1];
};
if(otherPixel && Math.random() < (otherInfo.isGas ? 0.2 : 0.1)) {
deletePixel(otherPixel.x,otherPixel.y);
continue;
};
if(Math.random() > 0.8) {
continue;
};
};
if (otherInfo.id === elements[pixel.element].id) { break }
};
}
}
deletePixel(pixel.x, pixel.y);
},
temp: 150000000,
category: "energy",
state: "gas",
excludeRandom: true,

View File

@ -1,6 +1,24 @@
var modName = "mods/save_loading.js";
try {
if(typeof(rebuildCurrentPixels) !== "function") {
rebuildCurrentPixels = function() {
var currPix = []; //rebuild currentPixels from pixelMap to try to fix bug
for(pmi = 0; pmi < pixelMap.length; pmi++) {
var pixelMapPart = pixelMap[pmi];
for(pmj = 0; pmj < pixelMapPart.length; pmj++) {
var pixelMapUnit = pixelMapPart[pmj];
if(typeof(pixelMapUnit) === "object") {
if(pixelMapUnit !== null) {
currPix.push(pixelMapUnit);
};
};
};
};
currentPixels = currPix;
};
};
//https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API
function storageAvailable(type) {
let storage;
@ -496,5 +514,5 @@ Pixel size (rendering only): <input id="pixelSize"> (Use if the save looks cut o
});
} catch (error) {
alert(`save_loading error: ${error.message}`);
alert(`save_loading error: ${error.toString()}`);
};