From 6ea2d7108284758a6641f090f199dbea1ab3a2c4 Mon Sep 17 00:00:00 2001
From: Matei Adriel <rafaeladriel11@gmail.com>
Date: Mon, 9 Dec 2019 11:44:05 +0200
Subject: [PATCH] fsharp(ygosim): feat: added basic effect types

Signed-off-by: prescientmoon <git@moonythm.dev>
---
 fsharp/ygosim/src/Board.fs   |  57 +++++++++----
 fsharp/ygosim/src/Card.fs    | 159 ++++++++++++++++++++---------------
 fsharp/ygosim/src/Program.fs |   4 +-
 3 files changed, 134 insertions(+), 86 deletions(-)

diff --git a/fsharp/ygosim/src/Board.fs b/fsharp/ygosim/src/Board.fs
index fc41fd8..8f44e03 100644
--- a/fsharp/ygosim/src/Board.fs
+++ b/fsharp/ygosim/src/Board.fs
@@ -1,14 +1,14 @@
 module Board
 
 module Side =
-    open Card
+    open Card.Card
 
-    type Side =
-        { field: CardInstance option
-          monsters: CardInstance list
-          spells: CardInstance list
-          graveyard: CardInstance list
-          deck: CardInstance list }
+    type Side<'s> =
+        { field: CardInstance<'s> option
+          monsters: CardInstance<'s> list
+          spells: CardInstance<'s> list
+          graveyard: CardInstance<'s> list
+          deck: CardInstance<'s> list }
 
     let emptySide =
         { field = None
@@ -20,27 +20,27 @@ module Side =
 
 module Player =
     open Side
-    open Card
+    open Card.Card
 
     type PlayerState =
         | InGame
         | Won
         | Lost of reason: string
 
-    type Player =
+    type Player<'s> =
         { lifePoints: int
-          side: Side
-          hand: CardInstance list
+          side: Side<'s>
+          hand: CardInstance<'s> list
           state: PlayerState }
 
-    let inflictDamage (player: Player) amount = { player with lifePoints = player.lifePoints - amount }
-
     let initialPlayer lp =
         { lifePoints = lp
           side = emptySide
           hand = []
           state = InGame }
 
+// module Side =
+
 module Turn =
     type Phase =
         | Draw
@@ -60,24 +60,45 @@ module Turn =
         | End -> (Draw, turn + 1)
 
 module Board =
-    open Player
     open Turn
+    open Card
 
-    type Board =
+    type Player = Player.Player<Board>
+
+    and Board =
         { players: Player * Player
           turn: int
           phase: Phase }
 
+    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>
+
     let emptyBoard =
-        { players = (initialPlayer 8000, initialPlayer 8000)
+        { players = (Player.initialPlayer 8000, Player.initialPlayer 8000)
           turn = 0
-          phase = Turn.Draw }
+          phase = Draw }
 
 module Game =
     open Board
     open Turn
     open Player
-    open Card
+
+    type PlayerAction =
+        | Pass
+        | NormalSummon
+        | InitialDraw
+        | Activate
+        | Set
+
+    // let canDoInitialDraw (board: Board) =
+
 
     let draw (player: Player) =
         match player.side.deck with
diff --git a/fsharp/ygosim/src/Card.fs b/fsharp/ygosim/src/Card.fs
index 87fa4e3..e74cd19 100644
--- a/fsharp/ygosim/src/Card.fs
+++ b/fsharp/ygosim/src/Card.fs
@@ -1,77 +1,104 @@
 module Card
 
-// TODO: actually implement it
-type BaseCard =
-    { name: string
-      text: string }
 
-type SpellCardType =
-    | NormalSpell
-    | Field
-    | Equip
-    | ContinuosSpell
-    | QuickPlay
-    | Ritual
+module Effect =
+    type Condition<'s> = 's -> bool
 
-type TrapCardType =
-    | NormalTrap
-    | Counter
-    | ContinuosTrap
+    type Action<'s> =
+        { condition: Condition<'s>
+          resolution: 's -> 's }
 
-type Attribute =
-    | Dark
-    | Light
-    | Water
-    | Fire
-    | Earth
-    | Wind
-    | Divine
+    type EffectType =
+        | Trigger
+        | Ignition
 
-type Race =
-    | Aqua
-    | Beast
-    | BeastWarrior
-    | Creator
-    | Cyberse
-    | Dinosaur
-    | DivineBeast
-    | Dragon
-    | Fairy
-    | Fiend
-    | Fish
-    | Insect
-    | Machine
-    | Plant
-    | Psychic
-    | Pyro
-    | Reptile
-    | Rock
-    | SeaSerpent
-    | Spellcaster
-    | Thunder
-    | Warrior
-    | WingedBeast
-    | Wyrm
-    | Zombie
-
-type SpellCardDetails =
-    { spellType: SpellCardType }
-
-type TrapCardDetails =
-    { trapType: TrapCardType }
+    type Effect<'s> =
+        { cost: Action<'s>
+          resolve: Action<'s>
+          _type: EffectType }
 
 
-type MonsterCardDetails =
-    { attack: int
-      defense: int
-      attribute: Attribute
-      level: int }
+module Card =
+    open Effect
+
+    type BaseCard<'s> =
+        { name: string
+          text: string
+          effects: Effect<'s> list }
+
+    type SpellCardType =
+        | NormalSpell
+        | Field
+        | Equip
+        | ContinuosSpell
+        | QuickPlay
+        | Ritual
+
+    type TrapCardType =
+        | NormalTrap
+        | Counter
+        | ContinuosTrap
+
+    type Attribute =
+        | Dark
+        | Light
+        | Water
+        | Fire
+        | Earth
+        | Wind
+        | Divine
+
+    type Race =
+        | Aqua
+        | Beast
+        | BeastWarrior
+        | Creator
+        | Cyberse
+        | Dinosaur
+        | DivineBeast
+        | Dragon
+        | Fairy
+        | Fiend
+        | Fish
+        | Insect
+        | Machine
+        | Plant
+        | Psychic
+        | Pyro
+        | Reptile
+        | Rock
+        | SeaSerpent
+        | Spellcaster
+        | Thunder
+        | Warrior
+        | WingedBeast
+        | Wyrm
+        | Zombie
+
+    type SpellCardDetails =
+        { spellType: SpellCardType }
+
+    type TrapCardDetails =
+        { trapType: TrapCardType }
 
 
-type Card =
-    | Monster of BaseCard * MonsterCardDetails
-    | Spell of BaseCard * SpellCardDetails
-    | Trap of BaseCard * TrapCardDetails
+    type MonsterCardDetails =
+        { attack: int
+          defense: int
+          attribute: Attribute
+          level: int }
 
-// TODO: actually make this do what its supposed to
-type CardInstance = Card
+
+    type Card<'s> =
+        | Monster of BaseCard<'s> * MonsterCardDetails
+        | Spell of BaseCard<'s> * SpellCardDetails
+        | Trap of BaseCard<'s> * TrapCardDetails
+
+    // TODO: actually make this do what its supposed to
+    type CardInstance<'s> = Card<'s>
+
+module Decklist =
+    type Decklist =
+        { main: int list
+          side: int list
+          extra: int list }
diff --git a/fsharp/ygosim/src/Program.fs b/fsharp/ygosim/src/Program.fs
index d0faa42..55c7546 100644
--- a/fsharp/ygosim/src/Program.fs
+++ b/fsharp/ygosim/src/Program.fs
@@ -4,9 +4,9 @@
     open Game
 
     [<EntryPoint>]
-    let main argv =
+    let main _ =
         let board = Board.emptyBoard
-        let sampleCard = Spell ({name= "sampleCard"; text="something"}, {spellType = Card.ContinuosSpell})
+        let sampleCard = Card.Spell ({name= "sampleCard"; text="something"; effects = []}, {spellType = Card.ContinuosSpell})
 
         let secondBoard = withCurrentPlayer <| Game.toDeckBottom sampleCard <| board