ターンベースの戦略ゲームに最小/最大を正常に適用するには、利用可能なすべてのチェステクニックを正しく適用する必要があります...
評価関数
評価機能が悪いと、チェスエンジンの強度も非常に悪くなります。評価関数の最も単純なバージョンは次のとおりです。1=白で勝ったゲーム、-1 =黒で勝ったゲーム、0 =その他のすべてのケース。しかし、これは非常に悪いパフォーマンスをもたらします。ターンベースのゲームでも同じことが起こります!チェスのように最小/最大(アルファ/ベータプルーニングなど)を使用する場合は、妥当な評価関数も実装する必要があります!それ以外の場合、戦略ゲームに適用される場合のアルゴリズムのパフォーマンスをチェスに適用される場合と比較することはできません。
チェスエンジンの評価関数が行うことは、次のようなものを評価することです。
- ボード上のピースの位置はどれくらいですか?
- ピースは何回攻撃されますか?
- 作品は何回保護されていますか?
- 各ピースはボード上で自由に「移動」できますか?(または:「制御」するタイルの数)
評価関数のこれらの部分は、最初にゲームに「翻訳」する必要があります。
- ピースの位置:例えば、射撃範囲を広げている丘の上にありますか?
- 攻撃された:各ピースはどれだけ危険にさらされていますか?(例えば、特殊ユニットを攻撃できるユニットの攻撃値の合計に、それによって攻撃される確率を掛けた。ユニットが既に損傷している場合は確率が増加し、他の多くのユニットが攻撃ユニットの範囲内にある場合は減少する)
- 自力攻撃:この各ユニットはいくつのユニットを攻撃できますか?
- 保護:隣にどれだけのピースがありますか(支援のため)?ユニットは最短距離でユニットを攻撃することはできず、近くのユニットを攻撃する可能性があるユニットで保護することが望ましいかもしれません。
- モビリティ:ユニットのモバイル性はどのくらいですか?(逃げることができますか?)
異なる評価は、すべてのユニットの重み関数(factor_a * rating_a + factor_b * ranting_b + ...)によって合計する必要があります...
戦略ゲームでは、残っているリソース(金、木、...)も考慮する必要があります。
評価関数が十分であれば、ほとんどの場合、実際にツリーを「深く」検索する必要はありません。したがって、おそらく、最も有望な3つまたは10の選択肢を詳しく調べるだけで十分です。次の章を参照してください...
各位置で可能な動き
戦略ゲームで最小/最大を使用することで最も問題なのは、1ターンで複数のユニットを指揮できることです。一方、チェスでは1つのユニットしか指揮できません(キャスリングを除きますが、これは明確に定義された移動の組み合わせです)。これにより、各ユニットの「北、南、西、東、または停止の移動」のみを決定する場合、各「位置」(チェス用語)のNユニットに対して5 ^ Nの移動が可能になります。複雑なコマンドを低レベルのコマンドに分解することでこれを解決できます。たとえば、ユニットAのアクションを選択し、深さに入り、ユニットBを決定します。...ユニットNを決定し、このターンを終了します。しかし、これだけでは複雑さは変わりません!アクションがユニットに割り当てられる順序を最適化する必要があります(たとえば、最初のユニットB、C、D、次にユニットA)。最後の計算中に各ユニットの決定の影響を記録し、重要度で並べ替えることができます。この方法では、アルファベータプルーニングを使用して、検索ツリーから不適切な組み合わせを非常に早期に削除できます。最高の優先順位は、各反復で常に「これ以上何もせずにあなたのターンを終了する」(ヌル移動プルーニング)でなければなりません。これにより、ほとんどのタスクをほとんどのユニットに「スキップ」して、前のタスクをそのまま続行できます。このように、「重要な」ユニット(たとえば、現在実際に戦闘中のユニット)を見るだけで、検索はすぐに深くなります。各ユニットを1回だけコマンドするようにしてください...また、「重要な」ユニットが時々コマンドを取得していることを確認するために、ランダム性を使用することもできます。特に、いくつかの仕事を終えたユニット(例
反復深化+キャッシュ/ハッシュテーブル
その後、「インタラクティブな深化」を行って、制限時間に達するまでますます深くなることができます。したがって、ユニットが少ない場合はより深く検索し、より良いソリューションの検索を停止すると、常に「結果」が得られます。繰り返し深化するには、ハッシュテーブルを使用して、以前の検索結果をキャッシュする必要があります。これにより、最後のターンの検索(最後のターンで実際に実行されたコマンドをカバーする検索ツリーのブランチ)の結果の一部を再利用することもできます。これを実装するには、繰り返し更新可能な非常に優れたハッシュ関数(「zobristキー」を参照)が必要です。ハッシュキーを更新するということは、古い「位置」のハッシュキーを取得するだけで、位置の変更をすぐに開始できることを意味します(例:位置xのユニットを取り出し、位置y)に配置します。この方法でハッシュキーを計算するのは簡単で、ボード全体の状況を処理して計算する必要はありません。ハッシュにこの位置の以前のエントリが含まれているかどうかを確認するだけです。ある意味では、ハッシュの衝突が発生しないことを確認する必要があります。
非決定的な動作
非決定的動作は、最小/最大検索の問題です。つまり、攻撃されたターゲットにヒットするかどうかはわかりません(たとえば、確率は10%です)。その後、あなたはこれが起こるだけで計画することはできません。その場合、アルゴリズムを変更して、間に「確率」層を配置する必要があります。「確率が変わる」ようなものです。それぞれの独立した結果は別々に考慮しなければなりません。この深さの「レイヤー」を介した評価をサンプリングし(モンテカルロサンプリング)、詳細な評価の結果を発生確率で重み付けする必要があります。確率層の異なる結果は、異なる敵の動きとみなされる必要があります(ただし、最小/最大の代わりに「平均」を計算する必要があります)。もちろん、これにより検索ツリーの複雑さが増します。
概要
これらのすべての手法(現在のチェスエンジンで使用されているすべて)を決定論的なゲームに適用すると、ゲームでも合理的な結果を確実に達成できます。非決定的ゲームの場合、これはおそらくより複雑になりますが、まだ管理しやすいと思います。
これらの手法(チェスの場合)の説明に役立つリソースは、http://chessprogramming.wikispaces.com/です。
最小/最大検索である種の有向ランダム性を実装することもできます。各反復で最初に最良の結果を決定論的に調査する代わりに、これをランダム化し、現在の評価に基づいた確率分布によって順序を決定することができます...