/// m11 pong model: the same ideas as the snake model, for a different game. module Snake.Pong.Model open Snake.Model /// The ball's direction of travel, one cell per frame on each axis. type Velocity = { Dx: int; Dy: int } /// Which of the player's two keys are being held down right now. type Held = { Up: bool; Down: bool } type Score = { Player: int; Cpu: int } // RequireQualifiedAccess: write `PongStatus.Playing`, `Paddle.Up`, `PongAction.Frame`, so these cases never get // mixed up with the snake's `Playing`, `Up` and `Frame`. [] type PongStatus = | Playing | Over /// The two keys that move the player's paddle. [] type Paddle = | Up | Down /// A whole match. Positions are in cells: `Ball` is a cell of the 80x50 court; `Player` and `Cpu` are the y of the /// top cell of each paddle. `Seed` is the unsigned 32-bit random seed used to pick the direction of each serve. type PongState = { Ball: Point Vel: Velocity Player: int Cpu: int Held: Held Score: Score Status: PongStatus Seed: uint32 Frame: int } /// Everything that can happen in a match, as data. [] type PongAction = | Press of Paddle | Release of Paddle | Frame | Restart // The court, in cells. let W = 80 let H = 50 /// Pixels per cell. let PCELL = 8 /// Paddle height in cells. let PADDLE = 8 /// Column of the player's paddle (left) and of the cpu's paddle (right). let PLAYER_X = 2 let CPU_X = 77 /// Points needed to win the match. let WIN = 5 /// A fresh match: ball at (40, 25) moving `{ Dx = 1; Dy = 1 }`, both paddles at y 21, no keys held, /// score 0 to 0, status Playing, the given seed, frame 0. /// (Hint: PongState also has `Player` and `Cpu` fields, so write the score as `{ Score.Player = 0; Cpu = 0 }`.) let initialPong (seed: uint32) : PongState = failwith "TODO m11"