Diary?::2009-12

2009-12-01
Tue

(22:03)

とりあえずメモ代わりに、 Scribblenauts で獲得できる Merit とその入手方法(ほぼ推測)を書いてみる。とりあえず俺が確認したのはこのあたり。

5th Cell
5th Cell の社員を出現させる(これはクレジットを見ればわかる)
All New
新規オブジェクトのみでクリア
Closet
衣類を二つ以上出現させる
Electrolysis
キャラクターを感電させる
Pyromaniac
四つ以上のオブジェクトに火を付ける
Firefighter
二つ以上のオブジェクトに火を付ける
No Weapons
武器を使わない。 Tool の類で撲殺する分には OK?
New Object
新規のオブジェクトを出現させる
Zoo Keeper
動物を二体以上出現させる
Genius
同一ステージを2回クリアすればいいらしい
Prodigy
同一ステージを3回クリアすればいいらしい
Savior
人間と動物を計二体以上生存させてクリア
Jockey
馬などに乗ってクリア
Exterminator
殺害可能なターゲットを(多分必要もないのに)全滅させる
Roped In
ロープの類を複数出現させる
Tooling Around
Tool を複数出現させる
Miner 49er
Shovel で掘りまくってるともらえる
Humanitarian
人間を二人以上出現させる
Mechanic
壊れた機械の修理。 3-2 クリアで普通にもらえる
Bioterrorist
毒物を使ってクリアするともらえる。 4-2 が狙い目
Chef
二つ以上の食べ物を出現させる
Elemental
一つ以上の Element を出現させる
Smasher
近接武器を複数出現させる
Ornithologist
鳥を二体以上出現させる
Clutton
食料を三回与える

現状ワールド3までクリアしてみたが、本当にステージによっては無茶苦茶なクリア方法がある。例えばワールド2のとあるステージは、ハロウィンの仮装をしてきた子供たちに何かを与えてクリアなのだが、お菓子を与えてクリアの他に地面に転がってるカボチャを投げつけて追っ払ってもいいとか、いくら何でもフリーダム過ぎる。

追記:Option から既に取得した Merit については確認できた……

2009-12-03
Thu

(23:20)

「ブラック会社に勤めてるんだが、もう俺は限界かもしれない」が大変なクソ映画と聞いたが、まああれは元スレからして「これは転職だなー」「その前にデカいトラブルが欲しいなー」とドス黒い期待をしながら読んでいたら「俺、まだ頑張れるよ!」という反吐の出る結末で、あれそのまま映画化したらブラック肯定映画にしかならねーだろ(あとまさかと思うけどみんなアレ実話とか思ってる? いや実際にあっても不思議じゃない部分がないわけじゃないが)。

だからそれへのカウンターとして「ブラック会社に勤めてたんだが、もう俺は転職した」があってもいいんじゃねえのと思う。主人公がブラック会社で成長したりとかそんなのはなく、ただただ鬱屈していって最後に会社を辞めて終わりという結末の奴。出来れば「長時間労働は体を壊す」「理不尽過ぎる業務は心を壊す」というブラックな職場の双璧を為すブラック業務(+それらが融合したブラック業務完全体)を描くのが望ましい。

特に重要なのは後者で、俺は SI 業界において社員の精神衛生が取り沙汰される現場は開発規約やそもそもの業務内容が(とりわけできる人にとって)我慢ならないクソな事が多く、そのストレスが精神を病む最大の原因だと睨んでる。実際問題、俺は業務内容が極めて退屈でそれが俺にとっても会社にとっても意味のないものだったとき、ほぼ毎日定時帰りだったけど精神的にはその前のデスマーチプロジェクトの時並に悪化してたからな。

というわけで俺はリアル「ブラック会社に勤めてたんだが、もう俺は転職した」なのだが、実は俺の日記のウケのいいネタって SI 業界残酷物語なんだよなー。もう半年近く殆ど書いてないし、俺はもう SI 業界から脱出したんでこれ以上何も書くことはないんだが。

2009-12-04
Fri

(13:06)

一昨日あたりから XO 醤を調味料に使い始めてみたんだが(といっても600円ぐらいで売ってる奴)、どうも俺の味付けの仕方がまずいのか鶏ガラと醤油とかの方がおいしくできる気がする。いや、俺の味覚がジャンク極まりないという可能性もあるか。

2009-12-06
Sun

(22:09)

Scribblenauts は全 10 ワールドのうち 9 ワールド目までクリアした。一つ一つのステージが閃き勝負で非常に短く、またクリアすればするほどゲームに必要な語彙と組み合わせが蓄積されていくので、とにかくテンポよく進められる。というわけで、オールクリア前だけどまとめの感想を書く。

前に書いたとおり、このゲームではクリアのために必要なオブジェクトはプレイヤーが自由に出現させる方式なのだが、プレイしていくうちに大まかな組み合わせのセオリー・パターンが見えてくる。例えば敵を全滅させるなら不死身の Vampire や Blob に始末させ、落とし穴回避には Pegasus か Roc に乗り込み、 Starite 自体を移動させるのに Airvent や各種の動物 + Rope など。なので単にステージをクリアするだけなら簡単なケースも結構ある。新たなワールドはステージクリア時にもらえる Ollar というゲーム内通貨で購入するのだが、それほど金額が高くない上にステージを順繰りにクリアする必要もないので、クリアできるステージだけ一通り遊ぶということもできる。そのため、あるステージで詰まってそれ以上進めないという事は起こりにくいだろう。

ところで単にクリアするだけなら簡単でも、一旦クリアしたステージに再度挑むときは勝手が違う。一旦クリアしたステージは次に挑むときに Advance モードとなり、そのモードでは連続で三回クリアしなければならなくなる。またその時は同一の言葉を連続で使えなくなるので、例えば最初のトライで Sword を使ったら、二回目と三回目では Sword が使えなくなる。ワンパターンなプレイをしていると Advance では詰まること必至だ。俺は大体 6 割前後のステージで Advance クリアはしたが、クリアするためのアプローチを根本的に変えなければならないことも結構あった。

一方で気になったのは操作性で、タッチペン操作故の融通の効かなさはやはり存在する。とはいえ十字キーも ABXY ボタンも視点移動にアサインされているので仕方がなく、また自キャラの精緻な操作ができないが故にオブジェクトの配置やタイミングの調整が重視されたゲーム性になっているとも言える。あと前述のとおり単にクリアするだけならわずかなバリエーションのアイテムだけで済んでしまうケースが多々あるので、そこからさらに Advance にチャレンジしたりネタ的なクリアを模索したりとしない人にはちと途中でマンネリになるかもしれない。

ちなみにそのネタ的なクリア方法の探索を始めると大変なカオスになるというか、、画面内のオブジェクトを全部ぶっ壊すステージを核ミサイルや洪水や隕石を召喚して超出オチクリアしたり、殺害可能なターゲットを可能な限り集約して機雷でぶっ飛ばしたり(注:大抵のステージではターゲットを殺害する必要はない。が、皆殺しにすると Exterminator の Merit が貰えるんだよなあ)、釣り竿の先に人参ぶら下げて馬に乗ってみたり、爆発物から Starite を守るのにわざわざ人間を出現させて肉の壁にしてみたり、手榴弾や TNT を一定間隔で設置して誘爆させてみたり、もう収拾がつかない。ハロウィンの仮装した子供たちにお菓子を与えるステージで、そこらに落ちてるジャック・オ・ランタンを投げつけて追っ払ってクリアできたときは笑いが止まらなかった。

まず間違いなく日本語版が出ないというか出しようがないのがアレだが、英語版でも問題ないぜという人には本当にお勧めだ。

2009-12-07
Mon

(16:31)

檜山さんがおもくそ先走って JSON ストレージの話を始めたので、ある意味で元凶たる俺も JSON ストレージの話をする。で、 JSON ストレージがどんなものかは檜山さんのエントリに書いてあるので、ここではどうやって JSON ストレージを実装するかの話ね(実は現在リリースしているバージョンにも JSON ストレージは同梱されているのだが、ぶっちゃけリリース2の作業の息抜きに半日ぐらいで作った代物なので、まあ参考にしたい人は参考にしてください程度の出来だ)。

基本的に JSON ストレージはバックエンド中立なライブラリで、例えば RDB をバックエンドに使ってもいいし普通のファイルに書き込んでしまってもいい。が、ひとまずは RDB を前提として話を進める。あとわかってると思うけど JSON スキーマの構文は標準として提案されてるものではなく Caty 構文を採用する。

JSON のようなデータを RDB に永続化する場合、大雑把に分けると構造写像とモデル写像の二つのアプローチがある。元々はどちらも XML を永続化するためのものだったと思うだが、入れ子構造の正規化されていないデータをそのまま永続化という意味では JSON も同じなので、ここから JSON を永続化する手段を模索する事にする。

二つのアプローチのうち簡単なのは構造写像で、これはプロパティ名=カラム名のテーブルにデータを永続化する手法だ。例えば以下のような JSON スキーマがあったとしたら

type person = object {
    "name": string,
    "birth": integer,
    "job": string | null,
};
//データ例
{
    "name": "鍬田力",
    "birth": 1984,
    "job": "プログラマ"
}

追記:クォーティングし忘れてたところを修正。

以下のようなテーブルを作成する。ここでの id はシステマティックに自動生成される人工キーとする。

|  id| name|birth|     job|
|0001|鍬田力|   25|プログラマ|

一見するとこのアプローチは上手く行きそうだが、次のような入れ子構造やリスト構造が入るとサブテーブルを作らなければならないのがネックだ。サブテーブルが入ると相関サブクエリと外部キーの嵐となり、わかりやすさが激減する。

type person = object {
    "name": string,
    "birth": integer,
    "job": string | null,
    "contacts": list [object {
        "kind": string,
        "address": string
    }]
};
//データ例
{
    "name": "鍬田力",
    "birth": 1984,
    "job": "プログラマ",
    "contacts": [
        {
            "kind": "website",
            "address": "http://return0.dyndns.org"
        },
        {
            "kind": "twitter",
            "address": "http://twitter.com/ckuwata"
        }
    ]
}

もう一つのモデル写像は次のようなテーブル構造に永続化するアプローチで、こちらは入れ子やリストを上手く扱える。

|  id| pid| ref| colname|   value|
|0001|0001|null|    null|    null|
|0001|null|0001|    name|   鍬田力|
|0001|null|0001|   birth|    1984|
|0001|null|0001|     job|プログラマ|
|0001|0002|0001|contacts|    null|
|0001|0003|0002|       0|    null|
|0001|null|0003|    kind| website|
|0001|null|0003| address|  (略) |
|0001|0004|0002|       1|    null|
|0001|null|0004|    kind| twitter|
|0001|null|0004| address|  (略) |

ここでの id は論理的なレコードでユニークな値となる。また pid は null でなければ子要素を持っていることとなり、子要素は親要素を ref で参照する。実際のプロパティ名と値は colname と value に格納される。また、 colname が整数値のみのときはリストという規約にする。

このアプローチの欠点はテーブルを見ただけでは何が格納されてるのかさっぱりわからず、またクエリを発行すると鬼のような自己相関サブクエリの嵐になってこれまたわかりにくい(=デバッグが困難なものになる)。おそらく、事情を知らない第三者がみたら卒倒するだろう。ちなみに現在の仮実装は殆どこのアプローチをそのまま使っていて、その理由は複数テーブルにまたがる相関サブクエリとか発行するライブラリ書くなら自己相関サブクエリを打ちまくるライブラリを書く方がなんぼかマシだと思ったからだ。

そしてもう一つ、実装が終わってから思いついたというか気がついたアプローチがある。元々 SQL で木構造を扱うための手法に経路列挙モデルというものがあるが、これの応用だ。このアプローチなら、先のスキーマとデータを以下のように格納できる。

|  id|                path|   value|
|0001|              $.name|   鍬田力|
|0001|             $.birth|    1984|
|0001|               $.job|プログラマ|
|0001|   $.contacts.0.kind| website|
|0001|$.contacts.0.address|  (略) |
|0001|   $.contacts.1.kind| twitter|
|0001|$.contacts.1.address|  (略) |

Caty では JSON パス式というものを実装しており、例えば先のデータの「contacts の 0 番めのインデックスの kind の値」を "$.contacts.0.kind" のように表現するのだが、これはそのまま RDB に格納する時のパス名として使うこともできる。加えてオブジェクトを永続化する手続きだけでなく永続化された情報を元に戻す処理も素朴なモデル写像よりはだいぶ簡単なものになる。

というわけで、正式版の JSON ストレージはこのアプローチで作ることになると思う。まだ他のバックエンドに永続化するための手法はまだ考えていないが、まあそっちはおいおいやっていくということで。

(19:56)

今日の晩飯は鳥団子鍋。作り方は前に書いたとおり。あと鍋物やった後は残り汁でおじやかうどんが鉄板だけど、今日は醤油と塩と調理酒入れて軽く煮立てて、ご飯にかけて出汁茶漬け風にしてみた。これはこれでいける。

2009-12-08
Tue

(23:10)

Wizardry 生命の楔」が届いたんで遊んでる。まだまだ序盤なんで詳細な感想は控えておく。まあちょっとだけ書くなら、固定主人公とかそれ Wiz でやる意味あんのってところか。あとキャラグラフィックとか別にいらなくねとか。しかしゲーム単体での出来云々以前に「正統派」だの「古典的」だのと宣伝されて出てきた結果がこれじゃ、そりゃ思い入れの強いオールドファンは激怒するだろうと思う(俺はそうじゃないので激怒には至らず)。無茶苦茶な喩えをさせてもらうと、 Metallica が「原点回帰して作った作品だ」とかいって出てきたアルバムが Load/Reload の続編だったら出来が云々以前の問題だろう。

何となく最近のダンジョン RPG のファンにアピールしつつ、オールドファンもターゲットにしたのかなとか思うわけだけど、それにしちゃ流通が Amazon のみなのが不可解。いや、逆に Amazon のみの方が好都合だったのか? この辺の事情は疎いんでよく分からん。しかし間違いなくストイックなイメージのある Wizardry をこういう風に弄くったところで、オールドファンは怒り出すだろうし最近のゲーマーがどんだけ手を出すかも怪しいものだ。マジでどういう経緯で世に出たんだこのゲーム。

2009-12-09
Wed

(23:49)

Caty リリース 4 の作業をしつつその後のバージョンに入れる機能の開発とかやってるわけだが、リリース 5 は JSON ストレージの他に RPC アプリケーションも同梱しようかと思ってる。クライアントサイドで JavaScript 使って入力値の検証するときとかに便利そうじゃん。まあそっちの方は実は全然たいした作業じゃなさげなのでいいとして、問題は JSON ストレージだ。いや、基本的な部分はもう実装してるんだが、クエリの組み立てが前のやり方よりはシンプルとはいえちと複雑だからな。今は次のようなクエリが動く程度。

strg:create-table person //person 型に対して person テーブルを作成
{"name": "鍬田 力", "job": "プログラマー"} | strg:insert person // 挿入
{"name": "鍬田 力"} | strg:select person // 検索

早く次のような検索クエリを投げられるようにしたい。

{"name": @_LIKE "鍬田 %"} | strg:select person // ワイルドカードで検索
{"job": @_OR ["プログラマー", "Web デザイナー", "コンサルタント"]} 
    | strg:select person // どれか一つに一致

ちなみに Python 側の API はおおよそ次のような感じになる。

# storage は JSON ストレージへのアクセッサ
storage.insert({"name": "鍬田 力", "job": "プログラマー"})
storage.select({"name": like("鍬田 %")})
storage.select({"job": _or(["プログラマー", "Web デザイナー", "コンサルタント"])})

できれば今週中にこれは完成させたいなー。

2009-12-11
Fri

(23:33)

Caty は何度か書いてるとおりデフォルトで HTML 特殊文字のエスケープを行うのだが、流石にもうそれを余計なお世話とか言い出すダメエンジニアに関しては「死ね」と返していいよな。そもそも今後の予定として、セッションやファイルなどにデータを書き込む処理を検出してある種の脆弱性(例えば CSRF など)への対策を示唆するメッセージと手法を表示するとか、そういうのも考えているんだが。 Caty スクリプトで使われるコマンドはすべて独自の型宣言を持っており、ファイルなどへの書き込みを行うかどうかをその宣言から判断できるので、そういった処理の作成者にユーザ認証やトークンチェックをするようアドバイスするのは十分可能なはずだ。

これは汎用的に使えるセキュリティ対策コマンド群(セッション ID の埋め込みコマンドと Cookie の値との照合コマンド)を用意すれば割と実用的になりそうだ。あとセッション ID の埋め込みと照合コマンドを使えば、 CSRF などに関してはスクリプトの入力の型からパイプライン全体がセキュアかどうか判断できる。

実際には次のような使い方になるんじゃなかろうか。

//入力フォームの出力
some_command | print form.html | add_session_id
 
//入力を受け取る側
translate SomeInputType & SessionToken | when {
    OK => check_token  | when {
        OK => //以降はファイルなどへの書き込み処理
        NG => //未ログインとみなしてログインページにリダイレクトとか、まあ適宜適切な処理を
    },
    NG => //入力エラー処理
}

SessionToken は例えばこんな型。

type SessionToken = object {
    "sessionID": string
};

この時 check_token の型は SomeInputType & SessionToken -> @OK SomeInputType | @NG ErrorInfo に推論できる。あるいは translate 自体にチェック機構を入れてしまってもいいかもしれない。まあこのあたりのやり方はいろいろあるので、一番ユーザの負担にならなそうなやり方を模索するか。あと俺が実装を頑張って translate も型推論させれば、次のようになる。

translate | when {
    OK => check_token | when {
        OK => //以降はファイルなどへの書き込み処理
        NG => //未ログインとみなしてログインページにリダイレクトとか、まあ適宜適切な処理を
    },
    NG => //入力エラー処理
}

この時推論の一部の流れを切り取ると、

  1. 2番目の when 節の入力型が @OK X | @NG ErrorInfo となる。ここで X は正常処理の型とする
  2. check_token の型は _T & SessionToken -> @OK _T | @NG ErrorInfo で、 _T が X となる
  3. translate の型は WebInput -> X & SessionToken に推論される

って感じかなあ。まあどこまでやるか、そもそも本当にできるか、できたとして穴は無いか、穴がある場合にどのような対策をユーザに取ってもらうかなど、考えるべき事は腐るほどあるんだが。

2009-12-12
Sat

(22:43)

今日は層圏トポス勉強会だった。レギュラーメンバー2名を C++ 軍団に拉致されつつも開催したのだが、よりによってそんな時にちょっと気になる問題が。テキストの第二版あとがきで p20 の証明における同値関係の定義に誤りがあることが書かれており、またその証明に対する補足説明もあったのだが、そこで出てきた中間層の定義がその問題。

ある前層が「Ef∩Eg⊂[f=g]ならばfとgは両立」であれば中間層となるというのだが、今日の勉強会でどうも前層は全部中間層になっちゃうんじゃないかという疑問が出された。それはつまり常に「Ef∩Eg⊂[f=g]ならばfとgは両立」なんじゃないのということ。それで今しがたちょっと調べてみたのだが、まずそもそも中間層という概念自体が全然出てこなくて早くも挫折。というか層について英語版の Wikipedia とかにあたってみると、かなり圏論と絡んだ説明になっている。どうもこの辺はまず先に進んでみて、もうちょっと層についての理解を深めてから考え直した方が良さげ。

追記:hirataraさんよりツッコミ。http://twitter.com/hiratara/status/6601497329

@ckuwata 単純に、「公理系から導けない」ってことでいいんじゃないかって気がします。連続関数とか制限とか定義域ってのを考える必要はまったくないというか、むしろ考えてはいけないんじゃないかと・・・。

言われてみればその通りですね。

2009-12-13
Sun

(21:06)

Wizardry 生命の楔は現在 B10F をクリア、パーティの平均レベルは 20 弱というところだが、現時点での感想としてはとても微妙だ。少し前に遊んでた幻ノ塔ト剣ノ掟も戦闘バランスを考えた奴の正気を疑う出来だったが、生命の楔も戦闘バランスは結構問題点が多い。

何が問題かって、敵が最大 27 体まで同時に殴りかかってくる上に AC による回避率上昇がそれほど大きくないので、たかが雑魚相手でも HP 200 近い戦士が 1 ターンで半分以上削られるとかいう事態がよく起こる。じゃあ先手を打って敵を倒せるかというとどうも行動順がランダムすぎるきらいがあり、こっちが一度も攻撃しないうちに敵に 10 体ぐらい連続で行動される可能性もある。

というわけで今現在の感想としてはちと徒労感の方が大きい感じ。あからさまな手抜きがされてる感じはしないし、むしろ作り込まれているとは思うんだが……。でもどうにも好意的な感想を抱きにくい。

2009-12-15
Tue

(23:25)

無事にバグフィックスリリースもされたようなので、とりあえず Caty の次のリリースで実装したい機能及び変更したい部分などについてその一部を箇条書きに。

  • コマンドの実装方法を変える(後方互換性なし)。今までのやり方だと主に translate コマンドを筆頭とした型変数を持つコマンドに不都合なので
  • 型推論は……間に合うかなあ。なるべく早く実装して、http://return0.dyndns.org/log/2009/12/11#s_1で書いた機能を追加したい
  • JSON ストレージは入ります
  • Smarty 記法のテンプレートが今まで以上にオリジナルとコンパチに

書ききれないのでこんぐらいで。

2009-12-16
Wed

(23:33)

さて、ここで適当な HTML テンプレートエンジンを考えてみる。とりあえず文法は Smarty っぽくこんな感じで。

<p><a href="{$url}">{$text}</a></p>

ここでテンプレートのプレースホルダーはすべて自動的に HTML 特殊文字をエスケープするものとする。それでも url の値がソーシャルブックマークなど、ユーザの投稿によるものだとすると、ここに javascript:alert("fuck you") とか入力されると、出力は以下のようになる。

<p><a href="javascript:alert(&quot;fuck you&quot;)">...</a></p>

勿論これは入力時に validator で弾くべきものなのだが、とりあえず以下のような仕様のフィルターを噛ませるとする。

  • スキームが http or https は受け付ける
  • 同一サイト内へのリンクも受け付ける
  • それ以外は全部弾いて変わりにエラーメッセージを出力する

これを validate_link フィルターと呼ぶことにすると、先のテンプレートは次のように記述できる。

<p><a href="{$url|validate_link}">{$text}</a></p>

手間はかかるが、こちらの方が安全ではある。問題はその手間及び確認コストで、サイト内で使われるあらゆるテンプレートを目視で確認して適切なエスケープが行われているのかチェックするのはぶっちゃけ無理、どう考えても漏れが出る。そして

  • 入力値の検証に穴があって
  • 出力値のエスケープに冒頭のような穴がある

というケースが発生すると、当然これは脆弱性に繋がりうる。

じゃあこの問題はどうするべきなのかだが、ここでテンプレート言語は HTML への値埋め込みなので、普通に HTML 文書として解析可能だ。つまり、 href や src などのいたずらされるとマズい属性の値がテンプレートのプレースホルダーかどうかはわかるはず。なので理屈の上ではテンプレートを静的に解析して単なる特殊文字のエスケープ以外の処理が必要かどうかチェックするプログラムを書くのは不可能ではない。

……そう、不可能ではない。不可能ではないんだが、複数のテンプレート言語をサポートすると、ある属性の値がプレースホルダーかどうか判定するのがやや厳しい。一応、個々のテンプレート言語の構文解析器を工夫して作ればどうにかなりそうではあるが。でもこれどんだけやる価値があるんだろうか。何よりこういうのは言い出したらキリがないし。

2009-12-19
Sat

(20:48)

「Wizardry 生命の楔(以下、生命の楔)」を表ボスまでクリアしたので感想を書く。遊び終えた感想としては、ぶっちゃけこれは「JRPG 風ダンジョン RPG」。

まずこの生命の楔は基本的に作りは丁寧で、また工夫されたシステムにはなっている。特に序盤のチュートリアルの親切さ加減はダンジョン RPG 初心者にも安心な作りで、シナリオキャラの初期レベルが多少あることから最初は戦闘もキツくなく、序盤のレベルデザインとしては割といいとは思う。戦闘システムもスキルと呪文の連携を入れたり、特定条件で戦闘後の宝箱が高品質になるミッションバトルなど、長丁場の探索に彩りを加える仕組みになっている。

ダンジョンの仕掛けもなかなかやりごたえがある。オートマッピングで形骸化したと思われる回転床トラップを他のトラップ(飛来する火の玉とか)に引っ掛けるための足止めに使ったり、松明を掲げられるダークゾーンに何の意味があるんじゃと思わせておいて「ダークゾーン + 針山」のようなトラップを仕掛けるなど、漫然と作ったわけじゃない事がよく分かる。

なのだが、

  • ダンジョンの仕掛けがリアルタイムなのに戦闘がターン制なので、「追いかけてくるゴーレムが戦闘中はダルマさんが転んだ状態」「フロアの水没が戦闘中は一時停止」などといった事態になる
  • キャラメイクはできるものの、シナリオキャラがパーティにいないけどくっついて回る仕様のため、イベントシーンで自分で作ったキャラとシナリオキャラの間に深い溝が感じられて微妙に萎える
  • 自作キャラ用のグラフィックのバリエーションが種族×性別の数しかなく、さらに人間の男なら侍など、特定職業を想起させるグラフィックになっている
  • 連携の発動が結構シビアなうえにパターンを探す必要性があるが、呪文もスキルもレベル別回数制のために試行錯誤を効率よく行えない
  • 敵の出現数が最大3列×9体と多い上にその全員が前衛に攻撃可能。一方でこちらは敵の各列の先頭にしか単体攻撃を行えないなど、微妙にアンフェアかつ大雑把
  • ダンジョンがリアルタイムにぬるぬる動くのに合わせてか、戦闘後の宝箱を開けるときにもいちいちアニメーションする。これがテンポをかなり損なっている
  • というか全面的にレスポンスがやや悪い
  • 微妙に不親切なインターフェース。呪文書を買うときに既に覚えてるキャラがわからないとか、スキルのセット方法とか

とまあ、個々の要素は悪くないどころかいいものもあったりするのだが、組み合わさった結果がなんとも違和感のある代物で、これが気になり出すと実に気になる。決してクソゲーではないし、ダンジョン RPG の入門編としては割といいと思う。

で、こっから先は完全に俺の憶測というか殆ど陰謀論のような話なので話半分にすら聞かなくていいんだけど、これ元々はオリジナルのダンジョン RPG だったんじゃねえの?

いや、本当にこれは憶測でしかないんだけど、 JRPG 的なストーリー主導の展開とかどう考えてもオリジナルの企画があったとしか思えない。そんなことして Wiz の名前で売ったら、間違いなく古参ユーザーの逆鱗に触れるだろうに。

あと俺が先に挙げたナンダカナーと思ったポイントは

  • キャラメイクを取っ払って
  • 呪文とスキルをレベル別回数制ではなく MP 制にして
  • ってかもう完全に Wiz っぽい部分取っ払う

というステップを踏むと、リアルタイムダンジョンとターン制バトルの食い合わせの悪さ以外のいろんな問題が解決しそうな気がする。というかそれも「あと何ターンでゴーレムに捕まる」とか「数ターンすると飛来した火の玉が戦闘中に炸裂」という手段で回避できるだろうしなあ。

完全に陰謀論の世界に入らせてもらうと、これ元々あったダンジョン RPG の企画にどこぞの版権ゴロが関わっちゃったせいで Wizardry Renaissance に組み込まれる事になって、それでいろいろゴタゴタがあって未調整な部分ができちゃったんじゃないの? いや、そう考えると

  • 途中で加入すると思ったら加入せずじまいの某ビショップキャラ
    • ビショップだけがシナリオキャラの加入なしでバランス悪い
  • 細かなターゲッティングのできない戦闘システム
  • リアルタイムなダンジョンの仕掛けとターン制コマンドバトルのギャップ
  • レスポンスとインターフェースの不備

などといった他の造り込みを感じる部分とえらいことギャップを感じる部分が「摺り合わせとリスケジュールの余裕がなかった」ということで俺は多いに納得できるんだが。

Wizardry Renaissance は PS3 でもダウンロード販売専用のタイトルを展開してるらしく、俺は PS3 持ってないのでそっちがどうなってるかわからないが、同じ企画の下の関連商品のくせして全然関連性の感じられない代物になっていたとしたら、この憶測がビンゴの可能性の目が出てきてしまうのだが実際のところどうなんだろう。


で、結局生命の楔は面白かったのかと聞かれると、いや決して物は悪くないよ? ただなんというか、宣伝にあるような「原点回帰」みたいな煽り文句は完全に嘘っぱちで、さらにゲーム本編も気になり出したら気になってしょうがない瑕疵があるというか。その辺があんまり気にならなそうなら、なかなか遊びごたえのある佳作だとは思う。

あとクリア後ダンジョンの見てくれが世界樹Iの第6階層それと酷似してるんだが、あれはいいのか?

2009-12-20
Sun

(23:55)

生命の楔やってて最終ワールドで止まっていた Scribblenauts を今しがたクリアしたが、何というか Puzzle も Action も最終ステージがある意味で神だった。ストーリーも世界観もへったくれもないゲームで、単純にゲームシステムとレベルデザインの妙だけで清々しい終わりを演出するとは。開発者が本当にゲームが好きなのが伝わってくる。

こりゃ今年の俺的ベストゲームはこれで決まりだな。

2009-12-21
Mon

(23:21)

ここ最近は広げまくった風呂敷をどうやって畳もうかということで頭を抱えているのだが、もっとも最近広げた風呂敷である「Caty:サイトのハイパーリンク構造を把握する」と「url=http://d.hatena.ne.jp/m-hiyama/20091221/1261354438]Catyの新スキーマ言語と型システムの必要性[/url]」についてちょっと補足。

檜山さんの記事ではハイパーリンクに話題を絞っているが、これはまったく同様にフォームからの送信についてもその構造を把握可能となる。そして新しいスキーマ言語の記事で言及されているフォームとスキーマの関連付けを合わせるとどうなるかというと、これはもう実際にアプリケーションを動かすまでもなく、送信フォームとその先の処理の齟齬が発見できるということになる。ということはだな、11日の日記で書いた機能なんかは「フォームにリクエストトークンがあるけど受取側でスルーしてる」とか、「受取側でトークンチェックしてるのにフォームにトークンが埋め込まれてない」ってのが静的に解析できるようになるわけだ。

まあ、この辺の機能はまだ欠片たりとも実装していないんで、実際にお披露目出来るのは一体いつのリリースになることやら。

2009-12-24
Thu

(20:39)

実に久しぶりの料理日記。いや、マジでネタ切れだったんだよここしばらく。で、今日の料理は肉と野菜の辛味噌炒め。いつもは野菜炒めの類は鶏ガラで味付けをしてるが、今日は豆板醤と甜麺醤で味付けしてみた。材料は細切れの豚肉 120g に野菜を適当(今回はせりとキャベツともやしと玉ねぎ)、豆板醤は小さじ一杯、甜麺醤は小さじ二杯ぐらい。あ、いつもの通りこれで二食分な。まずはフライパンで甜麺醤と豆板醤を加熱して、そこに豚肉を突っ込んで炒める。肉に火が通ったら、野菜を加えてあとは塩胡椒と醤油で味を整える。

2009-12-25
Fri

(23:01)

まともなゲーマーであれば、恐らく今週発売されたゲームではゼルダの伝説が鉄板なのだろうが、俺はまともであるという自信がないのでコロぱたを買ってきた。自律的に動くキャラが目的地に到達したりするのをサポートするというゲームなのだが、想像以上に凄い。何が凄いって、難しさが凄い。これは百聞は一見に如かずなので、是非ともプレイ動画を見てもらいたい。

これは最序盤の難所である8面なのだが、このステージは投げた鉄球がバケツに入るとクリアとなる。当然飛距離が足りないので、初期配置+プレイヤーの配置する三つの磁石で距離を稼ぐことになる。上記の動画は成功例なので、次に失敗例を見てもらいたい。

最左の磁石を1グリッドだけずらしたらこうなった。いいか、1グリッドだぞ、磁石一個分とか人間1キャラ分じゃなくて、1グリッドだ。このゲームはとにかく1グリッドのずれが生死を分けるステージばかりで、それも個々のオブジェクトに適用される演算の関係上、その1グリッドのずれ(=僅かな初期状態のぶれ)が思わぬ結果をもたらすというカオス極まりない調整がなされている。

そのためステージクリアまでには

  1. どうすればクリアできるのか、仮説を立てる
  2. 仮説に基づいて延々とオブジェクトの設置位置の調整を行う
  3. どうしてもダメだったら仮説を破棄して別の仮説を試す

という過程を繰り返すことになるのだが、これが本当に大変だ。

こちらは別の失敗例だが、この時は「一旦上方向に引き上げてから下に設置した磁石で落として加速度をつけ、最後の磁石の磁力をギリギリ振り切らせて落とす」というアプローチでやった。結果としてちゃんとブロック塀を越えてバケツのところに落ちるまでは到達したのだが、残念な事にバケツのへりに引っかかってクリアならず。これの調整に一体何十分かけたことやら。最終的にこのステージには一時間ぐらいかかったと思う。

というわけでこのゲームは児童向けのデザインがされてるわりにゲーム自体の難度調整はもの凄いハードコアな方向に振り切れており、これはマジで投げる奴が続出しそうだ。特に難度を上昇させているのがトライアンドエラーをひたすら繰り返すところで、多分このゲームはステージごとに正解とされるパラメータの幅がそれほど広くない。というかプレイヤーが調整できるパラメータの幅に対して正解の幅がかなり狭く、対してステージクリアのためのアプローチの幅は全体的にほどほどの広さといった具合か。

これは前まで遊んでいた Scribblenauts とはまるで逆で、あっちはアプローチの幅を広く取った代わりにパラメータ調整の部分は割とアバウトでいけるゲームだった。つまり、発想勝負 vs 調整勝負みたいな構図だ。このゲームにも発想勝負のステージがあるにはあるが、それよりも調整勝負の色がずっと強い。

ぶっちゃけていえばこのゲームが気に入るの人種って、プログラマで言うとプロファイル結果と延々睨めっこしてパフォーマンスチューニングするのが全然苦じゃない部類だと思うんだ。俺は今の仕事で必要になったというのもあるけど、既存のパーサジェネレータを使わずに自前のパーサライブラリを書いて、それのパフォーマンスチューニングを徹夜でやって「元のパーサジェネレータの4倍速いぜヒャッハー!」とかそんな事をしてるので、まあ結構気に入った。

俺はこういうプレイヤーに真っ正面から勝負を挑むストロングスタイルのゲームには是非とも売れて欲しいと思うのだが、いくらなんでもこれはハード過ぎるだろうという気もする。あとどうもこれ結構マイナーくさいので、攻略情報とかはあんまり期待しない方が良さげだ。買うなら覚悟すること。

2009-12-27
Sun

(02:08)

コロぱたは39面まで進んだ。正確にはそこで詰まった。かなり中毒性があるのでお好きな人には本当にたまらないゲームだと思うが、同時に好みが分かれそうだ。とりあえずこれから買おうという人は、以下の点に留意した方がいい(昨日書いたことと結構かぶってるが)。

  • オブジェクトの微調整でクリアの成否が決まる事が多く、多分攻略情報見ても難しい
    • そもそも攻略情報はしばらく出揃わないと思うが
  • 物理演算(?)のせいで本当に結果が予測困難
    • ごくごく稀にバグじゃねえのかと疑いたくなるような相互作用が発生するが、バグかどうかは不明
  • 予測困難性に対して正解の範囲が明らかに狭い
  • ステージをスキップすることができないので、詰まったらそこで投了の危険性あり
  • ほぼノーヒント

その一方でユーザーインターフェースと操作性はかなり優れている、というかその辺の良さで果てしないトライアンドエラーにかかるストレスがかなり軽減されており、アンドゥとかオブジェクト配置のスナップショットの保存がないことを除けばストレスは皆無に近い。逆に簡単にトライアンドエラーができるから、多少無茶な難度にしてもいけると判断されたのかな。一番ありそうなのは「開発者がゲームに慣れすぎてるので調整結果が鬼畜になった」なんだが。

とどのつまりはマゾゲーなので、例えばこれが

  • もっとラフなオブジェクト配置でもクリアできる(=調整勝負は控え、発想勝負の度合いを増やす)
  • 新規ステージ追加を1ステージ毎ではなく数ステージまとめて追加にする(=詰まっても遊べるように)
    • 例えば4ステージまとめて追加、2ステージクリアで次のブロック追加とか
      • 幕間のイベントシーンはブロッククリアで見れるようにするとか

ぐらいになっていれば、もっと大々的に「コロぱた超オススメ」と言えたんだが、現状はある程度以上コアなゲーマー向けのカルト作品になってると思う。

あと数ステージ事に挟まるイベントシーンが妙にオタ向けなのがなんとも。この辺はゲーム性の評価とはあまり関係ないので個人的にはどうでもいいが、ここでも無意味に客層を狭めている気がしなくもない。

2009-12-28
Mon

(13:42)

今日は麻婆キャベツ(?)を作った。材料は豚バラ100gちょい、キャベツは適当、もやし100g、人参中1/4弱、せりを少々。調味料は甜麺醤小さじ2杯、豆板醤小さじ1杯、鶏ガラスープ小さじ1杯、あとは水溶き片栗粉を少々。

作り方の手順は

  1. キャベツと人参をフライパンに敷いて水を50ml程度入れて、蓋をして蒸し焼きにする
  2. 大体5分ぐらいしたら残りの食材を入れて適当に蒸し焼きにする(時間測ってないので適当)
  3. 調味料と水溶き片栗粉を入れてよく混ぜれば出来上がり

かなり適当に作ったんだが、割と食える代物にはなってる。あとは調味料と水の分量と、蒸し焼きにする時間のバランスだな。

2009-12-30
Wed

(23:52)

ふと今年を振り返ろうと思ったが、ゴチャゴチャ書くのが面倒になったので箇条書きにて。

  • 会社勤め辞めてフリーになった
  • 何か数学の勉強をすることになった(半分ぐらい仕事)
  • ってか計算機科学含めて大学の時より明らかに勉強するようになった
  • 引っ越した

正直、今年の四月ぐらいには「俺はこのまま下請けソフトハウスで埋没していくんだろう」と半分どころか 90% ぐらい人生投げてたので、ここまで生活が変わるなんて思いもしなかったな。