見出し画像

Retro-gaming and so on

RE: プログラミング学習日記 2023/02/09〜

星田さんの記事に対するコメント

 ・・・継承・・最高やんm(_ _)m

う〜んとね。
結論から言うと「ゲームに於けるデータ設計」ってのは割にオブジェクト指向が役立つんだよ。
例えばRPGで、特にTRPGとかキャラシートとかあるでしょ?
んでモンスター図鑑的なモノがあって。
でも両者とも「パラメータ」類が色々設定されてるなら、何か共通のデータ型の「雛形」を設計しておいて、それを「継承」して作っていった方が「ラク」なんだよな。
原則、ゲームの場合、アクションとかパラメータとかデータ型に「色々と共通する」性質がある以上(例えば「飛行機」は「弾を撃つ」とか・笑)、一々バラバラに設計したくない、って言う背景が出てくると、やっぱ雛形、っつーか「テンプレ」を作っといてそれを全部「継承」した方が「作りやすい」ってのは事実なんだ。
まぁ、オブジェクト指向ってのを散々批判してるんだけど(笑)、結局、

「必要もねぇのに何でもかんでもオブジェクト指向で作ろう」

って言うカンジの「誘導」が意味がない、って事なんだよな。
例えばフツーにCLIのソフトを作る際に「何でもかんでもオブジェクト指向で作ろう」ってのは間違ってる、とは思う。
ゲームでもいつぞや見せた「ババ抜き」のように、「オブジェクト指向で全体を作りました」と言うカンジだと「構造化スパゲティコード」になる、って事も見た。
ただし、フツーのプログラミングの、特にデータ設計に「ちょっとオブジェクト指向を混ぜる」ってのは悪くないドコか効果的だし、ぶっちゃけRacketの構造体はそういうカンジでデザインされている。
そして、ゲームの場合、結構な比率でこういう「オブジェクト指向」的なアイディアが有用なケースが、フツーのプログラムより多いとは思う。

余談だけど、一般の誰もが「オブジェクト指向」なんぞ聞いた事がない70年代末から80年代にかけて。
ナムコなんかはマシン語/アセンブリ言語レベルのブログラムで「オブジェクト指向」的な事をやってたらしい。
ギャラクシアンが発祥かどうかは分からないんだけど、仮にそうだとしたら、1979年辺りでナムコのゲームプログラマはマシン語/アセンブリ言語レベルで「オブジェクト指向的な」発想をしてた、って事だ。
つまり、例えば自機とか敵キャラの「共通の性質」を括って定義しておいて、それを参照しつつ画像とか差異を「あるオブジェクトの定義部分」に埋め込みバラバラに動かす、とか(要は、OOPで言う「インスタンス」だ・笑)。
当時の職業ゲームプログラマって物凄かったんだな、と思うわ。ある意味マジで「時代と技術の最先端にいた」って事だよな。

と言うわけで、ゲームでの「データ設計」、特に似たようなオブジェクトが複数出てくる、って場合は、メソッド定義はさておき、「データ型」と言うガワに於いてはオブジェクト指向って考え方は「有用な場合が多い」って話だ。

とまぁ、そういう前フリを書いてはみたんだけど。
本題に入ろう。

 さて、別種の構造体をリストに入れてそれをSortする問題。実は頭の中では「Caseと(variant x)を使えば楽勝だろう」と考えていた。
 が! Sortの文法だとxが無いw

 こういう風に書きたいのに!

いっつも言ってるけど、星田さんの発想は100%正しい
極めて勘が優れてると思う。
いっつも「あと一歩」のトコにいるんだよな。

つまり、例えば構造体での設計がこんなカンジであるわけだろ?

(struct CHARACTER (Name Race Class Ali Lv Hp Ac Exp Money Move Arm Armor Item Str Int Wis Dex Con Chr) #:transparent)
(struct ENEMY (Name Hp Ac Exp Money Armor Item Str Int Wis Dex Con Chr) #:transparent)

まぁホントにこの通りかどうかは知らんが。
んで、構造体のインスタンスのリストがある、と。

`(
,(CHARACTER "tawa" "ELF" "MAGIC-USER" "" 1 6 10 0 90 6 '() '() '() 10 18 6 11 9 10)
,(CHARACTER "hosida" "HUMAN" "FIGHTER" "" 1 1 10 0 90 5 '() '() '() 17 10 12 8 15 14)
,(ENEMY "DEMON1" 10 5 10 5 '() '() 10 10 10 10 10 10)
 ,(ENEMY "DEMON2" 10 5 10 5 '() '() 10 10 10 10 10 10))

んで、このケースの場合だと「別々の構造体のインスタンス」のDEXスロットの値で、ソートしたいんだけど、どうすりゃエエんだ、と。

Sortの文法だとxが無いw
こういう風に書きたいのに!

ってのはそういう事だよな。
血の叫びだ(笑)。

さて、一回Racketに於けるsortの文法を確認してみよう。


さてさて。
#:keyと言うキーワードパラメータが受け取る値はextract-keyだと書かれてて、それは比較指定の完全型であるラムダ式の一部である、って書かれてる。

(lambda (x y)
 (less-than? (extract-key x) (extract-key y)))

つまり、#:keyに与えてるブツはクロージャだと言う事になる。
これは星田さんも認識してんだよ。

 相手が構造体だけど、もしかしてCar Cadr...の形で参照できるなら、両方共ケツから3つ目ってのは共通してるので大丈夫かも?と思ったが駄目か・・。

つまり、#:keyに与えるのはクロージャじゃなきゃダメだ、って知っている
ついでにこれだ。

Sortの文法だとxが無いw

うん、無い(笑)。でもxを使いたい
要はxを与えるのにいきなりcaseを使ってるから間違った、ってだけだ。何故ならcaseはクロージャを生成しないから。
そう、xを使いつつクロージャを生成する、ってぇのなら単にそこはラムダ式で指定すりゃエエ、って事だ。
つまり、正解はこうだ、って事。

(sort `(
   ,(CHARACTER "tawa" "ELF" "MAGIC-USER" "" 1 6 10 0 90 6 '() '() '() 10 18 6 11 9 10)
   ,(CHARACTER "hosida" "HUMAN" "FIGHTER" "" 1 1 10 0 90 5 '() '() '() 17 10 12 8 15 14)
   ,(ENEMY "DEMON1" 10 5 10 5 '() '() 10 10 10 10 10 10)
   ,(ENEMY "DEMON2" 10 5 10 5 '() '() 10 10 10 10 10 10))
  < #:key (lambda (x) ; ここはラムダ式で指定する
      (case (variant x)
       ((CHARACTER) (CHARACTER-Dex x))
       ((ENEMY) (ENEMY-Dex x)))))

ね?「言われてみりゃその通りだ」でしょ(笑)?
「あと一歩だった」と(笑)。
悔しがっていいからね(笑)。その方が「二度と同じパターンではハマらない」から(笑)。
  • Xでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

最近の「RE: プログラミング学習日記」カテゴリーもっと見る

最近の記事
バックナンバー
人気記事