Files
deepseek 486201655b 100 Days After — complete playable survival strategy game
- Seeded procedural runs (survivors, locations, weather, events)
- 100-day campaign with 5 phases, scripted story beats, Day-100 finale
- 8 endings incl. hidden 'First Light Again'
- Data-driven events (people/world/story packs) with callback chains
- Relationships, memories, grief, karma/hope systems
- Tactical encounters (fight/hide/run/negotiate) with honest odds
- 8 upgradeable camp buildings, 13 location templates
- Canvas parallax scenes, procedural SVG portraits, weather FX
- Synthesized adaptive audio (WebAudio, no assets)
- Save slots + autosave (localStorage), shareable seeds
- Tests: headless multi-seed simulator + browser E2E (playwright)
2026-08-23 06:58:47 +00:00

59 lines
2.5 KiB
JavaScript

import { chromium } from 'playwright-core';
const browser = await chromium.launch({ executablePath: '/root/.cache/ms-playwright/chromium_headless_shell-1148/chrome-linux/headless_shell', args:['--no-sandbox','--disable-gpu','--disable-dev-shm-usage'] });
const page = await browser.newPage({ viewport:{width:1440,height:900} });
page.setDefaultTimeout(9000);
await page.goto('http://127.0.0.1:5199', { waitUntil:'domcontentloaded' });
await page.waitForSelector('.title-screen');
await page.waitForTimeout(1200);
await page.screenshot({ path: 'shots/title.png' });
await page.click('text=NEW RUN');
await page.fill('.seed-input','31337');
await page.click('text=BEGIN DAY 1');
await page.waitForSelector('.game-layout');
await page.waitForTimeout(1500);
await page.screenshot({ path: 'shots/game.png' });
// survivor detail
await page.locator('.surv-card:not(.dead)').first().click();
await page.waitForTimeout(400);
await page.screenshot({ path: 'shots/survivor.png' });
await page.click('.modal-x');
// build menu
await page.click('.action:has-text("BUILD")');
await page.waitForTimeout(400);
await page.screenshot({ path: 'shots/build.png' });
await page.keyboard.press('Escape').catch(()=>{});
await page.evaluate(() => document.querySelector('.modal-x')?.click());
await page.waitForTimeout(300);
// force an encounter via hunt a few times for the shot; else map hover
await page.click('[data-tab="map"]');
await page.waitForTimeout(200);
await page.locator('.map-entry').nth(2).hover();
await page.waitForTimeout(800);
await page.screenshot({ path: 'shots/map-preview.png' });
// end day -> night report shot
await page.click('#btn-endday');
await page.waitForTimeout(600);
for (let i=0;i<6;i++){
const res = await page.evaluate(()=>{
const ov=document.querySelectorAll('.modal-root .overlay'); const last=ov[ov.length-1];
if(!last) return {done:true};
const btns=[...last.querySelectorAll('button')].filter(b=>!b.disabled&&b.offsetParent!==null);
const t=btns.find(b=>/CONTINUE|STEEL/i.test(b.textContent))||btns.find(b=>b.classList.contains('ev-choice')&&!b.classList.contains('locked'))||btns.find(b=>b.classList.contains('choice'));
if(!t) return {done:true};
const isEvent = !!t.closest('.event-modal, .ev-choice');
t.click();
return {done:false, isEvent};
});
if (res.done) break;
if (i===0) await page.waitForTimeout(250);
await page.screenshot({ path: 'shots/modal.png' }).catch(()=>{});
await page.waitForTimeout(380);
}
await browser.close();
console.log('shots done');