makeMove method
Make a move and modify the game state. Returns true if the move was valid
and made successfully.
generateMeta
determines whether to generate the BishopState.moveMeta
field. Set this to false for more efficient calculations.
Implementation
bool makeMove(Move move, [bool generateMeta = true]) {
BishopState state = this.state;
Square fromSq =
move.from >= Bishop.boardStart ? state.board[move.from] : Bishop.empty;
if (variant.hasActionsForEvent(ActionEvent.beforeMove)) {
state = state.executeActions(
trigger: ActionTrigger(
event: ActionEvent.beforeMove,
variant: variant,
state: state,
move: move,
piece: move.dropPiece ?? fromSq,
),
zobrist: zobrist,
);
}
if (state.invalidMove) return false;
BishopState? newState;
if (move is GatingMove) {
newState = makeGatingMove(state, move);
} else if (move is StandardMove || move is DropMove) {
newState = makeStandardMove(state, move);
} else if (move is PassMove) {
newState = makePassMove(state, move);
} else {
newState = variant.makeCustomMove(
MoveProcessorParams(state: state, move: move, zobrist: zobrist),
);
}
if (newState == null) return false;
if (variant.hasActionsForEvent(ActionEvent.afterMove)) {
newState = newState.executeActions(
trigger: ActionTrigger(
event: ActionEvent.afterMove,
variant: variant,
state: newState,
move: move,
piece: move.promoPiece ?? move.dropPiece ?? fromSq,
),
zobrist: zobrist,
);
}
final moveMeta = generateMeta
? MoveMeta(
algebraic: toAlgebraic(move),
formatted: toSan(move),
)
: null;
history.add(newState);
// todo: move this to before history.add (above) when move generation
// becomes part of state (i.e. not dependent on current state)
// probably after dart 3 cos records
// basically this sucks because methods depend on the state of the game
// instead of applying to specific states
if (generateMeta) {
history.last = newState.copyWith(
meta: StateMeta(
variant: variant,
moveMeta: moveMeta,
checks: [
getKingAttackers(Bishop.white),
getKingAttackers(Bishop.black),
],
),
);
}
if (newState.invalidMove) return false;
// kind of messy doing it like this, but inCheck depends on the current state
// maybe that's a case for refactoring some methods into State?
bool countChecks =
variant.gameEndConditions[newState.turn.opponent].checkLimit != null;
if (variant.forbidChecks || countChecks) {
bool isInCheck = inCheck;
if (isInCheck) {
if (countChecks) {
history.last = newState.copyWith(
checks: List.from(newState.checks)..[newState.turn.opponent] += 1,
);
}
if (variant.forbidChecks) {
return false;
}
}
}
zobrist.incrementHash(newState.hash);
return true;
}