game

package
v0.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 6, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package game implements Minesweeper rules as a deep, TUI-independent module.

Invariants:

  • Before the first Reveal, mines are not placed on the board.
  • Only hidden cells carry a mark; revealing a cell clears it.
  • A flag blocks revealing; a question mark never changes what an action does.
  • After Won or Lost, all mutating operations are no-ops.

Index

Constants

View Source
const DailyKeyword = "daily"

DailyKeyword selects the daily challenge seed on the command line.

Variables

This section is empty.

Functions

func DailyDate

func DailyDate(t time.Time) string

DailyDate returns the UTC date string identifying a daily challenge.

Types

type ActionResult

type ActionResult struct {
	Ok      bool
	Changed []Coord
	Status  Status
}

ActionResult describes the outcome of a board action.

type Board

type Board struct {
	// contains filtered or unexported fields
}

Board is the deep module encapsulating all game rules.

func NewBoard

func NewBoard(d Difficulty, seed Seed) *Board

NewBoard creates an empty board; mines are placed on the first Reveal so that the opening move is always safe. The same difficulty and seed always produce the same layout.

func NewNoGuessBoard added in v0.3.0

func NewNoGuessBoard(d Difficulty, seed Seed) *Board

NewNoGuessBoard is NewBoard for a board that can be cleared by deduction alone, so the player is never asked to flip a coin. Laying one out means searching, which costs time on the opening move and is not always possible; when the search comes up empty the board falls back to an ordinary layout and NoGuess reports false.

func (*Board) CanChord

func (b *Board) CanChord(c Coord) bool

CanChord reports whether Chord would have an effect.

func (*Board) CanMark added in v0.3.0

func (b *Board) CanMark(c Coord) bool

CanMark reports whether CycleMark would have an effect.

func (*Board) CanReveal

func (b *Board) CanReveal(c Coord) bool

CanReveal reports whether Reveal would have an effect.

func (*Board) CellView

func (b *Board) CellView(c Coord) CellView

CellView returns the UI-facing cell state.

func (*Board) Chord

func (b *Board) Chord(c Coord) ActionResult

Chord reveals adjacent hidden cells when flag count matches the number.

func (*Board) CycleMark added in v0.3.0

func (b *Board) CycleMark(c Coord, questions bool) ActionResult

CycleMark advances the mark on a hidden cell. With questions enabled the cycle is none, flag, question, none; otherwise it is a plain flag toggle. Keeping the choice in the caller lets the preference live with the UI while the board owns what each mark means.

func (*Board) Difficulty

func (b *Board) Difficulty() Difficulty

Difficulty returns the board difficulty.

func (*Board) ElapsedReady

func (b *Board) ElapsedReady() bool

ElapsedReady reports whether the timer should run (first reveal done).

func (*Board) FlagCount

func (b *Board) FlagCount() int

FlagCount returns number of flagged cells.

func (*Board) Height

func (b *Board) Height() int

Height returns board height.

func (*Board) MarkAt added in v0.4.2

func (b *Board) MarkAt(c Coord) Mark

MarkAt returns the mark on a cell.

func (*Board) MineCount

func (b *Board) MineCount() int

MineCount returns total mines.

func (*Board) NoGuess added in v0.3.0

func (b *Board) NoGuess() bool

NoGuess reports whether this board is known to be solvable without guessing. It is only meaningful once mines are placed, which happens on the first reveal.

func (*Board) RemainingMines

func (b *Board) RemainingMines() int

RemainingMines returns mine count minus flags (may be negative).

func (*Board) Reveal

func (b *Board) Reveal(c Coord) ActionResult

Reveal opens a cell and may trigger flood fill.

func (*Board) Seed

func (b *Board) Seed() Seed

Seed returns the seed this board was generated from.

func (*Board) SetMark added in v0.4.2

func (b *Board) SetMark(c Coord, mark Mark) ActionResult

SetMark places a mark on a hidden cell without cycling.

func (*Board) Status

func (b *Board) Status() Status

Status returns current game status.

func (*Board) Width

func (b *Board) Width() int

Width returns board width.

type Cell

type Cell struct {
	HasMine  bool
	Adjacent uint8
	Revealed bool
	Mark     Mark
}

Cell holds internal board state. Mine positions are never exposed to UI.

type CellState

type CellState int

CellState is the visible state of a cell.

const (
	CellHidden CellState = iota
	CellRevealed
	CellFlagged
	CellQuestioned
)

type CellView

type CellView struct {
	State    CellState
	Adjacent uint8
	ShowMine bool // true when game is lost — reveal all mines
}

CellView is the UI-facing projection of a cell (information hiding).

type Coord

type Coord struct {
	X, Y int
}

Coord is a cell position on the board (0-indexed).

func (Coord) InBounds

func (c Coord) InBounds(w, h int) bool

InBounds reports whether c is within a board of size w×h.

func (Coord) Neighbors

func (c Coord) Neighbors(w, h int) []Coord

Neighbors returns up to eight adjacent coordinates, clipped to bounds.

type Difficulty

type Difficulty struct {
	Preset Preset
	Width  int
	Height int
	Mines  int
}

Difficulty describes board dimensions and mine count.

func PresetDifficulty

func PresetDifficulty(p Preset) Difficulty

PresetDifficulty returns the standard settings for a preset.

func (Difficulty) Key

func (d Difficulty) Key() string

Key returns a stable string for high-score storage.

func (Difficulty) Validate

func (d Difficulty) Validate() error

Validate checks that the difficulty is playable with first-click safety.

type Mark added in v0.3.0

type Mark uint8

Mark is the note a player has put on a hidden cell. A cell carries at most one, which is why this is an enum rather than a pair of booleans.

const (
	// MarkNone is an unmarked cell.
	MarkNone Mark = iota
	// MarkFlag asserts a mine. Flagged cells cannot be revealed and count
	// towards the remaining-mine display and chording.
	MarkFlag
	// MarkQuestion records a suspicion. It is a note to the player and nothing
	// more: revealing, flood fill, and chording treat it as plain hidden.
	MarkQuestion
)

type Move added in v0.4.0

type Move struct {
	Kind MoveKind `json:"kind"`
	Coord
	// TargetMark is the mark left on the cell after a MoveMark. Older replays
	// omit this and fall back to a single flag cycle.
	TargetMark *Mark `json:"target_mark,omitempty"`
}

Move is one recorded action in order.

type MoveKind added in v0.4.0

type MoveKind int

MoveKind is a single player action in a replay.

const (
	MoveReveal MoveKind = iota
	MoveMark
	MoveChord
)

type Preset

type Preset int

Preset identifies a built-in difficulty level.

const (
	Beginner Preset = iota
	Intermediate
	Expert
	Custom
)

func PresetFromString

func PresetFromString(s string) (Preset, bool)

PresetFromString parses a preset name.

func (Preset) String

func (p Preset) String() string

String returns a human-readable preset name.

type Replay added in v0.4.0

type Replay struct {
	ID         string     `json:"id"`
	Seed       Seed       `json:"seed"`
	Difficulty Difficulty `json:"difficulty"`
	NoGuess    bool       `json:"no_guess"`
	Moves      []Move     `json:"moves"`
	Won        bool       `json:"won"`
	Seconds    int        `json:"seconds"`
	PlayedAt   time.Time  `json:"played_at"`
}

Replay is a finished game that can be watched again. The seed pins the mine layout; the moves pin what the player did. NoGuess records which generator built the board: classic and no-guess draw differently from the same seed. Older JSON omits the field and loads as classic.

func (Replay) Apply added in v0.4.0

func (r Replay) Apply(b *Board, n int)

Apply replays moves onto a fresh board in order, up to but not including index n. The board must already have been generated from the replay's seed and had its opening move applied the same way the original game did.

type Seed

type Seed uint32

Seed identifies a reproducible board layout. It is deliberately 32-bit so that seeds stay short enough to share verbally or in a chat message.

func DailySeed

func DailySeed(t time.Time) Seed

DailySeed derives the seed for the daily challenge on t's UTC date. Every player who starts the challenge on the same date gets the same board.

func ParseSeed

func ParseSeed(s string, now time.Time) (Seed, error)

ParseSeed accepts a decimal seed or the "daily" keyword. now supplies the clock for the daily challenge so callers can test it.

func RandomSeed

func RandomSeed() Seed

RandomSeed returns an unpredictable seed.

func (Seed) String

func (s Seed) String() string

String formats the seed for display and sharing.

type Status

type Status int

Status is the overall game state.

const (
	StatusPlaying Status = iota
	StatusWon
	StatusLost
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL