refactor: replace return/var in castlingTargets with functional style (#4)
Build & Test (NowChessSystems) TeamCity build finished

Reviewed-on: #4
Co-authored-by: Janis <janis.e.20@gmx.de>
Co-committed-by: Janis <janis.e.20@gmx.de>
This commit was merged in pull request #4.
This commit is contained in:
2026-03-25 08:48:49 +01:00
committed by Janis
parent b4116e9a82
commit d675966436
5 changed files with 67 additions and 610 deletions
@@ -132,29 +132,24 @@ object MoveValidator:
val kingSq = Square(File.E, rank)
val enemy = color.opposite
if ctx.board.pieceAt(kingSq) != Some(Piece(color, PieceType.King)) then return Set.empty
if GameRules.isInCheck(ctx.board, color) then return Set.empty
if !ctx.board.pieceAt(kingSq).contains(Piece(color, PieceType.King)) ||
GameRules.isInCheck(ctx.board, color) then Set.empty
else
val kingsideSq = Option.when(
rights.kingSide &&
ctx.board.pieceAt(Square(File.H, rank)).contains(Piece(color, PieceType.Rook)) &&
List(Square(File.F, rank), Square(File.G, rank)).forall(s => ctx.board.pieceAt(s).isEmpty) &&
!List(Square(File.F, rank), Square(File.G, rank)).exists(s => isAttackedBy(ctx.board, s, enemy))
)(Square(File.G, rank))
var result = Set.empty[Square]
val queensideSq = Option.when(
rights.queenSide &&
ctx.board.pieceAt(Square(File.A, rank)).contains(Piece(color, PieceType.Rook)) &&
List(Square(File.B, rank), Square(File.C, rank), Square(File.D, rank)).forall(s => ctx.board.pieceAt(s).isEmpty) &&
!List(Square(File.D, rank), Square(File.C, rank)).exists(s => isAttackedBy(ctx.board, s, enemy))
)(Square(File.C, rank))
if rights.kingSide then
val rookSq = Square(File.H, rank)
val transit = List(Square(File.F, rank), Square(File.G, rank))
if ctx.board.pieceAt(rookSq).contains(Piece(color, PieceType.Rook)) &&
transit.forall(s => ctx.board.pieceAt(s).isEmpty) &&
!transit.exists(s => isAttackedBy(ctx.board, s, enemy)) then
result += Square(File.G, rank)
if rights.queenSide then
val rookSq = Square(File.A, rank)
val emptySquares = List(Square(File.B, rank), Square(File.C, rank), Square(File.D, rank))
val transitSqs = List(Square(File.D, rank), Square(File.C, rank))
if ctx.board.pieceAt(rookSq).contains(Piece(color, PieceType.Rook)) &&
emptySquares.forall(s => ctx.board.pieceAt(s).isEmpty) &&
!transitSqs.exists(s => isAttackedBy(ctx.board, s, enemy)) then
result += Square(File.C, rank)
result
kingsideSq.toSet ++ queensideSq.toSet
def legalTargets(ctx: GameContext, from: Square): Set[Square] =
ctx.board.pieceAt(from) match
@@ -11,21 +11,18 @@ object Renderer:
private val AnsiBlackPiece = "\u001b[30m" // black text
def render(board: Board): String =
val sb = new StringBuilder
sb.append(" a b c d e f g h\n")
for rank <- (0 until 8).reverse do
sb.append(s"${rank + 1} ")
for file <- 0 until 8 do
val sq = Square(File.values(file), Rank.values(rank))
val isLightSq = (file + rank) % 2 != 0
val bgColor = if isLightSq then AnsiLightSquare else AnsiDarkSquare
val cellContent = board.pieceAt(sq) match
val rows = (0 until 8).reverse.map { rank =>
val cells = (0 until 8).map { file =>
val sq = Square(File.values(file), Rank.values(rank))
val isLightSq = (file + rank) % 2 != 0
val bgColor = if isLightSq then AnsiLightSquare else AnsiDarkSquare
board.pieceAt(sq) match
case Some(piece) =>
val fgColor = if piece.color == Color.White then AnsiWhitePiece else AnsiBlackPiece
s"$bgColor$fgColor ${piece.unicode} $AnsiReset"
case None =>
s"$bgColor $AnsiReset"
sb.append(cellContent)
sb.append(s" ${rank + 1}\n")
sb.append(" a b c d e f g h\n")
sb.toString
}.mkString
s"${rank + 1} $cells ${rank + 1}"
}.mkString("\n")
s" a b c d e f g h\n$rows\n a b c d e f g h\n"