feat: Implement threefold repetition detection and update game rules
Build & Test (NowChessSystems) TeamCity build failed

This commit is contained in:
2026-04-16 21:00:32 +02:00
parent 5aa1691b32
commit f8d2858d98
21 changed files with 137 additions and 21633 deletions
+11
View File
@@ -44,3 +44,14 @@
### Bug Fixes
* NCS-32 Queenside Castle doesn't care about pieces in the way ([#23](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/23)) ([fe8e3c0](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fe8e3c05397f433bfa34d1999e9738c82790adf7))
## (2026-04-16)
### Features
* NCS-13 Implement Threefold Repetition ([#31](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/31)) ([767d305](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/767d3051a76c266050b6335774d66e2db2273c16))
* NCS-14 implemented insufficient moves rule ([#30](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/30)) ([b0399a4](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b0399a4e489950083066c9538df9a84dcc7a4613))
* NCS-25 Add linters to keep quality up ([#27](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/27)) ([fd4e67d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fd4e67d4f782a7e955822d90cb909d0a81676fb2))
### Bug Fixes
* NCS-32 Queenside Castle doesn't care about pieces in the way ([#23](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/23)) ([fe8e3c0](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fe8e3c05397f433bfa34d1999e9738c82790adf7))
@@ -458,18 +458,11 @@ object DefaultRules extends RuleSet:
private def squareColor(sq: Square): Int = (sq.file.ordinal + sq.rank.ordinal) % 2
private def insufficientMaterial(board: Board): Boolean =
val nonKings = board.pieces.toList.filter(_._2.pieceType != PieceType.King)
val nonKings = board.pieces.toList.filter { case (_, p) => p.pieceType != PieceType.King }
nonKings match
case Nil => true
case Nil => true
case List((_, p)) if p.pieceType == PieceType.Bishop || p.pieceType == PieceType.Knight => true
case List((sq1, p1), (sq2, p2))
if p1.pieceType == PieceType.Bishop && p2.pieceType == PieceType.Bishop
&& p1.color != p2.color
&& squareColor(sq1) == squareColor(sq2) =>
true
case bishops
if bishops.forall(_._2.pieceType == PieceType.Bishop)
&& bishops.map(_._2.color).distinct.size == 1
&& bishops.map(e => squareColor(e._1)).distinct.size == 1 =>
true
case bishops if bishops.forall { case (_, p) => p.pieceType == PieceType.Bishop } =>
// All non-king pieces are bishops: draw only if they all share the same square color
bishops.map { case (sq, _) => squareColor(sq) }.distinct.sizeIs == 1
case _ => false
@@ -29,15 +29,10 @@ class DefaultRulesTest extends AnyFunSuite with Matchers:
test("pawn can capture diagonally"):
// FEN: white pawn e4, black pawn d5
val fen = "8/8/8/3p4/4P3/8/8/8 w - - 0 1"
val context = FenParser.parseFen(fen).fold(_ => fail(), identity)
val moves = rules.allLegalMoves(context)
val captures = moves.filter { m =>
m.from == Square(File.E, Rank.R4) && (m.moveType match
case _: MoveType.Normal => true
case _ => false
)
}
val fen = "8/8/8/3p4/4P3/8/8/8 w - - 0 1"
val context = FenParser.parseFen(fen).fold(_ => fail(), identity)
val moves = rules.allLegalMoves(context)
val captures = moves.filter(m => m.from == Square(File.E, Rank.R4) && (m.moveType match { case _: MoveType.Normal => true; case _ => false }))
captures.exists(m => m.to == Square(File.D, Rank.R5)) shouldBe true
test("pawn cannot move backward"):
+1 -1
View File
@@ -1,3 +1,3 @@
MAJOR=0
MINOR=2
MINOR=3
PATCH=0