refactor: NCS-19 Currying (#18)
Summary - Curried candidateMoves, legalMoves, and applyMove in the RuleSet trait to separate (context) as the world being operated on from the computation parameter - Updated DefaultRules overrides and all internal call sites - Updated all external call sites: GameEngine, PgnParser, PgnExporter, ChessBoardView, and all affected tests Test plan - All existing tests pass (./gradlew build) - No behaviour changes — pure style refactoring, existing test suite is the regression guard Co-authored-by: LQ63 <lkhermann@web.de> Reviewed-on: #18 Reviewed-by: Janis <janis-e@gmx.de> Co-authored-by: Leon Hermann <lq@blackhole.local> Co-committed-by: Leon Hermann <lq@blackhole.local>
This commit is contained in:
@@ -88,7 +88,7 @@ class GameEngine(
|
||||
case Some(piece) if piece.color != currentContext.turn =>
|
||||
notifyObservers(InvalidMoveEvent(currentContext, "That is not your piece."))
|
||||
case Some(piece) =>
|
||||
val legal = ruleSet.legalMoves(currentContext, from)
|
||||
val legal = ruleSet.legalMoves(currentContext)(from)
|
||||
// Find all legal moves going to `to`
|
||||
val candidates = legal.filter(_.to == to)
|
||||
candidates match
|
||||
@@ -119,7 +119,7 @@ class GameEngine(
|
||||
pendingPromotion = None
|
||||
val move = Move(pending.from, pending.to, MoveType.Promotion(piece))
|
||||
// Verify it's actually legal
|
||||
val legal = ruleSet.legalMoves(currentContext, pending.from)
|
||||
val legal = ruleSet.legalMoves(currentContext)(pending.from)
|
||||
if legal.contains(move) then
|
||||
executeMove(move)
|
||||
else
|
||||
@@ -203,7 +203,7 @@ class GameEngine(
|
||||
|
||||
private def executeMove(move: Move): Unit =
|
||||
val contextBefore = currentContext
|
||||
val nextContext = ruleSet.applyMove(currentContext, move)
|
||||
val nextContext = ruleSet.applyMove(currentContext)(move)
|
||||
val captured = computeCaptured(currentContext, move)
|
||||
|
||||
val cmd = MoveCommand(
|
||||
|
||||
+6
-6
@@ -89,8 +89,8 @@ class GameEngineIntegrationTest extends AnyFunSuite with Matchers:
|
||||
val promotionMove = Move(sq("e2"), sq("e8"), MoveType.Promotion(PromotionPiece.Queen))
|
||||
|
||||
val permissiveRules = new RuleSet:
|
||||
def candidateMoves(context: GameContext, square: Square): List[Move] = legalMoves(context, square)
|
||||
def legalMoves(context: GameContext, square: Square): List[Move] =
|
||||
def candidateMoves(context: GameContext)(square: Square): List[Move] = legalMoves(context)(square)
|
||||
def legalMoves(context: GameContext)(square: Square): List[Move] =
|
||||
if square == sq("e2") then List(promotionMove) else List.empty
|
||||
def allLegalMoves(context: GameContext): List[Move] = List(promotionMove)
|
||||
def isCheck(context: GameContext): Boolean = false
|
||||
@@ -98,7 +98,7 @@ class GameEngineIntegrationTest extends AnyFunSuite with Matchers:
|
||||
def isStalemate(context: GameContext): Boolean = false
|
||||
def isInsufficientMaterial(context: GameContext): Boolean = false
|
||||
def isFiftyMoveRule(context: GameContext): Boolean = false
|
||||
def applyMove(context: GameContext, move: Move): GameContext = DefaultRules.applyMove(context, move)
|
||||
def applyMove(context: GameContext)(move: Move): GameContext = DefaultRules.applyMove(context)(move)
|
||||
|
||||
val engine = new GameEngine(ruleSet = permissiveRules)
|
||||
val importer = new GameContextImport:
|
||||
@@ -111,15 +111,15 @@ class GameEngineIntegrationTest extends AnyFunSuite with Matchers:
|
||||
test("loadGame replay restores previous context when promotion cannot be completed"):
|
||||
val promotionMove = Move(sq("e2"), sq("e8"), MoveType.Promotion(PromotionPiece.Queen))
|
||||
val noLegalMoves = new RuleSet:
|
||||
def candidateMoves(context: GameContext, square: Square): List[Move] = List.empty
|
||||
def legalMoves(context: GameContext, square: Square): List[Move] = List.empty
|
||||
def candidateMoves(context: GameContext)(square: Square): List[Move] = List.empty
|
||||
def legalMoves(context: GameContext)(square: Square): List[Move] = List.empty
|
||||
def allLegalMoves(context: GameContext): List[Move] = List.empty
|
||||
def isCheck(context: GameContext): Boolean = false
|
||||
def isCheckmate(context: GameContext): Boolean = false
|
||||
def isStalemate(context: GameContext): Boolean = false
|
||||
def isInsufficientMaterial(context: GameContext): Boolean = false
|
||||
def isFiftyMoveRule(context: GameContext): Boolean = false
|
||||
def applyMove(context: GameContext, move: Move): GameContext = context
|
||||
def applyMove(context: GameContext)(move: Move): GameContext = context
|
||||
|
||||
val engine = new GameEngine(ruleSet = noLegalMoves)
|
||||
engine.processUserInput("e2e4")
|
||||
|
||||
@@ -153,10 +153,10 @@ class GameEnginePromotionTest extends AnyFunSuite with Matchers:
|
||||
// This makes completePromotion unable to find Move(from, to, Promotion(Queen)),
|
||||
// triggering the "Error completing promotion." branch.
|
||||
val delegatingRuleSet: RuleSet = new RuleSet:
|
||||
def candidateMoves(context: GameContext, square: Square): List[Move] =
|
||||
DefaultRules.candidateMoves(context, square)
|
||||
def legalMoves(context: GameContext, square: Square): List[Move] =
|
||||
DefaultRules.legalMoves(context, square).map { m =>
|
||||
def candidateMoves(context: GameContext)(square: Square): List[Move] =
|
||||
DefaultRules.candidateMoves(context)(square)
|
||||
def legalMoves(context: GameContext)(square: Square): List[Move] =
|
||||
DefaultRules.legalMoves(context)(square).map { m =>
|
||||
m.moveType match
|
||||
case MoveType.Promotion(_) => Move(m.from, m.to, MoveType.Normal())
|
||||
case _ => m
|
||||
@@ -173,8 +173,8 @@ class GameEnginePromotionTest extends AnyFunSuite with Matchers:
|
||||
DefaultRules.isInsufficientMaterial(context)
|
||||
def isFiftyMoveRule(context: GameContext): Boolean =
|
||||
DefaultRules.isFiftyMoveRule(context)
|
||||
def applyMove(context: GameContext, move: Move): GameContext =
|
||||
DefaultRules.applyMove(context, move)
|
||||
def applyMove(context: GameContext)(move: Move): GameContext =
|
||||
DefaultRules.applyMove(context)(move)
|
||||
|
||||
val promotionBoard = FenParser.parseBoard("8/4P3/4k3/8/8/8/8/8").get
|
||||
val initialCtx = GameContext.initial.withBoard(promotionBoard).withTurn(Color.White)
|
||||
|
||||
Reference in New Issue
Block a user