Bagaimana cara mengetahui kapan posisi FEN legal?

19

Saya sedang melakukan proyek pribadi, di mana pada satu titik saya perlu memvalidasi posisi FEN, saya mulai dengan beberapa cek dasar, seperti memeriksa apakah ada raja dan memastikan tidak ada baris atau kolom tambahan, dan semacam itu sesuatu.

Tapi cek apa lagi yang harus saya lakukan untuk memastikan FEN itu sah?

ajax333221
sumber

Jawaban:

18

Berikut adalah daftar yang terorganisir dengan baik yang seharusnya memvalidasi 99,99% + posisi umum:

Naik:

  • Tepatnya ada 8 cols
  • Jumlah dari kuadrat dan potongan kosong menambah 8 untuk setiap peringkat (baris)
  • Tidak ada angka berurutan untuk kotak kosong

Raja:

  • Lihat apakah ada tepat satu w_king dan satu b_king
  • Pastikan raja terpisah 1 persegi

Cek:

  • Warna tidak aktif tidak dicentang
  • Warna aktif diperiksa kurang dari 3 kali (tiga kali pemeriksaan tidak mungkin); dalam kasus 2 yang tidak pernah digadai + (gadai, uskup, ksatria), uskup + uskup, ksatria + ksatria

Pion:

  • Tidak ada lebih dari 8 pion dari setiap warna
  • Tidak ada pion di peringkat pertama atau terakhir (baris) karena mereka berada di posisi awal yang salah atau mereka seharusnya dipromosikan.
  • Dalam kasus en passant square; lihat apakah itu dibuat secara legal (mis. harus di pangkat x3atau x6, ada pion (dari warna yang benar) di depannya, dan en passant square dan yang di belakangnya kosong)
  • Mencegah memiliki lebih banyak barang yang dipromosikan daripada bidak yang hilang (mis. extra_pieces = Math.max(0, num_queens-1) + Math.max(0, num_rooks-2)...Kemudian extra_pieces <= (8-num_pawns)), Anda juga harus melakukan perhitungan khusus untuk uskup, Jika Anda memiliki dua (atau lebih) uskup dari warna kotak yang sama, ini hanya dapat dibuat melalui promosi gadai dan Anda harus memasukkan informasi ini ke rumus di atas entah bagaimana
  • Formasi pion dimungkinkan untuk dijangkau (misalnya dalam hal pion berganda dalam satu col, harus ada cukup potongan musuh yang hilang untuk membuat formasi itu), berikut adalah beberapa aturan yang berguna:
    1. tidak mungkin memiliki lebih dari 6 pion dalam satu file (kolom) (karena pion tidak bisa ada di peringkat pertama dan terakhir)
    2. jumlah minimum keping musuh yang hilang untuk mencapai beberapa pion dalam satu col 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, misalnya, jika Anda melihat 5 pion dalam A atau H, pemain lain harus kehilangan setidaknya 10 keping dari 15 kepingannya yang dapat ditangkap.
    3. jika ada pion putih di a2 dan a3, tidak mungkin ada satu di b2, dan ide ini dapat diperluas untuk mencakup lebih banyak kemungkinan

Castling:

  • Jika raja atau benteng tidak dalam posisi awal mereka; kemampuan castling untuk sisi itu hilang (dalam kasus raja, keduanya hilang)

Uskup:

  • Cari uskup di barisan pertama dan terakhir (baris) yang terjebak oleh pion yang belum bergerak, misalnya:
    1. seorang uskup (warna apa saja) terjebak di belakang 3 pion
    2. seorang uskup terperangkap di belakang 2 pion non-musuh (bukan oleh pion musuh karena kita dapat mencapai posisi itu dengan kurang mendukung pion, namun jika kita memeriksa jumlah pion dan extra_pieceskita dapat menentukan apakah kasus ini mungkin atau tidak)

Non-jumper:

  • (Hindari ini jika Anda ingin memvalidasi Catur Fisher960) Jika ada musuh non-jumper di antara raja dan benteng dan masih ada beberapa bidak tanpa bergerak; periksa apakah potongan musuh ini bisa secara legal masuk ke sana. Juga, tanyakan pada diri Anda: apakah raja atau benteng diperlukan untuk bergerak untuk menghasilkan posisi itu? (Jika ya, kita perlu memastikan kemampuan castling mencerminkan hal ini)
  • Jika semua 8 pion masih dalam posisi awal, semua non-jumper tidak boleh meninggalkan peringkat awal mereka (juga potongan musuh non-jumper tidak mungkin masuk secara legal), ada ide serupa lainnya, seperti jika putih - Pion bergerak sekali, benteng harus tetap terjebak di dalam formasi pion, dll.

Jam setengah / gerakan penuh:

  • Dalam kasus en passant square, setengah jam gerakan harus sama dengan 0
  • HalfMoves <= ((FullMoves-1)*2)+(if BlackToMove 1 else 0), +1 atau +0 tergantung pada sisi untuk bergerak
  • HalfMoves haruslah x >= 0dan FullMovesx >= 1

Lain:

  • Pastikan FEN berisi semua bagian yang diperlukan (mis. Warna aktif, kemampuan castling, en passant square, dll)

Catatan: tidak perlu membuat 'pemain tidak boleh memiliki lebih dari 16 buah' karena poin 'tidak lebih dari 8 pion' + 'mencegah potongan ekstra dipromosikan' + 'tepatnya satu raja' harus sudah mencakup poin ini

Note2: aturan ini dimaksudkan untuk memvalidasi posisi yang timbul dari posisi awal catur normal, beberapa aturan akan membatalkan beberapa posisi dari Chess960 (pengecualian jika dimulai dari pengaturan Nº518) dan menghasilkan puzzle sehingga menghindarinya untuk mendapatkan validator fungsional.

ajax333221
sumber
1
Anda juga dapat memeriksa struktur pion, misalnya pion putih tidak akan pernah berada pada a2, a3, dan b2; tidak mungkin ada pion pada a3 dan b2.
Akavall
Apakah itu mengatakan posisi FEN hanya dapat dicapai dari posisi awal? Bagaimana jika saya ingin posisi puzzle diwakili oleh FEN? Terkadang mereka diciptakan dengan cara yang tidak mungkin untuk dicapai dalam permainan yang sebenarnya ...
tbischel
@tbischel Saya membuat aturan-aturan ini dari perspektif catur normal (tidak dimaksudkan untuk Chess960 atau posisi lain yang dihasilkan), terima kasih saya mungkin menunjukkan tempat ini untuk membuatnya lebih jelas
ajax333221
Bahkan untuk catur normal, Anda mungkin tidak ingin melakukan semua cek ini. Anda berakhir dengan sebuah program yang tidak dapat mewakili posisi ilegal sebagai FEN. Tapi mereka memang terjadi dalam praktik - gerakan ilegal kadang-kadang hanya diperhatikan setelah pertandingan. Apakah tidak mungkin menampilkan diagram dari game semacam itu, dan sebagainya?
RemcoGerlich
1
@ ajax333221: Halaman ini memberikan permainan hukum di mana putih mendapat lebih dari 5 bidak pada aberkas.
9
\s*([rnbqkpRNBQKP1-8]+\/){7}([rnbqkpRNBQKP1-8]+)\s[bw-]\s(([a-hkqA-HKQ]{1,4})|(-))\s(([a-h][36])|(-))\s\d+\s\d+\s*

Berikut adalah ekspresi reguler yang saya gunakan untuk memastikan bahwa string FEN benar-benar valid. Itu tidak melakukan pengujian untuk posisi legal / ilegal, tapi itu adalah titik awal yang baik.

Andrew
sumber
Saya pikir warna aktif adalah suatu keharusan (Anda mengizinkan -) dan setengah / jam penuh kadang-kadang opsional saya pikir. Juga saya tidak mengerti a-hbagian tentang kemampuan castling, saya menulis ulang untuk/^\s*([rnbqkpRNBQKP1-8]+\/){7}([rnbqkpRNBQKP1-8]+)\s[bw]\s(-|K?Q?k?q?)\s(-|[a-h][36])/
ajax333221
Saya baru saja mencatat bahwa kita dapat melakukan tes "tidak ada pion dalam peringkat promosi" dengan sesuatu yang dimulai seperti([rnbqkRNBQK1-8]+\/)([rnbqkpRNBQKP1-8]+\/){6}([rnbqkRNBQK1-8]+) ....
ajax333221
juga untuk jam ini mungkin bagus (0|[1-9][0-9]*)\s([1-9][0-9]*)karena gerakan tidak dapat memiliki nol di depan dan gerakan penuh tidak bisa atau mulai dengan 0, (kode kredit)
ajax333221
4

Untuk yang lain, ada fungsi sederhana di mesin Stockfish, yang memvalidasi FEN String.

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
sumber
1
Sepertinya semua validasi aktual dilakukan di position.is_okay(). Kode di sini hanya melakukan beberapa pemeriksaan dasar untuk memastikannya diformat dengan benar dan layak melakukan validasi nyata (yaitu tidak jelas ilegal).
undergroundmonorail
3

Berikut ini adalah algoritma penelusuran mundur sederhana, asalkan Anda memiliki fungsi yang dapat memeriksa gerakan hukum terbalik di setiap kondisi dewan (juga dikenal sebagai posisi):

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
sumber
1

Tidak ada dalam spesifikasi FEN yang mengatakan bahwa posisi yang diwakili harus dapat dijangkau dari larik awal. Membuktikan bahwa posisi yang diberikan dapat dijangkau dari array awal adalah masalah yang belum terpecahkan.

Dalam string FEN yang valid, hitungan setengah langkah harus sesuai dengan kuadrat target en passant; jika kuadrat target hadir, maka jumlah langkah setengah harus nol. hitungan setengah langkah juga harus sesuai dengan jumlah langkah penuh; misal, hitungan setengah langkah dari sepuluh tidak sesuai dengan jumlah langkah penuh dari tiga.

CaturNotasi
sumber
1

Datang ke pesta terlambat.

Tidak mungkin memvalidasi 100% apakah suatu posisi legal, tetapi mengapa validasi itu penting? Kita dapat bermain catur terlepas dari apakah posisi tersebut berasal dari posisi awal (disebut “susunan permainan”). Mungkin ada posisi yang sangat menarik untuk dianalisis tetapi kebetulan itu ilegal.

Jadi saya akan periksa saja:

  • Apakah ada 1 raja dari masing-masing pihak?
  • Apakah tidak ada pion di peringkat pertama atau kedelapan?
  • Apakah pihak yang bergerak belum memberi cek?

Jika itu tiga YA maka kita bisa bermain catur ke depan dari diagram ini. Dan bahkan daftar pendek dari kondisi ini kita mungkin dapat melonggarkan.

Laska
sumber