私は個人的なプロジェクトを行っており、ある時点でFENの位置を検証する必要があります。私はいくつかの基本的なチェックから始めました。もの。
しかし、FENが合法であることを完全に確認するには、他にどのようなチェックを行う必要がありますか?
私は個人的なプロジェクトを行っており、ある時点でFENの位置を検証する必要があります。私はいくつかの基本的なチェックから始めました。もの。
しかし、FENが合法であることを完全に確認するには、他にどのようなチェックを行う必要がありますか?
回答:
一般的なポジションの99.99%以上を検証する必要がある、よく整理されたリストを次に示します。
ボード:
キングス:
チェック:
ポーン:
x3
か、x6
その前に正しい色からのポーン()、専用アンパッサン広場、それが空になっているの背後にある1がなければならない、ランク)extra_pieces = Math.max(0, num_queens-1) + Math.max(0, num_rooks-2)...
た後、extra_pieces <= (8-num_pawns)
あなたが同じ正方形の色から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
、あなたがAまたはHで5個の駒を見た場合、例えば、他のプレイヤーは15から少なくとも10枚の欠落しなければならないで捕捉枚キャスリング:
司教:
extra_pieces
この場合には可能であるかどうか、我々が決定することができます)非ジャンパー:
ハーフ/フルムーブ時計:
HalfMoves <= ((FullMoves-1)*2)+(if BlackToMove 1 else 0)
、+ 1または+0は移動する側に依存しますx >= 0
とFullMovesx >= 1
その他:
注:作成する必要はありません「の選手が16点の以上の作品持つべきではない」ポイントので、チェックを「せいぜい8つのポーンは」 + 「余分な推進の作品を防ぐには」 + "正確に一つの王、すでにこの点をカバーする必要がありますが
注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
キャスティング能力に関する部分を理解していなかったので、書き直した/^\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から開始できないため、良いかもしれません(コードクレジット)
その他については、FEN文字列を検証するStockfishエンジンの単純な関数があります。
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
パーティーに遅れて来る。
ポジションが合法かどうかを完全に検証することはできませんが、なぜ検証が重要なのでしょうか?位置がたまたま開始位置(いわゆる「ゲームアレイ」)から派生したかどうかに関係なく、チェスをプレイできます。分析する非常に興味深い立場があるかもしれませんが、それはたまたま違法であることが起こります。
だから私はちょうどチェックします:
それが3つのYESなら、この図からフォワードチェスをプレイできます。そして、この短い条件リストでさえ、緩めることができるかもしれません。