feat(scala): m09 input/app/runtime and m10 extensions with tests
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
bd0c9fcc0c
commit
c6ecb7c013
13 files changed
+448
-6
No files matched your search
@@ -1,12 +1,34 @@
|
||||
package snake
|
||||
|
||||
/** m05 game: one `update` turns every action into a new state; replaying a game is a fold over its actions. */
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
object Game:
|
||||
|
||||
/** How many frames pass between game steps: 8 at first, one fewer every 3 points, never fewer than 2. */
|
||||
def movesEvery(score: Int): Int = math.max(2, 8 - score / 3)
|
||||
|
||||
// One animation frame: count it, and every `movesEvery(score)`-th frame run a game step.
|
||||
private def frame(state: GameState): GameState =
|
||||
if state.status != Status.Playing then state
|
||||
else
|
||||
val counted = state.copy(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.
|
||||
private def togglePause(state: GameState): GameState = state.status match
|
||||
case Status.Playing => state.copy(status = Status.Paused)
|
||||
case Status.Paused => state.copy(status = Status.Playing)
|
||||
case Status.GameOver | Status.Won => state
|
||||
|
||||
// Every case is listed (no `case _`): adding an Action later makes the compiler point here.
|
||||
def update(state: GameState, action: Action): GameState = action match
|
||||
case Action.Tick => Spawn.tick(state)
|
||||
case Action.Turn(dir) => Rules.turn(state, dir)
|
||||
case _ => state // TogglePause, Restart and Frame arrive in m10
|
||||
case Action.Tick => Spawn.tick(state)
|
||||
case Action.Turn(dir) => Rules.turn(state, dir)
|
||||
case Action.TogglePause => togglePause(state)
|
||||
case Action.Restart => Spawn.newGame(state.seed)
|
||||
case Action.Frame => frame(state)
|
||||
|
||||
def replay(state: GameState, actions: List[Action]): GameState = actions.foldLeft(state)(update)
|
||||
|
||||
|
||||
Reference in new issue
Block a user