Reorganizing moving rules
This commit is contained in:
parent
bee9d5a75b
commit
a0660900ba
|
@ -6,44 +6,14 @@ import scalaz.Success
|
||||||
case class Actor(piece: Piece, pos: Pos, board: Board) {
|
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 ⇒ dir(pos) map { next ⇒
|
|
||||||
val unmoved = if (color == White) pos.y == 2 else pos.y == 7
|
|
||||||
val passable = if (color == White) pos.y == 5 else pos.y == 4
|
|
||||||
val one = Some(next) filterNot board.occupations
|
|
||||||
val moving = (pos2: Pos) ⇒ board.move(pos, pos2)
|
|
||||||
def capture(horizontal: Direction): Option[Implication] = for {
|
|
||||||
p ← horizontal(next); if (enemies(p));
|
|
||||||
b ← board.taking(pos, p)
|
|
||||||
} yield (p, b)
|
|
||||||
def enpassant(horizontal: Direction): Option[Implication] = for {
|
|
||||||
victimPos ← horizontal(pos); if (passable)
|
|
||||||
victim ← board(victimPos); if victim == !color - Pawn
|
|
||||||
targetPos ← horizontal(next)
|
|
||||||
victimFrom ← dir(victimPos) flatMap dir
|
|
||||||
if board.history.lastMove == Some(victimFrom, victimPos)
|
|
||||||
b ← board.taking(pos, targetPos, Some(victimPos))
|
|
||||||
} yield (targetPos, b)
|
|
||||||
List(
|
|
||||||
for (p ← one; b ← moving(p)) yield (p, b),
|
|
||||||
for {
|
|
||||||
p ← one; if (unmoved)
|
|
||||||
p2 ← dir(p); if (!board.occupations(p2))
|
|
||||||
b ← moving(p2)
|
|
||||||
} yield (p2, b),
|
|
||||||
capture(_.left),
|
|
||||||
capture(_.right),
|
|
||||||
enpassant(_.left),
|
|
||||||
enpassant(_.right)
|
|
||||||
).flatten toMap
|
|
||||||
} getOrElse Map.empty
|
|
||||||
|
|
||||||
case r if (r.trajectory) ⇒ implicationTrajectories(r.dirs, pos)
|
case Pawn ⇒ pawn
|
||||||
|
|
||||||
case role ⇒ {
|
case King ⇒ shortRange(King.dirs) ++ castle
|
||||||
(role.dirs map { d ⇒ d(pos) }).flatten filterNot friends map { to ⇒
|
|
||||||
(if (enemies(to)) board.taking(pos, to) else board.move(pos, to)) map (to -> _)
|
case role if (role.trajectory) ⇒ trajectory(role.dirs)
|
||||||
} flatten
|
|
||||||
} toMap
|
case role ⇒ shortRange(role.dirs)
|
||||||
})
|
})
|
||||||
|
|
||||||
lazy val moves: Set[Pos] = implications.keySet
|
lazy val moves: Set[Pos] = implications.keySet
|
||||||
|
@ -54,6 +24,14 @@ case class Actor(piece: Piece, pos: Pos, board: Board) {
|
||||||
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
|
||||||
|
|
||||||
|
def threatens(to: Pos): Boolean = enemies(to) && ((piece.role match {
|
||||||
|
case Pawn ⇒ dir(pos) map { next ⇒
|
||||||
|
List(next.left, next.right) flatten
|
||||||
|
} getOrElse Nil
|
||||||
|
case role if (role.trajectory) ⇒ trajectoryPoss(role.dirs)
|
||||||
|
case role ⇒ (role.dirs map { d ⇒ d(pos) }).flatten
|
||||||
|
}) contains to)
|
||||||
|
|
||||||
private def kingSafety(implications: Implications): Implications =
|
private def kingSafety(implications: Implications): Implications =
|
||||||
implications filterNot {
|
implications filterNot {
|
||||||
case (p, b) ⇒ b actorsOf !color exists { enemy ⇒
|
case (p, b) ⇒ b actorsOf !color exists { enemy ⇒
|
||||||
|
@ -61,16 +39,35 @@ case class Actor(piece: Piece, pos: Pos, board: Board) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// can it threaten the opponent king?
|
private def castle: Implications = {
|
||||||
def threatens(to: Pos): Boolean = enemies(to) && ((piece.role match {
|
Map.empty
|
||||||
case Pawn ⇒ dir(pos) map { next ⇒
|
}
|
||||||
List(next.left, next.right) flatten
|
|
||||||
} getOrElse Nil
|
|
||||||
case role if (role.trajectory) ⇒ posTrajectories(role.dirs, pos)
|
|
||||||
case role ⇒ (role.dirs map { d ⇒ d(pos) }).flatten
|
|
||||||
}) contains to)
|
|
||||||
|
|
||||||
private def posTrajectories(dirs: Directions, from: Pos): List[Pos] = {
|
private def shortRange(dirs: Directions): Implications = {
|
||||||
|
(dirs map { d ⇒ d(pos) }).flatten filterNot friends map { to ⇒
|
||||||
|
(if (enemies(to)) board.taking(pos, to) else board.move(pos, to)) map (to -> _)
|
||||||
|
} flatten
|
||||||
|
} toMap
|
||||||
|
|
||||||
|
private def trajectory(dirs: Directions): Implications = {
|
||||||
|
|
||||||
|
val moving = (to: Pos) ⇒ board.move(pos, to)
|
||||||
|
|
||||||
|
def forward(p: Pos, dir: Direction): List[Implication] = dir(p) match {
|
||||||
|
case None ⇒ Nil
|
||||||
|
case Some(next) if friends(next) ⇒ Nil
|
||||||
|
case Some(next) if enemies(next) ⇒ board.taking(pos, next) map { b ⇒
|
||||||
|
(next, b)
|
||||||
|
} toList
|
||||||
|
case Some(next) ⇒ moving(next) map { b ⇒
|
||||||
|
(next, b) :: forward(next, dir)
|
||||||
|
} getOrElse Nil
|
||||||
|
}
|
||||||
|
|
||||||
|
(dirs flatMap { dir ⇒ forward(pos, dir) }) toMap
|
||||||
|
}
|
||||||
|
|
||||||
|
private def trajectoryPoss(dirs: Directions): List[Pos] = {
|
||||||
|
|
||||||
def forward(p: Pos, dir: Direction): List[Pos] = dir(p) match {
|
def forward(p: Pos, dir: Direction): List[Pos] = dir(p) match {
|
||||||
case None ⇒ Nil
|
case None ⇒ Nil
|
||||||
|
@ -79,24 +76,38 @@ case class Actor(piece: Piece, pos: Pos, board: Board) {
|
||||||
case Some(next) ⇒ next :: forward(next, dir)
|
case Some(next) ⇒ next :: forward(next, dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
dirs flatMap { dir ⇒ forward(from, dir) }
|
dirs flatMap { dir ⇒ forward(pos, dir) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private def implicationTrajectories(dirs: Directions, from: Pos): Implications = {
|
private def pawn = dir(pos) map { next ⇒
|
||||||
|
val unmoved = if (color == White) pos.y == 2 else pos.y == 7
|
||||||
|
val passable = if (color == White) pos.y == 5 else pos.y == 4
|
||||||
|
val one = Some(next) filterNot board.occupations
|
||||||
|
val moving = (pos2: Pos) ⇒ board.move(pos, pos2)
|
||||||
|
def capture(horizontal: Direction): Option[Implication] = for {
|
||||||
|
p ← horizontal(next); if (enemies(p));
|
||||||
|
b ← board.taking(pos, p)
|
||||||
|
} yield (p, b)
|
||||||
|
def enpassant(horizontal: Direction): Option[Implication] = for {
|
||||||
|
victimPos ← horizontal(pos); if (passable)
|
||||||
|
victim ← board(victimPos); if victim == !color - Pawn
|
||||||
|
targetPos ← horizontal(next)
|
||||||
|
victimFrom ← dir(victimPos) flatMap dir
|
||||||
|
if board.history.lastMove == Some(victimFrom, victimPos)
|
||||||
|
b ← board.taking(pos, targetPos, Some(victimPos))
|
||||||
|
} yield (targetPos, b)
|
||||||
|
List(
|
||||||
|
for (p ← one; b ← moving(p)) yield (p, b),
|
||||||
|
for {
|
||||||
|
p ← one; if (unmoved)
|
||||||
|
p2 ← dir(p); if (!board.occupations(p2))
|
||||||
|
b ← moving(p2)
|
||||||
|
} yield (p2, b),
|
||||||
|
capture(_.left),
|
||||||
|
capture(_.right),
|
||||||
|
enpassant(_.left),
|
||||||
|
enpassant(_.right)
|
||||||
|
).flatten toMap
|
||||||
|
} getOrElse Map.empty
|
||||||
|
|
||||||
val moving = (to: Pos) ⇒ board.move(from, to)
|
|
||||||
|
|
||||||
def forward(p: Pos, dir: Direction): List[Implication] = dir(p) match {
|
|
||||||
case None ⇒ Nil
|
|
||||||
case Some(next) if friends(next) ⇒ Nil
|
|
||||||
case Some(next) if enemies(next) ⇒ board.taking(from, next) map { b ⇒
|
|
||||||
(next, b)
|
|
||||||
} toList
|
|
||||||
case Some(next) ⇒ moving(next) map { b ⇒
|
|
||||||
(next, b) :: forward(next, dir)
|
|
||||||
} getOrElse Nil
|
|
||||||
}
|
|
||||||
|
|
||||||
(dirs flatMap { dir ⇒ forward(from, dir) }) toMap
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue