ZoGを使いこなす(パート5:Mana Gathering)

今日は、Zillions of Gamesでゲームを開発するために使用されるZRF言語の機能に関する一連の記事を完成させています。 私は意図的に単純なものから複雑なものに移行したため、今日のゲーム(実装の観点から)は以前のすべてのゲームよりも難しいと考えるのが論理的です。 本当にそうです。 実際、ZRFはユニバーサルプログラミング言語に起因するものではありません。 チェスに似たゲームを記述することを目的としています。 ゲームが「チェスのように」なるほど、その説明はより明白になります(もちろん、 キャスリング通路の取り込みなどのトリッキーな動きのルールの説明に注意を払わない限り)。 このようなゲームの説明は非常に多くなる可能性がありますが(この場合、 に書いたPreZRFが役立ちます)、内容は非常に簡単です。



まったく似ていない(またはまったく似ていない)チェスで何かをしなければならないとき、すべてが変わります。 拡張機能なしで純粋なZRFを使用する場合、 Game of LifeMine Finderなどのアプリケーションを作成することは深刻な課題です。 今日は、そのような開発がどのような困難につながる可能性があるかをお見せします。



今回は、先ほど述べたバトルvsチェスのマナギャザリングミニゲームに触発されました。 プレーヤーには1つ以上のチェスの駒が用意されており、これを使ってフォークを置き、フィールドからランダムに配置された「クリスタル」を取り除きます。







ZRFを使用して同様のミニゲームを実装しようとすると、どのような困難に直面するかを考えてみましょう。 最初の困難は、戦闘中の数字の計算です。これは、「フォーク」の存在を判断するために必要です。 既に述べたように、ZRFでのあらゆる種類の計算はきついですが、特別な場合には、問題は完全に解決可能です。



「フォーク」の定義
(define common-check mark (if (on-board? $1) $1 (while (and empty? (on-board? $1)) $1) (if enemy? (if (flag? is-first) (set-flag is-second true) else (set-flag is-first true) ) ) ) back ) (define common-capture mark (if (on-board? $1) $1 (while (and empty? (on-board? $1)) $1) (if enemy? capture) ) back ) (define queen-slide ($1 (while empty? (set-flag is-first false) (set-flag is-second false) (common-check n) (common-check s) (common-check w) (common-check e) (common-check nw) (common-check ne) (common-check sw) (common-check se) (if (flag? is-second) (common-capture n) (common-capture s) (common-capture w) (common-capture e) (common-capture nw) (common-capture ne) (common-capture sw) (common-capture se) ) add $1 ) ) )
      
      







「攻撃中」の数字の正確な数を知る必要はないため、「カウント」には2つの「ブールフラグ」で十分です。 さまざまな方向の一連の共通チェックチェックの後にis-secondフラグが設定されている場合、「戦闘中」のすべての数字を削除する必要があります。



重要な(理解することは明らかではない)ポイントは、これらのチェックとテイクはすべて、 addコマンドが形成される前に完了しなければならないということです。 さらに、通常のチェスとは異なり、(対戦相手の駒によって)占有されているフィールドに行くことはできません。



すでにこの場所で、ZRFの「裏切り」が完全に現れています。 少し遊んだ後、次のバグに気づくでしょう:







開始位置の後ろ、ターンとは反対方向にあるフィギュアは、「戦闘中」とは見なされないことに気付くかもしれません。 これは、コースの計算時に、初期フィールドが空とは見なされないという事実によるものです。 エラーの原因を理解したら、簡単に修正できます。



「フォーク」の定義を修正
 (define common-check mark (if (on-board? $1) $1 (while (and (or (position-flag? is-start) empty?) (on-board? $1)) $1) (if enemy? (if (flag? is-first) (set-flag is-second true) else (set-flag is-first true) ) ) ) back ) (define common-capture mark (if (on-board? $1) $1 (while (and (or (position-flag? is-start) empty?) (on-board? $1)) $1) (if enemy? capture) ) back ) (define queen-slide ( (set-position-flag is-start true) $1 (while empty? (set-flag is-first false) (set-flag is-second false) (common-check n) (common-check s) (common-check w) (common-check e) (common-check nw) (common-check ne) (common-check sw) (common-check se) (if (flag? is-second) (common-capture n) (common-capture s) (common-capture w) (common-capture e) (common-capture nw) (common-capture ne) (common-capture sw) (common-capture se) ) add $1 ) ) )
      
      







最初のフィールドを位置フラグでマークし、さらに空と見なします。



定式化された規則を残りの部分の動きに一般化することは技術の問題です。 このソリューションは、1人の女王と遊ぶ場合にはうまく機能しますが、たとえば2つのルークで遊ぶ場合、完全ではありません。







プログラムは、移動する1つの図が別の図でプラグを「開く」ことができることを考慮していません。 これは、エラーを修正するために何を行う必要があるかが非常に明確な場合に該当しますが、(今のところ)方法が完全には明らかではありません。 明らかに、すべての数字を並べ替え、それぞれの数字から可能なフォークを確認する必要があります。 ボード上のすべてのピースの検索を自動化するには、チェーン内のすべてのフィールドをリンクする「方向」を作成すると便利です。



すべてのフィールドをリンク
 (define Next-Definitions (dummy offboard) (links next (a1 b1) (b1 c1) (c1 d1) (d1 e1) (e1 f1) (f1 g1) (g1 h1) (h1 a2) (a2 b2) (b2 c2) (c2 d2) (d2 e2) (e2 f2) (f2 g2) (g2 h2) (h2 a3) (a3 b3) (b3 c3) (c3 d3) (d3 e3) (e3 f3) (f3 g3) (g3 h3) (h3 a4) (a4 b4) (b4 c4) (c4 d4) (d4 e4) (e4 f4) (f4 g4) (g4 h4) (h4 a5) (a5 b5) (b5 c5) (c5 d5) (d5 e5) (e5 f5) (f5 g5) (g5 h5) (h5 a6) (a6 b6) (b6 c6) (c6 d6) (d6 e6) (e6 f6) (f6 g6) (g6 h6) (h6 a7) (a7 b7) (b7 c7) (c7 d7) (d7 e7) (e7 f7) (f7 g7) (g7 h7) (h7 a8) (a8 b8) (b8 c8) (c8 d8) (d8 e8) (e8 f8) (f8 g8) (g8 h8) (h8 offboard) ) ) (game ... (board (Board-Definitions) (Next-Definitions)) )
      
      







次の方向に加えて、 反復を完了するために使用されるダミーのオフボードフィールドも定義します 。 これはかなり一般的なZRFイディオムです。 すべてのフィールドをリンクする機能に加えて、 linksコマンドを使用して、「変更されたトポロジ」を持つさまざまなボードを作成できます。 たとえば、ボードの端を「接着」して、シリンダー、トーラス、またはメビウスの帯に変えることができます。



これで、作成した方向を使用できます。 残念ながら、それらのコースの一部として直接作品を「整理」しようとすると、技術的な困難に直面します。 検索を開始する前に、現在の位置を覚えておく必要があります(その後、移動を完了するaddコマンドを作成するため)。 通常、これには2つのmark / backコマンドが使用されますが、 common-checkおよびcommon-captureで既に使用されており、 markコマンドで保存された位置のスタックはサポートされていません。



この問題を解決するには、架空のプレイヤーを作成しますか?Clean



 (game ... (players Black ?White ?Clean) (turn-order ?White ?White ?White ?White ?White ?White ?White ?White Black ?Clean) )
      
      





前の記事ですでに述べたように、プレイヤーの名前の先頭にある疑問符は、プレイヤーがゲームに直接参加せず、ランダムに動きを実行することを意味します。 しかし、それはどのくらい正確に行きますか? 副作用のためだけにこのプレーヤーの動きが必要です(彼のターン中、ボード上のフォークの存在とその下にあるピースのチェックが行われます)。 明らかに、それは価値がありませんか?ピース移動するにはきれいなので、ボードにドロップする必要があります:



すべてのフォークを検索
 (define common-check mark (if (on-board? $1) $1 (while (and (or (position-flag? is-start) (or (piece? Cleaner) empty?)) (on-board? $1)) $1) (if (piece? Stone) (if (flag? is-first) (set-flag is-second true) else (set-flag is-first true) ) ) ) back ) (define common-capture mark (if (on-board? $1) $1 (while (and (or (position-flag? is-start) (or (piece? Cleaner) empty?)) (on-board? $1)) $1) (if (piece? Stone) capture) ) back ) (define clean-queen ( (verify empty?) (set-position-flag is-cleaner true) a1 (while (not-position? offboard) (if (piece? Queen) (set-flag is-first false) (set-flag is-second false) (common-check n)(common-check nw) (common-check s)(common-check ne) (common-check w)(common-check sw) (common-check e)(common-check se) (if (flag? is-second) (common-capture n)(common-capture nw) (common-capture s)(common-capture ne) (common-capture w)(common-capture sw) (common-capture e)(common-capture se) ) ) next ) a1 (while (not-position? offboard) (if (position-flag? is-cleaner) add ) next ) ) ) (define slide ( (set-position-flag is-start true) $1 (while empty? add $1 ) ) ) (game ... (players Black ?White ?Clean) (turn-order ?White ?White ?White ?White ?White ?White ?White ?White Black ?Clean) (board (Board-Definitions) (Next-Definitions)) (board-setup (?Clean (Cleaner off 1) ) (?White (Stone off 8) ) (Black (Queen e4) ) ) (piece (name Stone) (image ?White "images\Chess\SHaag\wpawn.bmp") (help " ") (drops (add-to-empty) ) ) (piece (name Cleaner) (image ?Clean "images\DarkChess\Invisible.bmp") (drops (clean-queen) ) ) (piece (name Queen) (image Black "images\Chess\SHaag\bqueen.bmp") (help "Queen: can slide any number of squares in any direction") (moves (slide n)(slide ne) (slide e)(slide nw) (slide s)(slide se) (slide w)(slide sw) ) ) )
      
      







かなりの数の変更がありますが、一般的な意味は理解できると思います。 私たちはプレイヤーにクリーンを許可し、自分の駒をフィールドに( 黒の移動の直後に)置き、その過程でフォークをチェックしました。 この数字はゲームプレイに関連していないため、非表示にすることが望ましいです。 完全に透明な図のリソースは、たとえばこの面白いゲームから取得できます。



?Cleanはフォークを見つけるのに素晴らしい仕事をしますが、それが追加する形状はどうですか? ゲームプレイを妨げないように、この数字が3回も見えない場合は、ボードから削除することをお勧めします。 移動中にそれを行いますか?ホワイト



ごみの清掃
 (define add-to-empty ( (verify empty?) (set-position-flag is-cleaner true) a1 (while (not-position? offboard) (if (piece? Cleaner) capture ) next ) a1 (while (not-position? offboard) (if (position-flag? is-cleaner) add ) next ) ) )
      
      







?Cleanがその形状を繰り返し使用できるように、対応するオプションを有効にします。



 (option "recycle captures" true)
      
      





原則としてこれはすべて機能しますが、 が移動中にプラグを入れないと、 「クリーンは彼の作品を費やし、 「白は彼が8枚の作品すべてがすでにボード上にあるため移動できないため、それをクリアできません 明らかに、移動を完了する機会を与えるべきですか?彼が少なくとも1つのフォークを見つけることができたという条件でのみクリーンアップします。



フォークの検索を修正
 (define clean-queen ( (verify empty?) (set-flag is-succeed false) (set-position-flag is-cleaner true) a1 (while (not-position? offboard) (if (piece? Queen) (set-flag is-first false) (set-flag is-second false) (common-check n)(common-check nw) (common-check s)(common-check ne) (common-check w)(common-check sw) (common-check e)(common-check se) (if (flag? is-second) (set-flag is-succeed true) (common-capture n)(common-capture nw) (common-capture s)(common-capture ne) (common-capture w)(common-capture sw) (common-capture e)(common-capture se) ) ) next ) a1 (while (not-position? offboard) (if (and (flag? is-succeed) (position-flag? is-cleaner)) add ) next ) ) )
      
      







ゲームが突然終了しないように、プレイヤーの1人が移動できない場合、次のオプションが役立ちます。



 (option "pass turn" 2)
      
      





Ufff ...すべてが機能するようになりました (ただし、オリジナルほど美しくはありませんが、どのような数字を再生するかを決定します)。 もちろん、この構造全体は互いに支え合う松葉杖の構造に非常に似ていますが、これはZRFで些細でないことをするための価格です。



デザートとして、次のバージョンのチェスをお楽しみください。







すべてのピースは通常のチェスと同じように進みます。 変更は1つだけでしたが、ゲームのコース全体を根本的に変更しました。 私は主観的であるため、そのメリットを理解することは困難ですが、個人的には、通常のチェスよりもコンピューターで勝つことははるかに難しいと言えます。 ゲームは非常にダイナミックで、10ムーブ以上続くことはめったにありません。 勝つためにフォークを入れてください!




All Articles