나는 개인 프로젝트를하고 있는데, 한 시점에서 FEN 위치를 확인해야하며 왕이 있는지 확인하고 여분의 행이나 열이 없는지 확인하는 것과 같은 몇 가지 기본 점검으로 시작했습니다. 소지품.
그러나 FEN이 합법적임을 확인하기 위해 다른 점검을해야합니까?
나는 개인 프로젝트를하고 있는데, 한 시점에서 FEN 위치를 확인해야하며 왕이 있는지 확인하고 여분의 행이나 열이 없는지 확인하는 것과 같은 몇 가지 기본 점검으로 시작했습니다. 소지품.
그러나 FEN이 합법적임을 확인하기 위해 다른 점검을해야합니까?
답변:
다음은 일반적인 위치의 99.99 % 이상을 검증해야하는 체계적인 목록입니다.
판:
왕 :
체크 무늬:
폰 :
x3
또는 위에 있어야합니다 x6
, 그 앞에 폰이 있어야합니다 (정확한 색에서), 그리고 광장과 그 뒤에있는 것이 비어 있습니다)extra_pieces = Math.max(0, num_queens-1) + Math.max(0, num_rooks-2)...
다음과를 extra_pieces <= (8-num_pawns)
두 개 (또는 그 이상) 같은 정사각형 색상에서 주교가있는 경우 또한, 주교 특별 계산을해야한다,), 다음은 전당포 프로모션을 통해 생성 될 수 있으며 포함해야한다 위의 공식에 대한 정보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 조각캐슬 링 :
주교 :
extra_pieces
이 경우 가능 여부를 경우 우리가 결정할 수있다)비 점퍼 :
반 / 전동 시계 :
HalfMoves <= ((FullMoves-1)*2)+(if BlackToMove 1 else 0)
, +1 또는 +0은 이동할쪽에 따라 다릅니다.x >= 0
FullMoves 및x >= 1
다른:
참고 : ' 8 명 이하의 폰' + '추가 판촉물 방지' + '정확히 한 왕' 이이 점을 이미 다루어야 하기 때문에 '플레이어는 16 개 이상의 조각을 가져서는 안됩니다' 확인을 할 필요가 없습니다.
참고 2 : 이 규칙은 일반 체스의 시작 위치에서 발생하는 위치의 유효성을 검사하기위한 것이며 일부 규칙은 Chess960 ( 일부 Nº518 에서 시작한 경우 제외)의 일부 위치를 무효화 하고 생성 된 퍼즐을 피하여 기능 유효성 검사기를 얻지 않도록합니다.
a
파일을.
\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
castling 능력에 대한 부분을 이해하지 못하고 그것을 다시 썼다/^\s*([rnbqkpRNBQKP1-8]+\/){7}([rnbqkpRNBQKP1-8]+)\s[bw]\s(-|K?Q?k?q?)\s(-|[a-h][36])/
([rnbqkRNBQK1-8]+\/)([rnbqkpRNBQKP1-8]+\/){6}([rnbqkRNBQK1-8]+) ....
(0|[1-9][0-9]*)\s([1-9][0-9]*)
이동이 선행 0을 가질 수없고 전체 이동이 0으로 시작하거나 0으로 시작할 수 없으므로 (코드 크레디트)
다른 것들을 위해, 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);
}
position.is_okay()
. 코드는 여기에 단지 기본적인 검사의 몇 올바르게 포맷 된 것 있는지 확인하고 그것의 가치는 실제 검증 (즉,하지하고 있음을합니까 분명히 불법을).
다음은 모든 보드 상태 (위치라고도 함)에서 역 법적인 이동을 확인할 수있는 기능을 제공하는 간단한 역 추적 알고리즘입니다.
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
늦게 파티에 왔습니다.
위치가 합법적인지 100 % 검증 할 수는 없지만 검증이 중요한 이유는 무엇입니까? 위치가 시작 위치 (소위 "게임 배열")에서 파생되는지 여부에 관계없이 체스를 할 수 있습니다. 분석해야 할 매우 흥미로운 입장이있을 수 있지만 불법 일뿐입니다.
그래서 나는 단지 점검 할 것이다 :
이것이 3 개의 YES라면이 다이어그램에서 체스 포워드를 재생할 수 있습니다. 이 짧은 조건 목록조차도 풀 수 있습니다.