From c80d01306548fee66ce0c9ec9f0e5e41c03b8b60 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 25 Oct 2026 18:48:40 +0000 Subject: [PATCH] Blockilization: a Great Engineer hurries only what's being built, Civ V style The hurry added 300 + 30 a citizen straight to the city's production with no cap, and what was over the current build's cost carried on to the next item, one finished a turn. A big city's engineer on a cheap build left hundreds of production over, so everything after it took a turn each for many builds. Now, as in Civ V, it puts in no more than the current build still needs (and fails, keeping the engineer, with nothing to hurry). Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01HaXWkqcsX9gsXphN4egMc1 --- src/games/blockilization/client/more.ts | 2 +- src/games/blockilization/rules/game.ts | 8 +++++++- src/games/blockilization/tests/cases.ts | 26 ++++++++++++++++++++++++- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/games/blockilization/client/more.ts b/src/games/blockilization/client/more.ts index 8b30713..36c040c 100644 --- a/src/games/blockilization/client/more.ts +++ b/src/games/blockilization/client/more.ts @@ -52,7 +52,7 @@ export function unitExtras(u: UnitWire, act: (label: string, o: Parameters { + const { game, at } = blank(); + const c = city(game, 0, at(10, 8), { pop: 10 }); + const monument = { kind: 'building', id: 'monument' } as const; + c.queue = [monument, { kind: 'unit', id: 'warrior' }, { kind: 'unit', id: 'warrior' }, { kind: 'unit', id: 'warrior' }]; + const g = unit(game, 'great_engineer', 0, c.tile); + ok(apply(game, 0, { t: 'greatPerson', unit: g.id, action: 'hurry' }).ok, 'hurried'); + eq(c.prod, itemCost(game, monument), 'as much as the monument needs'); + endTurn(game); + ok(c.buildings.includes('monument'), 'the monument built'); + ok(c.prod < itemCost(game, { kind: 'unit', id: 'warrior' }), `only a turn's production carried to the warrior (${c.prod})`); + endTurn(game); + eq(game.units.filter((u) => u.type === 'warrior' && u.owner === 0).length, 0, 'which takes more than a turn'); + // Nothing to hurry: the engineer kept. + c.queue = []; + c.prod = 0; + const g2 = unit(game, 'great_engineer', 0, c.tile); + ok(!apply(game, 0, { t: 'greatPerson', unit: g2.id, action: 'hurry' }).ok && game.units.includes(g2), 'not with nothing being built'); + // A wonder far from done gets the whole of it. + c.queue = [{ kind: 'building', id: 'cn_tower' }]; + ok(apply(game, 0, { t: 'greatPerson', unit: g2.id, action: 'hurry' }).ok, 'a wonder hurried'); + eq(c.prod, 300 + 30 * c.pop, 'with all 300 and 30 a citizen'); +}); + // ------------------------------------------------------------------------------------------------- // City-states, trade, spies, research agreements // -------------------------------------------------------------------------------------------------