computeLegalMoves function

List<LudoLegalMove> computeLegalMoves(
  1. LudoGameState state,
  2. LudoDiceRules diceRules,
  3. int diceValue, {
  4. List<LudoTeam>? teams,
})

Computes all legal moves for the current player given diceValue.

Teams mode additions:

  • A piece may land on a cell occupied by a teammate (friendly stack).
  • A piece may NOT land on a safe cell occupied by ANY opponent (safe cell protection still applies).
  • A piece MAY land on a non-safe cell occupied by opponents (triggering a capture).

teams — pass null for standard mode.

Implementation

List<LudoLegalMove> computeLegalMoves(
  LudoGameState state,
  LudoDiceRules diceRules,
  int diceValue, {
  List<LudoTeam>? teams,
}) {
  final moves       = <LudoLegalMove>[];
  final playerIndex = state.currentPlayerIndex;
  final myPieces    = state.pieces.where((p) => p.playerIndex == playerIndex);

  for (final piece in myPieces) {
    if (piece.isFinished) continue;

    if (piece.isHome) {
      // Can only leave home on an allowed start value.
      if (!diceRules.startAllowedValues.contains(diceValue)) continue;

      // Starting cell — check it's not blocked by an opponent safe-stack.
      if (_isBlockedByOpponent(
        playerIndex: playerIndex,
        trackPosition: 0,
        pieces: state.pieces,
        teams: teams,
      )) {
        continue;
      }

      moves.add(LudoLegalMove(
        pieceId: piece.id,
        playerIndex: playerIndex,
        fromPosition: LudoPiece.home,
        toPosition: 0,
      ));
      continue;
    }

    // On-board piece — advance by diceValue.
    final newPos = piece.trackPosition + diceValue;

    // Cannot overshoot the finish.
    if (newPos > LudoPiece.finished) continue;

    // Cannot land on a cell blocked by an opponent on a safe cell.
    if (newPos < LudoPiece.sharedPathSpan &&
        _isBlockedByOpponent(
          playerIndex: playerIndex,
          trackPosition: newPos,
          pieces: state.pieces,
          teams: teams,
        )) {
      continue;
    }

    moves.add(LudoLegalMove(
      pieceId: piece.id,
      playerIndex: playerIndex,
      fromPosition: piece.trackPosition,
      toPosition: newPos,
    ));
  }

  return moves;
}