--- 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)))
+*/
}