-
Notifications
You must be signed in to change notification settings - Fork 2
/
Game.purs
157 lines (128 loc) · 3.95 KB
/
Game.purs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
module Game where
import Prelude
import Game.Lenses as L
import Effect (Effect)
import Effect.Console (log)
import Control.Monad.State (State, get, put)
import Control.Monad.State.Trans (StateT, lift)
import Data.Lens (Lens', Traversal', filtered, over, set, view, (^.))
import Data.Lens.Traversal (traversed)
import Data.Lens.Zoom (zoom)
import Data.List.Lazy (replicateM)
import Data.Profunctor.Choice (class Choice)
import Data.Traversable (for)
import Game.Data (Game(..), GameUnit(..), GamePoint(..))
import Math (pow)
initialState :: Game
initialState = Game
{ score: 0
, units:
[ GameUnit
{ health: 10
, position: GamePoint { x: 3.5, y: 7.0 }
}
, GameUnit
{ health: 15
, position: GamePoint { x: 1.0, y: 1.0 }
}
, GameUnit
{ health: 8
, position: GamePoint { x: 0.0, y: 2.1 }
}
]
, boss: GameUnit
{ health: 100
, position: GamePoint { x: 0.0, y: 0.0 }
}
}
-- Intro (just to warm up ;) ): set | view | over lenses
-- get score
getScore :: State Game Unit
getScore = do
g <- get
let s = view (L._Game <<< L.score) g
--
-- OR using ^. operator
-- g <- get
-- let s = g ^. L._Game <<< L.score
--
-- OR using ^. operatore and deconstructing Game
-- Game g <- get
-- let s = g ^. L.score
pure unit
-- set score
setScore :: State Game Unit
setScore = do
put <<< set (L._Game <<< L.score) 10000 =<< get
pure unit
-- update score
updateScore :: State Game Unit
updateScore = do
put <<< over (L._Game <<< L.score) (_ + 222) =<< get
pure unit
-- Composition
-- update boss' health
strike :: StateT Game Effect Unit
strike = do
lift $ log "*shink*"
put <<< over (L._Game <<< L.boss <<< L._GameUnit <<< L.health) (_ + 33) =<< get
pure unit
-- update boss' health using bossHP
strike' :: StateT Game Effect Unit
strike' = do
lift $ log "*shink*"
put <<< over bossHP (_ + 33) =<< get
pure unit
-- composite lens to get health of boss
bossHP :: Lens' Game Int
bossHP =
L._Game <<< L.boss <<< L._GameUnit <<< L.health
-- Traversal
fireBreath :: StateT Game Effect Unit
fireBreath = do
lift $ log "*srawr*"
put <<< over partyHP (_ - 3) =<< get
pure unit
partyHP :: Traversal' Game Int
partyHP =
L._Game <<< L.units <<< traversed <<< L._GameUnit <<< L.health
fireBreath' :: GamePoint -> StateT Game Effect Unit
fireBreath' target = do
lift $ log "*srawr*"
put <<< over (L._Game <<< L.units <<< traversed <<< (around target 1.0) <<< L._GameUnit <<< L.health) (_ - 3) =<< get
pure unit
around :: forall p. Choice p => GamePoint -> Number -> p GameUnit GameUnit -> p GameUnit GameUnit
around center radius = filtered (\unit ->
(pow (diffX unit center) 2.0) + (pow (diffY unit center) 2.0) < (pow radius 2.0))
where
diffX (GameUnit u) (GamePoint p) =
(u ^. L.position <<< L._GamePoint <<< L.x) - (p ^. L.x)
diffY (GameUnit u) (GamePoint p) =
(u ^. L.position <<< L._GamePoint <<< L.y) - (p ^. L.y)
-- Zooming
partyLoc :: Traversal' Game GamePoint
partyLoc = L._Game <<< L.units <<< traversed <<< L._GameUnit <<< L.position
-- retreat :: StateT Game Effect Identity Unit
retreat :: StateT Game Effect Unit
retreat = do
lift $ log "Retreat!"
zoom (partyLoc <<< L._GamePoint) $
put <<< over L.x (_ + 10.0) <<< over L.y (_ + 10.0) =<< get
pure unit
-- Combining commands
battle :: StateT Game Effect Unit
battle = do
-- Charge!
_ <- for ["Take that!", "and that!", "and that!"] $
\taunt -> do
lift $ log taunt
strike
-- The dragon awakes!
fireBreath' $ GamePoint {x: 0.5, y:1.5}
_ <- replicateM 3 $ do
-- The better part of valor
retreat
-- Boss chases them
zoom (partyLoc <<< L._GamePoint) $
put <<< over L.x (_ + 10.0) <<< over L.y (_ + 10.0) =<< get
pure unit