困難を乗り越える:重力はsedで反抗した

画像 そのため、この記事は、これを目的としないツールで非標準の問題を解決したい人を対象としています。 ここでは、ストリーミングテキストエディタ(sed)を使用して、重力に反抗したゲームの類似物を作成するときに遭遇した主な問題について説明します。



さらに、読者は少なくともsedの構文とbashのスクリプトにある程度精通していることを前提としています。



12月の穏やかな夜は、先生から次のようなメッセージを受け取ったとき、穏やかでなくなりました。

sedで:

重力が反抗した

...

かっこいい



率直に言って、私が座っていた最初の半時間は、これがどのように可能であるかという考えでした。 しかし、それからどうにかして自分自身を引き合わせ、理解し始めました。



sedゲームについてグーグルで検索しようとすると、 アルカノイドと倉庫番になりました



問題の分析を始める前に、 リポジトリをプロジェクトと共有し結果のビデオデモを行いたい



したがって、 最初の問題:メモリーsed ビューは、ゲームの現在の状態を何らかの方法で保存する必要があります。 マジックホールドスペースパターンスペースには2つの場所があります



ホールドスペースは、反復間のゲームの状態を保存し(着信キャラクターを1つ処理すると呼びます)、パターンスペースではゲームの状態を変更します。

アルゴリズムは次のようなものです。



  1. 入力に受け取ったシンボルに関連付けられているアクションに渡します
  2. ホールドスペースの内容をパターンスペースに書き込む
  3. アクションのロジックに従ってパターン空間の内容を変更します
  4. スペースを保持するためにパターンスペースの内容を書き込む
  5. パターンスペースにエフェクトを適用します(このステップでは、ゲームの「サービス」状態からユーザーに表示される状態になります)
  6. パターンスペースの内容を画面に表示する
  7. 入力した文字ごとに手順1を繰り返します。


入力されたテキストの分析を簡素化するために、私たちは、着信行全体の、最初の文字のみが重要であると信じています。



最初のものは初期化です。 最初にゲームフィールドを作成する印刷ラベルを作成します。 ゲームが開始された瞬間から、空の文字列がsedの入力に渡されたときに1回だけ状況が発生します。これはゲームのまさに開始です。



このように



/^$/b print ... :print #   ,    g s/.*/\ +-----------------------+\ |BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB1\ |BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB2\ |BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB3\ |BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB4\ |BBBBBBBBBBBBBBBBBBBBBUPPABBBBBBBBBBBB5\ |BBBBBBBBBBBBBBBBBBBBUBBBABBBBBAPPPPPP6\ |DBBBBBBBBBBBBBBBBBUPBBBBABBBBBABBBBBB7\ |BDBSBFBBBBBBBBBBBUBBBBBBABBBBBABBBBBB8\ |BBPPPPPPPPPPPPPPPBBBBBBBPPPPPPPBBBBBB9\ +-----------------------+\ b end
      
      





この段階では、すべてはあなたの想像力に依存します。 各キャラクターが何を担当するかを決定します。 私はBを持っています-これは空の場所です、FとS-自転車の車輪、A、D、P、U-道路(美しさのために4つのタイプですが、その詳細は後で)。



受信したすべてを画面に表示する必要があります。 ご覧のとおり、印刷の最後にラベルの最後に移動します。



endは、アクションの全体的な完了です。



 :end #     hold space h #     -    #     i\ ^[[H #   pattern space   p
      
      





注: ^ [[Hはコピーする価値はありません。これはエスケープシーケンスです。 たとえば、vimでは次のように入力します。Ctrl + V Ctrl + ESC [H



sed -nf gravity.sed



を使用してスクリプトを実行します。 静止画像おめでとうございます!



フィールドがある場合は、即興ホイールを左右に動かすチームを作成するだけで十分です。



 s/FB/BF/ s/SB/BS/
      
      





上に移動するのはもう少し複雑ですが、困難を恐れませんよね?



 s/B(.{39})F)/F\1B/
      
      





ここでは、ポイント全体が数字39にあります。これは、文字列の文字数です。



いくつかのマークを追加し、それらを必要なキーに「バインド」します。そして、できれば、境界と物理学のない、ある種の抽象的な自転車(大丈夫、2輪)があります。 しかし、迷路を書きたい場合は、これが必要です。



ゲームを確認することは難しくありませんが、各キャラクターが入力された後にEnterキーを押すのは平均以下の喜びなので、このプロセスを自動化する必要があります。



問題2:ビート



ゲームの「ハート」はsedであるため、ボタンを押すたびにEnterキーを押すシェルが必要です。 無限のサイクルはそれです。



サンプルコード:



 (while true do read -s -n 1 key #           key echo $key done) | sed ...
      
      





ゲームはもう少し楽しくなりますが、それでも大きな欠陥があります。プレイヤーは時間の経過に影響を与えることができます。 プレイヤーがキーを突く速度が速いほど、ゲームの進行は速くなります。 これは私たちには合わないので、 ビートが必要です。 これで、クロックとユーザーという2つのデータソースができました。 頭に浮かぶ最も簡単な解決策は、読み取り時に-tスイッチを使用することです。 指定した秒数内にユーザーが何も入力しなかった場合、readはスクリプトをブロックしません。 この決定は私には向いていませんでした。SunOSの読み取りでは、秒の小数を受け入れることを拒否しました。1秒あたり1フレームのダイナミックゲームは、どういうわけか奇妙です。 2番目の解決策は、名前付きパイプを使用することです。



 #  (  ) pipe    rm -f gravity-fifo; mkfifo gravity-fifo; #     pipe    sleep 99999999 > gravity-fifo & #   sed -nf gravity.sed gravity-fifo & #  ,    $TIME * 10^-6     t  pipe while true do echo t > gravity-fifo usleep $TIME done & #   (while true do read -s -n 1 key echo $key [[ $key == "q" ]] && pkill -P $$ done ) | $SED -u -e '/t/d' > gravity-fifo
      
      





少し説明:



pkillは、クロックを停止してスリープ状態にする良い方法です。



そして、このスリープが必要な理由がわからない場合は、それなしで確認できます。最初のエコーパイプが閉じ、sedがEOFをキャッチします。 途中で、ユーザーが時計の記号を書くことを禁止します。ここでは自転車を運転しますが、時間は制御しません。



問題3:物理学



一定の間隔で呼び出されるタイミングシンボルがあります。 ゲームのすべての物理を登録できるのは、このシンボルのハンドラーです。 ここで私は一般的なアドバイスをすることはできません、すべての物理学はチェックされるすべてをチェックする正規のセットです。



問題4:後処理



終了ラベルに移動し、スペースを保持するために変更を保存した直後に、エフェクトの適用を開始できます。 先ほど、4種類の道路を使用することを述べました。 私は試行錯誤によってこれに来ました。 道路の最初のバージョンでは、それらは同じタイプ:Rであり、後処理段階で、道路の相対的な位置に応じて上昇/下降する規則を記述しようとしました。



アイデアは拒否されました。アルゴリズムは絶えずクラッシュし、道路のタイプを登録するのが簡単になりました。

ANSI Escapeシーケンステーブルを装備して 、Unicodeテーブルも使用しましたが、結果は...



 s/A/^[[107;38;5;82m█^[[0m/g s/D/^[[107;38;5;82m▚^[[0m/g s/P/^[[107;38;5;82m▀^[[0m/g s/U/^[[107;38;5;82m▞^[[0m/g
      
      





ここには落とし穴があります:Unicodeを使用する場合、検索パターンに正確な文字数を含めるべきではありません。 Unicode文字は2文字として認識され、そのような規則性のロジックは壊れます。



5番目の問題:小さなスペース



画面にはあまり多くのキャラクターがいないので、もっと地図を作りたいです。 ここでスクロールバッファーが役に立ちます。 これは、マップの継続部分を保存するユーザーには見えない場所です。 快適にスクロールするには、行に番号を付け、最後にゾーンに番号を付ける行(たとえばz1)を追加する必要があります。



仕事のアルゴリズム:



  1. プレイヤーの一部がマップの右端にNキャラクターより近い場合、次のステップに進みます
  2. マップの2番目のシンボルを削除します(最初のシンボルはフレームです)
  3. 各行の末尾の数字の前に、#を追加します
  4. 正確にM文字#を入力した場合は、次の手順を実行します。そうでない場合はスキップします
  5. 現在のゾーンの番号を確認し、すべての#をこのゾーンに対応するカードに置き換え、ゾーンの名前を次のゾーンの名前に変更します
  6. 終了ラベルに移動
  7. 後処理段階で、#文字が可視領域に入らないように可視部分を切り取り、ゾーン番号などの補助データを削除します。


やった! これで、sedでゲームを作成する方法の基本的な知識が得られました。 なんで? できるから。



PSタスクはZhmylyov S.Aから親切に提供されました。 次世代が私の経験に参加し、さらに素晴らしいことをしたいと思っています。 x)



All Articles