最近見た10個の007の感想

この2ヶ月で、なぜか007を10作品も見たので、感想のようなものを垂れ流してみる。 バラバラなのは自分で見た順だから。 見た順がバラバラなのは、特に理由はないです。

あとネタバレは特にないはず。

ゴールデンアイ

これを最初に見たのは理由があります。 小学生時代は NINTENDO64 ブームでゲーム版ゴールデンアイも流行ってたソフトの一つでしたが、我が家は64を買い与えられずとても悲しい思いをしました。
で、20年経ってこの前イタリアに行ったとき、フライト中の映画にゴールデンアイがあることに気づいて、かつての自分の悲しさを弔うために見ました。

肝心の映画の方ですが、娯楽映画だなってのが第一印象でした。良くも悪くも。 007全然知らないんで、もうちょっとシリアスだと思ってたんですよ。

これを見た後になんとなく他の作品が気になって、帰国後に色々と見てみることに。

カジノ・ロワイヤル

こっちは逆に思った以上にシリアスでびっくり。ゴールデンアイからの落差たるや。

でもダニエル・グレイグかっこよすぎ。アクションかっこよすぎ。オープニングもエンディングかっこよすぎ。
友人が「カジノ・ロワイヤルの欠点は他のグレイグボンドが見劣りすること」って言ってたのも納得。

慰めの報酬

これはなんというかこう、地味でしたね…… カジノ・ロワイヤルと比べるどうしても見劣っちゃう。

友人が「カジノ・ロワイヤルの欠点は他のグレイグボンドが見劣りすること」って言ってたのも納得。

トゥモロー・ネバー・ダイ

またピアーズ・ブロスナンのボンドに戻って娯楽映画っぷりにびっくり。 好みかって言われると微妙だけど、ストーリーがわかりやすくていいですね。

あとボンドカーはこれが一番印象深い。 あのデバイスは時代を先取りしてたと思う。

ダイ・アナザー・デイ

最初の展開には「なんだ超シリアスか!?」って思ったけど、やっぱりブロスナンの007でした。

黒幕の正体になかなか気付けなかったので、気付いた時には「……ああ!」ってなりました。 そういう意味では他のブロスナンボンドと比べて凝ってる気がする。

ロシアより愛をこめて

ここらで原点回帰で初代ボンドの作品見るかと思って、ショーン・コネリーの名作と呼び声が高いのを選択(なぜ1作目を選ばなかったのか)。

おもしろいけど、ちょっと地味かなぁと(ダイ・アナザー・デイの後に見たのがよくなった)。

死ぬのは奴らだ

ショーン・コネリー作品みたし、次はもっと作品数が多いロジャー・ムーアの見るか!」と思って選びました。 特に気づいてなかったけど、これがムーアの最初らしいです。

この作品はボンドガールが人気らしいけど、俺が一番好きなのはあの高笑いです。 あのどうあがいても印象に残るあの高笑い。

あとポール・マッカートニーのオープニングもいいですね。

ユア・アイズ・オンリー

ムーア作品もうちょっと見るか思って、適当に選びました。

正直、これはあまり印象に残ってない。 ムーアのボンドが俺の中であまりパッとしなかったのが要因かも(「死ぬのは奴らだ」もボンドより高笑いが印象に残ってる)。

リビング・デイライツ

ロジャー・ムーアの頃の作品はあまり好みじゃないことがわかったので、ティモシー・ダルトンの作品を選んだんですが、これ本当に好きです。

自分の中では、すごいバランスがいい作品。 アクションもあるし、秘密兵器もあるし、敵キャラも魅力的。 ストーリーもちゃんとあって、BGMはOPだけでなく敵キャラのテーマ(?)もかっこいい。

そしてなによりダルトンの演じるボンドがいい感じに渋い。 グレイグよりは人間味があるけど、ムーアやブロスナンほどチャラくない。 ボンドの中ではダルトンが一番好きですね。

消されたライセンス

リビング・デイライツが個人的ヒットだったので、ダルトンの次の作品のコレも見ました。 ダルトンは相変わらずかっこいいし、ストーリーの大筋は一本道なんだけど、途中の展開は二転三転して映画としてもおもしろかった。

……でも、一般にはあまり評価が高くないらしく、ガッカリ。 確かに他と雰囲気は違うし、やたらとエグイ描写が多いからはオススメしづらいけど、そんな言うほど悪くないと思うんだけどなぁ。

ここまで見た感想

まず言いたいのは、なんでティモシー・ダルトンの007がなんで2作だけなんですかね。 ダルトンボンド作品が少ない理由は、まあ色々あったらしいけど、そんなのどうでもいいから作って欲しかった……

好きなのを3つ選ぶなら

  1. カジノ・ロワイヤル
  2. リビング・デイライツ
  3. 消されたライセンス

上2つはすごい悩むんだけど、オープングとエンディングのかっこよさでカジノ・ロワイヤルの方がギリギリ上かな。


で、これから残りの作品どれだけ見るつもりかというと、とりあえずダニエル・グレイグのが現在あと2作出てるようなので、それは近いうちに見ます。 でもダルトンやグレイグのシリアス寄りな雰囲気が好きなので、他の作品を見るかはちょっと怪しい。

もしダルトンの作品がまだあったらそれも見る……と思ったけど、たぶんこの記事書く前に見てるでしょうね。 ほんと、なんで2作しかないんだ。


ちなみにどうやって見てるかというと、TSUTAYA のレンタルか、Amazon のプライムビデオです。 プライムビデオは人を駄目にする危険なサービスだと思います。

この1年間で変わったこと

社会人になって1年で変わったことを振り返ろうと思ったら140字に収まりそうにないので、ここで*1

明らかに生活が偏ってるけど、こうやって見ると社会人も悪くないなぁ、と思う。たぶん。

*1:現在、3/31 23:50

ドミニオン初心者4人に勉強会を開いた話

最近全然ブログ更新していなかったので、年を越す前に何か書くネタは無いか考えたところ、1ヶ月半前に知り合い相手にドミニオン勉強会を開いたのをまだ記事にしていなかった。

いわゆる「初心者にドミニオンを好きになってもらう方法」の一例ということで一つ。

なぜ勉強会をやったのか

幸運なことに、4月からほぼ週1回ペースでドミニオンをオフラインプレイできる環境にいる。 ただ、その環境というのはわりと力量差が激しく、特に自分と親しい数人が所謂初心者で、いつも3 or 4位になっていた。

経験を積むのがドミニオンで強くなる最もわかりやすい方法なのは百も承知だが、それにしたって知らないといけないことというのはある。 (ここで言う知らないといけないこととは「1Tに村購入はほぼ弱い」「属州残り4枚以下の時に5金出たらアクションより公領を買う」とかのレベルである)

初心者ではある彼らは「ドミニオン勝てないなー勝てるようになりたいなー」と興味自体は示してくれていたが、このままの状態が続くと、やがてドミニオンを嫌いになってしまうのではないか。 それはなんというかこう、嫌だ。 しかしだからと言ってナンタラマニアックスとかを一方的に渡すのも何か違う気がする。 そう考えて、ちょっとでもドミニオンを面白く感じてもらうために、未熟ながらも彼らを相手に実体験ベースで学んでもらう勉強会を提案し、実際に開催することにした。

勉強会でやったこと

勉強会の概要は以下の通り。

  • 初心者4人を招待
  • 意図的なサプライを6つ用意して4人にプレイしてもらう
    • それぞれにコンセプトや教訓めいたものがある
    • 一部、変則ルールを設けた
  • 試合前に1人にだけ「こうするといいよ」というヒントを教える
  • AuToはよほどの悪手を打たないかぎりは見てるだけ
  • 試合後にAuToが偉そうなことを言いながら感想戦

用意したサプライはだいたいこんな感じ。 (詳細は長くなるので、この記事では省略。いつか書くかも)

  • 村・鍛冶屋・玉座の間のみの変則サプライ
    • 鍛冶屋ステロで十分
  • 一般的に弱い or 輝く場面が極めて限定的なカード10種
    • 金ステロで十分
  • よろずや、大使館、商人ギルドなどのステロ強カード10種
    • 強いステロカードの強さを実感してもらうのが目的
  • 大使砲サプライ
  • ステロカード vs 玉座・執事・橋
    • 決まると気持ちいいコンボと、玉座玉座でアクションを増やせることの実体験
  • 冒険カード & イベントによる獲得メインのコンボサプライ
    • 当時、冒険サプライが多かったので対策ということで

前半と後半でステロ場とコンボ場を分けたのは、長丁場の勉強会にメリハリを付けるため。 昼過ぎから休憩を挟んで18-19時くらいまでかかる想定で、実際その通りになった。

勉強会当日に起きたこと

4戦目以外はだいたい当初の意図通りになり、ヒントを教えた人が勝った。

4戦目は大使砲が完成する前に終了。 これはサプライというか意図がよくなかった。 (4人戦と2人戦の違いを甘く見過ぎた……)

5戦目はヒントを教えなかった3人のうち1人が意図を見抜き、ヒントを教えた人よりも先に玉座・執事・橋を完成させる。 予想外ではあったが、コンボを決めた側が勝つ事自体は当初の意図通り。

勉強会後にどうなったか

4人のうち少なくとも2人は明らかに強くなっていた(というか純粋なステロ戦だと偶に負ける)。 1人は、勉強会後に自分でドミニオンを3パック購入するくらいにはハマっていた。 また「別の友人とやるときに勝てるようになった」とも言ってくれた。

定期的にネットで「どうやって初心者をドミニオンに誘い込むか」みたいな話題を見かける。 小規模ではあるが、この勉強会はその目的を達成できたと思う。 この方法が全ての初心者に通用するわけではないし、たぶんコスパも悪い(サプライ準備も当日もめっちゃ疲れた)が、なんだかんだいって自分も楽しかったので良しとする。

尻切れトンボな終わり方ではあるが、うだうだしてると年が変わってしまうので、よいお年を。


サプライ作成の際に多くの助言をくださった @r_kuzumi@mmhiyoko にお礼申し上げます。

Valgrindのエラーメッセージだけを出力したい

最近、プライベートではなぜかCを書くことが多くて、その過程で今更ながらValgrindを使うようになった。

で、使っているうちにValgrindのエラーメッセージだけを表示したくなったので、そのやり方をメモ。 環境は以下のとおり。

一応明記しておくと、Valgrindのバージョンは3.10.0。 シェルはbashなので、それ以外のシェルの場合は適宜読み替えるように。

ネタバレ

--log-fdオプションとリダイレクトを組み合わせればいい。

Valgrindの使い方

例えば以下のCコードsample.cを考える。

#include <stdio.h>
#include <stdlib.h>

int main(void) {
  puts("hello");
  malloc(42); // 特に意味もなく malloc して……
  fputs("goodby\n", stderr);
  return 0;   // free せずに終了
}

もちろんこのコードはコンパイルして実行することができる。

$ cc -Wall -g sample.c && ./a.out
hello  # 標準出力
goodby # 標準エラー出力

しかし、sample.cは6行目で(無意味に)mallocした領域を解放せずにプログラムを終了している。

Valgrindを介して実行すると、このようなメモリリークを検出できる。 --leak-check=fullオプションを付けると、メモリリーク箇所の詳細な情報もわかる

$ valgrind --leak-check=full ./a.out
==6865== Memcheck, a memory error detector
==6865== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==6865== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==6865== Command: ./a.out
==6865==
hello
goodby
==6865==
==6865== HEAP SUMMARY:
==6865==     in use at exit: 42 bytes in 1 blocks
==6865==   total heap usage: 1 allocs, 0 frees, 42 bytes allocated
==6865==
==6865== 42 bytes in 1 blocks are definitely lost in loss record 1 of 1
==6865==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6865==    by 0x400614: main (sample.c:6)
==6865==
==6865== LEAK SUMMARY:
==6865==    definitely lost: 42 bytes in 1 blocks
==6865==    indirectly lost: 0 bytes in 0 blocks
==6865==      possibly lost: 0 bytes in 0 blocks
==6865==    still reachable: 0 bytes in 0 blocks
==6865==         suppressed: 0 bytes in 0 blocks
==6865==
==6865== For counts of detected and suppressed errors, rerun with: -v
==6865== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

definitely lost≒メモリリークしていると思えばいい。 今回はデバッグフラグを付けてコンパイルしているので、mallocした場所(sample.c:6)まで出力されている。

-qオプションをつけるとエラーメッセージのみが出力される。

$ valgrind -q --leak-check=full ./a.out
hello
goodby
==7135== 42 bytes in 1 blocks are definitely lost in loss record 1 of 1
==7135==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7135==    by 0x400614: main (sample.c:6)
==7135==

Valgrind自体は他にも色んな用途があるようだが、ここではとりあえずメモリリーク検出ツールとして扱う。

やりたいこと

makeスクリプトでまとめてチェックするような場合、「プログラム自体の出力を全て抑制して」「Valgrindの出すエラー報告だけを表示」したくなる。 つまり以下のsimple_leak_checkコマンドが欲しい。

$ simple_leak_check ./a.out # hello も goodby も出力しない
==7135== 42 bytes in 1 blocks are definitely lost in loss record 1 of 1
==7135==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7135==    by 0x400614: main (sample.c:6)
==7135==

「Valgrindのエラー報告だけ」という部分は、先述のValgrindの-qオプションで解決済みなので、問題は前者である。

試した方法

ダメな方法: 単純なリダイレクト

Valgrindのメッセージは標準エラー出力に出力されるので、標準出力を/dev/nullにリダイレクトすればいい……とはいかない。 これだとsample.cの7行目のような、プログラム中の標準エラー出力への出力が混じってしまう。

$ valgrind -q --leak-check=full ./a.out >/dev/null
goodby   # <- ./a.out 中の stderr への出力
==7613== 42 bytes in 1 blocks are definitely lost in loss record 1 of 1
==7613==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7613==    by 0x400614: main (sample.c:6)
==7613==

「メモリチェックしたいプログラムが出力するのがおかしい」と言いたくもなるが、この時チェックしていたのは自作のテストフレームワークという、本質的に出力も込みのプログラムだったので、なんとかしたいところ。

一応大丈夫な方法: --log-fileオプションの使用

Valgrindのメッセージをファイルに出す方法がある筈と思って調べたら、--log-fileオプションがあった。 標準出力と標準エラー出力を両方共/dev/nullへリダイレクトし、Valgrindのエラーメッセージは適当なファイルへリダイレクトしてから、後で表示すればよい。

$ valgrind -q --leak-check=full ./a.out \
> --log-file=/tmp/log.txt \ # Valgrind の出力をファイルに一時保存
> >/dev/null 2>/dev/nul     # プログラム自体の出力は投げ捨てる
$ cat /tmp/log.txt          # 終了後に、保存しておいた出力を表示
==8057== 42 bytes in 1 blocks are definitely lost in loss record 1 of 1
==8057==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8057==    by 0x400614: main (sample.c:6)
==8057==

一応できた。

でもこの方法の何がイケてないって、/tmp/log.txtを作ってるのがイケてない。 別にパフォーマンス云々やディスク云々を気にするわけではないが、なんか腑に落ちない。 もうちょっとスマートにできないか。

腑に落ちた方法: --log-fdオプションの使用

ヘルプを眺めてたら、--log-file オプションのすぐ近くに --log-fd オプションがあることに気づく。 以下、抜粋。

$ valgrind --help
  (中略)
    --log-fd=<number>         log messages to file descriptor [2=stderr]

--log-file がファイル名を指定するのに対して、--log-fd はファイルディスクリプタの番号を直接指定する。 最初は「なんだそりゃ」と思ったが、これとリダイレクトを組み合わせれば、中間ファイルを使わずに目的を達成できる。

$ valgrind --log-fd=3 \  # Valgrind の出力をファイルディスクリプタ3番に
> -q --leak-check=full ./a.out 3>&2 \
> 3>&2 \                 # 3番を標準エラー出力に向ける
> >/dev/null 2>/dev/null # プログラム自体の出力は投げ捨てる
==8729== 42 bytes in 1 blocks are definitely lost in loss record 1 of 1
==8729==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8729==    by 0x400614: main (sample.c:6)
==8729==

今度こそできた!

ここではファイルディスクリプタは3を使っているが、3以上ならなんでもいい(はず)。 1つ落とし穴があり、--log-fdは実行するプログラム(ここでは./a.out)よりも前に置かないと、何故か無視される。解せぬ。

オマケ: --error-exitcodeオプション

デフォルトではValgrindの終了ステータスはエラーの有無に関係なく0となっている。 これではスクリプトで処理するときに何かと不便だが、--error-exitcodeオプションで、メモリリークを1つ以上検出した際の終了ステータスを指定できる。

というわけで、目標だったsimple_leak_checkコマンドは次のようになる。

alias simple_leak_check=
'valgrind --log-fd=3 -q --leak-check=full\
3>&2 >/dev/null 2>/dev/null'

まとめ

Valgrindのエラーメッセージのみを出力する方法を述べた。

正直、--log-fileオプションで中間ファイルを生成する方法でもいい気がするが、一生使う機会が無いと思っていた「3以上のファイルディスクリプタを使ったリダイレクト」が役に立つ形で使えたので、つい記事にまでしてしまった。

というか--log-fdオプションのこれ以外の用途が思いつかないけど、何かあるのかしら。


ちなみに上のsample.cは、コンパイル時に-O2オプションを付けるとmalloc呼出し自体が最適化によって削除される可能性があるので注意(?)*1

*1:手元のClang 3.6では、最適化後のアセンブリを覗いたら無くなってた

【ドミニオン】Adventure初体験

知人がドミニオンAdventure(英語版)を入手したので遊んでみた。

うろ覚えな対戦ログ

イベントはとりあえず3枚入れてみた(あとで調べたら2枚が推奨だったらしい)。 使ったカードやイベントはうろ覚えなので覚えている分だけ。

あと1・2戦目がタイマンで、3・4戦目は3人戦。

1戦目

  • サプライ: Raze, Ranger, Miser, Magpie, Messanger, Duplicate, Wine Merchant, Relic, Tresure Trove, Artifacer
  • イベント: Plan, Seaway, Pathfinding

Magpie楽しい。 こちらのMagpieは運良く財宝カードばかりをめくってくれた上に、Pathfindingで+1 cardトークンを乗せたら更に加速した。 途中でArtifacerを入れ、最終的にはArtifacerで8枚捨てて属州を獲得した上で、8金で属州を購入できるデッキになり勝利。 相手はMessagerに廃棄トークンを載せた上で、Messangerで呪いを獲得してばら撒く手に出るが、そこまで強くは無さそうだった(一応、あまったMessangerはRazeの餌にはなっていたが……)。

枚数が多いという理由でMagpieに+1 cardトークンを付けたが、Artifacerの方がよかったかもしれない。 Relicさえ無ければ、ArtifacerはArtifacerを簡単に増やせるし、ドローし続ければ属州が確定で獲得できるし。

あとRelicがなかなかえげつない。 アクション回数を無視して2金出しつつ、相手を足止めをするアタック……って文面に起こすとかなり強いんじゃないですか。

2戦目

ここからサプライがうろ覚え。

  • サプライ: Page, Peasant, Gear, Amulet, Port, Giant
  • イベント: Training

PageやPersantの旅人カードがどの程度強いのかは気になるが、どう見てもGearステロが強すぎる……と思ったらGiantで出てきて完全に話が変わる。 PortはChampionを撃つまでのコンボパーツにもGiantに対する壁にもなるし、Amuletで軽圧縮も可能。 結局2人ともChampionを目指しつつ、Giantをできるだけたくさん撃つコースを狙う。

結果的には2人ともChampionまで育つが、TrainingされたGiantを2回毎ターンプレイできる体制を先に整えられて負け。 Championまで育つ前にGiantで3回くらいで呪いを撒かれたのが辛かったが、そもそもデッキ構築がダメダメだった気がする。

3戦目

  • サプライ: Guide, Magpie, Wine Merchant, Relic, Tresure Trove
  • イベント: Borrow, Inheritance

Magpie、再び。 相変わらず相性が良いRelicに加え、今回はInheritanceが強力なサポートになりそう。 1戦目に試せなかったTresure Troveとの相性も気になるところ。

初手は5金スタートだったのでWine Merchantを入れる。 Relicと悩んだが、銅貨2枚とWine Merchantが揃えば、Borrowを使ってInheritanceを発動できるため。 さっそく3Tに6金 + BorrowでMagpieに屋敷トークンを置くことに成功。 これで事実上、4T目から屋敷3枚を圧縮してMagpieに入れ替わる。

その後は、RelicとTresure Troveを追加し、Magpieを増殖させながら屋敷を購入していく。 特にWine Merchantは+1 buyが屋敷増量に役立った(屋敷追加くらいなら大体2コインは余るので、酒場マットに送らずにすむ)。

そのまま順調に属州と屋敷を買うプレイで圧勝。 効果が公開された時からやばいやばいと思っていたInheritanceだったが、今回のような環境では案の定のぶっ壊れだった。

あとこのゲームは3人中Relicに行かなかった1人が完全に死んでいたのが印象深かった。 4枚にされた手札をGuideで復帰させようとしていたが、Guideを使うタイミングでは大抵-1 cardトークンが乗っているという。

4戦目

  • サプライ: Coin of the Realm, Gear, Lost City, Swamp Hag
  • イベント: Trade, Pathfinding

1番手3-4なので、今度こそGear-Gearスタートでステロへ。 ただでさえ早いGearステロがTradeによってさらに強化され、Gearに行かなかった2人とは頭2つくらい抜けてリード。 早々に属州を買い始め、そのまま圧勝……かと思ったら甘かった。

2番手がCoin of the RealmとLost CityでSwamp Hagを並べるコンボを着々と組み立て、呪いを受け取らざるを得なくなる。 Swamp Hagを2枚並べられたターンにTradeで呪いを銀に換えたり、PathfindingでGearを強化したりでお茶を濁してみたが、最終的には毎ターンSwamp Hagが3枚持続する体制を整えられ、1点差で捲くられる。

Gearをもう1枚入れてもよかったのかもしれないが、そもそもSwamp Hagコンボを舐めすぎていた。 これがAdventureの世界か。

感想

プレイ中は終始こんな感じだった。

TLでよく見かける「Adventureはパーティゲーだ」というは、なんとなく理解できた。 でも個人的には面白かったのでこれはこれでいいかな、と。

ただ「ルールを順守したプレイ」はこれまでよりも明らかに難しい。 もし来年日本選手権があってレギュレーションに冒険があったら、イベントとトークンの誤処理が大量発生してジャッジが過労死するんじゃないかなって。

【Ruby】OS XでDigest::MD5を使おうとすると「Symbol not found: _rb_Digest_MD5_Finish (LoadError)」なるエラーが出る問題

週末に久々に会った友人から「お前アナログゲーム以外のこともブログに書けよ」って言われたので、メモ代わりに最近が自分が嵌った落とし穴について。 YosemiteRuby 2.2を入れたところ、MD5を扱う標準ライブラリのDigest::MD5が使えなくて困った。

発生した問題

例えばこんな感じでRubyをインストールする。

$ rbenv install 2.2.1 # rbenvでCRuby 2.2.1をインストール
$ rbenv local 2.2.1   # 現在のディレクトリで2.2.1を使用

で、digest/md5requireすると……

$ ruby -e 'require "digest/md5"'
/Users/autopp/.rbenv/versions/2.2.1/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in
`require': dlopen(/Users/autopp/.rbenv/versions/2.2.1/lib/ruby/2.2.0/x86_64-darwin14/digest/md5.bundle,
9): Symbol not found: _rb_Digest_MD5_Finish (LoadError)
  Referenced from:
/Users/autopp/.rbenv/versions/2.2.1/lib/ruby/2.2.0/x86_64-darwin14/digest/md5.bundle
  Expected in: flat namespace
 in /Users/autopp/.rbenv/versions/2.2.1/lib/ruby/2.2.0/x86_64-darwin14/digest/md5.bundle
- /Users/autopp/.rbenv/versions/2.2.1/lib/ruby/2.2.0/x86_64-darwin14/digest/md5.bundle
from /Users/autopp/.rbenv/versions/2.2.1/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in
`require'
from -e:1:in `<main>'

あまり目にしない例外を吐いて死ぬ。 ここではrbenvを使っているが、恐らく他のツール野良ビルドでも発生する。 またRubyのバージョンは2.1でも発生することを確認している。

Digest::MD5はまあ色んな所で使われていて、例えばbundler/setupなんかも使えなくなってしまうため、これは無視できない問題である。

解決策

先ほどのエラーログではCのdlopenのエラー出力らしきものが含まれていることから「たぶんRuby自体のインストールに問題があったんだろうな」というところまでは検討が付くが、思い当たる節は特に無い。

ひたすらクエスチョンマークを頭から垂れ流しながらググっていてたら、次のstackoverflowの質問に行き着いた。

Mountain Lion - Rails - Symbol not found: _rb_Digest_MD5_Finish (LoadError)

これのアンサーによると、Mac OSRubyをインストールする時に環境変数C_INCLUDE_PATHが設定されているとマズイらしい。 なんじゃそりゃと思うような、まあそんなこともあるかと思うような……

手元の環境で確認してみると確かに定義されている。

$ if [[ $C_INCLUDE_PATH ]]; then echo yes; fi
yes

Rubyのインストール時にこの環境変数がセットされてさえいなければいいらしいので、以下の手順で再インストールすればよい。

$ rbenv uninstall 2.2.1 # 一度アンインストールして
$ unset C_INCLUDE_PATH  # 環境変数を一時的に削除して
$ rbenv install 2.2.1   # 再インストール

改めてdigest/md5requireしてみる。

$ rbenv local 2.2.1
$ ruby -e 'require "digest/md5"; puts "OK"'
OK

OK。

この問題、踏むと致命的なわりにはあまり情報が出てこなかった。 そもそもC_INCLUDE_PATHは普通はセットしないので、踏んだ人も少ないのだろうと推測(gccclangなら-Iオプションで十分なはず)。 正直なところ自分もいつC_INCLUDE_PATHなんかを設定したのか覚えが無いが、たぶん昔何かの都合で.bashrcに書いたのがずっと残っていたのだろう。


なんにせよアナログゲーム以外の記事も書いたので、友人(非エンジニア)の不満も解消できただろう。 これで次はアナログゲームの記事が書ける。