New worlds get generated camp names like new claims (t3)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -442,7 +442,7 @@ Previews drawn under the cursor: build ghosts, drill aim and pulses, selections,
|
|||||||
Events from the simulation (emit) turned into sounds, toasts and cards.
|
Events from the simulation (emit) turned into sounds, toasts and cards.
|
||||||
- functions: drainEvents
|
- functions: drainEvents
|
||||||
|
|
||||||
### src/ui/loop.js (127 lines)
|
### src/ui/loop.js (133 lines)
|
||||||
The frame loop and boot.
|
The frame loop and boot.
|
||||||
- functions: scanVisible, frame, boot
|
- functions: scanVisible, frame, boot
|
||||||
- variables: lastT, acc, lastRender, frameMs, simMs, fpsSm, ambientT
|
- variables: lastT, acc, lastRender, frameMs, simMs, fpsSm, ambientT
|
||||||
|
|||||||
@@ -4,6 +4,12 @@ What agents have done, newest first. Add an entry for every piece of work: the d
|
|||||||
note or request it was for, what changed, the files touched, the tests run, and anything left
|
note or request it was for, what changed, the files touched, the tests run, and anything left
|
||||||
open or not verified. Keep each entry short; the git history has the details.
|
open or not verified. Keep each entry short; the git history has the details.
|
||||||
|
|
||||||
|
## 2026-10-24: New worlds get camp names too (Claude Code, Codex)
|
||||||
|
|
||||||
|
- The new-world dialog prefills `claimName(seed, existing names)` instead of "World N", and
|
||||||
|
follows seed edits until the player types their own name; a blank name falls back to it too
|
||||||
|
(`src/ui/loop.js`, `session.js`). play.py checks updated. All tests pass.
|
||||||
|
|
||||||
## 2026-10-24: t30: progress while generating, loading and saving (Claude Code, Codex)
|
## 2026-10-24: t30: progress while generating, loading and saving (Claude Code, Codex)
|
||||||
|
|
||||||
- `worldgen.js`: `worldSteps` generator yields `[fraction, label]`; `generateWorld` (sync, tests)
|
- `worldgen.js`: `worldSteps` generator yields `[fraction, label]`; `generateWorld` (sync, tests)
|
||||||
|
|||||||
+9
-3
@@ -98,16 +98,22 @@ function boot(hotData) {
|
|||||||
buildTitleCells(); drawTitle();
|
buildTitleCells(); drawTitle();
|
||||||
$('nw-seed').value = String(Math.floor(Math.random() * 900000) + 100000);
|
$('nw-seed').value = String(Math.floor(Math.random() * 900000) + 100000);
|
||||||
$('wallet').onclick = () => { playSfx('ui'); openNotebook('Market'); };
|
$('wallet').onclick = () => { playSfx('ui'); openNotebook('Market'); };
|
||||||
|
let autoName = '', worldNames = [];
|
||||||
|
const newWorldSeed = () => parseInt(String($('nw-seed').value).replace(/\D/g, ''), 10) || Math.floor(Math.random() * 1e6);
|
||||||
$('btn-new').onclick = async () => {
|
$('btn-new').onclick = async () => {
|
||||||
auInit(); playSfx('ui'); $('newworld').hidden = !$('newworld').hidden;
|
auInit(); playSfx('ui'); $('newworld').hidden = !$('newworld').hidden;
|
||||||
if ($('newworld').hidden) return;
|
if ($('newworld').hidden) return;
|
||||||
try { $('nw-name').value = `World ${(await listWorlds()).length + 1}`; }
|
try { worldNames = (await listWorlds()).map(w => w.name); }
|
||||||
catch (e) { $('nw-name').value = 'World 1'; }
|
catch (e) { worldNames = []; }
|
||||||
|
$('nw-name').value = autoName = claimName(newWorldSeed(), worldNames);
|
||||||
$('nw-name').focus(); $('nw-name').select();
|
$('nw-name').focus(); $('nw-name').select();
|
||||||
};
|
};
|
||||||
|
$('nw-seed').oninput = () => {
|
||||||
|
if ($('nw-name').value === autoName) $('nw-name').value = autoName = claimName(newWorldSeed(), worldNames);
|
||||||
|
};
|
||||||
for (const id of ['nw-name', 'nw-seed']) $(id).onkeydown = e => { if (e.key === 'Enter') $('btn-generate').click(); };
|
for (const id of ['nw-name', 'nw-seed']) $(id).onkeydown = e => { if (e.key === 'Enter') $('btn-generate').click(); };
|
||||||
$('btn-generate').onclick = () => {
|
$('btn-generate').onclick = () => {
|
||||||
const seed = parseInt(String($('nw-seed').value).replace(/\D/g, ''), 10) || Math.floor(Math.random() * 1e6);
|
const seed = newWorldSeed();
|
||||||
const [w, h] = $('nw-size').value.split('x').map(Number);
|
const [w, h] = $('nw-size').value.split('x').map(Number);
|
||||||
startNewWorld(seed, w, h, $('nw-name').value);
|
startNewWorld(seed, w, h, $('nw-name').value);
|
||||||
};
|
};
|
||||||
|
|||||||
+1
-1
@@ -33,7 +33,7 @@ async function setupNewWorld(seed, w, h, name, carried, title = 'Generating worl
|
|||||||
async function startNewWorld(seed, w, h, name = '') {
|
async function startNewWorld(seed, w, h, name = '') {
|
||||||
try {
|
try {
|
||||||
const worlds = await listWorlds();
|
const worlds = await listWorlds();
|
||||||
await setupNewWorld(seed, w, h, cleanWorldName(name, `World ${worlds.length + 1}`));
|
await setupNewWorld(seed, w, h, cleanWorldName(name, claimName(seed, worlds.map(w => w.name))));
|
||||||
career = { id: newWorldId(), claims: [GAME.worldId], claimNo: 1 };
|
career = { id: newWorldId(), claims: [GAME.worldId], claimNo: 1 };
|
||||||
GAME.careerId = career.id; GAME.claimNo = 1;
|
GAME.careerId = career.id; GAME.claimNo = 1;
|
||||||
showLoading(true, 0.9, 'Saving');
|
showLoading(true, 0.9, 'Saving');
|
||||||
|
|||||||
+17
-6
@@ -1,7 +1,7 @@
|
|||||||
"""Play-test in a real browser: mouse, keyboard and a mocked gamepad drive the game; save and continue.
|
"""Play-test in a real browser: mouse, keyboard and a mocked gamepad drive the game; save and continue.
|
||||||
Screenshots go to shots/play/ (or the folder given as the first argument). Pixel look unless the
|
Screenshots go to shots/play/ (or the folder given as the first argument). Pixel look unless the
|
||||||
second argument is 'smooth'."""
|
second argument is 'smooth'."""
|
||||||
import json, sys, pathlib
|
import json, sys, pathlib, re
|
||||||
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent.parent / 'tools'))
|
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent.parent / 'tools'))
|
||||||
from use_venv import ensure_playwright; ensure_playwright()
|
from use_venv import ensure_playwright; ensure_playwright()
|
||||||
from playwright.sync_api import sync_playwright
|
from playwright.sync_api import sync_playwright
|
||||||
@@ -75,12 +75,23 @@ with sync_playwright() as p:
|
|||||||
if pg.is_visible('#nw-seed'): pg.click('#btn-new')
|
if pg.is_visible('#nw-seed'): pg.click('#btn-new')
|
||||||
pg.click('#btn-new')
|
pg.click('#btn-new')
|
||||||
pg.wait_for_function("document.activeElement === $('nw-name')")
|
pg.wait_for_function("document.activeElement === $('nw-name')")
|
||||||
names[seed] = 'Copper Valley' if seed == 222 else pg.input_value('#nw-name')
|
auto_name = pg.input_value('#nw-name')
|
||||||
check(f'new world {seed} offers the next default name', pg.input_value('#nw-name') == f'World {2 if seed == 222 else 3}')
|
check(f'new world {seed} offers a two-word camp name', bool(re.fullmatch(r'[A-Z][a-z]+ [A-Z][a-z]+', auto_name)))
|
||||||
|
check(f'new world {seed} default matches its seed', auto_name == pg.evaluate("async () => claimName(parseInt($('nw-seed').value, 10), (await listWorlds()).map(w => w.name))"))
|
||||||
|
check('default name is selected for replacement', pg.evaluate("$('nw-name').selectionStart === 0 && $('nw-name').selectionEnd === $('nw-name').value.length"))
|
||||||
|
pg.fill('#nw-seed', '42')
|
||||||
|
first_name = pg.input_value('#nw-name')
|
||||||
|
pg.fill('#nw-seed', str(seed))
|
||||||
|
expected = pg.evaluate("async seed => claimName(seed, (await listWorlds()).map(w => w.name))", seed)
|
||||||
|
check(f'changing seed to {seed} updates the camp name', pg.input_value('#nw-name') == expected and expected != first_name)
|
||||||
|
names[seed] = 'Copper Valley' if seed == 222 else expected
|
||||||
if seed == 222:
|
if seed == 222:
|
||||||
pg.fill('#nw-name', names[seed])
|
pg.fill('#nw-name', names[seed])
|
||||||
pg.screenshot(path=str(out / 'new-world.png'))
|
pg.fill('#nw-seed', '42')
|
||||||
pg.fill('#nw-seed', str(seed)); pg.press('#nw-name' if seed == 222 else '#nw-seed', 'Enter')
|
check('changing the seed keeps a typed world name', pg.input_value('#nw-name') == names[seed])
|
||||||
|
pg.fill('#nw-seed', str(seed))
|
||||||
|
pg.screenshot(path=str(out / 'new-world.png'))
|
||||||
|
pg.press('#nw-name' if seed == 222 else '#nw-seed', 'Enter')
|
||||||
pg.wait_for_function('GAME.running', timeout=20000)
|
pg.wait_for_function('GAME.running', timeout=20000)
|
||||||
check(f'new world {seed} paints a moving generation bar', pg.evaluate("__loads.some(([t, s, w]) => t === 'Generating world' && parseFloat(w) > 0 && parseFloat(w) < 90) && !GAME.loading"))
|
check(f'new world {seed} paints a moving generation bar', pg.evaluate("__loads.some(([t, s, w]) => t === 'Generating world' && parseFloat(w) > 0 && parseFloat(w) < 90) && !GAME.loading"))
|
||||||
check(f'new world {seed} shows the Welcome card', pg.evaluate("[...$('cards').children].some(c => c.textContent.includes('Welcome'))"))
|
check(f'new world {seed} shows the Welcome card', pg.evaluate("[...$('cards').children].some(c => c.textContent.includes('Welcome'))"))
|
||||||
@@ -133,7 +144,7 @@ with sync_playwright() as p:
|
|||||||
check('Continue chooses the most recently saved world', pg.evaluate('worldSeed') == 333)
|
check('Continue chooses the most recently saved world', pg.evaluate('worldSeed') == 333)
|
||||||
pg.evaluate('quitToTitle()')
|
pg.evaluate('quitToTitle()')
|
||||||
if not pg.is_visible('#nw-seed'): pg.click('#btn-new')
|
if not pg.is_visible('#nw-seed'): pg.click('#btn-new')
|
||||||
blank_default = pg.evaluate("listWorlds().then(w => `World ${w.length + 1}`)")
|
blank_default = pg.evaluate("listWorlds().then(w => claimName(777, w.map(w => w.name)))")
|
||||||
pg.fill('#nw-name', ' ')
|
pg.fill('#nw-name', ' ')
|
||||||
pg.fill('#nw-seed', '777'); pg.click('#btn-generate')
|
pg.fill('#nw-seed', '777'); pg.click('#btn-generate')
|
||||||
pg.wait_for_function('GAME.running === true', timeout=20000)
|
pg.wait_for_function('GAME.running === true', timeout=20000)
|
||||||
|
|||||||
Reference in New Issue
Block a user