-
Notifications
You must be signed in to change notification settings - Fork 0
/
GAS.hs
274 lines (218 loc) · 9.22 KB
/
GAS.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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
{-# OPTIONS_GHC -Wall #-}
{-# LANGUAGE MultiParamTypeClasses,
TypeSynonymInstances, FlexibleInstances #-}
module GAS where
import ProblemState
import Debug.Trace(trace)
import qualified Data.Map.Strict as M
{-
Pozițiile tablei de joc, în formă (linie, coloană), unde ambele coordonate
pot fi negative.
-}
type Position = (Int, Int)
{-
Culorile pătratelor și cercurilor.
-}
data Color = Red | Blue | Gray
deriving (Eq, Ord, Show)
{-
Orientările pătratelor și săgeților.
-}
data Heading = North | South | East | West
deriving (Eq, Ord)
instance Show Heading where
show North = "^"
show South = "v"
show East = ">"
show West = "<"
{-
*** TODO ***
Un obiect de pe tabla de joc: pătrat/ cerc/ săgeată.
-}
data Square = CSquare Color Heading deriving (Eq, Ord)
data Circle = CCircle Color deriving (Eq, Ord)
data Arrow = CArrow Heading deriving (Eq, Ord)
data Object = C1 Square | C2 Circle | C3 Arrow deriving (Eq, Ord)
{-
*** TODO ***
Reprezetarea textuală a unui obiect.
-}
--de modificat
instance Show Object where
show (C1 (CSquare square_color square_heading))
| square_color == Red = "R" ++ show square_heading
| square_color == Blue = "B" ++ show square_heading
| otherwise = "G" ++ show square_heading
show (C2 (CCircle circle))
| circle == Red = "r"
| circle == Blue = "b"
| otherwise = "g"
show (C3 (CArrow arrow_heading)) = show arrow_heading
{-
*** TODO ***
Un nivel al jocului.
Recomandăm Data.Map.Strict.
-}
data Level = CLevel (M.Map Position [Object]) deriving (Eq, Ord)
{-
*** TODO ***
Reprezetarea textuală a unui nivel.
-}
findMaxColumn :: [(Int, Int)] -> Int
findMaxColumn [] = -1;
findMaxColumn [(_, _)] = 1;
findMaxColumn xs = (maximum (map snd xs) + 1)
findMaxLine :: [(Int, Int)] -> Int
findMaxLine [] = -1;
findMaxLine [(_, _)] = 1;
findMaxLine xs = (maximum (map fst xs) +1)
findMinColumn :: [(Int, Int)] -> Int
findMinColumn [] = -1;
findMinColumn [(_, _)] = 1;
findMinColumn xs = (minimum (map snd xs))
f x y z = x.y z
findMinLine :: [(Int, Int)] -> Int
findMinLine [] = -1;
findMinLine [(_, _)] = 1;
findMinLine xs = (minimum (map fst xs))
generateMatrixPosition :: Int -> Int -> Int -> Int -> [[(Int, Int)]]
generateMatrixPosition maxColumn maxLine minColum minLine = map (\line -> map (\column -> (line, column)) [minColum..(maxColumn-1)]) [minLine..(maxLine-1)]
printOjects :: [Object] -> String
--printOjects [] = ""
printOjects [(C3 a)] = " " ++ show (C3 a)
printOjects [(C2 a)] = " " ++ show (C2 a)
printOjects [(C1 a)] = show (C1 a) ++ " "
printOjects [(C1 a), (C2 b)] = show (C1 a) ++ show (C2 b)
printOjects [(C1 a), (C3 b)] = show (C1 a) ++ show (C3 b)
makeDecision :: (Int, Int) -> Level -> [(Int, Int)]-> [[(Int, Int)]] -> String
makeDecision (a, b) (CLevel nivel) line wholeMaxtrix =
if(M.member (a, b) nivel) then
if((last line) == (a, b) && (last wholeMaxtrix) == line) then
(printOjects (nivel M.! (a, b)))
else if((last line) == (a, b)) then
(printOjects (nivel M.! (a, b))) ++ "\n"
else
(printOjects (nivel M.! (a, b))) ++ "|"
else
if((last (last wholeMaxtrix)) == (a, b)) then
" "
else if((last line) == (a, b)) then
" \n"
else
" |"
--(makeDecision per (CLevel nivel) line wholeMaxtrix))
instance Show Level where
show (CLevel nivel)
| (length (M.keys nivel)) > 1 = (concat (concat (map (\line -> (map (\per -> (makeDecision per (CLevel nivel) line wholeMaxtrix)) line)) wholeMaxtrix)))
|otherwise = (printOjects (nivel M.! (head (M.keys nivel))))
where
maxLine = findMaxLine (M.keys nivel)
maxColumn = findMaxColumn (M.keys nivel)
minLine = findMinLine (M.keys nivel)
minColumn = findMinColumn (M.keys nivel)
wholeMaxtrix = generateMatrixPosition maxColumn maxLine minColumn minLine
{-
*** TODO ***
Nivelul vid, fără obiecte.
-}
emptyLevel :: Level
emptyLevel = (CLevel M.empty)
{-
*** TODO ***
Adaugă un pătrat cu caracteristicile date la poziția precizată din nivel.
-}
addSquare :: Color -> Heading -> Position -> Level -> Level
addSquare cul dir (a, b) (CLevel nivel) = if (M.notMember (a, b) nivel) then
(CLevel (M.insert (a,b) [(C1 (CSquare cul dir))] nivel))
else
(CLevel (M.insertWith (++) (a,b) [(C1 (CSquare cul dir))] nivel))
{-
*** TODO ***
Adaugă un cerc cu caracteristicile date la poziția precizată din nivel.
-}
addCircle :: Color -> Position -> Level -> Level
addCircle cul (a, b) (CLevel nivel) = (CLevel (M.insert (a,b) [(C2 (CCircle cul))] nivel))
{-
*** TODO ***
Adaugă o săgeată cu caracteristicile date la poziția precizată din nivel.
-}
addArrow :: Heading -> Position -> Level -> Level
addArrow h (a, b) (CLevel nivel) = (CLevel (M.insert (a,b) [(C3 (CArrow h))] nivel))
{-
*** TODO ***
Mută pătratul de la poziția precizată din nivel. Dacă la poziția respectivă
nu se găsește un pătrat, întoarce direct parametrul.
-}
isThereSquare :: [Object] -> Bool
isThereSquare [(C3 _)] = False
isThereSquare [(C2 _)] = False
isThereSquare [(C1 _)] = True
isThereSquare [(C1 _), (C2 _)] = True
isThereSquare [(C1 _), (C3 _)] = True
getInitialDirection :: [Object] -> Object
getInitialDirection [(C1 (CSquare _ heading))] = (C3 (CArrow heading))
getInitialDirection [(C1 _), (C3 a)] = (C3 a)
getInitialDirection [(C1 (CSquare _ heading)), (C2 _)] = (C3 (CArrow heading))
getNextPosition :: Object -> (Int, Int) -> (Int, Int)
getNextPosition (C3 (CArrow heading)) (a, b)
|heading == North = (a-1, b)
|heading == East = (a, b+1)
|heading == West = (a, b-1)
|otherwise = (a+1, b)
getNewSquare :: Object -> [Object] -> Object
getNewSquare (C1 a) [(C1 _)] = (C1 a)
getNewSquare (C1 a) [(C1 _), (C2 _)] = (C1 a)
getNewSquare (C1 (CSquare col _)) [(C1 _), (C3 (CArrow heading))] = (C1 (CSquare col heading))
getNewSquare (C1 (CSquare col _)) [(C3 (CArrow heading))] = (C1 (CSquare col heading))
getNewSquare (C1 (CSquare col h)) [(C2 _)] = (C1 (CSquare col h))
deleteSquare :: [Object]-> (Int, Int) -> Level -> Level
deleteSquare [(C2 _)] _ nivel = nivel
deleteSquare [(C3 _)] _ nivel = nivel
deleteSquare [(C1 _)] (a, b) (CLevel nivel) = (CLevel (M.delete (a, b) nivel))
deleteSquare [(C1 _), (C2 (CCircle col))] (a, b) (CLevel nivel) = addCircle col (a, b) (CLevel (M.delete (a, b) nivel))
deleteSquare [(C1 _), (C3 (CArrow heading))] (a, b) (CLevel nivel) = addArrow heading (a, b) (CLevel (M.delete (a, b) nivel))
moveSquare :: Object -> (Int, Int) -> Object -> Level -> Level
moveSquare (C1 (CSquare col heading)) (a,b) (C3 dir) (CLevel nivel)
| (M.notMember (a, b) nivel) == True = addSquare col heading (a, b) (CLevel nivel)
| (isThereSquare (nivel M.! (a, b))) == False = addSquare n_c n_h (a, b) (CLevel nivel)
|otherwise = moveSquare curr_patrat nextPos (C3 dir) nou_nivel
where
curr_patrat = (head (nivel M.! (a, b)))
nextPos = getNextPosition (C3 dir) (a, b)
(C1 (CSquare n_c n_h)) = getNewSquare (C1 (CSquare col heading)) (nivel M.! (a, b))
nou_nivel = addSquare n_c n_h (a, b) (deleteSquare (nivel M.! (a, b)) (a, b) (CLevel nivel))
move :: Position -> Level -> Level
move (a,b) (CLevel nivel)
| (M.notMember (a, b) nivel) == True = (CLevel nivel)
| (isThereSquare (nivel M.! (a, b))) == False = (CLevel nivel)
|otherwise = moveSquare patrat nextPos initialDirection nou_nivel
where
patrat = (head (nivel M.! (a, b)))
initialDirection = getInitialDirection (nivel M.! (a, b))
nextPos = getNextPosition initialDirection (a, b)
nou_nivel = deleteSquare (nivel M.! (a, b)) (a, b) (CLevel nivel)
{-
*** TODO ***
Instanțiați clasa `ProblemState` pentru jocul nostru.
-}
isPositionRight :: [Object] -> Bool
isPositionRight [(C3 _)] = True
isPositionRight [(C2 _)] = True
isPositionRight [(C1 _)] = False
isPositionRight [(C1 (CSquare c heading)), (C2 (CCircle col))] = c == col
isPositionRight [(C1 _), (C3 _)] = False
isSquareOnWritePosition :: [Object] -> Bool
isSquareOnWritePosition [(C3 _)] = False
isSquareOnWritePosition [(C2 _)] = False
isSquareOnWritePosition [(C1 _)] = False
isSquareOnWritePosition [(C1 (CSquare c heading)), (C2 (CCircle col))] = c == col
isSquareOnWritePosition [(C1 _), (C3 _)] = False
getPositionsWithSquare :: Level -> [(Int, Int)]
getPositionsWithSquare (CLevel nivel) = filter (\(a,b) -> isThereSquare(nivel M.! (a, b))) poziti
where
poziti = M.keys nivel
instance ProblemState Level Position where
successors (CLevel nivel) = map (\poz -> (poz,(move poz (CLevel nivel))) ) (getPositionsWithSquare (CLevel nivel))
isGoal (CLevel nivel) = all isPositionRight (map snd (M.toList nivel))
-- Doar petru BONUS
heuristic (CLevel nivel) = ((length (getPositionsWithSquare (CLevel nivel))) - (length (filter isSquareOnWritePosition (map snd (M.toList nivel)))))