公理-孊䜍を䞊げおください

叀い灰色のロバEeyoreは森の草に芆われたアザミの角に䞀人で立ち、足を倧きく離し、頭を片偎にぶら䞋げ、重倧なこずを考えたした。

A.ミルン「くたのプヌさんずすべおすべお」

-ロバを芋たすか 譊官に尋ねたす。 -そこに小さな灰色のロバがいたす...蚘事2908。䟡栌は32コペックです。 圌には玠晎らしい未来がありたす。
「ロバはこれを行う」ず譊官は同意する。 -圌らは時々非垞に玠晎らしい未来を持っおいたす。

ヘンリヌ・アルトフ「ロバず公理」


ボヌドゲヌムの開発で最も難しい郚分は䜕ですか 明らかに、ボヌド䞊でピヌスを動かすアニメヌションではありたせん。 合理的で興味深いゲヌムルヌルを考案するのは困難です。 ゲヌムのバランスを確保するこずは非垞に困難です。 コンピュヌタヌ開発に携わっおいる堎合、高品質のAIを実装するのはめったに困難です囲Goや将giなどのゲヌムでは、この問題はこれたで解決されおいたせん。 そしお、たずえ機胜するAIを実装できたずしおも、その䜜業の品質を評䟡し、いく぀かの可胜なオプションから最適なものを遞択するために、非垞に倚くの䜜業を行う必芁がありたす。

これらすべおの問題に察する゜リュヌションを倧幅に簡玠化できるツヌルに぀いおお話したいず思いたす。 Axiom Development Kitは 、 Zillions of Gamesを改善する方法ずしお開発者によっお考案されたした。 特に、AI ZoGが非垞に貧匱な領域の発䜜に関連するゲヌムGoなどの実装に焊点を圓おおいたす。 さらに、AxiomはZoG開発者の機胜を倧幅に拡匵し、埓来のZRFルヌル蚘述蚀語のフレヌムワヌクでは実際には実珟されない倚くの機䌚を提䟛したす。 これにより、Axiomは、ZoGがコンピュヌタヌにむンストヌルたたは賌入されたこずがない堎合でも、完党に独立しお動䜜できたす。 しかし、たず最初に...

画像で


ZoGには倚くの欠点があるこずをすでに曞きたした。 幞いなこずに、開発者はそれらのいく぀かに察凊するメカニズムを提䟛しおいたす。 拡匵モゞュヌル゚ンゞンは、芖芚化を陀くゲヌムのあらゆる偎面を制埡する動的にロヌドされるラむブラリDLLです。 ここでは、そのような拡匵の䟋を芋るこずができたす。

独自の拡匵機胜を自分で開発するには、非垞に時間がかかる堎合がありたす。 ゚ンゞンを接続するず、通垞のZoG AIが無効になるため、AIを開発する必芁がありたすほずんどの堎合、C ++で。 Axiomは、AIアルゎリズムなど、開発者にずっお難しいものを実装するプログラム可胜な゚ンゞンであり、ゲヌムロゞックに集䞭する機胜を提䟛したす。

Royal Game of Urを実装しおみたしょう。 動䜜するには、最小限のZRFファむルが必芁です。

゚ンゞン接続
(version "2.0") (game (title "Ur") (engine "../Axiom/Ur/axiom.dll") (option "animate captures" false) (option "animate drops" false) (option "show moves list" false) (option "pass turn" forced) (option "highlight goals" false) (option "prevent flipping" true) (option "recycle captures" true) (drop-sound "Audio/Dice_cup.wav") (move-sound "Audio/Clack.wav") (capture-sound "") (players Black White ?Dice) (turn-order White ?Dice ?Dice ?Dice ?Dice Black ?Dice ?Dice ?Dice ?Dice) (board (image "Images\Ur\board.bmp") (grid (start-rectangle -503 -13 -442 79) (dimensions ("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q" (67 0)) ; files ("5/4/3/2/1" (0 66)) ; ranks ) ) ) (board-setup (?Dice (wdice q4) (bdice q3 q2) (lock q1) ) (Black (init i5 j5 k5 l5 m5 n5 o5) ) (White (init i1 j1 k1 l1 m1 n1 o1) ) ) (piece (name lock) (image ?Dice "Images\Ur\invisible.bmp" Black "Images\Ur\invisible.bmp" White "Images\Ur\invisible.bmp") ) (piece (name init) (image Black "Images\Ur\binit.bmp" White "Images\Ur\winit.bmp") ) (piece (name prom) (image Black "Images\Ur\bprom.bmp" White "Images\Ur\wprom.bmp") ) (piece (name wdice) (image ?Dice "Images\Ur\wdice.bmp") ) (piece (name bdice) (image ?Dice "Images\Ur\bdice.bmp") ) ; The following dummy piece is required in order to placate the Zillions engine. ; It appears as though Zillions must find at least one "moves" keyword somewhere ; in the zrf in order for it to be happy and thus allow "moves" to work correctly. (piece (name Dummy) (dummy) (moves (from))) ) 


ここにプレむダヌの説明、動きのシヌケンス、ピヌスがありたすが、ピヌスが行くルヌルの説明はありたせん。 たた、ボヌド䞊の方向、ゲヌムゟヌン、ゲヌムを終了する条件、およびゲヌムルヌルに関連する他のすべおの定矩はありたせん。 これらはすべお公理スクリプトに含たれたす。 悲しい点は、゚ンゞンずのZoGむンタヌフェヌスは、ZRFファむルに含たれる情報の転送を提䟛しないこずです。 ぀たり、これらの説明はすべおAxiomスクリプトで耇補する必芁がありたす。

幞いなこずに、Axiom Development Kitには、このプロセスを自動化するナヌティリティが付属しおいたす。 ZRF Converterは非垞に機嫌が悪いです。 ZRFファむル内の䜕かたずえば、マクロ内のボヌドの説明が気に入らなかった堎合、倉換プロセスが䞭断され、頭を痛める䞍思議な蚺断が行われたす。 すべおがうたくいった堎合、出力に次の説明が衚瀺されたす。

Ur.4th
 {board {position} a5 {position} b5 {position} c5 {position} d5 {position} e5 {position} f5 {position} g5 {position} h5 {position} i5 {position} j5 {position} k5 {position} l5 {position} m5 {position} n5 {position} o5 {position} p5 {position} q5 {position} a4 {position} b4 {position} c4 {position} d4 {position} e4 {position} f4 {position} g4 {position} h4 {position} i4 {position} j4 {position} k4 {position} l4 {position} m4 {position} n4 {position} o4 {position} p4 {position} q4 {position} a3 {position} b3 {position} c3 {position} d3 {position} e3 {position} f3 {position} g3 {position} h3 {position} i3 {position} j3 {position} k3 {position} l3 {position} m3 {position} n3 {position} o3 {position} p3 {position} q3 {position} a2 {position} b2 {position} c2 {position} d2 {position} e2 {position} f2 {position} g2 {position} h2 {position} i2 {position} j2 {position} k2 {position} l2 {position} m2 {position} n2 {position} o2 {position} p2 {position} q2 {position} a1 {position} b1 {position} c1 {position} d1 {position} e1 {position} f1 {position} g1 {position} h1 {position} i1 {position} j1 {position} k1 {position} l1 {position} m1 {position} n1 {position} o1 {position} p1 {position} q1 board} {players {player} Black {player} White {player} ?Dice {random} players} {pieces {piece} lock {piece} init {piece} prom {piece} wdice {piece} bdice {piece} Dummy pieces} {turn-order {repeat} {turn} White {turn} ?Dice {turn} ?Dice {turn} ?Dice {turn} ?Dice {turn} Black {turn} ?Dice {turn} ?Dice {turn} ?Dice {turn} ?Dice turn-order} {board-setup {setup} ?Dice wdice q4 {setup} ?Dice bdice q3 {setup} ?Dice bdice q2 {setup} ?Dice lock q1 {setup} Black init i5 {setup} Black init j5 {setup} Black init k5 {setup} Black init l5 {setup} Black init m5 {setup} Black init n5 {setup} Black init o5 {setup} White init i1 {setup} White init j1 {setup} White init k1 {setup} White init l1 {setup} White init m1 {setup} White init n1 {setup} White init o1 board-setup} 


ここで最初の驚きが埅っおいたす。 Axiomでは、ボヌドをよりコンパクトに蚘述できたすが、重倧な制限がありたす。 グリッドデザむンでは、「暙準」セル名を持぀長方圢のボヌドのみを蚘述できたすさらに、ボヌドの説明ではグリッドを1぀だけ䜿甚できたす。 より耇雑な圢状3次元などのボヌドを蚘述する必芁がある堎合は、ZRFコンバヌタヌず同じ方法で各䜍眮を明瀺的に蚘述する必芁がありたす。 この堎合、すべおの制限が尊重されるためZRF実装ず比范しお、ボヌドの列ず行の名前を倉曎する必芁がありたした、よりコンパクトなレコヌドを䜿甚したす。

 {board 5 17 {grid} board} 

次に、数字が移動できる方向を決定する必芁がありたす。 ChessやCheckersなどのゲヌムでは、座暙の増分に関しお方向を定矩するコンパクトな衚蚘法を䜿甚できたす。

 {directions -1 0 {direction} North 1 0 {direction} South 0 1 {direction} East 0 -1 {direction} West -1 1 {direction} Northeast 1 1 {direction} Southeast -1 -1 {direction} Northwest 1 -1 {direction} Southwest directions} 

悲しいかな、私たちの堎合、この方法は適切ではありたせん。 りルのゲヌムでは、ボヌド䞊のチップの動きの軌跡は非垞に奇劙なので、䜍眮間の関係を明確に決定する必芁がありたす。

道順
 {directions ( Anext ) {link} Anext i1 l2 {link} Anext j1 l2 {link} Anext k1 l2 {link} Anext l1 l2 {link} Anext m1 l2 {link} Anext n1 l2 {link} Anext o1 l2 {link} Anext l2 k2 {link} Anext k2 j2 {link} Anext j2 i2 {link} Anext i2 i3 {link} Anext i3 j3 {link} Anext j3 k3 {link} Anext k3 l3 {link} Anext l3 m3 {link} Anext m3 n3 {link} Anext n3 o3 {link} Anext o3 o2 {link} Anext o2 p2 {link} Anext p2 p3 {link} Anext p3 p4 {link} Anext p4 o4 {link} Anext o4 o3 ( Bnext ) {link} Bnext i5 l4 {link} Bnext j5 l4 {link} Bnext k5 l4 {link} Bnext l5 l4 {link} Bnext m5 l4 {link} Bnext n5 l4 {link} Bnext o5 l4 {link} Bnext l4 k4 {link} Bnext k4 j4 {link} Bnext j4 i4 {link} Bnext i4 i3 {link} Bnext i3 j3 {link} Bnext j3 k3 {link} Bnext k3 l3 {link} Bnext l3 m3 {link} Bnext m3 n3 {link} Bnext n3 o3 {link} Bnext o3 o4 {link} Bnext o4 p4 {link} Bnext p4 p3 {link} Bnext p3 p2 {link} Bnext p2 o2 {link} Bnext o2 o3 ( Cnext ) {link} Cnext p3 p4 {link} Cnext p4 o4 {link} Cnext o4 o3 {link} Cnext o3 n3 {link} Cnext n3 m3 {link} Cnext m3 l3 {link} Cnext l3 k3 {link} Cnext k3 j3 {link} Cnext j3 i3 {link} Cnext i3 h3 ( Dnext ) {link} Dnext p3 p2 {link} Dnext p2 o2 {link} Dnext o2 o3 {link} Dnext o3 n3 {link} Dnext n3 m3 {link} Dnext m3 l3 {link} Dnext l3 k3 {link} Dnext k3 j3 {link} Dnext j3 i3 {link} Dnext i3 h3 directions} 


黒ず癜のチップの動きは異なるため、癜の堎合はAnext 、黒の堎合はBnextの方向を決定する必芁がありたした。 さらに、倉換フィヌルドを通過したチップに぀いおは、 CnextおよびDnextの方向を決定する必芁がありたす 。 これが行われない堎合、フォヌクがo3フィヌルド䞊に圢成され、すべおのチップが小さなブロック内で円圢に回転し、利甚可胜な最初のルヌトを遞択したす。

 {symmetries Black {symmetry} Anext Bnext Black {symmetry} Cnext Dnext symmetries} 

この蚭蚈により、「察称性」を定矩できたす。 良い䟋は、チェスのポヌンの動きです。 ポヌンは垞に前方に移動したすが、癜の堎合はボヌドを䞊に移動し、黒の堎合は反察方向に移動したす。 より耇雑な察称圢匏がありたす。 たずえば、チェスの4蟺の倉圢では、色に応じお「前方」ぞの移動は、4぀の「基本ポむント」のいずれかの方向に発生する可胜性がありたす。 「察称性」を定矩したら 、図の色に泚意を払わずに、垞に同じ方向たずえばAnext を䜿甚できたす。 黒の堎合、自動的に察称 Bnext に倉換されたす。

芁塞


フォヌトずの知り合いは早かったが、非垞に長い間気たぐれのたただった。 フォヌトを初めお芋たのは、BC-ShekずMikroshのずきでした。 私の友人にはVector 06Cがあり 、すべおの芪の共同の努力により、耳からのみ成功したした。 Vektorには、ゲヌムの入ったカセットが時々賌入され、「䞍明」が時々発芋されたした。 そのような原因䞍明の䞭で、フォヌトの実装が芋぀かりたした。 友人ずスタックで十分に遊んだので、友人ず私は「aha」ず蚀っお、数字䜓系の基瀎をれロに蚭定したしたFortにはずおも楜しい機䌚がありたす。 砊は圓然これに耐えるこずができず、しばらく忘れおいたした。

その埌、すでに研究所で、フォヌトは私の泚意の衚面に繰り返し浮䞊したしたが、圌らはそれに真剣に察凊するこずができたせんでした。 実際、Fortのマむクロコントロヌラヌプログラミングやその他の䟿利なアプリケヌションに出䌚う機䌚はありたせんでした。 そしお今、Axiom開発者のおかげで、私にはそのような機䌚がありたす 実際には、Forthずいう単語が理由でForthScriptに衚瀺されたす。 実際、Axiom自䜓ずForthScriptの䞀郚の䞡方がFortに実装されおおり、 axiom.dllにはそれらを䜿甚できるむンタヌプリタヌがありたす。 必芁に応じお、 axiom.4thおよびCORE.4THで実装の詳现を確認し、おそらく修正するこずができたす。

したがっお、すべおのゲヌムロゞックをプログラミングするにはFortが必芁です。 しかし、どこから開発を始めたすか 手始めに、ボヌド䞊のピヌスの簡単な動きを実珟するこずは玠晎らしいこずです。 各図は、独自の軌道に沿っお1、2、3、たたは4個のセルを移動できる必芁がありたす「骚」にランダムなポむントを投げお気を散らすたで。

フィギュアの動き
 : common-move ( 'dir n -- ) SWAP BEGIN DUP EXECUTE verify SWAP 1- DUP 0= IF DROP TRUE ELSE SWAP FALSE ENDIF UNTIL empty? IF from here move add-move ENDIF ; : i-move-1 ( -- ) ['] Anext 1 common-move ; : i-move-2 ( -- ) ['] Anext 2 common-move ; : i-move-3 ( -- ) ['] Anext 3 common-move ; : i-move-4 ( -- ) ['] Anext 4 common-move ; : p-move-1 ( -- ) ['] Cnext 1 common-move ; : p-move-2 ( -- ) ['] Cnext 2 common-move ; : p-move-3 ( -- ) ['] Cnext 3 common-move ; : p-move-4 ( -- ) ['] Cnext 4 common-move ; {moves i-moves {move} i-move-1 {move} i-move-2 {move} i-move-3 {move} i-move-4 moves} {moves p-moves {move} p-move-1 {move} p-move-2 {move} p-move-3 {move} p-move-4 moves} {pieces {piece} init {moves} i-moves {piece} prom {moves} p-moves pieces} 


実行時にZRF-kuを実行するず、数字を移動できるようになりたす。 どのように機胜したすか common-moveの実装を芋おみたしょう。 名前の盎埌にあるコメントフォヌトスタむルは、スタック䞊の2぀のパラメヌタヌコンパむル枈みの方向遷移コマンドず移動ステップ数を取るこずを瀺しおいたす。 実装自䜓は2぀の郚分で構成されおいたす。 たず、指定された回数のサむクルで方向転換が実行され、次にタヌゲットフィヌルドが空であるこずを確認した埌、移動チップの移動を圢成する䞀連のAxiomコマンドが実行されたす。 最も重芁なこずは、このバランスをずるすべおの行為䞭に、スタックを砎壊しないこずです

実行可胜な各コマンドの説明は、Axiom Development KitにバンドルされおいるForthScriptおよびAxiomのマニュアルに蚘茉されおいたすが、このコヌドずZRFを䜿甚しお蚘述できるものずのいく぀かの重芁な違いに泚目しおください。


このバヌゞョンでしばらく遊んだ埌、小さなブロックに到達したチップが円を描くようになっおいるこずがわかりたす。 チップがこの「茪廻の茪」から抜け出すには、裏返しにする必芁がありたす裏返したチップに぀いおは、フィニッシュに至る方向CnextおよびDnextが䞎えられたす。 Urのゲヌムでチップを回すのは難しいこずを思い出させおください。 チップは裏返され、倉換フィヌルド䞊に立぀のではなく、通過したす。 さらに、チップは最埌たで進むこずができるので、フィニッシュに達したボヌドからチップを取り陀くこずを忘れないでください

チップの反転
 VARIABLE isPromouted : common-move ( 'dir n -- ) FALSE isPromouted ! SWAP BEGIN current-player White = IF here p2 ELSE here p4 ENDIF = IF TRUE isPromouted ! ENDIF DUP EXECUTE verify SWAP 1- DUP 0= IF DROP TRUE ELSE SWAP FALSE ENDIF UNTIL empty? IF from here move here h3 = IF capture ENDIF isPromouted @ IF current-piece-type 1+ change-type ENDIF add-move ENDIF ; 


ここにフォヌトの倉数に関するいく぀かの蚀葉がありたす。 VARIABLEキヌワヌドを䜿甚しおisPromouted倉数を定矩したす。 倉数が定矩された埌、コヌド内で倉数が蚀及されるず、この倉数のアドレスがスタックにプッシュされたす。 指定されたアドレスにある倀を取埗するには、 @コマンド、  倉数の倀を䞊曞きしたす。

Axiomの耇雑さは、圢状の皮類の操䜜によっお衚されたす。 実際のずころ、図の定矩は、それらの動きを制埡するコヌドの埌にありたすそれらが䜿甚されおいるため。 このため、コヌドで圢状のタむプの名前を䜿甚するこずはできたせんこの時点ではただ定矩されおいないため。 原則ずしお、この䞍快な状況から抜け出すこずができたす。 たずえば、コヌドでは、チップをフリップするために、移動を実行するピヌスのタむプを単玔にむンクリメントしたす。

ゲヌムプレむの重芁な郚分は、プレむダヌの動きをスキップする機胜です。 プレヌダヌは、可胜であれば移動を完了し、それ以倖の堎合は移動をスキップする必芁がありたす。 わざずこれを気にしない堎合、ゲヌムはプレむダヌのいずれかによる最初の移動䞍可胜性で匕き分けで自動的に完了したす。 たた、盞手のタヌンをスキップするこずにより、「アりトレット」ぞの移動の埌にプレむダヌの2番目の移動を実装するこずは論理的です。 それをやっおみたしょう

進捗をスキップ
 : is-rosette? ( -- ? ) here i2 = here i4 = OR here l3 = OR here o2 = OR here o4 = OR ; : common-move ( 'dir n -- ) q5 enemy-at? NOT IF FALSE isPromouted ! SWAP BEGIN current-player White = IF here p2 ELSE here p4 ENDIF = IF TRUE isPromouted ! ENDIF DUP EXECUTE verify SWAP 1- DUP 0= IF DROP TRUE ELSE SWAP FALSE ENDIF UNTIL empty? IF from here move here h3 = IF capture ENDIF isPromouted @ IF current-piece-type 1+ change-type ENDIF is-rosette? IF q1 piece-type-at q5 create-piece-type-at ELSE q5 capture-at ENDIF add-move ENDIF ENDIF ; : pass-move ( -- ) q5 capture-at Pass add-move ; {moves i-moves {move} i-move-1 {move-type} normal-type {move} i-move-2 {move-type} normal-type {move} i-move-3 {move-type} normal-type {move} i-move-4 {move-type} normal-type {move} pass-move {move-type} pass-type moves} {moves p-moves {move} p-move-1 {move-type} normal-type {move} p-move-2 {move-type} normal-type {move} p-move-3 {move-type} normal-type {move} p-move-4 {move-type} normal-type {move} pass-move {move-type} pass-type moves} {move-priorities {move-priority} normal-type {move-priority} pass-type move-priorities} 


is-rosetteのキャッチヌな定矩を最初にキャッチしたしたか 。 残念ながら、Axiomでは、ZRFずは異なり、ゲヌムゟヌンを定矩する方法はありたせん。 すべおのフィヌルドを個別にチェックする必芁がありたす。

スキップの実装は、ZRFで䜿甚されるアプロヌチずも異なりたす。 「パスタヌン」オプションの蚭定は、Axiomによっお無芖されたす。 代わりに、 Passコマンドでスキップを明瀺的に構成する必芁がありたす 。 これは、ZSGムヌブ蚘録蚘法機胜゚ンゞンからZoGにムヌブを転送するために䜿甚のより完党な䜿甚の䞀䟋です。 別のそのような䟋は、ZRFに実装されおいない、郚分的な移動を実行するずきにドロップコマンドを䜿甚する機胜です。

ご泚意
独自の拡匵モゞュヌル ゚ンゞン を開発する堎合、ZSG衚蚘法を理解するこずは非垞に重芁です。 ZoGで移動を実行する胜力は、ZSG衚蚘で蚘述できるかどうかによっお完党に決定されたす。 ZoGはこの圢匏を文曞化したせんが、Axiomの文曞にはそれを説明するセクションがありたす付録B。 このセクションに粟通しおいるず、ZSG衚蚘の機胜を明確にするために、開発者が長時間の実隓を行う必芁がなくなりたす。

他の移動の可胜性がない堎合にのみパスが機胜するためには、優先順䜍を䜿甚する必芁がありたす。 優先床の䜎い移動は、優先床の高い移動の可胜性がない堎合にのみ実行できたす。 残念ながら、「パスタヌン」オプションをforceに蚭定する堎合、AxiomスタむルのスキップはZoGの動䜜ず機胜的に完党に同等ではありたせん。 ZRF実装では、スキップは自動的に実行されたす。Axiomの堎合、ボタンをクリックする必芁がありたす。



これは玛らわしいこずです。

「アりトレット」ぞの移動埌にスキップ移動を実装するために、目に芋えない図圢ロックが䜍眮q5に配眮されたすが、これはゲヌムでは䜿甚されたせん。 common-moveの最初に、このフィヌルドに敵のフィギュアが存圚するかどうかのチェックが行われたす。 フィヌルドが敵に占領されおいる堎合、移動するこずはできたせん。

さお、さいころを振る方法を孊びたしょう。

骚投げ
 {players {player} White {player} Black {player} ?Dice {random} players} {turn-order {turn} White {turn} ?Dice {of-type} clear-type {turn} ?Dice {turn} ?Dice {turn} ?Dice {turn} Black {turn} ?Dice {of-type} clear-type {turn} ?Dice {turn} ?Dice {turn} ?Dice turn-order} : drop-dices ( -- ) q2 here = q3 here = OR q4 here = OR empty? AND IF drop add-move ENDIF ; : count-dices ( -- n ) q2 piece-at piece-value q3 piece-at piece-value + q4 piece-at piece-value + DUP 0= IF DROP 4 ENDIF ; : clear-dices ( -- ) q1 here = verify q2 not-empty-at? q3 not-empty-at? q4 not-empty-at? AND AND IF drop q2 capture-at q3 capture-at q4 capture-at add-move ENDIF ; : i-move ( -- ) ['] Anext count-dices common-move ; : p-move ( -- ) ['] Cnext count-dices common-move ; {moves p-moves {move} p-move {move-type} normal-type {move} pass-move {move-type} pass-type moves} {moves drops {move} drop-dices {move-type} normal-type {move} pass-move {move-type} pass-type moves} {moves clears {move} clear-dices {move-type} clear-type moves} {pieces {piece} lock {moves} clears {piece} init {moves} i-moves {piece} prom {moves} p-moves {piece} wdice {drops} drops 1 {value} {piece} bdice {drops} drops 0 {value} pieces} 


「ボヌン」 drop-dices のスロヌは基本的に実行されたす。 タヌゲットフィヌルドがサむコロを投げるためのものであるこずを確認し、 ドロップコマンドでシェむプを配眮し、 add-moveコマンドで移動を終了したす。 クリアダむスはもう少し耇雑です。 ZoGでは、ボヌドからピヌスを取り陀くだけで構成されるムヌブを圢成する方法はありたせん。 クリヌニングプロセスを、ゲヌムで䜿甚されおいないq1フィヌルドに䞍可芖の数字をリセットするこずに関連付けたす。 ボヌドから「骚」を取り陀くこずは、この動きの副䜜甚です。 ドロップされたポむントをカりントし count-dices 、この倀をcommon-moveに枡したす。

ゲヌムを終了する条件を決定するために、ボヌドを離れたチップを数える必芁がありたす。 完了チェック自䜓は、オヌバヌラむドされた単語OnIsGameOverを呌び出すこずにより、Axiomによっお実行されたす。 ゲヌムの開始時に初期アクション疑䌌乱数ゞェネレヌタヌの初期化などを実行するには、 OnNewGameをオヌバヌラむドする必芁がありたす。

終了条件
 {board 5 17 {grid} {variable} WhitePieces {variable} BlackPieces board} : WhitePieces++ WhitePieces ++ ; : BlackPieces++ BlackPieces ++ ; : common-move ( 'dir n -- ) q5 enemy-at? NOT IF FALSE isPromouted ! SWAP BEGIN current-player White = IF here p2 ELSE here p4 ENDIF = IF TRUE isPromouted ! ENDIF DUP EXECUTE verify SWAP 1- DUP 0= IF DROP TRUE ELSE SWAP FALSE ENDIF UNTIL empty? IF from here move here h3 = IF current-player White = IF COMPILE WhitePieces++ ELSE COMPILE BlackPieces++ ENDIF capture ENDIF isPromouted @ IF current-piece-type 1+ change-type ENDIF is-rosette? IF q1 piece-type-at q5 create-piece-type-at ELSE q5 capture-at ENDIF add-move ENDIF ENDIF ; : OnNewGame ( -- ) RANDOMIZE ; : OnIsGameOver ( -- gameResult ) repetition-reset #UnknownScore current-player White = IF BlackPieces @ 7 - 0= IF DROP #LossScore ENDIF ENDIF current-player Black = IF WhitePieces @ 7 - 0= IF DROP #LossScore ENDIF ENDIF ; 


ご泚意
オンボヌド倉数の䜿甚に぀いおは、Axiomドキュメントのセクション3.9.4「ボヌド倉数の曎新」で説明しおいたす。

完党なゲヌムを取埗するには、フィギュアの戊いず特別なフィヌルドの凊理を実装する必芁がありたす。 これらの詳现は基本的に新しいものを䜕も茉せおいないので、これらの詳现で蚘事を散らかしたせん。 興味のある方は、 GitHubで「Royal Game of Ur」の完党な実装を確認できたす 。

基本的な本胜


ZoGの䞻なハむラむトは、その汎甚性です。 ZRFでは、ルヌルを宣蚀するだけで、新しいゲヌムを䜜成たたは既存のゲヌムを蚘述できたす。 はい、それは特殊なプログラムよりも著しく悪いですが、ほずんどすべおのゲヌムのプロトタむプをすばやく䜜成するこのような機䌚は䟡倀がありたす ZoG甚に開発されたアプリケヌションの数は 、それ自䜓を物語っおいたす。

公理も普遍的です。 ZoGの䞍愉快な制限の倚くを取り陀き、ZoGが察応しおいないボヌドゲヌムを蚘述するこずができたす。 ブヌルフラグを操䜜する代わりに本栌的な算術挔算を䜿甚する1぀の可胜性は、この補品を質的に高いレベルに匕き䞊げたすが、これはAxiomの䞻な利点ではありたせん ZoGのプレむは良くも悪くもありたすが、私たちにずっおAIはブラックボックスです。 圌のゲヌムの品質に圱響を䞎えるこずはできたせん Axiomは、最適な動きを遞択するためのアルゎリズムの開発に参加する機䌚を提䟛したすただし、必須ではありたせん。

AI Axiomの䜜業を劚げる最も明癜な可胜性は、各䜍眮を評䟡するための重み関数の遞択です。 私たちに必芁なのは、 OnEvaluateを再定矩するこずだけです。 チップの最初から最埌たでの党䜓的なプロモヌションを基瀎ずしお、非垞に単玔な評䟡関数を䜜成しおみたしょう。 開始䜍眮でのチップの配眮を重み0で評䟡し、フルパスを通過したチップは、たずえば100などのより倧きな数で評䟡されたす。前進。 もちろん、敵に぀いおは、反察の笊号で取埗した同じ掚定倀を䜿甚したす。 敵の䜍眮が良いほど、䜍眮が悪くなりたす。

簡易評䟡機胜
 VARIABLE whiteScored VARIABLE blackScored : Score ( value piece-type player pos -- score ) DUP not-empty-at? IF DUP player-at White = IF whiteScored -- ELSE blackScored -- ENDIF DUP ROT SWAP player-at = ROT ROT piece-type-at = AND NOT IF DROP 0 ENDIF ELSE DROP DROP DROP DROP 0 ENDIF ; : OnEvaluate ( -- score ) 7 whiteScored ! 7 blackScored ! 0 1 White i1 Score 0 1 White j1 Score + 0 1 White k1 Score + 0 1 White l1 Score + 0 1 White m1 Score + 0 1 White n1 Score + 0 1 White o1 Score + 0 1 Black i5 Score + 0 1 Black j5 Score + 0 1 Black k5 Score + 0 1 Black l5 Score + 0 1 Black m5 Score + 0 1 Black n5 Score + 0 1 Black o5 Score + 1 1 White l2 Score + -1 1 Black l4 Score + 2 1 White k2 Score + -2 1 Black k4 Score + 3 1 White j2 Score + -3 1 Black j4 Score + 4 1 White i2 Score + -4 1 Black i4 Score + 5 1 White i3 Score + -5 1 Black i3 Score + 6 1 White j3 Score + -6 1 Black j3 Score + 7 1 White k3 Score + -7 1 Black k3 Score + 8 1 White l3 Score + -8 1 Black l3 Score + 9 1 White m3 Score + -9 1 Black m3 Score + 10 1 White n3 Score + -10 1 Black n3 Score + 11 1 White o3 Score + -11 1 Black o3 Score + 12 1 White o2 Score + -12 1 Black o4 Score + 13 1 White p2 Score + -13 1 Black p4 Score + 14 2 White p3 Score + -14 2 Black p3 Score + 15 2 White p4 Score + -15 2 Black p2 Score + 16 2 White o4 Score + -16 2 Black o2 Score + 17 2 White o3 Score + -17 2 Black o3 Score + 18 2 White n3 Score + -18 2 Black n3 Score + 19 2 White m3 Score + -19 2 Black m3 Score + 20 2 White l3 Score + -20 2 Black l3 Score + 21 2 White k3 Score + -21 2 Black k3 Score + 22 2 White j3 Score + -22 2 Black j3 Score + 23 2 White i3 Score + -23 2 Black i3 Score + 1 1 White c2 Score + 1 1 White c3 Score + 1 1 White c4 Score + -1 1 Black d2 Score + -1 1 Black d3 Score + -1 1 Black d4 Score + 3 1 White a2 Score + 3 1 White a3 Score + 3 1 White a4 Score + -3 1 Black b2 Score + -3 1 Black b3 Score + -3 1 Black b4 Score + 7 1 White f2 Score + 7 1 White f3 Score + 7 1 White f4 Score + -7 1 Black f2 Score + -7 1 Black f3 Score + -7 1 Black f4 Score + 10 1 White g2 Score + 10 1 White g3 Score + 10 1 White g4 Score + -10 1 Black g2 Score + -10 1 Black g3 Score + -10 1 Black g4 Score + 11 1 White e2 Score + 11 1 White e3 Score + 11 1 White e4 Score + -11 1 Black e2 Score + -11 1 Black e3 Score + -11 1 Black e4 Score + 17 2 White e2 Score + 17 2 White e3 Score + 17 2 White e4 Score + -17 2 Black e2 Score + -17 2 Black e3 Score + -17 2 Black e4 Score + 18 2 White g2 Score + 18 2 White g3 Score + 18 2 White g4 Score + -18 2 Black g2 Score + -18 2 Black g3 Score + -18 2 Black g4 Score + 21 2 White f2 Score + 21 2 White f3 Score + 21 2 White f4 Score + -21 2 Black f2 Score + -21 2 Black f3 Score + -21 2 Black f4 Score + whiteScored @ 100 * + blackScored @ 100 * - current-player Black = IF NEGATE ENDIF ; 


, Axiom . , . , ( ), , , :

 : Mobility ( -- mobilityScore ) move-count \ Number of moves available to us. current-player TRUE 0 $GenerateMoves \ Generate moves for opponent move-count \ Number of moves available to opponent. - \ #friendlyMoves - #unfriendlyMoves $DeallocateMoves \ Deallocate the opponent's move list ; : OnEvaluate ( -- score ) Mobility current-player material-balance 3 * + ; 

move-count , material-balance , , {value} ( , «»).

, , ? , , , , . , « », « »! Axiom :

 VARIABLE BestScore \ Keep track of the best score found so far by our search engine. VARIABLE Nodes \ The number of possibilities explored by our search engine. VARIABLE Eated VARIABLE Rosettes : enemy-value-at ( pos -- value ) DUP empty-at? IF DROP 0 ELSE 0 SWAP player-at current-player <> IF DROP 1 ENDIF ENDIF ; : friend-value-at ( pos -- value ) DUP empty-at? IF DROP 0 ELSE 1 SWAP player-at current-player <> IF DROP 0 ENDIF ENDIF ; : Make_enemy_p ( pos -- ) <BUILDS , DOES> @ enemy-value-at ; : Make_friend_p ( pos -- ) <BUILDS , DOES> @ enemy-value-at ; i1 Make_enemy_p e0 j1 Make_enemy_p e1 k1 Make_enemy_p e2 l1 Make_enemy_p e3 m1 Make_enemy_p e4 n1 Make_enemy_p e5 o1 Make_enemy_p e6 i5 Make_enemy_p e7 j5 Make_enemy_p e8 k5 Make_enemy_p e9 l5 Make_enemy_p e10 m5 Make_enemy_p e11 n5 Make_enemy_p e12 o5 Make_enemy_p e13 i2 Make_friend_p r0 i4 Make_friend_p r1 l3 Make_friend_p r2 o2 Make_friend_p r3 o4 Make_friend_p r4 : CountEated ( -- count ) e0 e1 + e2 + e3 + e4 + e5 + e6 + e7 + e8 + e9 + e10 + e11 + e12 + e13 + ; : CountRosettes ( -- count ) r0 r1 + r2 + r3 + r4 + ; : Score ( -- score ) Eated @ CountEated < IF 10 ELSE 0 ENDIF Rosettes @ CountRosettes < IF 5 ELSE 0 ENDIF + ; : Custom-Engine ( -- ) -1000 BestScore ! \ Keep track of the best score. 0 Nodes ! \ Count the number of possibilities explored. CountEated Eated ! CountRosettes Rosettes ! ( Notes: 1 - We do not need to invoke $GenerateMoves since they have already been generated for the current player { since ZoG has called DLL_GenerateMoves prior to calling DLL_Search}. 2 - ZoG does not invoke the search engine if there are no moves, so we can safely assume. that at least one move exists. Thus we can use BEGIN..UNTIL instead of BEGIN...WHILE..REPEAT for iterating moves. ) $FirstMove \ Obtain the address of the first move. BEGIN $CloneBoard \ Create a temporary copy of the current board. DUP $MoveString CurrentMove! \ Inform ZoG of the current move being examined. DUP .moveCFA EXECUTE \ Apply the move to the board by executing its code. Score \ Calculate the score for the new board. BestScore @ OVER < \ Have we found a better score? IF DUP BestScore ! \ Save the improved score. Score! \ Inform ZoG of the improved score. DUP $MoveString BestMove! ELSE DROP \ We didn't find a better move, drop the score. ENDIF $DeallocateBoard \ Done with the revised board. Nodes ++ \ Count one more node explored. Nodes @ Nodes! \ Inform ZoG of the node count. $Yield \ Allow ZoG to dispatch Windows messages. $NextMove \ Advance to the next move. DUP NOT \ No more moves? UNTIL DROP ; {players {player} White {search-engine} Custom-Engine {player} Black {search-engine} Custom-Engine {player} ?Dice {random} players} 


. , , . , , OnEvaluate , . . «», , , .

, Axiom {first} {random} . axiom.4th:

 : $RandomMoveEngine $FirstMove 0 $movesList @ CELLSIZE + @ 1- $RAND-WITHIN BEGIN DUP 0> WHILE SWAP @ SWAP $Yield 1- REPEAT DROP ( move ) $MoveString DUP CurrentMove! BestMove! 1 Nodes! 0 Score! 0 Depth! ; : {random} ['] $RandomMoveEngine $CompileEngine ; : $FirstMoveEngine $FirstMove $MoveString DUP CurrentMove! BestMove! $Yield ; : {first} ['] $FirstMoveEngine $CompileEngine ; 


先ほど蚀ったように、オヌプン゜ヌスの䞀郚でも゜ヌスコヌドは玠晎らしいです

嘘、露骚な嘘ず統蚈


さお、新しいゲヌムを䜜成し、ZoGを䜿甚しおプレむできたす。さたざたな移動遞択アルゎリズムを備えたいく぀かのゲヌムオプションを実装したしたが、どれがより良いかをどのように刀断するのですか もちろん、ダヌスの「専門家」を集めお、それぞれのオプションで100回プレむするように䟝頌するこずができたす。私の友人が蚀ったように、「それは䜕幎も続くこずができたす。」もっず良い方法がありたす

Axiomは、テストプロセスを自動化するAutoPlayナヌティリティを提䟛したす。自動化のパスをたどる最初のこずは、ゲヌムオプションを䜜成するこずです。

 (variant (title "Ur [random]")) (variant (title "Ur [simple evaluation]")) (variant (title "Ur [aggressive]")) 

これらの行をZRFファむルの最埌に远加した埌、ZRF Converterを再床起動しお、ゲヌムの4番目のバヌゞョンを取埗したす。これらのファむルを倉曎しお、プログラムで䜿甚される戊略に圱響を䞎える必芁がありたす。ここでは、たずえば、最も単玔なオプションの1぀に芋えたす。

 LOAD Ur.4th ( Load the base Ur game ) {players {player} White {random} {player} Black {random} {player} ?Dice {random} players} 

芋やすいように、説明の個々のセクションを再定矩しお、すべおの共有コヌドをロヌドされたスクリプトファむルに取り蟌むこずができたす。

オプションが䜜成された埌、あるオプションのゲヌムモヌドで別のオプションに察しおゲヌムを開始できたす。これが自動再生の䞻な利点ですプレむダヌがさたざたな戊略を䜿甚しおプレむするオプションを䜜成する必芁はありたせん。次のコマンドを入力するだけで十分です。

 AutoPlay Ur-[random] Ur-[random] 100 

. ( AutoPlay ) . . , ZoG! , ZSG-. , , , , , ( , «»):

 Final results: Player 1 "Ur-[random]", wins = 52. Player 2 "Ur-[random]", wins = 48. Draws = 0 100 game(s) played 

ZSG- , , ZoG . , ( , ).

ZSG-, , , , , / . , , «» :

 #!/usr/bin/perl -w my @S = (0, 0, 0, 0, 0, 0); my $ix = 0; my $T; while (<>) { if (/results/) { my $d = $S[0] - $S[1]; print "$T, $d, $S[3], $S[2], $S[4], $S[5]\n"; @S = (0, 0, 0, 0, 0, 0); $ix = 0; } else { if (/^(\d+)\.\s+[^?].*$/) { $T = $1; if (/x h3/) { $S[$ix]++; } if (/Pass|^(\d+)\.\s+x\s+q5\s*$/) { $S[$ix + 2]++; } if (/Black init [ijklmno]5/) { $S[4]++; } if (/White init [ijklmno]1/) { $S[5]++; } $ix++; if ($ix > 1) { $ix = 0; } } } } 


これで、開発したオプションのゲヌム品質を比范するために必芁なすべおが揃いたした。次の3぀のオプションを怜蚎したす。


ランダムvsランダム
( , , 150 ):



, ( — ):



«» :



, , , :

 Final results: Player 1 "Ur-[random]", wins = 52. Player 2 "Ur-[random]", wins = 48. Draws = 0 100 game(s) played 


ランダムvsシンプル
:



:

 Final results: Player 1 "Ur-[random]", wins = 50. Player 2 "Ur-[simple-evaluation]", wins = 50. Draws = 0 100 game(s) played 


単玔察ランダム
:



«» :



 Final results: Player 1 "Ur-[simple-evaluation]", wins = 87. Player 2 "Ur-[random]", wins = 13. Draws = 0 100 game(s) played 


ランダムvsアグレッシブ
:



random ( ):



, , «» :



«» , !

 Final results: Player 1 "Ur-[random]", wins = 25. Player 2 "Ur-[aggressive]", wins = 75. Draws = 0 100 game(s) played 


アグレッシブvsランダム
:



«» «» !



, «» , :



 Final results: Player 1 "Ur-[aggressive]", wins = 90. Player 2 "Ur-[random]", wins = 10. Draws = 0 100 game(s) played 


シンプルvsアグレッシブ
, . , simple :



!



 Final results: Player 1 "Ur-[simple-evaluation]", wins = 73. Player 2 "Ur-[aggressive]", wins = 27. Draws = 0 100 game(s) played 


アグレッシブvsシンプル
, agressive :



«» , , «»:



 Final results: Player 1 "Ur-[aggressive]", wins = 64. Player 2 "Ur-[simple-evaluation]", wins = 36. Draws = 0 100 game(s) played 


ずころで、次のすばらしい行に泚意しおください。

 Draws = 0 

, Axiom «3-Time Repetition Draw!». . , ZoG . (3-4 ) . « », , , ZoG ( Axiom) ! AutoPlay, . , , ZoG, .


 !


もちろん、たった1぀の蚘事では、Axiom Development Kitのような耇雑で倚面的な補品に぀いおすべおを䌝えるこずは䞍可胜です。開発者によっお発衚された機胜を参照しおください。

公理゚ンゞンの機胜
  • Contains a universal game engine designed to play a large variety of games. The search engine is not optimized for any particular class of games.
  • Allows (actually requires) the game programmer to specify a custom game AI. This is one of the main benefits of Axiom. Some 'built-in' AI helpers are provided. For example, one helper is simply the difference between the number of available moves for each player, another takes into consideration material advantage. The list is expected to grow over time.
  • «Minimax with Alpha-Beta pruning» search algorithm.
  • Iterative deepening with transposition table.
  • Zobrist hashing
  • Limited move reordering based on 'best move from previous iteration' stored in the transposition table.
  • Full width searching.
  • Support for 'partial' and 'pass' moves.
  • Supports 'teams'.
  • Time management.
  • Supports additional user-supplied custom engines.
  • Programmer controlled quiescence (currently experimental)

, , ZoG. Axiom (Ring Buffer) «» « ». , ( ZoG, , ), Axiom , .

. , . , ZoG 60 , Axiom, .

Source: https://habr.com/ru/post/J226235/


All Articles