FEN 포지션이 언제 합법적인지 아는 방법?


19

나는 개인 프로젝트를하고 있는데, 한 시점에서 FEN 위치를 확인해야하며 왕이 있는지 확인하고 여분의 행이나 열이 없는지 확인하는 것과 같은 몇 가지 기본 점검으로 시작했습니다. 소지품.

그러나 FEN이 합법적임을 확인하기 위해 다른 점검을해야합니까?

답변:


18

다음은 일반적인 위치의 99.99 % 이상을 검증해야하는 체계적인 목록입니다.

판:

  • 정확히 8 열이 있습니다
  • 빈 사각형과 조각의 합은 각 순위 (행)에 8을 더합니다.
  • 빈 사각형에는 연속 된 숫자가 없습니다.

왕 :

  • 정확히 하나의 w_king과 하나의 b_king이 있는지 확인하십시오.
  • 왕이 1 평방 떨어져 있는지 확인하십시오

체크 무늬:

  • 비활성 색상이 확인 되지 않음
  • 활성 색상이 3 회 미만으로 확인됩니다 (3 중 확인 불가). 전당포 + (전주, 주교, 기사), 주교 + 주교, 기사 + 기사가 아닌 2의 경우

폰 :

  • 각 색상에서 폰이 8 개를 넘지 않아야합니다.
  • 첫 순위 나 마지막 순위 (행)에 폰이 없습니다. 시작 위치가 잘못되었거나 승격 되었기 때문입니다.
  • 통과 광장의 경우; 그것이 합법적으로 만들어 졌는지 확인하십시오 (예를 들어, x3또는 위에 있어야합니다 x6, 그 앞에 폰이 있어야합니다 (정확한 색에서), 그리고 광장과 그 뒤에있는 것이 비어 있습니다)
  • 방지 (예 실종 폰보다 더 승진 조각을 가지고 extra_pieces = Math.max(0, num_queens-1) + Math.max(0, num_rooks-2)...다음과를 extra_pieces <= (8-num_pawns)두 개 (또는 그 이상) 같은 정사각형 색상에서 주교가있는 경우 또한, 주교 특별 계산을해야한다,), 다음은 전당포 프로모션을 통해 생성 될 수 있으며 포함해야한다 위의 공식에 대한 정보
  • 폰 형성은 도달 할 수 있습니다 (예를 들어, 단일 col에 여러 폰이있는 경우, 그 형성을 위해 적의 조각이 충분하지 않아야합니다).
    1. 단일 파일 (열)에 폰을 6 개 이상 가질 수 없습니다 (폰이 첫 번째 순위와 마지막 순위에 존재할 수 없기 때문에)
    2. 단일 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는 A 또는 H 5 폰을 보면, 예를 들면은, 다른 플레이어는 15 개에서 적어도 10 개 누락해야 captureable 조각
    3. a2 및 a3에 흰색 폰이 있으면 b2에 흰색 폰이있을 수 없으며이 아이디어는 더 많은 가능성을 포함하도록 확장 될 수 있습니다

캐슬 링 :

  • 왕 또는 루크가 출발 위치에 있지 않은 경우; 그 쪽의 캐스팅 능력이 사라집니다 (왕의 경우 둘 다 손실 됨)

주교 :

  • 이동하지 않은 전당포에 의해 갇힌 첫 번째 및 마지막 순위 (행)에서 주교를 찾으십시오.
    1. 3 명의 폰 뒤에 갇힌 주교 (모든 색)
    2. 주교는 갇혀 뒤에아닌 적 (우리가 underpromoting 심 복에 의해 그 위치에 도달 할 수 있기 때문에 우리가 졸의 수를 확인하고 그러나 경우에,하지 적의 폰으로 폰 extra_pieces이 경우 가능 여부를 경우 우리가 결정할 수있다)

비 점퍼 :

  • (피셔의 Chess960을 검증하려면 이것을 피하십시오.) 왕과 루크 사이에 점수 적 조각이 있고 여전히 움직이지 않는 일부 폰이 있다면; 이 적들이 합법적으로 입수 할 수 있는지 확인하십시오. 또한 자신에게 물어보십시오. 왕이나 사기꾼은 그 지위를 창출하기 위해 움직여야 했습니까? (그렇다면 캐슬 링 능력이 이것을 반영하도록해야합니다)
  • 8 개의 폰이 여전히 시작 위치에 있다면, 모든 비 점퍼는 초기 순위를 벗어나지 않아야합니다 (또한 점퍼가 아닌 적의 조각은 합법적으로 들어갈 수 없었습니다). 흰색 h와 같은 다른 유사한 아이디어가 있습니다 -한 번 움직여도 루크는 여전히 폰 형성 내부에 갇혀 있어야합니다.

반 / 전동 시계 :

  • 통과 광장의 경우 반 이동 시계 0과 같아야합니다.
  • HalfMoves <= ((FullMoves-1)*2)+(if BlackToMove 1 else 0), +1 또는 +0은 이동할쪽에 따라 다릅니다.
  • HalfMoves이어야합니다 x >= 0FullMoves 및x >= 1

다른:

  • FEN에 필요한 모든 부품이 포함되어 있는지 확인하십시오 (예 : 활성 색상, 주조 능력, 정사각형 등).

참고 : ' 8 명 이하의 폰' + '추가 판촉물 방지' + '정확히 한 왕' 이이 점을 이미 다루어야 하기 때문에 '플레이어는 16 개 이상의 조각을 가져서는 안됩니다' 확인을 할 필요가 없습니다.

참고 2 : 이 규칙은 일반 체스의 시작 위치에서 발생하는 위치의 유효성을 검사하기위한 것이며 일부 규칙은 Chess960 ( 일부 Nº518 에서 시작한 경우 제외)의 일부 위치를 무효화 하고 생성 된 퍼즐을 피하여 기능 유효성 검사기를 얻지 않도록합니다.


1
폰 구조를 확인할 수도 있습니다. 예를 들어 흰색 폰은 a2, a3 및 b2에있을 수 없습니다. 폰이 a3와 b2에있을 수있는 방법은 없습니다.
Akavall

말하자면 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-hcastling 능력에 대한 부분을 이해하지 못하고 그것을 다시 썼다/^\s*([rnbqkpRNBQKP1-8]+\/){7}([rnbqkpRNBQKP1-8]+)\s[bw]\s(-|K?Q?k?q?)\s(-|[a-h][36])/
ajax333221

방금 "프로모션 랭크에 전당포 없음"테스트를 다음과 같은 것으로 시작할 수 있다고 언급했습니다([rnbqkRNBQK1-8]+\/)([rnbqkpRNBQKP1-8]+\/){6}([rnbqkRNBQK1-8]+) ....
ajax333221

또한 시계의 경우 (0|[1-9][0-9]*)\s([1-9][0-9]*)이동이 선행 0을 가질 수없고 전체 이동이 0으로 시작하거나 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(). 코드는 여기에 단지 기본적인 검사의 몇 올바르게 포맷 된 것 있는지 확인하고 그것의 가치는 실제 검증 (즉,하지하고 있음을합니까 분명히 불법을).
undergroundmonorail

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 문자열에서 절반 이동 수는 통과 대상 사각형과 일치해야합니다. 목표 사각형이 존재하면, 반 이동 횟수는 0이어야합니다. 절반 이동 수는 전체 이동 수와 일치해야합니다. 예를 들어, 10의 절반 이동 횟수는 3의 전체 이동 수와 호환되지 않습니다.


1

늦게 파티에 왔습니다.

위치가 합법적인지 100 % 검증 할 수는 없지만 검증이 중요한 이유는 무엇입니까? 위치가 시작 위치 (소위 "게임 배열")에서 파생되는지 여부에 관계없이 체스를 할 수 있습니다. 분석해야 할 매우 흥미로운 입장이있을 수 있지만 불법 일뿐입니다.

그래서 나는 단지 점검 할 것이다 :

  • 양쪽에서 정확히 1 명의 왕이 있습니까?
  • 1 등석이나 8 등석에 폰이 없습니까?
  • 움직일 측이 이미 점검을하지 않습니까?

이것이 3 개의 YES라면이 다이어그램에서 체스 포워드를 재생할 수 있습니다. 이 짧은 조건 목록조차도 풀 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.