forked from graninas/Adv2Game
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Objects.hs
188 lines (152 loc) · 8.41 KB
/
Objects.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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
module Objects where
import Types
import Tools
import Text.Printf(printf)
import qualified Data.List as L
--- Data functions ---
homePhone1 = Object "Digital Phone" NoRoom
homePhone2 = Object "Broken Phone" NoRoom
homeTable = Object "Table" NoRoom
homeUmbrella1 = Object "Red Umbrella" NoRoom
homeUmbrella2 = Object "Blue Umbrella" NoRoom
rope = Object "Rope" NoRoom
homeHook = Object "Hook" NoRoom
ropeOnHook = Complex "Rope on hook" rope homeHook NoRoom
homeLighter = Object "Lighter" NoRoom
homeDiary = Object "Diary" NoRoom
homeDrawer = Container "Drawer" Closed [homeDiary, homeLighter] NoRoom
bag = Container "Bag" Opened [] InventoryRoom
objectDescription' :: Object -> String
objectDescription' obj | obj == homeUmbrella1 = "Nice red mechanic Umbrella."
| obj == homeUmbrella2 = "Nice blue Umbrella."
| obj == homePhone1 = "The Phone has some voice messages for you."
| obj == homePhone2 = "Broken electric phone."
| obj == rope = "Good 30 meters rope."
| obj == homeHook = "Massive steel hook nailed to wall."
| obj == homeTable = "Good wooden table with drawer."
| obj == homeDiary = "Your diary."
| obj == ropeOnHook = "Rope on hook looks tight."
| otherwise = printf "There is nothing special about %s." (showObject obj)
objectPickupFailMessage' :: Object -> String
objectPickupFailMessage' obj | obj == homePhone1 = "Phone drawes a wires and strikes against the table!"
| otherwise = printf "You can't take a %s." (showObject obj)
isPickupable :: Object -> Bool
isPickupable obj = obj `elem` [homeUmbrella1, rope]
wld1 (obj1:obj2:[]) | obj1 == rope && obj2 == homeHook = Just (ropeOnHook, "You successfully tied rope to the hook.")
wld1 _ = Nothing
welders :: [Welder]
welders = [wld1]
(<|>) :: Welder -> Welder -> Welder
w1 <|> w2 = \os -> let perm = L.permutations os in
case filter (/= Nothing) (map w1 perm) of
[] -> case filter (/= Nothing) (map w2 perm) of
[] -> Nothing
(x:_) -> x
(y:_) -> y
----------------------
isContainer :: Object -> Bool
isContainer (Container _ _ _ _) = True
isContainer _ = False
readObject' :: [String] -> [String] -> Bool
readObject' [] _ = False
readObject' _ [] = False
readObject' (x:xs) oNs = (any (== x) oNs) || readObject' xs oNs
readObject :: String -> Objects -> Objects
readObject [] _ = []
readObject _ [] = []
readObject str (o:os) = case readObject' (words str) ((words . objectName) o) of
True -> o : readObject str os
False -> readObject str os
-- Ôóíêöèÿ ýêâèâàëåíòíîñòè. Ïîçâîëÿåò ñðàâíèâàòü îáúåêòû ïî èõ ÷àñòè÷íîìó ñîâïàäåíèþ.
(=|=) :: Object -> Object -> Bool
Complex _ x1 x2 _ =|= o@(Object _ _) = x1 == o || x2 == o
o@(Object _ _) =|= Complex _ y1 y2 _ = y1 == o || y2 == o
x =|= y = x == y
matchedObjects :: Object -> Objects -> Objects
matchedObjects _ [] = []
matchedObjects obj objects = filter (=|= obj) objects
replaceObject :: Object -> Objects -> Objects
replaceObject obj objects = obj : [newObj | newObj <- objects, newObj /= obj]
replaceObjectList :: Objects -> Objects -> Objects
replaceObjectList [] _ = []
replaceObjectList _ [] = []
replaceObjectList (n:ns) objects = replaceObjectList ns (replaceObject n objects)
pickup :: Object -> (Maybe Object, String)
pickup obj | objectRoom obj == InventoryRoom = (Nothing, objectAlreadyInInventoryError obj)
| otherwise = case isPickupable obj of
True -> (Just (obj {objectRoom = InventoryRoom}), successPickupingObjectMsg obj)
False -> (Nothing, failurePickupingObjectMsg obj)
weld :: Object -> Object -> MaybeWeldedObject
weld o1 o2 = (foldr1 (<|>) welders) [o1, o2]
roomObjects :: Room -> Objects -> [Object]
roomObjects room = filter (\x -> objectRoom x == room)
----------- Messages, Errors ------------
-- f :: Object -> String
notVisibleObjectError obj = printf "You don't see any %s here." (showObject obj)
cannotBeOpenedError obj = printf "The %s cannot be opened." (showObject obj)
cannotBeClosedError obj = printf "The %s cannot be closed." (showObject obj)
alreadyOpenError obj = printf "%s already opened." (showObject obj)
alreadyCloseError obj = printf "%s already closed." (showObject obj)
successPickupingObjectMsg obj = printf "%s added to your inventory." (showObject obj)
failurePickupingObjectMsg = objectPickupFailMessage'
objectAlreadyInInventoryError obj = printf "You already have a %s." (showObject obj)
failureWeldObjectsError o1 o2 = printf "You can't weld %s to %s." (showObject o1) (showObject o2)
successOpeningObjectMsg :: Object -> Objects -> String
successOpeningObjectMsg obj [] = "Opened."
successOpeningObjectMsg obj (o:[]) = printf "Opening %s reveals %s." (showObject obj) (showObject o)
successOpeningObjectMsg obj os = describeObjects (printf "Opening %s reveals some objects: " (showObject obj)) os
instance Openable Object where
open obj@(Container _ Opened _ _) = (Nothing, alreadyOpenError obj)
open obj@(Container _ Closed _ _) = (Just $ obj {objectContainerState = Opened}, successOpeningObjectMsg obj (objectContents obj))
open obj = (Nothing, cannotBeOpenedError obj)
close obj@(Container _ Opened _ _) = (Just $ obj {objectContainerState = Closed}, "Closed.")
close obj@(Container _ Closed _ _) = (Nothing, alreadyCloseError obj)
close obj = (Nothing, cannotBeClosedError obj)
showStated obj@(Container _ Opened _ _) = "(opened) " ++ showObject obj
showStated obj = showObject obj
showContents obj@(Container _ Opened cont@(x:xs) _) = describeObjects (printf "\nThe %s contains " (showObject obj)) cont
showContents _ = []
instance Eq Object where
o1 == o2 = objectName o1 == objectName o2
----------------------- Ôóíêöèè îòîáðàæåíèÿ îáúåêòà è ñïèñêà îáúåêòîâ. ---------------------------
type ObjectShowPrefix = (String, String)
type IntroString = String
type ShowObjectsFunc = ((Object -> Int -> String), (Int -> Int), Int)
type ShowObjectsBoundStrings = [String]
-- Âñïîìîãàòåëüíûå ôóíêöèè
showLeftBracket :: ShowObjectsBoundStrings -> String
showRightBracket :: ShowObjectsBoundStrings -> String
showDelimiter :: ShowObjectsBoundStrings -> String
showLeftBracket = head
showRightBracket = head . tail
showDelimiter = last
standartObjectShowingF :: ShowObjectsFunc
standartObjectShowingF = ((\x _ -> showStated x), \_ -> 0, 0)
standartBoundStrs :: ShowObjectsBoundStrings
standartBoundStrs = ["[", "].", ", "]
-- Âûâîäèò èíôîðìàöèþ îá îáúåêòå. Íå ïåðåêðûâàåò show, ÷òîáû îñòàâèòü âîçìîæíîñòü ñîõðàíÿòü äàííûå íà äèñê.
showObject :: Object -> String
showObject = objectName
applyObjectShowingF :: ShowObjectsFunc -> Object -> String
applyObjectShowingF (showingLambda, _, enumVal) obj = showingLambda obj enumVal
modifyObjectShowingF :: ShowObjectsFunc -> ShowObjectsFunc
modifyObjectShowingF (showingLambda, enumChangeF, enumVal) = (showingLambda, enumChangeF, enumChangeF enumVal)
showObjects :: ObjectShowPrefix -> ShowObjectsFunc -> ShowObjectsBoundStrings -> Objects -> String
showObjects pref _ _ [] = fst pref
showObjects pref lFuncDescr boundStrs xs = snd pref ++ (showLeftBracket boundStrs) ++ showObjects' xs lFuncDescr
where
showObjects' (x:[]) lFuncDescr = applyObjectShowingF lFuncDescr x ++ (showRightBracket boundStrs)
showObjects' (x:xs) lFuncDescr = applyObjectShowingF lFuncDescr x ++ (showDelimiter boundStrs) ++ showObjects' xs (modifyObjectShowingF lFuncDescr)
-- Ïåðå÷èñëÿåò îáúåêòû â âèäå [ñïèñêà]. Åñëè íå ïåðåäàíà ñòðîêà Intro, áóäåò ïîäñòàâëåíà ñòðîêà ïî óìîë÷àíèþ.
describeObjects :: IntroString -> Objects -> String
describeObjects [] os = (showObjects ([], "\nThere are some objects here: ") standartObjectShowingF standartBoundStrs os) ++ unwords(map showContents os)
describeObjects str os = (showObjects ([], str) standartObjectShowingF standartBoundStrs os) ++ unwords(map showContents os)
-- Ïîêàçûâàåò îñîáûå ñâîéñòâà îáúåêòîâ (åñëè îíè åñòü).
investigateObjects :: IntroString -> Objects -> String
investigateObjects str = showObjects ([], str) ((\x _ -> printf "\n%s: %s" (showObject x) (objectDescription' x)), \_ -> 0, 0) ["","",""]
-- Ïåðå÷èñëÿåò îáúåêòû èíâåíòàðÿ â âèäå [ñïèñêà]. Åñëè èíâåíòàðü ïóñò, òàê è ñîîáùàåò.
showInventory :: Objects -> String
showInventory os = showObjects ("No objects in your inventory.", "You have: ") standartObjectShowingF standartBoundStrs os
-- Ïåðå÷èñëÿåò îáúåêòû â âèäå ïðîíóìåðîâàííîãî ñïèñêà, íà÷èíàþùåãîñÿ ñ 0.
enumerateObjects :: IntroString -> Objects -> String
enumerateObjects str = showObjects ([], str) ((\x n -> printf "\n%d: %s" n (showObject x)), \y -> y + 1, 0) ["","",""]