Como saber quando uma posição da FEN é legal?

19

Estou fazendo um projeto pessoal, no qual, a certa altura, preciso validar a posição FEN, comecei com algumas verificações básicas, como verificar se há reis e garantir que não haja linhas ou colunas extras e esse tipo de coisas.

Mas que outras verificações devo fazer para garantir que uma FEN seja legal?

ajax333221
fonte

Respostas:

18

Aqui está uma lista bem organizada que deve validar 99,99% + das posições comuns:

Borda:

  • Existem exatamente 8 cols
  • A soma dos quadrados e das peças vazias é adicionada a 8 para cada classificação (linha)
  • Não há números consecutivos para quadrados vazios

Reis:

  • Veja se existe exatamente um w_king e um b_king
  • Certifique-se de que os reis estejam separados 1 quadrado

Verificações:

  • Cor não ativa não está em cheque
  • A cor ativa é verificada menos de 3 vezes (a verificação tripla é impossível); no caso de 2, nunca é peão + (peão, bispo, cavaleiro), bispo + bispo, cavaleiro + cavaleiro

Peões:

  • Não há mais de 8 peões de cada cor
  • Não há peões na primeira ou na última fila (linha), pois eles estão em uma posição inicial incorreta ou deveriam ter sido promovidos.
  • No caso de uma praça passante; veja se ele foi criado legalmente (por exemplo, deve estar no x3ou x6rank, deve haver um peão (da cor correta) na frente e o quadrado en passant e o que está atrás dele estão vazios)
  • Evite ter mais peças promovidas do que peões perdidos (por exemplo, extra_pieces = Math.max(0, num_queens-1) + Math.max(0, num_rooks-2)...e então extra_pieces <= (8-num_pawns)), também faça cálculos especiais para os bispos. Se você tem dois (ou mais) bispos da mesma cor quadrada, eles só podem ser criados através da promoção de peões e você deve incluir esta informação para a fórmula acima de alguma forma
  • É possível alcançar a formação de peões (por exemplo, no caso de vários peões em uma única coluna, deve haver peças inimigas suficientes para fazer essa formação), eis algumas regras úteis:
    1. é impossível ter mais de 6 peões em um único arquivo (coluna) (porque os peões não podem existir na primeira e na última fila)
    2. o número mínimo de peças faltantes do inimigo para atingir um peão múltiplo em uma única coluna B to G 2=1, 3=2, 4=4, 5=6, 6=9 ___ A and H 2=1, 3=3, 4=6, 5=10, 6=15, por exemplo, se você ver 5 peões em A ou H, o outro jogador deve estar perdendo pelo menos 10 peças de suas 15 peças capturáveis
    3. se houver peões brancos em a2 e a3, legalmente não pode haver um em b2, e essa ideia poderá ser expandida para abranger mais possibilidades

Castling:

  • Se o rei ou as torres não estiverem na posição inicial; a habilidade de rolar para esse lado está perdida (no caso do rei, ambos estão perdidos)

Bispos:

  • Procure bispos na primeira e na última fileiras (linhas) capturadas por peões que não foram movidos, por exemplo:
    1. um bispo (de qualquer cor) preso atrás de 3 peões
    2. um bispo preso atrás de 2 peões não inimigos (não por peões inimigos, porque podemos chegar a essa posição desprotegendo peões, no entanto, se verificarmos o número de peões e extra_piecespoderemos determinar se esse caso é possível ou não)

Não-saltadores:

  • (Evite isso se você quiser validar o Fisher's Chess960). Se houver peças inimigas que não saltam entre o rei e a torre e ainda houver alguns peões sem se mover; verifique se essas peças inimigas poderiam ter entrado legalmente lá. Além disso, pergunte-se: o rei ou a torre precisavam se mover para gerar essa posição? (se sim, precisamos garantir que as habilidades de castell reflitam isso)
  • Se todos os 8 peões ainda estiverem na posição inicial, todos os que não saltam não devem ter saído de sua classificação inicial (as peças inimigas que não saltam não podem ter entrado legalmente), há outras idéias semelhantes, como se o h branco -pawn se moveu uma vez, as torres ainda devem estar presas dentro da formação do peão, etc.

Relógios de movimento parcial / completo:

  • No caso de um quadrado en passant, o relógio de meio movimento deve ser igual a 0
  • HalfMoves <= ((FullMoves-1)*2)+(if BlackToMove 1 else 0), +1 ou +0 depende do lado a ser movido
  • O HalfMoves deve ser x >= 0e o FullMovesx >= 1

De outros:

  • Certifique-se de que o FEN contenha todas as peças necessárias (por exemplo, cor ativa, capacidade de fundição, quadrado passante etc.)

Nota: não há necessidade de fazer o teste 'jogadores não devem ter mais de 16 peças', porque os pontos 'não mais que 8 peões' + 'impedem peças extras promovidas' + o 'exatamente um rei' já deve cobrir esse ponto

Nota2: essas regras têm como objetivo validar posições decorrentes da posição inicial do xadrez normal, algumas regras invalidam algumas posições do Chess960 (exceção se iniciadas no arranjo Nº518) e geram quebra-cabeças, portanto, evite que obtenham um validador funcional.

ajax333221
fonte
1
Você também pode verificar a estrutura do peão, por exemplo, peões brancos nunca poderiam estar em a2, a3 e b2; não há como um peão estar em ambos a3 e b2.
precisa saber é o seguinte
Isso significa que as posições da FEN só devem ser alcançadas a partir da posição inicial? E se eu quisesse ter posições de quebra-cabeça representadas por uma FEN? Às vezes, eles são criados de uma forma impossível de alcançar em um jogo real ...
tbischel
@tbischel I fazer estas regras a partir do normal de perspectiva de xadrez (não destinadas a Chess960 ou outros cargos gerados), graças eu poderia apontar isso em algum lugar para torná-lo mais claro
ajax333221
Mesmo no xadrez normal, talvez você não queira fazer todas essas verificações. Você acaba com um programa que não pode representar uma posição ilegal como FEN. Mas eles acontecem na prática - movimentos ilegais às vezes só são notados após o jogo. Deveria ser impossível mostrar diagramas de tais jogos e assim por diante?
RemcoGerlich 17/09/2013
1
@ ajax333221: Esta página dá jogos legais em que o branco recebe mais de 5 peões no aarquivo.
9
\s*([rnbqkpRNBQKP1-8]+\/){7}([rnbqkpRNBQKP1-8]+)\s[bw-]\s(([a-hkqA-HKQ]{1,4})|(-))\s(([a-h][36])|(-))\s\d+\s\d+\s*

Aqui está uma expressão regular que eu uso para garantir que uma string FEN seja realmente válida. Ele não faz nenhum teste para uma posição legal / ilegal, mas é um bom ponto de partida.

Andrew
fonte
Eu acho que a cor ativa é uma obrigação (você está permitindo -) e relógios meio / cheio às vezes são opcionais, eu acho. Também eu não entendia a a-hparte sobre o roque capacidade, eu reescrevi-a/^\s*([rnbqkpRNBQKP1-8]+\/){7}([rnbqkpRNBQKP1-8]+)\s[bw]\s(-|K?Q?k?q?)\s(-|[a-h][36])/
ajax333221
Eu só notou que podemos fazer o "há peões em promoção ocupa o" teste com algo começando como([rnbqkRNBQK1-8]+\/)([rnbqkpRNBQKP1-8]+\/){6}([rnbqkRNBQK1-8]+) ....
ajax333221
também para os relógios isso pode ser bom (0|[1-9][0-9]*)\s([1-9][0-9]*)como movimentos não podem ter zeros à esquerda e movimento completo não pode ser ou começam com 0, (crédito código)
ajax333221
4

Para os outros, existe uma função simples no mecanismo Stockfish, que valida uma String FEN.

bool Position::is_valid_fen(const std::string &fen) {
   std::istringstream iss(fen);
   std::string board, side, castleRights, ep;

   if (!iss) return false;

   iss >> board;

   if (!iss) return false;

   iss >> side;

   if (!iss) {
      castleRights = "-";
      ep = "-";
   } else {
      iss >> castleRights;
      if (iss)
         iss >> ep;
      else
         ep = "-";
   }

   // Let's check that all components of the supposed FEN are OK.
   if (side != "w" && side != "b") return false;
   if (castleRights != "-" && castleRights != "K" && castleRights != "Kk"
       && castleRights != "Kkq" && castleRights != "Kq" && castleRights !="KQ"
       && castleRights != "KQk" && castleRights != "KQq" && castleRights != "KQkq"
       && castleRights != "k" && castleRights != "q" && castleRights != "kq"
       && castleRights != "Q" && castleRights != "Qk" && castleRights != "Qq"
       && castleRights != "Qkq")
      return false;
   if (ep != "-") {
      if (ep.length() != 2) return false;
      if (!(ep[0] >= 'a' && ep[0] <= 'h')) return false;
      if (!((side == "w" && ep[1] == '6') || (side == "b" && ep[1] == '3')))
         return false;
   }

   // The tricky part: The board.
   // Seven slashes?
   if (std::count(board.begin(), board.end(), '/') != 7) return false;
   // Only legal characters?
   for (int i = 0; i < board.length(); i++)
      if (!(board[i] == '/' || (board[i] >= '1' && board[i] <= '8')
            || piece_type_is_ok(piece_type_from_char(board[i]))))
         return false;
   // Exactly one king per side?
   if (std::count(board.begin(), board.end(), 'K') != 1) return false;
   if (std::count(board.begin(), board.end(), 'k') != 1) return false;
   // Other piece counts reasonable?
   size_t wp = std::count(board.begin(), board.end(), 'P'),
      bp = std::count(board.begin(), board.end(), 'p'),
      wn = std::count(board.begin(), board.end(), 'N'),
      bn = std::count(board.begin(), board.end(), 'n'),
      wb = std::count(board.begin(), board.end(), 'B'),
      bb = std::count(board.begin(), board.end(), 'b'),
      wr = std::count(board.begin(), board.end(), 'R'),
      br = std::count(board.begin(), board.end(), 'r'),
      wq = std::count(board.begin(), board.end(), 'Q'),
      bq = std::count(board.begin(), board.end(), 'q');
   if (wp > 8 || bp > 8 || wn > 10 || bn > 10 || wb > 10 || bb > 10
       || wr > 10 || br > 10 || wq > 9 || bq > 10
       || wp + wn + wb + wr + wq > 15 || bp + bn + bb + br + bq > 15)
      return false;

   // OK, looks close enough to a legal position. Let's try to parse
   // the FEN and see!
   Position p;
   p.from_fen(board + " " + side + " " + castleRights + " " + ep);
   return p.is_ok(true);
}
Thiago Pires
fonte
1
Parece que toda a validação real é feita no position.is_okay(). O código aqui faz apenas algumas verificações básicas para garantir que esteja formatado corretamente e que valha a pena fazer a validação real (ou seja, não é obviamente ilegal).
Undergroundmonorail
3

Aqui está um algoritmo simples de retorno, desde que você tenha uma função que possa verificar movimentos legais reversos em todos os estados do fórum (também conhecidos como posição):

function is_legal_state(state,move)

   //Terminate if a starting state was found. This immediately implies there
   //was a legal game that generated this state, in fact the backtracking
   //can tell you precisely such a game       
   if (state in starting board state)
     return true

   //Apply some move to get to a new state, state is a persistent object
   apply_reverse_move(state,move)

   //Generate all legal "reverse" moves, that is, moves that could have
   //been performed to get to the current state from another position,
   //provided the previous position was valid. You do not have to check the
   //validness of the previous state, you just have to make sure the
   //transitioning move was valid
   legalmoves = enumerate_all_reverse_moves( state )

   for local_move in legalmoves:
     return is_legal_state(state,local_move)

   //Reverse the move that was previously applied so backtracking can
   //work properly 
   reverse_reverse_move(state,move)

   return false
ldog
fonte
1

Não há nada na especificação FEN dizendo que a posição representada deve ser alcançável a partir da matriz inicial. Provar que uma determinada posição é alcançável a partir da matriz inicial é um problema não resolvido.

Em uma sequência FEN válida, a contagem de meio movimento deve estar de acordo com o quadrado alvo passante; se um quadrado alvo estiver presente, a contagem de meio movimento deve ser zero. a contagem de meio movimento também deve estar de acordo com o número de movimento completo; por exemplo, uma contagem de dez movimentos de meia é incompatível com um número de movimento completo de três.

ChessNotation
fonte
1

Chegando tarde na festa.

Não é possível validar 100% se uma posição é legal, mas por que a validação importa? Podemos jogar xadrez, independentemente de a posição derivar ou não da posição inicial (o chamado "conjunto de jogos"). Pode haver uma posição muito interessante para analisar, mas acontece que é ilegal.

Então eu verificaria apenas:

  • Existe exatamente 1 rei de cada lado?
  • Não há peões na primeira ou na oitava posição?
  • O lado a mover já não está dando cheque?

Se são três SIM, podemos jogar xadrez a partir deste diagrama. E mesmo nesta pequena lista de condições, podemos ser capazes de relaxar.

Laska
fonte