Come sapere quando una posizione FEN è legale?


19

Sto facendo un progetto personale, dove a un certo punto devo convalidare la posizione FEN, ho iniziato con alcuni controlli di base, come controllare se ci sono re e assicurarmi che non ci siano righe o colonne extra e quel tipo di cose.

Ma quali altri controlli dovrei fare per assicurarmi che una FEN sia legale?

Risposte:


18

Ecco un elenco ben organizzato che dovrebbe convalidare il 99,99% + di posizioni comuni:

Tavola:

  • Ci sono esattamente 8 col
  • La somma dei quadrati e dei pezzi vuoti si aggiunge a 8 per ogni rango (riga)
  • Non ci sono numeri consecutivi per i quadrati vuoti

Re:

  • Verifica se esiste esattamente un w_king e un b_king
  • Assicurati che i re siano separati a 1 quadrato di distanza

controlli:

  • Il colore non attivo non è sotto controllo
  • Il colore attivo viene controllato meno di 3 volte (il triplo controllo è impossibile); nel caso di 2 che non sia mai pedone + (pedone, vescovo, cavaliere), vescovo + vescovo, cavaliere + cavaliere

pedine:

  • Non ci sono più di 8 pedine per ogni colore
  • Non ci sono pedine nel primo o nell'ultimo rango (riga) poiché sono in una posizione iniziale errata o avrebbero dovuto essere promossi.
  • In caso di en passant square; vedere se è stato creato legalmente (ad es. deve essere sul rango x3o x6, deve esserci un pedone (dal colore corretto) di fronte ad esso, e il quadrato en passant e quello dietro di esso sono vuoti)
  • Impedisci di avere più pezzi promossi rispetto ai pedoni mancanti (ad es. extra_pieces = Math.max(0, num_queens-1) + Math.max(0, num_rooks-2)...E poi extra_pieces <= (8-num_pawns)), inoltre dovresti fare calcoli speciali per i vescovi, se hai due (o più) vescovi dello stesso colore quadrato, questi possono essere creati solo attraverso la promozione dei pedoni e dovresti includere questa informazione alla formula sopra in qualche modo
  • È possibile raggiungere la formazione del pedone (ad es. In caso di pedine multiple in un singolo colle, ci devono essere abbastanza pezzi nemici per fare quella formazione), ecco alcune regole utili:
    1. è impossibile avere più di 6 pedine in un singolo file (colonna) (perché le pedine non possono esistere nella prima e nell'ultima fila)
    2. il numero minimo di pezzi mancanti nemici per raggiungere una pedina multipla in una singola colonna 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, ad esempio, se vedi 5 pedine in A o H, l'altro giocatore deve perdere almeno 10 pezzi tra i suoi 15 pezzi catturabili
    3. se ci sono pedine bianche in a2 e a3, non ci può essere legalmente una in b2 e questa idea può essere ulteriormente ampliata per coprire più possibilità

arrocco:

  • Se il re o i corvi non sono nella loro posizione iniziale; l'abilità di castelling per quella parte è persa (nel caso del re, entrambi sono persi)

Vescovi:

  • Cerca i vescovi nel primo e nell'ultimo rango (fila) intrappolati da pedine che non si sono mosse, ad esempio:
    1. un vescovo (qualsiasi colore) intrappolato dietro 3 pedine
    2. un vescovo intrappolato dietro 2 pedine non nemiche (non da pedine nemiche perché possiamo raggiungere quella posizione sottoproponendo pedine, tuttavia se controlliamo il numero di pedine e extra_piecespotremmo determinare se questo caso è possibile o meno)

Non ponticelli:

  • (Evitatelo se volete convalidare gli scacchi di Fisher960) Se ci sono pezzi nemici non saltatori tra il re e la torre e ci sono ancora alcune pedine senza muoversi; controlla se questi pezzi nemici potrebbero esserci entrati legalmente. Inoltre, chiediti: era necessario il re o la torre per spostarsi per generare quella posizione? (se sì, dobbiamo assicurarci che le abilità di castling riflettano questo)
  • Se tutte e 8 le pedine sono ancora nella posizione iniziale, tutti i non saltatori non devono aver lasciato il loro rango iniziale (anche i pezzi nemici non saltatori non possono essere entrati legalmente), ci sono altre idee simili, come se il bianco h -pawn spostato una volta, le torri dovrebbero essere intrappolate all'interno della formazione del pedone, ecc.

Orologi a metà / completa mossa:

  • Nel caso di un quadrato en passant, il clock di mezzo movimento deve essere uguale a 0
  • HalfMoves <= ((FullMoves-1)*2)+(if BlackToMove 1 else 0), +1 o +0 dipendono dal lato da spostare
  • HalfMoves deve essere x >= 0e FullMovesx >= 1

Altro:

  • Assicurarsi che la FEN contenga tutte le parti necessarie (ad es. Colore attivo, capacità di rigatura, quadrato passante, ecc.)

Nota: non è necessario effettuare il controllo dei "giocatori non devono avere più di 16 pezzi" perché i punti "non più di 8 pedine" + "impediscono i pezzi in più promossi" + l '"esattamente un re" dovrebbe già coprire questo punto

Nota2: queste regole hanno lo scopo di convalidare le posizioni derivanti dalla posizione iniziale degli scacchi normali, alcune delle regole invalideranno alcune posizioni da Chess960 (eccezione se avviata dalla disposizione Nº518) e generano puzzle in modo da evitare di ottenere un validatore funzionale.


1
Puoi anche controllare la struttura del pedone, ad esempio i pedoni bianchi non potrebbero mai essere su a2, a3 e b2; non è possibile che una pedina sia su a3 e b2.
Akavall,

Vale a dire che le posizioni FEN dovrebbero essere ottenibili solo dalla posizione iniziale? E se volessi avere posizioni puzzle rappresentate da una FEN? A volte sono creati in un modo impossibile da raggiungere in un gioco reale ...
tbischel

@tbischel Sto facendo queste regole dalla normale prospettiva di scacchi (non inteso per Chess960 o altre posizioni generate), grazie potrei indicarlo da qualche parte per renderlo più chiaro
ajax333221

Anche per gli scacchi normali, potresti non voler fare tutti questi controlli. Si finisce con un programma che non può rappresentare una posizione illegale come FEN. Ma in pratica accadono: a volte le mosse illegali vengono notate solo dopo il gioco. Dovrebbe essere impossibile mostrare i diagrammi di tali giochi e così via?
RemcoGerlich,

1
@ ajax333221: Questa pagina dà giochi legali in cui bianco si fà più di 5 pedine sul afile.

10
\s*([rnbqkpRNBQKP1-8]+\/){7}([rnbqkpRNBQKP1-8]+)\s[bw-]\s(([a-hkqA-HKQ]{1,4})|(-))\s(([a-h][36])|(-))\s\d+\s\d+\s*

Ecco un'espressione regolare che uso per garantire che una stringa FEN sia effettivamente valida. Non esegue alcun test per una posizione legale / illegale, ma è un buon punto di partenza.


Penso che il colore attivo sia un must (stai permettendo -) e che a volte gli orologi a metà / completi sono opzionali. Inoltre non ho capito la a-hparte sull'abilità /^\s*([rnbqkpRNBQKP1-8]+\/){7}([rnbqkpRNBQKP1-8]+)\s[bw]\s(-|K?Q?k?q?)\s(-|[a-h][36])/
castling

Ho appena notato che possiamo fare il test "nessuna pedina nei ranghi della promozione" con qualcosa che inizia come([rnbqkRNBQK1-8]+\/)([rnbqkpRNBQKP1-8]+\/){6}([rnbqkRNBQK1-8]+) ....
ajax333221

anche per gli orologi questo potrebbe essere buono (0|[1-9][0-9]*)\s([1-9][0-9]*)poiché le mosse non possono avere zeri iniziali e la mossa completa non può essere o iniziare con 0, (credito del codice)
ajax333221

5

Per gli altri, esiste una semplice funzione nel motore Stockfish, che convalida una stringa 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);
}

1
Sembra che tutta la validazione effettiva sia stata eseguita position.is_okay(). Il codice qui fa solo un paio di controlli di base per assicurarsi che sia formattato correttamente e che valga la pena fare la vera validazione (cioè non ovviamente illegale).
undergroundmonorail,

4

Ecco un semplice algoritmo di backtracking, a condizione che tu abbia una funzione in grado di controllare i movimenti legali inversi in ogni stato della scheda (noto anche come posizione):

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

1

Nulla nella specifica FEN afferma che la posizione rappresentata deve essere raggiungibile dall'array iniziale. Provare che una determinata posizione è raggiungibile dall'array iniziale è un problema irrisolto.

In una stringa FEN valida, il conteggio delle metà mosse deve essere in accordo con il quadrato target en passant; se è presente un quadratino di destinazione, il conteggio della mezza mossa deve essere zero. anche il conteggio delle metà mosse deve essere in accordo con il numero completo della mossa; ad esempio, un conteggio di mezzo movimento di dieci non è compatibile con un numero di movimento completo di tre.


1

Venendo alla festa in ritardo.

Non è possibile convalidare al 100% se una posizione è legale, ma perché la convalida dovrebbe essere importante? Possiamo giocare a scacchi indipendentemente dal fatto che la posizione derivi o meno dalla posizione iniziale (il cosiddetto "array di gioco"). Potrebbe esserci una posizione molto interessante da analizzare, ma capita solo che sia illegale.

Quindi vorrei controllare solo:

  • C'è esattamente 1 re per parte?
  • Non ci sono pedine nel primo o nell'ottavo grado?
  • La parte da spostare non sta già dando un assegno?

Se sono tre SÌ, allora possiamo giocare a scacchi in avanti da questo diagramma. E anche questo breve elenco di condizioni potremmo essere in grado di allentare.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.