-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathChoices.hs
134 lines (127 loc) · 6.17 KB
/
Choices.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
{-# LANGUAGE TupleSections #-}
module LoneWolf.Choices where
import Control.Lens
import Data.List
import LoneWolf.Character
import LoneWolf.Chapter
import LoneWolf.Rules (check, updateSimple)
import qualified LoneWolf.Cartwheel
importantItem :: Item -> CharacterConstant -> CharacterVariable -> Bool
importantItem i cconstant cvariable =
case i of
Weapon Sommerswerd -> True
Weapon MagicSpear -> True
Weapon w -> case usedWeapon cconstant cvariable of
WithSkill _ -> False
NoWeapon -> True
WithoutSkill _ -> WeaponSkill w `elem` cconstant ^. discipline
_ -> True
data CanTake = SpaceAvailable
| Mustdrop [Item]
| Nope
deriving (Show, Eq)
canTake :: Item -> CharacterConstant -> CharacterVariable -> CanTake
canTake item cconstant cvariable =
case itemSlot item of
BackpackSlot | itemsInBackpack > 8 -> error "canTake: too many items in backpack"
| itemsInBackpack == 8 -> Mustdrop (map fst backpackItems)
| otherwise -> SpaceAvailable
WeaponSlot -> case weapons of
[] -> SpaceAvailable
[_] -> SpaceAvailable
lst -> Mustdrop $ map Weapon $ case usedWeapon cconstant cvariable of
WithSkill w -> filter (/= w) lst
WithoutSkill Sommerswerd -> filter (/= Sommerswerd) lst
_ -> lst
PouchSlot -> SpaceAvailable
SpecialSlot -> if hasItem item inventory
then Nope
else SpaceAvailable
where
inventory = cvariable ^. equipment
weapons = getWeapons inventory
backpackItems = filter ( (== BackpackSlot) . itemSlot . fst ) (items inventory)
itemsInBackpack = sum (map snd backpackItems)
flattenDecision :: CharacterConstant -> CharacterVariable -> Decision -> [([String], ChapterOutcome)]
flattenDecision cconstant cvariable d =
let inventory = cvariable ^. equipment
takeItem item = withEffects [GainItem item 1]
withEffects effects nxt = do
let nvariable = foldl' (updateSimple cconstant) cvariable effects
(dsc, o) <- flattenDecision cconstant nvariable nxt
return ( show effects : dsc, Simple effects o)
in case d of
AfterCombat nxt
| hasItem HealingPotion inventory && missingHp >= 4
-> nopotion ++ withEffects [HealPlayer 4, LoseItem HealingPotion 1] nxt
| hasItem PotentPotion inventory && missingHp >= 5
-> nopotion ++ withEffects [HealPlayer 5, LoseItem PotentPotion 1] nxt
| otherwise -> nopotion
where
nopotion = flattenDecision cconstant cvariable nxt
missingHp = cconstant ^. maxendurance - cvariable ^. curendurance
Conditional bc d' -> if check cconstant cvariable bc
then flattenDecision cconstant cvariable d'
else []
Special Portholes -> [([], Goto 197)]
Special Cartwheel -> cartwheel (cvariable ^. equipment . gold)
NoDecision o -> [([], o)]
EvadeFight nrounds cid fdetails co -> [ (["no evasion"], Fight fdetails co)
, (["evasion"], Fight (fdetails & fightMod %~ (Timed nrounds (Evaded cid) :)) co)
]
Decisions lst -> do
(desc, d') <- lst
(alldesc, o) <- flattenDecision cconstant cvariable d'
return (desc : alldesc, o)
CanTake item count nxt
| item == Gold
-> withEffects [GainItem Gold count] nxt
| count == 0
-> flattenDecision cconstant cvariable nxt
| otherwise ->
case canTake item cconstant cvariable of
Nope -> notake
SpaceAvailable -> takeItem item nxt'
Mustdrop drops
| not (importantItem item cconstant cvariable) -> notake
| otherwise -> do
itemDropped <- drops
withEffects [LoseItem itemDropped 1, GainItem item 1] nxt'
where
notake = flattenDecision cconstant cvariable nxt
nxt' = CanTake item (count - 1) nxt
Canbuy item price nxt
| cvariable ^. equipment . gold < price
-> nobuy
| not (importantItem item cconstant cvariable)
-> nobuy
| otherwise ->
case canTake item cconstant cvariable of
Nope -> nobuy
SpaceAvailable -> withEffects [LoseItem Gold price, GainItem item 1] nxt
Mustdrop drops -> do
itemDropped <- drops
withEffects [LoseItem Gold price, LoseItem itemDropped 1, GainItem item 1] nxt
where nobuy = flattenDecision cconstant cvariable nxt
Cansell item price nxt
| not (hasItem item inventory)
-> flattenDecision cconstant cvariable nxt
| otherwise -> case usedWeapon cconstant cvariable of
WithSkill w -> if Weapon w == item then nosell else sell
WithoutSkill w -> if Weapon w == item then nosell else sell
_ -> nosell
where nosell = flattenDecision cconstant cvariable nxt
sell = withEffects [GainItem Gold price, LoseItem item 1] nxt
cartwheel :: Price -> [([String], ChapterOutcome)]
cartwheel m
| m == 50 = [([], Goto 186)]
| m == 0 = [([], Goto 169)]
| otherwise = do
target <- [max m 22 .. min 50 (m + 40)]
let desc = "target: " ++ show target
res = do
(newmoney, proba) <- LoneWolf.Cartwheel.solveFor target m
return $ (proba,) $ if newmoney == 0
then GameLost
else Simple [GainItem Gold (newmoney - m)] (Goto 186)
return ([desc], Randomly res)