diff -r 4ffba2f72692 -r 244df77507c2 main_testing4/shogun.scala --- a/main_testing4/shogun.scala Sun Jul 14 14:31:39 2024 +0100 +++ b/main_testing4/shogun.scala Sun Sep 15 12:57:59 2024 +0100 @@ -1,5 +1,7 @@ -// Main Part 4 about the Shogun Board Game -//========================================= +// Resit about the Shogun Board Game +//==================================== + +// Task 1 - 6 see below object M4 { @@ -17,10 +19,10 @@ def col : Colour def en : Int // energy for Pawns 1 - 4, for Kings 1 - 2 } - case class Pawn(en: Int, col: Colour, pos: Pos) extends Piece case class King(en: Int, col: Colour, pos: Pos) extends Piece +// how to extract components from pieces //val p = Pawn(4, Wht, (3,2)) //assert(p.pos == (3,2)) //assert(p.col == Wht) @@ -89,7 +91,7 @@ def print_board(b: Board): Unit = { println() for (i <- 8 to 1 by -1) { - println("+" ++ "-" * 31 ++ "+") + println("----" * 8) for (j <- 1 to 8) { val opc = occupied((j,i), b) if (opc.isDefined) print(s"|${pp(opc.get)}") @@ -97,7 +99,7 @@ } println("|") } - println("+" ++ "-" * 31 ++ "+") + println("----" * 8) } // example board: initial board @@ -129,7 +131,6 @@ // |PW4|PW3|PW2|KW2|PW1|PW4|PW3|PW2| // -------------------------------- - // Moves //======= abstract class Move @@ -137,116 +138,102 @@ case object D extends Move // down case object R extends Move // right case object L extends Move // left -case object RU extends Move // ... -case object LU extends Move -case object RD extends Move +case object RU extends Move // first right, then possibly up +case object LU extends Move // first left, then possibly up +case object RD extends Move // ... case object LD extends Move case object UR extends Move case object UL extends Move case object DR extends Move case object DL extends Move -// Task 1: calculates all next possible positions according to a move +//====================== +// ADD YOUR CODE BELOW +//====================== + + +// Task 1: def eval(pc: Piece, m: Move, en: Int, b: Board) : Set[Piece] = { - val p = pc.pos - val c = pc.col - if (!inside(p, b)) Set() - else if (en == 0 && !is_occupied(p, b)) Set(pc) - else if (en == 0 && is_occupied(p, b) && c != occupied_by(p, b).get) Set(pc) - else if (is_occupied(p, b)) Set() - else m match { - case U => eval(incy(pc), U, en - 1, b) - case D => eval(decy(pc), D, en - 1, b) - case R => eval(incx(pc), R, en - 1, b) - case L => eval(decx(pc), L, en - 1, b) - case RU => eval(incx(pc), RU, en - 1, b) ++ eval(pc, U, en, b) - case LU => eval(decx(pc), LU, en - 1, b) ++ eval(pc, U, en, b) - case RD => eval(incx(pc), RD, en - 1, b) ++ eval(pc, D, en, b) - case LD => eval(decx(pc), LD, en - 1, b) ++ eval(pc, D, en, b) - case UR => eval(incy(pc), UR, en - 1, b) ++ eval(pc, R, en, b) - case UL => eval(incy(pc), UL, en - 1, b) ++ eval(pc, L, en, b) - case DR => eval(decy(pc), DR, en - 1, b) ++ eval(pc, R, en, b) - case DL => eval(decy(pc), DL, en - 1, b) ++ eval(pc, L, en, b) -}} - -/* -// test cases -val pw_a = Pawn(4, Wht, (4,4)) -println(eval(pw_a, U, 4, b_init)) // Set(Pawn(4,Wht,(4,8))) -println(eval(pw_a, U, 3, b_init)) // Set(Pawn(4,Wht,(4,7))) -println(eval(pw_a, RU, 4, b_init)) // Set(Pawn(4,Wht,(6,6)), Pawn(4,Wht,(4,8)), - // Pawn(4,Wht,(5,7)), Pawn(4,Wht,(7,5)), - // Pawn(4,Wht,(8,4))) -val pw_b = Pawn(4, Red, (4,4)) -println(eval(pw_b, RU, 4, b_init)) // Set(Pawn(4,Red,(8,4)), Pawn(4,Red,(7,5)), - Pawn(4,Red,(6,6)), Pawn(4,Red,(5,7))) -*/ + val pos = pc.pos + if (!inside(pos, b)) then Set() + else if (en == 0) then + if is_occupied(pos, b) then + val occupant = occupied_by(pos, b) + if occupant.get != pc.col then + Set(pc) + else Set() + else Set(pc) + else if (is_occupied(pos,b)) then Set() + else {m match { + case U => eval(incy(pc), U, en-1, b) + case D => eval(decy(pc), D, en-1, b) + case R => eval(incx(pc), R, en-1, b) + case L => eval(decx(pc), L, en-1, b) + case RU => eval(incx(pc), RU, en-1, b) ++ eval(pc, U, en, b) + case LU => eval(decx(pc), LU, en-1, b) ++ eval(pc, U, en, b) + case RD => eval(incx(pc), RD, en-1, b) ++ eval(pc, D, en, b) + case LD => eval(decx(pc), LD, en-1, b) ++ eval(pc, D, en, b) + case UR => eval(incy(pc), UR, en-1, b) ++ eval(pc, R, en, b) + case UL => eval(incy(pc), UL, en-1, b) ++ eval(pc, L, en, b) + case DR => eval(decy(pc), DR, en-1, b) ++ eval(pc, R, en, b) + case DL => eval(decy(pc), DL, en-1, b) ++ eval(pc, L, en, b) + } + } +} -// Task 2: calculates all possible moves for a piece +// Task 2: def all_moves(pc: Piece, b: Board) : Set[Piece] = { - Set(U,D,L,R,RU,LU,RD,LD,UR,UL,DR,DL).flatMap(eval(pc, _, pc.en, b - pc)) + val temporary_board = b - pc //not sure if this is + //what was meant by changes to the board (Perth discussion on keats) + val all_possible_moves = Set(U, D, R, L, RU, LU, RD, LD, UR, UL, DR, DL) + all_possible_moves.flatMap(move => eval(pc, move, pc.en, temporary_board)) +} + + +// Task 3: +def attacked(c: Colour, b: Board) : Set[Piece] = { + val my_pieces = b.pces.filter(_.col == c) + val opponent_pieces = b.pces.filter(_.col != c) + val attacked_pieces = opponent_pieces.filter(pc => my_pieces.flatMap(p => all_moves(p, b)).exists(_.pos == pc.pos)) + attacked_pieces +} + + +// Task 4: +def attackedN(pc: Piece, b: Board) : Int = { + val opponent_pieces = b.pces.filter(_.col != pc.col) + val attacking_pieces_num = opponent_pieces.count(p => all_moves(p, b).exists(_.pos == pc.pos)) + attacking_pieces_num +} + + +// Task 5: +def protectedN(pc: Piece, b: Board) : Int = { + val temporary_board = b - pc + val my_pieces = b.pces.filter(_.col == pc.col) + val protecting_pieces_num = my_pieces.count(p => all_moves(p, temporary_board).exists(_.pos == pc.pos)) + protecting_pieces_num +} + + +// Task 6: +def legal_moves(pc: Piece, b: Board) : Set[Piece] = { + if is_king(pc) then + val all_king_moves = all_moves(pc, b) + val valid_king_moves = all_king_moves.filter{m => + val temporary_board = Board(b.pces.filter(_.pos != m.pos))//remove potentially captured pieces + val updated_temp_board = temporary_board + m + val opponent_pieces = updated_temp_board.pces.filter(_.col != pc.col) + val opponent_moves = opponent_pieces.flatMap(p => all_moves(p, updated_temp_board)) + !(opponent_moves.exists(_.pos == m.pos))} + valid_king_moves + else {all_moves(pc, b)} } /* -// test cases -val pw_c = Pawn(2, Wht, (4,4)) -val pw_d = Pawn(3, Red, (4,4)) -println(all_moves(pw_c, b_init)) - // Set(Pawn(2,Wht,(3,5)), Pawn(2,Wht,(2,4)), Pawn(2,Wht,(3,3)), Pawn(2,Wht,(5,5)), - // Pawn(2,Wht,(6,4)), Pawn(2,Wht,(4,6)), Pawn(2,Wht,(4,2)), Pawn(2,Wht,(5,3))) -println(all_moves(pw_d, b_init)) - // Set(Pawn(3,Red,(4,7)), Pawn(3,Red,(5,2)), Pawn(3,Red,(3,2)), Pawn(3,Red,(1,4)), - // Pawn(3,Red,(6,3)), Pawn(3,Red,(3,6)), Pawn(3,Red,(2,5)), Pawn(3,Red,(2,3)), - // Pawn(3,Red,(4,1)), Pawn(3,Red,(5,6)), Pawn(3,Red,(7,4)), Pawn(3,Red,(6,5))) -*/ - - -// Task 3: calculates all pieces that are attacked by colour -def attacked(c: Colour, b: Board) : Set[Piece] = { - val (me, opponent) = b.pces.partition(_.col == c) - val all = me.flatMap(all_moves(_, b)) - opponent.filter(pc => is_occupied(pc.pos, Board(all))) -} - -// test cases -val b_checkmate = Board(Set(King(2, Red, (4,2)), King(2, Wht, (7,1)), - Pawn(3, Red, (6,1)), Pawn(2, Wht, (8,4)), - Pawn(4, Red, (4,4)), Pawn(2, Wht, (4,1)), - Pawn(4, Red, (5,3)), Pawn(3, Wht, (8,7)), - Pawn(3, Red, (6,5)))) -print_board(b_checkmate) -println(attacked(Red, b_checkmate)) // Set(Pawn(2,Wht,(8,4)), King(2,Wht,(7,1))) -println(attacked(Wht, b_checkmate)) // Set(Pawn(3,Red,(6,1))) -println(attacked(Wht, b_init)) // Set() -println(attacked(Red, b_init)) // Set() - -// Task 4: calculates the number of pieces that attack a piece -def attackedN(pc: Piece, b: Board) : Int = { - val (me, opponent) = b.pces.partition(_.col == pc.col) - val all = opponent.toList.flatMap(all_moves(_, b)) - all.count(_.pos == pc.pos) -} - -// test cases -println(attackedN(Pawn(2, Wht, (8,4)), b_checkmate)) // 3 -println(attackedN(King(2, Wht, (7,1)), b_checkmate)) // 1 -println(attackedN(Pawn(3, Red, (6,1)), b_checkmate)) // 1 - - -// Task 5: calculates the number of pieces that protect a piece -def protectedN(pc: Piece, b: Board) : Int = { - val (me, opponent) = b.pces.partition(_.col == pc.col) - val all = (me - pc).toList.flatMap(all_moves(_, (b - pc))) - all.count(_.pos == pc.pos) -} - -println(protectedN(Pawn(2, Wht, (8,4)), b_checkmate)) // 1 -println(protectedN(Pawn(4, Red, (5,3)), b_checkmate)) // 3 - - - -// +// more test cases +//================= val pw1 = Pawn(4, Wht, (4,6)) val pw2 = Pawn(4, Wht, (2,4)) val pw3 = Pawn(3, Red, (6,8)) @@ -255,16 +242,21 @@ print_board(bt) println(s"Capture Red: ${attacked(Wht, bt)}") - // Set(Pawn(2,Red,(2,8)), Pawn(3,Red,(6,8))) + // => Set(Pawn(2,Red,(2,8)), Pawn(3,Red,(6,8))) + println(s"Capture Wht: ${attacked(Red, bt)}") - // Set(Pawn(4,Wht,(4,6))) + // => Set(Pawn(4,Wht,(4,6))) + println(s"ProtectedN: ${protectedN(pw3, bt)}") - // 2 + // => 2 + println(s"AttackedN: ${attackedN(pw4, bt)}") - // 2 + // => 2 + println(s"all moves: ${all_moves(pw2, bt)}") - // Set(Pawn(4,Wht,(4,2)), Pawn(4,Wht,(1,7)), Pawn(4,Wht,(5,3)), Pawn(4,Wht,(5,5)), - // Pawn(4,Wht,(2,8)), Pawn(4,Wht,(3,7)), Pawn(4,Wht,(6,4))) + // => Set(Pawn(4,Wht,(4,2)), Pawn(4,Wht,(1,7)), Pawn(4,Wht,(5,3)), Pawn(4,Wht,(5,5)), + // Pawn(4,Wht,(2,8)), Pawn(4,Wht,(3,7)), Pawn(4,Wht,(6,4))) +*/ }