ダガズ先を芋る

画像 1秒間に113回、それは䌞び、さらに匕っ匵りたす。 確認が来た堎合、シグナル-それは停止する可胜性があり、停止したせん。 それは手を䌞ばし、これたでにない新しい方法を芋぀けたす。 即興で勉匷したす。 䜕をしおいるのかわかりたせん...



ゞェヌムズ・コリヌ「シボレの火」



䞀般的に、匷力なAIゲヌムは私の優先事項ではありたせん。 特殊なゲヌム゚ンゞンず競争するのは愚かで、普遍的であり、コンピュヌティングリ゜ヌスずしおブラりザに組み蟌たれたシングルスレッドJavaScriptのみを持っおいたす。 さらに、耇雑なAIの必芁性がたったく生じないゲヌムがいく぀かありたす。 ここでは、たずえば、AI党䜓が最短経路を芋぀けるこずになり、 このゲヌムではタスクはタスクに完党に察応したす。 残念ながら、そのようなゲヌムはルヌルよりも䟋倖である可胜性が高いです。 倚くの堎合、単玔にばかげおいるずは思えない動きをプログラムが行うために䞀生懞呜働く必芁がありたす。



私のプロゞェクトの目暙は、ボヌドゲヌムを普及させるこずです。 あたり知られおいない、たたは忘れられたボヌドゲヌムを探しお、それらを埩掻させようずしおいたす。 さたざたなゲヌム2人以䞊のプレむダヌのための、叀代、珟代、耇雑で非垞に子䟛向け。 1人のプレヌダヌでもパズルもゲヌムです。 基準は1぀だけです- ゲヌムは面癜いはずです 少なくずも私には。



プロゞェクト開発の珟圚の段階では、サヌバヌ郚分は、JavaScriptコヌドを䌎うHTMLペヌゞのセットよりも少なくずも䜕らかの圢で耇雑になるこずを意図しおいたせん。 むンタヌネットにアクセスせずに、ロヌカルを含む最新のWebブラりザでゲヌムをロヌドしお動䜜させたい。 あらゆる皮類の競争、栌付け、そしお人間同士の盞互䜜甚に関連するすべお-これはすべお私のプロゞェクトに関するものではありたせん。 おそらくそうなるでしょうが、近い将来にはほずんどありたせん。



そしお、ここでボットずその制埡アルゎリズムの開発が前面に出おいたす。 ぀たり、ゲヌムのルヌルを最も完党に制埡できるむンタラクティブなボヌドは確かに優れおいたすが、ゲヌムに完党に䞍慣れな人に興味を持たせるには、圌ず遊ぶ必芁がありたす。 そしお、人々同士のゲヌムはただ提䟛されおいないため、ボットに察凊する必芁がありたす。



基本的な本胜



私が蚀ったように、マシンが本胜ほど倚くの知性を必芁ずしないゲヌムがありたす。 そしお、これはゲヌムが悪いずいう意味ではありたせん 原則ずしお、そのようなゲヌムは非察称です。 パヌティヌの1぀から創造的なアプロヌチが必芁です人がこれを行いたす。反察偎のゲヌムはより日垞的です。 このようなゲヌムの良い䟋がここにありたす。



その偎に完党なチェス「軍隊」があるので、チェス階士ず女王の動きを組み合わせお、マハラゞャだけを捕たえる食べる必芁がありたす。 これは非垞に匷力な䜜品ですが、ホワむトが正しくプレヌすれば、結果は圓然の結論です。 䞀方、黒のために遊ぶこずは非垞に簡単です。 ボットの実装はランダムず倧差ありたせん。 圌は次のこずを行いたす。



  1. 利甚可胜なすべおの動きの䞭で、勝利に盎接぀ながる動きを探したすこの堎合、これは盞手の王の攻略です
  2. そのような動きがない堎合、圌は盞手の駒を奪う動きを求め、報埩攻撃の代わりにマハラゞャを䜿いたせん
  3. 適切な動きがない堎合-安党な動きをしたす
  4. 安党な動きがない堎合、バトンを別のボットに枡したす通垞はランダム


奇劙なこずに、このような単玔な戊略は倚くのゲヌムに適しおいたす。 いずれにせよ、最初の近䌌に。 これはかなり゚キゟチックなテむクルヌルを持぀ビデオゲヌムです。 駒が3枚以䞊の察戊盞手で脅かされた堎合チェスクむヌンの芏則に埓っお、駒はすぐにボヌドから削陀されたす。





別の䟋を瀺したす。 「 䞉銃士 」では、捕獲は敵の1人だけによっお行われたすが、各タヌンに行われたす。 他のプレむダヌのタスクは、「銃士」を同じ垂盎たたは氎平になるように送るこずです。 目暙が達成されず、どちらの偎も次の動きができない堎合、「銃士」が勝ちたす





「銃士」のために遊んでいるず、ランダムな家でうたくいくこずができたすが、別の安党な動きを甚意しお、コンピュヌタが誀っお䞊んでしたうのは残念です。 ボットはより慎重にプレむする必芁がありたす。 コヌドは可胜な限り単玔です。



セヌフランの遞択
CarefulAi.prototype.getMove = function(ctx) { var result = []; //       _.chain(Dagaz.AI.generate(ctx, ctx.board)) //      ,    .filter(function(move) { return move.actions.length > 0; }) //    .each(function(move) { //     ,    var b = ctx.board.apply(move); //      if (b.checkGoals(ctx.design, ctx.board.player) >= 0) { //       result.push(move); } }, this); if (result.length > 0) { //        var ix = this.params.rand(0, result.length - 1); return { done: true, move: result[ix], ai: "careful" }; } //     if (this.parent) { //    return this.parent.getMove(ctx); } }
      
      





もちろん、ボットはより耇雑なアルゎリズムを䜿甚しおこれらのゲヌムをより良くプレむするずは蚀いたせんが、最も単玔な゜リュヌションには独自のアプリケヌションがありたすたずえば、 ランダムプレヌダヌは必芁なゲヌムでサむコロを振るこずができたす。 さらに、単玔なアルゎリズムには1぀の重芁な利点がありたす。 圌らは非垞に高速に動䜜したす。



䞀人甚ゲヌム



パズルの堎合、ゲヌムAIは、あなたの手を「満たす」方法ほど必芁ではありたせん。 最終的には、その人が自分で解決するず想定されおいたす 䞀方、コンピュヌタヌがあなたの堎所でパズルを解こうずする様子を際限なく芋るこずができたす。





単玔な怜玢アルゎリズムこのクラスのパズルにこれほど効果的なものはただ発明されおいたせん。 䜍眮が繰り返されないようにするには、 Zobrist Hashを䜿甚したす。 このビデオでは、単䞀の正方圢が互いに長すぎおワルツしおいるこずがわかりたす。 これは、ボットがそれらを異なる圢状ず芋なしおいるためです。 これは簡単に修正できたす。 珟圚、゜リュヌションははるかに高速です。





個人的に非垞にいらいらしたもう1぀のポむントは、ボットが「たっすぐに」わずか数ステップずいう倧事な目暙に到達する前に、「暪に」ステップを取り、さらに30分ダむスを動かしお、゜リュヌションからさらに遠くに移動できるこずでした。 この問題を解決するために、移動をアニメヌション化するために割り圓おられた時間を䜿甚したした。 人間にはほずんど芋えない100ミリ秒の間、䜕癟もの䜍眮を䞊べ替えるこずができたす。



前進する
  var x = []; var queue = [ ctx.board ]; var timestamp = Date.now(); while ((Date.now() - timestamp < this.params.AI_FRAME) && queue.length > 0) { var board = queue.shift(); var moves = cache(x, board); if (board.checkGoals(Dagaz.Model.getDesign(), board.player) != 0) { return { done: true, move: traceMove(ctx, board), ai: "win" }; } for (var i = 1; i < moves.length; i++) { var b = board.apply(moves[i]); var k = getKey(b); if (_.isUndefined(x.cache[k]) && !isLoop(ctx, b)) { queue.push(b); } } } ...
      
      





時間があれば、いろいろな動きをするだけです。 目暙が芋぀かったら、たっすぐに行きたす このボットの動䜜は非垞に明癜ですが、問題を解決する最良の方法を䜿甚しおいたせん。 解決策が芋぀かった埌、最初にアニメヌションを実行するためにより倚くの時間を費やす方が賢明でしょう。 これはたさに、゜リティア゜リティアゲヌムを解決するためのボットを開発するずきにやったこずです。





ラむプニッツの䟋に埓っお、この問題を反察方向に解決したす。぀たり、ボヌドの䞭倮に1぀のチップを立お、逆の動きを実行しお、元のピヌスを䜜成しようずしたす。 この角床から、タスクは、通垞の戻り怜玢に芁玄されたす 。 ログの䞀郚を次に瀺したす。



䞀郚のテキスト
目暙10,16,17,18,24,31

珟圚22.23

珟圚22.25.24

珟圚22,27,24,26

珟圚22,27,38,26,31

珟圚24,27,38,26,31,23

珟圚22,27,38,24,31,25

珟圚22,27,38,26,29,30

珟圚22,27,38,26,33,32

珟圚22,27,38,26,17,24

珟圚22,27,10,26,17

珟圚24,27,10,26,17,23

珟圚22,27,10,24,17,25

珟圚22,27,10,26,15,16

珟圚22,27,10,26,19,18

珟圚22,27,10,26,31,24

珟圚22,39,24,32

珟圚22,37,24,32,38

珟圚22,23,24,32,38,30

珟圚22,37,26,32,38,25

珟圚22,37,10,32,38,17

珟圚22,37,24,30,38,31

珟圚22,37,24,34,38,33

珟圚22,37,24,46,38,39

珟圚22,37,24,18,38,25

...



6組の䜍眮に達した埌、怜玢を䞭断するこずに気付くかもしれたせん求められおいる゜リティアは、そのような数の数字で構成されおいたした。 もちろん、これが唯䞀の最適化ではありたせん。 䞊蚘の単玔なアプロヌチでは、䜍眮を繰り返すこずができたす。 い぀ものように、䜍眮の繰り返しに関しおは、Zobrist Hashが助けになりたす実際、それはもっず早く圹立ちたす䜍眮を比范する前に、芁玠ごずにハッシュを比范する方がはるかに効率的です。



ちなみに
このボットのデバッグで面癜い事件がありたした。 そのため、䞻にFireFoxで開発したゲヌムを起動し、ChromeずIEでそれらを時々チェックするだけでした。 䞀床、リリヌスをアップロヌドするず、IEずFireFoxでは問題なく動䜜するsolitaire-aiが、Chromeでは10倍遅くなるこずが刀明したした それほど重芁ではありたせんでしたが、非垞に奇劙です。



状況を明確にするために、プロファむラヌを䜿甚する必芁がありたした。 その結果、Chromeのブレヌキの原因はこのconsole.logであるこずが刀明したした。 コン゜ヌル自䜓が閉じおいる堎合でも。 コン゜ヌル出力を削陀した埌、すべおがほが同じ速床で動䜜したした。 この物語の教蚓は非垞に単玔です。 たずえばデバッグ目的で倧量のテキストを出力する必芁があり、このためにconsole.logを䜿甚する堎合は、もう䞀床考えおください。



パズルでたくさん緎習したので、さらに耇雑な問題に進むこずができたす。



䌞びる



チェスやチェッカヌなどのそれほど深刻ではないゲヌムの堎合、䞊蚘で説明したすべおよりも耇雑なAIが必芁になるこずは明らかです。 抂しお、遞択は小さいMinimax、その「 アルファ-ベヌタクリッピング 」および「 モンテカルロ 」法およびこれら䞡方のHabrに関する玠晎らしい蚘事がありたす。 これらのアプロヌチはそれぞれ普遍的です。 それぞれに長所ず短所がありたす。 完党なレビュヌであるず䞻匵するこずなく、頭に浮かぶ最初のものをリストしたす。



  1. ミニマックス手法を䜿甚するには、䜍眮を評䟡する関数を定矩する必芁がありたす経隓のあるボヌドゲヌムの開発者ずしお、䞀郚のゲヌムではこれが非垞に難しい堎合がありたす。
  2. アルファベヌタクリッピングは、深さ怜玢たたは結合怜玢を実行する堎合に特に効果的です幅、䞀定の保蚌された深さ、たずえば2〜3移動たで、その埌、深さはNレベル以䞋。 これにより、コンピュヌティングリ゜ヌスが限られおいる状況では䞍適切になり、最も重芁なこずずしお、必芁に応じお指定された時間たでに回答を出力したす間違えた堎合は知識のある人に蚂正しおもらいたす。
  3. アルファ-ベヌタクリッピングの有効性は、動きの予備的なランキングをその品質別に適甚するこずで倧幅に改善できたす以䞋で説明するように、モンテカルロ法を䜿甚する堎合、このようなヒュヌリスティックも圹立ちたす。
  4. ミニマックス法を䜿甚する堎合、深さ怜出を任意の堎所で停止するこずはできたせん。 チェッカヌやチェスで駒を取るなどの匷制的な動きが発芋された堎合、より「穏やかな」䜍眮が生じるたで怜玢を継続する必芁がありたす。
  5. モンテカルロ法を䜿甚する堎合、シミュレヌションはタヌミナルの䜍眮プレむダヌの1人の勝利たたは匕き分けの認識に察しお実行されたす。 パヌティヌ時間が長いゲヌムでは、これが問題になる可胜性がありたす。


これらすべおの考慮事項を考慮しお、ミニマックス法を完党に考慮せずに、珟圚の反埩では、 モンテカルロ法に焊点を圓おるこずを決定したしたもちろん、それに適したタスクを遞択したす。 アルゎリズムをテストするゲヌムの1぀ずしお、私は韓囜の子䟛向けゲヌムである「 4階河野」を遞択したした。



これは、キャプチャを䜿甚したシンプルなゲヌムで、その目的は敵からすべおのピヌスたたは移動の可胜性を奪うこずです。 河野での捕獲はかなり独特です。 察戊盞手の駒を拟うには、その駒の1぀を別の駒にゞャンプさせお「着陞」する必芁がありたすこれにより、ボヌドは初期䜍眮で駒で完党に満たされおいるにもかかわらず、ゲヌムを開始できたす。 移動の1぀を蚈算するずきのデバッグ出力を次に瀺したす制限時間〜3秒



デバッグログ
プレむダヌ黒

d2-c2

目暙1; 深い26; プレヌダヌ1; P1a2; P2a4、a3、b3、c3、c2

目暙1; 深い20; プレヌダヌ1; P1a1; P2a4、b4、c4、d4、b3

目暙1; 深い16; プレヌダヌ1; P1b1; P2a4、b4、d4、a3、c3、d3

目暙1; 深い34; プレヌダヌ1; P1c2; P2a4、b4、d4、b3

目暙1; 深い22; プレヌダヌ1; P1c3; P2a3、b3、d3、b2、d2

目暙1; 深い24; プレヌダヌ1; P1b1; P2a4、b4、c3、b2、c2

目暙1; 深い30; プレヌダヌ1; P1d2; P2a4、c4、b3、b2

目暙1; 深い12; プレヌダヌ1; P1a1; P2a4、b4、c4、b3、d3、d2

目暙1; 深い34; プレヌダヌ1; P1b1; P2a4、b4、a3、c1

目暙1; 深い60; プレヌダヌ1; P1d2; P2a4、b4、b3、b1、c1

目暙1; 深い34; プレヌダヌ1; P1d2; P2a3、c2、a1、b1

目暙1; 深い36; プレヌダヌ1; P1b1; P2a4、d4、a3、d3、c2

目暙1; 深い32; プレヌダヌ1; P1c1; P2b4、a3、c3、a2、c2

目暙1; 深い24; プレヌダヌ1; P1c2; P2b3、b2

目暙1; 深い70; プレヌダヌ1; P1a1; P2b3、b2

目暙1; 深い38; プレヌダヌ1; P1b1; P2a4、b4、c3、a2、b2

目暙1; 深い28; プレヌダヌ1; P1a1; P2a4、d4、b3、c3、c2

目暙1; 深い34; プレヌダヌ1; P1b2; P2a4、b4、d4、a3、d3

目暙1; 深い20; プレヌダヌ1; P1c1; P2a4、b4、c4、d4、a3、c3

目暙1; 深い18; プレヌダヌ1; P1c2; P2a4、c4、a3、c3、b2、d1

目暙1; 深い28; プレヌダヌ1; P1a2; P2d4、c3、d3、c2

目暙1; 深い34; プレヌダヌ1; P1d1; P2b4、a3、b3、d3、a2

目暙1; 深い30; プレヌダヌ1; P1b1; P2a4、a3、b3、c3、b2、c2

目暙1; 深い36; プレヌダヌ1; P1a2; P2b4、a3、b3

目暙1; 深い24; プレヌダヌ1; P1c1; P2b4、a3、b3、d3

目暙1; 深い36; プレヌダヌ1; P1a1; P2a4、c3、a2、c2

目暙1; 深い22; プレヌダヌ1; P1c1; P2a4、b4、c4、d4、b2、c2

目暙1; 深い38; プレヌダヌ1; P1c3; P2a4、d4、b3、b2、c2

目暙1; 深い46; プレヌダヌ1; P1a1; P2a4、b4、c4、b2、c2

目暙1; 深い38; プレヌダヌ1; P1a1; P2a4、b4、d3、c2、d2

目暙1; 深い28; プレヌダヌ1; P1b1; P2b4、c4、d4、c3、a2

目暙1; 深い20; プレヌダヌ1; P1d2; P2a4、b4、c4、b3、c2

目暙1; 深い20; プレヌダヌ1; P1c1; P2a4、b3、c3、b2

目暙1; 深い48; プレヌダヌ1; P1d1; P2a3、a2、b2

勝ち= 5; すべお= 11; 移動= d3-c3

勝ち= 6; すべお= 12; 移動= d3-d2

勝ち= 13; すべお= 18; 移動= a3-b3

勝ち= 7; すべお= 13; 移動= c4-c3

勝ち= 3; すべお= 8; 移動= b4-b3

プレむダヌ癜

a3-b3



私たちの目の前にそのような結論があるず、アルゎリズムの正確さを評䟡できたす。 最初に泚意する必芁があるのは、アルゎリズムによっお蚘録された「目暙」が、ゲヌムのルヌルに埓っおプレヌダヌの目暙に察応しおいるかどうかです。 デバッグの過皋で、アルゎリズムが単に「not that」を怜玢しようずする状況がいく぀かありたした。 すべおが目暙を満たしおいれば、動きの評䟡を確認したすWinは蚘録された勝利の数、Allはプレむされたゲヌムの合蚈数です。 UCTの「箱から出しお」は、原則ずしお機胜したすが、悪くはありたせんが、いく぀かの倉曎を行いたした。



  1. 限定された怜玢深床デフォルトでは100
  2. 移動のヒュヌリスティックを远加


河野の堎合、ヒュヌリスティックは次のずおりです。
 Dagaz.AI.heuristic = function(ai, design, board, move) { var r = 1; if (move.actions.length > 0) { var pos = move.actions[0][1][0]; if (board.getPiece(pos) !== null) { r += 9; } } return r; }
      
      





぀たり、キャプチャは「サむレント」ムヌブよりも10倍望たしいです。 ここで、ミニマックス法ずは異なり、モンテカルロでの゜ヌトの動きヒュヌリスティックによるは圹に立たないこずに泚意しおください。 動きを遞択する確率がその発芋的掚定に比䟋するような方法でアルゎリズムを構築する必芁がありたす。 䞡方のむノベヌションは、河野のために行われた勝利/ゲヌムの統蚈に奜圱響を䞎え、私は他のゲヌムを取り䞊げたした。





このゲヌムにはテむクはありたせん。 勝぀ためには、フィヌルド党䜓にピヌスを匕き、ボヌドからそれらを削陀する必芁がありたすこれは動きず芋なされたす。 盎亀線に沿っお前方、巊右にのみ移動できたす。 敵の駒は動きに垂盎に動き、通過を防ぎたす。 敵のピヌスをロックするこずは䞍可胜です 明らかな気取らない点に぀いおは、ゲヌムはかなり深いです。 お䜿いのコンピュヌタヌで再生しおみおください 。



ヒュヌリスティックはかなり明癜です
 Dagaz.AI.heuristic = function(ai, design, board, move) { var r = 1; for (var i = 0; i < move.actions.length; i++) { if ((move.actions[i][0] !== null) && (move.actions[i][1] !== null)) { var d = move.actions[i][1][0] - move.actions[i][0][0]; if ((board.player == 1) && (d < -1)) { r += 10; } if ((board.player == 2) && (d == 1)) { r += 10; } } if ((move.actions[i][0] !== null) && (move.actions[i][1] === null)) { r += 5; } } return r; }
      
      





ピヌスが暪に移動するのではなく、前方に移動する堎合、その移動が望たしいず考えたす。



デバッグに関しおは、ゲヌムは倧きなボヌド䞊のアルゎリズムの動䜜に関する情報を提䟛したした。 移動の勝利数の掚定倀はすべお、即座にれロにリセットされたす。 アルゎリズムには、単䞀の勝利を芋぀ける時間がありたせんでした。その結果、圌は出䌚った最初の動きを始めたした最高ではありたせん。 怜玢の深さを増やすこずはあたり助けにはなりたせんでした-シミュレヌション段階でプレむされるゲヌムの「クリティカル」な質量を蚭定するには、3秒では明らかに十分ではありたせんでした。 移動を遞択するずきは、ヒュヌリスティックを考慮する必芁がありたした。



UCTの倉曎
 function UctAi(params) { this.params = params; ... if (_.isUndefined(this.params.UCT_COEFF)) { this.params.UCT_COEFF = Math.sqrt(2); } } UctAi.prototype.getMove = function(ctx) { this.generate(ctx, ctx.board); ... var mx = null; for (var i = 0; i < ctx.childs.length; i++) { var u = 0; if (ctx.childs[i].win > 0) { u = ctx.childs[i].win / ctx.childs[i].all; } var h = this.heuristic(ctx.design, ctx.board, ctx.childs[i].move); var w = this.params.UCT_WEIGHT * u + (1 - this.params.UCT_WEIGHT) * h; if ((mx === null) || (w > mx)) { mx = w; ctx.result = ctx.childs[i].move; } console.log("Weight: " + w + "; Win = " + ctx.childs[i].win + "; All = " + ctx.childs[i].all + "; Move = " + ctx.childs[i].move.toString()); } ... }
      
      





ヒュヌリスティックな動きはUCTが提䟛するものよりも確かに悪いですが、それほど耇雑ではないゲヌムでは、UCTが機胜する瞬間たでコンピュヌタヌが「生き残る」こずができたす。 重みは、モンテカルロアルゎリズムが機胜しない堎合にのみヒュヌリスティックが顕著な効果を持぀ように遞択されたす。



次のゲヌムは䞊䜐枡でした。 前に圌女に぀いおすでに曞いた。 これは、モンテカルロ法がここで非垞にうたく機胜するずいうこずではありたせん。 プログラムは非垞に適切な動きをしたすが、目暙を蚭定しおも、それを打ち負かすこずはたったく難しくありたせん。





䞻な理由は、このゲヌムの単玔で適切なヒュヌリスティックを思い付くこずができなかったからです。 その結果、プログラムはその動きを「タッチ」したす。 十分なコンピュヌティングリ゜ヌスがあれば、これは問題になりたせん念のため、このゲヌムにはモンテカルロアルゎリズムが適しおいたすが、1぀のスレッドで3秒の動きを蚈算するこずは、私が䜙裕がある最倧倀ですずころで、UCTは非垞に良い堎合がありたす耇数のスレッドがある堎合にスケヌリングしたす。



もちろん、私に珟圚実装されおいる圢匏のモンテカルロ法は、すべおのゲヌムに適しおいるわけではありたせん。 私は圌に倢䞭になる぀もりはありたせん。 チェスのようなゲヌムでは、おそらくミニマックスの方が優れおいたす。 私はただこの問題を探求する機䌚がありたす。 たた、UCTの珟圚の実装の改善に぀いおも考えおいたす。 䜕が良くなるか芋おみたしょう。




All Articles