Smalltalk-72で遊ぶOOPの原点:宇宙船を描く(たぶんこうなんじゃないか編)

アラン・ケイの“メッセージングによるプログラミング”という着想に基づき(非同期処理などいろいろ足りていないながらも──)比較的忠実に実装された1970年代の非常に古いSmalltalk-72に実際に触れてみるシリーズ 第2弾です(なお最新のSmalltalkについては Pharo などでお楽しみください!)。

今回は謎言語「Smalltalk-71」で書かれたスペースウォー・ゲームSmalltalk-72に移植して動かすことを目指します。前回(2019年)を含む他の記事はこちらから→Smalltalk-72で遊ぶOOPの原点 | Advent Calendar 2023 - Qiita


エスパー力を発揮して宇宙船完成図を予想する

Smalltalk-71 のコードをもう一度確認してみましょう。一辺の長さが 2 もしくは 4 で宇宙船胴体とおぼしき扁平6角形が描かれたあと(青字)、2√3 → 2 → 2 → 2√3 の長さで4本の線分が引かれています(オレンジと赤字)。

to ship :size
  penup, left 180, forward 2 * :size, right 90
  forward 1 * :size, right 90
  pendown, forward 4 * :size, right 30, forward 2 * :size
  right 120, forward 2 * :size
  right 30, forward 4 * :size
  right 30, forward 2 * :size
  right 120, forward 2 * :size
  left 150, forward :size * 2 * sqrt 3
  left 330, forward :size * 2
  right 60, forward :size * 2
  left 330, forward :size * 2 * sqrt 3
  penup, left 90, forward :size, right 90, forward 2 * :size
end to

[2023-12-04 追記:最後の right 60 との誤りと思われていた記述は、誌面では正しく right 90OCR の誤認識でしたので、以降もしれっと無かったことにしています。あしからず^^;]

ここで、あらぬ方向に伸びている最後の4本の線分について、その角度はともかく長さについては正しいと仮定します。

さらに、オレンジの線については角度も正しいとすると、最後の 2√3 の長さの赤線は、オレンジの線と同様に宇宙船の右側に沿って描かれる必要がある、と考えるのは妥当でしょう。

残りの二本の赤線の長さは 2 、オレンジと最後の赤の線分の長さが 2√3 であることをあわせると、宇宙船胴体底部の頂点に接するように 60度の角を作って2本の長さ 2 の線分が描かれるとすれば、収まりが良さそうです。

ところで、330という数は 360 - 30 から求められた数値と考えることもできます。タートルグラフィックスで例えば正三角形を描く場合、60 度の角を作るために 180 - 60 度、つまり 120度 曲げなければならないのですが、この 180360 とうっかり取り違えてしまったとしたら…と想像するのはうがち過ぎでしょうか?

つまり、330180-30180360 に取り違えで、続く 60180-60180 から引くのを忘れたよくあるミス…と解釈すると、それっぽく説明がつきそうではあります。

もとより、扁平六角形はきちんと描けているので、どうしてここに来て2度までも違う方法でミスったかという疑問は残りますが…^^;

[2023-12-04 追記:ぼんやりと図を眺めていたら、左に 330度、右に 60度、左に 330度…とよくある「180 から引くのを忘れる」勘違いをしたと解釈する方が自然では?思えてきました。その場合は一貫していて「2度までも違う方法」ではないですね^^; もっとも依然「どうしてここに来てミスったか?」という疑問は残りますが…]

ともあれ、Smalltalk-71 のコードは、とりあえずは次のように読み替えることにいたしましょう。

to ship :size
  penup, left 180, forward 2 * :size, right 90
  forward 1 * :size, right 90
  pendown, forward 4 * :size, right 30, forward 2 * :size
  right 120, forward 2 * :size
  right 30, forward 4 * :size
  right 30, forward 2 * :size
  right 120, forward 2 * :size
  left 150, forward :size * 2 * sqrt 3
  left 150, forward :size * 2
  right 120, forward :size * 2
  left 150, forward :size * 2 * sqrt 3
  penup, left 90, forward :size, right 90, forward 2 * :size
end to

したがって、Smalltalk-72 へのトランスパイルは次のようにするのがよさそうです。

to sqrt x (:x. !1.73)

to ship size (
    @ penup turn 180 go 2 * :size turn 90
        go 1 * size turn 90
        pendn go 4 * size turn 30 go 2 * size
        turn 120 go 2 * size
        turn 30 go 4 * size
        turn 30 go 2 * size
        turn 120 go 2 * size
        turn `150 go (sqrt 3) * 2 * size
        turn `150 go 2 * size
        turn 120 go 2 * size
        turn `150 go (sqrt 3) * 2 * size
        penup turn `90 go 1 * size turn 90 go 2 * size
)

disp clear
@ home penup goto 200 100 pendn. ship 10

スラスターの火炎を描く(準備編)へ続く)