diff --git a/mods/a_mod_by_alice.js b/mods/a_mod_by_alice.js index 4e6a8914..1c67752c 100644 --- a/mods/a_mod_by_alice.js +++ b/mods/a_mod_by_alice.js @@ -2467,7 +2467,11 @@ color1 and color2 spread through striped paint like dye does with itself. col height = Math.round(newHeight/newPixelSize)-1; width = Math.round(newWidth/newPixelSize)-1; mousePos = {x:Math.round(width/2),y:Math.round(height/2)}; - if (clear!==false) { clearAll(); } + if (clear!==false) { //Edit: Resetting the scene clears the "Reset Scene" text that shows up when you change the canvas size + clearAll(); + var resetAdvisory = document.querySelector('[setting="pixelsize"] span:nth-child(2)'); + if(resetAdvisory && resetAdvisory.innerText.length > 0) { resetAdvisory.innerText = "" } + } } autoResizeCanvas = function(clear) { pixelSize = settings.pixelsize || 6; @@ -5164,7 +5168,7 @@ color1 and color2 spread through striped paint like dye does with itself. col else if (view === 2) { // thermal view // set the color to pixel.temp, from hottest at -66 (294.1875) hue to coldest 265 hue, with the minimum being -273, max being 7755 var temp = pixel.temp; - temp = Math.min(Math.max(temp + 900,(settings.abszero ?? -273.15)),5553000000000); + temp = Math.min(Math.max(temp + 900,(settings.abszero ?? -273.15)),55530000000000); var hue,sat,lig; sat = 100; lig = 50; @@ -5622,6 +5626,27 @@ color1 and color2 spread through striped paint like dye does with itself. col acidSettingSpan.appendChild(settingInput); acidSettingSpan.appendChild(newHelpMark); yellowShockSettingSpan.after(acidSettingSpan); + var rankineSettingSpan = document.createElement("span"); + rankineSettingSpan.setAttribute("setting","userankine"); + rankineSettingSpan.setAttribute("title","Default: OFF"); + rankineSettingSpan.classList.add("setting-span","multisetting"); + var settingInput = document.createElement("input"); + settingInput.setAttribute("type","button"); + settingInput.setAttribute("value",'Use degrees Rankine'); + settingInput.setAttribute("state","0"); + settingInput.classList.add("toggleInput"); + settingInput.setAttribute("onclick","toggleInput(this,'userankine',false)"); + var options = { + "false": "Disabled", + "true": "Enabled" + }; + var newHelpMark = document.createElement("span"); + newHelpMark.setAttribute("title","Use degrees Rankine (Fahrenheit based around absolute zero) for temperature display. Only affects imperial units."); + newHelpMark.classList.add("helpMark"); + newHelpMark.innerText = "?"; + rankineSettingSpan.appendChild(settingInput); + rankineSettingSpan.appendChild(newHelpMark); + acidSettingSpan.after(rankineSettingSpan); var sizeSetting = document.querySelector('span[setting="pixelsize"]'); var sizeDropdown = sizeSetting.querySelector("select"); sizeDropdown.setAttribute("onchange","var size = (this.value === 'null' ? null : parseFloat(this.value)); console.log(size); if((size >= 0.05) && (size <= 194.73749999999999) && (size !== null) && (size !== false) && !(isNaN(size))) { console.log(size); setSetting('pixelsize',size);this.nextElementSibling.innerText='Reset Scene' }"); @@ -5709,6 +5734,13 @@ color1 and color2 spread through striped paint like dye does with itself. col } function tryMove(pixel,nx,ny,leaveBehind,force) { if(!pixel) { return false }; + if ((typeof(pixel.tempDrag) !== "undefined") && (!force)) { + if(typeof(pixel.tempDrag) === "number" && pixel.tempDrag >= pixelTicks) { + return true + } else { + delete pixel.tempDrag + } + }; if (pixel.drag && !force) { return true; } var info = elements[pixel.element]; var oob = outOfBounds(nx,ny); @@ -5767,7 +5799,7 @@ color1 and color2 spread through striped paint like dye does with itself. col elements.move_up = { color: "#1C0000", tool: function(pixel) { - tryMove(pixel,pixel.x,pixel.y-1); + for(var i = 0; i < (shiftDown ? 3 : 1); i++) { tryMove(pixel,pixel.x,pixel.y-1,null,true) }; }, category: "movement tools", excludeRandom: true, @@ -5775,7 +5807,7 @@ color1 and color2 spread through striped paint like dye does with itself. col elements.move_down = { color: "#000038", tool: function(pixel) { - tryMove(pixel,pixel.x,pixel.y+1); + for(var i = 0; i < (shiftDown ? 3 : 1); i++) { tryMove(pixel,pixel.x,pixel.y+1,null,true) }; }, category: "movement tools", excludeRandom: true, @@ -5783,7 +5815,7 @@ color1 and color2 spread through striped paint like dye does with itself. col elements.move_left = { color: "#007000", tool: function(pixel) { - tryMove(pixel,pixel.x-1,pixel.y); + for(var i = 0; i < (shiftDown ? 3 : 1); i++) { tryMove(pixel,pixel.x-1,pixel.y,null,true) }; }, category: "movement tools", excludeRandom: true, @@ -5791,7 +5823,7 @@ color1 and color2 spread through striped paint like dye does with itself. col elements.move_right = { color: "#000E00", tool: function(pixel) { - tryMove(pixel,pixel.x+1,pixel.y); + for(var i = 0; i < (shiftDown ? 3 : 1); i++) { tryMove(pixel,pixel.x+1,pixel.y,null,true) }; }, category: "movement tools", excludeRandom: true, @@ -5799,7 +5831,7 @@ color1 and color2 spread through striped paint like dye does with itself. col elements.move_up_left = { color: "#E00000", tool: function(pixel) { - tryMove(pixel,pixel.x-1,pixel.y-1); + for(var i = 0; i < (shiftDown ? 3 : 1); i++) { tryMove(pixel,pixel.x-1,pixel.y-1,null,true) }; }, category: "movement tools", excludeRandom: true, @@ -5807,7 +5839,7 @@ color1 and color2 spread through striped paint like dye does with itself. col elements.move_down_left = { color: "#0001C0", tool: function(pixel) { - tryMove(pixel,pixel.x-1,pixel.y+1); + for(var i = 0; i < (shiftDown ? 3 : 1); i++) { tryMove(pixel,pixel.x-1,pixel.y+1,null,true) }; }, category: "movement tools", excludeRandom: true, @@ -5815,7 +5847,7 @@ color1 and color2 spread through striped paint like dye does with itself. col elements.move_up_right = { color: "#038000", tool: function(pixel) { - tryMove(pixel,pixel.x+1,pixel.y-1); + for(var i = 0; i < (shiftDown ? 3 : 1); i++) { tryMove(pixel,pixel.x+1,pixel.y-1,null,true) }; }, category: "movement tools", excludeRandom: true, @@ -5823,7 +5855,7 @@ color1 and color2 spread through striped paint like dye does with itself. col elements.move_down_right = { color: "#000007", tool: function(pixel) { - tryMove(pixel,pixel.x+1,pixel.y+1); + for(var i = 0; i < (shiftDown ? 3 : 1); i++) { tryMove(pixel,pixel.x+1,pixel.y+1,null,true) }; }, category: "movement tools", excludeRandom: true, @@ -8572,29 +8604,27 @@ color1 and color2 spread through striped paint like dye does with itself. col color: "#000000", maxColorOffset: 0, excludeRandom: true, + insulate: true, tick: function(pixel) { - pixel.lastTemps ??= []; - pixel.lastTemps.push(pixel.temp); - if(pixel.lastTemps.length > 5) { pixel.lastTemps.shift() }; - var biggestLastTemp = Math.max(...pixel.lastTemps); - if(pixel.temp < biggestLastTemp) { pixel.temp = biggestLastTemp }; pixel.color = "rgb(0,0,0)"; var range = (pixel.range ?? 30) * 2; var targets = mouseRange(pixel.x,pixel.y,range,"circle",true); + shuffleArray(targets); for (var i = 0; i < targets.length; i++) { var newPixel = pixelMap[targets[i][0]]?.[targets[i][1]]; if ((!newPixel) || newPixel.del) { continue }; - if((newPixel.element == pixel.element) || ((newPixel.x == pixel.x) && (newPixel.y == pixel.y))) { continue }; - newPixel.drag = true; + if(((newPixel.element == pixel.element) || (elements[pixel.element].ignore && elements[pixel.element].ignore.includes(newPixel.element))) || ((newPixel.x == pixel.x) && (newPixel.y == pixel.y))) { continue }; + newPixel.tempDrag = pixelTicks + 1; var [mX, mY] = [pixel.x, pixel.y]; var distanceComplement = (range / 2) - pyth(mX,mY,newPixel.x,newPixel.y); - var distanceProportion = 0.3 + (distanceComplement / (range / 2)); + var distanceProportion = 0.2 + (distanceComplement / (range / 2)); var distanceModifier = distanceProportion ** 2; - var pullCount = (4 * distanceModifier) * (commonMovableCriteria(pixel.element) ? 1 : 0.8); + var pullCount = (4 * distanceModifier) * (commonMovableCriteria(newPixel.element) ? 1 : 0.8); var pullCountIntegerPart = Math.floor(pullCount); var pullCountFractionalPart = pullCount % 1; var truePullCount = Math.min(3,pullCountIntegerPart + (Math.random() < pullCountFractionalPart)); for(var j = 0; j < truePullCount; j++) { + if((pullCountIntegerPart >= 1) && (Math.random() < pullCount / 3)) { tryBreak(newPixel) }; var x = newPixel.x; var y = newPixel.y; var empty = checkForEmptyPixels(x, y); @@ -8626,9 +8656,78 @@ color1 and color2 spread through striped paint like dye does with itself. col state: undefined, density: 1797.69313486e305, //about as close to Infinity as we can serializably get category: "special", - hardness: 1 + hardness: 1, + ignore: ["amba_white_hole"] }; - + + elements.amba_white_hole = { + color: "#ffffff", + maxColorOffset: 0, + excludeRandom: true, + insulate: true, + tick: function(pixel) { + pixel.color = "rgb(255,255,255)"; + var range = (pixel.range ?? 30) * 2; + var targets = mouseRange(pixel.x,pixel.y,range,"circle",true); + shuffleArray(targets); + for (var i = 0; i < targets.length; i++) { + var newPixel = pixelMap[targets[i][0]]?.[targets[i][1]]; + if ((!newPixel) || newPixel.del) { continue }; + if(((newPixel.element == pixel.element) || (elements[pixel.element].ignore && elements[pixel.element].ignore.includes(newPixel.element))) || ((newPixel.x == pixel.x) && (newPixel.y == pixel.y))) { continue }; + newPixel.tempDrag = pixelTicks + 1; + var [mX, mY] = [pixel.x, pixel.y]; + var distanceComplement = (range / 2) - pyth(mX,mY,newPixel.x,newPixel.y); + var distanceProportion = 0.2 + (distanceComplement / (range / 2)); + var distanceModifier = distanceProportion ** 2; + var pullCount = (4 * distanceModifier) * (commonMovableCriteria(newPixel.element) ? 1 : 0.8); + var pullCountIntegerPart = Math.floor(pullCount); + var pullCountFractionalPart = pullCount % 1; + var truePullCount = Math.min(3,pullCountIntegerPart + (Math.random() < pullCountFractionalPart)); + for(var j = 0; j < truePullCount; j++) { + if((pullCountIntegerPart >= 1) && (Math.random() < pullCount / 3)) { tryBreak(newPixel) }; + var x = newPixel.x; + var y = newPixel.y; + var empty = checkForEmptyPixels(x, y); + let bestVal = Math.sqrt(Math.pow(mX - x, 2) + Math.pow(mY - y, 2)); + let best = null; + for (const pixelPair of empty) { + const x_ = x + pixelPair[0]; + const y_ = y + pixelPair[1]; + const c = Math.sqrt(Math.pow(mX - x_, 2) + Math.pow(mY - y_, 2)); + if (c < bestVal) { + bestVal = c; + best = pixelPair; + } + } + if (best) { + var destCoords = [x - best[0], y - best[1]]; + newPixel.vx = -(truePullCount * (best[0])); + newPixel.vy = -(truePullCount * (best[1])); + var moveResult = tryMoveAndReturnBlockingPixel(newPixel, destCoords[0], destCoords[1], undefined, true); + if((moveResult !== true) && !(outOfBounds(...destCoords))) { + swapPixels(newPixel,moveResult); + tryMove(newPixel, destCoords[0] - best[0], destCoords[1] - best[1], undefined, true) + }; + heatNeighbors(newPixel,20); + var a0 = settings.abszero ?? -273.15; + if(pixel.temp >= a0) { + if(pixel.temp <= (a0 + 20)) { + pixel.temp = a0 + } else { + pixel.temp -= 20 + } + } + } + } + } + }, + state: undefined, + density: -(1797.69313486e305), //about as close to -Infinity as we can serializably get + category: "special", + hardness: 1, + ignore: ["amba_black_hole"] + }; + //ASSORTED RAINBOW VARIANTS ## elements.concoction.reactions.diorite_gravel = { elem1: "static", elem2: null @@ -12655,6 +12754,41 @@ Pixel size (rendering only): (Use if the save looks cut o color: "#FFFFFF", desc: saveLoaderDescription, }; + + function formatTempWithAbbreviation(temp) { // temp is Celcius + var _temp; + var suffix; + var unitSetting = settings?.["units"] ?? "m"; + switch(unitSetting) { + default: + case "m": + _temp = temp; + suffix = "°C"; + break; + case "i": + if(settings.userankine == true) { + _temp = (temp*1.8)+491.67; + suffix = "°R"; + } else { + _temp = temp*1.8+32; + suffix = "°F" + }; + break; + case "s": + _temp = temp+273.15; + suffix = "°K"; + break; + }; + var displayTemp = Math.round(_temp); + if(displayTemp > 999999999) { + var shrinkage = (10 ** (Math.floor(Math.log10(_temp)) - 4)); + displayTemp = [Math.floor(_temp/shrinkage),"e",Math.log10(shrinkage),suffix].join(""); + } else { + displayTemp = Math.round(_temp).toString() + suffix; + }; + return displayTemp + }; + //Somehow, for some illogical reason, quicksaving causes updateStats to somehow disregard its if-statement and fucking TypeError when you mouse over an empty space; this is an attempt to fix it with overkill-level existence checks. function updateStats() { var statsDiv = document.getElementById("stats"); @@ -12673,7 +12807,7 @@ Pixel size (rendering only): (Use if the save looks cut o displayName += ` (${currentPixel?.displayText})` }; stats += "Elem:"+displayName+""; - stats += "Temp:"+formatTemp(currentPixel.temp)+""; + stats += "Temp:"+formatTempWithAbbreviation(currentPixel.temp)+""; if (currentPixel.charge) { stats += "C"+currentPixel.charge+""; } diff --git a/mods/betaworldgen.js b/mods/betaworldgen.js index 9c25dd1f..33561e42 100644 --- a/mods/betaworldgen.js +++ b/mods/betaworldgen.js @@ -1,128 +1,187 @@ -//This mod was made by Alex the transfem, https://discord.com/users/778753696804765696 on discord and https://www.tiktok.com/@alextheagenenby?_t=8hoCVI3NRhu&_r=1 on tiktok. -function randomAlter(num, list){ - let r = Math.floor(Math.random() * list.length); - return (num + list[r]); +//This mod was made by Adora the transfem, https://discord.com/users/778753696804765696 on discord and https://www.tiktok.com/@alextheagenenby?_t=8hoCVI3NRhu&_r=1 on tiktok. +let code = { a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10, k: 11, l: 12, m: 13, n: 14, o: 15, p: 16, q: 17, r: 18, s: 19, t: 20, u: 21, v: 22, w: 23, x: 24, y: 25, z: 26, A: 27, B: 28, C: 29, D: 30, E: 31, F: 32, G: 33, H: 34, I: 35, J: 36, K: 37, L: 38, M: 39, N: 40, O: 41, P: 42, Q: 43, R: 44, S: 45, T: 46, U: 47, V: 48, W: 49, X: 50, Y: 51, Z: 52 } +let invertedCode = {} +let flat = function(){ + let str = ""; + for(var i = 0; i < width; i++){ + str += "a"; + } + return str; +} +let biomes = { + plains: { + layers: 2, + thicknesses: [15, 10], + specificSeeds: "flat", + heights: [1, 21], + layersObj: { + 1: ["rock","rock","rock","rock","rock","rock","rock","rock","rock","rock","rock","rock","rock","rock","rock","iron","iron","iron","aluminum","aluminum","aluminum","aluminum","uranium","diamond","copper","copper","copper","copper","sodium","sodium","potassium","potassium","charcoal","charcoal","charcoal","charcoal","charcoal", "calcium"], + 2: ["dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt","dirt", "dirt", "dirt","dirt", "dirt", "gravel", "gravel"] + }, + ssHeight: 39, + ssElems: ["grass_seed","grass_seed","grass_seed","grass_seed","grass_seed","grass_seed","grass_seed","grass_seed","grass_seed","grass_seed","grass_seed","grass_seed","grass_seed","grass_seed","grass_seed","sapling","pinecone","seeds","seeds"] + }, + desert: { + layers: 1, + thicknesses: [20], + specificSeeds: "flat", + heights: [1], + layersObj: { + 1: ["sand"] + }, + ssHeight: 40, + ssElems: [undefined,undefined,undefined,undefined,undefined,undefined,"cactus"] + }, + forest: { + layers: 2, + specificSeeds: "flat", + heights: [1, 16], + thicknesses: [15, 10], + ssHeight: 29, + layersObj: { + 1: ["rock","rock","rock","rock","rock","rock","rock","rock","rock","rock","charcoal","charcoal","charcoal","charcoal","charcoal","iron","iron","iron","aluminum","aluminum","aluminum","calcium","calcium","sodium","potassium","diamond"], + 2: ["dirt","dirt","dirt","dirt","dirt","dirt","dirt","dirt","dirt","dirt","dirt","dirt","dirt","dirt","gravel"] + }, + ssElems: ["grass_seed","grass_seed","grass_seed","grass_seed","grass_seed","grass_seed","grass_seed","grass_seed","grass_seed","grass_seed","grass_seed","grass_seed","grass_seed","sapling", "pinecone"], + } +} +for (var item in code){ + invertedCode[code[item]] = item; +} +let ranNum = function(max, last) { + // Calculate a bias factor + let bias = Math.random() * 0.07 + 0.5; // Adjust this range to control the bias strength + + // Generate a biased random number towards the 'last' value + let num = Math.round(bias * last + (1 - bias) * Math.random() * max) + 1; + + // Randomly assign a negative or positive sign + return (Math.random() > 0.5) ? num : -num; +} +function decode(str){ + let result = []; + str.split(""); + for(var i = 0; i < str.length; i++){ + if(code[str[i]]){ + if(str[i - 1] == "*"){ + result[i] = code[str[i]] * 2; + } else { + result[i] = code[str[i]]; + } + } else if(str[i] == ":"){ + result[i] = ":"; + } else {continue;} + } + return result.filter(element => element !== undefined); +} +function makeSeed(layers, thickness){ + let result = ""; + for(var i = 0; i < layers; i++){ + let avgThickness = thickness[i]; + let str = ""; + let lastNum = 0; + for(var ii = 1; ii <= width-1; ii++){ + let num = ranNum(4, lastNum); + let cThickness = avgThickness + num; + lastNum = num; + if(invertedCode[cThickness] != undefined){ + str += invertedCode[cThickness]; + } else { + let num = Math.round(cThickness / 2); + str += `*${invertedCode[num]}`; + } + } + result += (i == (layers - 1)) ? str : `${str}:`; + } + return result; +} +function splitArrayByCharacter(arr, char) { + let result = []; + let subArray = []; + + arr.forEach(element => { + if (element === char) { + result.push(subArray); + subArray = []; + } else { + subArray.push(element); + } + }); + + // Push the last subarray if it's not empty + if (subArray.length > 0) { + result.push(subArray); + } + + return result; } -let avgheight = 0; let seed = ""; -function getSeed(type = "plains", thickness = 15){ - seed = ""; - console.log(thickness) - if(thickness == 15){ - avgheight = Math.floor(Math.random() * (18 - 12 + 1)) + 12; +function generate(type, seed1 = undefined){ + if(seed1){ + seed = seed1; } else{ - avgheight = thickness; + seed = makeSeed(biomes[type].layers, biomes[type].thicknesses); } - console.log(avgheight) - - if(type == "plains"){ - let location = Math.floor(Math.random(0, pixelMap.length) * 100); - let i = 0; - while (i < pixelMap.length){ - if (i !== location){ - seed += `${randomAlter(avgheight, [0, 1, 1, 2, 0, 0])}|`; - i += 1; - } else if (i == location){ - let height = `${Math.floor(Math.random(40, pixelMap[i].length) * 10)}`; - let prevH = randomAlter(avgheight, [1, 1, 1, 2, 0, 0]); - while (height > prevH){ - prevH = randomAlter(prevH, [0, 1, 1, 2, 0, 0, 0, 1]); - seed += `${prevH}|`; - } - - i += 1; - + let semifinalArr = decode(seed); + let finalArr = splitArrayByCharacter(semifinalArr, ":"); + for(var i = 0; i < finalArr.length; i++){ + let lHeight = biomes[type].heights[i]; + for(var ii = 1; ii < width-1; ii++){ + for(var iii = (height - 1) - lHeight; iii > height - lHeight - finalArr[i][ii]; iii--){ + let x = ii; + let y = iii; + let Num = Math.round(Math.random() * biomes[type].layersObj[i+1].length); + if(Num == biomes[type].layersObj[i+1].length){Num-=1;} + let element = biomes[type].layersObj[i+1][Num]; + if(isEmpty(x, y) && !outOfBounds(x, y)){ + createPixel(element, x, y); + } else {console.log("could not place. " + x + ", " + y); continue;} + } + } + } + if(biomes[type].specificSeeds){ + if(biomes[type].specificSeeds == "flat"){ + for(var i = 1; i < width-1; i++){ + let y = height - biomes[type].ssHeight; + let Num = Math.round(Math.random() * biomes[type].ssElems.length); + if(Num == biomes[type].ssElems.length){Num-=1;} + let element = biomes[type].ssElems[Num]; + if(element == undefined){continue;} + if(isEmpty(i, y) && !outOfBounds(i, y)){ + createPixel(element, i, y); } } - return seed; } - if(type == "desert"){ - let i = 0; - while (i < pixelMap.length){ - seed += `${randomAlter(avgheight, [0, 1, 1, 2, 0, 0])}|`; - i += 1; + } +} +elements.copy_seed = { + category: "tools", + onSelect: function(pixel){ + navigator.clipboard.writeText(seed).then(function() { + alert(`Seed succesfully copied to clipboard!`); + }).catch(function(error) { + alert("Unable to copy text.") + }); - } - } - return seed; - } -function spawnElements(seed, list, height2 = 1, condition = [1, 1, 0]){ - console.log(list); - let width = pixelMap.length - 1; - let element; - let height = pixelMap[1].length - 1; - console.log(seed); - let seedArray = seed.split("|"); - console.log(seedArray); - seedArray.splice(seedArray.indexOf(""), 1); - seedArray.splice(pixelMap.length); - console.log(seedArray); - let i = 0; - while (i < seedArray.length - 1){ - - let ii = 0; - while (ii < seedArray[i]){ - if((Math.floor(Math.random() * (condition[0] - condition[1] + 1))) == condition[2]){ - if (height2 != 1){ - element = list[Math.floor(Math.random() * list.length)]; - createPixel(element, (width - 1) - i, (height - (height2 + 1)) - ii); - } else{ - element = list[Math.floor(Math.random() * list.length)]; - createPixel(element, (width - 1) - i, (height - 1) - ii); - } - } - ii += 1; - } - - i += 1; } } - -function flat(){ - let iii = 0; - let flat = ""; - while (iii < pixelMap.length){ - flat += "1|"; - iii += 1; - } - return flat; -} -function processSeed(seed, type = "plains"){ - - console.log(flat()); - let seedsArray = seed.split(":"); - console.log(seedsArray); - if(type == "plains"){ - spawnElements(seedsArray[0],["rock","rock","rock","rock","rock","rock","metal_scrap","metal_scrap","metal_scrap","gold_coin","uranium","uranium","diamond","rock","iron","iron","iron","aluminum","aluminum","aluminum","aluminum","copper","copper","copper","zinc","zinc","rock","rock","rock","rock","rock","rock","rock","rock","rock","rock","rock","rock","rock","rock","rock"].sort(() => Math.random() - 0.5)); - setTimeout(function(){ spawnElements(seedsArray[1], ["dirt"], 24); }, 200); - setTimeout(function(){ spawnElements(flat(),["grass","grass","grass","sapling","flower_seed","grass","grass","pinecone","grass","grass","grass","grass","grass","grass","grass","grass","grass","grass"], 40); }, 300); - } else if(type == "desert"){ - spawnElements(seed, ["sand"]); - setTimeout(function(){ spawnElements(flat(), ["cactus"], 40, [6, 0, 3]); }, 100); +elements.random_generation = { + category: "tools", + onSelect: function(pixel){ + autoResizeCanvas(); + focusGame(); + let type = prompt("Enter the biome you want to generate: \nOptions: plains, desert, forest"); + if(!biomes[type]) {type = "plains";} + generate(type); } } -elements.worldGen = { - color: "#FFFFFF", - behavior: elements.erase.behavior, - temp: 2, - category: "tools", - insulate:true, - canPlace: false, - desc: "Generate worlds with random seeds or your own seeds.", - onSelect: function() { - let Seed = prompt("Enter desert or plains random generation! automatically set to plains."); - let regex = /[a-z]/; - if (regex.test(Seed)){ - if(Seed.toLowerCase() == "desert"){ - processSeed(getSeed("desert", 30), "desert"); - } - } else { - if (Seed == ""){ - seed = `${getSeed("plains", 20)}:${getSeed("plains", 8)}` - processSeed(seed); - } else{ - processSeed(Seed); - } - } +elements.seed_generation = { + category: "tools", + onSelect: function(pixel){ + autoResizeCanvas(); + focusGame(); + let type = prompt("Enter the biome you want to generate: \nOptions: plains, desert, forest"); + let seed1 = prompt("Enter the seed: "); + generate(type, seed1); } } diff --git a/mods/extrasaveslots.js b/mods/extrasaveslots.js index 5321bd03..118c2359 100644 --- a/mods/extrasaveslots.js +++ b/mods/extrasaveslots.js @@ -39,120 +39,4 @@ if (!confirm("Are you sure you want to erase this save slot?")) { return } localStorage.removeItem("SandboxelsSaves/"+i); showSaves(); - } - function confirmSave() { - if (!savingState) { return } - var saveName = document.getElementById("saveName").value || "Unnamed"; - var saveTemp = document.getElementById("saveTemp").getAttribute("state") === "1"; - var saveColors = document.getElementById("saveColors").getAttribute("state") === "1"; - var saveMods = document.getElementById("saveMods").getAttribute("state") === "1"; - var saveSettings = document.getElementById("saveSettings").getAttribute("state") === "1"; - var saveRaw = document.getElementById("saveRaw").getAttribute("state") === "1"; - var saveAuthor = document.getElementById("saveAuthor").value || ""; - if (saveAuthor && !currentSaveData) { - setSetting("authorName",saveAuthor) - } - var saveDesc = document.getElementById("saveDesc").value || ""; - var config = {name:saveName,temp:saveTemp,mods:saveMods,settings:saveSettings,raw:saveRaw,keep:[],author:saveAuthor,desc:saveDesc}; - if (saveTemp) { config.keep.push("temp") } - if (saveColors) { config.keep.push("color") } - if (savingState.slot) { - // save stringified generateSave() to localStorage SandboxelsSaves/i - localStorage.setItem("SandboxelsSaves/"+savingState.slot, JSON.stringify(generateSave(undefined,config))); - closeMenu(); - showSaves(); - } - else { - // save to .sbxls - var save = generateSave(undefined,config); - var blob = new Blob([JSON.stringify(save)], {type: "application/json"}); - var url = URL.createObjectURL(blob); - var a = document.createElement("a"); - a.href = url; - a.download = saveName+".sbxls"; - document.body.appendChild(a); - a.click(); - setTimeout(function() { - document.body.removeChild(a); - window.URL.revokeObjectURL(url); - }, 0); - closeMenu(); - } - } - function saveToFile() { - savingState = {slot:null}; - document.getElementById("saveName").value = ""; - document.getElementById("saveAuthor").value = ""; - document.getElementById("saveDesc").value = ""; - showSavePrompt(); - } - function loadFromFile() { - var input = document.createElement("input"); - input.type = "file"; - // input.accept = ".sbxls,.json,.txt,text/*,application/json"; - input.addEventListener("change", function(e) { - var file = e.target.files[0]; - var reader = new FileReader(); - reader.readAsText(file,"UTF-8"); - reader.onload = readerEvent => { - var content = readerEvent.target.result; - loadSave(JSON.parse(content)); - } - closeMenu(); - }); - input.click(); - } - function showSavePrompt() { - closeMenu(); - var savePromptParent = document.getElementById("savePromptParent"); - var saveWarning = document.getElementById("saveWarning"); - if (currentSaveData) { - document.getElementById("saveName").value = currentSaveData.name || ""; - document.getElementById("saveAuthor").value = currentSaveData.author || ""; - document.getElementById("saveDesc").value = currentSaveData.desc || ""; - } - else if (settings.authorName) { - document.getElementById("saveAuthor").value = settings.authorName; - } - saveWarning.innerHTML = "
" - var menuTitle = document.querySelector("#savePromptMenu .menuTitle"); - if (savingState.slot === null) { - menuTitle.innerHTML = "Save to File"; - } - else { - menuTitle.innerHTML = "Save to Slot"; - if (localStorage["SandboxelsSaves/"+savingState.slot]) { - saveWarning.innerHTML += "
This will overwrite the save in slot "+savingState.slot+"!"; - } - } - var saveMods = document.getElementById("saveMods"); - if (enabledMods.length !== 0) { - saveMods.style.display = "inline-block"; - saveWarning.innerHTML += "
Mods might not be necessary to include, and may annoy the user!"; - } - else { saveMods.style.display = "none"; } - savePromptParent.style.display = "block"; - showingMenu = "savePrompt"; - document.getElementById("saveName").focus(); - } - function showSettings() { - var settingsParent = document.getElementById("settingsParent"); - settingsParent.style.display = "block"; - showingMenu = "settings"; - } - function setSetting(setting,value) { - settings[setting] = value; - saveSettings(); - } - function toggleInput(input,setting,updateText) { - if (input.getAttribute("state") === "0") { - input.setAttribute("state","1"); - if (updateText !== false) { input.value = "ON"; } - if (setting) { setSetting(setting,1); } - } - else { - input.setAttribute("state","0"); - if (updateText !== false) { input.value = "OFF"; } - if (setting) { setSetting(setting,0); } - } } \ No newline at end of file diff --git a/mods/morechemistry.js b/mods/morechemistry.js index 3d793eea..6dacbe57 100644 --- a/mods/morechemistry.js +++ b/mods/morechemistry.js @@ -1,5 +1,5 @@ //This mod was made by Adora the transfem, https://discord.com/users/778753696804765696 on discord and https://www.tiktok.com/@alextheagenenby?_t=8hoCVI3NRhu&_r=1 on tiktok. -let version = "1.5.2"; +let version = "1.6.2"; function pixelInRange(pixel, range){ let i = 0; while (i < range.length) { @@ -20,6 +20,8 @@ function customExplosion(pixel1, pixel2, radius, list) { let y = pixel1.y; deletePixel(x, y); deletePixel(pixel2.x, pixel2.y); + doFrame(); + focusGame(); explodeAt(x, y, radius, list); }; function reactPixels(pixel1,pixel2) { @@ -169,7 +171,7 @@ elements.sodiumhydroxidecrystals = { //tempHigh: 64.7, fireColor: "#fba600", category: "powders", - state: "powder", + state: "solid", density: 2130, name: "SodiumHydroxideCrystals", } @@ -632,10 +634,13 @@ elements.potassiumhydroxidecrystals = { //tempHigh: 64.7, fireColor: "#fba600", category: "powders", - state: "powder", + state: "solid", density: 2040, name: "PotassiumHydroxideCrystals", } +let filterItems; +let direction; + elements.iron_chloride = { color: ["#010014", "#a2ff94"], reactions: { @@ -691,7 +696,7 @@ elements.kilonova = { temp: 100000000, } elements.supernova.behavior = [ ["XX", "XX", "XX"], [ "XX", "EX:80>plasma,plasma,plasma,plasma,plasma,plasma,plasma,plasma,plasma,plasma,plasma,plasma,plasma,plasma,plasma,plasma,plasma,plasma,plasma,plasma,molten_iron,molten_uranium,oxygen,molten_sodium,sulfur_gas,neon,chlorine,molten_calcium,molten_nickel,molten_copper,molten_zinc,gallium_gas,hydrogen,hydrogen,hydrogen,hydrogen,helium,helium,helium AND CH:NeutronStar", "XX" ], ["XX", "XX", "XX"] ] -elements.kilonova.behavior = [ ["XX", "XX", "XX"], [ "XX", "EX:200>plasma,plasma,plasma,plasma,plasma,plasma,molten_iron,molten_uranium,molten_lead,oxygen,molten_sodium,molten_gold,molten_tungsten,sulfur_gas,neon,chlorine,molten_calcium,molten_nickel,molten_copper,molten_zinc,gallium_gas,hydrogen,hydrogen,hydrogen,hydrogen,hydrogen,helium,helium,helium,helium AND CH:void", "XX" ], ["XX", "XX", "XX"] ] +elements.kilonova.behavior = [ ["XX", "XX", "XX"], [ "XX", "EX:200>plasma,plasma,molten_iron,molten_uranium,molten_lead,oxygen,molten_sodium,molten_gold,molten_tungsten,sulfur_gas,neon,chlorine,molten_calcium,molten_nickel,molten_copper,molten_zinc,gallium_gas,hydrogen,hydrogen,hydrogen,hydrogen,hydrogen,helium,helium,helium,helium AND CH:void", "XX" ], ["XX", "XX", "XX"] ] elements.NeutronStar = { behavior: [["XX", "XX", "XX"], ["CR:light", "XX", "CR:light"], ["XX", "XX", "XX"]], name: "NeutronStar", @@ -708,6 +713,7 @@ elements.NeutronStar = { "NeutronStar": { "elem1": "kilonova", "temp1": 100000000, }, }, density: 10**17, + hardness: 1, } elements.acid.ignore.push("pipe"); elements.acid.ignore.push("gold"); @@ -724,27 +730,16 @@ elements.NaK = { color: "#848484", viscosity: 9.4, reactions: { - "water": { - func: function (pixel1, pixel2) {customExplosion(pixel1, pixel2, 5, ["fire", "fire", "pop", "hydrogen", "sodiumhydroxide", "potassiumhydroxide","sodiumhydroxide", "potassiumhydroxide","sodiumhydroxide", "potassiumhydroxide"])} - }, + water: { + explosion: "fire,fire,pop,hydrogen,sodiumhydroxide,potassiumhydroxide,sodiumhydroxide,potassiumhydroxide,sodiumhydroxide,potassiumhydroxide", radius: 5,}, acid: { - func: function (pixel1, pixel2) {customExplosion(pixel1, pixel2, 6, ["fire", "pop", "hydrogen", "water", "pop", "hydrogen", "hydrogen"])} - }, + explosion: "fire,fire,pop,hydrogen,salt,potassium_salt,hydrogen,fire", radius: 6,}, acidic_water: { - func: function (pixel1, pel2) {customExplosion(pixel1, pixel2, 3, ["pop", "hydrogen", "hydrogen", "water","sodiumhyixdroxide", "potassiumhydroxide"])} - }, - chloroauric_acid: { elem1: "gold", - func: function (pixel1, pixel2) {customExplosion(pixel1, pixel2, 7, ["fire", "fire", "pop", "hydrogen", "gold_coin", "hydrogen", "pop"])} - }, - liquid_chloroauric_acid: { elem1: "gold", - func: function (pixel1, pixel2) {customExplosion(pixel1, pixel2, 7, ["fire", "fire", "pop", "hydrogen", "gold_coin", "hydrogen", "hydrogen", "pop"])} - }, - nitric_acid:{ - func: function (pixel1, pixel2) {customExplosion(pixel1, pixel2, 6, ["fire", "fire", "pop", "hydrogen", "hydrogen", "pop"])} - }, + explosion: "fire,fire,pop,hydrogen,sodiumhydroxide,potassiumhydroxide,salt,potassium_salt", radius: 5,}, + nitric_acid: { + explosion: "fire,fire,fire,pop,hydrogen,sodiumhydroxide,potassiumhydroxide", radius: 6,}, aqua_regia: { - func: function (pixel1, pixel2) {customExplosion(pixel1, pixel2, 9, ["fire", "fire", "pop", "hydrogen", "fire", "fire", "hydrogen", "pop", "flash"])} - }, + explosion: "fire,fire,pop,hydrogen,sodiumhydroxide,potassiumhydroxide,salt,potassium_salt,fire,hydrogen,pop", radius: 7,}, }, density: 868, }; @@ -770,6 +765,7 @@ elements.rubidium = { tick: function(pixel) { pixel.burning = true; }, + state: "solid", } elements.moltenrubidium = { density: 1532, @@ -798,7 +794,7 @@ elements.moltenrubidium = { } elements.rubidiumsalt = { - state: "powder", + state: "solid", name: "RubidiumSalt", alias: "Rubidium Chloride or RbCl", color: ["#e6e6e6", "#f5f5f5", "#fafafa", "#f0f0f0"], @@ -899,7 +895,7 @@ elements.rubidiumhydroxidecrystals = { }, fireColor: "#d91e1e", category: "powders", - state: "powder", + state: "solid", density: 2.12, name: "RubidiumHydroxideCrystals", } @@ -1022,11 +1018,12 @@ elements.specialsmasher = { } }, tick: function(pixel) { - if(pixel.start == pixelTicks) { + if(pixel.start + 1 == pixelTicks) { pixel.range = num2; + pixel.exclude = exclude; } let range = mouseRange(pixel.x, pixel.y, pixel.range); - smash(range, exclude); + smash(range, pixel.exclude); } } let num3 = 0; @@ -1038,7 +1035,7 @@ elements.specialmixer = { noMix: true, onSelect: function(pixel) { let item = prompt("enter range for mixing."); - exclude = prompt("Enter elements to exclude, seperate them with commas.").replace(/\s/g, "").split(","); + exclude1 = prompt("Enter elements to exclude, seperate them with commas.").replace(/\s/g, "").split(","); if(/^\d+$/.test(item)){ num3 = parseInt(item); } else { @@ -1046,11 +1043,12 @@ elements.specialmixer = { } }, tick: function(pixel) { - if(pixel.start == pixelTicks) { + if(pixel.start + 1 == pixelTicks) { pixel.range = num3; + pixel.exclude = exclude1; } let range = mouseRange(pixel.x, pixel.y, pixel.range); - mix(range, exclude); + mix(range, pixel.exclude); } } @@ -1355,7 +1353,10 @@ function pull(range, pixel1, include = []){ } } } - +function reduceToSign(num) { + if(num == 0){return 0;} + return num && num / Math.abs(num); +} let prevNum; elements.etemper = { name: "E-Temper", @@ -1377,11 +1378,15 @@ elements.etemper = { if(outOfBounds(x,y)){ continue; } if(isEmpty(x,y)){ continue; } let pixel2 = pixelMap[x][y]; - - if (pixel2.temp < pixel.Temp && pixel.charge > 0 ){ - pixel2.temp += pixel.Temp / 6; + if(reduceToSign(pixel.Temp) == -1){ + if (pixel2.temp > pixel.Temp && pixel.charge > 0 ){ + pixel2.temp += pixel.Temp / 6; + } + } else { + if (pixel2.temp < pixel.Temp && pixel.charge > 0 ){ + pixel2.temp += pixel.Temp / 6; + } } - } }, } @@ -1401,6 +1406,7 @@ elements.sign = { let attrElem = ""; let magnetRange = 0; let magnetElems = []; +let magnetPixels = []; elements.magnet = { category: "machines", tick:function(pixel){ @@ -1413,6 +1419,9 @@ elements.magnet = { for (var i = 0; i < currentPixels.length; i++){ if(pixelInRange(currentPixels[i], range)){ let pixel2 = currentPixels[i] + if(!magnetPixels.includes(pixel2)){ + magnetPixels.push(pixel2); + } if(!pixel2.drag && pixel.elem.includes(pixel2.element)){pixel2.drag = true} if(pixel2.drag && !pixel.elem.includes(pixel2.element) && !beamPixels.includes(pixel2) && ((draggingPixels && draggingPixels.includes(pixel2)) || !draggingPixels)){pixel2.drag = false;} if(!magnetElems.includes(pixel2) && pixel.elem.includes(pixel2.element)){magnetElems.push(pixel2)} @@ -1424,6 +1433,18 @@ elements.magnet = { currentPixels[i].drag = false; } } + for(var i = 0; i < magnetPixels.length; i++){ + if(magnetPixels.length != 0){ + if(!pixel.elem.includes(magnetPixels[i].element)){ + magnetPixels[i].drag = false; + magnetPixels.splice(i, 1); + } + if(!pixelInRange(magnetPixels[i], range)){ + magnetPixels[i].drag = false; + magnetPixels.splice(i, 1); + } + } + } }, onSelect: function(){ attrElem = prompt("Enter the element you want to attract.", (attrElem || undefined)); @@ -1537,6 +1558,44 @@ document.addEventListener("keydown", function(event){ } } } + if(event.key.toLowerCase() == "v"){ + for(var i = 0; i < UFOs.length; i++){ + let pixel = UFOs[i]; + let x = pixel.x + for (var y = pixel.y + 1; y < height; y++) { + if (outOfBounds(x, y)) { + break; + } + if (isEmpty(x, y)) { + if (Math.random() > 0.05) { continue } + createPixel("flash", x, y); + pixelMap[x][y].color = "#032dff"; + pixelMap[x][y].temp = -3500; + } + else { + if (elements[pixelMap[x][y].element].isGas) { continue } + if (elements[pixelMap[x][y].element].id === elements.heat_ray.id) { break } + pixelMap[x][y].temp -= 10; + pixelTempCheck(pixelMap[x][y]); + break; + } + } + } + } + if(event.key.toLowerCase() == "t"){ + for(var i = 0; i < UFOs.length; i++){ + for(var ii = 0; ii < adjacentCoords.length; ii++){ + let x = UFOs[i].x + adjacentCoords[ii][0]; + let y = UFOs[i].y + adjacentCoords[ii][1]; + if(x == pixel.x || y == pixel.y) {continue;} + if(!outOfBounds(x,y) && !isEmpty(x,y)){ + if(pixelMap[x][y].element == "ufo"){continue;} + deletePixel(x,y); + + } + } + } + } }) function isArray(item) { return Object.prototype.toString.call(item) === '[object Array]'; diff --git a/mods/text.js b/mods/text.js new file mode 100644 index 00000000..1918f1fb --- /dev/null +++ b/mods/text.js @@ -0,0 +1,681 @@ +// RedBirdly's mod that adds pixel text in sandboxels + + +function drawText(font, text, position, element, scale = 1) { + const { + x: startX, + y: startY + } = position; + var currentX = startX; + var currentY = startY; + + // Iterate through each character in the text + for (var char of text) { + if (char === '\n') { + // Handle new lines + currentY += (5 * scale) + scale; // Assuming each character height is 5 and we add 1 for line spacing + currentX = startX; + continue; + } + + if (char === ' ') { + // Handle spaces + currentX += 4 * scale; + continue; + } + + // Get the character's pixel representation from the font + const charArray = font[char]; + if (!charArray) { + charArray = font["invalid"] + } + + // Place the character in the pixelMap + for (var row = 0; row < charArray.length; row++) { + for (var col = 0; col < charArray[row].length; col++) { + const pixel = charArray[row][col]; + if (pixel === '#') { + for (var i = 0; i < scale; i++) { + for (var j = 0; j < scale; j++) { + var x = currentX + (col * scale) + j; + var y = currentY + (row * scale) + i; + if (x < width && y < height && !pixelMap[x][y]) { + createPixel(element, x, y); + } + } + } + } + } + } + + // Move to the next character + currentX += (charArray[0].length * scale) + scale; + } +} + +var textToPlace = "Text"; +var textElement = "copper"; + +elements.text = { + behavior: behaviors.WALL, + category: "tools", + state: "solid", + maxSize: 1, + cooldown: 2, + onSelect: function() { + textToPlace = prompt("Input Text\n(Previous element = Text's element)", textToPlace); + textElement = previousValidTextElement; + }, + tick: function(pixel) { + if (pixel.start == pixelTicks) { + deletePixel(pixel.x, pixel.y); + drawText(font, textToPlace, { + x: pixel.x, + y: pixel.y + }, textElement, 1); + } + } +}; + +// Keep track of previous valid text element, only if it can be used for text +var previousValidTextElement = "copper"; +var oldSelectElement = selectElement; +selectElement = function(element) { + // Don't include sand because the game auto-selects it at the start and would be annoying + if (currentElement != "text" && currentElement != "unknown" && currentElement != "sand") { + previousValidTextElement = currentElement; + } + oldSelectElement(element); +} + + +var font = { + "invalid": [ + "###", + "###", + "###", + "###", + "###", + ], + "A": [ + " # ", + "# #", + "###", + "# #", + "# #", + ], + "B": [ + "## ", + "# #", + "## ", + "# #", + "###", + ], + "C": [ + "##", + "# ", + "# ", + "# ", + "##", + ], + "D": [ + "## ", + "# #", + "# #", + "# #", + "## ", + ], + "E": [ + "###", + "# ", + "## ", + "# ", + "###", + ], + "F": [ + "###", + "# ", + "## ", + "# ", + "# ", + ], + "G": [ + "###", + "# ", + "# #", + "# #", + "###", + ], + "H": [ + "# #", + "# #", + "###", + "# #", + "# #", + ], + "I": [ + "###", + " # ", + " # ", + " # ", + "###", + ], + "J": [ + "###", + " #", + " #", + "# #", + "## ", + ], + "K": [ + "# #", + "# #", + "## ", + "# #", + "# #", + ], + "L": [ + "# ", + "# ", + "# ", + "# ", + "###", + ], + "M": [ + "# #", + "## ##", + "# # #", + "# #", + "# #", + ], + "N": [ + "# #", + "## #", + "# ##", + "# #", + "# #", + ], + "O": [ + "###", + "# #", + "# #", + "# #", + "###", + ], + "P": [ + "###", + "# #", + "###", + "# ", + "# ", + ], + "Q": [ + "###", + "# #", + "# #", + "## ", + " #", + ], + "R": [ + "###", + "# #", + "###", + "## ", + "# #", + ], + "S": [ + "###", + "# ", + "###", + " #", + "###", + ], + "T": [ + "###", + " # ", + " # ", + " # ", + " # ", + ], + "U": [ + "# #", + "# #", + "# #", + "# #", + "###", + ], + "V": [ + "# #", + "# #", + "# #", + " # ", + " # ", + ], + "W": [ + "# #", + "# #", + "# # #", + "## ##", + "# #", + ], + "X": [ + "# #", + "# #", + " # ", + "# #", + "# #", + ], + "Y": [ + "# #", + "# #", + " # ", + " # ", + " # ", + ], + "Z": [ + "###", + " #", + " # ", + "# ", + "###", + ], + "a": [ + " ", + " ", + " ##", + "# #", + " ##", + ], + "b": [ + "# ", + "# ", + "###", + "# #", + "###", + ], + "c": [ + " ", + " #", + "# ", + "# ", + " #", + ], + "d": [ + " #", + " #", + "###", + "# #", + "###", + ], + "e": [ + " # ", + "# #", + "###", + "# ", + " ##", + ], + "f": [ + " #", + " # ", + "###", + " # ", + " # ", + ], + "g": [ + " ##", + "# #", + "###", + " #", + "###", + ], + "h": [ + "# ", + "# ", + "###", + "# #", + "# #", + ], + "i": [ + " ", + "#", + " ", + "#", + "#", + ], + "j": [ + " #", + " #", + " #", + "# #", + "###", + ], + "k": [ + "# #", + "# #", + "## ", + "# #", + "# #", + ], + "l": [ + " ", + "#", + "#", + "#", + "#", + ], + "m": [ + " ", + "## ##", + "# # #", + "# #", + "# #", + ], + "n": [ + " ", + " ", + "## ", + "# #", + "# #", + ], + "o": [ + " ", + " ", + " ##", + "# #", + "## ", + ], + "p": [ + " ", + "## ", + "# #", + "###", + "# ", + ], + "q": [ + " ", + " ##", + "# #", + "###", + " #", + ], + "r": [ + " ", + "##", + "# ", + "# ", + "# ", + ], + "s": [ + " ##", + "# ", + "## ", + " #", + "## ", + ], + "t": [ + " ", + " # ", + "###", + " # ", + " # ", + ], + "u": [ + " ", + " ", + "# #", + "# #", + " ##", + ], + "v": [ + " ", + " ", + "# #", + "# #", + " # ", + ], + "w": [ + " ", + " ", + "# #", + "# # #", + " # # ", + ], + "x": [ + " ", + " ", + "# #", + " # ", + "# #", + ], + "y": [ + " ", + "# #", + " ##", + " #", + " # ", + ], + "z": [ + " ", + "###", + " #", + "# ", + "###", + ], + "0": [ + "###", + "# #", + "# #", + "# #", + "###", + ], + "1": [ + " # ", + "## ", + " # ", + " # ", + "###", + ], + "2": [ + "###", + " #", + "###", + "# ", + "###", + ], + "3": [ + "###", + " #", + " ##", + " #", + "###", + ], + "4": [ + "# #", + "# #", + "###", + " #", + " #", + ], + "5": [ + "###", + "# ", + "###", + " #", + "###", + ], + "6": [ + "###", + "# ", + "###", + "# #", + "###", + ], + "7": [ + "###", + " #", + " #", + " #", + "###", + ], + "8": [ + "###", + "# #", + "###", + "# #", + "###", + ], + "9": [ + "###", + "# #", + "###", + " #", + "###", + ], + "@": [ + " ### ", + "# ##", + "# # #", + "# ##", + " # ", + ], + "!": [ + "#", + "#", + "#", + " ", + "#", + ], + "#": [ + " # # ", + "#####", + " # # ", + "#####", + " # # ", + ], + "%": [ + " # ", + "# # ", + " # ", + " # #", + " # ", + ], + "[": [ + "##", + "# ", + "# ", + "# ", + "##", + ], + "]": [ + "##", + " #", + " #", + " #", + "##", + ], + "{": [ + " #", + " # ", + "## ", + " # ", + " #", + ], + "}": [ + "# ", + " # ", + " ##", + " # ", + "# ", + ], + "<": [ + " #", + " # ", + "# ", + " # ", + " #", + ], + ">": [ + "# ", + " # ", + " #", + " # ", + "# ", + ], + "(": [ + " #", + "# ", + "# ", + "# ", + " #", + ], + ")": [ + "# ", + " #", + " #", + " #", + "# ", + ], + "-": [ + " ", + " ", + "###", + " ", + " ", + ], + "_": [ + " ", + " ", + " ", + " ", + "###", + ], + "^": [ + " # ", + "# #", + " ", + " ", + " ", + ], + "*": [ + " # ", + "###", + " # ", + " ", + " ", + ], + "+": [ + " ", + " # ", + "###", + " # ", + " ", + ], + "/": [ + " #", + " # ", + " # ", + " # ", + "# ", + ], + "?": [ + " ##", + "# #", + " #", + " ", + " # ", + ], + ".": [ + " ", + " ", + " ", + " ", + "#", + ], + ",": [ + " ", + " ", + " ", + "#", + "#", + ], +};