function activeCell
activeCell(settings: Settings, cell: number): boolean
Row-major addresses stay stable; omitted cells have no clue and no neighbours.
@johnmorrisdotca/jirai 0.4.1 · 7 entry points · 90 exports
@johnmorrisdotca/jiraiactiveCell activeCells Board Constraint dailySeed decodeOrthogonalGame deduce Deduction DEFAULT_SETTINGS encodeOrthogonalGame ENUMERATION_CELLS ENUMERATION_NODES Game gameFromProgress gameProgress GENERATION_ATTEMPTS GenerationError GenerationOptions Grid GRID_SPECS GRIDS hintFor HUGE_SIZES hugeSettings HugeSize isSolvable Language Level LEVEL_ALIASES LEVEL_SIZES LevelAlias levelNamed LEVELS levelSettings LevelSize makeBoard makeOrthogonalBoard Mark MARKS Material MAX_CELLS MAX_SIDE Measure measureBoard Move MOVES neighbours neighboursOf newGame newOrthogonalGame ORTHOGONAL_VARIANT orthogonalHint orthogonalNeighbours OrthogonalSettings Pieces play PRESETS ProofKind ProofTally seededRandom Settings SHAPES Status STATUSES validCell validSettings VERSION visibleGame VisibleGame withBoard
activeCell(settings: Settings, cell: number): boolean
Row-major addresses stay stable; omitted cells have no clue and no neighbours.
activeCells(settings: Settings): number[]
Returns all active cells in stable row-major order.
type Board = { settings: Settings; mines: readonly boolean[]; clues: readonly number[]; first: number; /** Which candidate this deal was: below the `attempts` limit it is a random layout, at or above it a repaired one. */ attempt: number; };
A dealt board including its answer; keep it off public clients.
type Constraint = { cells: readonly number[]; mines: number; sources: readonly number[] };
An exact count over unknown cells, with the clues that supplied it.
dailySeed(day: string, grid?: string): number
UTC by definition, so two people sharing a daily seed get the same board.
decodeOrthogonalGame(code: string): Game | null
Restores only version 2 orthogonal progress records.
deduce(game: VisibleGame, knownMines?: ReadonlySet<number>, enumerate?: boolean, adjacent?: readonly (readonly number[])[]): Deduction
What the clues prove, without reading the answer or trusting a player's flags. A flag is a note; treating it as evidence makes a bad note a bad hint.
type Deduction = { safe: readonly number[]; mines: readonly number[]; reason: "count" | "overlap" | "total" | "enumeration" | "none"; sources: readonly number[]; /** A conflicting clue, or a board with no consistent mine placement. */ contradiction: boolean; };
Certain safe cells and mines proved from visible clues.
DEFAULT_SETTINGS: Settings
Default easy game, with a verified no-guess board and clear opening.
encodeOrthogonalGame(game: Game): string
Encodes an orthogonal game with an explicit variant marker and version 2.
ENUMERATION_CELLS: 18
Largest frontier enumerated for exact deductions.
ENUMERATION_NODES: 100000
Maximum partial assignments checked in one exact deduction search.
type Game = { settings: Settings; board: Board | null; marks: readonly Mark[]; status: Status; exploded: number | null; moves: readonly Move[]; /** A proved hint has been shown during this run. */ helped: boolean; };
Rules data includes the answer; never send it to a competitive client. Use visibleGame for hints and drawing.
gameFromProgress(progress: string): Game | null
A saved game is rebuilt under the rules. Malformed or unavailable boards return null.
gameProgress(game: Game): string
Keep settings and moves, never an unchecked answer array. Version the deal before changing it.
GENERATION_ATTEMPTS: 128
Default number of random layouts tried before a no-guess deal falls back to repairing the closest one.
GenerationError: typeof GenerationError
A bounded generator must say it failed, never quietly return a guessing board.
type GenerationOptions = { attempts?: number; repairs?: number; repair?: boolean; enumerate?: boolean };
Work limits for seeded board generation and its no-guess check. attempts is the number of random layouts tried first; repairs is how many single-mine moves the repair stage may try on the closest of them (0, or repair: false, keeps the 0.2 behaviour of giving up after the attempts); enumerate switches the exact small-frontier check.
type Grid = "square" | "orthogonal" | "hex" | "wrap";
Neighbour topology used to count the clues around each cell.
GRID_SPECS: Record<Grid, { offsets: readonly (readonly [number, number])[]; wrap: boolean; }>
Neighbour offsets and edge behaviour for each topology. Hex coordinates are axial: each row is displaced half a cell to the right.
GRIDS: { readonly square: "square"; readonly orthogonal: "orthogonal"; readonly hex: "hex"; readonly wrap: "wrap"; }
Names for the supported square, four-neighbour, hex, and wrap grids.
hintFor(game: VisibleGame): Deduction
Keep discovering certain mines until there is a safe cell or nothing more is proved.
HUGE_SIZES: readonly [{ readonly width: 32; readonly height: 32; }, { readonly width: 48; readonly height: 24; }, { readonly width: 24; readonly height: 48; }]
The huge fields: four times the area of a 16×16 (the medium level), 1,024 to 1,152 squares, for a long solve. The same share of mines as a level, see hugeSettings. They are dealt, proved and drawn like any other field: a no-guess deal takes a few milliseconds to a tenth of a second here, and 2,400 squares is the most validSettings accepts.
hugeSettings(level: Level | LevelAlias, board?: { grid?: Grid; shape?: Settings["shape"]; size?: HugeSize; }): LevelSize
The size and mine count of a level on a huge field: a field of HUGE_SIZES (32 × 32 unless size says another of them), with the level's own share of mines over its squares. Easy is 12% mines, medium 16%, hard 21% and extra-hard 25%, as on the level's own field, and a heart, star or hexagon outline keeps that share over the squares it has left. Every field is still dealt and proved to need no guess, on every grid. Throws RangeError for a name that is no level or a size that is not huge.
type HugeSize = { width: number; height: number };
The outline of a huge field: one of HUGE_SIZES' width and height.
isSolvable(board: Board, enumerate?: boolean): boolean
Verify a board from one opening, using only clues that have been uncovered.
type Language = "en" | "ja";
Supported interface copy locales.
type Level = "easy" | "medium" | "hard" | "extra-hard";
A difficulty level: easy, medium, hard or extra-hard.
LEVEL_ALIASES: { readonly beginner: "easy"; readonly intermediate: "medium"; readonly expert: "hard"; }
The 0.1 and 0.2 names for the first three levels. They are still accepted wherever a level is.
LEVEL_SIZES: Record<"easy" | "medium" | "hard" | "extra-hard", { width: number; height: number; mines: number; }>
Size and mine count of each level on a rectangular board. Shaped boards keep the size and the density.
type LevelAlias = "beginner" | "intermediate" | "expert";
The 0.1 and 0.2 names for easy, medium and hard, still accepted wherever a level is.
levelNamed(name: unknown): Level | null
The level a name means, or null. Accepts easy, medium, hard and extra-hard (also written extra hard, extra_hard or extraHard, in any case), and the older beginner, intermediate and expert.
LEVELS: readonly ["easy", "medium", "hard", "extra-hard"]
The four difficulty levels, easiest first. Each is a larger and denser field than the one before.
levelSettings(level: Level | LevelAlias, board?: { grid?: Grid; shape?: Settings["shape"]; }): LevelSize
The size and mine count of a level. A rectangle gets the level's own numbers; a shaped board keeps the level's width and height and its density of mines over the cells that are left. Throws RangeError for a name that is no level.
type LevelSize = Pick<Settings, "width" | "height" | "mines">;
Board size and mine count a level asks for.
makeBoard(settings: Settings, first: number, options?: GenerationOptions): Board
Deal after the first reveal. A seed fixes the whole candidate stream and the accepted board.
A no-guess deal first draws random layouts, as 0.1 and 0.2 did, so every board those versions dealt is still dealt. If none of them can be finished by deduction it takes the closest and repairs it: single mines are moved near the place the solver stopped until the solver finishes the whole field. The result is proved the same way either route.
makeOrthogonalBoard(settings: OrthogonalSettings, first: number, options?: GenerationOptions): Board
Deals a board whose clues count only up, down, left and right.
type Mark = "covered" | "flag" | "question" | "open";
Player-facing state of one cell; the answer is never a mark.
MARKS: { readonly covered: "covered"; readonly flag: "flag"; readonly question: "question"; readonly open: "open"; }
Names for the cell mark cycle.
type Material = "ivory" | "wood" | "slate";
Board colours for drawing and mounted play.
MAX_CELLS: 2400
Largest total cell count accepted by settings validation.
MAX_SIDE: 60
Largest width or height accepted by settings validation.
type Measure = { /** Mines per playable cell. */ density: number; /** Playable cells. */ cells: number; /** Share of the safe cells the first reveal opens before any reasoning. */ opening: number; /** Cells proved by each kind of reasoning: one clue, two clues together, the mine counter, or every arrangement of a small frontier. */ proofs: ProofTally; /** Share of the playable cells proved by anything beyond one clu…
How demanding a dealt board is to solve by deduction, measured by solving it.
measureBoard(board: Board): Measure
Solve a dealt board from its opening and report what it took. The score is 100 × density + 100 × multiStep + depth ÷ 4, so it rises with the crowding of the mines, with the share of the field that needs more than a single clue, and with how long the longest chain of reasoning runs. It is a way to put boards in order, not a rating of how long a person will take.
type Move = { kind: "reveal" | "mark" | "chord"; cell: number };
A reveal, mark-cycle, or numbered-cell chord applied to a game.
MOVES: { readonly reveal: "reveal"; readonly mark: "mark"; readonly chord: "chord"; }
Names for the moves accepted by the engine.
neighbours(settings: Settings, cell: number): number[]
Every neighbour once. Wrap joins both pairs of opposite edges.
neighboursOf(settings: Settings): number[][]
Precomputes the neighbour list for each row-major cell.
newGame(settings?: Settings): Game
Creates an unstarted game with covered cells and no dealt answer.
newOrthogonalGame(settings: OrthogonalSettings): Game
Starts a game under four-neighbour rules.
ORTHOGONAL_VARIANT: "orthogonal"
Identifies the four-neighbour rules and progress-code format.
orthogonalHint(game: Game): import("/home/runner/work/jirai/jirai/src/jirai.types").Deduction
Gives a clue-only deduction; flags remain notes and cannot influence the result.
orthogonalNeighbours(settings: OrthogonalSettings, cell: number): number[]
Returns the adjacent cells under the orthogonal rules.
type OrthogonalSettings = Omit<Settings, "grid">;
Settings accepted by the four-neighbour-specific helpers.
type Pieces = "flags" | "stones" | "flowers";
Symbols used to mark mines.
play(game: Game, move: Move): Game
A legal move returns a new game; an unavailable move returns the same one.
PRESETS: { readonly beginner: { width: number; height: number; mines: number; }; readonly intermediate: { width: number; height: number; mines: number; }; readonly expert: { width: number; height: number; mines: number; }; readonly wide: { readonly width: 21; readonly height: 9; readonly mines: 24; }; readonly tall: { readonly width: 9; readonly height: 21; readonly mines: 24; }; readonly easy: { width: number; heig…
Common minefield dimensions and mine counts. The levels, their older names, and two shapes of field.
type ProofKind = "count" | "overlap" | "total" | "enumeration";
Why a cell was proved: one clue, two overlapping clues, the mine counter, or every arrangement of a small frontier.
type ProofTally = Record<ProofKind, number>;
Cells proved by each kind of reasoning.
seededRandom(seed: number): () => number
Mulberry32, pinned by the replay tests: changing it would change every kept board.
type Settings = { /** Shape omits cells; rectangle is the compatible default. Wrap requires rectangle. */ shape?: "rectangle" | "heart" | "star" | "hexagon"; width: number; height: number; mines: number; grid: Grid; /** Only accept boards the deduction solver finishes from the opening. */ noGuess: boolean; /** The opening and every neighbour are safe, not only the first cell. */ opening: "safe" | "clear"; seed: numb…
Board dimensions and rules used to deal and validate a game.
SHAPES: readonly ["rectangle", "heart", "star", "hexagon"]
Board silhouettes supported by settings.
type Status = "ready" | "playing" | "won" | "lost";
Current game state, including whether a mine has been hit.
STATUSES: { readonly ready: "ready"; readonly playing: "playing"; readonly won: "won"; readonly lost: "lost"; }
Names for the game lifecycle states.
validCell(settings: Settings, cell: number): boolean
Reports whether a row-major cell is inside the board's active shape.
validSettings(value: unknown): value is Settings
Reject a setting before it reaches a board allocation or a shuffle.
VERSION: "0.4.1"
Package version, kept in step with the release metadata.
visibleGame(game: Game): VisibleGame
The clue-only view used by the solver. No hidden mine, including under a flag, survives it.
type VisibleGame = { settings: Settings; /** Null is hidden, including flags. Only opened cells give a clue. */ clues: readonly (number | null)[]; marks: readonly Mark[]; status: Status; };
Answer-free state suitable for deductions, hints, and public display.
withBoard(game: Game, board: Board): Game
Attaches a worker-dealt board that matches the game's settings, preserving existing moves.
@johnmorrisdotca/jirai/orthogonaldecodeOrthogonalGame encodeOrthogonalGame makeOrthogonalBoard newOrthogonalGame ORTHOGONAL_VARIANT orthogonalHint orthogonalNeighbours OrthogonalSettings
decodeOrthogonalGame(code: string): Game | null
Restores only version 2 orthogonal progress records.
encodeOrthogonalGame(game: Game): string
Encodes an orthogonal game with an explicit variant marker and version 2.
makeOrthogonalBoard(settings: OrthogonalSettings, first: number, options?: GenerationOptions): Board
Deals a board whose clues count only up, down, left and right.
newOrthogonalGame(settings: OrthogonalSettings): Game
Starts a game under four-neighbour rules.
ORTHOGONAL_VARIANT: "orthogonal"
Identifies the four-neighbour rules and progress-code format.
orthogonalHint(game: Game): import("/home/runner/work/jirai/jirai/src/jirai.types").Deduction
Gives a clue-only deduction; flags remain notes and cannot influence the result.
orthogonalNeighbours(settings: OrthogonalSettings, cell: number): number[]
Returns the adjacent cells under the orthogonal rules.
type OrthogonalSettings = Omit<Settings, "grid">;
Settings accepted by the four-neighbour-specific helpers.
@johnmorrisdotca/jirai/playJiraiMount mountJirai MountOptions STRINGS
type JiraiMount = { game: () => Game; progress: () => string; play: (cell: number, mark?: boolean) => void; hint: () => void; restart: () => void; load: (settings: Settings, progress?: string) => void; set: (options: DrawOptions) => void; destroy: () => void; };
Controls for reading and operating a mounted board.
mountJirai(host: HTMLElement, options?: MountOptions): JiraiMount
One playable board in any element. The engine owns the rules, this module owns presses, focus, the clock and the worker. Destroy removes only its own root, so two mounted boards never take each other's listeners or children.
type MountOptions = DrawOptions & { settings?: Settings; progress?: string; controls?: boolean; onChange?: (game: Game) => void; onFinish?: (game: Game) => void; onError?: (error: Error) => void; };
Initial game, appearance, control, and lifecycle callbacks for a mounted board.
STRINGS: { readonly en: { readonly board: "Minesweeper board"; readonly covered: "covered"; readonly flag: "flagged"; readonly question: "uncertain"; readonly empty: "empty"; readonly mine: "mine"; readonly wrong: "incorrect flag"; readonly ready: "Open a cell to begin. Your first cell is safe."; readonly playing: "Read the numbers. Open every safe cell."; readonly won: "Every safe cell is open. Well played."; reado…
Built-in English and Japanese strings used by the player and renderer.
@johnmorrisdotca/jirai/drawboardModel BoardModel CellModel DrawOptions JIRAI_STYLE
boardModel(game: Game, options?: DrawOptions): BoardModel
Where the cells sit, and what may be shown. The drawing never exposes a covered clue.
type BoardModel = { width: number; height: number; cells: CellModel[] };
Layout and cell presentation returned by boardModel.
type CellModel = { cell: number; x: number; y: number; width: number; height: number; label: string; text: string; kind: string; hint: boolean };
Accessible presentation data for one active board cell.
type DrawOptions = { material?: Material; pieces?: Pieces; language?: Language; hint?: number | null };
Appearance and optional hint marker used by drawing and play.
JIRAI_STYLE: "\n.jr-root{--jr-ground:#a98954;--jr-cover:#fbf8f1;--jr-open:#efe8d8;--jr-line:#cfc6b2;--jr-ink:#1f2320;--jr-accent:#2f7a4f;color:var(--jr-ui-ink,var(--jr-ink));font:inherit;position:relative}\n.jr-root[data-material=wood]{--jr-ground:#ae804a;--jr-cover:#e0bb7e;--jr-open:#c69d63;--jr-line:#936e40;--jr-ink:#352c20;background-image:repeating-linear-gradient(4deg,transparent 0 8px,#4b2b0c08 9px 10px)}\n.jr…
Scoped to one mounted board. Its host supplies the font and may override every colour.
@johnmorrisdotca/jirai/elementdefineJirai(registry?: CustomElementRegistry): void
Registers the <jirai-board> custom element once in a registry.
JiraiElement: typeof JiraiElement
Configurable <jirai-board> element that owns its mounted game.
@johnmorrisdotca/jirai/element/define@johnmorrisdotca/jirai/reactJiraiBoard({ settings, progress, material, pieces, language, controls, onChange, onFinish, onError, ...element }: JiraiProps): import("/home/runner/work/jirai/jirai/node_modules/.pnpm/@types+react@19.3.0/node_modules/@types/react/index").JSX.Element
Renders the DOM player inside a React-owned host. Options are read on mount; use a new key to load a new board.
この日本語は、まだ日本語を母語とする方の確認を受けていません。訂正を歓迎します。