2019-12-05 18:17:05 +01:00
|
|
|
module Board
|
|
|
|
|
2019-12-06 10:51:27 +01:00
|
|
|
module Side =
|
2019-12-09 10:44:05 +01:00
|
|
|
open Card.Card
|
2019-12-05 18:17:05 +01:00
|
|
|
|
2019-12-09 10:44:05 +01:00
|
|
|
type Side<'s> =
|
|
|
|
{ field: CardInstance<'s> option
|
|
|
|
monsters: CardInstance<'s> list
|
|
|
|
spells: CardInstance<'s> list
|
|
|
|
graveyard: CardInstance<'s> list
|
|
|
|
deck: CardInstance<'s> list }
|
2019-12-05 18:25:03 +01:00
|
|
|
|
2019-12-06 10:51:27 +01:00
|
|
|
let emptySide =
|
|
|
|
{ field = None
|
|
|
|
monsters = []
|
|
|
|
spells = []
|
|
|
|
graveyard = []
|
|
|
|
deck = [] }
|
|
|
|
|
|
|
|
|
|
|
|
module Player =
|
|
|
|
open Side
|
2019-12-09 10:44:05 +01:00
|
|
|
open Card.Card
|
2019-12-06 10:51:27 +01:00
|
|
|
|
2019-12-07 18:56:20 +01:00
|
|
|
type PlayerState =
|
|
|
|
| InGame
|
|
|
|
| Won
|
|
|
|
| Lost of reason: string
|
|
|
|
|
2019-12-09 10:44:05 +01:00
|
|
|
type Player<'s> =
|
2019-12-06 10:51:27 +01:00
|
|
|
{ lifePoints: int
|
2019-12-09 10:44:05 +01:00
|
|
|
side: Side<'s>
|
|
|
|
hand: CardInstance<'s> list
|
2019-12-07 18:56:20 +01:00
|
|
|
state: PlayerState }
|
2019-12-06 10:51:27 +01:00
|
|
|
|
|
|
|
let initialPlayer lp =
|
|
|
|
{ lifePoints = lp
|
2019-12-07 18:31:53 +01:00
|
|
|
side = emptySide
|
2019-12-07 18:56:20 +01:00
|
|
|
hand = []
|
|
|
|
state = InGame }
|
2019-12-06 10:51:27 +01:00
|
|
|
|
2019-12-09 10:44:05 +01:00
|
|
|
// module Side =
|
|
|
|
|
2019-12-07 18:31:53 +01:00
|
|
|
module Turn =
|
|
|
|
type Phase =
|
|
|
|
| Draw
|
|
|
|
| Standby
|
|
|
|
| Main1
|
|
|
|
| Battle
|
|
|
|
| Main2
|
|
|
|
| End
|
2019-12-06 10:51:27 +01:00
|
|
|
|
2019-12-07 18:31:53 +01:00
|
|
|
let nextPhase (previous: Phase) (turn: int) =
|
|
|
|
match previous with
|
|
|
|
| Draw -> (Standby, turn)
|
|
|
|
| Standby -> (Main1, turn)
|
|
|
|
| Main1 -> (Battle, turn)
|
|
|
|
| Battle -> (Main2, turn)
|
|
|
|
| Main2 -> (End, turn)
|
|
|
|
| End -> (Draw, turn + 1)
|
2019-12-06 10:51:27 +01:00
|
|
|
|
|
|
|
module Board =
|
2019-12-07 18:31:53 +01:00
|
|
|
open Turn
|
2019-12-09 10:44:05 +01:00
|
|
|
open Card
|
2019-12-06 10:51:27 +01:00
|
|
|
|
2019-12-09 10:44:05 +01:00
|
|
|
type Player = Player.Player<Board>
|
|
|
|
|
|
|
|
and Board =
|
2019-12-07 18:31:53 +01:00
|
|
|
{ players: Player * Player
|
|
|
|
turn: int
|
|
|
|
phase: Phase }
|
|
|
|
|
2019-12-09 10:44:05 +01:00
|
|
|
type Card = Card.Card<Board>
|
|
|
|
|
|
|
|
type CardInstance = Card.CardInstance<Board>
|
|
|
|
|
|
|
|
type Effect = Effect.Effect<Board>
|
|
|
|
|
|
|
|
type Condition = Effect.Condition<Board>
|
|
|
|
|
|
|
|
type Action = Effect.Action<Board>
|
|
|
|
|
2019-12-07 18:31:53 +01:00
|
|
|
let emptyBoard =
|
2019-12-09 10:44:05 +01:00
|
|
|
{ players = (Player.initialPlayer 8000, Player.initialPlayer 8000)
|
2019-12-07 18:31:53 +01:00
|
|
|
turn = 0
|
2019-12-09 10:44:05 +01:00
|
|
|
phase = Draw }
|
2019-12-07 18:31:53 +01:00
|
|
|
|
|
|
|
module Game =
|
|
|
|
open Board
|
|
|
|
open Turn
|
|
|
|
open Player
|
2019-12-09 10:44:05 +01:00
|
|
|
|
|
|
|
type PlayerAction =
|
|
|
|
| Pass
|
|
|
|
| NormalSummon
|
|
|
|
| InitialDraw
|
|
|
|
| Activate
|
|
|
|
| Set
|
|
|
|
|
|
|
|
// let canDoInitialDraw (board: Board) =
|
|
|
|
|
2019-12-07 18:31:53 +01:00
|
|
|
|
|
|
|
let draw (player: Player) =
|
|
|
|
match player.side.deck with
|
2019-12-07 18:56:20 +01:00
|
|
|
| [] -> { player with state = Lost "deckout" }
|
2019-12-07 18:31:53 +01:00
|
|
|
| card :: deck ->
|
|
|
|
{ player with
|
|
|
|
hand = card :: player.hand
|
|
|
|
side = { player.side with deck = deck } }
|
|
|
|
|
|
|
|
// Player is the last arg to be able to use this with the withCurrentPlayer function
|
|
|
|
let toDeckBottom (card: CardInstance) (player: Player) =
|
|
|
|
{ player with side = { player.side with deck = card :: player.side.deck } }
|
|
|
|
|
|
|
|
let currentPlayer (board: Board) =
|
|
|
|
let (first, second) = board.players
|
|
|
|
|
|
|
|
if board.turn % 2 = 0 then first
|
|
|
|
else second
|
|
|
|
|
|
|
|
let withCurrentPlayer callback board =
|
|
|
|
let (first, second) = board.players
|
|
|
|
|
|
|
|
let players =
|
|
|
|
if board.turn % 2 = 0 then (callback first, second)
|
|
|
|
else (first, callback second)
|
|
|
|
|
|
|
|
{ board with players = players }
|
|
|
|
|
|
|
|
|
|
|
|
let processTurn (board: Board) =
|
|
|
|
match board.phase with
|
|
|
|
| Draw -> withCurrentPlayer draw board
|
|
|
|
| _ -> board
|
|
|
|
|
|
|
|
let doTurn (board: Board) =
|
|
|
|
let newBoard = processTurn board
|
|
|
|
let (phase, turn) = nextPhase newBoard.phase newBoard.turn
|
2019-12-06 10:51:27 +01:00
|
|
|
|
2019-12-07 18:31:53 +01:00
|
|
|
{ newBoard with
|
|
|
|
turn = turn
|
|
|
|
phase = phase }
|