Test and implement standard chess kingside castle
parent
e7e0afef07
commit
a5664c94a0
|
@ -7,19 +7,20 @@ case class Actor(piece: Piece, pos: Pos, board: Board) {
|
|||
|
||||
lazy val implications: Implications = kingSafety(piece.role match {
|
||||
|
||||
case Pawn ⇒ pawn
|
||||
case Pawn ⇒ pawn
|
||||
|
||||
case King ⇒ shortRange(King.dirs) ++ castle
|
||||
case King ⇒ shortRange(King.dirs) ++ castle
|
||||
|
||||
case role if (role.longRange) ⇒ longRange(role.dirs)
|
||||
|
||||
case role ⇒ shortRange(role.dirs)
|
||||
case role ⇒ shortRange(role.dirs)
|
||||
})
|
||||
|
||||
lazy val moves: Set[Pos] = implications.keySet
|
||||
|
||||
def color = piece.color
|
||||
def is(c: Color) = c == piece.color
|
||||
def is(p: Piece) = p == piece
|
||||
def friends: Set[Pos] = board occupation color
|
||||
def enemies: Set[Pos] = board occupation !color
|
||||
def dir: Direction = if (color == White) _.up else _.down
|
||||
|
@ -29,7 +30,7 @@ case class Actor(piece: Piece, pos: Pos, board: Board) {
|
|||
List(next.left, next.right) flatten
|
||||
} getOrElse Nil
|
||||
case role if (role.longRange) ⇒ longRangePoss(role.dirs)
|
||||
case role ⇒ (role.dirs map { d ⇒ d(pos) }).flatten
|
||||
case role ⇒ (role.dirs map { d ⇒ d(pos) }).flatten
|
||||
}) contains to)
|
||||
|
||||
private def kingSafety(implications: Implications): Implications =
|
||||
|
@ -40,7 +41,21 @@ case class Actor(piece: Piece, pos: Pos, board: Board) {
|
|||
}
|
||||
|
||||
private def castle: Implications = {
|
||||
Map.empty
|
||||
val kingSide: Option[Implication] = for {
|
||||
kingPos ← board kingPosOf color
|
||||
if board.history canCastleKingSide color
|
||||
rook = color.rook
|
||||
rookPos ← board actorsOf color collectFirst {
|
||||
case a if (a is rook) && (a.pos.x > kingPos.x) ⇒ a.pos
|
||||
}
|
||||
newKingPos ← kingPos > 2
|
||||
newRookPos ← newKingPos.left
|
||||
b1 ← board take rookPos
|
||||
b2 ← b1.move(kingPos, newKingPos)
|
||||
b3 ← b2.place(rook, newRookPos)
|
||||
} yield (newKingPos, b3)
|
||||
|
||||
kingSide toMap
|
||||
}
|
||||
|
||||
private def shortRange(dirs: Directions): Implications = {
|
||||
|
|
|
@ -38,6 +38,10 @@ case class Board(pieces: Map[Pos, Piece], history: History) {
|
|||
else success(copy(pieces = pieces + ((at, piece))))
|
||||
}
|
||||
|
||||
def place(piece: Piece, at: Pos) =
|
||||
if (pieces contains at) None
|
||||
else Some(copy(pieces = pieces + ((at, piece))))
|
||||
|
||||
def takeValid(at: Pos): Valid[Board] = take(at) toSuccess ("No piece at " + at + " to take")
|
||||
|
||||
def take(at: Pos): Option[Board] = pieces get at map { piece ⇒
|
||||
|
|
|
@ -14,3 +14,10 @@ case class History(
|
|||
def canCastleKingSide(color: Color): Boolean = castles(color)._1
|
||||
def canCastleQueenSide(color: Color): Boolean = castles(color)._2
|
||||
}
|
||||
|
||||
object History {
|
||||
|
||||
def castle(color: Color, kingSide: Boolean, queenSide: Boolean) = History(
|
||||
castles = Map(color -> (kingSide, queenSide))
|
||||
)
|
||||
}
|
||||
|
|
|
@ -21,4 +21,12 @@ trait LilaSpec
|
|||
case p ⇒ Visual.addNewLines(Visual.>>|(board, Map(p -> 'x'))) must_== visual
|
||||
}
|
||||
|
||||
def beBoard(visual: String): Matcher[Valid[Board]] = beSuccess.like {
|
||||
case b => b.visual must_== (Visual << visual).visual
|
||||
}
|
||||
|
||||
def beSituation(visual: String): Matcher[Valid[Situation]] = beSuccess.like {
|
||||
case s => s.board.visual must_== (Visual << visual).visual
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,35 +11,45 @@ class CastleTest extends LilaSpec {
|
|||
|
||||
"castle" in {
|
||||
"king side" in {
|
||||
val board: Board = """
|
||||
PPPPPPPP
|
||||
R QK R"""
|
||||
"impossible" in {
|
||||
"pieces in the way" in {
|
||||
Board().movesFrom(E1) must bePoss()
|
||||
}
|
||||
"not allowed by history" in {
|
||||
board movesFrom E1 must bePoss(F1)
|
||||
}
|
||||
}
|
||||
"possible" in {
|
||||
val board = """
|
||||
val board2 = board withHistory History.castle(White, true, true)
|
||||
val situation = board2 as White
|
||||
"viable moves" in {
|
||||
board2 movesFrom E1 must bePoss(F1, G1)
|
||||
}
|
||||
"correct new board" in {
|
||||
situation.playMove(E1, G1) must beSituation("""
|
||||
PPPPPPPP
|
||||
R QK R"""
|
||||
"viable moves" in {
|
||||
board movesFrom E1 must bePoss(F1, G1)
|
||||
}
|
||||
}
|
||||
}
|
||||
"queen side" in {
|
||||
"impossible" in {
|
||||
"pieces in the way" in {
|
||||
Board() movesFrom E1 must bePoss()
|
||||
}
|
||||
}
|
||||
"possible" in {
|
||||
val board = """
|
||||
PPPPPP
|
||||
R KB"""
|
||||
"viable moves" in {
|
||||
board movesFrom E1 must bePoss(D1, C1)
|
||||
R Q RK """)
|
||||
}
|
||||
}
|
||||
}
|
||||
//"queen side" in {
|
||||
//"impossible" in {
|
||||
//"pieces in the way" in {
|
||||
//Board() movesFrom E1 must bePoss()
|
||||
//}
|
||||
//}
|
||||
//"possible" in {
|
||||
//val board = """
|
||||
//PPPPPP
|
||||
//R KB"""
|
||||
//"viable moves" in {
|
||||
//board movesFrom E1 must bePoss(D1, C1)
|
||||
//}
|
||||
//}
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue