-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLogic.hs
141 lines (104 loc) · 4.54 KB
/
Logic.hs
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
module Logic(createHero, think) where
import Prelude hiding (Either(..))
import qualified Data.Map as M
import Data.Maybe
import Data.List
import Types.World
import Types.Common
import Types.Items
import AI
import Random
import Helpers
-- First time calculation of hero stats
createHero :: World -> String -> Race -> Class -> World
createHero w n r c =
w { wHero = h {
hName = n,
hClass = c,
hRace = r,
hInventory = inventory,
hReputation = reputation,
hSkills = skills,
hCurrEnergy = energy,
hMaxEnergy = energy,
hWield = weapon,
hWear = armor,
eCurrHP = hp,
eMaxHP = hp,
eHitDie = hitDie,
eDamageDie = dmgDie,
eEvadeDie = evdDie,
eMitigation = mitigation,
eSpeed = speed
}
}
where
h = wHero w
inventory = cStartingInventory c
-- todo: experience
reputation = cStartingReputation c
energy =
round $ fromIntegral (cBaseEnergy c) * rEnergyMultiplier r
skills = cStartingSkills c
hp =
round $ fromIntegral (cBaseHP c) * rHPMultiplier r
armor = cStartingArmor c
weapon = cStartingWeapon c
hitDie = (cHitDie c) { dMod = dMod (cHitDie c) + rHitModifier r + wepHitBonus weapon }
evdDie = (cEvadeDie c) { dMod = dMod (cEvadeDie c) + rEvasionModifier r + aEvasion armor}
mitigationMod = cMitigationBonus c + rMitigationModifier r
damageMod = cDamageBonus c + rDamageModifier r
dmgDie = (wepDamageDie weapon) { dMod = dMod (wepDamageDie weapon) + damageMod}
mitigation = mitigationMod + aMitigation armor
speed =
round $ fromIntegral (cBaseSpeed c) * rSpeedMultiplier r
-- Finds which entities whose turns are up, performs AI, those entities whose turns are not up have updated their eNextMove values. Returns a new World with these changes.
think :: World -> IO World
think world =
return world''
where
b = wBoss world
h = wHero world
lvl = wLevel world
e = b:h:getEntitiesFromViewFrame world (getViewFrame world) -- every entity in view
e' = prepare e -- subtracts the lowest eNextMove value from every entity,
-- always yielding 1 with 0.
h' = fromJust $ find (\x -> case x of -- find to not have to iterate through the whole thing, fromJust is safe because the hero was added to e.
Hero { } -> True -- Crashing is a good idea if hero can't be found in e'
_ -> False
) e'
b' = fromJust $ find (\x -> case x of
Boss { } -> True
_ -> False
) e'
-- feed boss every entity that has been skipped.
(skippedEnts, deletedSkippedMap) = getAndDeleteSkippedEntities world $ getViewFrame world
-- eat skipped entities, move forward boss if it is his turn.
bossWorld = bossAI skippedEnts $ world { wBoss = b'}
e'' = filter (\x -> eNextMove x == 0) e' -- the monsters whose turns are up!
-- monsters whose turns are now
monstersAI = filter monsterFilter e''
-- monsters whose turns are not up yet.
monstersWAIT = ((e' \\ [b']) \\[h']) \\ monstersAI
monsterFilter :: Entity -> Bool
monsterFilter x = case x of
Monster {} -> True
_ -> False
-- update the map for monsters whose turns are not yet up!
emap = foldl' (\map m -> updateMap (eCurrPos m) m map) deletedSkippedMap monstersWAIT
-- update map for monsters whose turns are up
monsters' = map (\m -> m {eNextMove = eSpeed m}) monstersAI
emap' = foldl' (\map m -> updateMap (eCurrPos m) m map) emap monsters'
world' = bossWorld { wLevel = lvl {lEntities = emap' }, wHero = h'}
-- perform AI.
world'' = foldl' (flip performAI) world' monsters'
-- find the lowest timeRemaining, subtract it from all.
prepare :: [Entity] -> [Entity]
prepare entities = map (\x -> x { eNextMove = eNextMove x - lowestRemaining }) entities
where
-- 10000 is infinite in this case.
lowestRemaining = eNextMove $ foldl1' (\x y ->
if eNextMove x > eNextMove y
then y
else x
) entities