updated default tip
authorChristian Urban <christian.urban@kcl.ac.uk>
Sun, 15 Sep 2024 12:57:59 +0100
changeset 493 244df77507c2
parent 492 4ffba2f72692
updated
main_testing4/shogun.scala
main_testing4/shogun_test.sh
progs/lecture3.scala
progs/mandelbrot.sc
--- 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)))
+*/
 
 }
 
--- a/main_testing4/shogun_test.sh	Sun Jul 14 14:31:39 2024 +0100
+++ b/main_testing4/shogun_test.sh	Sun Sep 15 12:57:59 2024 +0100
@@ -18,13 +18,13 @@
 # compilation tests
 
 function scala_compile {
-  (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala-cli compile -color never -Xprint:parser "$1" 2> c$out 1> c$out)
+  (scala-cli compile -color never -Xprint:parser "$1" 2> c$out 1> c$out)
 }
 
 # functional tests
 
 function scala_assert {
-  (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala-cli -i "$1" "$2" -e "urbanmain()" 2> /dev/null 1> /dev/null)
+  (scala-cli --server=false --java-opt -Xmx1g -i project.scala "$1" "$2" -e "urbanmain()" 2> /dev/null 1> /dev/null)
 }
 
 # purity test
--- a/progs/lecture3.scala	Sun Jul 14 14:31:39 2024 +0100
+++ b/progs/lecture3.scala	Sun Sep 15 12:57:59 2024 +0100
@@ -347,6 +347,18 @@
 for (n <- 1 to 20) 
  println(fizz_buzz(n))
 
+// more interesting patterns for lists - calculate the deltas between 
+// elements
+
+def delta(xs: List[Int]) : List[Int] = xs match {
+  case Nil => Nil
+  case x::Nil => x::Nil
+  case x::y::xs => (x - y)::delta(y::xs)
+}
+
+delta(List(10, 7, 8, 2, 5, 10))
+
+
 // guards in pattern-matching
 
 def foo(xs: List[Int]) : String = xs match {
@@ -391,6 +403,16 @@
 
 fav_colour(Blue)
 
+enum ChessPiece:
+  case Queen, Rook, Bishop, Knight, Pawn
+  def value = this match
+    case Queen  => 9
+    case Rook   => 5
+    case Bishop => 3
+    case Knight => 3
+    case Pawn   => 1
+
+
 
 // ... a tiny bit more useful: Roman Numerals
 
--- a/progs/mandelbrot.sc	Sun Jul 14 14:31:39 2024 +0100
+++ b/progs/mandelbrot.sc	Sun Sep 15 12:57:59 2024 +0100
@@ -5,7 +5,7 @@
 //
 // You can run on the file one the commandline with
 //
-//   scala-cli mandelbrot.sc
+//   scala mandelbrot.sc
 //
 //
 //
@@ -16,7 +16,7 @@
 
 // for parallel collections
 //> using dep org.scala-lang.modules::scala-parallel-collections:1.0.4
-import scala.language.implicitConversions
+import scala.language.implicitConversions.*
 import scala.collection.parallel.CollectionConverters.*
 
 // for graphics
@@ -24,6 +24,8 @@
 import java.awt.{Color, Dimension, Graphics, Graphics2D}
 import java.awt.image.BufferedImage
 
+// for implicits in comples numbers
+import scala.language.implicitConversions