FEN形式またはOBF形式をコマンドラインまたはOBFファイルから受け取り、n手先のありえる盤面を全てOBFファイル群(最小形式)および標準出力として出力するプログラムです。
このプログラムは、リバーシ(オセロ)の指定されたFEN形式またはOBF形式の初期局面から開始して、指定された手数先の全ての可能な局面を網羅的に生成します。生成された局面は、標準出力にFEN形式で表示され、同時に個別のOBFファイル(最小形式)として保存されます。
重複排除機能: デフォルトで回転・反転による同一局面の重複を排除し、効率的な局面列挙を行います。
主な用途:
- リバーシAIの学習データ生成
- 局面解析用のデータセット作成
- Edaxとの連携による強解決準備
- ゲーム木の可視化・解析
- Python 3.6以上
- 標準ライブラリのみを使用(追加パッケージのインストール不要)
# リポジトリのクローン後、enumeratorディレクトリに移動
cd enumerator
# 実行権限の付与(Linuxの場合)
chmod +x reversi_enumerator.pypython reversi_enumerator.py [-n DEPTH] [--fen FEN | --obf OBF | --obf-file OBF_FILE] [--output-dir OUTPUT_DIR] [--no-obf-output] [--allow-duplicates] [--subdir-name SUBDIR]| オプション | 説明 | 必須 |
|---|---|---|
--fen FEN |
FEN形式の初期局面を直接指定(省略時は標準初期盤面) | - |
--obf OBF |
OBF形式の初期局面を直接指定 | - |
--obf-file OBF_FILE |
局面を記載したOBFファイルを指定 | - |
-n DEPTH, --depth DEPTH |
何手先の局面を列挙するか(デフォルト: 1) | - |
--output-dir OUTPUT_DIR |
OBFファイル出力ディレクトリ(デフォルト: カレント) | - |
--no-obf-output |
OBFファイル出力を無効にする | - |
--edax-format |
標準出力をedax setboard形式で出力する | - |
--allow-duplicates |
回転・反転による同一局面の重複を許可する | - |
--subdir-name SUBDIR |
OBFファイルを格納するサブディレクトリ名(省略時はタイムスタンプで自動生成) | - |
-h, --help |
ヘルプを表示 | - |
このプログラムで使用するFEN形式は以下の通りです:
基本構造: 盤面表現 手番
盤面表現:
- 8行を'/'で区切って表現
- 各行は左から右へのマス状態を示す
X= 黒石、O= 白石- 数字 = 連続する空きマスの数(1~8)
手番:
X= 黒番(先手)O= 白番(後手)
例:
8/8/8/3OX3/3XO3/8/8/8 X # 標準的な開始局面、黒番
2O1OX2/X1OOO3/8/8/8/8/8/8 O # 複雑な局面、白番
このプログラムで使用するOBF形式は以下の通りです:
基本構造: 盤面文字列64文字 手番
盤面文字列:
- 64文字でA1からH8まで順番に表現
XまたはB= 黒石OまたはW= 白石-= 空きマス
手番:
XまたはB= 黒番(先手)OまたはW= 白番(後手)
例:
----------------------------OX------XO--------------------------- X # 標準的な開始局面、黒番
---------------------------XOX------XO--------------------------- O # 複雑な局面、白番
# 1. 標準初期盤面から1手先の局面を列挙(最も簡単)
python reversi_enumerator.py -n 1
# 2. コマンドラインでFEN形式を指定して1手先の局面を列挙
python reversi_enumerator.py --fen "8/8/8/3OX3/3XO3/8/8/8 X" -n 1
# 3. 2手先の局面を列挙
python reversi_enumerator.py --fen "8/8/8/3OX3/3XO3/8/8/8 X" -n 2
# 4. コマンドラインでOBF形式を指定して1手先の局面を列挙
python reversi_enumerator.py --obf "----------------------------OX------XO--------------------------- X" -n 1
# 5. OBFファイルから複数の初期局面を読み込んで1手先の局面を列挙
python reversi_enumerator.py --obf-file input_positions.obf -n 1# 6. OBFファイル出力を無効にして標準出力のみ
python reversi_enumerator.py --fen "8/8/8/3OX3/3XO3/8/8/8 X" -n 1 --no-obf-output
# 7. OBF形式でもファイル出力を無効化可能
python reversi_enumerator.py --obf "----------------------------OX------XO--------------------------- X" -n 2 --no-obf-output
# 8. 出力ディレクトリを指定
python reversi_enumerator.py --fen "8/8/8/3OX3/3XO3/8/8/8 X" -n 2 --output-dir ./results
# 9. 深い探索(3手先の局面を列挙)
python reversi_enumerator.py --obf "----------------------------OX------XO--------------------------- X" -n 3 --output-dir ./deep_search
# 10. edax setboard形式で出力(Edaxと連携)
python reversi_enumerator.py --fen "8/8/8/3OX3/3XO3/8/8/8 X" -n 2 --edax-format --no-obf-output
# 11. 重複を許可して全局面を列挙(従来の動作)
python reversi_enumerator.py --fen "8/8/8/3OX3/3XO3/8/8/8 X" -n 2 --allow-duplicates
# 12. 重複排除の効果を確認(デフォルト vs 重複許可)
python reversi_enumerator.py --fen "8/8/8/3OX3/3XO3/8/8/8 X" -n 3 --no-obf-output | wc -l
python reversi_enumerator.py --fen "8/8/8/3OX3/3XO3/8/8/8 X" -n 3 --allow-duplicates --no-obf-output | wc -l
# 13. 最も簡単な実行(標準初期盤面から2手先の局面を列挙)
python reversi_enumerator.py -n 2
# 14. カスタムサブディレクトリ名を指定
python reversi_enumerator.py -n 2 --subdir-name "test_game"
# 出力先: ./test_game/position_000001.obf, ./test_game/position_000002.obf, ...
# 15. サブディレクトリ名指定なし(タイムスタンプで自動生成)
python reversi_enumerator.py -n 2
# 出力先: ./positions_20240101_123000/position_000001.obf, ./positions_20240101_123000/position_000002.obf, ...各局面がFEN形式で1行ずつ表示されます:
8/8/8/3OX3/3XO3/8/8/8 X
8/8/8/2XOX3/3XO3/8/8/8 O
8/8/8/3OXX2/3XO3/8/8/8 O
8/8/8/3OX3/2XXO3/8/8/8 O
8/8/8/3OX3/3XOX2/8/8/8 O
各局面がedax setboard用の形式で1行ずつ表示されます:
----------------------------ox------xo---------------------------- x
---------------------------xox------xo---------------------------- o
----------------------------oxx-----xo---------------------------- o
----------------------------ox------xxo--------------------------- o
----------------------------ox------xox--------------------------- o
この形式はedaxのsetboardコマンドで直接使用できます。
各局面が個別のOBFファイル(最小形式)として専用ディレクトリ内に出力されます:
出力ディレクトリ構造:
- カスタムサブディレクトリ指定時:
[base-dir]/[subdir-name]/position_XXXXXX.obf - サブディレクトリ未指定時:
[base-dir]/positions_YYYYMMDD_HHMMSS/position_XXXXXX.obf
ファイル内容例:
----------------------------OX------XO--------------------------- X;
出力例:
# カスタムサブディレクトリ使用時
./test_game/position_000001.obf
./test_game/position_000002.obf
...
# タイムスタンプ自動生成時
./positions_20240101_143022/position_000001.obf
./positions_20240101_143022/position_000002.obf
...# 4 局面をOBFファイルとして ./positions_20240101_143022 に出力しました
各行に1つの局面を記述します:
----------------------------OX------XO--------------------------- X;
---------------------------XOX------XO--------------------------- O;
% コメント行(%で始まる行は無視されます)
# 空行も無視されます
注意事項:
- セミコロンまでが盤面部分として解析されます
- 64文字の盤面 + 手番 + セミコロンの形式
- コメント行(%で始まる)と空行は自動的にスキップされます
指定手数先の局面数は手数が増えるにつれて指数関数的に増加します:
注意: 出力されるのは指定手数先の局面のみで、途中の中間状態は含まれません。
重複排除有効時(デフォルト):
| 手数 | 概算局面数 | 実行時間目安 |
|---|---|---|
| 1手先 | 4局面 | < 1秒 |
| 2手先 | 10-15局面 | < 1秒 |
| 3手先 | 30-60局面 | 1秒 |
| 4手先 | 100-300局面 | 数秒 |
| 5手先 | 500+局面 | 数秒 |
重複許可時(--allow-duplicates):
| 手数 | 概算局面数 | 実行時間目安 |
|---|---|---|
| 1手先 | 4局面 | < 1秒 |
| 2手先 | 10-20局面 | < 1秒 |
| 3手先 | 50-100局面 | 1-2秒 |
| 4手先 | 200-500局面 | 数秒 |
| 5手先 | 1000+局面 | 十数秒 |
- 全局面がメモリ上で保持されるため、深い探索では大量のメモリを消費
- 実用的な範囲: 3-5手先程度
- 各局面が個別ファイルとして出力されるため、大量のファイルが生成される
- ファイルシステムの制限(inode数など)に注意
このプログラムで生成された局面は、Edaxで直接解析できます:
# 1. OBFファイルを生成してEdaxで強解決
python reversi_enumerator.py --fen "8/8/8/3OX3/3XO3/8/8/8 X" -n 2 --output-dir ./positions
for obf in ./positions/*.obf; do
edax -l 60 -solve "$obf"
done
# 2. edax setboard形式で出力してEdaxで直接使用
python reversi_enumerator.py --fen "8/8/8/3OX3/3XO3/8/8/8 X" -n 1 --edax-format --no-obf-output | while read board; do
echo "setboard $board" | edax -l 60
done
# 3. 特定の局面をedaxで設定
python reversi_enumerator.py --fen "8/8/8/3OX3/3XO3/8/8/8 X" -n 1 --edax-format --no-obf-output
# 出力例: ----------------------------ox------xo---------------------------- x
# edaxで使用: setboard ----------------------------ox------xo---------------------------- x重要: edaxのsetboardコマンドはFEN形式を受け付けません。以下の形式を使用してください:
setboard [64文字の盤面] [手番]
- 黒石:
b,x,*(大文字小文字問わず) - 白石:
o,w(大文字小文字問わず) - 空きマス:
-,. - 手番:
b/x/*(黒番) またはo/w(白番)
# 標準開始盤面をedaxで設定
setboard ----------------------------ox------xo---------------------------- x
# プログラムでedax形式を生成
python reversi_enumerator.py --fen "8/8/8/3OX3/3XO3/8/8/8 X" -n 1 --edax-format
# 出力: ----------------------------ox------xo---------------------------- xエラー: 「FEN形式の行数が不正です」
- 原因: FEN文字列の'/'区切りが8行でない
- 対処:
8/8/8/3OX3/3XO3/8/8/8 Xのような正しい形式を使用
エラー: 「OBFファイル 'xxx' が見つかりません」
- 原因: 指定されたOBFファイルが存在しない
- 対処: ファイルパスを確認し、正しいパスを指定
警告: 「局面 'xxx' をスキップしました」
- 原因: 不正なFEN形式の局面がOBFファイルに含まれている
- 対処: 警告は無視して継続、または入力ファイルを修正
# 解決策1: 探索手数を減らす
python reversi_enumerator.py --fen "..." -n 2 # 3から2に変更
# 解決策2: OBFファイル出力を無効にする
python reversi_enumerator.py --fen "..." -n 3 --no-obf-output# ulimitでファイル数制限を確認・変更
ulimit -n 10000
# または出力を無効にして標準出力のみ使用
python reversi_enumerator.py --fen "..." -n 3 --no-obf-output# 基本的な動作テスト(FEN形式)
python reversi_enumerator.py --fen "8/8/8/3OX3/3XO3/8/8/8 X" -n 1
# 基本的な動作テスト(OBF形式)
python reversi_enumerator.py --obf "----------------------------OX------XO--------------------------- X" -n 1
# エラーハンドリングのテスト
python reversi_enumerator.py --fen "invalid_fen" -n 1
python reversi_enumerator.py --obf "invalid_obf" -n 1
# OBFファイル読み込みテスト
echo "----------------------------OX------XO--------------------------- X;" > test.obf
python reversi_enumerator.py --obf-file test.obf -n 1標準エラー出力に詳細な情報が表示されます:
- エラーメッセージ
- 警告メッセージ(スキップされた局面など)
- 処理結果統計
- 標準ライブラリのみを使用しているため、追加の依存関係はありません
- Python 3.6以上での動作を保証
- クロスプラットフォーム対応(Windows、macOS、Linux)