From ffd2c6c724acbc5be9842e073e3fd3692101d140 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Sat, 25 Feb 2012 17:10:49 +0100 Subject: [PATCH] Implement and test conditioned pos vectors --- src/main/scala/model/Pos.scala | 25 ++-- src/test/scala/model/BoardTest.scala | 206 +++++---------------------- src/test/scala/model/PosTest.scala | 15 +- 3 files changed, 49 insertions(+), 197 deletions(-) diff --git a/src/main/scala/model/Pos.scala b/src/main/scala/model/Pos.scala index e28bd2fca0..e71f79e225 100644 --- a/src/main/scala/model/Pos.scala +++ b/src/main/scala/model/Pos.scala @@ -3,7 +3,7 @@ package model import scala.math.{ abs, min, max } -sealed case class Pos private(x: Int, y: Int) extends Ordered[Pos] { +sealed case class Pos private (x: Int, y: Int) extends Ordered[Pos] { import Pos.pos @@ -13,8 +13,8 @@ sealed case class Pos private(x: Int, y: Int) extends Ordered[Pos] { lazy val left: Option[Pos] = this < 1 lazy val upLeft: Option[Pos] = up flatMap (_ left) lazy val upRight: Option[Pos] = up flatMap (_ right) - lazy val downLeft: Option[Pos] = down flatMap(_ left) - lazy val downRight: Option[Pos] = down flatMap(_ right) + lazy val downLeft: Option[Pos] = down flatMap (_ left) + lazy val downRight: Option[Pos] = down flatMap (_ right) def ^(n: Int): Option[Pos] = pos(x, y + n) def v(n: Int): Option[Pos] = pos(x, y - n) @@ -24,25 +24,18 @@ sealed case class Pos private(x: Int, y: Int) extends Ordered[Pos] { def |?(other: Pos) = y == other.y def /?(other: Pos) = abs(x - other.x) == abs(y - other.y) def *?(other: Pos) = (this -? other) || (this |? other) || (this /? other) - def ^^(n: Int): List[Pos] = <>(n, Pos.^) - def >>(n: Int): List[Pos] = <>(n, Pos.>) - def vv(n: Int): List[Pos] = <>(n, Pos.v) - def <<(n: Int): List[Pos] = <>(n, Pos.<) - def <>(n: Int, d: Option[Pos] => Option[Pos]): List[Pos] = - expand(n, List(Some(this)), d).flatten reverse + def >|(stop: Pos ⇒ Boolean): List[Pos] = |<>|(stop, _.right) + def |<(stop: Pos ⇒ Boolean): List[Pos] = |<>|(stop, _.left) + def |<>|(stop: Pos ⇒ Boolean, dir: Direction): List[Pos] = dir(this) map { p ⇒ + p :: (if (stop(p)) Nil else p.|<>|(stop, dir)) + } getOrElse Nil def xToString = Pos xToString x - def yToString = y.toString + def yToString = y.toString override def toString = xToString + yToString def compare(other: Pos) = toString compare other.toString - - private def expand(i: Int, accumulator: List[Option[Pos]], direct: Option[Pos] ⇒ Option[Pos]): List[Option[Pos]] = { - if (i > 0 && accumulator.head.isDefined) - expand(i - 1, direct(accumulator.head) :: accumulator, direct) - else accumulator - } } object Pos { diff --git a/src/test/scala/model/BoardTest.scala b/src/test/scala/model/BoardTest.scala index a59e42d66f..55ffc92112 100644 --- a/src/test/scala/model/BoardTest.scala +++ b/src/test/scala/model/BoardTest.scala @@ -67,190 +67,56 @@ class BoardTest extends LilaSpec { "allow chaining actions" in { Board.empty.seq( - _ place White-Pawn at A2, - _ place White-Pawn at A3, + _ place White - Pawn at A2, + _ place White - Pawn at A3, _ move A2 to A4 ) must beSuccess.like { - case b => b(A4) mustEqual Some(White-Pawn) - } + case b ⇒ b(A4) mustEqual Some(White - Pawn) + } } "fail on bad actions chain" in { Board.empty.seq( - _ place White-Pawn at A2, - _ place White-Pawn at A3, + _ place White - Pawn at A2, + _ place White - Pawn at A3, _ move B2 to B4 ) must beFailure } "provide occupation map" in { Board( - A2 -> (White-Pawn), - A3 -> (White-Pawn), - D1 -> (White-King), - E8 -> (Black-King), - H4 -> (Black-Queen) + A2 -> (White - Pawn), + A3 -> (White - Pawn), + D1 -> (White - King), + E8 -> (Black - King), + H4 -> (Black - Queen) ).occupation must havePairs( - White -> Set(A2, A3, D1), - Black -> Set(E8, H4) - ) + White -> Set(A2, A3, D1), + Black -> Set(E8, H4) + ) } - //"advise which positions currently threaten a given position, given a side (opposing pawns)" in { - //val newBoard = board.place(White-Pawn).at(F6) - //(newBoard threatsTo Black at G7) must containPositions(F6) - //} - - //"advise which positions currently threaten a given position, given a side (opposing non-threatening piece)" in { - //val newBoard = board.place(White-Knight).at(F6) - //(newBoard threatsTo Black at G7) must beEmpty - //} - - //"advise which positions currently threaten a given position, given a side (multiple pawn opponents)" in { - //val newBoard = board.place(White-Pawn).at(F6).place(White-Pawn).at(H6) - //(newBoard threatsTo Black at G7) must containPositions(F6, H6) - //} - - //"advise which positions currently threaten a given position, given a side (same side pawns)" in { - //val newBoard = board.place(Black-Pawn).at(F6) - //(newBoard threatsTo Black at G7) must beEmpty - //} - - //"advise which positions currently threaten a given position, given a side (opposing rooks)" in { - //val newBoard = board.place(White-Rook).at(B5) - //(newBoard threatsTo Black at A5) must containPositions(B5) - //(newBoard threatsTo Black at H5) must containPositions(B5) - //(newBoard threatsTo Black at B8) must containPositions(B5) - //(newBoard threatsTo Black at B1) must containPositions(B5) - //} - - //"advise which positions currently threaten a given position, given a side (same side rooks)" in { - //val newBoard = board.place(Black-Rook).at(B5) - //(newBoard threatsTo Black at A5) must beEmpty - //(newBoard threatsTo Black at H5) must beEmpty - //(newBoard threatsTo Black at B8) must beEmpty - //(newBoard threatsTo Black at B1) must beEmpty - //} - - //"advise which positions currently threaten a given position, given a side (eclipsed rook)" in { - //val newBoard = board.place(White-Rook).at(B5).place(Black-Rook).at(D5) - //(newBoard threatsTo Black at E5) must beEmpty - //(newBoard threatsTo Black at D5) must containPositions(B5) - //(newBoard threatsTo Black at C5) must containPositions(B5) - //(newBoard threatsTo Black at B5) must beEmpty - //} - - //"advise which positions currently threaten a given position, given a side (opposing bishops)" in { - //val newBoard = board.place(Black-Bishop).at(F7) - //(newBoard threatsTo White at G8) must containPositions(F7) - //(newBoard threatsTo White at G6) must containPositions(F7) - //(newBoard threatsTo White at E8) must containPositions(F7) - //(newBoard threatsTo White at A2) must containPositions(F7) - //} - - //"advise which positions currently threaten a given position, given a side (same side bishops)" in { - //val newBoard = board.place(Black-Bishop).at(D6) - //(newBoard threatsTo Black at F4) must beEmpty - //(newBoard threatsTo Black at F8) must beEmpty - //(newBoard threatsTo Black at B8) must beEmpty - //(newBoard threatsTo Black at B4) must beEmpty - //} - - //"advise which positions currently threaten a given position, given a side (eclipsed bishops)" in { - //val newBoard = board.place(White-Rook).at(B5).place(Black-Bishop).at(D7) - //(newBoard threatsTo White at A4) must beEmpty - //(newBoard threatsTo White at B5) must containPositions(D7) - //(newBoard threatsTo White at C6) must containPositions(D7) - //(newBoard threatsTo White at D7) must beEmpty - //} - - //"advise which positions currently threaten a given position, given a side (opposing queens on rank/file)" in { - //val newBoard = board.place(White-Queen).at(B5) - //(newBoard threatsTo Black at A5) must containPositions(B5) - //(newBoard threatsTo Black at H5) must containPositions(B5) - //(newBoard threatsTo Black at B8) must containPositions(B5) - //(newBoard threatsTo Black at B1) must containPositions(B5) - //} - - //"advise which positions currently threaten a given position, given a side (same side queen on rank/file)" in { - //val newBoard = board.place(Black-Queen).at(B5) - //(newBoard threatsTo Black at A5) must beEmpty - //(newBoard threatsTo Black at H5) must beEmpty - //(newBoard threatsTo Black at B8) must beEmpty - //(newBoard threatsTo Black at B1) must beEmpty - //} - - //"advise which positions currently threaten a given position, given a side (eclipsed queen on rank/file)" in { - //val newBoard = board.place(White-Queen).at(B5).place(Black-Rook).at(D5) - //(newBoard threatsTo Black at E5) must beEmpty - //(newBoard threatsTo Black at D5) must containPositions(B5) - //(newBoard threatsTo Black at C5) must containPositions(B5) - //(newBoard threatsTo Black at B5) must beEmpty - //} - - //"advise which positions currently threaten a given position, given a side (opposing queens on diagonal)" in { - //val newBoard = board.place(Black-Queen).at(F7) - //(newBoard threatsTo White at G8) must containPositions(F7) - //(newBoard threatsTo White at G6) must containPositions(F7) - //(newBoard threatsTo White at E8) must containPositions(F7) - //(newBoard threatsTo White at A2) must containPositions(F7) - //} - - //"advise which positions currently threaten a given position, given a side (same side queen on diagonal)" in { - //val newBoard = board.place(Black-Queen).at(D6) - //(newBoard threatsTo Black at F4) must beEmpty - //(newBoard threatsTo Black at F8) must beEmpty - //(newBoard threatsTo Black at B8) must beEmpty - //(newBoard threatsTo Black at B4) must beEmpty - //} - - //"advise which positions currently threaten a given position, given a side (eclipsed queen on diagonal)" in { - //val newBoard = board.place(White-Rook).at(B5).place(Black-Queen).at(D7) - //(newBoard threatsTo White at A4) must beEmpty - //(newBoard threatsTo White at B5) must containPositions(D7) - //(newBoard threatsTo White at C6) must containPositions(D7) - //(newBoard threatsTo White at D7) must beEmpty - //} - //} - - //"advise which positions currently threaten a given position, given a side (opposing knights)" in { - //val newBoard = board.place(Black-Knight).at(F7) - //(newBoard threatsTo White at D8) must containPositions(F7) - //(newBoard threatsTo White at H8) must containPositions(F7) - //(newBoard threatsTo White at D6) must containPositions(F7) - //(newBoard threatsTo White at H6) must containPositions(F7) - //(newBoard threatsTo White at E5) must containPositions(F7) - //(newBoard threatsTo White at G5) must containPositions(F7) - //} - - //"advise which positions currently threaten a given position, given a side (same side knights)" in { - //val newBoard = board.place(Black-Knight).at(F7) - //(newBoard threatsTo Black at D8) must beEmpty - //(newBoard threatsTo Black at H8) must beEmpty - //(newBoard threatsTo Black at D6) must beEmpty - //(newBoard threatsTo Black at H6) must beEmpty - //(newBoard threatsTo Black at E5) must beEmpty - //(newBoard threatsTo Black at G5) must beEmpty - //} - - //"advise which positions currently threaten a given position, given a side (opposing kings)" in { - //val newBoard = board.place(Black-King).at(B4) - //(newBoard threatsTo White at B3) must containPositions(B4) - //(newBoard threatsTo White at B5) must containPositions(B4) - //(newBoard threatsTo White at A3) must containPositions(B4) - //(newBoard threatsTo White at A4) must containPositions(B4) - //(newBoard threatsTo White at A5) must containPositions(B4) - //(newBoard threatsTo White at C3) must containPositions(B4) - //(newBoard threatsTo White at C4) must containPositions(B4) - //(newBoard threatsTo White at C5) must containPositions(B4) - //} - - //"advise which positions currently threaten a given position, given a side (same side kings)" in { - //val newBoard = board.place(Black-King).at(A3) - //(newBoard threatsTo Black at A4) must beEmpty - //(newBoard threatsTo Black at A2) must beEmpty - //(newBoard threatsTo Black at B2) must beEmpty - //(newBoard threatsTo Black at B3) must beEmpty - //(newBoard threatsTo Black at B4) must beEmpty + "navigate in pos based on pieces" in { + "right to end" in { + val board: Board = """ +R K R""" + E1 >| (p ⇒ board occupations p) must_== List(F1, G1, H1) + } + "right to next" in { + val board: Board = """ +R KB R""" + E1 >| (p ⇒ board occupations p) must_== List(F1) + } + "left to end" in { + val board: Board = """ +R K R""" + E1 |< (p ⇒ board occupations p) must_== List(D1, C1, B1, A1) + } + "right to next" in { + val board: Board = """ +R BK R""" + E1 |< (p ⇒ board occupations p) must_== List(D1) + } + } } } diff --git a/src/test/scala/model/PosTest.scala b/src/test/scala/model/PosTest.scala index d3e7a923a8..773648ec05 100644 --- a/src/test/scala/model/PosTest.scala +++ b/src/test/scala/model/PosTest.scala @@ -36,17 +36,10 @@ class PosTest extends LilaSpec { } "be used to derive a relative list of positions" in { - "D4 ^^ 3" in { D4 ^^ 3 must contain(D4, D5, D6, D7) } - "D4 >> 3" in { D4 >> 3 must contain(D4, E4, F4, G4) } - "D4 vv 3" in { D4 vv 3 must contain(D4, D3, D2, D1) } - "D4 << 3" in { D4 << 3 must contain(D4, C4, B4, A4) } - } - - "be used to derive a relative list of positions not including those off the board" in { - "D4 ^^ 8" in { D4 ^^ 8 must contain(D4, D5, D6, D7, D8) } - "D4 >> 8" in { D4 >> 8 must contain(D4, E4, F4, G4, H4) } - "D4 vv 8" in { D4 vv 8 must contain(D4, D3, D2, D1) } - "D4 << 8" in { D4 << 8 must contain(D4, C4, B4, A4) } + "D4 >| false" in { D4 >| (_ ⇒ false) must contain(E4, F4, G4, H4) } + "D4 |< false" in { D4 |< (_ ⇒ false) must contain(C4, B4, A4) } + "D4 >| (==G4)" in { D4 >| (G4 ==) must contain(E4, F4, G4) } + "D4 |< (==C4)" in { D4 |< (C4 ==) must contain(C4) } } "be a string" in {