前回、CARDインスタンスの中にクロージャと引数のリストを用意して、それをFOLDで回すことで組み合わせ自由、個数無制限のイベント処理システムが作れるのでは無いだろうか?と思いついたワケですが・・。
例えばSAでは
・戦闘を行うか?
・イベント発生に必要なアイテムを持っているか?
・持っていた場合運試しを行うか?
・運試し実行
・バトルへ
・運試し無しでバトルへ
という流れが発生します。入れ子になってる部分は引数で処理するとして(これも再考の余地ありで後述)
CARDインスタンスにF-LISTとしてクロージャをこのように入れたい
で、クロージャの数と同数の引数リストA-LISTを用意して初期値としてWORLDインスタンスを用意して、出力されたWORLDも引数として利用して・・というのをFOLDで回していくと
とりあえず実際に書式に沿った各種関数を作っていくか・・。テストなので理解しやすいようにメッセージ結合方式でやってます。Selectの場合は受ければそのままWorldを次へ回し、受けない場合は次のPlayerでメインを進めるので・・脱出になるわけだな?
次に今回の場合は所持アイテムをチェックしてイベント発生条件を満たしていれば、引数に入れてある別のクロージャや関数を呼び出して処理。持ってない場合はWorldをそのまま返す=スルー。
ちょっと引っかかるのがここでして・・引数にクロージャや関数を忍ばせるのが良いのか、それともWORLDのスロットを1つ使ってスルーさせる処理を作るのが良いのか・・今回の場合で言うと
(,select ,satisfy-item(luck? luck) ,battle-read)
と、入れ子になってるのを
(,select ,satisfy-item ,luck? ,luck ,battle-read)
と言う風にとりあえず全部のクロージャをCARDにリストとして持たせて置いて、すべてを通過させるようにするか。多分、WORLDのスロットに判定用の何かを埋めれば可能だとは思うんだよなぁ。すべてのクロージャをブロックのようにつないで動かす・・という思想からするとこっちを選ぶべきか・・?
とりあえず今回は入れ子容認で作ったのでこのままで・・。satisfy-item用の引数リストの1に'luck?が入れてあって、これをhash-refで読み込む仕組み
呼び出されたluck?にはsatisfy-itemのW Aがそのまま引き継がれるので、それを使って処理。運試しをする場合は更にLuckを呼び出す
Luckでも同じ引数を用いて成功判定。処理は更にLuck-resultに任せる。成功の場合はA-LISTの2のCAR部分、失敗の場合はCADR部分を渡す。
(0 0 0) (-3 0) #f はそれぞれ(プレイヤーの技術点、体力点、運点)(敵の技術点、体力点)(強制移動ありか?)の引数になっている
引数を元に数値を変更したPlayer Enemyのインスタンスを作って表示して新たなWORLDインスタンスを組み上げて返す、と。これが最終的なsatisfy-itemクロージャの返り値となって次の(今回は)Battle-readへと渡される、と。
メッセージ部分は・・とりあえずこんな感じで?引数をFlattenでバラして何個目が0じゃないかで処理。複数の数値変動がある場合は破綻するが、多分無いんじゃないかな?
今回不安なのはSatisfy-itemクロージャでイベント発生に必要なアイテムを持ってるかどうかをチェックする部分なので小テスト。この自作関数で・・
シンボルの場合はオッケイ
インスタンスでもオッケイ。良かった・・じゃあどうすっかなぁ・・手軽さで言えばインスタンスを直接リストするようにした方が(特に後に作る装備品からステータス変化をさせる部分では)多分楽だしなぁ・・
という事で、とりあえずインスタンスのリストにしておくことに
PLAYER-ITEMに必要なものを持たせて・・
テスト用のEval部分を書く。おお・・たったこれだけで(理屈が合ってれば)動く(はずな)のか・・
で、テスト!実はここがまた大変だった・・仕様にそって出来上がってるCARDが1つだけなので(だってテストだから)、各種関数が要求する引数やら関数を無効化しないといけなくてコードがコメントアウトの嵐!
そしてCARDインスタンスの引数として直接クロージャやインスタンスを指定しているのでコードの置き場所もBattle-readが存在するメイン部分にCARDを持ってこないといけなかったりでグチャグチャに。もしかしてこういうのを防ぐためにハッシュテーブルに登録して'キーで呼び出すようにしてるのか!?と思ったけど後の祭りで・・。まあ、テストが無事終わったらそうしよう!まだ動くか分からないんだから・・
で、テスト用WORLDインスタンス。実際はENEMIESは'()になってて、main-readの時に現在のCARDからENEMYを読み込んで次に渡す事になる、と。ではいよいよ・・実行!
よっしゃ!実験成功! ま、結果だけ書いてますからスンナリ進んでるように見えますけど実際のトコロ大変だったんですけどね(^_^;)
あと、本来は運試しの結果は技術点に影響するんですけど、技術点は表示しない設計になってるのでテスト用に体力点を変えてます。
とにかくこれでFOLDによるクロージャ連鎖システムでちゃんと動くことが分かったので、この仕様に沿った各種イベント関数を書いていけばオッケイって事だな〜。感覚的には峠を超えた感じ。
しかし懸念はクロージャ入れ子方式かクロージャオールブロック貫通方式か・・だな。ブランチ分けて一度作ってみるか・・カード作る前の今しか無いからなぁ〜