-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCategories.hs
157 lines (126 loc) · 4.22 KB
/
Categories.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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
module Categories where
import Control.Monad
import Data.Char
import Defs
{-
There are six categories of things visible to the player, and, hence, the
parser. They are:
1. The player
2. The player's inventory
3. The room
4. The room's contents, excluding the player
5. Things in containers (in the room or inventory)
6. Exits of the room
This file is about generating and distinguishing (1-6) and has actions to
stop when handling the wrong category of Ref.
-}
-- getPlayer is in Defs.hs
getInventory :: Game [Ref]
getInventory = do
player <- getPlayer
getContents' player
getRoom :: Game Ref
getRoom = do
player <- getPlayer
maybeRoom <- getLocation player
case maybeRoom of
Nothing -> error "Internal error: player has no location"
Just room -> return room
-- Excludes player
getRoomContents :: Game [Ref]
getRoomContents = do
room <- getRoom
player <- getPlayer
contents <- getContents' room
return $ filter (/= player) contents
-- helper function: get all unlocked containers in inventory or room
getOpenContainers :: Game [Ref]
getOpenContainers = do
inventory <- getInventory
roomContents <- getRoomContents
containers <- filterM getIsContainer (inventory ++ roomContents)
filterM getIsUnlocked containers
getThingsInOpenContainers :: Game [Ref]
getThingsInOpenContainers = do
openContainers <- getOpenContainers
contents <- mapM getContents' openContainers
return $ concat contents
getRoomExits :: Game [Ref]
getRoomExits = do
room <- getRoom
getExits room
-- Predicates for distinguishing among categories 1-6
isPlayer :: Ref -> Game Bool
isPlayer ref = (== ref) <$> getPlayer
isInInventory :: Ref -> Game Bool
isInInventory ref = elem ref <$> getInventory
isRoom :: Ref -> Game Bool
isRoom ref = (== ref) <$> getRoom
-- Excludes player
isInRoom :: Ref -> Game Bool
isInRoom ref = elem ref <$> getRoomContents
isInOpenContainer :: Ref -> Game Bool
isInOpenContainer ref = elem ref <$> getThingsInOpenContainers
isExit :: Ref -> Game Bool
isExit ref = elem ref <$> getRoomExits
-- Stop functions for use in doVerb
stopIfPlayer :: String -> Ref -> Game ()
stopIfPlayer verb ref = do
flag <- isPlayer ref
-- name <- qualifiedName ref
when flag $ stop $ "You can\'t " ++ verb ++ " yourself."
stopIfInInventory :: String -> Ref -> Game ()
stopIfInInventory verb ref = do
flag <- isInInventory ref
-- name <- qualifiedName ref
when flag $ stop $ "You can\'t " ++ verb ++ " something you are holding."
stopIfRoom :: String -> Ref -> Game ()
stopIfRoom verb ref = do
flag <- isRoom ref
name <- qualifiedName ref
when flag $ stop $ "You can\'t " ++ verb ++ " " ++ name ++ "."
stopIfInRoom :: String -> Ref -> Game ()
stopIfInRoom verb ref = do
flag <- isInRoom ref
-- name <- qualifiedName ref
when flag $ stop $ "You can\'t " ++ verb ++ " an object in your room."
stopIfInOpenContainer :: String -> Ref -> Game ()
stopIfInOpenContainer verb ref = do
flag <- isInOpenContainer ref
-- name <- qualifiedName ref
when flag $ stop $ "You can\'t " ++ verb ++ " something in a container."
stopIfExit :: String -> Ref -> Game ()
stopIfExit verb ref = do
flag <- isExit ref
name <- qualifiedName ref
when flag $ stop $ "You can\'t " ++ verb ++ " " ++ name ++ ", which is " ++
"a way to go."
-- Additional stop functions
stopIfNotOpenContainer :: Ref -> Game ()
stopIfNotOpenContainer ref = do
name <- qualifiedName ref
container <- getIsContainer ref
unless container $ stop $ capitalize name ++ " is not a container."
unlocked <- getIsUnlocked ref
unless unlocked $ stop $ capitalize name ++ " is locked."
stopIfNotObject :: String -> Ref -> Game ()
stopIfNotObject verb ref = do
stopIfPlayer verb ref
stopIfRoom verb ref
stopIfExit verb ref
stopIfNotInInventory :: String -> Ref -> Game ()
stopIfNotInInventory verb ref = do
stopIfNotObject verb ref
inRoom <- isInRoom ref
inContainer <- isInOpenContainer ref
name <- qualifiedName ref
when (inRoom || inContainer) $ stop $
"You need to hold onto " ++ name ++ " first."
stopIfNotAccessible :: String -> Ref -> Game ()
stopIfNotAccessible verb ref = do
stopIfNotObject verb ref
stopIfInOpenContainer verb ref
-- Utility functions
capitalize :: String -> String
capitalize "" = ""
capitalize (c:cs) = toUpper c : cs