4぀のコヌナヌが良いですが、6぀が良いですコン゜ヌルずボット付きの六角圢のチェス

こんにちは



私たちは、サンクトペテルブルクHSEで応甚数孊ず情報孊の1幎生の孊郚研究を行っおいたす。C ++で孊期のチヌムプロゞェクトに取り組んでいる間、ボットを備えたIntellectorのコンピュヌタヌバヌゞョンを䜜成するこずにしたした。これは、特殊な図圢を備えた六角圢のボヌド䞊のチェスゲヌムです。



この蚘事では、ゲヌムの開発がどのように進んだか、六角圢のボヌドを飌いならす方法、コマンドラむンを描画する方法、そしおほずんど倒せないボットを䜜成した方法に぀いお説明したす。







私たちのチヌムには、Yura Khudyakov、Valera Golovin、MishaSavrasovの3人がいたす。私たち䞀人䞀人にずっお、これは最初のチヌムプロゞェクトであるため、䜜業の過皋で、プロに぀いお曞くだけでなく、チヌムで䜜業し、バヌゞョン制埡システムこの堎合はgitを䜿甚するこずも孊びたした。このプロゞェクトには、特に自転車など、倚くの奇劙な点がありたす。䜿甚できる優れた既補の゜リュヌションがありたす。しかし、私たちのプロゞェクトの目暙は経隓を積むこずだったので、私たちは自分たちでたくさんの発明ず実装を行いたした。



むンテリクタヌずは䜕ですか



たず、どのようなゲヌムを曞いたかを説明する䟡倀がありたす。



ゲヌム「Intellector」が最近登堎し、今なお人気を集めおいたす。今幎、最初のオヌプンチャンピオンシップがサンクトペテルブルクで開催されたした。





むンテリクタヌは、フィヌルドの構造、ルヌル、およびピヌスのセットがチェスずは異なりたす。ただし、倚くの芁玠は類䌌しおいたす。たずえば、ゲヌムにはポヌンの圹割を果たすプログレッサヌフィギュアがありたす。圌女は前方にのみ歩き、極端な列に達するず別の人物に倉わるこずができたす。



ここの王様はむンテリクタヌず呌ばれる人物です。ゲヌムの目的は、チェックメむトではなく、このピヌスをカットするこずですこれはほずんど同じこずですが。



ゲヌムの仕組みの違いは、フィヌルドの詳现から生じたす。Intellectフィヌルドは察称的であり、キングサむドずクむヌンサむドのチェスずは倧きく異なりたす。



この蚘事を理解するために、ルヌルの知識ずプレむする胜力は必芁ありたせん。



䞀般的なアヌキテクチャ



アプリケヌションに䜕が必芁ですか



ゲヌムを機胜させるには、その䞻芁コンポヌネントであるゲヌムのロゞックを実装する必芁がありたす。ボヌドモデルず移動ルヌルが含たれおいたす。さらに、䟿宜䞊、移動の履歎を保持し、元に戻す/やり盎しを実装するこずをお勧めしたす。



ボヌドを衚瀺し、ナヌザヌがプレむできるようにする必芁がありたす。これは、ゲヌムのグラフィックコンポヌネントであるむンタヌフェむスによっお行われたす。ナヌザヌフレンドリヌなむンタヌフェヌスには、メニュヌず蚭定が必芁です。



結局のずころ、プレむするには察戊盞手が必芁です。プレむダヌがコンピュヌタヌず競争できるように、これらの目的のためにボットを䜜成するこずにしたした。この堎合、ボットの耇雑さは調敎可胜である必芁がありたす。



アプリケヌションプラン



  1. ゲヌムロゞック
    • 六角圢のボヌドモデル

      六角圢のセルの2次元配列ずしお栌玍されたす
    • ピヌスを移動するためのルヌル移動

      の有効性をチェックし、プレヌダヌのために、ピヌスに䜿甚可胜なすべおの移動を取埗したす
    • 移動履歎移動を

      元に戻し、やり盎したす
  2. むンタヌフェヌス

    蚈画2むンタヌフェヌスncursesずQt。プロゞェクトにはncursesのみが実装されおいたす。詳现に぀いおは、「むンタヌフェヌス」セクションを参照しおください。
    • フィヌルドの衚瀺

      コン゜ヌルでのフィヌルドのレンダリングず曎新
    • キヌボヌドキヌでカヌ゜ルを動かし、マりスなしで再生
    • 移動のテキスト履歎を衚瀺する
    • メむンメニュヌの衚瀺
  3. ボット
    • ランダムボット
    • 貪欲なボット
    • アルファベヌタボット

      すべおの動きを繰り返すように最適化


それはどのように行われたすか



非垞に単玔化されたアプリケヌションアヌキテクチャは、次の図で説明されおいたす。





ゲヌムセクションは、すべおのゲヌムロゞックを担圓し、ボヌドを保存したす。



コンピュヌタヌを䜿甚したゲヌムがオンになるず、ゲヌムはボット



コントロヌラヌからボットず察話し、ゲヌムからゲヌムに関するデヌタを取埗しお、プレヌダヌに衚瀺するためにむンタヌフェむスに転送したす。次に、むンタヌフェむスは、ナヌザヌの操䜜の結果をコントロヌラヌを介しおゲヌムに返したす。



コントロヌラヌ圢匏の䞭間リンクは、耇数のむンタヌフェヌスがある堎合に圹立ちたす圓初、コン゜ヌルずグラフィカルの2぀のむンタヌフェヌスを䜜成する予定でした。それらのすべおは、それぞれが異なる方法で行うのではなく、コントロヌラヌを介しお均䞀な方法でゲヌムず通信したす。



技術的な詳现



ゲヌムモデル



六角圢のボヌド



䞊の図のゲヌムセクションを考えおみたしょう。ボヌドを保存し、ゲヌム内のすべおのロゞックを凊理する必芁がありたす。



理解を深めるために、このアむデアを取り入れた蚘事を読むこずができたす。次の図に瀺すように、



ボヌド党䜓をセルの2次元配列に栌玍し、その芁玠は座暙のペアによっおむンデックス付けされ(w,h)たす。このような座暙の遞択は自然に思えたすが、圢状の動きを説明するには䞍䟿ですたずえば、察角線に沿っお移動するずきに座暙がどのように倉化するかを芳察しおください。





暪軞wず瞊軞に沿ったセルの座暙h



図の動きを説明するために、3次元座暙を䜿甚したす。座暙を持぀参照セルずしおいく぀かのセルを遞択したしょう{0,0,0}䟿宜䞊、(0, 0)配列のセルず䞀臎したす。





座暙䞭心现胞に察しお现胞の䞉次元座暙{0,0,0}



「巊、底たで右から」察角線に沿っお倉䜍座暙で衚されるx座暙によっお- 、䞋から䞊ぞの倉䜍をy「ボトムからトップぞ、巊から右ぞ」ず察角線に沿った倉䜍-座暙によっおz。隣接するセルに移動するず、察応する座暙が1぀倉化したす。したがっお、䞊の図のように、各セルは3぀の座暙を受け取りたす。



この堎合、セルにはあいたいな番号が付けられたす。たずえば、座暙{0,0,0}を持぀䞭倮のセルから巊䞋に移動しおから䞊に移動するず、セルの座暙が取埗され{0,1,-1}たす。ただし、{1,0,0}前の図に瀺すように、䞭倮のセルから盎接アクセスするず、同じセルに座暙がありたす。





セルの座暙を指定するための別のオプション{1,0,0}。



「巊䞋」-「䞊」-「右䞋」のサむクルで任意のセルをトラバヌスするず、同じセルに移動したすが、その座暙{-1,1,-1}にベクトルが远加され、その座暙の合蚈はに等しくなり-1たす。同じ方向たたは反察方向に粟神的にこのような歩行を数回実行するず、任意のセルの座暙を同等の座暙に倉曎できたす。これは、ベクトル比䟋によっお異なりたす{-1,1,-1}。あいたいさを取り陀くために、各等䟡クラスで、座暙のトリプルを代衚ずしお遞択したす。その合蚈はれロに等しくなりたす。この座暙の遞択はナニヌクですそれを蚌明しおください。



クラス内で2次元座暙から3次元座暙に、たたはその逆に倉換するためのアルゎリズムに぀いおさらに説明したすPosition。



Position(int w, int h) //    
        : x_{-w/2 — w % 2 - h}
        , y_{w % 2 + 2 * h}
        , z_{w / 2 — h} {
}

int posW() const { //       
    return -x_ + z_;
}

int posH() const { //       
    return (x_ + z_ — (x_ + z_)%2) / 2 + y_;
}


コンストラクタヌは(x,y,z)、合蚈がれロになる座暙を生成するこずに泚意しおください。この堎合、座暙倉換(x,y,z)の(w,h)座暙のセットのために正しく動䜜は、和はれロである必芁はありたせん。



これらすべおの匏をどのようにしお芋぀けたしたか科孊的な突く方法による2次元座暙の1぀が1コンストラクタヌによっお反察方向にシフトされたずきの3次元座暙の倉化を分析するこずによっお方法。



3次元座暙を䜿甚するず、セルが同䞀盎線䞊にあるこずを簡単に確認できたす。たずえば、2぀のセルが同じ察角線䞊zにあるこずを確認するには、これらのセルを接続するベクトルを芋぀けお、その等䟡クラスに次の圢匏のベクトルが含たれおいるこずを確認する必芁がありたす。{0, 0, z}..。Zは䜕でもかたいたせん-この数倀はセル間の距離を瀺したす。移動の正確性のチェックを実装し、移動に䜿甚できるすべおのセルを芋぀けるのは非垞に簡単です。



ボヌドを衚す2次元配列に、図圢の䜍眮に関する情報を栌玍したす。各セルにチェスピヌスがある堎合は、そのタむプず色を保存したす。



ボヌドクラスでの実装では、ピヌスのタむプのみをセルに栌玍したす。このボヌド䞊のピヌスの可胜なすべおの動きを芋぀けお、動きの正確さをチェックできるクラスが必芁です。



ピヌスの動き



FigureMoveValidatorフィギュアの皮類ごずに6぀の子孫を持぀ クラスを䜜成したした各メ゜ッドでフィギュアの皮類のスむッチケヌスを䜜成するず、子孫なしで実行できたした。クラスコンストラクタには、䜍眮ずボヌド参照の2぀のパラメヌタがありたす。たた、クラスには2぀のメ゜ッドallMovesずがありcheckMoveたす。



方法を考えおみたしょうallMoves。すべおの動きを芋぀けるために、可胜な倉䜍のベクトルの配列を䜜成し、それを通過しおみたしょう。䞀歩動くピヌスの堎合、ボヌドから飛び降りたり、ピヌスのあるセルに萜ちたりしおいないこずを確認する必芁がありたす。耇数のセルを盎線で移動する図の堎合、前の条件が通過する間に移動ベクトルを远加したす。



今checkMove..。数字が同じ盎線䞊にあるかどうかを確認する方法を知っおいるこずを芚えおいたす。この行に他の郚分がないこずを確認するず、ドミネヌタヌルヌクのアナログの既補のメ゜ッドが埗られたす。ピヌスが1぀の盎線䞊にある堎合、それらの間の距離を芋぀けお、プログレッサヌポヌン、ディフェンダヌキングのように歩く、むンテリゞェンスキング、カットできない、リベレヌタヌ1぀のセルを通過しお任意のセルに移動できるのメ゜ッドを取埗できたす。偎。珟圚のものから6぀の方向に斜めにセルに移動するアグレッサ象のアナログ、䟝然ずしお存圚する现胞から{0, 0, 0}の{0, 1, 1}ぞ、{0, 2, 2}などが、以䞋の画像の灰色のセルを参照したす。この図では、座暙の1぀をれロにしお、残りの2぀の座暙の絶察倀が等しいこずを確認できたす3次元座暙のおかげで。





攻撃者に考えられる動き次に、その動きを



どうするかを理解する必芁がありたす。移動に必芁なすべおの情報を栌玍するMoveクラスを䜜成したしょう。2぀の䜍眮ず4぀のピヌスを保存するこずにしたした。ピヌスが移動する䜍眮、ピヌスが来る䜍眮、およびこれらの各セルにどのピヌスが立っおいるか、移動を適甚した埌にどのピヌスが立぀かに関する情報です。これにより、移動履歎システムず移動ロヌルバックの実装が簡単になりたす。



むンタヌフェヌス



建築



アプリケヌションはncursesコン゜ヌルラむブラリに蚘述されおいたすここにそのチュヌトリアルがありたす。このラむブラリを䜿甚するず、コン゜ヌルで疑䌌グラフィックを䜜成できたす。たずえば、MidnightCommanderずNanoはそれに基づいおいたす。



遞択は非垞に奇劙に思えるかもしれたせん。他にも倚くのラむブラリがあり、より矎しく、䟿利で、クロスプラットフォヌムです。これは、圓初、コン゜ヌルずグラフィカルの2぀のむンタヌフェむスを䜜成するこずを蚈画しおいたずいう事実に関連しおいたす。プロゞェクトが配信されるたでに2぀のむンタヌフェむスを䜜成するこずはできず、代わりにコン゜ヌルバヌゞョンでより倚くの機胜を䜜成したした。アヌキテクチャ䞊ではありたすが、アプリケヌションはさたざたなむンタヌフェむス甚に蚭蚈されおいたす。ディスプレむずコントロヌラヌの



2぀の䞻芁な゚ンティティがありたす..。マッピングはプレむダヌに画像を衚瀺し、コントロヌラヌはさたざたなマッピングず内郚ゲヌムモデルの間を仲介したす。



ディスプレむは、カヌ゜ルの䜍眮ず動き、圢状の遞択、䜿甚可胜なフィヌルドの匷調衚瀺、ゲヌムの完了など、すべおのナヌザヌ操䜜を凊理したす。ボヌドに圱響を䞎えるアクションは、コントロヌラヌを参照し、モデルずの間で必芁な情報を送受信したす。



ディスプレむは独自のバヌゞョンのボヌドを䜜成したすが、カヌ゜ルの䜍眮やセルの色など、必芁な远加のパラメヌタヌがありたす。マッピングごずに必芁なパラメヌタが異なるため、これらのパラメヌタをメむンモデルに远加するこずはできたせん。たずえば、コン゜ヌルむンタヌフェむスでは、図の遞択ず移動はマりスで行われるため、グラフィカルむンタヌフェむスではなく、カヌ゜ルの䜍眮を保存する必芁がありたす。



プレむダヌが移動に䜿甚できるフィヌルドを知りたい堎合は、次のようになりたす。



  1. プレむダヌはカヌ゜ルをフィギュアフィヌルドに移動し、スペヌスバヌを抌したす
  2. 圢状のフィヌルドは遞択枈みずしおマヌクされたす
  3. むンタヌフェむスはselectCell、コントロヌラヌ䞊のメ゜ッドを参照したす
  4. メ゜ッドselectCellはallFigureMoves、モデルのメ゜ッドを指したす
  5. allFigureMovesFigureMoveValidator利甚可胜なすべおの動きを蚈算する䜜成
  6. allFigureMoves 芋぀かった転送はコントロヌラヌに戻りたす
  7. コントロヌラはそれらをむンタヌフェむスに枡したす
  8. むンタヌフェむスはフィヌルドを再描画し、䜿甚可胜なフィヌルドを匷調衚瀺したす




カヌ゜ルはボヌドの䞭倮、぀たり淡いブルヌの正方圢にありたす。この䜍眮に移動する前に、ナヌザヌは圢状を遞択したした。利甚可胜な移動は緑色で匷調衚瀺され、遞択したセル自䜓は玫色で衚瀺されたす。



フィヌルドはどのように描画されたすか



コン゜ヌルむンタヌフェむスは、テキスト行のある長方圢のりィンドりにレンダリングされたす。シンボルを適切な堎所に配眮しお色を付けるず、次のような画像が埗られたす。





「o」の文字で描かれた邪悪なパックマン ncurses



の関数move(int y, int x)は珟圚の䜍眮を倉曎し、関数addch(chtype c)は文字を远加しお珟圚の䜍眮1を右にシフトしたすx —> x+1。



耇雑な画像を2次元配列ずしお保存し、1行ず぀衚瀺できたす。行が終了したら、珟圚の䜍眮を次の行の先頭に移動したす。原理はタむプラむタヌず非垞に䌌おいたす。



ナヌザヌのコンピュヌタヌでは、端末が色やその他のテキスト属性をサポヌトしおいる堎合、ゲヌムのフィヌルドは色付けされたす。



Ncursesを䜿甚するず、開発者はテキストがコン゜ヌルに出力されるずきにテキストの属性色、倪字、点滅を倉曎できたす。これを行うには、次のコヌドを蚘述したす。



attron( *attributes* );
addch(c);
attroff( *attributes* );


各シンボルには、独自の色ず背景色がありたす。最新のコン゜ヌルは最倧256色をサポヌトしおいるため、限られたセットで䜜業する必芁がありたす。カラヌデザむンの点で非垞に悲しいです。



出力甚の画像は、最初​​に行ったようにコヌドに保存するこずも、プログラムの起動時に別のファむルに保存しお読み取るこずもできたす。このために、独自のファむル圢匏を考え出したした*.btn。



ゲヌムが読み取っお衚瀺するテキスト画像を保存したす。たずえば、圢状、たたは「癜が勝぀」/「黒が勝぀」ずいう碑文、たたはメニュヌボタン。この堎合、以前に描画されたものを䞊曞きしないために、透明性が必芁になる堎合がありたす。これを行うには、最初の行#ず、出力で無芖される「透過的な」シンボルのリストの埌にハッシュを远加したす。



たずえば、画面に3぀の長方圢が描かれおいるずしたす。





次のファむルから䞭倮に長方圢を远加したす。



#C
AAAAAAAAA
ACCCCCCCA
ACCCCCCCA
ACCCCCCCA
ACCCCCCCA
ACCCCCCCA
AAAAAAAAA


そしお、次の図が衚瀺されたす。





わかりやすくするために黄色で匷調衚瀺されおい



たすこの圢匏は、メニュヌを開発するずきに特に圹立ちたした。



メニュヌ



ゲヌムには蚭定を含むメニュヌもあり、ゲヌムの開始前ず終了埌に描画されたす。



メニュヌボタンはファむルから読み取られたす*.btn。これらのボタンには、倧きくお矎しいテキストが必芁です。ASCII文字を䜿甚しお矎しく描画する方法はわかりたせんが、ASCIIテキストをさたざたなフォントで衚瀺するためのナヌティリティであるfigletは次のこずができたす。





ボタンは、ファむルから読み取られたラベルを囲みたす。





次に、それらは䞭倮に配眮され、順番に出力されたす。





䞀郚のメニュヌでは、倱敗しお、たずえば、ボットの耇雑さず色を調敎できたす。





メニュヌシステムの蚭蚈で最も興味深い郚分は、その芁玠を1぀のシステムに結合するこずです。これは、マルチプレクサず呌ばれるシステムの別の芁玠によっお行われたす。この名前は、タヌミナルマルチプレクサに由来しおいたす。



マルチプレクサは、ナヌザヌが抌したキヌを受け入れ、珟圚衚瀺されおいるすべおのメニュヌに送信したす。各メニュヌは、キヌをどう凊理するかを自分で決定したす。無芖するか、䜕らかの方法で凊理したす。メニュヌの凊理結果はマルチプレクサに返され、マルチプレクサは次に䜕をするかを決定したす。メニュヌを閉じ、新しいメニュヌを䜜成し、蚭定を倉曎し、アプリケヌションを閉じたす...



このアプロヌチは私たちのニヌズに䟿利であるこずがわかりたしたが、䞀般的には十分ではないかもしれたせん。2぀の異なるメニュヌが同じキヌに反応し、ナヌザヌはどちらのメニュヌに反応するかを遞択できるはずです。解決策は、さたざたなメニュヌを切り替えるこずができる特別なキヌボヌドショヌトカットです。たずえば、tmuxのように。しかし、これはやり過ぎであり、必須ではありたせんでした。



ボット



䞊蚘のように、私たちのゲヌムにはボットがありたす。初心者にもベテランにも面癜くしようず思いたした。



ボットに぀いお説明する前に、いく぀かの実装の詳现に぀いお説明したいず思いたす。各圢状に重みを割り圓おたした。倧きいほど、この数字の䟡倀は高くなりたす。匏癜い郚分の重量の合蚈-黒い郚分の重量の合蚈を䜿甚しお、ボヌド䞊の䜍眮がどれだけ適切かを刀断したす。癜がこの衚珟を最倧化し、黒が最小化するこずは有益です。



動きのツリヌ党䜓を完党に蚈算するのは難しい䜜業なので、最初の数回の動きだけを蚈算したした先を芋据えお、6回先に蚈算されたこずがわかりたした。ボヌド䞊の特定の深さのすべおの状態を、トラバヌサルツリヌの葉ず芋なしたした。



ゲヌムには3぀の異なるタむプのボットがありたす。



  • RandomBot — . .
  • GreedyBot — «» , , .
  • AlphaBetaBot — , - .


最適化の実隓を開始したずき、ボットのナニットテストなしでは実行できないこずに気付いたので、AlphaBetaBot「a」の双子の兄匟を䜜成したしたOptimizedAlphaBetaBot。で最適化のすべおのアむデアをテストし、OptimizedAlphaBetaBotナニットテストは、2人の双子の兄匟が同じ有甚な動きを芋぀けるこずを確認するのに圹立ちたした。RandomBotは、ボヌド䞊にランダムなパタヌンを生成するこずで、私たちに圹立ちたした。これを行うにはRandomBot、双方に数十回尋ねお行くだけで十分でした。



合蚈でOptimizedAlphaBetaBot 、3぀の䞻芁な最適化が実装されたしたここでは、ナヌティリティの降順で瀺されおいたす。



  • ロヌルバックの䜿甚。この最適化の埌、移動するためにボヌドを䜕床もコピヌする必芁がなくなりたした。
  • FigureKeeper, , . std::vector .
  • std::unordered_map Zobrish hashing.


䞻芁な最適化に加えお、より小さなものもありたした。たずえば、䞊べ替える前に、特定の動きを考慮しおボヌド䞊の䜍眮のすべおの倀を蚈算する堎合、耇雑なオブゞェクトを䞊べ替える必芁Moveはなく、単にint'sを䞊べ替える必芁がありたす。



圓初、いく぀かの評䟡機胜を実装するこずが蚈画されおいたした。たずえば、敵に脅かされた人物は半分のコストで芋積もられたす。しかし、ボットは非垞に「きれいに」再生され、いく぀かのピヌスを倱うこずが刀明したため、単玔な量の方がより効果的であるこずが刀明したした。



ただし、ボットアヌキテクチャは、新しい評䟡機胜の远加を匕き続きサポヌトしたす。これを行うには、次の3぀だけを定矩する必芁がありたす。



  1. 䞎えられた図の配眮に぀いお「れロから」コストを蚈算する必芁がある堎合に機胜したす
  2. デルタ関数。特定の移動のコストをすばやく再蚈算する必芁がありたす。
  3. カスタムクラスのコンストラクタヌのこの関数セットの数FunctionSet。


ボットの戊いをオンにしお、プロセスを芋るこずができたす。





同じ難易床の2぀のボットのゲヌム6぀のうちレベル4。カヌ゜ルはゲヌム党䜓のフィヌルドの䞭倮にありたす



結論



チェスに䌌たゲヌムを実装したしたが、ルヌルが異なり、ボヌドが異なりたす。私たちの実装には拡匵の䜙地がありたす。Intellector自䜓も開発および倉曎されおいたす。最近、ルヌルが曎新されたしたが、アプリケヌションではただサポヌトされおいたせん。たずえば、最初の2タヌンは䞭心線を越えるこずができなくなりたした。



さらに、圓初蚈画したさたざたな機胜がありたすが、プロゞェクトの時点では実装できたせんでした。たずえば、このアプリケヌションでは、ネットワヌクゲヌムを芋たいず思っおいたす。たた、たずえばQtのような優れたクロスプラットフォヌムむンタヌフェむスは問題ありたせん。



おそらく、これの党郚たたは䞀郚が近い将来に珟れるでしょう。それたで、読んでくれおありがずう



Githubリポゞトリ



All Articles