Complete forsyth notation tests and implementation
parent
fdb7cd25fa
commit
1c9d39a2f1
|
@ -1,20 +1,43 @@
|
|||
package lila.chess
|
||||
package format
|
||||
|
||||
import Pos.posAt
|
||||
import Pos.{ posAt, A8 }
|
||||
|
||||
/**
|
||||
* Transform a game to standard Forsyth Edwards Notation
|
||||
* http://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_Notation
|
||||
*/
|
||||
object Forsyth extends Format[Game] {
|
||||
object Forsyth {
|
||||
|
||||
def <<(source: String): Game = {
|
||||
val useful = """\s*([\w\d/]+)\s.+""".r.replaceAllIn(
|
||||
def <<(source: String): Option[Situation] = {
|
||||
|
||||
val boardChars = """\s*([\w\d/]+)\s.+""".r.replaceAllIn(
|
||||
source.replace("/", ""),
|
||||
m ⇒ m group 1
|
||||
)
|
||||
Game()
|
||||
).toList
|
||||
|
||||
val colorOption = for {
|
||||
letter ← """^[\w\d/]+\s(\w).+$""".r.replaceAllIn(source, m ⇒ m group 1).headOption
|
||||
color ← Color(letter)
|
||||
} yield color
|
||||
|
||||
def board(chars: List[Char], pos: Pos): Option[List[(Pos, Piece)]] = chars match {
|
||||
case Nil ⇒ Some(Nil)
|
||||
case c :: rest ⇒ c match {
|
||||
case n if (n.toInt < 58) ⇒
|
||||
tore(pos, n.toInt - 48) flatMap { board(rest, _) }
|
||||
case n ⇒ for {
|
||||
role ← Role forsyth n.toLower
|
||||
} yield (pos, Piece(Color(n.isUpper), role)) :: {
|
||||
tore(pos, 1) flatMap { board(rest, _) } getOrElse Nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
color ← colorOption
|
||||
pieces ← board(boardChars, A8)
|
||||
} yield Situation(Board(pieces), color)
|
||||
}
|
||||
|
||||
def >>(game: Game): String = List(
|
||||
|
@ -34,6 +57,11 @@ object Forsyth extends Format[Game] {
|
|||
game.fullMoveNumber
|
||||
) mkString " "
|
||||
|
||||
def tore(pos: Pos, n: Int): Option[Pos] = posAt(
|
||||
((pos.x + n - 1) % 8 + 1),
|
||||
(pos.y - (pos.x + n - 1) / 8)
|
||||
)
|
||||
|
||||
private def exportBoard(board: Board) = {
|
||||
{
|
||||
for (y ← 8 to 1 by -1) yield {
|
||||
|
|
|
@ -42,34 +42,57 @@ class ForsythTest extends ChessTest {
|
|||
}
|
||||
}
|
||||
"import" in {
|
||||
"torus" in {
|
||||
"A8 + 1" in { f.tore(A8, 1) must_== Some(B8) }
|
||||
"A8 + 2" in { f.tore(A8, 2) must_== Some(C8) }
|
||||
"A8 + 7" in { f.tore(A8, 7) must_== Some(H8) }
|
||||
"A8 + 8" in { f.tore(A8, 8) must_== Some(A7) }
|
||||
"C4 + 3" in { f.tore(C4, 3) must_== Some(F4) }
|
||||
"C4 + 8" in { f.tore(C4, 8) must_== Some(C3) }
|
||||
"F1 + 2" in { f.tore(F1, 2) must_== Some(H1) }
|
||||
}
|
||||
val moves = List(E2 -> E4, C7 -> C5, G1 -> F3, G8 -> H6, A2 -> A3)
|
||||
def compare(ms: List[(Pos, Pos)], fen: String) =
|
||||
Game().playMoveList(ms) must beSuccess.like {
|
||||
case g ⇒ (f << fen) must beSome.like {
|
||||
case situation ⇒ situation.board.visual must_== g.situation.board.visual
|
||||
}
|
||||
}
|
||||
"new game" in {
|
||||
f << "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1" must_== Game()
|
||||
compare(
|
||||
Nil,
|
||||
"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"
|
||||
)
|
||||
}
|
||||
"one move" in {
|
||||
Game().playMoveList(moves take 1) must beSuccess.like {
|
||||
case g ⇒ (f << "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1").situation must_== g.situation
|
||||
}
|
||||
compare(
|
||||
moves take 1,
|
||||
"rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1"
|
||||
)
|
||||
}
|
||||
"2 moves" in {
|
||||
Game().playMoveList(moves take 2) must beSuccess.like {
|
||||
case g ⇒ (f << "rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR w KQkq c6 0 2") must_== g.situation
|
||||
}
|
||||
compare(
|
||||
moves take 2,
|
||||
"rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR w KQkq c6 0 2"
|
||||
)
|
||||
}
|
||||
"3 moves" in {
|
||||
Game().playMoveList(moves take 3) must beSuccess.like {
|
||||
case g ⇒ (f << "rnbqkbnr/pp1ppppp/8/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R b KQkq - 1 2") must_== g.situation
|
||||
}
|
||||
compare(
|
||||
moves take 3,
|
||||
"rnbqkbnr/pp1ppppp/8/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R b KQkq - 1 2"
|
||||
)
|
||||
}
|
||||
"4 moves" in {
|
||||
Game().playMoveList(moves take 4) must beSuccess.like {
|
||||
case g ⇒ (f << "rnbqkb1r/pp1ppppp/7n/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq - 2 3") must_== g.situation
|
||||
}
|
||||
compare(
|
||||
moves take 4,
|
||||
"rnbqkb1r/pp1ppppp/7n/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq - 2 3"
|
||||
)
|
||||
}
|
||||
"5 moves" in {
|
||||
Game().playMoveList(moves take 5) must beSuccess.like {
|
||||
case g ⇒ (f << "rnbqkb1r/pp1ppppp/7n/2p5/4P3/P4N2/1PPP1PPP/RNBQKB1R b KQkq - 0 3") must_== g.situation
|
||||
}
|
||||
compare(
|
||||
moves take 5,
|
||||
"rnbqkb1r/pp1ppppp/7n/2p5/4P3/P4N2/1PPP1PPP/RNBQKB1R b KQkq - 0 3"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue