fen property

String fen

Implementation

String get fen {
  assert(board.length == variant.boardSize.numIndices);
  String fen = '';
  int empty = 0;

  void addEmptySquares() {
    if (empty > 0) {
      fen = '$fen$empty';
      empty = 0;
    }
  }

  for (int i = 0; i < variant.boardSize.v; i++) {
    for (int j = 0; j < variant.boardSize.h; j++) {
      int s = (i * variant.boardSize.h * 2) + j;
      Square sq = board[s];
      if (sq.isEmpty) {
        empty++;
      } else {
        if (empty > 0) addEmptySquares();
        String char = variant.pieces[sq.type].char(sq.colour);
        if (variant.outputOptions.showPromoted && sq.hasInternalType) {
          char += '~';
        }
        fen = '$fen$char';
      }
    }
    if (empty > 0) addEmptySquares();
    if (i < variant.boardSize.v - 1) fen = '$fen/';
  }
  if (variant.handsEnabled) {
    fen = '$fen[$handString]';
  }
  if (variant.gatingMode == GatingMode.flex) {
    String whiteGate = state.gates![Bishop.white]
        .map((p) => variant.pieces[p].symbol.toUpperCase())
        .join('');
    String blackGate = state.gates![Bishop.black]
        .map((p) => variant.pieces[p].symbol.toLowerCase())
        .join('');
    fen = '$fen[$whiteGate$blackGate]';
  }
  if (variant.gatingMode == GatingMode.fixed) {
    String whiteGate = state.gates![Bishop.white]
        .map((p) => variant.pieces[p].symbol.toUpperCase())
        .join('');
    String blackGate = state.gates![Bishop.black]
        .map((p) => variant.pieces[p].symbol.toLowerCase())
        .join('');
    // replaces dots with numbers
    String processGate(String g) {
      String o = '';
      int n = 0;
      for (String c in g.split('')) {
        if (c == '.') {
          n++;
        } else {
          if (n > 0) {
            o = '$o$n';
            n = 0;
          }
          o = '$o$c';
        }
      }
      if (n > 0) {
        o = '$o$n';
      }
      return o;
    }

    whiteGate = processGate(whiteGate);
    blackGate = processGate(blackGate);

    fen = '$blackGate/$fen/$whiteGate';
  }
  String turnStr = state.turn == Bishop.white ? 'w' : 'b';
  String castling = state.castlingRights.formatted;
  if (variant.outputOptions.castlingFormat == CastlingFormat.shredder) {
    castling = replaceMultiple(
      castling,
      Castling.symbols.keys.toList(),
      castlingFileSymbols,
    );
  }
  if (variant.outputOptions.virginFiles) {
    String whiteVFiles = state.virginFiles[Bishop.white]
        .map((e) => fileSymbol(e).toUpperCase())
        .join('');
    String blackVFiles =
        state.virginFiles[Bishop.black].map((e) => fileSymbol(e)).join('');
    castling = '$castling$whiteVFiles$blackVFiles';
  }
  String ep = state.epSquare != null ? size.squareName(state.epSquare!) : '-';
  String aux = '';
  if (variant.gameEndConditions.hasCheckLimit) {
    aux = ' +${state.checks[Bishop.white]}+${state.checks[Bishop.black]}';
  }
  fen =
      '$fen $turnStr $castling $ep ${state.halfMoves} ${state.fullMoves}$aux';
  return fen;
}