package snake /** A grid cell. Two points with the same `x` and `y` are `==` (case classes compare structurally). */ final case class Point(x: Int, y: Int) enum Direction: case Up, Down, Left, Right enum Status: case Playing, Paused, GameOver, Won /** Everything that can happen to the game, as data. */ enum Action: case Tick case Turn(dir: Direction) case TogglePause case Restart case Frame /** The whole game. `snake` is head first; `seed` is the unsigned 32-bit random seed (0 until 2^32). */ final case class GameState( width: Int, height: Int, snake: List[Point], dir: Direction, nextDir: Direction, apple: Option[Point], seed: Long, score: Int, status: Status, frame: Int ) /** m02 model: the data the whole game is built from. Case classes and enums are immutable. */ object Model: def delta(dir: Direction): Point = dir match case Direction.Up => Point(0, -1) case Direction.Down => Point(0, 1) case Direction.Left => Point(-1, 0) case Direction.Right => Point(1, 0) def opposite(dir: Direction): Direction = dir match case Direction.Up => Direction.Down case Direction.Down => Direction.Up case Direction.Left => Direction.Right case Direction.Right => Direction.Left def initialState(seed: Long): GameState = GameState( width = 20, height = 20, snake = List(Point(10, 10), Point(9, 10), Point(8, 10)), dir = Direction.Right, nextDir = Direction.Right, apple = None, seed = seed, score = 0, status = Status.Playing, frame = 0 )