Diary?::2009-04

2009-04-01
Wed

(20:24)

仕事辞めました。

2009-04-02
Thu

(20:16)

さて前の現場は先月末で終了だったので、今は本社勤務に戻っているのだが、早速無茶な要求が来たというか無茶な仕事の取り方をしようとしているというか。案件自体は C# 使って特殊なクライアントを作る以外に特筆するべき所はないんだが、デスクトップアプリの製作経験があるのが本社組では俺だけというのは死亡フラグにしか思えない。というか C# の経験 or 知識がある奴自体がほとんどいないんだがな。

2009-04-03
Fri

(20:45)

派遣切りだの内定切りだのといったニュースが流れる中、俺の勤務先はスキルセットの怪しい連中の仕事がガンガンなくなり自宅待機組がちらほら出ている状況になっており、それでもなお俺の前に提示された来月以降のスケジュールはどう好意的に解釈しても俺が三人月分ぐらい働かないと達成不可能なので他の連中はもっと修行しやがれ畜生。

……まあ、どんな危機に陥ってもダメな奴はとことんダメなんだけどな。そして俺の仕事の幾許かは、その手のバカの雇用を作り出すための仕事でもあるが、今の仕事はなあ。ちょっと要求されるスキルレベルというかスキルセットがなあ。

(23:29)

セブンスドラゴンは現在ラストダンジョンを攻略中。多分今晩中にクリアできるだろうけど、プレイ記録に反映されるのは来週にずれ込む見込み。そのラストダンジョンは突入時に平均でレベル 50 だったのが、途中で 54 ぐらいに上がってるんだが、これはもしかしてレベル低すぎたのか。まあ、今回はマジでまったくレベル上げしてないし、途中何回か奇策を用いて倒したボスがいるのは確かだけど。

2009-04-04
Sat

(17:17)

セブンスドラゴンは一応表のラスボスは倒したけど、さてクリア後ダンジョンの方はどうすっかな。

  • ストーリーはあくまでも表ボスで完結してる
  • パーティの面子的に戦略が完璧にネタ切れ

というわけで、今回のプレイ記録は表クリアで幕引きにする線が濃厚。特にラスボス戦がこれまでの集大成といえる死闘になったんで、それで満足してしまったんでな。ちなみにクリア時の平均レベルは 56 ぐらい。この程度だとラスボスのとある攻撃で全滅確定なんで、一点読み & ランダム要素のある奇策を使う必要があったぜ。

まあ、そのあたりの話はプレイ記録の方でということで。更新にはまだ時間がかかるけど。

(21:31)

試しに買ってみたけど、これはちょっと食いきれない。あと食ってて途中で飽きるので、数回に分けて食べることになりそう。

2009-04-05
Sun

(13:06)

セブンスドラゴンプレイ記録を更新。今回はラスボスのアレが登場するところまで。このままのペースで書いてくと、来週中には完結だろうな。しかしこういうのは書いてくとキリがねえというか、本当はもう少し短くまとめる予定だったんだが。何かもう、キャラが一人歩き気味だ。

2009-04-06
Mon

(20:43)

ここ数日FlowChart.Netという製品を使った開発をやってる。こいつはフローチャート・ダイアグラムの類を簡単に実装できる製品で、ちょっと使ってみた限りとても便利に感じたのだが、一点だけちょっとアレだなあと思ったことがあった。

俺がやりたかったのは「ダブルクリック時に角丸と菱形など図形ごとに異なった動作をさせる」だったのだが、そのためには以下のようなイベントハンドラを書いて、自前のShapeNodeのサブクラスであるMyShapeNodeを実装する必要があった。

private void diagram1_NodeDoubleClicked(object sender, NodeEventArgs e)
{
    if (!(e.Node is MyShapeNode)) return;
    MyShapeNode node = (MyShapeNode) e.Node;
    node.DoSomething();
}
 
private void diagram1_NodeCreated(object sender, NodeEventArgs e)
{
    MindFusion.Diagramming.ShapeNode node = (ShapeNode) e.Node;
    MyShapeNode newNode = new MyShapeNode(node);
    diagram1.Nodes.Remove(node);
    diagram1.Nodes.Add(newNode);
}
 
public class MyShapeNode : ShapeNode {
    public MyShapeNode(ShapeNode node) : base(node) { ... }
    
    public void DoSomething() {
        //後はフィールドに持っている Shape オブジェクトで処理を振り分け
    }
}

これの何がムカつくってそりゃキャストしてるところに決まってる。そもそもキャストなんてのはシステム設計と言語設計の決定的敗北を意味すると俺は考えるので、できればこんなものに頼らずに済ませたいところだ。それに生成されたノードの付け替えをしてるところも実にダサい。もっともファクトリオブジェクトが自由に付け替えられないために、イベントハンドラに渡されるのは常にコンポーネント側で定義されたオブジェクトなのでしかたがないのだが。

ところでいわゆるOOPLにおいて、継承というのは単一継承か多重継承かに関わらず、基本的にツリーの末端に要素を追加していくようなイメージだと思う。

 --------------
|  BaseClass   |
 --------------
     |---------------
     |               |
     v               v
 -------------   -------------
|  SubClass1  | |  SubClass2  |
 -------------   -------------
     |
     v
 ------------------
| UserDefinedClass |
 ------------------

ところがこれだと、先に出したFlowChart.Netのイベントハンドラのように、あくまでもメソッドが必要なのは既存のクラスという場合にちょっと不便だ。なので、次のような継承構造を考えてみる。

 --------------
|  BaseClass   |
 --------------
     |             ------------------
     |<-----------| UserDefinedClass |
     |             ------------------
     |---------------
     |               |
     v               v
 -------------   -------------
|  SubClass1  | |  SubClass2  |
 -------------   -------------

さあちょっと斜め上感が漂ってきた。つまり既存の継承ツリーの途中に全然関係ないクラスを混ぜ込んでしまおうというアイディアなんだが、果たしてそんな事をできる言語があるのか?

結論としてはそういう事のできる言語はあって、それは3.0及び2.6以降のPythonだ。動的型付け言語故に元からメソッドを後付けしたりできたんだが、新しく標準モジュールに搭載されたabcモジュールで、継承構造まで書き換え可能になっている。とりあえずざっくりしたサンプルを。

from abc import ABCMeta, abstractmethod
 
class Foo:
    def foo(self):
        print('foo')
 
class Bar(metaclass=ABCMeta):
    def bar(self):
        print('bar')
 
    __additionalslot__ = [bar]
 
    @classmethod
    def __addfunction__(cls. tgt):
        for slot in cls.__additionalslot__:
            setattr(tgt, slot.__name__, slot)
 
    @classmethod
    def register(cls, tgt):
        ABCMeta.register(cls, tgt)
        cls.__addfunction__(tgt)
 
class Buz(Foo): pass
 
Bar.register(Buz)
print(issubclass(Bar, Foo)) # False
print(issubclass(Buz, Foo)) # True
print(issubclass(Buz, Bar)) # True
buz = Buz()
buz.foo() # 'foo'
buz.bar() # 'bar'

流石にデカいプロジェクトでこういう機能を野放しにするのはアウトだけど、制御可能な範囲内なら有効に働くんじゃないのかな、これは。特に先に出したイベントハンドラまわりでファクトリ部分が決め打ちされていると、どうしても似たような泥臭いコード(キャストとか)があちこちに散らばってしまう。実行時型情報とキャストに頼るのとこういう技巧に走るのとでどっちが好みかといったら、プロジェクトのメンバーにもよるけど俺は技巧に走るかもしれない(=現場じゃまず使えない)。

(23:27)

セブンスドラゴンが終わったので、購入予定リストのゲームをちょこちょこと遊んでる。まず手を付けたのはデスティニーリンクスなんだが、まあ普通の2DのアクションRPGだ。とりあえず三番目の島までクリアしたので、ファーストインプレッションでも。

まず目についたのはダンジョンに入ると武器の変更が出来ないということ。このゲームは敵によって武器の有効度が大きく違う上、弱点武器で攻撃するとドロップアイテム2倍という仕様で、装備品はおろか回復アイテムもドロップアイテムを元に作る必要があるので、効率的にアイテムを集めるには以下のような手順を取る必要がある。

  1. ダンジョンを一通り見てまわり、敵の分布を調べる
  2. 図鑑でモンスターの弱点とドロップアイテムを調べる
  3. 必要なアイテムの優先度順に武器を持ち替えてダンジョンに潜る

ちなみにアイテムはそのままでは換金不可能で、ただ戦っていてもお金は稼げない。じゃあどうやってお金を稼ぐかというと、NPCのクエストをこなす必要がある。もっともそのクエストは「○を□個取ってきて」が殆どなので、ひたすら武器やアクセサリを作ってダンジョン内で試し斬りをしてるといつの間にか達成してる。クエストの状況はバックログ込みで確認可能なので、うっかりボタン連打で読み飛ばしても大丈夫だ。

それで俺はどうもNPCの台詞を読み飛ばしがちなのだが、テキスト自体の魅力はゼロではない。というかむしろ、ほのぼのとした絵本か何かのような雰囲気はなかなかいいと思う。もっとも直前までやはりテキスト量のそれなりに多いRPGをやっていたせいか、何かもうそういうのはお腹一杯という感じだ。

戦闘バランスは凄まじくピーキーで、「氷系の攻撃で凍結→死亡」とか「大枚はたいて傭兵召喚→ボス瞬殺」とか、一体いつの時代のゲームだかわからん愉快バランスだ。敵の攻撃が結構痛いので雑に遊んでるとすぐに死ぬが、死んだときのペナルティなんぞ無きに等しいので問題ない。何しろ救助費用として所持金をほんのちょびっと引かれるだけで、アイテムのロストもなしに帰還できるからな。命が尽きるまでひたすらダンジョンで敵を狩りつづけ、死んだらクエストの報告と新しい武器の作成というのもアリ。何回か武器を持ち替えて探索してたらクエストの大半を達成できたので、基本はシナリオガン無視でひたすらハンティングか?

他に重要な点としてレベルの概念がないので、育成マニアには多分あまり向かないゲームだ。一方で死ぬほど使い勝手の悪い両手武器でボスの撲殺を目論むマソプレイからひたすら逃げ回りながら飛び道具連発のチキンプレイまで、遊び方の幅自体は割と広めなので案外バトルマニア向けかもしれん。

ちなみにゲームのメイン画面はマジでドット絵のみに近い簡素な作りで、時々思い出したようにイメージムービーがちょろと流れる程度のビジュアル表現なので、美麗なCGとかイラストを拝みたいという人にもまったく向かない。オープニングムービーはそれなりに力が入ってるが、主題歌の終わるタイミングがバイオリズムに合致しないのが残念だった。

というわけで俺は殆ど密猟者のようなプレイスタイルで進めているが、今のところ結構楽しめてる。問題は敵の攻撃パターンがイマイチ少ないのと攻撃方法が武器ごとに二種類のみで回避行動等がないせいで、敵の密集地帯に飛び込みでもしないと展開がやや一本調子なところか。完全にダレる前に終わるか新しい攻撃パターンの投入でテンションを保つかすれば、良作といっても良さそうな気がする。

2009-04-07
Tue

(23:07)

Adagioの"Archangels In Black"を購入。今作からヴォーカルがまた変わっているけど、実力に問題のある人選が行われるはずもないのでそこは大丈夫だ。楽曲の方は前作に輪をかけてヘヴィになっており、クラシックパートとの対比がより一層鮮烈になった印象。先行公開されてPVも作られた"Fear Circus"がそのいい例だ。それに続く"Undead"に至っては美麗なピアノソロから超絶ヘヴィリフに急転直下で展開するキチガイナンバーで、ほんとこのバンドはやり過ぎを通り越してるぜ。

ちなみに一番の驚きは、月戦士(Getsu Senshi)という楽曲の存在。これは日本盤ボーナストラックだろうと思ったら違ってやんの。一体何やってんだStephan Forte(まあ、確かに日本でのAdagioへの評価はかなり高いと思うけど)。

2009-04-08
Wed

(23:35)

論文自体はまだ全然読めてないけど、 Terence Parr の主張はつまり「JSP にしろ別のものにしろ、チューリング完全なパワフル過ぎるテンプレート/プレゼンテーションエンジンは過ぎたるは及ばざるが如しなので Suck」という事で OK? だったらその点に関しては全面的に賛成。プレゼンテーション部分でリッチな事が出来すぎると、それは時々大変な惨事を引き起こすわけでして。

※ところで論文のリンク先は http://www.cs.usfca.edu/~parrt/papers/mvc.templates.pdf が正しいはず。 "papers" が "paers" になってるから typo かな。

そういえば四年前に開発を放棄してるんだけど、俺もテンプレートエンジンを作ったことがあったんだ。確か Python を始めて三週間ぐらいのときにでっち上げたテンプレートエンジンで、実はこの日記とかゲーム系コンテンツとかの生成に今でも使ってる奴なんだけど、ぶっちゃけそいつは酷い代物だった。まあ四年前の俺は今よりもずっと未熟というかアホだったんだなあという事なんだけど、とりあえずどんな代物か晒してみるか。これはこの日記の最新3日分ページのテンプレートの一部だ。

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html
  PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN'
  'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
<html xml:lang="ja" xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>{var title}::{var year}-{var month}-{var day}</title>
    (def prev:
      <link rel="prev" href="{var prev}" />
    )
    (def next:
     <link rel="next" href="{var next}" />
    )
    <link rel="stylesheet" href="/log/style.css"/>
  </head>
  <body>
    <div class="section">
      <h1>{var title}</h1>
      (each item:
        <div class="section">
          <h2><a href="./{var item.year}/{var item.month}/{var item.day}">
          {var item.year}-{var item.month}-{var item.day}<br/>{var item.dow}</a></h2>
          {rvar item.body}
        </div>
      )
    </div>
  </body>
</html>

ちょっとテンプレートの構成要素を抜き出すと、

{var variable}
variable を出力する。 HTML 特殊文字はすべてエスケープ。
{rvar variable}
variable を出力する。 HTML 特殊文字のエスケープを行わない。
(each list: body)
list の要素数分だけ body を出力。
(def variable: body)
variable が未定義あるいは偽として扱われない値であれば body を出力

こんな感じ。実に素朴というか改めてみるとその低機能っぷりに驚く。こいつを処理するコードは今でも入手可能だけど、ぶっちゃけバグが残ってるんで使わない方がいい。コードのクオリティも酷いしね。まあ、そもそも機能性が低すぎる上に手抜きまみれなんで他の人が使うに耐える代物じゃないんだけど。

ちなみに開発がストップした理由だけど、どうもこの日記の更新スクリプトを一通り作り終わったあたりで「あ、もういいや」ってなったらしい。最初は別テンプレートのインクルードとか付けるつもりだったんだけど、別になくても支障のないものしか作らなかったというか何というか。あと HTML 特殊文字のエスケープの切り替えをテンプレート側でやってるのが今にして思えばクソだ。これは文字列型の他に HTML 文字列型を定義して、型によって処理をオーバーロードするのが多分正しい。そこら辺の判断はデータモデルの責務であって、テンプレートのものではない。

しかし昔の俺はずいぶんと正規表現が好きだったんだなあ……。いや、今でも使うときは使うけどさ。

2009-04-09
Thu

(22:57)

下請けソフトウェアハウスで働いていてつくづく感じるのは、俺たちは結局のところ下請けであって、そんな野心的な事なんかなかなかできないってこと。確かに俺は業務としてワケのワカラン R&D 的な事をやっていた時期があったけど、それも結局俺がそれに専念することは難しいということで雲散霧消気味だ。まあ、出せばそれなりの単価とれる俺を遊ばせとくなって意見は正しいっちゃそうだ。

今の仕事はクライアントにとっては野心的な部分が大きくて、関係各社が尻込みする中で俺の技量を当て込んで取ってきたというものらしい。まあこの仕事が順調にいけば、そりゃあ旨味はでかいだろうよ。でも去年やってた R&D から今の仕事って全然まったく何も繋がってないし、そこには戦略のかけらも感じられない。

もっとできる奴が多ければ、俺が某プロジェクトの火消しをやった後に別プロジェクトの基盤技術の整備をやってから新規プロジェクトの調査と見積りやって、それからまた別のプロジェクトの技術調査と基盤開発をやってる合間に可能であれば R&D というふざけたことをしなくても済むんだがなあ。人がいないんだから仕方がないとはいえ、朝令暮改に付き合うのはマジでストレスが溜まるぜ。

そうそう、 R&D と平行して企業ブログを書いていた時期もあったんだけど、結局それも殆どポシャったようなもんだ。やはり特定の技術だけにテーマを絞ったブログを書きつづけるには、その技術にフルタイムでコミットできるメンバーが絶対に必要だ。それにしたってその技術が廃れたり、そもそも全然隆盛しなかったら情報の価値がなくなるわけで、その程度の見通しもなしに無駄に継続しにくい形態を取るのってどうよ。

……ということをいくら主張しても馬の耳に念仏だったんだよなあ。そもそもの R&D の内容に付いても、当事者である俺の判断よりもその技術について疎い(ってか何も知らない)上司が意見をゴリ押ししてきたりとろくなもんじゃなかったが、何にせよ俺が本当に興味を持ってる分野ではなかったのでどうでもいいか、今となっては。

この一連の経験から俺が学んだことは、会社の上層部が「君の技術力に期待している」という時は「我々の出す予想の斜め上なドリームをそのまま叶えてくれ」という意味であって、それを行うこと自体の是非に付いての俺の意見は参考意見という名のゴミ箱に捨てられるということだ。

元からこんなだったところに不況の波がやってきたんだから、輪をかけてアレな事になるのは当たり前か。ってかマジでこの先どうするんだ、この会社は。

(23:35)

というわけでクソといったらクソに失礼な現実から逃避するためにセブンスドラゴンプレイ記録の続きを書いているのだが、こっちはこっちで収拾がつかなくなりそうだ。ってか前回の更新であまりにもぶっ飛ばし過ぎた。

……何か世界樹の時から余計悪化してるなあ。

2009-04-10
Fri

(22:57)

最近腰痛が酷い。ってかこれヘルニアじゃねえの?

しかし最近の仕事に対するモチベーションの低下っぷりは異常だ。別に新規性なんざ(俺にとっては)さっぱりないし、ほぼ独立愚連隊で仕事してるから本社勤務なのに他の社員と殆ど喋らねえし、喋ったところで俺の話についてこれる奴なんざいねえし、設計・実装してて面白い部分はもう殆ど全部やっちゃったし、あと一個残ってる課題はやってて不愉快千万な代物(MS が .NET で切り捨てた部分の尻拭い)だし、それすら終わったらあとは俺じゃなくてもできるだろうしなあ。

ってか別に給料なんざ割かしどうでもいいから、本当に技術力の必要な部分が終わったら自宅待機とかの生活をしたい。どうせこの会社が請け負う仕事で技術力が必要な部分なんて、俺が半年も働きゃカバーできる分量だろ。

まあ、今抱えてる仕事もカタが付く目処が立ってきたし、そろそろ業務時間の半分をサボって別の事をする生活に戻すか。本社勤務の良いところは、成果さえ上げれば後は全部俺の裁量でできるところだ。いや本当は多分マズいんだろうけど、そこはいくらでも誤魔化せるし、俺の技術力と会社の取ってこれる仕事の難易度の上限値がほぼイコールだから、向こうも多分あんまり強く意見できないだろうし。

2009-04-12
Sun

(23:50)

えーと、今日中に仕上げるつもりだったセブンスドラゴンプレイ記録だけど、どうも仕上がり切らないっぽい。とりあえず公開は明日の予定。

……しかし今回は文章と写真の量が半端じゃねえな。

2009-04-13
Mon

(22:50)

セブンスドラゴンプレイ記録、ついに完結。実はまだ後書きというか総評・感想を書いてないんだけど、そっちはやっぱ今週末になりそう。それにしてもあれだ、多分俺は製作者の意図を越えて楽しんでた気がするな。

後書きで触れてほしいというか答えてほしい事があったら、それはメールしてくれれば答えるかもしれないし答えないかもしれないので、奇特な方はメールミー。

しかし疲れた。こういうコンテンツはやってて楽しいけど、ものすごく HP と MP を消費する。

2009-04-14
Tue

(22:46)

メールで「セブンスドラゴンプレイ記録の最終話で、マレアイア群島国で男連中が普通に喋ってるっすよ」というツッコミをもらったので、ちょっと修正。えーと、これは普通に中の人が忘れてました。実際には帝竜討伐をトリガーに「あなた方は特例です」みたいな事を門番が喋るようになるので辻褄はあってるんだけど、いやマジでこれは忘れてた。

2009-04-15
Wed

(23:32)

今月に入ってから C# + MS Office の開発をやってるんだが、なんか MS Office の API ってちょっとおかしくない?

俺がやろうとしていたのは Excel と Word でファイルセーブのイベントをフックして独自の処理を入れ込むことで、それ自体は Excel にも Word にもイベントハンドラがあったので実現はできたんだが、どうにも釈然としない。

Excel も Word も一つの Application クラスのインスタンスに対してそれぞれ複数の Workbook クラスと Document クラスのインスタンスが紐付くという作りになっていて、そこだけ見ると非常に似通ったオブジェクトの作り方なのだが、どういうわけだかファイルセーブのイベントハンドラの記述箇所が両者で違っていた。

Excel
Workbook クラスにイベントハンドラがある
Word
Application クラスにイベントハンドラがある

そして Word の方のイベントハンドラは、引数の型を見ると Document のインスタンスを渡す以外は Excel の物と同じで、何となく内部処理にはたいして違いがないように見える。いや、別に俺は MS の中の人じゃないんでまったくの当てずっぽうなんだけど。でもこういう不統一性は気になるっちゃ気になるんだよな。

2009-04-16
Thu

(20:24)

「ソフトウェア開発はアート」という言葉をまた見かけたのだが、正しくは「ソフトウェア開発は芸術作品を作るプロセスと同程度にしか工学的・科学的・合理的手法が研究されていない」ってことなんじゃないかなあというのが最近の俺の考えかな。

そもそも考えてみれば、芸術作品を作ってる連中だって霞食って生きてるわけじゃないから、最低でも金出す人にそっぽ向かれない程度には作品を作っていかないといけない。レコード会社と契約してるミュージシャンなんて、制作期間が十分とれないまま次の作品を発表しないといけなかったりするわけでしょ。結局アートの世界も限られた時間・予算・人員・設備などの制限下で作品を作んないといけないわけで、そしてそこには多少なりとも工学的なプロセスがあるんじゃないかなと思う。

ただまあそうは言っても行き詰まりを感じてるのも確かで、例えば先月の大きな仕事であったソフトウェア見積りにしたって、あれ全然サイエンスじゃないだろ。とりあえず統計的にこのぐらいだろって数値は出ているけど、結局それも開発対象のアプリケーション、開発チーム、過去の実績などから辻褄合わせの謎調整を山のようにかける必要がある。そもそも会社が違ったら見積りのやり方が根本から全然違うって事も普通にあるし、とりあえず顧客がキレなくて、コンサルの経験から大きく外れてなくて、開発会社がそれなりに儲かるラインの人月工数のエクスキューズに使われてるケースってあるんじゃないの?

そもそも俺の働いてる SI 業界って基本は人月単価でいくらで請け負う業務体系で、そしてまともなエンジニアとそこらに糞尿を撒き散らさないだけ動物(英語で言うとアニモー)よりはマシレベルのカスの間で単価の格差がたいしてない(給与格差はもっとない)。さらにこれが元請けと下請けとかに分かれると、まともなエンジニアよりもアニモーの方がずっと給料がいいとか言う事態になる。こういう状況だと、より合理的な開発手法を模索するモチベーションって出てこないよな。

(21:08)

デスティニーリンクスをクリアしたので、総まとめ的な感想でも書く。

……とはいっても大体前に書いたとおりの感想だ。基本的なゲームの流れとかはずっと変わらなくて、変化といえば敵の攻撃力がどんどこ上がって行って、ついでに出現パターンの殺意も上がっていくぐらい。そのため大体四番目の島あたりからは、一回の探索でダンジョンを回りきれずにぶち殺されることが多くなってくる。つまり歯応えはそれなりにあるので、ヌルゲーを所望の向きにはオススメできない。適度にクリアしがいのあるアクションゲームをやりたい人にオススメかな。

ストーリーを進めるにあたってクエストというかお使いを散々やらされるハメになるが、俺はまずダンジョンに潜って敵を狩りまくって、一通りの武器でダンジョンを回り終えたらストーリーを進めるというやり方だったので、あまり面倒は感じなかった。もっともこの手の面倒な要素との上手い付き合い方を見付けらんない人にはちょっと微妙な出来かもしれない(これはセブンスドラゴンにも言えるな)。

ただまあ、 Wi-Fi やらなんやらをやらないとコンプリートできない仕様なので、これ以上やり込む気がイマイチ起きないのが残念っちゃ残念だ。十分遊べたから別にいいんだが。

2009-04-17
Fri

(21:49)

まず主人公が手の甲に釘を打たれまくるという拷問シーンで掴みはオッケー。しかもその拷問をやってるのがどう見ても小学生だろって感じの少女というのが狂いっぷりに拍車をかけてる。他にも自分の姉の若い頃に瓜二つな少女を誘拐して子供を産ませようとするおっさんとか、よくこの原稿が通ったな(他の拷問シーンも実に痛いし)。そもそも鉄一族ってどう考えても近親相姦で子孫を増やしてるくさいんだけど、この設定もよく通ったもんだというか、シリウスってそういう雑誌なのか?

あと今回は今までいまいちヘタれてた辻が、本当に追い詰められた結果ブチ切れたのが好印象。何せ「お前らを殺す」と明確な殺意の表明をして、それで実際に相手を不具にしてるからな。怒りと憎しみでパワーアップというのは愛と勇気が友達なんかよりもずっとしっくりくるので、是非ともこのままのダーク路線で続けてほしい。ミスミソウの鬱に対してこっちはブチ切れの躁で、ダークサイドの書き分けは出来てると思うし。

そんなブルータルな漫画を連載しつつ、よくもまあ主人公が猫耳少女に変化させられてしまうバカ展開を描けるなあと思うわけで、つまり今回はもう猫耳少女になってしまった耳雄に尽きるね。惜しくも途中で戻ってしまったが、このままやりすぎると留渦ちゃんの正ヒロインとしての立場が危うくなりそうだったから仕方がないか。

いや、実際のヒロインは相原なんだろうけど。

2009-04-18
Sat

(20:57)

一昨日あたりからロックス・クエストを遊んでるんだが、これはなかなか新鮮だ。ゲームのルールは要塞を築いて拠点を守ったり先に敵の拠点を制圧するという物で、そこだけ聞くと RTS っぽい感じだ。といっても俺は RTS は全然詳しくないので良く分からなかったりするんだが。

多分一番の特徴は要塞を造りあげる建築パートと実際に敵と戦う戦闘パートが完全に分かれているところで、さらに建築パートには時間制限が付いており、戦闘パートで操作するのは主人公だけという制約が独特のゲーム性を生み出している。特に戦闘パートでは主人公一人で

  • 能動的な敵への攻撃(仲間は基本的に迎撃しかしない)
  • 敵拠点の制圧
  • 破損した要塞の修繕

といったことを全て行う必要がある。そのため操作がえらいこと忙しく、把握しなければいけない情報量も多い。とはいえ比較的チュートリアルはしっかりしており、最初の数ステージは割とぬるいので慣れないうちに撲殺されてやる気デストラクションとはならない……と思う。

というわけで俺はかなりハマってるんだが、これちゃんと売れてんのかな。バタ臭いキャラデザのせいで売れてないんだとしたら実に残念だ。まあ、そもそも発売時期が悪くて俺も買うのが遅くなっちまったんだが、今のところ今年の俺的ベストゲームの最右翼だ。

2009-04-19
Sun

(17:22)

セブンスドラゴンプレイ記録に後書き追加。というわけで本当にこれで最後の更新なんだが、しかし終わってみれば一ヶ月とちょっとだったか。世界樹IIなんて足掛け三ヶ月だったから、大体こんぐらいの期間の方が読んでる方にとってはいいのかな。まあ、世界樹IIが長引いた理由としては攻略の難易度という要因もあるんだが。

2009-04-21
Tue

(23:01)

仕事で大した事やってねえと、マジで日記に書くことがなくなるな。いや、他の連中にしてみれば俺のやってることはかなり新規性の高いことなんだろうが、俺にとっては既に新規性ゼロだからな。この辺のギャップばかりはどうにもならん。

というわけでロックス・クエスト。なんかもう国内じゃ全然話題になってないけど、これはやっぱ絵柄が萌絵じゃないからダメなのか。こういうバタ臭いカートゥーン調も悪くないと思うんだが。

サブタイトルに「百日戦争」とある通り、おそらく最低でも100ステージあるんだろうけど、一戦一戦は大体2分から3分でケリが付き、建築パート含めても5分程度の分量なのでサクサクと進められる。特にこの一戦のスパンが短いのは通勤時間=ゲームの時間な俺にとってはかなり有難い。

それで現在66日めまで進めているが、もう途中で何度も敗北しまくりだ。とにかくリソースの制限がキツい上に多くの場合は連戦につぐ連戦なので、初期配置のヘマが後に響く響く。とはいえ敗北したときには「戦闘をやり直す」「直前の建設からやり直す」「一連のシリーズを最初からやり直す」といった選択肢が出るので、いわゆるハマリにはならない設計になっている。ここでも一戦の短さがリトライの容易さに繋がっており、また敵の編成が読めれば最適戦略が立て易くなっているために同じステージで停滞する事はまず無い。

というわけで今のところはさらに評価が右肩上がり。既にスキルと素材が殆ど出揃った状態なので、ここからどれだけテンションを保てるかが勝負か。

2009-04-22
Wed

(22:23)

のっぴきならない事情により XML Schema 込みで XML 言語の設計(まあ、そこまで大したもんでもないけど)を仕事でやっており、相変わらず直観に反する XML Schema はマジでツールのサポートが無いとまともなもんが書けなくて困るよなあとか、これが RELAX NG だったらとりあえずのスキーマをサクッと定義できるのになあとか、そういう事を思っていたわけだけど、「第53代横綱・琴桜の銅像が、パンティーを被った変質者に様変わりした件。」を読んだらそんなことどうでもよくなった。

折田先生像にも散々笑わせてもらったけど、こっちはまったくシャレになっていないのがおいしすぎる。

2009-04-23
Thu

(00:21)

見出しだけ読んだときは「頑丈な連中もいたもんだなあ」程度に思ってたけど、本文読んだら唖然とした。特に以下のくだりは決定的にマズいだろ。

「社会に出ると、少しぐらい体調が悪くても仕事を休めない。学校で休まないことを身につけさせたい」

「入学式からまもなくして、頭が痛いので休みたいと電話があったが、遅れてもいいからと母親を説得して生徒を登校させた。夏休みを過ぎると、『学校に来るのが当然』という一体感が生まれたという」

まず「少しぐらい体調が悪くても休めない」という妄言をどうにかしろ。人間どうしても体調の悪い時はあるし、そういう時はあんまり無理しちゃダメだろ。俺の今までの経験からしても「こんぐらいならまだ大丈夫かな?」と思って出社してもろくな事になった試しがない。大体だな、社員が一日二日休んだだけで支障が出るような体制・スケジュールで仕事してること自体が大間違いなんだって。そりゃあ、どうしても休めない「今この一時」なタイミングはあるだろうけど、そういう時に万全のコンディションで挑める確率を上げるためには普段から十分な休養をとっておくべきじゃないのか。

ちと極端な事を書いてしまえば、どんなに健康な奴だって居眠り運転や飲酒運転してるバカにはねられることだってあるし、ストーカーに付きまとわれてノイローゼになる可能性だってあんだろ。とにかく組織のメンバーに何かがあったときにどうやってバックアップするかこそが重要なのであって、「なるべく休むな」なんていう精神論はどんなに頑丈な精神・肉体の持ち主でも奴でも壊れるときは壊れるという事実から目を背けており、ドブ川に吐き出された酔っ払いのゲロに湧いたウジよりも価値の無い寝言であり、そんなに寝言が言いたきゃとっとと永眠していただきたいところだ。

いい加減にこういうクソのようなといったらクソに失礼な根性至上主義は滅びてくれないかな。根性出したってそれだけじゃどうにもならない事でこの世界は満たされているし、そもそも凡人の根性なんて本当に簡単に叩き潰されてしまうってのに。

2009-04-24
Fri

(00:55)

第一回モニャドセミナーに行ってきた。檜山さんのコンディションがベストとは程遠かったり、親しみやすかろうと思って出した圏の例で思わぬ事故が起こったり、とにかくまあいろいろな要因が重なった結果として「少し違った視点で見れば、世界が面白くなる」というスローガンの元に始まったモニャドセミナー第一回は愉快な混沌の元に終わった。

そして俺はセミナーが始まる前から「まとめ記事は頼んだ」という無茶を振られ、終いにゃ「みんなが混乱した部分の分析頼む」という更なる無茶を振られて頭を抱えていたのだが、まとめというか補足記事の落としどころが見えてきた気がするので、風呂入ったら執筆を開始することにする。

ちなみに俺の場合テンションの高いうちに全力で突っ走って体力が尽きるか壁にぶつかったらしばらくの間くたばって休憩ってのがマイペースだったりするんで、「お前明日仕事だろ」とか「体力保つのか」といった心配はしなくて大丈夫っす。別に今は会社の仕事でろくな事してないしな。

(01:45)

というわけで第一回モニャドセミナーのまとめというか、混乱した人の出てきた部分の俺なりの説明というか、まあそういうものを書くことにする。そもそも俺自身今回は(今回も?)きちんと落とし前を付けられる自信がまったくないので、その辺は差し引いて読んでください。

まず今回のセミナーの目標は

  1. 圏の形式的な定義と直感的なイメージの両方を知る
  2. いろいろなお絵描きを実習する
  3. 圏の実例を手でいじり倒して、体になじませる
  4. 横道にそれて、面白そうな話題を紹介する

だったわけだが、混乱が起きたのは二番目から三番目にかけての部分だった。というわけで今回はその混乱の原因についての考察などがメインになるが、その前に圏の形式的な定義から。セミナーで触れた範囲で「これが圏の構成要素」というものを列挙してみよう。

  • 任意の対象が存在する
  • 任意の対象 a, b に対して a -> b となるが存在する
  • a -> b という射において a を、b を余域とする
  • 射 f および g において、 f の余域と g の域が一致するとき f;g という結合が可能である
  • a -> a という恒等射を持つ

以上がの構成要素だ。これだけの説明だと「何それ?」って感じなので、セミナーで使われた(檜山さんの過去エントリーにもある)「しりとりの圏」を例に出して説明してみる。

しりとりの圏において、前述の圏の構成要素は以下のようになる。

対象
ひらがなの集合 H
任意のひらがなから作られる文字列 HStr
任意の HStr の最初の文字 first関数で取得できるものとする
余域
任意の HStr の最後の文字 last関数で取得できるものとする
恒等射
一文字からなる文字列
結合
しりとりのルールその物。任意の射 a, b に関して last a == first b の時 a;b

この場合の結合は以下のようになる。

  • こぶた, たぬき => こぶたぬき
  • らいおん, んじゃぴー => らいおんじゃぴー
    • 任意の文字列なんでまともな日本語の単語じゃなくてもいい
    • 「ん」で終わっていようがお構いなし
  • あ, あか => あか

とりあえずここまではオーケー? とにかく、この条件下ではしりとりが圏になっている。それでは檜山セミナーでヘビーに使われる絵算で「こぶた たぬき」の結合を見てみようか。

うんまあ、見たまんまだ。じゃあ試しにここに「きつね」という射を結合させてみよう。

当然だけど射(=任意のひらがな文字列)は無数にあるし、結合の数も無数にある。

こういう風に、いくらでも結合が作れるな。めでたしめでたし。……とは行かずに、ここまでの内容に関して質問が投げられ、楽しい混乱が始まった。その質問は以下の三つ(確かこんな感じ)。

  • 例えば「た」を域に「き」を余域に持つ射はそれぞれアイデンティティを持つのか? それともすべて同じとみなせるのか?
  • 「ねんね」のように域と余域が一致する射は恒等射か?
  • 「ここ」のような同一文字二文字の射はそれを作る過程で恒等射になってしまわないか?

結論から書くとそれぞれ「アイデンティティは持つよ。『たぬき』と『たんき』などは別の射」「恒等射にはならない」「射はそこにあるもので作られるものではないし、何にしても『ここ』のような射は恒等射にはならない」といったものだった……と思う。これについては、俺がどのようにしりとりの圏を理解したかの過程を書くことで補足してみようと思う。……と思って書いたけど、案の定派手に間違っていたので、以下のツッコミ及び補足記事を代わりに読んでください。

そもそも何でこんな勘違いをしたかというのを考えてみたら、どうも恒等射についての理解が滅茶苦茶だったのが原因に思える。俺は恒等射のことを物凄く特別な射だと思い込んでいて、その特別さ加減がシグネチャから割り出せないとマズいんじゃねえのと思い、それで以下にあるようなトンデモ論法に行き着いたわけだ(他にもいろいろわかってなさげだが)。でも実際には実装の違いでしかないというのが正しい理解っぽい(まだきちんと理解できてない)。やっぱあれだ、もうちょっと圏の実例に触って圏の概念を体に覚えさせないとダメだな(あと Haskell とかの型システムのちゃんとした理解とか。これも全然ダメダメだ)。

まずは「たぬき」という射だが、そもそもこれは「たぬ」と「ぬき」という射を結合してできたものだと言える。そして圏論というのは極めて強く型付けされた体系で、結合するときに型が完全に一致しないと型エラーを引き起こす。例えば以下のようなプログラムは型エラーとなる。文法とか型のイメージは、まあ常識的に考えてください。

f :: Float -> Float
g :: Integer -> Integer
h :: Number -> Number
x = f;g;h

こういうのを暗黙の型変換で通しちゃうプログラミング言語は多いかもしれないけど、圏論で扱うような世界では間違いなくエラーになる。そのため、以下のような中継ポイントが必要になる。

f :: Float -> Float
g :: Integer -> Integer
h :: Number -> Number
i :: Float -> Integer
j :: Integer -> Number
x = f;i;g;j;h

「これとしりとりの圏の何が関係あるんじゃ」と思われるかもしれないけど、俺の理解した範囲ではしりとりの圏におけるひらがな一文字は型そのもの。そして射の文字列はそのまま関数の引数の型で、関数の戻り値の型は文字列の最後の文字。この論法に従うと、しりとりの圏における文字列というのは以下のような型の関数になる。

  • "あ" = あ -> あ
  • "ああ" = あ -> あ -> あ
  • "あい" = あ -> い -> い
  • "あいう" = あ -> い -> う -> う

というわけで、一番目の質問に出たような同じ域と余域を持つ射のアイデンティティ問題は解決。「たぬき」という射は「た -> ぬ -> き -> き型」で「たんき」という射は「た -> ん -> き -> き型」と全然違うものだし、それでいて余域が同じだから「きつね」のような射を結合可能。

二番目の質問で出た域と余域の一致する一文字より多い射が恒等射にならない理由もこれでわかると思う。恒等射である「あ」は「あ -> あ型」なのに対して、「あじあ」などは「あ -> じ -> あ型」であり、恒等射の条件は「a -> a であるような射」だからだ。三番目の質問の答えとしてもこれで良かろう。

書いててなんか不安になってきたので、 Haskell でコードを書いてみる(ちなみに俺は Haskell プログラマレベルでいうとキャラメイク途中、つまりレベル1にすら達してない)。実に投げやりなコードだけど、とりあえずしりとりの圏ってこういう問題じゃないかな。恒等射の処理が書かれてないけど、そっちはまあわかるでしょう。

main = putStrLn $ ((morph1 `compose1` morph2) `compose2` (morph3 `compose1` morph4)) 1 'a' "abc" True "xyz"
 
morph1 :: Int -> Char -> Char
morph1 x y = y
 
morph2 :: Char -> String -> String
morph2 x y = y
 
morph3 :: String -> Bool -> Bool
morph3 x y = y
 
morph4 :: Bool -> String -> String
morph4 x y = y
 
compose1 :: (a -> b -> b) -> (b -> c -> c) -> (a -> b -> c -> c)
compose1 f g = \m n o -> o
 
compose2 :: (a -> b -> c -> c) -> (c -> d -> e -> e) -> (a -> b -> c -> d -> e -> e)
compose2 f g = \m n o p q -> q

このコードをコンパイルして実行すると "xyz" という文字列が出力される。という事は、きちんとしりとりが成立したことだと思って良いはずだ。納得できない? コンパイラがこれで良いっつってんだから良いんだよ。……多分。


えーと、それでセミナーで起きた混乱の原因を考えてみると、やはり「'あ' という対象と "あ" という恒等射と "ああ" という射」など、射と対象の間に混同が起きていたような気がするのと、実例に入る前に説明された圏論における型の扱いのシビアさと射の結合あたりが有機的に関連付けられて理解されてなかったのかもしれないのと、この二点なのかなと思ったりする。

実際問題、俺もしりとりの圏の理解で使ったひらがな文字=型という連想ゲームが正しい理解といえるのかどうか、全然自信がなかったりして。というわけでツッコミ歓迎。


今回はしりとりの圏に絞って書くつもりだったから一時間ぐらいで終わるだろと思ったら、もう四時半だよ。やべえ会社行きたくねえ。


追記@04:40 大事な事を一点書き忘れた。しりとりの圏の絵算とアローダイアグラムによる関数適用・結合の類似性というのが抜け落ちてる。もういい加減眠いので寝るけど、これについては後できちんと追記した方がいいか。

(08:10)

さっそくツッコミが。えーと、とりあえず会社から帰ってきたらまた考えます。

俺もだいぶ混乱してるなあ。

(19:21)

セミナーの報告記事を大幅改訂。ってかかなりの部分を訂正というか取り下げ。詳しい内容はたけをさんのツッコミにて(素早いツッコミ thanks です)。

で、たけをさんも書かれていることだけど、しりとりの圏の場合は恒等射の扱いがややこしいってのが確かに気になる。「圏の例としてはこんなのがありますよー」という掴みとしては結構親しみ易いと思うけど、そこからほんのちょびっと考えて行ったら混乱したからな(いやそれにしてもここまでこじらせるのは俺だけかもしれんが)。そこさえ引っかからなければ、そこまでわかりにくい例ではない……かもしれないけどどうだろ。

あと懇親会で「セミナーの報告記事とかをまとめて、教科書・チュートリアル的にしたら良いんじゃない?」という意見をもらっていて、その意見には賛同したいところなんだけど、今回の報告記事でわかったとおり俺は明らかにそこまでやるだけの実力が伴ってないんで、誰か俺より頭のいい人に任せたいなあ。

2009-04-25
Sat

(20:07)

檜山さんの「有限集合と写像の圏もJavaScriptで書いてみた、遊んでみてね」に倣って、 MapFO を Python で書いてみた。例外処理とか投げやりだけど、そこは気にしない方向で。

class FO(list):
    def __init__(self, num):
        list.__init__(self)
        ls = range(1, num + 1)
        self.extend(ls)
 
class MapFO(object):
    def __init__(self, a, b=None, map=None):
        if not (isinstance(a, FO) and isinstance(b, FO) and isinstance(map, list)):
            raise Exception()
        if len(a) != len(map):
            raise Exception()
        if max(b) < max(map):
            raise Exception()
 
        self.dom = a
        self.cod = b
        self.map = map
 
    def __add__(self, another):
        if self.cod == another.dom:
            newmap = []
            for i in self.map:
                newmap.append(another.map[i - 1])
            return MapFO(self.dom, another.cod, newmap)
        else:
            raise Exception()
 
    def __eq__(self, another):
        if self.dom != another.dom: return False
        if self.cod != another.cod: return False
        if self.map != another.map: return False
        return True
 
    def __str__(self):
        s = '[%d] --> [%d]\n' % (self.dom[-1], self.cod[-1])
        for i, j in zip(self.dom, self.map):
            s += ' %d | --> %d\n' % (i, j)
        s += 'dom=%d cod=%d value=[%d]\n' % (self.dom[-1], self.cod[-1], len(self.map))
        return s
 
    @classmethod
    def id(cls, fo):
        return MapFO(fo, fo, list(fo))

使い方及び実行結果はこんな感じになる。まずは普通に射の生成。

>>> f = MapFO(FO(2), FO(3), [2, 1])
>>> print f
[2] --> [3]
 1 | --> 2
 2 | --> 1
dom=2 cod=3 value=[2]
 
>>> g = MapFO(FO(3), FO(3), [2, 3, 3])
>>> print g
[3] --> [3]
 1 | --> 2
 2 | --> 3
 3 | --> 3
dom=3 cod=3 value=[3]
 
>>> h = MapFO(FO(3), FO(4), [4, 3, 1])
>>> print h
[3] --> [4]
 1 | --> 4
 2 | --> 3
 3 | --> 1
dom=3 cod=4 value=[3]

続いて射の合成。

>>> print f + g
[2] --> [3]
 1 | --> 3
 2 | --> 2
dom=2 cod=3 value=[2]
 
>>> print f + g + h
[2] --> [4]
 1 | --> 1
 2 | --> 3
dom=2 cod=4 value=[2]

それでもって俺がしりとりの圏で醜態を晒す原因となった恒等射。

>>> i = MapFO.id(FO(2))
>>> print i
[2] --> [2]
 1 | --> 1
 2 | --> 2
dom=2 cod=2 value=[2]
 
>>> print i + f
[2] --> [3]
 1 | --> 2
 2 | --> 1
dom=2 cod=3 value=[2]
 
>>> print i + f == f
True

PMapFO と RelMapFO はまた後で。

(21:54)

PMapFO と RelMapFO も書いた。コードを見せる前に、超大雑把に PMapFO と RelMapFO の説明。

PMapFO
域の要素の中に使わない、つまり対応が未定義のものがあってもいい。
RelMapFO
域の要素と余域の要素が 1:n 対応していてもよい。あと未定義なマッピングがあっても良かったはず。

それぞれの凡例はこんな感じ。

それじゃあ PMapFO の実装から。

class PMapFO(object):
    def __init__(self, a, b, map):
        if not (isinstance(a, FO) and isinstance(b, FO) and isinstance(map, dict)):
            raise Exception()
        if max(b) < max(map.values()):
            raise Exception()
 
        self.dom = a
        self.cod = b
        self.map = map
 
    def __add__(self, another):
        if self.cod == another.dom:
            newmap = {}
            for k in self.map.keys():
                v = self.map[k]
                if v in another.map:
                    newmap[k] = another.map[v]
            return PMapFO(self.dom, another.cod, newmap)
        else:
            raise Exception()
 
    def __eq__(self, another):
        if self.dom != another.dom: return False
        if self.cod != another.cod: return False
        if self.map != another.map: return False
        return True
 
    def __str__(self):
        s = '[%d] --> [%d]\n' % (self.dom[-1], self.cod[-1])
        for i in self.dom:
            if i in self.map:
                s += ' %d | --> %d\n' % (i, self.map[i])
        s += 'dom=%d cod=%d value=[%d]\n' % (self.dom[-1], self.cod[-1], len(self.map))
        return s
 
    @classmethod
    def id(cls, fo):
        return PMapFO(fo, fo, dict(zip(list(fo), list(fo))))

MapFO と違って辞書をマッピングに使うので使い方及び実行結果はこんな感じ。

>>> f = PMapFO(FO(3), FO(3), {1:1, 2:3})
>>> print f
[3] --> [3]
 1 | --> 1
 2 | --> 3
dom=3 cod=3 value=[2]

結合と恒等は MapFO と似たり寄ったりなんで、まあいいや。そこは飛ばして RelMapFO のコード。

class RelMapFO(object):
    def __init__(self, a, b, map):
        if not (isinstance(a, FO) and isinstance(b, FO) and isinstance(map, dict)):
            raise Exception()
        for vs in map.values():
            if max(b) < max(vs):
                raise Exception()
 
        self.dom = a
        self.cod = b
        self.map = map
 
    def __add__(self, another):
        if self.cod == another.dom:
            newmap = {}
            for k in self.map.keys():
                vs = self.map[k]
                for v in vs:
                    if v in another.map:
                        newmap[k] = another.map[v]
            return RelMapFO(self.dom, another.cod, newmap)
        else:
            raise Exception()
 
    def __eq__(self, another):
        if self.dom != another.dom: return False
        if self.cod != another.cod: return False
        if self.map != another.map: return False
        return True
 
    def __str__(self):
        s = '[%d] --> [%d]\n' % (self.dom[-1], self.cod[-1])
        for i, vs in self.map.items():
            for v in vs:
                s += ' %d | --> %d\n' % (i, v)
        s += 'dom=%d cod=%d value=[%d]\n' % (self.dom[-1], self.cod[-1], len(self.map))
        return s
 
    @classmethod
    def id(cls, fo):
        map = {}
        for i in fo:
            map[i] = [i]
        return RelMapFO(fo, fo, map)

「PMapFO もそうだったけど、コピペだらけじゃねーかこの野郎」とお怒りの方への説明:ぶっちゃけこれ全部一個もリファクタリングしてないっす。いやー、最初は MapFO からの継承構造を考えてたんだけど、処理をやたら細切れにしないと効果的じゃないのとか、例えば PMapFO が MapFO のサブクラスだったら MapFO の射と PMapFO の射って結合できんのかよという問題(OOP的にはできても良い。域と余域の辻褄はあってるから圏論的にもできると思うけど)とか、いろいろあってやめた。

それでこの RelMapFO だけど、今までは int から int への辞書だったのがリストへの辞書に変わっている。なので使い方はこんな感じ。

>>> f = RelMapFO(FO(3), FO(3), {1:[1, 2], 2:[3]})
>>> print f
[3] --> [3]
 1 | --> 1
 1 | --> 2
 2 | --> 3
dom=3 cod=3 value=[2]

とりあえず一通り実装してみたけど、実装が正しいかどうか確認するのが手間だった。先に出したノートの写真みたく、 FO から FO へのマッピングを手で書いて追いながら検証してたからな。単純に射を作るだけなら難しい話じゃないけど、結合が絡むと途端に怪しくなった。まあ、手で圏の実例を触りながらやった方が勉強になるっちゃそうか。

(23:36)

ロックス・クエストをクリアした。最終的な感想は前にちょろと書いたの時と同じく、非常に満足。それでこのゲームは一体何が面白いのかだけど、そのキーワードの一つは恐らく「緊張感」だろうな。建築パートも戦闘パートも時間制限が大変な緊張感を生み出していて、そしてその緊張感の性質はまるで違う。

建築パート
制限時間以内に要塞を築く必要がある。「あと○○秒で終わっちまう!」という緊張感。
戦闘パート(防衛)
制限時間が過ぎるまで敵の攻撃を防がなければならない。「どうにかあと○○秒耐えないと!」という緊張感。
戦闘パート(拠点制圧・ボス戦)
制限時間以内に拠点を制圧するかボスを倒すかしなければならない。上記二つの入り交じった緊張感。

と逆ベクトルの緊張感が混在しているので、非常にメリハリのあるプレイ感覚だ。

面白さのもう一つは「トレードオフ」。要塞を築く上では大まかに分けると以下の四種類のパーツを組み合わせて行く。

普通の壁。安価に作れるが、それだけでは本当に壁でしかない。
砲台
敵に直接ダメージを与える。壁と組み合わせると強度が上がる、というか組み合わせないとリソースが足りなくなる。
ヘルパー
要塞を修復したり、砲台の性能を上げたりする。これだけではクソの役にも立たないが、これを上手く活用できないと苦戦は必至。
トラップ
地雷の類。極めて安価で効果が高いが、一戦限りの効力しかないので使いすぎるとリソースが足りなくなる。

それぞれに確固たる役割があり、出現する敵の編成によっては神のような強さになったりゴミになったりするパーツもある。例えば地下を潜って奇襲をかけてくるユニットには対地下のトラップが極めて有効だが、そいつが湧いてこないことには設置するだけ無駄になる。また、地下に潜られる前に倒すこともできたりする。同じ事がいえるパーツは対空砲など他にもあり、敵の編成によっては全部の特殊用途のパーツを配置することが無理だったりする。そのため、自分の戦闘技術や敵の編成から取捨選択しなければならず、これがまた非常に悩ましくも面白い。

ちなみに俺のプレイスタイルは要塞の周りを氷結トラップで固め、敵が通行する通りに酸性トラップを仕掛けまくるというものだった。ラスボスに至っては酸性トラップと地雷を通り道にギッチリ敷き詰め、こちらの拠点に到達するころには体力を90%近くけずっていたりした。

というわけで、ロックス・クエストは俺的には名作に決定。カートゥーン調のバタ臭いデザインで敬遠するにはもったいないゲームだぞ。

2009-04-26
Sun

(00:19)

そういやどっかで「日本の RPG は全部携帯ゲーム機で出せ」とかいう記事があって、そん時は「ああ、こいつはデカいテレビに XBox 360 を繋いで人間のハラワタを秒間 60 フレームで描写することだけがゲームなクソ外人だな、死ねよ」と思ったんでろくすっぽ読まなかったし今でもまともに読んでないんだが、俺にとっちゃ据置のゲーム機自体が既に終了済みだ。据置ゲーム機の何が終わっているかというと、

  • プレイする場所が限定される
  • ものにもよるだろうが相当に場所を取る
  • テレビ(あるいは対応した端子を持ったモニタ)に依存してる
  • レジューム・スリープ機能の欠如(Wii にはレジュームがあるんだっけ?)

以上四点。少なくとも俺にとっては据置ゲーム機なぞ存在しないも同然だ。何より現状俺はテレビを持っていないし、据置のゲーム機を今使ってる PC モニタに繋げられるかどうかなんぞまったくわからん。

2009-04-27
Mon

(19:31)

50万円/月ってのは、そのエンジニアに渡る金額じゃあないんだよね? 一体ここからどのくらい(ry

その50万円がどの会社からどの会社へ支払われるお金かで変わるなあ。

最終顧客(実はITゼネコン。真の顧客は別にいる)
         ↓
ピンハネ業者(当然上前をハネて利益を出す)
         ↓
新たなるピンハネ業者(またも上前をハネて利益を出す)
         ↓
下請けソフトウェアハウス

まあ常識的に考えれば50万円という数字は最終顧客の支払う金額ではなくて、最下層のピンハネ業者から下請けに支払われる金額だと思う。というわけで下請けに支払われる金額が50万円だとしたら、エンジニアに支払われる給料は20万円切るだろうな。ソースは俺。

こういう風に書くとピンハネ業者が凄い悪人で下請けソフトウェアハウスが被害者っぽいけど、俺の見聞きしてる範囲での実態はこんな感じ。

            ITゼネコン
               ↓
 ---------------------------------------
| ピンハネ業者兼ソフトウェアハウス(A)       |
|               ↑                      |
|       状況に応じて斡旋し合う              |
|               ↓                      |
| ピンハネ業者兼ソフトウェアハウス(B)       |
|                :                      |
|                :                      |
 ---------------------------------------

多少の力関係の大小はあれど、結局みんなピンハネ業もやってんのよ(要するに共犯)。ここには顧客企業や一次請けのITゼネコンとの繋がりとか、それぞれの会社の抱えてるプロジェクトおよびその要員計画とかいろんな要素が絡み合っていて、その結果がこの持ちつ持たれつなピンハネループなわけだ。いや、あくまで俺の周辺の話だけどさ。

それにまあ、こういった雇用調整の仕組みは基本的には悪いものじゃない。悪いのは「お前もうコード書かないで家でマスかいてろよ」と言いたくなるバカと「マジこいつ無敵。神」なエンジニアで単価に格差があまり出ないことで、それは最初に仕事を請け負った会社の予算という制約がかかってしまうのが原因。その予算も「○○人で××ヶ月でいくら」みたいな計算だから、直請けですら単価について交渉できる余地はあまり多くない。多重下請けの下の方だと交渉の余地なんてない。

もっとも現状の SIer 主導のソフトウェア開発って、素人集めて人海戦術でドバーって感じで、どいつもこいつも一様にダメだから先に出したようなエンジニアの差を考えていない人月計算が通っちゃうんだよな。それで上手く行くのかっていうと、上手く行かねえ事例を目の当たりにしてるわけで、もうちょっとなんとかならねえものかと思っているんだが。

(22:07)

女神異聞録デビルサバイバー」を遊んでいるんだが、評判通りの面白さ。ただ電車の中で遊ぶには一戦一戦にかかる時間が長すぎで、平日にあんまゲームの時間の取れない俺にはその点では厳しいゲームだ。

とりあえず主人公を魔法重視で育成して、初日のボスのウェンディゴを叩き殺したところまで進めた。撃破時のレベルは主人公Lv9、アツロウLv8、ユズLv7。主人公の仲魔は何かしらの機動力強化と騎士の精神持ちにして、アツロウはヒーラーを従えるというのが基本の布陣。この二人で敵のヒーラー部隊を重点的に叩いて、回復と討ち漏らした敵の対処はユズの部隊というのが現時点での作戦。あとウェンディゴからスキルクラックした氷の乱舞が消費 MP に見合ったブルータルな威力で、もしかしたら主人公は物理攻撃も上げて防御は捨て去り、ガードは仲魔の騎士の精神任せというのもありかもしれん。

いや、さすがにそんな戦法が通用するはずもないので、もうちょいバランスは考えるが。でも普通に物理攻撃よりも魔法の方がエクストラターンを取り易いので、魔法中心で育てるのは変わらないだろうな。

2009-04-28
Tue

(22:21)

「層・圏・トポス 現代的集合像を求めて」 勉強会が開かれるようなので、とりあえずその本を買ってきた。勉強会には土日であれば参加可能、というか多分これ勉強会にでも参加しないと俺は途中で挫折して投げるのが確実だと思うので、是非とも参加させてください。

2009-04-29
Wed

(14:40)

何か調子が悪いというかやる気が出ねえから、朝からずっとデビルサバイバーやってる。進行具合としては2日目をクリア。

  • 主人公のステータスは2日目クリア時点で以下の通り。
    • Lv19/力9/魔15/体4/速7
    • 開幕と同時に敵のヤバいスキル持ちに突撃、各種の乱舞で瞬殺が基本
    • 疾風の秘法をつけてるので、敵が行動する前に殲滅可能
  • アツロウは必中の秘法+怒りの一撃が強い。ガンガン敵のエクストラを剥がせる
  • ユズのチームは何か器用貧乏になってしまった。ヒーラー部隊なので腐りはしないが

3日目にさらに仲間が増えて、これからどう育成しようか悩みどころ。

2009-04-30
Thu

(19:30)

デビルサバイバーは3日目をクリア。主人公とそれ以外でレベル格差が広がり始めて、これはちょっとどうにかせにゃならん。どうもこのゲームはステータスの数値にキャラクターのレベルが係数として掛けられてるようで、レベル格差が大きすぎると戦力の計算が面倒だ。

以下、適当にプレイ内容を箇条書き。

  • 3日目クリアの時点でパーティのレベルは主人公28、アツロウ25、ユズ24、ケイスケ24
    • 相変わらず主人公は魔力中心に伸ばしてるので、魔法攻撃の威力がシャレになってない
      • 疾風の秘法付きなので、敵から殴りかかられても結構な割合で先制してそのまま滅殺
    • アツロウは相変わらず壁だが、全体攻撃が増えてくると守りきれないのがちょっとアレだ
    • 仲魔がそれなりに育ってきて回復スキル持ちが増えたので、ユズもアタッカーに回ることに
    • ケイスケの使いどころは邪念の波動持ちと組ませての遊撃隊ということで落ち着いた
      • エクストラを取りにくい編成相手の場合、遠隔攻撃の方が有効っぽいんで
        • ってか、ある属性が弱点の奴と吸収/反射/無効/耐性が同じパーティに居ると面倒にも程がある
  • 3日目の山であるベル・デル戦は凄まじい消耗戦になった
    • 敵を全滅させてベル・デルに殴りかかったはいいけど、途中で敵を召喚されるというアクシデント
    • 解決方法:敵の進路を主人公以外の3人で塞いで壁にする
      • 撃破時点でアツロウとケイスケが戦闘不能、ユズも瀕死 & MP 切れ
    • 配下の悪魔は比較的順調に撃破できたんだけどなあ
  • シナリオはどんどん暗くなってきていろんな意味でいい感じ
    • 自衛隊が民間人を制圧するところとか、良く CERO B で通ったな
      • 今のチンコが右に曲がりすぎな日本じゃ、反社会的描写扱いされてもおかしくなさげ

というわけで4日目を攻略中。

(20:38)

半分以上ネタがわからんかったが、わかるネタは笑えたので別にいいや。一番笑えたのは第二話の冒頭。一体どういう発想してるんだ。