Published on: 2022-01-21
思考エンジン
思考エンジンの大まかな処理の流れは以下の通り:
- ルート局面(思考開始局面)を評価する。
- 探索による思考(定跡不使用)を行い、最善手を求める。
基本的に 1 手先しか読まないが、王手の場合はプレイヤー玉の詰み判定も行う。
- 条件を満たせば定跡手も検討し、最終的な指し手を決める。
また、手数などに基づく「進行度」が思考に影響する。
以下、特に断らない限り玉位置は ルート局面での 玉位置が使われる(末端局面の評価時であっても)。
なお、局面評価などは多くの場合オーバーフローを考慮していない。
進行度
進行度の初期値は 0 で、最大値は 3 である。ただし、実際には 1 以上の進行度は全て同じ意味になる。
進行度が 0 のとき、探索による思考の後に定跡手が検討される可能性がある。つまり進行度は定跡を使うかどうかのフラグ(0:true, 非0:false)と考えてよい。
思考エンジンは、通常の手数とは別に「進行度管理用手数」を持つ。これは開始局面での初期値は 0 で、1 手ごとに 1 増える(ただし最大 100)。
プレイヤーが着手を行った後、進行度管理用手数が 51 以上ならば進行度が 1 増え(ただし最大 2)、71 以上ならば進行度が 3 になる。
進行度管理用手数そのものも思考に影響する。
ルート局面評価
ルート局面の評価項目は以下の通り:
- 最大駒得価値。「今取れる駒の最大価値」と解釈できる。
- 最大駒損価値。「次に取られる駒の最大価値」と解釈できる。
- プレイヤー power (
8*(持飛+持角+成駒) + 4*(持金+持銀) + 2*(持桂+持香) + 1*(持歩) + (手数補正)
)。
「進行度を加味したプレイヤー側の戦力」と解釈できる。
- COM power (
8*(持飛+持角+成駒) + 4*(持金+持銀) + 2*(持桂+持香) + 1*(持歩) + (手数補正)
)。
「進行度を加味したCOM側の戦力」と解釈できる。
- COM側の
持飛+持角+成駒
。
power の手数補正は以下の通り:
(進行度管理用手数) < 77
の場合、(進行度管理用手数) / 11
(進行度管理用手数) >= 77
の場合、(進行度管理用手数) / 11 * 2
ルート局面の最大駒得価値が 30 以上の場合、プレイヤーが自殺手を指したと判定し、探索による思考をスキップする(玉の価値は 40 で、他の駒の価値は全て 30 未満であることに注意)。
これはほとんどの場合プレイヤーの負けになるが、ごく稀な例外もある(後述)。
探索による思考
基本深さ 1 の探索を行う(プレイヤー玉の詰み判定を行う場合のみ深さ 2)。
候補手の集合はルート局面における全ての疑似合法手となる。疑似合法手には自殺手および打ち歩詰めが含まれるが、打ち歩詰めはプレイヤー玉の詰み判定の際に除外される。なお、千日手判定は行わない。
全ての候補手を生成し、各候補手を適用した末端局面を評価し、その評価を現在の最善手と比較して最善手を更新していく。
初期状態では最善手が存在しないので、最善手の評価として最も悪いものを割り当てておく(これは自殺手扱いになるので、最終的に最善手が存在しない場合はプレイヤーの勝ちになる)。
末端局面評価
末端局面評価は 2 段階に分かれている。第 1 段階で簡易評価を行い、第 2 段階で諸々の要素を加味した補正を行う。
一部の候補手は第 1 段階で却下される(最善手との比較が行われない)。
末端局面評価 第 1 段階
以下の項目を評価する:
- その指し手で捕獲する駒の価値(駒取りでなければ 0)。駒価値テーブルA を用いる。後から補正を受ける。
- 最大駒得価値。「次に取れる駒の最大価値」と解釈できる。後から補正を受ける。
- 最大駒得マス。
- 最大駒損価値。「今取られる駒の最大価値」と解釈できる。後から補正を受ける。
- 最大駒損マス。
- 総駒得価値。「次に取れる駒の価値の総和」と解釈できる。後から補正を受ける。
- 総駒損価値。「今取られる駒の価値の総和」と解釈できる。後から補正を受ける。
- プレイヤー玉の危険度。プレイヤー玉から距離 2 以内のマスへのCOM利き数の総和で評価される。
- COM玉の危険度。以下の項目で評価される:
- COM玉から距離 2 以内へのCOM利き数の総和
- COM玉から距離 2 以内へのプレイヤー利き数の総和
- COM玉からちょうど距離 1 へのプレイヤー利き数の総和
- COM玉からちょうど距離 1 で、
(プレイヤー利き数) >= (COM利き数)
なるマスの個数
- プレイヤー側の垂れ歩または垂れ香が存在するかどうか。
- COM側の成駒の個数。
- COM側の離れ駒の個数。ただし歩、香、桂、玉は除く。
また、以下の条件を全て満たすとき、プレイヤー玉の詰み判定を行う:
- 最大駒損価値が 30 未満 (「自殺手でない」と解釈できるが、取り返しフラグ補正 が大量にかかると自殺手を弾き損ねることがある。これは COMが王手放置して詰ましてくるバグ の原因となっている)
- 最大駒得価値が 30 以上 (「プレイヤー玉に王手がかかっている」と解釈できる)
- 候補手の移動先からプレイヤー玉への距離が 3 未満。これは計算量を減らす工夫と思われるが、遠隔駒での王手の場合詰み判定が行われないケースがありうる(その場合は次にプレイヤーが自殺手を指して終了するだけなので、あまり問題にはならないが)。
詰み判定の際、打ち歩詰めと判定されたらその候補手は却下される。
プレイヤー玉が正当な詰みと判定された場合、それより後の候補手は生成しない。また、現在の候補手に以下の補正をかける:
- 捕獲する駒の価値を 60 とする
- 最大駒得価値を 60 とする
- 最大駒損価値を 0 とする
また、王手対応(最大駒損価値が 30 以上)や詰ます手を除き、駒捨ての候補手は却下する。
具体的には、移動先が駒損マスで、かつ駒取りでない手は駒捨てとみなされる。
これは 合法手があっても投了してしまう現象 の一因となっている。
末端局面評価 第 2 段階
第 1 段階で得られた評価に対し、以下の補正を行う:
- 最大駒損価値が 20 未満で、かつ歩(不成)で駒を取る手であれば、総駒損価値を 1 減らす。
「COM側の玉、龍、馬が取られず、歩で駒を取る手の評価を上げる」と解釈できる。
- プレイヤー側の垂れ歩または垂れ香が存在すれば、総駒損価値を 4 増やす。
- ルート局面のプレイヤー power または COM power が 15 以上で、かつ総駒損価値が 3 未満で、かつ最大駒損マスからCOM玉への距離が 4 以上ならば、総駒損価値から最大駒損価値を差し引く。
「中盤以降はCOM玉から遠い歩またはと金を取られるのを軽視する」と解釈できる。
- プレイヤー power, COM power の少なくとも一方が 25 以上であれば、以下の補正を行う(「終盤用補正」と解釈できる):
- 最大駒得マスからプレイヤー玉への距離が 4 以上かつCOM玉への距離が 3 以上ならば、総駒得価値から最大駒得価値を差し引く。
「互いの玉から遠い最大駒得マスを軽視する」と解釈できる。
- 最大駒損価値が 7 未満で、最大駒損マスからプレイヤー玉およびCOM玉への距離がともに 3 以上ならば、総駒損価値から最大駒損価値を差し引く。
「互いの玉から遠く、かつ価値の低い最大駒損マスを軽視する」と解釈できる。
- 候補手が駒取りで、かつ移動先からプレイヤー玉への距離が 2 以下ならば、捕獲する駒の価値を 2 増やす。
「プレイヤー玉に近い駒を取る手の評価を上げる」と解釈できる。
- 候補手が駒取りで、かつ移動先からプレイヤー玉およびCOM玉への距離がともに 4 以上ならば、捕獲する駒の価値を 3 減らす。
「互いの玉から遠い駒を取る手の評価を下げる」と解釈できる。
- 最大駒得価値が 30 以上で、プレイヤー玉から距離 2 以内へのCOM利き数の総和が 12 未満で、
(総駒得価値)-(最大駒得価値)
が 3 未満で、ルート局面でのCOM側の 持飛+持角+成駒
が 4 未満かつ COM power が 35 未満ならば、総駒得価値から最大駒損価値を差し引く。
「寄せが見込めない状況ではむやみに王手をかけない(ただし「王手xx取り」を除く)」と解釈できる。
- 候補手が飛角金銀のいずれかを打つ手で、移動先が 5 段目かそれより上で、移動先からプレイヤー玉およびCOM玉への距離がともに 3 以上で、ルート局面での最大駒損価値が 30 未満ならば、総駒損価値を 2 増やす。
「高い駒を自陣側かつ互いの玉から遠くに打つ手の評価を下げる(合駒は除く)」と解釈できる。
- ルート局面での COM power が 27 以上のとき、総駒得価値が 6 以上ならば捕獲する駒の価値を 4 増やし、総駒得価値が 3 以上 6 未満ならば、捕獲する駒の価値を 1 増やす。この補正は候補手が駒取りでなくても適用される。
「戦力が多ければ駒取りをかける手の評価を上げる」という意図?
- 候補手が大駒を打つ手のとき、移動先が 8, 9 段目ならば、総駒得価値を 2 増やし、総駒損価値を 2 減らす。
「大駒を敵陣 1, 2 段目に打つ手の評価を上げる」と解釈できる。
- 候補手が大駒を打つ手で、ルート局面での最大駒損価値が 30 未満のとき、移動先が 1〜7 段目ならば、総駒得価値を 2 減らし、総駒損価値を 2 増やす。移動先が 1〜4 段目ならば、さらに総駒損価値を 2 増やす。
「大駒を敵陣 1, 2 段目以外に打つ手の評価を下げる(合駒を除く)」と解釈できる。
- 候補手が玉を動かす指し手の場合、捕獲する駒の価値を 1 減らし、総駒得価値を 2 減らす。この補正は候補手が駒取りでなくても適用される。
「玉で駒を取ったり駒取りをかける手の評価を下げる(なるべく他の駒を使う)」と解釈できる。
- ルート局面での COM power が 31 以上のとき、最大駒得価値が 4 未満で、最大駒損価値が 0 で、プレイヤー玉から距離 2 以内へのCOM利き数の総和が 7 以上で、最大駒得マスからCOM玉への距離が 2 以下ならば、総駒得価値に
((プレイヤー玉から距離 2 以内へのCOM利き数の総和)-7) / 2
を加える。
これはどう解釈すべきかよくわからないが、最後の条件はCOM玉でなくプレイヤー玉が対象だった可能性はある。そのように仮定すれば、「戦力が豊富でプレイヤー玉に十分迫れていれば、駒損しない限りプレイヤー玉周辺の最大駒得マスは対象が安い駒でも評価を上げる」と解釈できる。
- 最大駒得価値が 16 で、候補手が角を動かすまたは打つ手ならば、総駒得価値から最大駒得価値を差し引き、さらに最大駒得価値を 0 とする。
「自分から角をぶつける手を抑制する」と解釈できる。
- ルート局面での COM power が 27 以上のとき、候補手が大駒を打つ手でなければ、ペナルティ値を
4 * (COM玉からちょうど距離 1 で、(プレイヤー利き数) >= (COM利き数) なるマスの個数)
として、総駒得価値からペナルティ値を差し引き、総駒損価値にペナルティ値を加える。
「戦力が豊富なとき、手駒の飛車角を温存する手はCOM玉の危険度が高いほど評価を下げる」と解釈できる。
- 候補手が飛角金銀のいずれかを取る手で、捕獲する駒の価値が 8 以上で、プレイヤー玉から距離 2 以内へのCOM利き数の総和が 7 以上で、ルート局面での COM power が 30 以上で、ルート局面でのCOM側の
持飛+持角+成駒
が 4 以上で、(最大駒得価値が 30 以上、または最大駒得マスからプレイヤー玉への距離が 3 未満)であれば、総駒得価値を 2 減らす。最大駒損価値が 8 以上 30 未満の場合、さらに総駒損価値と最大駒損価値を 8 とする。
「優勢なときは高い駒を取りながらプレイヤー玉に迫る手の評価を上げ、駒損を軽視する」と解釈できる。
- 候補手が玉を動かす手で、COM玉からちょうど距離 1 へのプレイヤー利き数の総和が 5 以上ならば、捕獲する駒の価値を 0 とする。
「COM玉が危険な場合、玉による駒取りは無価値とする」と解釈できる。
なお、該当コードは候補手が駒打ちのとき配列外参照を行うバグがあり、参照先がCOM玉を表す値だった場合、この補正が誤って適用されてしまう(極めて稀なケースだとは思われる)。
- ルート局面での COM power が 35 以上のとき、最大駒得価値が 30 以上で、捕獲する駒の価値が 2 以上ならば、総駒損価値を 2 減らす。
「戦力が豊富なら駒を取りつつ王手する手の評価を上げる」と解釈できる。
- ルート局面での COM power が 20 以上で、捕獲する駒の価値が 2 未満のとき、総駒得価値に応じて捕獲する駒の価値を増やす(総駒得価値が
5..=9
なら 1, 10..=19
なら 2, 20 以上なら 3 を加える)。
「ある程度戦力があるときは、次に駒を取る手も駒取りに準ずるものとして評価する」といった意図だと思われる。
- 候補手が大駒を打つ手のとき、移動先が 6 段目かそれより上ならば、総駒得価値を 3 減らし、総駒損価値を 3 増やす。
「大駒を敵陣以外に打つ手の評価を下げる」と解釈できる(同様の補正が既にかかっているが…)。
- 候補手が成駒を動かす手のとき、総駒得価値に
(移動元からプレイヤー玉への距離) - (移動先からプレイヤー玉への距離)
を加える。
「成駒を動かす場合、プレイヤー玉に近づく手の方を高く評価する」と解釈できる。
- ルート局面での COM power が 25 以上のとき、最大駒得価値が 30 以上ならば、総駒得価値を 4 増やし、捕獲する駒の価値を 1 増やし、総駒損価値を 2 減らす。
「戦力が豊富なら王手の評価を上げる」と解釈できる。
- 最大駒損価値が 30 以上で、捕獲する駒の価値が 8 以上ならば、総駒損価値を 4 減らす。
「高い駒を取りながらの王手の評価を上げる」と解釈できる。
- 捕獲する駒の価値、総駒得価値、総駒損価値それぞれについて負ならば 0 にする。
候補手と最善手の比較
まず、候補手と最善手のいずれか一方のみが自殺手ならば自殺手でない方を採用する:
- 候補手の最大駒損価値が 40 以上で、最善手の最大駒損価値が 40 未満ならば、候補手のみが自殺手なので直ちに最善手を採用する。
(この自殺手判定は閾値がギリギリなので、取り返しフラグ補正 が 1 回かかっただけで機能しなくなる。これは 合法手があっても投了してしまう現象 の一因となっている)。
- 候補手の最大駒損価値が 40 未満で、最善手の最大駒損価値が 40 以上ならば、最善手のみが自殺手なので直ちに候補手を採用する。
次に、総駒損価値の大小により場合分けして判定を行う(末端局面の駒損マスは「今取られる駒」なので、「次に取れる駒」である駒得マスより重要と考えられる):
(候補手の総駒損価値) > (最善手の総駒損価値)
の場合(基本的には最善手の方が良いと考えられる):
(候補手の捕獲する駒の価値) < (最善手の捕獲する駒の価値)
ならば、最善手を採用する。
(候補手の捕獲する駒の価値) > (最善手の捕獲する駒の価値)
ならば、(捕獲する駒の価値の差分) >= (総駒損価値の差分)
のとき候補手を、そうでないとき最善手を採用する。
(候補手の捕獲する駒の価値) == (最善手の捕獲する駒の価値)
ならば、ルート局面での COM power が 18 以上で、捕獲する駒の価値が 0 で、(候補手の総駒得価値) > (最善手の総駒得価値)
で、(総駒得価値の差分) > (総駒損価値の差分)
の場合のみ候補手を採用し、さもなくば最善手を採用する。
(先に述べた自殺手判定が失敗した場合、大抵は総駒損価値評価で自殺手が弾かれるが、この条件を満たした場合のみ 自殺手が採用されてしまう ことがある)
(候補手の総駒損価値) < (最善手の総駒損価値)
の場合(基本的には候補手の方が良いと考えられる)、最善手の総駒損価値が 30 以上 80 未満ならば直ちに候補手を採用する。そうでない場合:
(候補手の捕獲する駒の価値) > (最善手の捕獲する駒の価値)
ならば、候補手を採用する。
(候補手の捕獲する駒の価値) < (最善手の捕獲する駒の価値)
ならば、捕獲する駒の価値の差分と総駒損価値の差分を比較し、良い方を採用する。差分が等しい場合、タイブレーク処理に移る。
(候補手の捕獲する駒の価値) == (最善手の捕獲する駒の価値)
ならば、ルート局面での COM power が 18 以上で、捕獲する駒の価値が 0 で、(候補手の総駒得価値) < (最善手の総駒得価値)
の場合のみ、総駒得価値の差分と総駒損価値の差分を比較し、良い方を採用する。差分が等しければタイブレーク処理に移る。本項の条件を満たさなければ候補手を採用する。
(候補手の総駒損価値) == (最善手の総駒損価値)
の場合、捕獲する駒の価値を比較し、良い方を採用する。これも等しければタイブレーク処理に移る。
ここまでで決着しなかった場合、タイブレーク処理を行う:
- COM側の成駒の個数が異なるなら、多い方を採用。
- 総駒得価値が異なるなら、良い方を採用。
- 最大駒得価値が異なるなら、良い方を採用。
- 候補手が駒打ちの場合、
- ルート局面での最大駒損価値が 30 未満ならば最善手を採用する。
「合駒でない限り、駒打ちより盤上の駒を動かす手を優先する」と解釈できる。
- より安い駒(安い方から 歩香桂銀金角飛 の順)を打つ手を採用する。
(該当コードは最善手の移動元を参照するが、これは局面ごとに初期化されないので、場合によっては以前の局面が思考に影響しうる)
- 候補手が盤上の駒を動かす手の場合、
- プレイヤー玉から距離 2 以内へのCOM利き数の総和が異なるなら、多い方を採用。
- COM玉から距離 2 以内へのCOM利き数の総和が異なるなら、多い方を採用。
- COM玉から距離 2 以内へのプレイヤー利き数の総和が異なるなら、少ない方を採用。
- COM側の離れ駒の個数が異なるなら、少ない方を採用。
- 候補手の移動元からCOM玉への距離が 3 以上で、移動先からプレイヤー玉への距離が異なるなら、距離が小さい方を採用。
- 移動元からCOM玉への距離を比較し、候補手の方が大きければ候補手を採用し、さもなくば最善手を採用する。
「自玉周りの駒はなるべく動かさない」と解釈できる。
定跡処理と最終的な指し手決定
まず、以下の条件を全て満たす場合はここまでの思考結果によらず定跡処理(後述)を行う:
- 進行度管理用手数が 6 以下
- 直前のプレイヤーの指し手の移動先が2二, 4五, 5六のいずれか
- 進行度が 0
(これはプレイヤーが自殺手を指した場合にも適用されるため、王手放置ができてしまうバグ の原因となっている)
そうでない場合、まず対局終了判定を行う:
- ルート局面評価でプレイヤーが自殺手を指したと判定されていたらCOMの勝ちとする。
- 探索による思考で得られた最善手の最大駒損価値が 31 以上ならCOM玉が詰んだとみなし、プレイヤーの勝ちとする。
(取り返しフラグ補正 が大量にかかるとCOM玉の詰み判定に失敗し、COM玉が取れてしまう ことがある)
そして、以下の条件を全て満たすとき定跡処理を行う:
- 進行度が 0
- ルート局面での最大駒得価値と最大駒損価値がともに 0 であり、最善手が駒取りでない
(「駒得/駒損が発生するなら定跡処理をキャンセル」と解釈できる)
- 最善手の総駒得価値と最大駒得価値が等しいか、もしくは最善手の総駒得価値が 8 未満
(「有望な駒得マスが複数あるなら定跡処理をキャンセル」と解釈できる)
定跡処理
定跡は戦型別に定義されており、プレイヤーの特定の指し手への対応を定める「定跡分岐」と、序盤の手順を定める「定跡手順」からなる。
定跡分岐は具体的な応手または戦型変更のいずれかである。
戦型が変わらない限り、定跡分岐/定跡手順のいずれについても、一度定跡処理で返した手は二度と使われない。
まず定跡分岐処理を行う。直前のプレイヤーの指し手に対応するエントリがある場合、それが具体的な応手ならば定跡手として返す。戦型変更の場合、戦型を変更して定跡分岐処理を最初からやり直す。
定跡分岐処理でエントリが見つからなかった場合、定跡手順処理を行う。定跡手順内に未使用の指し手があれば、最初のものを定跡手として返す。
定跡手順内の指し手が全て使用済みならば定跡を抜ける(戦型を「なし」に変更し、進行度を 1 にする)。
以上の処理で定跡手が返された場合、それを実際に採用するかどうかのテストを行う(このテストに失敗しても定跡手は使用済みとなる):
- 定跡手が違法手となるなら却下。
- 定跡手の移動先について
(プレイヤー利き数) >= (COM利き数)
ならば却下。
- 定跡手を指した局面を評価した結果、駒損する(最大駒損価値が 0 でない)なら却下。
ただし、進行度管理用手数が 6 以下かつ直前のプレイヤーの指し手の移動先が4五の場合のみ却下しない。これにより、序盤いきなり右桂を跳ね出して5三を破る手順が成立する。意図は不明だが、裏技的要素なのかも?
このテストを通ったら定跡手を採用し、さもなくば探索による思考で得られた最善手を採用する。