127 // | | | | | | | | | |
129 // | | | | | | | | | |
128 // -------------------------------- |
130 // -------------------------------- |
129 // |PW4|PW3|PW2|KW2|PW1|PW4|PW3|PW2| |
131 // |PW4|PW3|PW2|KW2|PW1|PW4|PW3|PW2| |
130 // -------------------------------- |
132 // -------------------------------- |
131 |
133 |
132 |
|
133 // Moves |
134 // Moves |
134 //======= |
135 //======= |
135 abstract class Move |
136 abstract class Move |
136 case object U extends Move // up |
137 case object U extends Move // up |
137 case object D extends Move // down |
138 case object D extends Move // down |
138 case object R extends Move // right |
139 case object R extends Move // right |
139 case object L extends Move // left |
140 case object L extends Move // left |
140 case object RU extends Move // ... |
141 case object RU extends Move // first right, then possibly up |
141 case object LU extends Move |
142 case object LU extends Move // first left, then possibly up |
142 case object RD extends Move |
143 case object RD extends Move // ... |
143 case object LD extends Move |
144 case object LD extends Move |
144 case object UR extends Move |
145 case object UR extends Move |
145 case object UL extends Move |
146 case object UL extends Move |
146 case object DR extends Move |
147 case object DR extends Move |
147 case object DL extends Move |
148 case object DL extends Move |
148 |
149 |
149 // Task 1: calculates all next possible positions according to a move |
150 //====================== |
|
151 // ADD YOUR CODE BELOW |
|
152 //====================== |
|
153 |
|
154 |
|
155 // Task 1: |
150 def eval(pc: Piece, m: Move, en: Int, b: Board) : Set[Piece] = { |
156 def eval(pc: Piece, m: Move, en: Int, b: Board) : Set[Piece] = { |
151 val p = pc.pos |
157 val pos = pc.pos |
152 val c = pc.col |
158 if (!inside(pos, b)) then Set() |
153 if (!inside(p, b)) Set() |
159 else if (en == 0) then |
154 else if (en == 0 && !is_occupied(p, b)) Set(pc) |
160 if is_occupied(pos, b) then |
155 else if (en == 0 && is_occupied(p, b) && c != occupied_by(p, b).get) Set(pc) |
161 val occupant = occupied_by(pos, b) |
156 else if (is_occupied(p, b)) Set() |
162 if occupant.get != pc.col then |
157 else m match { |
163 Set(pc) |
158 case U => eval(incy(pc), U, en - 1, b) |
164 else Set() |
159 case D => eval(decy(pc), D, en - 1, b) |
165 else Set(pc) |
160 case R => eval(incx(pc), R, en - 1, b) |
166 else if (is_occupied(pos,b)) then Set() |
161 case L => eval(decx(pc), L, en - 1, b) |
167 else {m match { |
162 case RU => eval(incx(pc), RU, en - 1, b) ++ eval(pc, U, en, b) |
168 case U => eval(incy(pc), U, en-1, b) |
163 case LU => eval(decx(pc), LU, en - 1, b) ++ eval(pc, U, en, b) |
169 case D => eval(decy(pc), D, en-1, b) |
164 case RD => eval(incx(pc), RD, en - 1, b) ++ eval(pc, D, en, b) |
170 case R => eval(incx(pc), R, en-1, b) |
165 case LD => eval(decx(pc), LD, en - 1, b) ++ eval(pc, D, en, b) |
171 case L => eval(decx(pc), L, en-1, b) |
166 case UR => eval(incy(pc), UR, en - 1, b) ++ eval(pc, R, en, b) |
172 case RU => eval(incx(pc), RU, en-1, b) ++ eval(pc, U, en, b) |
167 case UL => eval(incy(pc), UL, en - 1, b) ++ eval(pc, L, en, b) |
173 case LU => eval(decx(pc), LU, en-1, b) ++ eval(pc, U, en, b) |
168 case DR => eval(decy(pc), DR, en - 1, b) ++ eval(pc, R, en, b) |
174 case RD => eval(incx(pc), RD, en-1, b) ++ eval(pc, D, en, b) |
169 case DL => eval(decy(pc), DL, en - 1, b) ++ eval(pc, L, en, b) |
175 case LD => eval(decx(pc), LD, en-1, b) ++ eval(pc, D, en, b) |
170 }} |
176 case UR => eval(incy(pc), UR, en-1, b) ++ eval(pc, R, en, b) |
|
177 case UL => eval(incy(pc), UL, en-1, b) ++ eval(pc, L, en, b) |
|
178 case DR => eval(decy(pc), DR, en-1, b) ++ eval(pc, R, en, b) |
|
179 case DL => eval(decy(pc), DL, en-1, b) ++ eval(pc, L, en, b) |
|
180 } |
|
181 } |
|
182 } |
|
183 |
|
184 |
|
185 // Task 2: |
|
186 def all_moves(pc: Piece, b: Board) : Set[Piece] = { |
|
187 val temporary_board = b - pc //not sure if this is |
|
188 //what was meant by changes to the board (Perth discussion on keats) |
|
189 val all_possible_moves = Set(U, D, R, L, RU, LU, RD, LD, UR, UL, DR, DL) |
|
190 all_possible_moves.flatMap(move => eval(pc, move, pc.en, temporary_board)) |
|
191 } |
|
192 |
|
193 |
|
194 // Task 3: |
|
195 def attacked(c: Colour, b: Board) : Set[Piece] = { |
|
196 val my_pieces = b.pces.filter(_.col == c) |
|
197 val opponent_pieces = b.pces.filter(_.col != c) |
|
198 val attacked_pieces = opponent_pieces.filter(pc => my_pieces.flatMap(p => all_moves(p, b)).exists(_.pos == pc.pos)) |
|
199 attacked_pieces |
|
200 } |
|
201 |
|
202 |
|
203 // Task 4: |
|
204 def attackedN(pc: Piece, b: Board) : Int = { |
|
205 val opponent_pieces = b.pces.filter(_.col != pc.col) |
|
206 val attacking_pieces_num = opponent_pieces.count(p => all_moves(p, b).exists(_.pos == pc.pos)) |
|
207 attacking_pieces_num |
|
208 } |
|
209 |
|
210 |
|
211 // Task 5: |
|
212 def protectedN(pc: Piece, b: Board) : Int = { |
|
213 val temporary_board = b - pc |
|
214 val my_pieces = b.pces.filter(_.col == pc.col) |
|
215 val protecting_pieces_num = my_pieces.count(p => all_moves(p, temporary_board).exists(_.pos == pc.pos)) |
|
216 protecting_pieces_num |
|
217 } |
|
218 |
|
219 |
|
220 // Task 6: |
|
221 def legal_moves(pc: Piece, b: Board) : Set[Piece] = { |
|
222 if is_king(pc) then |
|
223 val all_king_moves = all_moves(pc, b) |
|
224 val valid_king_moves = all_king_moves.filter{m => |
|
225 val temporary_board = Board(b.pces.filter(_.pos != m.pos))//remove potentially captured pieces |
|
226 val updated_temp_board = temporary_board + m |
|
227 val opponent_pieces = updated_temp_board.pces.filter(_.col != pc.col) |
|
228 val opponent_moves = opponent_pieces.flatMap(p => all_moves(p, updated_temp_board)) |
|
229 !(opponent_moves.exists(_.pos == m.pos))} |
|
230 valid_king_moves |
|
231 else {all_moves(pc, b)} |
|
232 } |
171 |
233 |
172 /* |
234 /* |
173 // test cases |
235 // more test cases |
174 val pw_a = Pawn(4, Wht, (4,4)) |
236 //================= |
175 println(eval(pw_a, U, 4, b_init)) // Set(Pawn(4,Wht,(4,8))) |
|
176 println(eval(pw_a, U, 3, b_init)) // Set(Pawn(4,Wht,(4,7))) |
|
177 println(eval(pw_a, RU, 4, b_init)) // Set(Pawn(4,Wht,(6,6)), Pawn(4,Wht,(4,8)), |
|
178 // Pawn(4,Wht,(5,7)), Pawn(4,Wht,(7,5)), |
|
179 // Pawn(4,Wht,(8,4))) |
|
180 val pw_b = Pawn(4, Red, (4,4)) |
|
181 println(eval(pw_b, RU, 4, b_init)) // Set(Pawn(4,Red,(8,4)), Pawn(4,Red,(7,5)), |
|
182 Pawn(4,Red,(6,6)), Pawn(4,Red,(5,7))) |
|
183 */ |
|
184 |
|
185 |
|
186 // Task 2: calculates all possible moves for a piece |
|
187 def all_moves(pc: Piece, b: Board) : Set[Piece] = { |
|
188 Set(U,D,L,R,RU,LU,RD,LD,UR,UL,DR,DL).flatMap(eval(pc, _, pc.en, b - pc)) |
|
189 } |
|
190 |
|
191 /* |
|
192 // test cases |
|
193 val pw_c = Pawn(2, Wht, (4,4)) |
|
194 val pw_d = Pawn(3, Red, (4,4)) |
|
195 println(all_moves(pw_c, b_init)) |
|
196 // Set(Pawn(2,Wht,(3,5)), Pawn(2,Wht,(2,4)), Pawn(2,Wht,(3,3)), Pawn(2,Wht,(5,5)), |
|
197 // Pawn(2,Wht,(6,4)), Pawn(2,Wht,(4,6)), Pawn(2,Wht,(4,2)), Pawn(2,Wht,(5,3))) |
|
198 println(all_moves(pw_d, b_init)) |
|
199 // Set(Pawn(3,Red,(4,7)), Pawn(3,Red,(5,2)), Pawn(3,Red,(3,2)), Pawn(3,Red,(1,4)), |
|
200 // Pawn(3,Red,(6,3)), Pawn(3,Red,(3,6)), Pawn(3,Red,(2,5)), Pawn(3,Red,(2,3)), |
|
201 // Pawn(3,Red,(4,1)), Pawn(3,Red,(5,6)), Pawn(3,Red,(7,4)), Pawn(3,Red,(6,5))) |
|
202 */ |
|
203 |
|
204 |
|
205 // Task 3: calculates all pieces that are attacked by colour |
|
206 def attacked(c: Colour, b: Board) : Set[Piece] = { |
|
207 val (me, opponent) = b.pces.partition(_.col == c) |
|
208 val all = me.flatMap(all_moves(_, b)) |
|
209 opponent.filter(pc => is_occupied(pc.pos, Board(all))) |
|
210 } |
|
211 |
|
212 // test cases |
|
213 val b_checkmate = Board(Set(King(2, Red, (4,2)), King(2, Wht, (7,1)), |
|
214 Pawn(3, Red, (6,1)), Pawn(2, Wht, (8,4)), |
|
215 Pawn(4, Red, (4,4)), Pawn(2, Wht, (4,1)), |
|
216 Pawn(4, Red, (5,3)), Pawn(3, Wht, (8,7)), |
|
217 Pawn(3, Red, (6,5)))) |
|
218 print_board(b_checkmate) |
|
219 println(attacked(Red, b_checkmate)) // Set(Pawn(2,Wht,(8,4)), King(2,Wht,(7,1))) |
|
220 println(attacked(Wht, b_checkmate)) // Set(Pawn(3,Red,(6,1))) |
|
221 println(attacked(Wht, b_init)) // Set() |
|
222 println(attacked(Red, b_init)) // Set() |
|
223 |
|
224 // Task 4: calculates the number of pieces that attack a piece |
|
225 def attackedN(pc: Piece, b: Board) : Int = { |
|
226 val (me, opponent) = b.pces.partition(_.col == pc.col) |
|
227 val all = opponent.toList.flatMap(all_moves(_, b)) |
|
228 all.count(_.pos == pc.pos) |
|
229 } |
|
230 |
|
231 // test cases |
|
232 println(attackedN(Pawn(2, Wht, (8,4)), b_checkmate)) // 3 |
|
233 println(attackedN(King(2, Wht, (7,1)), b_checkmate)) // 1 |
|
234 println(attackedN(Pawn(3, Red, (6,1)), b_checkmate)) // 1 |
|
235 |
|
236 |
|
237 // Task 5: calculates the number of pieces that protect a piece |
|
238 def protectedN(pc: Piece, b: Board) : Int = { |
|
239 val (me, opponent) = b.pces.partition(_.col == pc.col) |
|
240 val all = (me - pc).toList.flatMap(all_moves(_, (b - pc))) |
|
241 all.count(_.pos == pc.pos) |
|
242 } |
|
243 |
|
244 println(protectedN(Pawn(2, Wht, (8,4)), b_checkmate)) // 1 |
|
245 println(protectedN(Pawn(4, Red, (5,3)), b_checkmate)) // 3 |
|
246 |
|
247 |
|
248 |
|
249 // |
|
250 val pw1 = Pawn(4, Wht, (4,6)) |
237 val pw1 = Pawn(4, Wht, (4,6)) |
251 val pw2 = Pawn(4, Wht, (2,4)) |
238 val pw2 = Pawn(4, Wht, (2,4)) |
252 val pw3 = Pawn(3, Red, (6,8)) |
239 val pw3 = Pawn(3, Red, (6,8)) |
253 val pw4 = Pawn(2, Red, (2,8)) |
240 val pw4 = Pawn(2, Red, (2,8)) |
254 val bt = b_init + pw1 + pw2 |
241 val bt = b_init + pw1 + pw2 |
255 |
242 |
256 print_board(bt) |
243 print_board(bt) |
257 println(s"Capture Red: ${attacked(Wht, bt)}") |
244 println(s"Capture Red: ${attacked(Wht, bt)}") |
258 // Set(Pawn(2,Red,(2,8)), Pawn(3,Red,(6,8))) |
245 // => Set(Pawn(2,Red,(2,8)), Pawn(3,Red,(6,8))) |
|
246 |
259 println(s"Capture Wht: ${attacked(Red, bt)}") |
247 println(s"Capture Wht: ${attacked(Red, bt)}") |
260 // Set(Pawn(4,Wht,(4,6))) |
248 // => Set(Pawn(4,Wht,(4,6))) |
|
249 |
261 println(s"ProtectedN: ${protectedN(pw3, bt)}") |
250 println(s"ProtectedN: ${protectedN(pw3, bt)}") |
262 // 2 |
251 // => 2 |
|
252 |
263 println(s"AttackedN: ${attackedN(pw4, bt)}") |
253 println(s"AttackedN: ${attackedN(pw4, bt)}") |
264 // 2 |
254 // => 2 |
|
255 |
265 println(s"all moves: ${all_moves(pw2, bt)}") |
256 println(s"all moves: ${all_moves(pw2, bt)}") |
266 // Set(Pawn(4,Wht,(4,2)), Pawn(4,Wht,(1,7)), Pawn(4,Wht,(5,3)), Pawn(4,Wht,(5,5)), |
257 // => Set(Pawn(4,Wht,(4,2)), Pawn(4,Wht,(1,7)), Pawn(4,Wht,(5,3)), Pawn(4,Wht,(5,5)), |
267 // Pawn(4,Wht,(2,8)), Pawn(4,Wht,(3,7)), Pawn(4,Wht,(6,4))) |
258 // Pawn(4,Wht,(2,8)), Pawn(4,Wht,(3,7)), Pawn(4,Wht,(6,4))) |
268 |
259 */ |
269 } |
260 |
270 |
261 } |
271 |
262 |
|
263 |