Як дізнатися, коли позиція FEN є законною?


19

Я роблю особистий проект, коли в один момент мені потрібно перевірити позицію FEN, я почав з деяких основних перевірок, таких як перевірка наявності королів і переконайтеся, що немає зайвих рядків чи стовпців, і подібного роду речі.

Але які ще перевірки потрібно зробити, щоб повністю переконатися, що FEN є законним?

Відповіді:


18

Ось добре організований список, який повинен підтвердити 99,99% + загальних позицій:

Рада:

  • Там рівно 8 кол
  • Сума порожніх квадратів і шматочків додається до 8 для кожного рангу (ряду)
  • Немає послідовних чисел для порожніх квадратів

Королі:

  • Подивіться, чи є рівно один w_king та один b_king
  • Переконайтеся, що королі відокремлені 1 квадрат один від одного

Перевірки:

  • Неактивний колір не перевіряється
  • Активний колір перевіряється менше 3 разів (потрійна перевірка неможлива); у випадку 2, що це ніколи пішак + (пішак, єпископ, лицар), єпископ + єпископ, лицар + лицар

Пішаки:

  • З кожного кольору не більше 8 пішаків
  • Немає пішаків першого чи останнього рангу (ряду), оскільки вони перебувають у неправильному стартовому положенні, або вони повинні були просуватися.
  • У випадку прохідної площі; подивіться, чи був він створений на законних підставах (наприклад, він повинен бути на x3чи x6ранговому рівні, перед ним повинен бути пішак (з правильного кольору), а прохідний квадрат і той, що знаходиться за ним, порожні)
  • Не дозволяйте мати більше рекламних фігур, ніж відсутні пішаки (наприклад, extra_pieces = Math.max(0, num_queens-1) + Math.max(0, num_rooks-2)...і тоді extra_pieces <= (8-num_pawns)), також вам слід зробити спеціальні розрахунки для єпископів. Якщо у вас є два (або більше) єпископів одного квадратного кольору, їх можна створити лише за допомогою просування пішаків, і вам слід включити ця інформація до формули вище якось
  • Формування пішаків можна досягти (наприклад, у випадку кількох пішаків в одному колі, для її формування має бути достатньо кількості ворожих фігур), ось кілька корисних правил:
    1. не можна мати більше 6 пішаків в одному файлі (стовпці) (оскільки пішаки не можуть існувати в першому та останньому рядах)
    2. мінімальна кількість ворожих відсутніх фігур, щоб досягти декількох пішаків в одному колі 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, наприклад, якщо ви бачите 5 пішаків A або H, інший гравець повинен бракувати не менше 10 штук з його 15 захоплюючих штук
    3. якщо в а2 та а3 є білі пішаки, юридично їх не може бути в b2, і цю ідею можна додатково розширити, щоб охопити більше можливостей

Закладки:

  • Якщо король чи граки не перебувають у вихідному положенні; здатність закидання для цієї сторони втрачається (у випадку короля обоє втрачаються)

Єпископи:

  • Шукайте єпископів у першому та останньому рядах (рядах), захоплених пішаками, які не рухалися, наприклад:
    1. єпископ (будь-якого кольору), захоплений за 3 пішаки
    2. єпископ в пастку за 2 без ворожих пішаків (НЕ ворожих пішаків , тому що ми можемо досягти цієї позиції шляхом underpromoting пішаки, однак , якщо ми перевіряємо кількість пішаків і extra_piecesми могли б визначити , є чи цей випадок можливий чи ні)

Не стрибки:

  • (Уникайте цього, якщо ви хочете перевірити шахи Фішера960) Якщо між королем та граком є шматки ворога, які не стрибають, і ще є пешки, не рухаючись; перевірте, чи могли ці ворожі частини законно потрапити туди. Крім того, запитайте себе: чи потрібен був король чи грак для переміщення, щоб створити цю посаду? (якщо так, нам потрібно переконатися, що здатності акторської майстерності відображають це)
  • Якщо всі 8 пішаків все ще знаходяться у вихідному положенні, всі неперехідники не повинні залишати свого початкового рангу (також неперехідні ворожі фігури, можливо, не могли вступити на законних підставах), є інші подібні ідеї, наприклад, якщо білий -пауна переїхала один раз, граки все одно повинні бути захоплені всередині закладу пішаків тощо.

Годинники на половину / повний хід:

  • У випадку прохідного квадрата, половинчастий хід руху повинен дорівнювати 0
  • HalfMoves <= ((FullMoves-1)*2)+(if BlackToMove 1 else 0), +1 або +0 залежить від сторони руху
  • HalfMoves повинні бути x >= 0і FullMovesx >= 1

Інший:

  • Переконайтесь, що FEN містить усі необхідні деталі (наприклад, активний колір, здатність до виведення, прохідний квадрат тощо)

Примітка: немає необхідності робити перевірку "гравці не повинні мати більше 16 штук", оскільки бали "не більше 8 пішаків" + "запобігають додатковим рекламним фігурам" + "точно один король" вже повинен охоплювати цю точку

Примітка2: ці правила призначені для підтвердження позицій, що виникають із вихідної позиції звичайних шахів, деякі правила позбавлятимуть позиції від Chess960 (виняток, якщо розпочато з розташування Nº518) та генеровані головоломки, тому уникайте їх, щоб отримати функціональний валідатор.


1
Ви також можете перевірити структуру пішака, наприклад, білі пішаки ніколи не можуть бути на а2, а3 та b2; жодного способу пішак не може бути як на a3, так і на b2.
Акавал

Це означає, що позиції FEN повинні бути досягнуті лише з початкової позиції? Що робити, якщо я хотів, щоб позиції головоломки були представлені FEN? Іноді вони створюються таким чином, що неможливо досягти в реальній грі ...
tbischel

@tbischel Я викладаю ці правила з звичайної шахової точки зору (не призначена для Chess960 або інших сформованих позицій), дякую, що я можу вказати це десь, щоб було зрозуміліше
ajax333221

Навіть для звичайних шахів ви, можливо, не захочете робити всі ці перевірки. Ви отримуєте програму, яка не може представляти нелегальну позицію як FEN. Але вони трапляються на практиці - незаконні ходи іноді помічаються лише після гри. Чи не може бути неможливо показати діаграми таких ігор тощо?
RemcoGerlich

1
@ Ajax333221: Ця сторінка дає юридичні гри , в яких білі отримують більше 5 пішаки на aфайл.

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

Ось регулярний вираз, який я використовую, щоб переконатися, що рядок FEN дійсно дійсний. Вона не проводить тестування на законну / незаконну посаду, але це хороша відправна точка.


Я думаю, що активний колір є обов'язковим (ви дозволяєте -), і половина / повний годинник іноді є необов'язковим, я думаю. Крім того, я не зрозумів, що a-hстосується здатності до /^\s*([rnbqkpRNBQKP1-8]+\/){7}([rnbqkpRNBQKP1-8]+)\s[bw]\s(-|K?Q?k?q?)\s(-|[a-h][36])/
закидання

Я щойно зазначив, що ми можемо зробити тест "без пішаків у просуванні промоції" з чогось, що починається на кшталт([rnbqkRNBQK1-8]+\/)([rnbqkpRNBQKP1-8]+\/){6}([rnbqkRNBQK1-8]+) ....
ajax333221

також для годинника це може бути добре, (0|[1-9][0-9]*)\s([1-9][0-9]*)оскільки в ходах не може бути провідних нулів, а повний хід не може бути або починати з 0, (код кредиту)
ajax333221

5

Для інших існує проста функція в двигуні Stockfish, яка підтверджує струну 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
Схоже, все фактичне підтвердження зроблено в position.is_okay(). Код тут просто робить кілька основних перевірок, щоб переконатися, що він відформатований правильно, і що варто зробити реальну перевірку (тобто не очевидно незаконну).
підземниймонорельс

4

Ось простий алгоритм зворотного відстеження, за умови, що у вас є функція, яка може перевіряти зворотні легальні ходи у кожному стані плати (також відомий як позиція):

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

У специфікації FEN немає нічого, що говорить про те, що представлена ​​позиція повинна бути доступною з початкового масиву. Доведення того, що дана позиція є доступною з початкового масиву, є невирішеною проблемою.

У дійсному рядку FEN половинний хід руху повинен відповідати прохідному цільовому квадрату; якщо присутній цільовий квадрат, то кількість половинного ходу має бути дорівнює нулю. половина підрахунку переміщення також повинна відповідати повного номера переміщення; наприклад, кількість половинних переміщень у десятку несумісна з повним номером ходу три.


1

Приходьте на вечірку пізно.

Неможливо на 100% перевірити, чи є позиція законною, але чому має бути валідація? Ми можемо грати в шахи, незалежно від того, чи є позиція, що виходить із вихідної позиції (так званий «ігровий масив»). Аналіз може бути дуже цікавим, але просто трапляється, що це незаконно.

Тому я би перевірив:

  • Чи є рівно 1 король з кожного боку?
  • Немає пішаків першого чи восьмого рангу?
  • Чи сторона, яка рухається, вже не дає чека?

Якщо це три ТАК, то ми можемо грати в шахи вперед на цій схемі. І навіть цей короткий список умов ми можемо ослабити.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.