From c9f532c6fb576941c9ca3eac84f426c953016bd5 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Sat, 25 Feb 2012 00:32:34 +0100 Subject: [PATCH] Tweak trajectories and implications --- src/main/scala/model/Actor.scala | 130 ++++++++++++++--------------- src/main/scala/model/package.scala | 3 + 2 files changed, 66 insertions(+), 67 deletions(-) diff --git a/src/main/scala/model/Actor.scala b/src/main/scala/model/Actor.scala index e0c03d7497..838823550a 100644 --- a/src/main/scala/model/Actor.scala +++ b/src/main/scala/model/Actor.scala @@ -5,67 +5,55 @@ import scalaz.Success case class Actor(piece: Piece, pos: Pos, board: Board) { + def 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 = board move pos + def capture(horizontal: Direction): Option[Implication] = for { + p ← horizontal(next); if (enemies(p)); + b1 ← (board take p toOption) + b2 ← b1 move pos toOption p + } yield (p, b2) + 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) + b1 ← moving toOption targetPos + b2 ← (b1 take victimPos toOption) + } yield (targetPos, b2) + List( + for (p ← one; b ← moving toOption p) yield (p, b), + for { + p ← one; if (unmoved) + p2 ← dir(p); if (!board.occupations(p2)) + b ← moving toOption 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 role ⇒ { + val tos: Set[Pos] = (role.dirs map { d ⇒ d(pos) }).flatten.toSet -- friends + (tos map { to: Pos ⇒ + val nboard = + if (enemies(to)) board take to flatMap (_ move pos to to) + else board move pos to to + nboard.toOption map (to -> _) + }).flatten toMap + } + }) + def moves: Set[Pos] = implications.keySet - def implications: Map[Pos, Board] = { - val implications: Map[Pos, Board] = 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 = board move pos - def capture(horizontal: Direction): Option[(Pos, Board)] = for { - p ← horizontal(next); if (enemies(p)); - b1 ← (board take p toOption) - b2 ← b1 move pos toOption p - } yield (p, b2) - def enpassant(horizontal: Direction): Option[(Pos, Board)] = 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) - b1 ← moving toOption targetPos - b2 ← (b1 take victimPos toOption) - } yield (targetPos, b2) - List( - for (p ← one; b ← moving toOption p) yield (p, b), - for { - p ← one; if (unmoved) - p2 ← dir(p); if (!board.occupations(p2)) - b ← moving toOption 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 role ⇒ { - val tos: Set[Pos] = (role.dirs map { d ⇒ d(pos) }).flatten.toSet -- friends - (tos map { to: Pos ⇒ - val nboard = - if (enemies(to)) board take to flatMap (_ move pos to to) - else board move pos to to - nboard.toOption map (to -> _) - }).flatten toMap - } - } - - kingSafety(implications) - } - - def kingSafety(implications: Map[Pos, Board]): Map[Pos, Board] = { - implications filterNot { - case (pos, nboard) ⇒ nboard actorsOf !color exists { enemy ⇒ - nboard kingPosOf color map (enemy threatens _) getOrElse false - } - } - } - // can it threaten the opponent king? def threatens(to: Pos): Boolean = enemies(to) && threats(to) @@ -84,6 +72,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 + private def kingSafety(implications: Implications): Implications = { + implications filterNot { + case (pos, nboard) ⇒ nboard actorsOf !color exists { enemy ⇒ + nboard kingPosOf color map (enemy threatens _) getOrElse false + } + } + } + private def posTrajectories(dirs: Directions, from: Pos): Set[Pos] = { def forward(p: Pos, dir: Direction): List[Pos] = dir(p) match { @@ -96,22 +92,22 @@ case class Actor(piece: Piece, pos: Pos, board: Board) { dirs flatMap { dir ⇒ forward(from, dir) } toSet } - private def implicationTrajectories(dirs: Directions, from: Pos): Map[Pos, Board] = { + private def implicationTrajectories(dirs: Directions, from: Pos): Implications = { val moving = board move from - def forward(p: Pos, dir: Direction): List[Option[(Pos, Board)]] = dir(p) match { + 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) ⇒ List(for { + case Some(next) if enemies(next) ⇒ (for { b1 ← (board take next toOption) b2 ← b1 move from toOption next - } yield (next, b2)) - case Some(next) ⇒ (for { - b ← moving toOption next - } yield (next, b)) :: forward(next, dir) + } yield next -> b2) toList + case Some(next) ⇒ moving toOption next map { b => + (next, b) :: forward(next, dir) + } getOrElse forward(next, dir) } - (dirs flatMap { dir ⇒ forward(from, dir) }).flatten toMap + (dirs flatMap { dir ⇒ forward(from, dir) }) toMap } } diff --git a/src/main/scala/model/package.scala b/src/main/scala/model/package.scala index 96bfefb556..9d577b1cb7 100644 --- a/src/main/scala/model/package.scala +++ b/src/main/scala/model/package.scala @@ -4,4 +4,7 @@ package object model { type Direction = Pos => Option[Pos] type Directions = List[Direction] + + type Implication = (Pos, Board) + type Implications = Map[Pos, Board] }