こんにちは。この記事ははてなエンジニアAdvent Calendarの24日目の記事です。昨日はid:todays_mitsuiさん、明日はid:d-haruさんです。いいタイミングで風邪を引いてしまったので、今年も趣味の話です。
ローグライクといえば最近は定義がけっこう広がってきている印象がありますが、いわゆるRogueライクなコンピュータゲームの系譜で、Nethackと並んで重要なのがAngbandですね。自分も高校生の頃だったか、指輪物語を読んであまりに面白かったので何かゲームをやりたい! と思って何故かAngbandのフォークのフォークである変愚蛮怒を始めたような覚えがあります。いや順序が逆だったかもしれねェ……。何も覚えていない……。ともあれこういうテキストベースのゲームですね。トルネコとかシレンとか。
思うところあって今年はこのAngbandの日本語化を休み休みやっていたので、その紹介をしようと思います。ちなみにまだまだ途上で、かつ自分のメイン環境であるmacOS対応しかできてないです……。
Angbandは派生バリアントが星の数ほどあって、まとめて*bandと呼ばれたりもします。*bandも歴史が長く、日本語化も何度かなされているようです。
- JAngband
- 日本語版 Angband(Internet archive)
- 変愚蛮怒
- こちらはAngbandの日本語化じゃないけど、日本語ローグライクの非常に重要なゲーム。いまも更新が続いている!
国際化の戦略
Angbandの日本語化というか、国際化について考えるべきなのはおそらくテキストだけ。タイムゾーンのようなものは存在しないので、そこは楽ですね。そしてAngbandに含まれるテキストにソースコード中のメッセージと、別ファイルとして存在しているゲームデータの二種類がある。ゲームデータには多数の敵モンスターの名前やアイテムなどの名前や挙動がテキストで記されている。
上で紹介した先駆者たちは、#ifdef JP
のような分岐をソースコード中に入れてメッセージの表示を出し分けていたけど、翻訳データを外出しすることで翻訳自体の進捗がわかりやすくなるだろうという見込みのもと、今回はlibintl (gettext) の仕組みで対応してみることにした。ゲームプレイ中に言語を切り替えることを想定する必要もないので、メッセージは静的に決定できていいわけだけど、まあ後からどうとでもできるかなという想定。
過去に日本語化が行われたときはAngbandのバージョンは2.xや3.xだったけど、今見てみるとメジャーバージョンは4となっていて、内部的な改善も進んでいる模様。Unicodeへの対応などはすでになされていて、そこはすんなりいったのでよかった。
日本語化
とはいえ完全に英語圏に向けて作られたものなので、日本語に対応するのはそれなりに骨が折れる。スクリーンショットを見ると分かるとおりテキストベースのゲームなので(グラフィックを有効にすることもできる)、日本語の表示幅がASCIIの倍であるところがやはり罠。strlen
や数字の 1
が使われているところで、いま注目しているのが文字数なのか画面幅なのかを気にしてやる必要がある。
まあこれはわかりやすい。難しいのはメッセージ文字列をプログラムで組み立てているところだ。こういう箇所は綺麗には解決できない。たとえば次に続く数字が8か80台だったら、不定冠詞として"a"を出力したあとに"n"も出力するとか。これは日本語化のときには完全に不要なので、 #ifdef
とかで消す対応とした。
英語と日本語との文法の体系の違いで困る部分もある。例えば敵の行動の説明に「These monsters bite, claw and terrify.」とあった場合、日本語なら「このモンスターは噛みつき、引っ掻き、恐怖させる。」などと動詞を活用させたくなる。かといって、これらの説明文はゲームデータから構成されていて、同じ単語が別の位置で登場しうるので、biteをそのまま「噛みつき」に翻訳することはできない。ここは翻訳の工夫でなんとかしようとしているがあまりすっきりしない。変愚蛮怒などではこの活用を実装していた覚えがある。そもそも自然な文章の形に落とそうとするのが無理な話なのかもしれない。
あと面白かったのが、アイテムを拾ったときに You have {count} {item}s. と表示するのでこれをそのまま「{count}個の{item}を持っている。」と翻訳してしまうと、アイテムをすべて捨てたときに「no more個の{item}を持っている。」になってしまうこと。英語だとYou have no more {item}. で素直に通ることを利用していておもしろい。
まあだいたいの場所では、文字列リテラルを国際化することでなんとかなるパターンが多い。sprintfが使われる場面では、%sにはめたい引数の場所が日英で違うことがおおいのでPOSIX拡張の %1$s
のようなものを使うことにしている。
進捗の可視化
まあこれはライフワーク的にのんびりやろうと思っているので、ときどき思い出したら手を出せるよう、国際化および日本語への翻訳の進捗をトラッキングするようにしている。後者は.poファイルの msgtxt
エントリが埋まっているかをカウントすればよいだけなので簡単。前者はソースコード中の文字列リテラルが _()
で囲まれているかを調べたいのでちょっと難しい。これをなんとかしたい動機で生まれたのがclang-tidyのカスタムチェックでした。
このへんは https://github.com/motemen/angband/issues/4 や https://github.com/motemen/angband/issues/3 で元気に動いていそうです。
また、tokuhiromさんがIMEを作っている話で紹介されていた、GitHubのDiscussionsに開発日誌を書く話がよかったので真似している。
というわけでリポジトリはこちら。生暖かく応援してくださいね。書いてて思ったけどまずはWindows版の対応かな……。
GitHub - motemen/angband: A free, single-player roguelike dungeon exploration game