Reorganizing moving rules

pull/1/merge
Thibault Duplessis 2012-02-25 14:08:56 +01:00
parent bee9d5a75b
commit a0660900ba
1 changed files with 73 additions and 62 deletions

View File

@ -6,44 +6,14 @@ import scalaz.Success
case class Actor(piece: Piece, pos: Pos, board: Board) {
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 {
(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 -> _)
} flatten
} toMap
case King shortRange(King.dirs) ++ castle
case role if (role.trajectory) trajectory(role.dirs)
case role shortRange(role.dirs)
})
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 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 =
implications filterNot {
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?
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) posTrajectories(role.dirs, pos)
case role (role.dirs map { d d(pos) }).flatten
}) contains to)
private def castle: Implications = {
Map.empty
}
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 {
case None Nil
@ -79,24 +76,38 @@ case class Actor(piece: Piece, pos: Pos, board: Board) {
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
}
}