A new table plays Tablut unless the host chooses Copenhagen
The declared default on the rules option is now Tablut, listed first, and the engine plays it when no rules are given, so the hall's still, the preferences' table default and a bare createGame agree. Tests that read Copenhagen positions ask for Copenhagen; the Tablut layout test pins the default. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GwFKMuQnPAEHJ5yA1q4orh
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
32152c05f0
commit
e95a090ac0
@@ -21,7 +21,7 @@ const E9 = '.........';
|
||||
|
||||
describe('the opening', () => {
|
||||
it('lays Copenhagen out with 24 attackers, 12 defenders and the king on the throne', () => {
|
||||
const s = createGame(names);
|
||||
const s = createGame(names, 1, 1, { set: 'copenhagen', side: 'defenders' });
|
||||
expect(s.size).toBe(11);
|
||||
expect(s.cells.filter((p) => p === 'a').length).toBe(24);
|
||||
expect(s.cells.filter((p) => p === 'd').length).toBe(12);
|
||||
@@ -29,8 +29,8 @@ describe('the opening', () => {
|
||||
expect(s.toMove).toBe('attackers');
|
||||
});
|
||||
|
||||
it('lays Tablut out on nine by nine with 16 attackers and 8 defenders', () => {
|
||||
const s = createGame(names, 1, 1, { set: 'tablut', side: 'defenders' });
|
||||
it('lays Tablut out on nine by nine with 16 attackers and 8 defenders, and plays it when no rules are chosen', () => {
|
||||
const s = createGame(names);
|
||||
expect(s.size).toBe(9);
|
||||
expect(s.cells.filter((p) => p === 'a').length).toBe(16);
|
||||
expect(s.cells.filter((p) => p === 'd').length).toBe(8);
|
||||
@@ -70,7 +70,7 @@ describe('moving', () => {
|
||||
});
|
||||
|
||||
it('refuses the wrong side, a stranger, and an impossible square, with reasons', () => {
|
||||
const s = createGame(names);
|
||||
const s = createGame(names, 1, 1, { set: 'copenhagen', side: 'defenders' });
|
||||
expect(validateMove(s, 'A', { from: at(11, { x: 5, y: 3 }), to: at(11, { x: 5, y: 2 }) })).toMatch(/not your side/);
|
||||
expect(validateMove(s, 'B', { from: at(11, { x: 5, y: 3 }), to: at(11, { x: 5, y: 2 }) })).toMatch(/not one of your pieces/);
|
||||
expect(validateMove(s, 'B', { from: at(11, { x: 3, y: 0 }), to: at(11, { x: 3, y: 5 }) })).toMatch(/cannot move there/);
|
||||
@@ -139,7 +139,7 @@ describe('the king', () => {
|
||||
});
|
||||
|
||||
it('needs four attackers on the throne, and three beside it', () => {
|
||||
const s = createGame(names);
|
||||
const s = createGame(names, 1, 1, { set: 'copenhagen', side: 'defenders' });
|
||||
const t = throneOf(11);
|
||||
// Clear the defenders and ring the throne with three attackers; the fourth arrives.
|
||||
const onThrone = s.cells.map((p) => (p === 'd' ? '.' : p)) as Piece[];
|
||||
@@ -216,7 +216,7 @@ describe('the ends of the game', () => {
|
||||
}, 120_000);
|
||||
|
||||
it('opens with the same move every time, so a ledger replays to the same choice', () => {
|
||||
const s = createGame(names, 3);
|
||||
const s = createGame(names, 3, 1, { set: 'copenhagen', side: 'defenders' });
|
||||
expect(movesOf(rulesetOf(s), s.cells, 'attackers').length).toBe(116);
|
||||
expect(chooseMove(s, 'B')).toEqual({ from: 3, to: 2 });
|
||||
});
|
||||
|
||||
@@ -13,6 +13,8 @@ import { chooseMove } from './bot';
|
||||
export { at, beyond, cellOf, cornersOf, isEdge, pieceWord, sideOf, squareName, throneOf, type Input, type Piece, type Side } from './board';
|
||||
|
||||
const CURRENT_RULES = 1;
|
||||
/** The rules a table plays when the host chooses none. */
|
||||
const DEFAULT_SET: Ruleset['id'] = 'tablut';
|
||||
|
||||
export interface Player {
|
||||
id: SeatId;
|
||||
@@ -64,7 +66,7 @@ export function rulesetOf(state: State): Ruleset {
|
||||
// --- Setting up ---------------------------------------------------------------
|
||||
|
||||
export function createGame(names: Record<SeatId, string>, _seed = 0, rules = CURRENT_RULES, options?: TableOptions): State {
|
||||
const set = options?.set === 'tablut' ? RULESETS.tablut : RULESETS.copenhagen;
|
||||
const set = RULESETS[options?.set as Ruleset['id']] ?? RULESETS[DEFAULT_SET];
|
||||
const size = set.size;
|
||||
const cells: Piece[] = Array(size * size).fill('.');
|
||||
for (const c of set.attackers) cells[at(size, c)] = 'a';
|
||||
@@ -205,10 +207,10 @@ export const game: GameSpec<State, Input> = {
|
||||
key: 'set',
|
||||
label: 'Rules',
|
||||
choices: [
|
||||
{ value: 'copenhagen', label: 'Copenhagen, 11 by 11', note: 'The modern tournament game. The king escapes to a corner and falls only to four attackers, three beside the throne.' },
|
||||
{ value: 'tablut', label: 'Tablut, 9 by 9, after Linnaeus', note: 'The older game. The king escapes to any edge square, and away from the throne two attackers take him like any piece.' }
|
||||
{ value: 'tablut', label: 'Tablut, 9 by 9, after Linnaeus', note: 'The older game. The king escapes to any edge square, and away from the throne two attackers take him like any piece.' },
|
||||
{ value: 'copenhagen', label: 'Copenhagen, 11 by 11', note: 'The modern tournament game. The king escapes to a corner and falls only to four attackers, three beside the throne.' }
|
||||
],
|
||||
default: 'copenhagen'
|
||||
default: DEFAULT_SET
|
||||
},
|
||||
{ key: 'side', label: 'You play', choices: SIDES, default: 'defenders' }
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user