import test from 'node:test';import assert from 'node:assert/strict';import fs from 'node:fs';import vm from 'node:vm';import {definitions} from '../tools/definitions.mjs';import {solve,graph} from '../tools/engine-template.mjs'; function boot(mode,width=340){const draws=[],elements=new Map();let context; class Element{constructor(id=''){this.id=id;this.children=[];this.handlers={};this.hidden=false;this.disabled=false;this.value='';this.textContent='';this.className='';}replaceChildren(){this.children=[];}append(e){this.children.push(e);}addEventListener(n,f){this.handlers[n]=f;}setPointerCapture(){}getBoundingClientRect(){return {left:0,top:0,width,height:420};}click(){this.onclick?.();}} const ctx={globalAlpha:1,lineWidth:1,font:'',fillStyle:'',strokeStyle:'',textAlign:'center',textBaseline:'middle',setTransform(){},clearRect(){draws.length=0;},beginPath(){this.p=[];},moveTo(x,y){this.p.push([x,y]);},lineTo(x,y){this.p.push([x,y]);},closePath(){},fill(){draws.push({kind:'fill',points:this.p,color:this.fillStyle});},stroke(){draws.push({kind:'stroke',points:this.p,color:this.strokeStyle});},fillText(s,x,y){draws.push({kind:'text',text:s,x,y,font:this.font});},save(){},restore(){},translate(){},rotate(){},setLineDash(){}}; function get(id){if(!elements.has(id))elements.set(id,new Element(id));return elements.get(id);} const canvas=get('board');canvas.clientWidth=width;canvas.clientHeight=420;canvas.getContext=()=>ctx; const document={getElementById:get,createElement:()=>new Element()},window={devicePixelRatio:1,addEventListener(){}}; context=vm.createContext({document,window,localStorage:{getItem:()=>null,setItem(){}},performance:{now:()=>100},setTimeout,URL,Blob,console}); const html=fs.readFileSync(new URL('../modes/'+mode+'/play.html',import.meta.url),'utf8');const script=html.match(/