sandboxels/mods/bf.js

394 lines
14 KiB
JavaScript
Raw Normal View History

2025-09-28 04:48:46 -04:00
async function _modprompt(message, defaultValue = "") { // thanks to ggod for this prompt function. Taken from nousersthings.js
return new Promise(resolve => {
promptInput(message, (result) => {
2025-09-28 11:22:43 -04:00
resolve(result);
}, "bf.js is asking you...", defaultValue);
2025-09-28 04:48:46 -04:00
})
}
class Interpreter {
constructor() {
this.map = new Array(64).fill(0)
this.index = 0
this.ci = 0
this.loops = []
this.code = ""
this.tsay = ""
}
async run(px, code = this.code) {
this.ci = 0
while (this.ci < code.length) {
const token = code[this.ci]
2025-09-28 04:48:46 -04:00
switch (token) {
case ">":
if (this.index + 1 == this.map.length) {
this.map.push(0)
}
this.index++
break
case "<":
if (this.index - 1 != -1) {
this.index--
}
break
case "+":
this.map[this.index]++
break
case "-":
this.map[this.index]--
break
case ".":
this.tsay += String.fromCharCode(this.map[this.index])
break
case "!":
promptText(this.tsay, () => { }, "bf.js")
break
case "/":
this.tsay = ""
break
case ",":
const ans = await _modprompt("")
if (ans.trim().length > 0) {
this.map[this.index] = ans[0].charCodeAt(0)
}
break
case "[":
if (this.map[this.index] === 0) {
let open = 1
while (open > 0) {
this.ci++
if (code[this.ci] === "[") open++
else if (code[this.ci] === "]") open--
2025-09-28 04:48:46 -04:00
}
} else {
this.loops.push(this.ci)
}
break
case "]":
if (this.map[this.index] !== 0) {
this.ci = this.loops[this.loops.length - 1]
} else {
this.loops.pop()
}
break
}
this.ci++
}
px.running = false
}
}
class RemoteBase {
constructor(base) {
this.base = base
this.code = ""
}
run() {
pixelMap[this.base[0]][this.base[1]].interpreter.run(pixelMap[this.base[0]][this.base[1]], this.code)
this.code = ""
}
getMap() {
return pixelMap[this.base[0]][this.base[1]].interpreter.map
}
}
2025-09-28 04:48:46 -04:00
const bftokens = {
bf_base: "#00ff00",
bf_remote_base: "#008600",
">": "#ff7f00",
"<": "#ff00ff",
"+": "#00ffff",
"-": "#800080",
"[": "#ff1493",
"]": "#1e90ff",
".": "#ffd700",
",": "#ff4500",
"!": "#ff69b4",
2025-09-28 11:22:43 -04:00
"split": "#565656",
"act": "#ffc400",
"bf_gate": "#ffc400",
2025-09-28 04:48:46 -04:00
}
const bftokenslist = Object.keys(bftokens)
elements.bf_base = {
category: "bf",
color: "#00ff00",
state: "solid",
behavior: behaviors.WALL,
conduct: 1,
tick: (px) => {
if (pixelTicks == px.start) {
px.act = false
px.interpreter = new Interpreter()
px.base = [px.x, px.y]
px.running = false
}
2025-09-28 11:22:43 -04:00
if (!(px.interpreter instanceof Interpreter)) {
px.interpreter = new Interpreter()
}
2025-09-28 04:48:46 -04:00
},
2025-09-28 11:22:43 -04:00
2025-09-28 04:48:46 -04:00
}
let remotebase1 = undefined
let bfreader = undefined
let bfreader2 = undefined
elements.bf_remote_base = {
category: "bf",
color: "#008600",
state: "solid",
behavior: behaviors.WALL,
onSelect: async function () {
2025-09-28 11:22:43 -04:00
var bfans1 = await _modprompt("Please input in the coordinates of the desired pixel. When it activates, this activates. (X,Y)", "0,0");
2025-09-28 04:48:46 -04:00
if (!bfans1) { return }
let [x, y] = bfans1.split(",")
remotebase1 = [Number(x), Number(y)]
},
tick: (px) => {
if (pixelTicks == px.start) {
px.act = false
px.interpreter = new RemoteBase(pixelMap[remotebase1[0]][remotebase1[1]].base)
px.base = [px.x, px.y]
2025-09-28 04:48:46 -04:00
if (!pixelMap[remotebase1[0]][remotebase1[1]].remotes) {
pixelMap[remotebase1[0]][remotebase1[1]].remotes = []
}
pixelMap[remotebase1[0]][remotebase1[1]].remotes.push([px.x, px.y])
px.parent = remotebase1
2025-09-28 04:48:46 -04:00
px.cd = false
}
},
onDelete: (px) => {
if (!isEmpty(px.parent[0], px.parent[1]) && pixelMap[px.parent[0]][px.parent[1]].remotes) {
pixelMap[px.parent[0]][px.parent[1]].remotes.filter(a => !(a[0] === px.x && a[1] === px.y))
}
}
2025-09-28 04:48:46 -04:00
}
elements.reader = {
category: "bf",
color: "#008600",
state: "solid",
behavior: behaviors.WALL,
conduct: 1,
onSelect: async function () {
2025-09-28 11:22:43 -04:00
var bfans2 = await _modprompt("Please input in the desired value to activate when read.", "0");
2025-09-28 04:48:46 -04:00
if (!bfans2) { return }
bfreader = Number(bfans2)
},
tick: (px) => {
if (pixelTicks == px.start) {
px.tread = bfreader
}
},
}
elements.pointer_reader = {
category: "bf",
color: "#008600",
state: "solid",
behavior: behaviors.WALL,
conduct: 1,
onSelect: async function () {
2025-09-28 11:22:43 -04:00
var bfans3 = await _modprompt("Please input in the desired pointer and value to activate when read. (pointer,value)", "0,0");
2025-09-28 04:48:46 -04:00
if (!bfans3) { return }
let [x, y] = bfans3.split(",")
bfreader2 = [Number(x), Number(y)]
},
tick: (px) => {
if (pixelTicks == px.start) {
px.tread = bfreader2
}
},
}
elements.bf_runner = {
category: "bf",
color: "#ababab",
tool: (px) => {
2025-09-28 11:22:43 -04:00
if (px.element == "bf_base" && !px.running) {
2025-09-28 04:48:46 -04:00
px.running = true
px.act = true
px.interpreter.map.fill(0)
px.interpreter.code = ""
px.interpreter.index = 0
px.interpreter.ci = 0
}
}
}
dependOn("logicgates.js", () => {
elements.bf_gate = {
category: "bf",
color: "#ffc400",
state: "solid",
behavior: behaviors.WALL,
tick: (px) => {
if (!px.base) {
px.act = false
const ns = getNeighbors(px)
if (ns.length > 0) {
if (!isEmpty(px.x - 1, px.y)) {
const left = ns[0]
if (bftokenslist.includes(left.element) && left.base) {
px.base = left.base
}
}
}
} else {
if (px.act) {
px.color = "#00ff00"
} else {
px.color = "#ffc400"
}
var countNeighborsResult = countNeighbors(pixel)
if (countNeighborsResult.charged > 0) {
px.can = true
} else {
px.can = false
}
if (!isEmpty(px.x - 1, px.y)) {
const left = pixelMap[px.x - 1][px.y]
if (bftokenslist.includes(left.element) && left.base) {
if (left.act && !px.act && px.can) {
left.act = false
px.act = true
pixelMap[px.base[0]][px.base[1]].interpreter.code += "g"
if (isEmpty(px.x + 1, px.y) || !pixelMap[px.x][px.y].base || (pixelMap[px.x][px.y].element == "bf_gate" && !pixelMap[px.x][px.y].can)) {
px.act = false
}
if (px.remotes) {
px.remotes.forEach(remote => {
pixelMap[remote[0]][remote[1]].act = true
})
} else {
pixelMap[px.base[0]][px.base[1]].interpreter.run(pixelMap[px.base[0]][px.base[1]])
}
}
}
}
const ns = getNeighbors(px)
ns.forEach(n => {
if (pixelMap[px.base[0]][px.base[1]].interpreter instanceof Interpreter) {
if (n.element == "reader" && pixelMap[px.base[0]][px.base[1]].interpreter.map[pixelMap[px.base[0]][px.base[1]].interpreter.index] == n.tread) {
n.charge = 1
} else if (n.element == "pointer_reader" && pixelMap[px.base[0]][px.base[1]].interpreter.map[n.tread[0]] == n.tread[1]) {
n.charge = 1
}
} else {
if (n.element == "reader" && pixelMap[px.base[0]][px.base[1]].interpreter.getMap()[pixelMap[px.base[0]][px.base[1]].interpreter.index] == n.tread) {
n.charge = 1
} else if (n.element == "pointer_reader" && pixelMap[px.base[0]][px.base[1]].interpreter.getMap()[n.tread[0]] == n.tread[1]) {
n.charge = 1
}
}
})
}
if (isEmpty(px.x + 1, px.y) || !pixelMap[px.x + 1][px.y].base || (pixelMap[px.x + 1][px.y].element == "bf_gate" && !pixelMap[px.x + 1][px.y].can)) {
px.act = false
}
}
}
}, true)
2025-09-28 11:22:43 -04:00
for (let token of bftokenslist) {
if (token == "bf_base" || token == "bf_remote_base" || token == "bf_gate") { continue }
2025-09-28 04:48:46 -04:00
elements[token] = {
category: "bf",
color: bftokens[token],
state: "solid",
behavior: behaviors.WALL,
tick: (px) => {
if (!px.base) {
px.act = false
const ns = getNeighbors(px)
if (ns.length > 0) {
if (!isEmpty(px.x - 1, px.y)) {
const left = ns[0]
if (bftokenslist.includes(left.element) && left.base) {
px.base = left.base
}
}
}
} else {
if (px.act) {
px.color = "#00ff00"
} else {
px.color = bftokens[token]
}
const ns = getNeighbors(px)
if (ns.length > 0 && !isEmpty(px.x - 1, px.y)) {
const left = pixelMap[px.x - 1][px.y]
2025-09-28 04:48:46 -04:00
if (bftokenslist.includes(left.element) && left.base) {
if (left.act && !px.act) {
left.act = false
px.act = true
pixelMap[px.base[0]][px.base[1]].interpreter.code += token
if (px.remotes) {
px.remotes.forEach(remote => {
pixelMap[remote[0]][remote[1]].act = true
console.log(pixelMap[remote[0]][remote[1]].act)
})
} else {
pixelMap[px.base[0]][px.base[1]].interpreter.run(pixelMap[px.base[0]][px.base[1]])
2025-09-28 04:48:46 -04:00
}
}
}
}
if (ns.length >= 2) {
ns.forEach(n => {
if (pixelMap[px.base[0]][px.base[1]].interpreter instanceof Interpreter) {
2025-09-28 04:48:46 -04:00
if (n.element == "reader" && pixelMap[px.base[0]][px.base[1]].interpreter.map[pixelMap[px.base[0]][px.base[1]].interpreter.index] == n.tread) {
n.charge = 1
} else if (n.element == "pointer_reader" && pixelMap[px.base[0]][px.base[1]].interpreter.map[n.tread[0]] == n.tread[1]) {
n.charge = 1
}
} else {
if (n.element == "reader" && pixelMap[px.base[0]][px.base[1]].interpreter.getMap()[pixelMap[px.base[0]][px.base[1]].interpreter.index] == n.tread) {
n.charge = 1
} else if (n.element == "pointer_reader" && pixelMap[px.base[0]][px.base[1]].interpreter.getMap()[n.tread[0]] == n.tread[1]) {
n.charge = 1
}
}
})
2025-09-28 04:48:46 -04:00
}
}
if (isEmpty(px.x + 1, px.y) || !pixelMap[px.x + 1][px.y].base || (pixelMap[px.x + 1][px.y].element == "bf_gate" && !pixelMap[px.x + 1][px.y].can)) {
px.act = false
}
2025-09-28 04:48:46 -04:00
}
}
2025-09-28 11:22:43 -04:00
}
elements.act.conduct = 0.1
const oldact = elements.act.tick
elements.act.tick = (px) => {
oldact(px)
2025-09-28 04:48:46 -04:00
2025-09-28 11:22:43 -04:00
if (px.charge && !px.act) {
px.act = true
px.charge = 0
} else {
px.charge = 0
}
}