import { LessonTask } from "./MoveOutcome"; export type RuleId = "board" | "sowing" | "extraTurn" | "evenCapture" | "emptyPitCapture" | "endOfGame" | "clock"; // A rule shown on a board: the position, player 1 (bottom) to move, and the pit played, if any. export interface RuleExample { board: number[]; pitIndex?: number; } // The rule taught on a prepared position (player 1, bottom, to move) with a task. export interface Lesson { board: number[]; task: LessonTask; taskKey: string; } export interface Rule { id: RuleId; titleKey: string; // At most three sentences. textKeys: string[]; example?: RuleExample; lesson?: Lesson; } const START = [4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4, 0]; const SOWING = [4, 4, 1, 4, 4, 4, 1, 4, 4, 4, 4, 4, 4, 2]; const EVEN_CAPTURE = [4, 4, 4, 4, 4, 4, 0, 4, 3, 4, 4, 4, 4, 1]; const EMPTY_PIT_CAPTURE = [2, 0, 4, 4, 4, 4, 3, 4, 4, 4, 4, 5, 4, 2]; const END_OF_GAME = [0, 0, 0, 0, 0, 1, 20, 2, 3, 1, 0, 2, 1, 18]; const texts = (id: string, count: number) => Array.from({ length: count }, (_, i) => `Rule${id}Text${i + 1}`); // The rules of the game in the order they are taught (docs/specs/tutorial). Every board here is checked against the // engine by the tests; the boards after a move are never written by hand. export const RULES: Rule[] = [ { id: "board", titleKey: "RuleBoardTitle", textKeys: texts("Board", 3), example: { board: START }, lesson: { board: START, task: "anyMove", taskKey: "LessonTaskAnyMove" }, }, { id: "sowing", titleKey: "RuleSowingTitle", textKeys: texts("Sowing", 3), example: { board: SOWING, pitIndex: 0 }, lesson: { board: SOWING, task: "anyMove", taskKey: "LessonTaskSowing" }, }, { id: "extraTurn", titleKey: "RuleExtraTurnTitle", textKeys: texts("ExtraTurn", 2), example: { board: START, pitIndex: 3 }, lesson: { board: START, task: "extraTurn", taskKey: "LessonTaskExtraTurn" }, }, { id: "evenCapture", titleKey: "RuleEvenCaptureTitle", textKeys: texts("EvenCapture", 2), example: { board: EVEN_CAPTURE, pitIndex: 5 }, lesson: { board: EVEN_CAPTURE, task: "evenCapture", taskKey: "LessonTaskEvenCapture" }, }, { id: "emptyPitCapture", titleKey: "RuleEmptyPitCaptureTitle", textKeys: texts("EmptyPitCapture", 2), example: { board: EMPTY_PIT_CAPTURE, pitIndex: 0 }, lesson: { board: EMPTY_PIT_CAPTURE, task: "emptyPitCapture", taskKey: "LessonTaskEmptyPitCapture" }, }, { id: "endOfGame", titleKey: "RuleEndOfGameTitle", textKeys: texts("EndOfGame", 3), example: { board: END_OF_GAME, pitIndex: 5 }, lesson: { board: END_OF_GAME, task: "endGame", taskKey: "LessonTaskEndGame" }, }, { id: "clock", titleKey: "RuleClockTitle", textKeys: texts("Clock", 2), }, ]; export const LESSON_RULES: Rule[] = RULES.filter((rule) => rule.lesson); export function getRule(id: string | undefined): Rule | undefined { return RULES.find((rule) => rule.id === id); } // The lesson after the given one, or undefined after the last. export function getNextLessonRule(id: RuleId): Rule | undefined { const index = LESSON_RULES.findIndex((rule) => rule.id === id); return index >= 0 ? LESSON_RULES[index + 1] : undefined; }