forked from hackclub/sprig
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
78 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,28 @@ | ||
import { baseEngine } from "../engine/baseEngine.js" | ||
import { iterateReader } from "https://deno.land/[email protected]/streams/conversion.ts"; | ||
import * as pathUtils from "https://deno.land/std/path/mod.ts"; | ||
|
||
async function spadeRun(path) { | ||
const H = Deno.env.get("HOME"); | ||
const p = Deno.run({ | ||
cmd: ["./spade", path], | ||
cmd: [H + "/spade/pc_build/spade", H + "/sprig/games/" + path], | ||
stdout: "piped", | ||
stdin: "piped" | ||
}); | ||
|
||
/* feels like this is necessary, to get 'er warmed up */ | ||
await new Promise(res => setTimeout(res, 100)); | ||
|
||
const decoder = new TextDecoder(); | ||
const encoder = new TextEncoder(); | ||
async function *mapReader() { | ||
const decoder = new TextDecoder(); | ||
|
||
for await (const out of iterateReader(p.stdout)) | ||
yield decoder.decode(out).trim(); | ||
} | ||
|
||
const encoder = new TextEncoder(); | ||
return { | ||
out: iterateReader(p.stdout), | ||
out: mapReader(), | ||
simKey: key => p.stdin.write(encoder.encode(key + '\n')), | ||
cleanup: () => p.close(), | ||
}; | ||
|
@@ -27,14 +35,22 @@ let brokenGames = []; | |
let log = false; | ||
async function main() { | ||
brokenGames = []; | ||
const tasks = []; | ||
for await (const dirEntry of Deno.readDir('./games')) { | ||
const name = dirEntry.name; | ||
const isJS = name.slice(-3) === ".js"; | ||
if (!isJS) continue; | ||
await testScript(name); | ||
tasks.push((async () => { | ||
const i = setInterval(() => console.log(name + ' is still running'), 10000); | ||
await testScript(name); | ||
clearInterval(i); | ||
})()); | ||
} | ||
await Promise.all(tasks); | ||
|
||
console.log("broken games:", brokenGames); | ||
for (const { error, name } of brokenGames) | ||
console.log(` --- ${name} ---\n` + error); | ||
console.log("number of broken games:", brokenGames.length); | ||
|
||
return brokenGames; | ||
|
@@ -50,41 +66,55 @@ async function testScript(name) { | |
/* generate simulated inputs */ | ||
const choose = arr => arr[Math.floor(Math.random() * arr.length)]; | ||
const shakespeareMonKeys = [...Array(1000)].map(_ => choose("wasdjilk".split(''))); | ||
// const shakespeareMonKeys = [...Array(10)].map(_ => choose("wasdjilk".split(''))); | ||
|
||
const spade = await spadeRun(name); | ||
try { | ||
const fn = new Function(...Object.keys(api), script); | ||
const compareMaps = async () => { | ||
const spadeMap = (await spade.out.next()).value; | ||
const sprigMap = gridToString(api); | ||
|
||
if (spadeMap != sprigMap) { | ||
const text = `maps different!\nsprig map:\n${sprigMap}\nspade map:\n${spadeMap}`; | ||
throw new Error(text); | ||
} | ||
} | ||
|
||
console.log(`running ${name}!`); | ||
const fn = new Function(...Object.keys(api), script); | ||
fn(...Object.values(api)); /* init */ | ||
|
||
for (const key of shakespeareMonKeys) { | ||
await compareMaps(); | ||
simulateKey(key); | ||
await spade.simKey(key); | ||
if (log) console.log(`<<< pressing ${key} >>>`); | ||
if (log) console.log(gridToString(api)); | ||
} | ||
} catch(e) { | ||
cleanup(); | ||
console.log(`ERROR WHILE RUNNING "${name}"`); | ||
brokenGames.push({ | ||
name, | ||
error: e | ||
}) | ||
} | ||
|
||
cleanup(); | ||
finally { | ||
cleanup(); | ||
spade.cleanup(); | ||
} | ||
} | ||
|
||
function gridToString(api) { | ||
const w = api.width() | ||
const h = api.height() | ||
/* +1 is for newline */ | ||
const grid = [...Array((w + 1) * h)].fill('.'); | ||
for (let y = 0; y < h; y++) grid[y*(w + 1) + w] = '\n'; | ||
for (const [s] of api.getGrid()) | ||
if (s) | ||
grid[s.y*(w + 1) + s.x] = s.type; | ||
|
||
return grid.join('').trim(); | ||
const max_z = Math.max(...api.getGrid().map(x => x.length)); | ||
return new Array(h).fill(0).map((_, y) => ( | ||
new Array(max_z).fill(0).map((_, z) => ( | ||
new Array(w).fill(0).map((_, x) => { | ||
const tile = api.getTile(x, y).reverse()[z]; | ||
return (tile) ? tile.type : '.'; | ||
}).join('') | ||
)).join('|') | ||
)).join('\n'); | ||
} | ||
|
||
function simEngine() { | ||
|
@@ -95,19 +125,21 @@ function simEngine() { | |
|
||
timeouts.forEach(clearTimeout); | ||
timeouts = []; | ||
api.setTimeout = (fn, n) => { | ||
const t = setTimeout(fn, n); | ||
timeouts.push(t); | ||
return t; | ||
} | ||
api.setTimeout = () => {}; | ||
// api.setTimeout = (fn, n) => { | ||
// const t = setTimeout(fn, n); | ||
// timeouts.push(t); | ||
// return t; | ||
// } | ||
|
||
intervals.forEach(clearInterval); | ||
intervals = []; | ||
api.setInterval = (fn, n) => { | ||
const i = setInterval(fn, n); | ||
intervals.push(i); | ||
return i; | ||
}; | ||
api.setInterval = () => {}; | ||
// api.setInterval = (fn, n) => { | ||
// const i = setInterval(fn, n); | ||
// intervals.push(i); | ||
// return i; | ||
// }; | ||
|
||
let tileInputs = { | ||
w: [], | ||
|
@@ -130,6 +162,13 @@ function simEngine() { | |
afterInputs.push(fn); | ||
}; | ||
|
||
let jsr = 0x5EED; | ||
const random = () => { | ||
jsr^=(jsr<<17); | ||
jsr^=(jsr>>13); | ||
jsr^=(jsr<<5); | ||
return (jsr>>>0)/4294967295; | ||
}; | ||
api = { | ||
/* you literally shouldn't use this */ | ||
getState: () => { throw new Error(" BAD! NO! ") }, | ||
|
@@ -152,7 +191,13 @@ function simEngine() { | |
...api, | ||
|
||
/* gotta do watchu gotta do */ | ||
console: { log: () => {} } | ||
console: { log: () => {} }, | ||
Math: new Proxy({}, { | ||
get(target, prop, receiver) { | ||
if (prop == "random") return random; | ||
return Reflect.get(Math, prop, Math); | ||
} | ||
}), | ||
}; | ||
|
||
return { | ||
|