Smalltalk-72で遊ぶOOPの原点:宇宙船「spaceship」の仮実装と複数インスタンスの動作確認
アラン・ケイの“メッセージングによるプログラミング”という着想に基づき(非同期処理などいろいろ足りていないながらも──)比較的忠実に実装された1970年代の非常に古いSmalltalk-72に実際に触れてみるシリーズ 第2弾です(なお最新のSmalltalkについては Pharo などでお楽しみください!)。
今回は謎言語「Smalltalk-71」で書かれたスペースウォー・ゲームを Smalltalk-72に移植して動かすことを目指します。前回(2019年)を含む他の記事はこちらから→Smalltalk-72で遊ぶOOPの原点 | Advent Calendar 2023 - Qiita
描いて移動するだけの spaceship
複数の宇宙船のキーボードからの同時操作を早く試さないといけないので、まず移動 moveship
と描画 display ship
のみに限定した spaceship
をSmalltalk-72で実装します。
to clock (!mem 280) to spaceship : pilot thrust steer trigger numtorps location speed direction time ( isnew ? (:pilot. :#thrust. :#steer :#trigger. "numtorps _ "speed _ "direction _ 0. "location _ point (rand between 50 462) (rand between 50 462). "time _ clock) 0 < clock - time + MOVELAG ? ( "time _ clock + MOVELAG. moveship. display ship) ) "SSIZE _ 6. "MOVELAG _ 0. "SPSCALE _ 1.0. "DIRSCALE _ 1.0. "LSCALE _ 1.0.
システムクロックの取得については mem 280
のままでもよさそうですが、Smalltalk-71の元のコードに見た目を似せるため clock
アクションを作りました。(不明点が多かったり、いろいろ破綻してきているので、もはや「元のコードに似せる」努力自体、無駄なあがきのようにも思えますが…^^;)
spaceship
はこれまでのプロシージャと違い、クラスとして機能する(インスタンス生成能を持つ)と仮定して、Smalltalk-72版ではインスタンスを生成する isnew とその非偽時、つまり、インスタンス生成直後のコンテキストである場合に実行される初期化処理を加えています。
仮引数の pilot
、thrust
、steer
、trigger
は送られてきたメッセージから引数としての値をフェッチ :
しています。後三者については、逐次評価して値が変わるオブジェクトであることを想定して(将来的にはジョイスティックをエミュレートするオブジェクトを渡す予定)、通常の値のフェッチ :
ではなく参照をフェッチ :#
しています。
その他のインスタンス変数については、適当な値で初期化しました。
非同期処理を想定したと思われる pause ...
のところは悩ましいところですが、指定した間隔を置いて処理をするように最初に移動しました。もっとも、このエミュレーターは大変遅いので、画面更新や位置情報の更新のためのラグを考慮する必要はほとんど無いと思われます。
なおここで使用している MOVELAG
を含めたグローバル変数については、すべて大文字に変更しました。加えて、Smalltalk-71版に登場する :size
については何かと問題が発生したため SIZE
からさらに SSIZE
に名前を変えています。なお、Smalltalk-71 でプロシージャの仮引数として :size
を使っているものは変更無しです。
これをうけて moveship
、display
については次のようにコードが変更になります。どうぞあしからず。
to moveship ( "speed _ speed + SPSCALE * thrust. "direction _ (direction + DIRSCALE * steer) mod 360. location x _ (location x + (cos direction) * LSCALE * speed) mod 512. location y _ (location y + (sin direction) * LSCALE * speed) mod 512. ) to display ( @ penup goto location x location y up turn direction + 90 pendn. (:#) SSIZE. (0 < thrust ? (flame SSIZE) 0 > thrust ? (retro flame SSIZE)) )
各グローバル変数の初期値はそれぞれ、上図およびコピペ用のコードに示したとおりです。
spaceship
について、あとは、moveship
と display ship
だけをコールするようにコードしました。
では、さっそく動かしてみましょう。とりあえず、thrust
と steer
、trigger
は 5
、30
、false
に設定しています。
disp clear "s1 _ spaceship 'Jimmy' 5 30 false. repeat (s1)
良い感じですね。宇宙船を増やしてみましょう。
"s2 _ spaceship 'Beth' `5 `20 false. repeat (s1. s2)
esc
キーで停止します。
( 簡易スケジューラーを作る へ続く)