Files

99 lines
3.1 KiB
Scala

package gambit
object Fen:
val startPosition = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"
def parse(fen: String): Position =
val parts = fen.trim.split("\\s+")
val pos = new Position
var rank = 7
for row <- parts(0).split("/") do
var file = 0
for ch <- row do
if ch.isDigit then file += (ch - '0')
else
val piece = charToPiece(ch)
val sq = Square.make(file, rank)
pos.board(sq) = piece
if (piece & 7) == Piece.King then pos.kingSquare(piece >> 3) = sq
file += 1
rank -= 1
pos.sideToMove = if parts(1) == "w" then Color.White else Color.Black
var castle = 0
if parts(2) != "-" then
for ch <- parts(2) do
ch match
case 'K' => castle |= Castling.WhiteKing
case 'Q' => castle |= Castling.WhiteQueen
case 'k' => castle |= Castling.BlackKing
case 'q' => castle |= Castling.BlackQueen
case _ => ()
pos.castling = castle
pos.epSquare = if parts(3) == "-" then -1 else Square.fromName(parts(3))
pos.halfmove = if parts.length > 4 then parts(4).toInt else 0
pos.fullmove = if parts.length > 5 then parts(5).toInt else 1
pos.hash = pos.computeHash()
pos
def toFen(pos: Position): String =
val sb = new StringBuilder
var rank = 7
while rank >= 0 do
var empty = 0
var file = 0
while file < 8 do
val p = pos.board(Square.make(file, rank))
if p == Piece.Empty then empty += 1
else
if empty > 0 then
sb.append(empty)
empty = 0
sb.append(pieceToChar(p))
file += 1
if empty > 0 then sb.append(empty)
if rank > 0 then sb.append('/')
rank -= 1
sb.append(' ')
sb.append(if pos.sideToMove == Color.White then 'w' else 'b')
sb.append(' ')
if pos.castling == 0 then sb.append('-')
else
if (pos.castling & Castling.WhiteKing) != 0 then sb.append('K')
if (pos.castling & Castling.WhiteQueen) != 0 then sb.append('Q')
if (pos.castling & Castling.BlackKing) != 0 then sb.append('k')
if (pos.castling & Castling.BlackQueen) != 0 then sb.append('q')
sb.append(' ')
sb.append(if pos.epSquare < 0 then "-" else Square.name(pos.epSquare))
sb.append(' ')
sb.append(pos.halfmove)
sb.append(' ')
sb.append(pos.fullmove)
sb.toString
private def charToPiece(ch: Char): Int =
val color = if ch.isUpper then Color.White else Color.Black
val pieceType = ch.toLower match
case 'p' => Piece.Pawn
case 'n' => Piece.Knight
case 'b' => Piece.Bishop
case 'r' => Piece.Rook
case 'q' => Piece.Queen
case 'k' => Piece.King
case _ => Piece.Empty
Piece.make(color, pieceType)
private def pieceToChar(piece: Int): Char =
val letter = Piece.typeOf(piece) match
case Piece.Pawn => 'p'
case Piece.Knight => 'n'
case Piece.Bishop => 'b'
case Piece.Rook => 'r'
case Piece.Queen => 'q'
case Piece.King => 'k'
case _ => '?'
if Piece.colorOf(piece) == Color.White then letter.toUpper else letter