Back to GRAV / RIFT
SOURCE / PINNED RELEASE

Made of little things.

GRAV / RIFT

Release
288aa261ce07…
Author-recorded commit
c549b5a4e17e…
License
LICENSE
Author’s source reference
nostr://npub182jczunncwe0jn6frpqwq3e0qjws7yqqnc3auccqv9nte2dnd63scjm4rf/wss%3A%2F%2Fgit.napplet.soy%2F/n-8a7361981e8

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

tests/walkers.mjs
// Real controls in soyLI: intercept a physical shell and return it to its sender.
import assert from 'node:assert/strict';
import {fireKeyboard,fireTouch} from './input.mjs';
import {createRequire} from 'node:module';
import {realpathSync,mkdirSync} from 'node:fs';
const require=createRequire(realpathSync(new URL('../node_modules/@napplet/conformance-cli/package.json',import.meta.url)));
const {chromium}=require('playwright');
const url=process.argv.slice(2).find(arg=>/^https?:\/\//.test(arg));if(!url)throw new Error('Pass the soyli dev URL.');
const browser=await chromium.launch(),errors=[];
mkdirSync('.napplet-space/promotion',{recursive:true});
const stage='#stage{position:fixed!important;inset:0!important;z-index:100!important}#stage iframe{width:100vw!important;height:100dvh!important;min-height:0!important}body{overflow:hidden!important}';
let page;
try {
 page=await browser.newPage({viewport:{width:1200,height:750}});page.on('pageerror',e=>errors.push(e.message));
 await page.goto(url);await page.locator('iframe').waitFor();const frame=page.frames().find(f=>f!==page.mainFrame());await frame.locator('#deploy').waitFor();
 await page.addStyleTag({content:stage});await page.clock.install({time:new Date('2026-09-27T12:00:00Z')});await page.clock.pauseAt(new Date('2026-09-27T12:01:00Z'));await page.clock.runFor(100);
 const state=()=>frame.locator('#game').evaluate(n=>({...n.dataset}));
 const aim=async(x,y)=>{const {d,r}=await frame.locator('#game').evaluate(n=>({d:{...n.dataset},r:n.getBoundingClientRect().toJSON()}));await page.mouse.move(r.left+(x-Number(d.camera))*Number(d.viewScale),r.top+(y-Number(d.cameraY))*Number(d.viewScale));};
 await frame.locator('#practice').click();await page.keyboard.press('Digit2');
 await page.keyboard.down('KeyW');await page.keyboard.down('KeyD');await page.clock.runFor(800);await page.keyboard.up('KeyW');
 for(let i=0;i<20&&Number((await state()).shipX)<920;i++)await page.clock.runFor(100);
 await page.keyboard.up('KeyD');
 let d=await state();await aim(Number(d.walkerX),Number(d.shipY));await page.keyboard.down('Space');
 for(let i=0;i<80&&Number((await state()).shellsCaught)===0;i++) {
  d=await state();if(d.shellX)await aim(Number(d.shellX),Number(d.shellY));
  await page.clock.runFor(50);
 }
 d=await state();console.log('CAUGHT',d);assert.ok(Number(d.shellsCaught)>0,'incoming shell captured through pointer aim and field input');
 await aim(Number(d.walkerX),Number(d.walkerY));await page.clock.runFor(450);
 assert.ok(Number((await state()).shellsHeld)>0);assert.equal(await frame.locator('#chargeLabel').textContent(),'SHELL SECURED');
 await page.screenshot({path:'.napplet-space/promotion/walker-caught.png'});
 const before=Number((await state()).explosions);await fireKeyboard(page);await page.keyboard.up('Space');
 for(let i=0;i<100&&Number((await state()).explosions)===before;i++)await page.clock.runFor(25);
 await page.screenshot({path:'.napplet-space/promotion/walker-return.png'});
 await page.clock.runFor(350);d=await state();console.log('RETURNED',d);
 assert.ok(Number(d.shellsReturned)>0);assert.ok(Number(d.returnKills)>0,'the caught shell kills its original walker through real collision');
 await page.screenshot({path:'.napplet-space/promotion/walker-wreck.png'});
 for(const [w,h] of [[390,844],[844,390]]) {
  const context=await browser.newContext({viewport:{width:w,height:h},isMobile:true,hasTouch:true});const phone=await context.newPage();phone.on('pageerror',e=>errors.push(e.message));
  await phone.goto(url);await phone.locator('iframe').waitFor();const f=phone.frames().find(f=>f!==phone.mainFrame());await f.locator('#deploy').waitFor();await phone.addStyleTag({content:stage});
  await phone.clock.install({time:new Date('2026-09-27T12:00:00Z')});await phone.clock.pauseAt(new Date('2026-09-27T12:01:00Z'));await phone.clock.runFor(100);await f.locator('#practice').tap();await f.locator('[data-mode="1"]').tap();
  const cdp=await context.newCDPSession(phone),stick=await f.locator('#joystick').boundingBox(),field=await f.locator('#fieldButton').boundingBox();
  const touch=(id,x,y)=>({id,x,y,radiusX:4,radiusY:4,force:1});
  const held=[touch(1,stick.x+stick.width/2+30,stick.y+stick.height/2-25),touch(2,field.x+field.width/2,field.y+field.height/2)];
  await cdp.send('Input.dispatchTouchEvent',{type:'touchStart',touchPoints:[held[0]]});await phone.clock.runFor(1400);
  await cdp.send('Input.dispatchTouchEvent',{type:'touchStart',touchPoints:[touch(1,stick.x+stick.width/2+30,stick.y+stick.height/2),held[1]]});
  for(let i=0;i<25&&Number(await f.locator('#game').getAttribute('data-ship-x'))<1000;i++)await phone.clock.runFor(100);
  await cdp.send('Input.dispatchTouchEvent',{type:'touchMove',touchPoints:[touch(1,stick.x+stick.width/2,stick.y+stick.height/2),held[1]]});
  for(let i=0;i<65&&Number(await f.locator('#game').getAttribute('data-shells-caught'))===0;i++)await phone.clock.runFor(100);
  assert.ok(Number(await f.locator('#game').getAttribute('data-shells-caught'))>0,`${w}: touch auto aim captures a shell`);
  await cdp.send('Input.dispatchTouchEvent',{type:'touchMove',touchPoints:[touch(1,stick.x+stick.width/2,stick.y+stick.height/2),held[1]]});
  await phone.screenshot({path:`.napplet-space/promotion/walker-touch-${w}x${h}.png`});
  await fireTouch(phone,f,cdp,[touch(1,stick.x+stick.width/2,stick.y+stick.height/2),held[1]]);await cdp.send('Input.dispatchTouchEvent',{type:'touchEnd',touchPoints:[]});await phone.clock.runFor(1000);
  assert.ok(Number(await f.locator('#game').getAttribute('data-shells-returned'))>0,`${w}: release returns the secured shell`);
  await context.close();
 }
 assert.deepEqual(errors,[]);console.log('WALKERS: pointer catch, armed return, own-shooter kill, salvage, portrait/landscape touch catch and release passed.');
} catch(error) {if(page)await page.screenshot({path:'.napplet-space/promotion/walker-failure.png'});throw error;}
finally{await browser.close();}