Test and implement standard chess kingside castle
This commit is contained in:
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 {
|
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 if (role.longRange) ⇒ longRange(role.dirs)
|
||||||
|
|
||||||
case role ⇒ shortRange(role.dirs)
|
case role ⇒ shortRange(role.dirs)
|
||||||
})
|
})
|
||||||
|
|
||||||
lazy val moves: Set[Pos] = implications.keySet
|
lazy val moves: Set[Pos] = implications.keySet
|
||||||
|
|
||||||
def color = piece.color
|
def color = piece.color
|
||||||
def is(c: Color) = c == piece.color
|
def is(c: Color) = c == piece.color
|
||||||
|
def is(p: Piece) = p == piece
|
||||||
def friends: Set[Pos] = board occupation color
|
def friends: Set[Pos] = board occupation color
|
||||||
def enemies: Set[Pos] = board occupation !color
|
def enemies: Set[Pos] = board occupation !color
|
||||||
def dir: Direction = if (color == White) _.up else _.down
|
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
|
List(next.left, next.right) flatten
|
||||||
} getOrElse Nil
|
} getOrElse Nil
|
||||||
case role if (role.longRange) ⇒ longRangePoss(role.dirs)
|
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)
|
}) contains to)
|
||||||
|
|
||||||
private def kingSafety(implications: Implications): Implications =
|
private def kingSafety(implications: Implications): Implications =
|
||||||
|
@ -40,7 +41,21 @@ case class Actor(piece: Piece, pos: Pos, board: Board) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private def castle: Implications = {
|
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 = {
|
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))))
|
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 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 ⇒
|
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 canCastleKingSide(color: Color): Boolean = castles(color)._1
|
||||||
def canCastleQueenSide(color: Color): Boolean = castles(color)._2
|
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
|
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 {
|
"castle" in {
|
||||||
"king side" in {
|
"king side" in {
|
||||||
|
val board: Board = """
|
||||||
|
PPPPPPPP
|
||||||
|
R QK R"""
|
||||||
"impossible" in {
|
"impossible" in {
|
||||||
"pieces in the way" in {
|
"pieces in the way" in {
|
||||||
Board().movesFrom(E1) must bePoss()
|
Board().movesFrom(E1) must bePoss()
|
||||||
}
|
}
|
||||||
|
"not allowed by history" in {
|
||||||
|
board movesFrom E1 must bePoss(F1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
"possible" in {
|
"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
|
PPPPPPPP
|
||||||
R QK R"""
|
R Q RK """)
|
||||||
"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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//"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 a new issue