Whiteのふりーとーく

2007年10月チーネセ

About this Page |過去分一覧

_ another blog@hatena/Wiki/BBS


10.5

@抽象化とインフレーションのこと

先々月ぐらいからの念願だったEmpire Builderを先々週ぐらいだかにプレイした。先日提唱してみた仕事のトレードルールはもちろん導入してみた。

で、結果。やっぱり終盤のダレはそのままだった。

トレードルール導入が失敗とかそういう問題ではない。トレードルールによってそのへんを意識してみた結果、これは要するにゲームルールのデザインの根本からくる構造問題なんだな、ということを実感するに至った。

_最初に思い至った問題点は、「抽象化が足りない」だった。

Empire Builderのデザインには要素が多すぎる。資源の種類も多ければ、都市の数も多い。最近のドイツのボードゲーム風のデザイン作業を経たならば、どちらも半分程度に減らされることだろう。それから減らした結果に合わせてマップのサイズを決めればマップの面積も半分ぐらいになり、あとはプレイ時間も半分ぐらいになるだろう。

そのような、大胆に半分に削り落とすようなデザイン作業ができるのは、「現実の地図に基づいている」という前提を一度捨てて「ゲームルールとして適切であるか」を考慮するからだと思う。一度ゲームのルール全体を抽象化して眺めなおすことで、最適化を図ることができるというわけだ。

_その後つらつらと考えて思い至ったのは、「インフレーションのコントロールができていない」だった。序盤〜中盤にかけては「仕事をするために線路を引き、儲けた金でまた(次の仕事のための)線路を引く」というスパイラルが回る。その回転の隙間をいかに詰められるか、というあたりが差を作る要素になる。

このとき、だんだん路線が延びていくことによって、一回の仕事から得られる収益も徐々に大きくなっていく。だから、中盤までゲームは順調にインフレーションしていくことになる。ところがゲームが終盤に至ると、既存の路線だけで仕事がこなせてしまうようになる。結果、単位時間あたりに得られる収入量があるところで上限に張り付いてしまうのではないか。

しかしそれが張り付くのは困る。序盤〜中盤にできた差が、累加的に蓄積されているからだ。この差を埋めるためには、「もっと収入量を増やす」ことができないといけない。しかしEmpire Builderにはそのための手段が存在しない。負けているものがリスク覚悟で選ぶ手段に欠ける。

しかもメカニズム的に他のプレイヤーとの直接的なインタラクションにも乏しい。ということで差を作っていく段階(序盤〜中盤)は面白いのだが、そこでできた差を単に並行するだけとなる終盤は詰まらない、という状況に陥るわけだ。

_いっそ速度36だが搭載量1の列車とか、速度6だが搭載量6の列車とか、そういう阿呆な選択肢を用意するのはどうだろう、とか思ってみた。多分試さない。

+comment(5) +trackback(0)


10.12

@仕事:ポポポインタに悩む

BREWへのフレームワークの移植作業をしていたら、ポインタのポインタのポインタが必要そうな場面に遭遇。

元がJavaでVectorにObjectの配列を突っ込むという実装なうえ、どうせObjectを突っ込んでいるのだからとばかりに実に野放図な使い方をしまくった(Objectを入れるところにはObject[]も入れられる!)ので同等の機能を確保するのにはそれなりに手をかけてやる必要がある。

JavaのときにはObject型という便利な概念があったというだけで、そういう便利な概念がないC++ならObject型から始まる継承ツリーに相当するものを自前でコーディングすればいいだけだ……と書くだけでひどくがっかりしてくるのは何故だ。

_この問題を更にがっかりな感じにさせる事実に、これが特定のUIウィジェットの実装の問題として出てきているという点がある。

具体的に作っているのはHTMLのテーブルみたいなのを実現するためのウィジェットなのだが、ウィジェットとしてLabel(文字を表示する)とかが既にあるのに、テーブル内部用にLabelに酷似した「テーブル内文字列」とか「テーブル内整数」みたいなクラスを作ることになる。その、ウィジェット内ウィジェット、あるいはアプリ内アプリ、みたいな対称性の崩れた入れ子構造を作りこむ羽目になるのがなんともダサい。しかしそのダサさを解消しようとすると複雑すぎてわけわからん実装になる。自分の趣味ならともかく他人にも使わせるフレームワークでそれはありえない。

_ということでポインタのポインタのポインタという話に戻る。できれば扱わせたくないこのデータ構造を、どうやって上手く包んでやるか、というあたりが目先で最大の仕事になる……はず。しかもこのTableを継承することになるクラスも多い予定なので、それが更に問題をややこしくする。今回の仕事の最大のポイントだろうなあ、これ。

+comment(0) +trackback(97)


10.15

@仕事:ポポポインタに悩んでいる。

とりあえずのところ清く正しく(?)Table -> TableData -> TableRow -> TableCell という参照構造のオブジェクト群を作ってみた。TableとTableDataを一体化してないのは移植元におけるTableの継承クラスに標準のTableとは異なるデータ構造を持つ奴がいたから。いちおう分割しておけばポリモーフィズムが使えるかなという淡い期待。そしてVectorなど使わずTableのインスタンス生成時に(最大)row数とcolumn数を指定して配下インスタンスを全部こしらえるというダサいがメモリ管理に優しい方針で。

Tableに出すものはおおむね通信の結果得られるものだが、通信して結果を得るのたびにメモリ割り当てをしたりするとメモリのフラグメンテーションが大変ひどいことになる。そしてBREWの駆動モデルではそういう状態になるとシステム全体を巻き込んでくれやがる。そのへんiアプリではJavaであることで大きな恩恵を受けていたのだなあ。明らかにVMがメモリリークしてる機種もあったけれど。

_ということで素組みしてコンパイルは通るようにしたが本当にこれでいいのかはまだわからない。メモリ管理機構への優しさを考えるならば、TableRowなぞ削ってTableDataで直接TableCellの管理をした方がいいような気もする。素直に組んだ場合のデストラクタ呼び出しチェーンとか考えると特に。終了処理だって1秒を要求されるのであろうから。あるいはTableCellManagerなんてのを作ってそこから割り当てを受けるみたいな機構とかか。

本当に至る所で「1秒」が鎌首をもたげてくる。SandBoxなしにダイレクトに駆動させるモデルの弊害……というか弊害の方が多すぎるような気がしてならない。なんでOSでプロセスかなんかで分けねえんだよ。たぶんプロセスをボコボコ起こすって概念がOSの側にないんだろうなあ。規格を作った時期を考えれば現実的な回答だったのだろうが、今となってはその現実性が足を引っ張っているのだろう。将来性だけはバッチリだったJavaとはそりゃあ差がついて行くであろうて。

+comment(0) +trackback(143)


御意見・御感想の宛先white@niu.ne.jp