見出し画像

進捗報告/ 迷走ではなく近道であると信じて


何でまたLispなんかに手を出すのか

「あれ?Ren'Pyだけで良いって言ってたくせにSuika2に浮気して、舌の根も乾かないうちに今度はゲームエンジンでもないLisp?」

はい、仰ることはわかります。傍目に見てみっともないのは自分でも自覚しております。ツール変えたからって上手くい訳ではないことも。
まず1つ言いたいのは、ちゃんとゲーム作ってあわよくば販売するところまで行くには(切に行ってみたいけど)Ren'PyかSuika2で作るという気持ちは変わってないです。Lispで作ろうとしてるのは、ゲーム本体ではなくてゲームデザイン用のツール/自分用ゲームエンジンであります。
ツール自体をRen'PyやSuika2で作っても良いのだと思いますが、これらはあくまでもゲームエンジン(しかもノベルゲーム特化)なので、いわゆるプログラムだけをするのにはちょっとキツい。
あとゲームエンジンで作ると、なんか「ちゃんとゲームとして作らなくちゃいけない」プレッシャーがあって、理論検証をもう少しやりたい自分には心理的負荷になっているみたい。(早くゲームにしたい気持ちはとってもあるけど。)
ゲームとして完成させる前にゲームシステムを作りたくて、そのゲームシステムが面白いゲームを生み出せる検証をしたい訳なんですよ。

今はプログラムレベルで試行錯誤しないといけない段階なのだけれど、特にあらかじめきちんとデータ構造やら何やらを決めておかないと厳しいSuika2のwmsでは自分の能力的には非常に難しく感じる。本職のプログラマ並みの構想力、構築力が自分に有れば良いのだろうけど。
誤解して欲しくないのですが、Suika2でゲームを作るのが難しいのではなくて、自分がwmsに無茶振りしようとしているのがいけない。
素直にノベルゲームを作るならSuika2は現時点で最良の選択肢の1つだと思います。今もどんどん進化しているし。

お前さんの個人的事情は分かったけど、じゃあPythonで良いのでは?と言うのは正直あって、多分それが実は正解だとも思います。
Pythonは初心者にも取っ付き易い言語だとも思うし、自分はPython本も頑張ってオライリーのとかも買ったりして結構な手間暇を費やしたり、天拝山クエストでは色々いじれたりもしてるので、このままPython使い続けるのはあり。
(難しいところはRen'Pyの先輩たちに優しく教えてもらえたし。)
ただ天拝山クエストでRen'Py経由でPythonいじっている時は大丈夫だったのだけれど、Pythonだけで何か作ろうと言うかツール作ろうという気が自分に全く湧かないのが困ってしまうのでした。

自分の貧相なプログラム遍歴

自分は過去にプログラマーでございと言って就職したこともあるのだけれど、その時ははっきり言ってPHPのフレームワークをいじらせてもらっただけなので経歴に残せるようなものではなく、自分はプログラマーでもなければ習得したプログラム言語も無いと思ってます。
そんな自分が本気で学ぶ熱意もなく、なんとなく使えたら良いなあと思って入門書だけはいっぱい読んできたのがPythonとLisp系(一応Common Lispとschemeの両方)です。

Pythonにはめっちゃくちゃ豊富なライブラリ群があって、大体自分のやりたいことへの道筋は既に舗装されていると言っても過言ではないのだけれど、恐らくだけどその「自分のやりたいこと」が本当は全然具体的じゃなかったので踏み出さなかったのでしょう。あとプログラム書いていて微妙に楽しく無い感があったかもしれない。

Lisp系はPythonよりも前から知っていて、Pythonより本は買っていて、更に色々な処理系を触ってみてはいました。最初は本は難しくて全然分からなくって積ん読の山だし、処理系インストールしてフィボナッチ数を計算するプログラムの写経してはアンイストールばっかりしていた気がします。
だけれど幾度となく触ろうとしてたのは、これらLisp族が他の言語とは違う何か良いものだ、と無意識レベルで感じていたからだと思いますが、今ならそれがREPLのせいだとはっきり言えます。
大体今時の言語はインタラクティブモードがあってREPLは珍しいものじゃ無いですが、Lisp族のREPLはスクリプトを処理して終わりではなくて、ずっと駐在してて、REPLと対話しながらプログラムしていくのが楽しいのだ!と言うことに気がついたのは最近のことです。
つまり自分にとってLisp系のプログラムは書いていて楽しいのです。

Lisp系が良いな、と思うところ

#lang racket
(require srfi/1)

(define (xDy x y)
  (define (dice x y) (cons (random 1 x) y))
  (define (diceroll x y)
    (if (= x 0)
        '()
        (dice y (diceroll (- x 1) y))))
  (diceroll x (+ y 1)))

(define (check-dice x y)
  (define (check-num->list x y)
    (count (lambda (xx) (= xx y)) x))
  (define (check-result x y)
    (if (= y 0)
        '()
        (cons (check-num->list x y) (check-result x (- y 1)))))
  (reverse (check-result x y)))

(define (check-judge x y)
  (reduce + 0 (drop x (- y 1))))

(define (judge-xDy x y z)
  (define dice (xDy x y))
  (cons dice (check-judge (check-dice dice y) z)))

(display (judge-xDy 10 6 5))

上のコードはRacketで10d6を振って、出た目と5以上の目の数をセットで表示するプログラムで、ヘッダーの画像が実際に動かしているところです。
知らない人が見れば何のことやらさっぱり、Lisperな人が見たら失笑ものだろうと思いますが、取り敢えずは自分の期待した通りに動くし、書いている間とても楽しかったです。
この短いプログラムを作るのにも半日くらい掛かってはいますが、
「ヘッダーの画面左側で上から書いてて右側で期待通りに動作するか確認して、上手くいったら今書き上げたパーツを使って次のパーツを作ってまた確認して…」
というサイクルが気持ち良くて全然ストレスがありませんでした。
1つ1つのパーツは割合堅牢に書けるし長さも数行で収まるので、短期記憶への負担が少ないからだと思います。

あとLispだと汎用的なプログラムを書き易いというか、自然とそうなる感じがします。例えば上の例だと10d6ですが、8d20とかにしたければ一番下の行を書き換えればすぐできます。
できればプログラム自体には労力を割きたくなく、かつ色々プログラミング上で試行錯誤をしてみたい、となるとこの「自然とそうなる」のはとても良いです。
少ない記述で多くのケースに対応できるというLisp系の強みは、日本の代表的なLisperの1人、川合史朗さんのコラムで教えてもらいました。

なぜRacketにしようとしているのか

実は目の前の旧式MacBookAirには3つのCommon Lisp処理系と4つのscheme処理系がインストールされてたりするのですが(もちろんインストールされてるだけで使い分けたりましてや使いこなしたりは出来ていない)、その中でもある意味scheme派生で独自路線に行ってしまっているRacketを選んだのか?ということで自分のための整理を兼ねてRacketの勧めを書きます。

Python並みの”Battery Included”

schemeは「黒板での動作に定評がある」とか揶揄されるほど、プログラミング言語としてはシンプルで美しいけれど実用的では無い、というイメージがありますが、自分がインストールしているscheme系は全部「実用的」を謳ってます。
(ちなみにRacket、gauche、gambit、biglooです。)
特にRacketは開発環境が一緒になっているし(ヘッダーのIDEとか)、総じてLisp系が弱いGUI周りのライブラリも最初から揃ってます。何か個人で作ろうと思うレベルであればほぼ用意はあるんじゃないでしょうか。
更にPythonでいうpipのようはネット経由でインストールしてくれるパッケージライブラリも充実していて、自分の大好きなサウンド周りのプログラミングも色々と選択肢があったりします。

時々忘れてしまうんですが、自分がなんでゲームを作り出したかと言うと自分の音楽をもっと聴いて欲しいからなんですよね。回り道している感はありますが。

公式ドキュメントが豊富

英語しかないんですが文章資料はいっぱいあります。Racketをフルでインストールしていればネットに繋がらなくてもドキュメント丸ごと見られます。
もともとRacketを作り始めた動機が教育用だったそうで、資料もちゃんと全くの初心者でも興味をもって始められるように段階的になっているのと、更にはプログラミング言語開発の研究ツール用としても作られたという事で、細かい事まで記述がされていて玄人さんにも痒いところに手が届きます。

英語が苦にならなくてプログラミングに興味がある人には本当にオススメしたい。自分はお世辞にも英語が堪能って訳じゃないですが、多少schemeの事を知っているので特に引っかからずに読むことが出来てます。

出来たものを配布し易い

Lispに限らずかもしれませんが、素のプログラミング言語というのは基本はプログラマー向けの道具なので、プログラマーじゃ無い人にプログラム成果物を使ってもらうのは結構ハードルが高いです。その中でもLispは特にその傾向が強いかも(ネットワーク経由のwebアプリは意外とあるみたいですが。)
そういう意味でゲームエンジンを作っている方々にはリスペクトと感謝を惜しみません。
そんな中でRacketはアプリ単体の実行ファイルを作ることができるしGUIアプリも作り易いので、出来たものを配布するには手軽なプログラミング言語です。
今作ろうとしているBaMaDiS用ツールは、きちんと作っていけばテキスト主体のゲームエンジンになり突き詰めればBaMaDiSそのものになる可能性が高いので、そこまでいったらオープンソースソフトとして公開しようと思っています。
その時配布しやすく使ってもらいやすかったら嬉しいし、現時点でのモチベーションにもつながります。

Ren'Pyへの潰しが効く / Pythonプログラムに変換できる環境がある。

まだ弄ってみてはいないのでどの程度使えるのかは分かっていないんですが、上のパッケージサイトにpythonに変換するものがあります。
ざっと見たところ、Racketのプログラムを、Pythonで書かれたLispであるHyに変換して更にPythonに変換するものなので、Ren'Pyで使用するアルゴリズム的なものに限って言えば、RacketとHyに習熟すれば自分でも作れそうな気がします。
つまりプログラミングで面倒なところはRacket上で書いて、ゲームとしてのGUIとか演出とかはRen'Pyで書く、という事ができるかも。

まーた夢みたいなこと言って、プログラミング自体に労力を割かないんじゃなかったのか?という声も聞こえますが、実はこんなサイトもあったりします。

これはAI技術ありき、のようですがRacketからpythonに限らずプログラムを変換してくれるサービスで、小さなプログラムレベルであれば無料で試せます。
ちなみにちょっとしたGUIプログラムを変換してみたら、ベースになるGUIプラットフォームは違うのにちゃんと動くものへ変換されました。凄い!使える!

先達がいる / 参考資料がある

Racketでゲームを作る事例をブログであげている方が複数名います。
しかも日本語!

特にこちらの記事その4はインタフェースまわりはほぼ解答が乗っているようなものなので熟読させていただく。なんならそのあとの本格的なノベルゲームのところも参考になるというか、このままゲームにはなってしまう。

こちらはちょっとRacketの記事だけを追いにくいのだが、テキストベースのRPGを作っているので更に参照できる要素大だったり。

なんなら英語だけれどRacketでゲームを作ろう!的な書籍もある。これはかの有名な"Land of Lisp"のRacket版だったり。

https://www.realmofracket.com

BaMaDiS定義Ver3

Racketについて長々と書いてしまったので、現時点で自分の目指すものを箇条書きにして今回は終わりにします。

プレイヤーが得るもの

  • プレイ感覚としてはノベル的な内容が主体のライフシミュレーションゲーム。

  • プレイヤーが楽しいと思う要素の1つ目はイベント発生とそれに対するプレヤー/NPCのアクション、およびNPCのリアクション。
    ここの楽しさはノベルゲーム的で制作者が頑張って書く/作る。

  • プレイヤーが楽しいと思う要素の2つ目はNPCの自律的行動。
    いわゆるノベルゲームと違い、プレイヤーのアクションがなくてもNPCが行動を起こす。ここはシミュレーション的。

  • プレイヤーが楽しいと思う要素の3つ目は、イベントの発生の連なりが大きなストーリーを感じさせること。
    イベントの連なりは直線的であったりランダムであったあり時系列であったりでは「なく」、イベントのネットワークが繋がりを変化させながら発生する。これがBaMaDiSの独自要素の核。

プレイ感覚を実現するためのメカニクス

  • CRT(戦闘結果表)
    全ての判定は乱数とCRTで決まる。後述のAIもCRT。

  • Card Driven
    イベントとイベントの繋がりはカードによって定義される。

  • Automa
    NPC行動はNPC独自のカードデッキで決まる。

ではまた。

この記事が気に入ったらサポートをしてみませんか?