Files
deepseek 8fbe70d0b0 Repterra Web — full game: base building, power grid, taming & breeding, aquatic raiders, day/night, save/load
- Isometric canvas RTS vs dinosaur waves (fan demake of Repterra)
- Economy: houses/taxes, farms, foresters, quarries; colonist staffing
- Power grid: generators extend build range; brownout + recovery
- Defense: walls/gates, watchtowers (AA), cannon towers (ground-only)
- Taming: Primal Pen + Tamers collar weakened dinos; pets obey commands
- Breeding: tamed pairs incubate eggs at the pen; hatchlings grow up
- 7 dino species incl. flying Pteranodons and lake-raiding Suchomimus
- Telegraphed waves with direction arrows; day-15 final horde; 3 difficulties
- Day/night cycle, fog of war, minimap, synth audio, 1x-3x speeds
- Save/Load/Continue + dawn autosave (full JSON state snapshots)
- Tests: 80-assertion headless suite, browser boot + E2E, balance harness
2026-08-23 07:00:23 +00:00

80 lines
3.2 KiB
JavaScript

/* Capture polished screenshots: base building + a mid-game battle. */
'use strict';
const { chromium } = require('/tmp/node_modules/playwright-core');
(async () => {
const browser = await chromium.launch({
executablePath: '/root/.cache/ms-playwright/chromium_headless_shell-1148/chrome-linux/headless_shell',
args: ['--no-sandbox', '--disable-gpu'],
});
const page = await browser.newPage({ viewport: { width: 1440, height: 860 } });
page.on('pageerror', e => console.error('PAGEERROR:', e.message));
await page.goto('http://127.0.0.1:8933/', { waitUntil: 'load' });
await page.waitForTimeout(600);
await page.screenshot({ path: '/root/dinorts/shots/menu.png' });
await page.click('[data-diff="normal"]');
await page.waitForTimeout(1500);
// build a believable starter base near the HQ via the sim API
await page.evaluate(() => {
const s = RTS.sim.state();
s.res.gold += 2000; s.res.wood += 2000; s.res.stone += 2000;
const hq = RTS.sim.hq();
const put = (defId, r0, r1, tries) => {
const rng = RTS.util.makeRng(defId.length * 77 + r0);
for (let i = 0; i < (tries || 400); i++) {
const a = rng() * Math.PI * 2, r = r0 + rng() * (r1 - r0);
const x = Math.round(hq.x + Math.cos(a) * r), y = Math.round(hq.y + Math.sin(a) * r);
if (RTS.sim.canPlace(defId, x, y).ok && RTS.sim.place(defId, x, y).ok) return true;
}
return false;
};
put('house', 2.2, 4); put('house', 2.2, 4); put('house', 3, 5);
put('generator', 5, 7);
put('farm', 2.5, 5); put('forester', 4, 9, 900); put('quarry', 4, 9, 900);
// defensive ring
for (let k = 0; k < 8; k++) {
const a = (k / 8) * Math.PI * 2;
const x = Math.round(hq.x + Math.cos(a) * 6.5), y = Math.round(hq.y + Math.sin(a) * 6.5);
RTS.sim.place(k % 2 ? 'watchtower' : 'wall', x, y);
}
// wall arc facing south-east
for (let d = -3; d <= 3; d++) RTS.sim.place('wall', hq.x + d, hq.y + 5);
RTS.sim.place('gate', hq.x, hq.y + 5);
put('barracks', 3, 6);
return true;
});
await page.waitForTimeout(2500);
await page.screenshot({ path: '/root/dinorts/shots/base.png' });
console.log('base shot saved');
// jump to just before wave day and let the horde arrive at the walls
await page.evaluate(() => {
const s = RTS.sim.state();
s.day = 5; s.dayT = 30;
s.waves.forEach(w => { if (!w.final && w.day <= 6 && !w.spawned) { /* leave schedule intact */ } });
});
await page.click('#topbtns .tbtn:nth-child(4)'); // 3x
let shots = 0;
let lastKills = -1;
for (let i = 0; i < 45; i++) {
await page.waitForTimeout(1000);
const stt = await page.evaluate(() => {
const s = RTS.sim.state();
return { kills: s.stats.kills, dinos: s.dinos.length, day: s.day };
});
// snap when combat is hot
if (stt.dinos > 10 && stt.dinos < 90 && shots < 2 && stt.kills !== lastKills) {
lastKills = stt.kills;
shots++;
await page.screenshot({ path: '/root/dinorts/shots/battle' + shots + '.png' });
console.log('battle shot', shots, JSON.stringify(stt));
}
if (stt.day >= 8 || shots >= 2) break;
}
await browser.close();
console.log('done');
})().catch(e => { console.error('CRASH:', e); process.exit(1); });