制限ゲート

最終更新 : 2019/07/18

今回のテーマは制限ゲートについてです。

ゼロから説明するような口ぶりで書かれている部分もありますが、実際はガジェットや手直しメニューの「教えてチップ」をチェック済みの方を対象としています。さわってみたもののピンとこなかった人向けです。

もともと筆者がそういう人でした。ゲーム内のヘルプだけでは解釈が難しい部分を自分なりに補完し、制限ゲートの機能とその検証方法を紹介していきます。

本記事では、制限ゲートのことをしばしば「ゲート」と略します。ANDとかNOTとかは一切出てきません。

「オープン要求」と書かれている場合、「ゲートのインプットにシグナルを送る」ことを指しています。

概要

制限ゲートはオレンジのアイコンの中、セレクターのとなりにあります。

画像 柵みたいなアイコンです

たくさんのイベントのうち「一つだけ」処理したい時に使えるガジェットです。これだけ聞けばセレクターで良さそうですが、制限ゲートにはスペシャルな機能がついています。

イベントが同時に呼び出された場合に備えて優先度を決める機能、そして優先度が低い処理をいったん待たせておいて、後追いで実行する機能です。

まずは制限ゲートの機能をガバっとまとめてから、じわじわと機能をチェックしていきたいと思います。

制限ゲートって?

  • オープンとクローズの状態を持つノードである
  • オープンの時だけ、インプットのシグナルをアウトプットへ通す
  • 同じ名前のゲートのうち、オープンになれるのは一つだけである
  • 同時にオープン要求が出された場合を考慮し、優先度を設定できる
  • あるゲートがオープン中、別ゲートがオープン要求を受けた場合、優先度によってふるまいが変わる
    • 1 別ゲートの優先度が高いまたは、同じで「割り込み」オンの場合:現行ゲートをクローズして即座に別ゲートをオープン。
    • 2 別ゲートの優先度が同じまたは低い場合: オープン要求を却下
  • オープン要求が却下された場合、設定次第でキューに登録できる。クローズ状態になり次第、キュー内で優先度の高いゲートから順次オープンされる

耳慣れない「キュー」という言葉が出てくるので、敬遠されがちなガジェットだと思います。

順を追ってくわしく見ていきましょう。

教えてチップの実践例

まずは教えてチップをやってみます。

実践の内容としては、□ボタンと×ボタンで、それぞれ一定時間点灯するランプを作るというものです。片方のタイマーが終わるまで、もう片方のボタン操作は無視されます。

画像 リセットモード「手動」にして、タイマーでクローズします

教えてチップ内では明記されていませんが、二つのゲートの名前はデフォルト名です。同じ名前なので同一の制限が適用されています。もしゲートに別々の名前をつけたなら、二つのランプを同時に点灯できるようになります。

参考までに、これをセレクターで作るとこんな感じになります。

画像 片方しか点灯できないことは、パッと見こちらの方が分かりやすいかも

ポートA(デフォルト)をクローズ状態と見なしています。単純な処理なら問題ないですが、ここに優先度の機能を盛り込むとなると、制限ゲートを使わないと大変だろうなと思います。

ボタンを同時押ししたらどうなる?

実践例のロジックで、ボタンを同時押しするとどうなるかというと、その人の環境によって結果が変わるかもしれません。どちらのゲートを先に配置したか、とかで。

どの環境でも同じ結果になるように、優先度をつける機能が用意されています。その名もズバリ「優先度」です。

画像 優先したい時は数値を高くします

デフォルト10です。片方に11を設定すれば、同時押し時にそちらが必ず優先されます。

ゲートがオープンされたかどうかをチェックしたい時は、リセットモード「手動」にして、「アクティブ」ポートをナンバー表示マシンにつなぐと分かりやすいです。1だとオープン、0だとクローズです。

優先度の数値が同じだったらどうなる?

数値が同じ場合は、「割り込み」がオンになっているものが優先されます。数値が同じでどちらも「割り込み」がオンで……となったらもうシステム任せで、こちらからは制御できません。

画像 今はまだ「割り込み」という名前の効果は見えてきません。この項目が真価を発揮するのは次節です。

オープン中の動作チェック

次のようなロジックを組んでみます。ゲートのリセットモードは「手動」です。

画像 「ゲートを閉じる」は使用しません

まず□ボタンを押します。するとゲートを閉じるシグナルがないので、いつまでもオープンになったままです。この状態で×ボタンを押すとどうなるでしょう。 この実験によって、現行ゲートがオープン中に、別ゲートがオープンした場合の動作を確認できます。結果は、現行ゲートと比較した別ゲートの優先度によって変わります。

| 別ゲートの優先度 | 結果 | | ---- | ---- | | 高い | 現行をクローズして即座に開く | | 同じ(割り込みオン) | 現行をクローズして即座に開く | | 同じ(割り込みオフ) | 却下 | | 低い | 却下 |

ということで、割り込みオンは同じ優先度のゲートに対して重要な働きをすることが分かります。


ここまでが機能のひとまとまりです。

  • 同じ名前のゲートのうち一つしかオープンできない
  • 優先度を指定できる
  • 優先度によってオープン中のゲートを強制クローズできる

ここからはもう一つのスペシャル機能の紹介に移ります。スペシャルなので、不要なら使わないこともできますよ……と言いたいところなのですが、これまでに出た「割り込み」が関係する機能になっているために、知識としては必須となります。

ということで、どんな機能か見ていきましょう。

キュー(待ち行列)

キュー(待ち行列)というのは情報処理分野の言葉です。Wikipediaを読んでみてください。

制限ゲートにおけるキューは、「処理待ちリスト」のようなイメージです。目には見えないリストです。

先ほどの「オープン中の動作チェック」において、却下されるケースがありましたね。次のいずれかの設定をしておくと、却下されたゲートはキューに登録されます。

  • 制限ゲートのリセットモードを「キュー」にする
  • 割り込みオンにする

画像

キューに登録されるとどうなるかというと、現行ゲートがクローズされた時、なんとキューのゲートが自動オープンされます。却下されておしまいではなく、順番を待ってから後追いで実行されるということです。

もしキューに複数のゲートが登録されているなら、キュー内で並び替えが行われ、順番にオープンされていきます。

並び替えは「優先度」の高い順です。優先度が同じ場合は「割り込み」オンが先です。それでも優劣がつかない場合は先に登録された方が勝ちです。

次のようなロジックを組むと動作を確認できます。

キューの実験

△×○□ボタンから制限ゲートにつないで、タイマーを起動する仕組みを作ります。タイマー完了でゲートクローズとします。 次の通りに設定します。

  • 各ゲートのリセットモードは「キュー」
  • **タイマーのスタートには「アクティブ」**ポートを使う
  • 最初に実行するゲートの優先度を一番高い数値にする(図では△ボタン)

そしてどうするかというと、最初のゲートの実行中に、残りのゲートのオープン要求を出します。

画像 ナンバー表示マシンはアクティブポートにつないでいますが、タイマーで視覚的に分かるので、省略してかまいません

今回の例では、△ボタンを押してタイマーが動いている間に、□○×をポポポンと押す流れです。

最初のゲートは優先度が高いので、それ以降のオープン要求は却下されると同時に、「しれっと」キューに登録されます。キューに登録されると、制限ゲートのチップが点滅します。

そのままことの成り行きを見守りましょう。

最初のゲートがクローズされると、キュー内の優先度が一番高いゲートが自動的にオープンされます。それが終わると、キュー内2番目が、それが終わるとキュー内3番目が、順次実行されます。

後から押す3つのボタンの順番や優先度を変えて実験してみてください。キュー内の並び替えの法則が見えてきます。

キューの中身と自動オープンのイメージ

いろいろなパターンでゲートの動作をテストするにあたっては、キューの中身と自動オープンの流れについて、自分なりのイメージを持った方が良いと思います。正しい仕組みはもちろん不明です。

筆者の場合、キューの中身は「ゲートX:優先度」というそれだけの情報がリストアップされているイメージを持っています。

クローズ状態になったら、リストの一番上の情報を取り出して(リストから削除)、そこに自動でオープン要求を送ります。もしオープンできなかったら、そのゲートの設定に従いまたリストに登録して、最上位に並び替えられます。

自動オープンできないことがあるの? と疑問に思うかもしれませんが、次のようなケースがあります。

キューと普通のオープン要求がぶつかったら?

キューがあるという前提で、現行ゲートがクローズしたまさにその直後、別のゲートにオープン要求が出されたらどうなるでしょう。

この場合は、キュー内最上位とその最新要求とで優先度を比べて、上位のゲートが実行されます。キューが負けて最新要求が実行された場合(割り込まれた場合)は、それがクローズした後で、ちゃんとキューは実行されます。

こういった結果を予想しやすくするためにも、イメージを持っておくことは大事だと思います。リストから削除されるタイミングについては意見が割れそうですが、答えの出ない問題なので悩むのはほどほどにしましょう。追究したい方は後述の「ゲートを同期」も検討材料にしてくたざい。


とにかく重要なことは、キューを使えば、却下された処理も後追いで実行できるということです。

実行順位は低いけど、実行しないとゲーム的におかしくなる処理なら、キューを使えば良い(使わなければいけない)ということです。もっとも、そういった処理がもしあれば、キューに登録するのではなく「同時にぶつからないように作る」という対処の方が簡単だろうと思います。

最初に紹介した、優先度を加味してゲートを一つだけオープンできる機能とこのキュー機能、大きく分けて二つあると考えると分かりやすいです。

オープン機能がまずありきで、それからキューを使うかどうかを検討します。「割り込み」をオンにするとキューに登録されるようになることは忘れがちなので、注意しましょう。

ゲートを同期

制限ゲートのポートの中で、まだ関わってきていないものがあります。「ゲートを同期」です。

常にオンになっている項目で、機能を使わないならそのまま触らないでOKです。

画像

この項目で何ができるかというと、ゲートをオープン・クローズする「タイミング」を指定できます。

機能を使う場合、まずはワイヤーをつないでオフにします。するとなんということでしょう。オープン要求を送っても無視されるようになります。そしてキュー登録中のようにゲートが点滅します。この状態になってから同期をオンにすると、その瞬間にオープンされます。

ゲートを閉じる時も同様で、同期オフの状態で閉じようとしても無視されますが、その後同期をオンにした瞬間にゲートが閉じます。

つまり、この項目がオフだと要求が「保留」され、オンにした瞬間に「承認」されるということです。

ちなみに、オープン保留後は承認を待つばかりとなって、「保留取り消し」はできません。ゲートの電源を切っても保留状態は生き続けます。取り消したい時は、承認された後の処理を食い止めてからクローズしましょう。

キュー絡みの動き

保留から承認された時、上位ゲートがオープン中だと、やはり却下されます。キューに登録されるのはこの承認却下時です。保留時ではありません。

また、同期オンで普通にキューに登録された後、キュー実行時に同期オフになっているケースでは、やはり保留されます。キューに複数登録があるなら、そのまま次の優先度のゲートに進みます。


ようやく一通りの機能紹介が完了しました。続いて、おさらいの意味も込めてポートを列挙します。

ポート一覧

画像

インプット

ここにシグナル・パルスを送ると、オープンを試みます。別のゲートがオープン中なら優先度を見て、強制クローズするか判定します。 この記事では「オープン要求」と書いてきました。

アウトプット

ゲートがオープンになっている間、インプットの内容をそのまま通します。

ゲートを同期

OFFの間受け取ったオープン/クローズ要求を保留し、ONになった時に承認します。デフォルトは常時ONなので、即時承認ということです。

ゲートを閉じる

リセットモードが手動・キューの場合、ここにシグナルを送ればクローズ状態にできます。

アクティブ

オープンなら1、クローズなら0です。

優先度

大きい数値の方が優先度が高いです。

割り込み

オンにしておけば、優先度が同じゲートを強制クローズできます。また、オープン要求却下時にキューに登録されます。

リセットモード

ゲートがオープンした後、どのタイミングでクローズするかをリセットモードで決めます。

自動

インプットシグナルがなくなると自動でクローズします。

手動

一度オープンしたら、「ゲートを閉じる」をやらないとクローズしません。ただし、上位/同位割り込みゲートによる強制クローズはあります。

キュー

一度オープンしたら、「ゲートを閉じる」をやらないとクローズしません。 ただし、上位/同位割り込みゲートによる強制クローズはあります(手動と同じ)。また、オープン要求却下時にキューに登録されます。


ポートについては以上です。

最後にちょっとした注意点を紹介して終わります。

キューや同期を使う場合のアウトプット

リセットモード「手動」や「キュー」なら、インプットシグナルが短くてもパルスでも、クローズするまではオープン状態が保たれます。教えてチップでもボタン押下という、短いシグナルが例になっていましたね。

この、短いシグナルによってオープン要求を出されたゲートがキューに登録された場合や、「ゲートを同期」でオープン保留→承認された場合にどうなるかというと、いざオープンされたその時には、アウトプットには何のシグナルも残っていないことになります。

もしゲートのアウトプットからパルスを受信するつもりだったとしたら、オープンされたものの、やることがなくて停止してしまいます。

意図的に使う分には良いですが、こういった停止ケースがあると困る、なくししたいという場面もあるでしょう。どう対応すれば良いでしょうか。

おすすめの方法があります。「キューの実験」ですでに登場した方法です。処理のスタートを、アウトプットポートでなくアクティブポートで行うことです。アクティブポートはオープンになったらONシグナルが流れますので、オープン時にインプットがなくなっていても確実にスタートできます。

インプットの強弱を伝える必要がなく、単に処理をスタートするのが目的であれば、ふだんからアクティブポートを使って良いでしょう。

画像 セレクターやランダムマシンのアウトプットと同じ扱いができます

なお、アクティブポートONのタイミングでパルスを送りたい場合はシグナル操作マシンを通せばOKです。 (関連記事:シグナルとパルス]


いかがでしたか。制限ゲートは分厚いガジェットですが、その分とても強力な機能を持っていると思います。インタラクティブなゲームには必須でしょう。

……とか言いつつ、筆者は今まで一切使っておりませんでした。なんせ意味が分からなかったので。今後は機会をみて積極的に使っていきたいと思います。

プロフィール

溟犬一六(めいけんいちろ)。雑種のクリエイター。ハンドル名はガバチョなど