Back to Impossible Machine
SOURCE / PINNED RELEASE

Made of little things.

Impossible Machine

Release
841127ac75f3…
Author-recorded commit
123625b81870…
License
LICENSE
Author’s source reference
nostr://npub1n8ga89w8h6tvwamxusfyzexw8gjy84yxu9rxgnmk955cxtml4ujswzxydd/wss%3A%2F%2Fgit.napplet.soy%2F/n-47d97da9d80

Archive hash verified: db7c8101167c4b07…. The source-to-build association is the author’s claim; it has not been independently rebuilt.

tests/physics.test.mjs
import assert from 'node:assert/strict';
import {readFile} from 'node:fs/promises';
import test from 'node:test';
import ts from 'typescript';
const source=await readFile(new URL('../src/physics.ts',import.meta.url),'utf8');
const code=ts.transpileModule(source,{compilerOptions:{module:ts.ModuleKind.ESNext}}).outputText;
const {step,caught}=await import('data:text/javascript;base64,'+Buffer.from(code).toString('base64'));
const solutions=[
 {start:{x:125,y:90},cup:{x:435,y:505},pieces:[{x:175,y:120,angle:.15}]},
 {start:{x:100,y:80},cup:{x:495,y:510},pieces:[{x:157.473223587894,y:242.613056585146,angle:.47438392586023004},{x:274.62445977967747,y:307.36651218563304,angle:.5032906042623198}]},
 {start:{x:470,y:75},cup:{x:115,y:510},pieces:[{x:410,y:120,angle:-.2}]}
];
for(const [i,s]of solutions.entries())test(`puzzle ${i+1} is physically solvable`,()=>{const b={...s.start,vx:0,vy:0};let won=false;for(let n=0;n<2880;n++){step(b,s.pieces.map((p,id)=>({...p,id,kind:'ramp'})),1/240);if(caught(b,s.cup)){won=true;break;}}assert.equal(won,true);});
test('bumper rebounds a falling marble upward',()=>{const b={x:300,y:200,vx:0,vy:220};let bounced=false;for(let i=0;i<240;i++){step(b,[{id:1,kind:'bumper',x:300,y:280,angle:0}],1/240);if(b.vy<0){bounced=true;break;}}assert.equal(bounced,true);});
test('a miss never counts as reaching the cup',()=>{const b={x:80,y:80,vx:0,vy:0};for(let i=0;i<240;i++){step(b,[],1/240);assert.equal(caught(b,{x:435,y:505}),false);}});