ISUCON6予選で負けたので反省します

ICFPCが楽しかったのでまたチーム戦しようという話になり、かねてから興味のあったISUCON6にチーム「イーグルジャンプ」として、id:pepsin_amylaseとmkutとともに参加しました。Python実装を選び、8時間かけて12830点しか取れず、社会的には完全に人権を喪失しました。以下、反省文です。

やったこと

  • Opsフローの策定 (osa_k)
    • 基本的にはpull-reqベースで開発を進める。masterは常にデプロイ可能な状態に保っておき、featureをマージするときにはmasterからfast-forwardできることを要求する。
    • 設定ファイル類はすべてリポジトリに入れておき、通常のデプロイ操作だけでnginxやMySQLの設定まで変更できるようにする。
    • デプロイ時に変な操作をして環境破壊することを防ぐため、Rundeckジョブを叩いてデプロイする。
  • 本番サーバの他にテスト用サーバを立てる (osa_k)
  • 秘伝のタレnginx.confとmy.cnfをサーバに置くが、たまたまアプリ実装のバグでアプリの起動に失敗し、原因を切り分けるため設定ファイルをロールバックしたまま忘れる (osa_k)
  • RundeckとSlackのインテグレーションを設定する (osa_k)
  • 静的ファイルをnginxで配信する (osa_k)
  • isutarをisudaに併合する (mkut)
  • ついでにスター処理をRedis化する (pepsin_amylase)
  • ログイン処理とキーワード一覧の取得をRedis化する (pepsin_amylase)
  • リンクのsha1をキャッシュする (pepsin_amylase)
  • htmlifyの結果をキャッシュする(別プロセスでひたすら最新30件のキャッシュを作りRedisに突っ込む) (osa_k)

やってよかったこと

情報共有の時間を取る

全員の作業のキリがよくなりそうなタイミングで小休止を挟み、現在自分が何をやっているか、何が分かったかという情報を共有する時間を設けることで、全員が全体の状況を把握できるようになるとともに、改善案を取捨選択して重要そうなものに注力することが可能になりました。相談せずにずっとコードを書いているとだんだんノッてきて書きたいものは増えていくのですが、すべて実装する時間はないのでアイデアの切り捨てが必要になります。強制的に休憩を取ってミーティングを行うことで、全員でアイデアの共有と吟味ができるため、大きな手戻りは防ぐことができました。1人でもそのへんは同じだと思いますが、チーム戦だと誰か1人が言い出せば良いので、アイデア吟味の時間を取り忘れる可能性が下がるのが良い点です。

開発フローを定める

今回はmasterを常にデプロイ可能な状態に保ち、各自がfeatureブランチをmasterから作ってfast-forwardな状態を保つことで全体の信頼性を確保する、いわゆるGithub FlowContinuous Deliveryと呼ばれている手法を使いました。ISUCONのようにあるタイミングで必ず動くものを提出しないといけないというコンテストでは、常にmasterがデプロイ可能という状態は安心感がありました。

ただし、featureの粒度を小さく保つのが難しく、あるfeatureで関係ない箇所のバグに気づいてfixを混ぜてしまい、他のfeatureでもそのfixが必要になったため、masterからではなくfeatureからブランチを生やすというケースが発生してしまいました。こうなるとそのfixを含んだfeatureがrejectされたときに大変面倒な状況になるため、運用には専用のgitコマンド群を用意するなど、ある程度のDevOps作業が必要になると感じました。

やるべきでなかったこと

Rundeckを小規模オペレーションに使う

これが(自分が担当した中では)一番の敗因でした。コンテスト中は、アプリのデプロイ手順はテスト環境でも本番環境でも変わらないという理由により、ひとつのRundeckジョブにテスト用と本番の両方のノードを登録して、ジョブを叩く人がデプロイ先を選ぶ形にしていました。しかし、そもそもRundeckはChefやCapistranoのように、複数のサーバで同じコマンドを同時に叩くというオペレーションが主眼に置かれており、本番とテストのデプロイ操作をひとつのRundeckジョブで共有しようというのは、かなり踏み込んだ自動化をしないと無謀です。実際、テスト用サーバで作業している最中に間違ってデプロイを叩かれ、作業中のデータが消えるという事件がありました。また、ノードのマシン名やログイン情報などは手書きでXMLを編集しないといけなかったり、ジョブ定義のUIが煩雑でTry & Errorを前提とした改修に向かなかったりと、設定作業が割と煩雑なため、どうしても使いたいのであれば、プロジェクトの生成から全部スクリプトで自動化するべきでした。練習中はRundeckジョブを叩いてくれるhubotを運用していたのですが、Rundeckを通してデプロイしていると開発のテンポが悪くなることと、そもそも本番で設定がうまく行かずに動いてくれなかったため、手動でRundeckを叩く運用にしたのも良くなかったです。

とは言えGUIでサーバを触れるようにするという方針は、実行ログや処理内容が一箇所に集約できて管理が楽になるという点で、間違っていなかったと思います。後述のように本番環境と開発環境の分離がうまくできず、Rundeckで管理する対象の大きさが不必要に膨れ上がってしまった点が問題なので、これは本当に集約管理しないといけないか?という切り分けをリソースごとにじっくり考えるべきだったと言えます。

環境設定をしていた時間のほとんどはRundeckの設定を調整していた時間になっていたので、この規模の用途でRundeckを使ったのは完全にオーバーキルであったと思います。使うにしても、設定を可能な限り自動化してやるべきでした。

開発用サーバをケチる

練習の段階では、ローカルで環境構築する手間を省くために個人ごとに作業用VMを立てようという話をしていたのですが、AzureのFree tierプランでは1リージョンに4コアまでしかマシンリソースを置けないという制約があり、面倒だったので開発用兼テスト用サーバの1台しか用意しませんでした。また、前述のようにRundeckの設定が煩雑だったため、ノード数を増やすと作業量が増えてしまうという問題もありました。結果として、3人チームなのに2人しかサーバ環境が使えず、1人はローカルで環境構築する必要があるという二度手間になってしまいました。

急な方針転換はオペレーションが混乱するため、可能な限り避けるべきです。設定ファイルのチューニング忘れも完全にこの辺の混乱が尾を引いてしまった形です。また、アプリの開発環境整備は、処理系のバージョンを揃えたり、DBの導入をする必要があったりと結構面倒な作業を(特にMacを使っていたりすると)含むため、なるべくなら自動化されたものをそのまま使う方が良いです。

開発環境とテスト・本番環境の分離をはっきりしない

開発用サーバとして用意したサーバは、実質テスト用サーバを兼ねており、作ったブランチを試したいときにはアプリをデプロイし、ベンチマークに投げるという運用がなされていました。しかし、当初はデプロイ処理の大部分がRundeckジョブとして記述されており、ちょっとしたテストをするにもブランチをpushしてどこかにデプロイするという作業が必要で、全体で1〜2分ほどかかっていたため、かなりまどろっこしい運用になってしまっていました。

後半ではデプロイ作業の大部分をdeploy.shとしてまとめ、Rundeckジョブではこのシェルスクリプトを叩くだけになりました。こうすることで、開発用サーバ上でも開発者がdeploy.shを叩くだけでデプロイできるようになったのですが、開発環境はコードの編集からデプロイまでの素早いイテレーションが求められ、テスト環境では可能な限り本番に近づけた運用が求められるということに気づかず、ごちゃ混ぜの運用をしていたのは大きなミスでした。そもそも今回は短時間コンテストな上、間違えて環境を破壊しても復帰が容易だったので、テスト環境という概念自体が不要だったと思います。

プロファイルを取らない

ボトルネックの特定は主にnginxのアクセスログの解析と目視のコード確認で行っており、トップページのレンダリングにかなり時間がかかっていることは比較的早い段階で分かっていたものの、キーワードやログイン情報のキャッシュなど、本質的でない箇所の高速化に時間を割いてしまい、htmlifyのキャッシュに取り掛かったのは終了2時間前でした。ちゃんとした経験か洞察力があれば、巨大な正規表現ボトルネックであると看過できたはずなのですが、そうでない以上は闇雲に最適化を進めるのではなく、行レベルのプロファイリングなどで実行時間を測定し、定量的にボトルネックを探すべきでした。

このあたりはサーバ設定が遅れたことでオペレーションが混乱し、データが欲しいときにすぐ得られる状況でなかったため、nginxのログの確認すらスムーズに進められなかったことも大きな原因になっていると思います。環境構築の遅れはとにかく致命的です。

まとめ

せっかくのチーム戦だし、普段から興味のあったオペレーション役をやりたいと思っていたのですが、過度に複雑なオペレーションを組んでしまって爆死しました。開発経験なさすぎですね……。ツールの使い方や最適な開発フローなど、自分1人の開発でも勉強できた点は多かったと思うので、個人プロジェクトでいろいろ試して来年のISUCONまでに経験値を積みます。

ICFPC2016 Team 天羽々斬

ICFPC2016にTeam 天羽々斬として参加しました。チーム名は、直前に観に行ったシン・ゴジラ(名作なのでまだ観てない人はこんなブログ読んでないで今すぐチケットを予約しましょう)で、ゴジラ討伐部隊の1つが「天羽々斬」と呼ばれており、それを聞いた瞬間にシンフォギアだ!!!!となって勢いでチームSlackのドメインをamenohabakiriにしたところ、そのまま流れでチーム名となってしまいました。

f:id:osa_k:20160811023921p:plain

チームメンバーは弊社同期の8人です。8人!多いですね。確か2012年にBoulder Dashやったときも東工大の西8号館にそれくらい集まってた気がしますが、人数が多いとそれはそれでうまく回すのが大変ですね。

ICFPCはチームを組むと作業の分担ができて楽しいのですが、今回も例に漏れず、アルゴリズム班とインフラ班になんとなく分かれるような感じで計画していました。最終的にはインフラ1:アルゴリズム4:手動(!)3みたいな配分になっていました。僕はアルゴリズム力が(比較的)弱い&サーバ周りの作業が好きという理由でインフラをやりました。自分以外の人間が集中的に使うサービスの管理って実際に手を動かさないと勉強できないんだけど、意外とそういう機会ってないんですよね……。

ということで、自分が何をやったのかを中心に、3日間のチームの動きを書いていきます。ちなみに同じチームの id:pepsin-amylase は仕事が速く既に記事を書いているので、合わせて読むと面白いかもしれません。

pepsin-amylase.hatenablog.com

あと提出したコード群。

github.com


0日目

せっかくのチーム戦だし、普段できないサーバの使い方をしてみたいと思ったので、imosさんの記事を参考にして環境を作ることにした。チームメンバーと相談して、結局以下のような方針に決まった。

  • サーバはEC2のr3.8xlargeをスポットインスタンスで使う。1時間あたり$0.4程度が相場のようなので、72時間取っても$30程度。十分安い。
  • ファイルは基本的にサーバ上に置き、各自sshfsでマウントして管理する。imosさんの記事にあるDropBoxはメリットがよく分からないので見送り。
  • 上記の性質上Gitは使えない or 使いにくいため、バージョン管理はしない。定期的にバックアップは取る。 -- マイクロサービス群も特別なデプロイ作業はせず、共有ディレクトリ上から直接実行する。
  • コンパイルと実行は環境を揃えるため、サーバ上で行う(これはあまり徹底されていなかった)。

チーム名が天羽々斬なので、サーバのドメインtsubasa.osak.jpにした。

1日目

開始と同時に公式ブログに飛んで問題文を読む。折り紙を折った後の形が与えられるので、そういう形になるような展開図を構成する問題らしい。えっ、幾何問題なの……。無限精度の有理数ライブラリが必要とされているらしく、ICPCにありがちな誤差ゲーは避けられるものの、多倍長が組み込みの言語かそういうライブラリを持ってないと無理だよなぁという空気になる。GMPを使うかHaskellを使うかみたいな話が出たものの、kawateaが有理数ライブラリを持っていてなんとかなるかもと言っていたので、とりあえず任せることになる。

問題背景のセクションには、大ブッダ像に祝福されたオリガミを供えて庇護を得るだの、古事記にも数々のオリガミが登場するだの、色々とパワーワードが散りばめられている。電通大が主催だし、やっぱりニンジャスレイヤー好きなんだろうなぁ。

1人で黙々とサーバのセットアップをしている間に、他の人々は折り紙の性質について議論をしたり、本物の折り紙を買いに行ったりしていた。開始から2時間くらい経ったところで各人のやっていることをすり合わせるフェーズに入り、いくつかの事実と、いくつかの方針案が出た。

  • 目標となる形がすべて有理数の座標だからと言って、展開図にしたときも有理数の範囲で表現できる座標に収まるの?→折り紙の周は有理数長さでしか分割されないので、必ず有理数の座標が取れる。
  • スコア効率を良くする方法は?→問題サイズによって決まる基準点があり、完全に一致する折り紙を折れたN人でそのうちのN/(N+1)を山分けし、残りの1/(N+1)を完全一致でない人たちが一致度で比例配分する、という採点方式なので、完全一致解以外はほとんど意味がない。近似ソルバ作ってないで厳密解ソルバに全力を注ぐべき。
  • そもそも展開図から折ったときの形って一意に定まるの?→どうやら定まるらしい。今回は重なりの順番は無視していい(物理的に不可能な重なり方であってすらよい)ので、一般の折り紙よりは楽。
  • 凸包を作ってその形に合わせて折っていけばよいのでは?
  • DPっぽく外周になり得る辺をたどって、長さ1の辺を4本復元できたらなんとかなるのでは?

このうちDP解は展開図の復元が無理そうだったので、凸包解をkawateaが書き、その他の人は折り紙の折り方を研究するなり、必要そうなツールを書くなりすることになった。自分はREST APIを使った問題クローラを書いていた。今回は運営側からREST APIが提供されていて、すべてのアクセスはAPI越しでやれ、むしろ人間用のUIをクロールするな、あと1時間に1回しか更新しないから無駄にクロールしてきて負荷かけんな、という今までのICFPCの反省をふんだんに盛り込んだ制約がかかっていて、運営めっちゃ頑張ってるなぁと思った。

クローラを書き終えるころ、yuustiがビジュアライザ書いたんだけど、これWeb UIで見せることできますかと聞いてくる。どんなのを作ったか聞くと、問題ファイルを入力にして、imosさんのJSビジュアライザの関数呼び出し列を吐くようなものだったので、まあ外部プロセス呼び出しでくっつければいいかと思ってSinatraでフロントエンドを書く(この時は多倍長有理数ライブラリをつかっておらず、doubleを超えるような入力が来て破綻したので後でRubyにポートした)。ついでにUserJSを書いて、公式の問題ページからビジュアライザに飛べるようにする。今思えばこの判断は微妙で、とっとと静的な画像を生成して一覧表示しておくべきだった。あと、無駄に1回生成したJSをキャッシュするような機構にもなってたが、プロセスの呼び出しなんてそんな負荷でもないので、ビジュアライザがアップデートされて情報が増えることを考えると、おとなしく毎回生成するべきだった気がする(実際後で何回も問題になった)。

必要最低限のインフラはできたので、次は各人のプログラムをすべての問題に対して実行した結果を残しておき、性能比較ができるようなシステムを作ることにする。とりあえず逆羅刹と名付ける。実行のスケジューリングとかをRubyで書くのは流石にだるかったし、コケたときのログを残すのも面倒なので、JenkinsのParametarized Buildで実行対象のバイナリを指定したら勝手に走らせてくれるようにする、という方針にした。Jenkinsはなんかゴツいイメージなのでカ・ディンギルと名付けた(適当)。

ビジュアライザで古事記(運営が用意した問題は、すべて古事記に記されているらしい)の問題を見て、10番台に1回だけ折った問題が多いことに気付いたkeitakが、1回折り専用のソルバを書いていて、ちょうど逆羅刹の完成と同じくらいだったので試してみる。

f:id:osa_k:20160811143306p:plain f:id:osa_k:20160811143310p:plain

(Problem 11と12)

何回か失敗したものの、ちゃんと走った。実行結果一覧を眺めていたら、これ一括サブミットできるといいよねとkawateaが言い出したので、ボタンを押した瞬間に全サブミットのループが走り、終わるまで返ってこないという闇のエンドポイントを生やす。このあたりで単純なファイルだけではデータの管理が難しくなってきたので、MongoDBを導入する。その後kawateaの凸ソルバも走らせるようにする。ビルドまでJenkins側でやるようにしたら、jenkinsユーザが644の他人のディレクトリに書き込みできなくてちょっと面倒くさいことになったので、パーミッションを777にすることで解決した(sysadの屑)。

yuustiがまたなんか言ってくる。どうやら今度は解答のビジュアライザを書いたらしい。問題ビジュアライザと同じ仕組みが使いまわせるのでそのようにする。今ひとつ役に立つのか分からなかったが、手動でひたすら折り紙を折っては展開し、折り目を見て手作業で座標を計算していた勢(主にhyonhinaとmkut)には便利だったっぽい。

mkutは「ねじり」を理解したとか言って、方眼紙の上でひたすらねじりの入った折り紙の座標計算をしていた。後で聞いたところ、ねじりは大体90度回転させると一致するやつだから問題は普通の折り紙の4倍簡単で、辺をじっと見てうまく繋がりそうなパスを見つければいいだけだみたいな事を言っていた。よくわからない。

f:id:osa_k:20160811143738p:plain f:id:osa_k:20160811143820p:plain

(Problem 19と98)

この辺で手作業で解かれた問題が溜まってきて、とはいえ運営の用意したフォームで提出するとログが残らなくて不便なので、何かしらログが残る手段で提出したいという自然な需要が生えた。インフラしかやっていなくてもその必要性は十分に感じていたので、即座に提出用のコマンドと、サブミットキューを消化していくデーモン(蒼ノ一閃)を作る。このデーモンが止まると点数が取れなくてやばいので、 id:pepsin-amylase が作ったコマンド(レイシス)でチームSlackに死亡通知を流すようにしたところ、文章が面白かったらしくなんかウケた。

f:id:osa_k:20160811041416p:plain

開始から24時間までがLightning Roundで、この時点での1位は別に表彰されるので結構頑張っていたのだが、3位~4位をうろうろしている上、凸包解法ではそれ以上伸ばせそうになく、半ば諦めていた。するとkawateaが突然、手で座標入力したら折れる気がすると言い出してツールを書き、ビジュアライザで表示した頂点の座標を見ながら簡単な問題を手動で解き始めた。やばい。しかし奮闘むなしく、4位(だっけ?)に留まってしまう。

24時間を過ぎたところからは各チームの問題提出が始まる。解答ファイルをアップロードすると運営側で自動的に折られて問題が作られるようになっており、(5000-解答ファイルのバイト数)/(厳密解で解いた人数+1)の点が入る。解いた側の基準点は解答ファイルのバイト数になるため、2500バイト以内であれば提出するだけ得となる。とりあえず古事記にあった、Fの形をした折り紙をhyonhinaが手作業で解いており(やばい)、他のチームも解いていないようなので、こいつをmkutのGideon(解答ファイルを食わせてコマンドを指定すると、平行移動・回転・任意の直線で折り返しした解答ファイルを吐くやつ)でちょっと回転させたものを提出することにして、家に帰って寝た(ここで朝10時くらい)。

f:id:osa_k:20160811144015p:plain

(Problem32 「F」)

2日目

16時くらいに目覚めて会場に向かう。どうやらcronで仕掛けておいたクローラが寝ている間にうまく動いておらず、問題の更新が滞っていたらしい。cronは難しすぎてよく分からないので、クローラもJenkinsで回すことにする。最初からそうするべきだった……。

kawateaが完全に手折り職人と化してしまったので、折り紙ヘルパーを作ることになる。折り途中の折り紙から折りたい辺と面を指定するとその通りに折れるというもので、例によってバックエンドで動くステートレスなC++プログラムをSinatraが叩いてユーザに送り返すというシステムになった。

https://raw.githubusercontent.com/osak/ICFPC2016/master/images/gekirin.png

これを得たkawateaがものすごい勢いで折り紙を折り始め、簡単だけど手入力は厳しいような問題を次々と人力で解いていってしまった。AIなんていらんかったんや……。手動で解いていたhyonhinaとcarbon_twelveも謎の才能に目覚め始め、特にhyonhinaが、未知の折り紙を勘でどんどん実際に折っていっては展開して座標計算してSubmitという行為を繰り返しており、まさに若者の人間離れだと思った。

f:id:osa_k:20160811145728p:plain

(Problem18 「パカ」(yuusti命名) 現実には内側を開いて潰すように折る操作(潰し折り)が必要になるが、今回の問題では過程は無視して展開図さえ作れれば受理されるため、直線で折り返すだけで作れる(途中で面が切れてもう一度くっつく))

その間に id:pepsin-amylaseグレイスを作って平行移動、回転、鏡像反転で同じ問題になるものを使いまわせるようにしたり、yuustiが天空の夜明けを作って非凸の折り紙を1回だけどこかで展開し、凸にした上でkawateaの凸ソルバに食わせ、最後にmkutのGideonで元の線で折るというパイプラインによる解法を開発し、100問くらい解いた(らしい)。Gideonは元々、古事記の難しい問題をもう1回折ればめちゃくちゃ難しくなるだろうし、回転させると適当な合同判定ルーチンしか持ってないチームには解かれないだろう、という発想の出題用ツールだったのだが、問題を解くためのパイプラインになったのは面白い。この方針でもっと解けばよかった気がする。

そんなことをしていたら、なんとUnagiを抜いて1位になった。魔剤?

Unagiは潜伏しているのかもしれないけど、他のチームも似たようなもんだし、こんな探索しづらそうな問題で大きく差は付かないだろうと思い、現状維持の方針を取ることにする。結果的にはこれが完全に分水嶺だった。とりあえず、グレイスが合同かつ未解決な問題をクラスタリングして提示してくれるようになったので、逆羅刹にクラスタを見るページを作り、手動勢は大きいクラスタから解いてもらうようにする。あと、このクラスタが解けたら何点取れるかも計算したのだが、なんか出力がおかしいのでとりあえず放置する。

このへんから、DAOを書かずに色々なアプリケーションから勝手気ままにMongoを叩いていた影響で、あちこちのフィールドで型が想定とズレて死に、火消しに奔走する。朝になって集中力が保たなくなってきたので、帰って就寝。たしか13時くらい。

3日目

寝て起きたらまたクローラが止まっていたらしい。どうやら前日に帰る直前に入れた変更が良くなかったらしい。ずっと起きてると無自覚でも思考能力がガタ落ちしているので、変なことしちゃだめですね……。そもそもなんでテストしなかったのか。

点数計算のバグがわかる。Problem IDから自分のベストスコアへのHashだと思ってたオブジェクトが実はArrayだったため、変な数値を計算に使っていた。静的に型の付かない言語はこれだから……(責任転嫁する屑)

夕食に寿司を食べていたら、スコアボードも寿司になっていた。一瞬もう凍結されたのかと思った。

Unagiとギリギリ競っているので、Unagiが解けなさそうな問題を出して差を広げようという話になる。とりあえずUnagiがFの折り紙を解けないとは思えないので、もっと難しい問題を作りたい。Unagiが提出している問題を見ると、そもそも折っていくにしろ開いていくにしろダントツで難しい。そこで、Unagiは古事記くらいは解けるにしても、彼らが自分自身で出している問題は解けないんじゃないかという仮説を立て、同じような問題を作ることにする。が、そもそもUnagiの問題が手動でも解けない。仕方がないので、Unagiの問題を解こうとしながら天ノ逆鱗で試行錯誤している最中にできた、Unagiの問題もどきを提出すればいいのではないかとkeitakが主張し始めたので、そういうのを出してみることにする。Unagiの似非なので穴子と命名される。

f:id:osa_k:20160811145533p:plain

(Problem3937 「穴子」)

穴子を出して様子見していたところで2時になる。と、Unagiが10万点くらいスコアを上げて一気に引き離された。えっまじで。潜伏していたのはいいにしても、戦闘力が想定と全然違うっぽい。やばい。 このままだと2位も危うそうなので、特殊ソルバでもいいからもっと頑張って作ろうということになる。自分が起きてくる前に問題一覧をサーベイした人たちによると、yowaさんの問題がかなり特殊な形式になっているらしく、簡単(簡単とは言っていない)な貪欲で解けるらしい。id:pepsin-amylase が専用のソルバを書き始める。

f:id:osa_k:20160811151742p:plain

(Problem1726 ひとつ角を固定し、その角を通るような直線で扇状に折りたたんだ図形になっている。対角線で折られることがないようなので対角の特定が容易にできて、あとはその角から生えている2辺を特定すればよい。)

スコアボード凍結直前の3時。Unagiが70万点くらい、天羽々斬が20万点くらいと、もう話にならなそうな差が付いている。既存の問題を見てみても、1チームだけが厳密解を提出しているものがザクザク出てくる……。これはどう考えてもUnagiが厳密解ソルバを持っているということなので、今から勝つのは無理っぽいし2位維持をがんばろうということになる。つらい。

インフラはいい加減やることがなくなってきたので、少しmkutと議論をする。与えられたシルエットから面どうしの繋がりを維持しつつ正方形にパッキングしていく問題を考えると、探索として解けるかもしれないらしい。ぱっと見はめちゃくちゃ計算量が大きそうだが、確かに色々な枝刈りが考えられるので、枝刈りのプロがいれば実装できるかもしれない。しかし6時間でバグなく高速なソルバにできる自信はなかったので見送られてしまった。

そうこうしている間にyowaソルバが完成する。数回のデバッグと実行を経た後、yowaさんの問題をすべて解くことに成功する。やったー。

また、Skobochkaというチームが、細長くたたんだ折り紙をS字に曲げたものを大量に出しているのを発見したので、yuustiがソルバを書き始める。正確には最初はめんどくさがっていたのだが、Gideonで折る面と折らない面を区別できるようになったら実装してやると言ってmkutを煽っていたところ、mkutが実際にGideonをアップグレードしてしまったため、ソルバを書く羽目になっていた。かわいそう。 残念なことに、このソルバは終了までに間に合わなかった。

f:id:osa_k:20160811153218p:plain

(Problem3961 「S」)

kawateaとhyonhina、keitak、carbon_twelveがひたすら手動で問題を説き続け、時間が来て試合終了。結局手動解法に偏りすぎてしまったのが少し残念。

反省

成り行き上仕方なかったとはいうものの、1人でインフラを全部回すのは厳しかった。システムを作るところまではまあいいけど、実装に使う技術をちゃんと考えておかないと、だんだん体力が削れていく中でデバッグと保守を行うことになり、少しずつシステムが壊れていく。

チームの戦略としては、ソルバにモジュール性を持たせて、雑ソルバでもいいから量産するべきだった。というかそういう風にしたかったのだが、インフラ開発が忙しすぎて自分ではソルバが書けなかったので、他人を説得してそういう方針に引きずり込むのもちょっと難しいという状況になっていた。チームで反省会をしたときにも話題に出たが、数時間に1回くらい完全に作業を中断し、みんなで状況を共有して次の一手を決めるような会議が必要だと思う(というのをICPCに参加していたときからずっと言っているができておらず、成長していない……)

とはいえ、良いサーバを使ってマイクロサービスを立てまくるのは、サービスの本当に最初期の設計を考えるという点でかなり得るものがあった。人数が少なければ指数的に規模が膨らむことはないので、精神的に余裕があれば割といつでもリファクタリングはできる。ファイルベースの管理からMongoに切り替えるとかね。ただし複雑度は指数的に膨らんでいくので、ある程度長期に使われそうなコードならバグりにくい設計を考えておくべきだと思った。あと既存かつ実績のあるプロダクト(Jenkinsとか)はハマリどころが少ないので神。

また、一般論としてサーバサイドアプリとしては異常な構成であっても、割りきってコードの簡略化やモジュール化を進めるのはかなり有効だった。たとえば、REST APIを叩くときにはRubyのNet::HTTPではなく外部コマンド実行でcurlを叩くようにしたり(楽だから)、stdin / stdoutを介した通信でバックエンドのC++プログラムに面倒な幾何をすべて任せたりすることで、管理しないといけない領域を効果的に狭めることができた。

Gitを使わずにsshfsでみんなのファイルを共有して、かつ即デプロイするような環境を作ったのは一長一短だった。他人の成果物へ即座にアクセスできるのはかなり使いやすい。しかし、誰かが使っているコマンドやサービスを改修しようとすると必ず干渉してしまうという欠点がある。特にSinatraのviewは変更が即座に反映されるので、実装途中の機能がユーザに見えてしまうことがよくあって一瞬ではあるものの混乱を招き、精神的に負担が大きかった。

総括

3日間ずっとめまぐるしくコードを書いていたのは楽しかったです。自分がインフラを作っていると、他の人がインフラを使って成果を出してくれるという体験をこの密度でできるのは、なかなか得難い体験ですね。折り紙という題材を最初に見た時はどうなることかと思いましたが、最初の印象以上に問題もジャッジシステムも完成度が高く、ずっと飽きずに、かつシステム面でフラストレーションが溜まるようなことがなく、遊び続けることができました。

チームの動きとしては、もっと探索して計算機の力を使うようにするべきだった感はあります。なまじ人数が多いというのも考えもので、今回のように人間がある程度能力を発揮できる問題だと、すぐに人海戦術に流れてしまう。4,5人しかいなければ確実に探索の方針を考えていたのではないかと考えると、もっといい戦い方はできたんじゃないかなぁと思います。

来年はうなぎに勝ちたいですね。

Windows10 on VirtualBox

Windowsでないと動かず、かつ使えないと困るプログラムがそれなりにあるので(ScanSnapのドライバとかiTunesとか)、立てて放置してた自宅サーバにWindows10を入れることにしました。まあWindowsにホストは渡したくないのでVirtualBox上です。

一応Headlessでサーバ管理したいみたいな目標があるので、GUIフロントエンドを使わずにVBoxManageでちくちく頑張って仮想マシンを立ち上げることにしました。よく分かんないので適当にぐぐったところ、良さそうなページを見つけたので、真似して以下のようなコマンド群でVMを作りました。

$ VBoxManage createvm --name Windows10 --ostype Winddows10_64 --register --basefolder `pwd`
$ VBoxManage createhd --filename Windows10/Windows10.vdi --size 20000
$ VBoxManage storagectl Windows10 --name "SATA Controller" --add sata --controller IntelAHCI
$ VBoxManage storageattach Windows10 --storagectl "SATA Controller" --port 0 --device 0 --type hdd --medium Windows10/Windows10.vdi
$ VBoxManage storagectl Windows10 --name "IDE Controller" --add ide
$ VBoxManage storageattach Windows10 --storagectl "IDE Controller" --port 0 --device 0 --type dvddrive --medium host:/dev/sr0
$ VBoxManage modifyvm Windows10 --ioapic on
$ VBoxManage modifyvm Windows10 --boot1 dvd --boot2 disk --boot3 none --boot4 none
$ VBoxManage modifyvm Windows10 --memory 2048 --vram 64
$ VBoxManage modifyvm Windows10 --nic1 bridged --bridgeadapter1 enp0s25

DVDドライブをIDEで繋いでてちょっとどうなのという気がしなくもないですが、変にアレンジしてハマるのも嫌だったのでそのままにしました。長いものには巻かれろ精神です。この状態でWindows10のインストールディスクを入れて

$ VBoxHeadless -s Windows10

するとVMが立ち上がるので、

$ rdesktop kadingel:3389

とかやってリモートデスクトップで繋ぎます。するとインストーラが出てくる……はずだったんですが、CPUが64bitに対応してないよ的なエラー(0xc000035a)が出てきて進めませんでした。ちゃんとCPUは64bitだし、VT-xも有効化してるのにどういうことなんだ……。

しばらく調べてると、どうやらWindows10は新しいチップセットしかサポートしていなさそうという情報が見つかったので、

$ VBoxManage modifyvm Windows10 --chipset ICH9

すると、今度はうまくインストーラが立ち上がってくれました。ハマるの嫌だから先に色々調べたのに、結局3時間くらいかかってしまった。

原田ひとみ アコースティックライブ2016

原田ひとみのアコースティックライブに行ってきた。そもそも原田ひとみを知ったのが2007年頃にアニメ経由でefを知って、ゲームPVで聞いた悠久の翼に感動したのが初めなので、実に9年の時を経てついにライブイベントで実物を見られたことになる。

事前に1stアルバムのglanzendを何回か聞いたが、結論から言えば、今回のライブはカバー曲ばっかりだったので特に関係なかった。自分は声が好きなので、カバーでも聞ければよいというスタンスである。

カバーとはいえ、原田ひとみのよく通る力強い声で歌うと、元の曲とはまた違った味わいがあって楽しい。歌い方や声質の似ている林原めぐみの「Infinity」や島谷ひとみの「アンジェラス」はもちろんうまくハマっているし、アイマスの「エージェント夜を往く」や初音ミクの「メルト」もとても良かった。というか、メルトを生で安定して歌えるのがやばい。人間を殺しにかかってくる高音部もなんなく歌い上げ、その後すぐに普通の声に戻してまったくブレないのは、さすがと言ったところ。

MCトークも面白かった。Twitter等で結構エキセントリックな人だというのは知られているが、現実でもあのままの言動で、隙あらばおっぱいの話をしている。入院中に暇だったからという理由で一気に作り上げた同人ノベルゲームが、周囲の知り合いにイラストや音楽、声を頼んだらみんなプロだったので、同人とは思えない異常に豪華なキャストになっているという話は、面白いというのはもちろん、純粋にすごいと思った。これが業界人か……。あと、MC中も座っている回転椅子を左右に振ったり、履いているタイツをしきりにいじったりしていて、落ち着きがないのがちょっと面白かった。

坂本真綾の古いアルバムの曲や、「ショムニ」の歌を歌いつつ、新人声優が10代でジェネレーションギャップを感じるという話から、犬夜叉の「アンジェラス」は最近だからみんな知ってるよね!と言い始めたのは様式美という感じ。犬夜叉ってもう12年とか前……。

最後は回レ!雪月花で、全員起立&ペンライト振り。音域のやばいメルトはちゃんと歌えてたのに、早口がやばいこの曲は途中で歌えなくなってた。まあしょうがないね。

欲を言えば、efの曲を歌ってほしかった。とは言ってもefすらもう8年とか前の話なんだよなぁ。

最近見た映画

アイアムアヒーローとレヴェナントのネタバレを含むので注意してください。

アイアムアヒーロー

予告編が邦画にしては感動っぽい要素がなかったり、音声による煽りがなかったりして、かなり攻めている要素があったので面白そうだと思っていた。見ようと思ってタイミングがなくずるずると先送りになっていたのだが、Twitterで評判が良かったのでこれは観ないといけないと思って映画館に行った。

少年漫画のように、かなり分かりやすくヒーロー物という内容だった。鬱屈した主人公であるヒデオがZQN(要するにゾンビ)と戦って成長する物語……というと荒すぎるか。劇中を通して徹頭徹尾臆病で、ZQNに襲われれば腰を抜かし、散弾銃を持っていても外で撃つと銃刀法違反だからと言って撃たず、道中で助けて行動を共にした女の子にも手を出さない、そんなヒデオが最後の瞬間だけ、自分を信じてくれた人と自分が守りたいと思った人のため、自分から進んでZQNの大群との戦いに身を投じる。そんな最後の瞬間で最大限にカタストロフィを生み出すため、それだけのために途中の全ての展開が存在したのだという、説得力のある清々しさを感じた。最初は照れと自虐、それと願望の混ざった感じに「英雄と書いてヒデオです」と言っていたのが、最後に仲間を助けて本当の英雄となった途端に「ただのヒデオです」と言ったのは、本当に等身大のヒーローという感じでよい。ヤブに評価されていた、ヒロミちゃんを助けてZQNを発症しても連れて歩いたというエピソードも、ギリギリ普通の人でもできそうというラインを保っていて、過度に超人という描写がないのがすごい。

逆に本筋以外のストーリーについては、全体としての完成度を損なわせるまでではないにしても、多少のアラが目についた。富士山に向かえばZQNの感染を阻止できるという情報をすんなりと信じた点や、高飛びを繰り返している陸上選手のZQNを危険視せず放置していた点など、ストーリーを進めるためとは言え、強引でご都合主義という面は否めない。ただ、ヒデオの英雄譚という観点で言えば、特に問題になるほどではないと思う。

あと、予告編を観て、コメディタッチの映画かと思っていたら、かなりZQNの描写がえげつなくて少し後悔した。叫び声とともに突然アップでZQNが襲いかかってきたり、ZQNを鈍器や刃物で攻撃して肉が見えたり、逆にZQNに食われた人間に痛々しい食い跡があったり……。最後の展開のためにこの映画を見る価値は確実にあったが、それでも怖いのとか痛いのは苦手……。ただ、そういう層を取り込むという意味でも、コメディだと思わせる予告編の演出には意味があったのだと思う。実際、怖いゾンビものだと分かってたら観なかったと思うし。

レヴェナント

これも予告編で観て、子供を殺された父親の復讐譚というニンジャスレイヤーのようなストーリーに惹かれた。子供を殺した犯罪者集団を父親が次々と殺していくタイプの話かと思っていたのだが、予想に反して、フィッツジェラルドに子供を殺されたグラスが、フィッツジェラルドのみを標的として、瀕死の状態から蘇って追跡の果てに殺すという、かなりストイックな物語だった。

役者の演技はどれもうまく、映像は美しいし、アクションも派手でこそないものの息を呑ませるシーンが多いので2時間半という長丁場にも関わらず飽きることなく観ることができたのだが、やはり次々と敵を殺していくという話を期待していると肩透かしを喰らった。性質としてはおそらくオデッセイに近く、グラスがいかにして死の淵から蘇り、途中で出会った人々と関わりつつフィッツジェラルドに肉薄していくかという、泥臭い道程を追体験することに主眼がある作品なのだが、やはり映像では泥臭さの表現に限界があり、淡白になりすぎてしまっている印象を受けた。

明確な悪役とヒーローがいるのではなく、どの登場人物も各人の信念に基いて正しいと思う選択を取り続けており、わずかな不運によって悲劇が起こり復讐劇に繋がっているという設定が、アメリカ映画にしては珍しく感じた。しかも復讐という、基本的には復讐する側とされる側の双方にとって不幸な結末が待っていることの多い題材に対して、最終的にグラスがフィッツジェラルドを殺すことに成功し、そのグラスも雪山で力尽きつつ愛したポワカ(でいいんだよね?)の幻影を見て終わるという、ある種のハッピーエンドにも見える結末になっており、爽快感こそないものの、現実はこんなもんだよねという、地に足の着いた物語だと感じた。

原作が小説であるためか、オデッセイと同じく映画としては説明不足な点もある。アリカラ族の娘のポワカについては、グラスがポワカを奪い、その子供がホークであることを示唆する言動は多々あるものの明確には言及されなかったし、アリカラ族がポワカを求めてアメリカ人を追っていることの背景についても、彼らがなぜ強くこだわるのかの説明はなかった(ホークが既に青年と言える歳なので、ポワカの事件は20年程度昔の話であるはず)。また、アメリカ人たちが毛皮商としてインディアンと戦いつつも毛皮を買っている理由もあまり明らかではなかった。アメリカ史としては常識なんだろうか?

俳優の演技は総じてクオリティが高く、特にホークの心の奥底に色々な思いを貯めこんでいるような青年の演技と、ブリッジャーの経験の浅さからくる優柔不断さと、フィッツジェラルドの断定的な決断に流されてしまう演技はかなりリアリティがあった。

ワイルドアームズ日記 その18

引き続きマルドゥークの攻略を続ける。次は神殿エリアへ。

神殿エリアの石碑は、ダンジョンの攻略方法ではなくてマルドゥーク関連のアイテムの解説が書かれていた。神器と呼ばれる3種類のアイテムを集めることでマルドゥークの中央制御室へと入ることができるらしい。神殿ダンジョン自体はスイッチを切り替えて扉を開け閉めしていくタイプの仕掛けで、歩きまわるタイプの仕掛けにしてはエンカウント率が高めなこと以外は特に苦労せずに進むことができた。

道中に石碑があり、後ろの隠し通路を通るとゴーレムのルシファアと戦えると書いてある。ただしめちゃくちゃ強いとのこと。まあでもバルバトスだって倒せたし行けるでしょー。

奥には火が燃えているが、マジックポットで消火しても何も起きない。もしかしてと思って試しにオールドギターをかき鳴らすと、ルシファアが現れて戦闘になった。こいつが思っていたよりも10倍くらい強い。初手で全体攻撃をしてきたかと思ったら、2000弱のダメージを食らう。えっこれやばいじゃんと思って回復しようとしたら、次のターンに先制されてセシリアが倒された……。アンブロシアで全体回復しつつフル・リヴァイブで生き返らせようとしたが、動揺して間違ってネクタールを使ってしまい、後手に回ってしまう。その後も崩れに崩れて、あっさりと全滅してしまった。念のためセーブしといてよかった……。

ルシファアはやばそうなので後回しにして、マルドゥークの腕を回収する。体のパーツが分かれてるのを集めるってエグゾディアみたいだな。

最後は鉱石採掘エリア。石碑には、機械に宿った心が道を示すと書いてある。機械と心……ロディ?よくわからんのでとりあえず進んでみるも、特に何も起こらない。うーん、一体なんなんだ。

そんな感じで潜っていくと、マルドゥークの瞳をあっさり入手した。結局石碑のヒントは使わなかった。なんなんだろう。

制御室に戻り、集めた神器を扉の前に置いてみる。腕と翼は置くと光を放ち始めたが、瞳は何も起こらず、ニセモノなのかっ!?と言われる。確かに鉱石採掘エリアから戻るとき、他に開かない宝箱があったな……。ここから本物を探し出さないといけないのか。

ニセモノを宝箱に戻し、適当に他の宝箱を開けて瞳を取り出してみる。さっきの光というヒントから、本物は取り出した瞬間に光るか、もしくは青い部分があるんじゃないかと思っていくつか試すが、どうもどれも変わらなさそうに見える。そもそも青だとマルドゥークの腕とかぶるし……。悩みながらダンジョンをさまよっていると、何やら意味ありげな部屋に出た。そこの前に置いてある石を爆弾で壊すと、真実の目のようなオブジェがでてきた。あ、もしかしてこいつがマルドゥークの瞳の真贋判定をしてくれるのか!

さっそく一つ拾ってきたところ、真実の目が青く光った。これが正解か。というか一発で正解を引いてしまった……。ちなみに真実の目の部屋の向こうにはゴーレムの1体であるセトがいるらしいが、さっきのルシファアで懲りたのでこいつも後回しにする。

手に入れた瞳は無事に輝き出し、中央制御室の扉をくぐる。するとゴーレムの1体、ベリアルが立ちはだかる。こいつも激強なのかと思いきや、アーマーダウンをしてきたりちょっと強めの全体攻撃をしたりする程度で、死にそうなほどのダメージは喰らわない。いつもどおりの戦術で倒し、中央制御室へ入ることができた。

中央制御室にはジークフリードが待っていた。やはりマルドゥークの力でファルガイアを破壊する気マンマンのようなので、そんなことをさせるわけには行かないと戦闘に突入した。攻撃自体はあまり大したことがなく、全体攻撃があるもののヒール・プラスで対処できる程度。ちょっと拍子抜けだった。

ジークフリードを倒すと、突然苦しみだし、破壊が真理などとマザーのようなことを言い出した。それどころか、どこからか闇を呼び出してファルガイアを包みこんでしまった。

そしてマザーと融合した真の姿、マザーフリードを現す。さっきまで戦っていたジークフリードは既に抜け殻であり、実体は完全にマザーに支配されてしまっていた。

マザーフリードは全体攻撃+状態異常付与であるアルス・マグナを撃ってくるのが面倒くさい。初見で食らって回復に手間取ったが、一度見たらステータスロックをかけておけばよい。クイックやハイ・シールドも一応使ったが、魔法効果の解除もしてくるので、一度解除されてからはターンの無駄なのでかけないようにした。

マザーフリードを倒したものの、滅び際に、ファルガイアを包んだ滅びの力は振り払えないという捨て台詞を残していった。このままファルガイアは滅んでしまうのか……。

そんな状況でも諦めない渡り鳥一行の思いに反応して、涙のかけらが輝きだした。取り戻された生命の力を用いて、ガーディアンたちがファルガイアの闇を取り除きにかかる。

ガーディアンたちの力で、闇は振り払われた。人間の心は傷ついて荒んでしまったが、時間をかければ元に戻り、ファルガイアの荒廃を止めることもできるだろう。そして、その奇跡を起こせる存在は、ファルガイアのガーディアンたる人間でしかない。

世界を救うという一仕事を成し遂げたので、転送装置を使ってカ・ディンギルへ戻る。

……カ・ディンギルへの転送中、突然ジークフリードが現れた!マザーに喰われて共に滅んだかと思われたが、その執念でマザーから逃れ、この不安定な次元のはざまで渡り鳥一行と戦うことで暴走を起こし、滅びへの道連れにしようという。そんな勝手な思惑に乗って滅ぶわけには行かない。

ジーク・ツヴァイは特に強い攻撃はしてこないが、状態異常魔法で混乱や魔力封印をしてくる上、HPが減ってくるとハイ・ヒールも使ってくる。ちょっと、シドーじゃないんだからそんなんどうやって倒せばいいんだ……。とりあえずステータスロックで状態異常を避けつつ、高火力の攻撃を叩き込み続ける。かなり長引いたものの、ハイ・ヒールを使わないターンと、ブーストアタックの発動をうまく重ねることで、なんとか倒すことができた。

ジークフリードの思惑はここで渡り鳥一行を倒すことではなく、亜空間に衝撃を与えてもろともに吹き飛ぶことであった。分かってはいたけど避けられない。

カ・ディンギルの崩壊が始まる。幸いというべきか、転送座標がずれたことにより、渡り鳥一行はカ・ディンギルの外に転送された。しかしこのままではカ・ディンギルの爆発に巻き込まれてしまう。

するとアースガルズがひとりでに動き出し、3人を対消滅バリアで守り始めた。アースガルズもまた、戦うためだけではない、自分の意志で大切なものを守る心をもった機械だった。

爆発から3人を守ったアースガルズは、そのまま機能を停止してしまった。魔族との戦いが終わった今、アースガルズはもはや戦う必要はなく、また安らかな眠りに戻ることができた。

世界を救った一行。ロディとザックは自分たちの力を求める人々を救うため、また渡り鳥として旅に出た。一方公女であるセシリアは、アーデルハイド城に残ることになり、2人に手紙を渡して別れることになった。

手紙の中で、ロディとザックに教わった、大切なものを守るという思いと、そのために自分もできることをやることにしたと心中を語るセシリア。手紙の結びには、もうすぐ2人の元へ忘れ物が届くと書いてある。

何を隠そう、忘れ物とはセシリア自身だった。公女でありながら、世界を守るという目的のために、アーデルハイド城を出て、また3人で旅をするという道を選んだセシリア。先は長いが、奇跡を信じて努力を積み重ねていけば、ファルガイアは少しづつ復活していくに違いない。

それは、ぜったいに、ぜったいですッ!

ワイルドアームズ日記 その17

カ・ディンギル……の前に天の回廊再チャレンジ。行き止まりの前にある踊り場で涙のかけらを使ったら大賢者ディーが現れ、セシリアに新しいフォース「デュアルキャスト」をくれた。しかしセシリアはラフティーナのハイ・マテリアルが強すぎるからたぶんフォース4つも溜めないんだよなぁ。

カ・ディンギルに入ると、そこにはブーメランが待っていた。ブーメランによれば、ジークフリードはカ・ディンギルを使い、宇宙に浮かぶ攻撃用コロニーである「マルドゥーク」を手中に収めようとしているらしい。そこまで教えてくれるなら早く通して欲しいのだが、こいつは文字通りの戦闘狂で、ここまで教えたからには渡り鳥一行はカ・ディンギルを通ってジークフリードを止めに行かざるを得ず、そのためにもここを通せんぼしているブーメランと戦わざるを得ないだろう、という思考を持っていた。こいつアルハザードとかジークフリードから裏切り者って言われてたのは、卑怯だからじゃなくて、単に自分が強い相手と戦うためにはチームの利害すら考えずに行動するからか……。ゼットと似たタイプのアホだ。

しかし攻撃パターンはいつもと変わらないので、ハイ・シールドしてからルシエドを袋叩きにすれば、ブーメラン自体はそんなに攻撃力も高くないので楽勝になる。もっと頑張れよ。

戦いに負けると満足気に道を開け、ジークフリードの野望を阻止するがいいとか言ってくれた。本当に魔族のこととかどうでもいいのね。しかし当然ジークフリードの気には食わず、ブーメランもろとも渡り鳥一行を始末するべく、モンスターをけしかけてきた。また戦闘かと思っていると、なんとブーメランがモンスターに立ちはだかり、渡り鳥一行は先に行けという。おい、強い敵を育てるためとはいえ、そこまでするのか。しかもそれ死亡フラグじゃん……。

一度中に入ってから外に出ると、既にそこにはモンスターとブーメランの姿はなく、戦闘中に彼が何度も使っていたクレッセントファングが落ちているだけだった。おい……。クレッセントファングは武器かと思ったら誰も装備できないし、戦闘中にも使えないんだけど、この後どうなるんだろう。

カ・ディンギル内部はいつもより難しめのパズルで埋まっていた。最上階にはカ・ディンギルの転送装置があり、 そこではアルハザードが待ち構えていた。レディ・ハーケンの生体反応がなくなったことを、最高傑作のおもちゃが壊されてしまったと残念がり、こいつもこいつで、ジークフリードの計画などどうでもよく、ただおもちゃで遊べれば良いという。こいつら本当に協調性ないな……。そしていつも被っているローブを脱ぎ捨て、真の姿で戦闘が始まった。

基本的には弱めの全体攻撃を繰り返す感じなので、セシリアがハイ・ヒールをしながらいつも通りにABMランチャーとマグナムファングで殴る。5ターン目あたりで眠らせる攻撃をしてきてやばいと思ったが、その直後にロディとセシリアが起き、また眠らされても嫌だしなぁと思ってステータスロックをかけようとしたら、その前に勝ってしまった。えっ、弱くない?

あれだけ威勢がよかったのに、最後には弱音を吐きながら滅んでいくアルハザード。こうして見ると、自分の滅びさえ喜んでいたマザーはある意味異常なまでに器がでかかったんだなぁ。そして宿敵が滅んでいく様を見たザックの心からも霧が晴れ、最後のフォース「ダブルコマンド」を習得した。

亜空間エレベータを起動して「新しい月」マルドゥークへ飛ぶ。回復してないけど大丈夫かな。でも一度出てもっかいここまで来るの面倒くさいしな……。

マルドゥークへ到着した。敵が強く、一撃で500くらい削る全体攻撃魔法をバンバン撃ってくる上、HPが3000程度と高くて、魔法を積極的に撃っていかないと長引く上に安定しづらい。道中で新しいARMのアークスマッシャーと、ザックのアイテムであるオールドギターを手に入れた。アークスマッシャーは初の全体攻撃ARMで、威力も200と高いが、弾数が3発しかないのと命中率が70%と低めなので少し使いづらそう。まあ強化すればいいのか。オールドギターは完全にネタ枠で、使うと強制的に戦闘が始まるらしい。こんなところで使うと面倒くさい敵が出てくるだけなのでまだ使ってない。

奥にはセーブポイントと転送装置があり、マルドゥーク内の様々な区画に転送できるようになっている。そのうちの一つである居住区に行くと、ここから先は偽りの街という警句があり、実際に町中の家から聞こえてくる話し声は、どれも嘘ばかりであった。しかし必ず嘘と分かっているならそれはそれで情報であり、それらをヒントにしながら墓場を探索して、マルドゥークの翼を見つけた。あと2箇所行けるところがあるから、もう2つ起動アイテムを入手すればいいのかな。

回復ポイントがなく、ひたすら呪文とアイテムで回復する運用になっているものの、マジックキャロットが腐るほどあるのであまり問題はない。バレットチャージは7個くらいしかないので、ARMはあまり適当に撃つわけには行かない(ここに来るまで、1回くらいは町に戻るだろうと思ってバニシングレイを雑魚敵に打ちまくった結果、弾切れになってしまった)。まあでもこのまま突っ切れそう。

次回はアイテム集めから。