feat(fsharp): m01-m06 util, model, rules, random, spawn, game, view with Expecto tests
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
183821737e
commit
9cbefeb2be
@@ -0,0 +1,38 @@
|
||||
/// m05 game: one `update` turns every action into a new state; replaying a game is a fold over its actions.
|
||||
/// m10 adds pause, restart and a frame clock that speeds up as the score grows.
|
||||
module Snake.Game
|
||||
|
||||
open Snake.Model
|
||||
|
||||
/// How many frames pass between game steps: 8 at first, one fewer every 3 points, never fewer than 2.
|
||||
let movesEvery (score: int) : int = max 2 (8 - score / 3)
|
||||
|
||||
// One animation frame: count it, and every `movesEvery score`-th frame run a game step.
|
||||
let private frame (state: GameState) : GameState =
|
||||
if state.Status <> Playing then
|
||||
state
|
||||
else
|
||||
let counted = { state with Frame = state.Frame + 1 }
|
||||
if counted.Frame % movesEvery counted.Score = 0 then Spawn.tick counted else counted
|
||||
|
||||
// Pause and resume only make sense in those two statuses; a finished game stays finished.
|
||||
let private togglePause (state: GameState) : GameState =
|
||||
match state.Status with
|
||||
| Playing -> { state with Status = Paused }
|
||||
| Paused -> { state with Status = Playing }
|
||||
| GameOver
|
||||
| Won -> state
|
||||
|
||||
// Every case is listed (no `| _ ->`): adding an Action later makes the compiler point here.
|
||||
let update (state: GameState) (action: Action) : GameState =
|
||||
match action with
|
||||
| Tick -> Spawn.tick state
|
||||
| Turn dir -> Rules.turn state dir
|
||||
| TogglePause -> togglePause state
|
||||
| Restart -> Spawn.newGame state.Seed
|
||||
| Frame -> frame state
|
||||
|
||||
let replay (state: GameState) (actions: Action list) : GameState = List.fold update state actions
|
||||
|
||||
// List.scan is List.fold that keeps every intermediate result (the start state included).
|
||||
let history (state: GameState) (actions: Action list) : GameState list = List.scan update state actions
|
||||
Reference in New Issue
Block a user