DCSS qw botの中身を探る
この記事は Roguelike Advent Calendar 2016 の8日目の記事です。
■設定ファイル、使っていますか?
DCSSの設定ファイルには様々なオプションが設定でき、知っておくとゲームを円滑に進める助けになります。
配布版ならsettings/init.txtを編集するなり、Webtileなら(edit rc)のリンクを押して編集画面を出すなりしましょう。
よく使うところでは
# 余分な --more-- をスキップ show_more = false # スキル割り振りをマニュアルモードで開始 default_manual_training = true # HPが30%以下になると警告(デフォルトは10%) hp_warning = 30
でしょうか。
設定ファイル中ではLua言語によるスクリプトも使うことができ、
: if you.race() == "Ogre" or you.race() == "Troll" then # オーガとトロルは大岩を拾う autopickup_exceptions ^= <large rock : end
のように場合分けで設定をすることもできます。便利!
■DCSS qw bot
本題です。
DCSS開発チームの一人elliptic氏が、DCSSを自動的にプレイしてくれるbotを公開していました。
(やや古いバージョンがDCSS本体のリポジトリツリーにも含まれています。*1 )
はて、いったいどういう仕組みで動くものか? とりあえず中身を見てみました。
すると仰天、qw botの本体は7700行にも及ぶ設定ファイルqw.rcだったのです。
■動かしてみよう
botのお手並み拝見ということでローカルで動かしてみます。READMEにはオンラインサーバでの動かし方も書かれていますがあまり推奨しません(特にトーナメント中は)。
https://github.com/elliptic/qw/ のページの"Clone or download"を押すと"Download ZIP"というボタンが出てくるので、ボタンを押してqw-master.zipをダウンロードします。
zipを展開するとその中にqw.rcというファイルがあるので、それをDCSSのsettingsディレクトリにコピーします。
settings/init.txtを編集し、末尾に
include = qw.rc
と追記します。
qw.rcの先頭には各種設定がありますが、以下の項目でキャラクターの初期組み合わせを指定します。
# 闇ドワーフ戦士斧、ガーゴイル狂戦士斧、ミノタウロス狂戦士斧のどれかでスタート combo = DDFi.waraxe, GrBe.handaxe, MiBe.handaxe
ゲームを開始すると自動的にqwというキャラ名でゲームがスタートしています。Tabを押してbot運行モードに切り替えると、あとはSpaceやその他のキーを押しっぱなしでゲームが進みます。'%'キーでいつもの通りステータスや装備が確認できます(反応しない場合は何度か押してください)。手動操作に戻したい場合は再度Tabを押します。
■どんな感じ?
良い点
けっこう賢いです。敵の群れを狭い通路まで釣ったり、階段昇降して敵を分散させたり、適切に武器防具を交換したりをこなしているようです。店が出たら買い物もします。
(トログ信仰の場合)ここぞというところでバーサークして相手を殲滅したり、トログの御手でMR上昇&回復したり、仲間を召喚したりで適切に進んでくれます。まあ、トログ信仰(とそれを最初から得ている狂戦士)が強いってのもありますが。
デフォルトの組み合わせ(闇ドワーフ戦士斧、ガーゴイル狂戦士斧、ミノタウロス狂戦士斧)での序盤性能は高く、ルーンを拾う所まで進むこともしばしばです。というか私より強いんじゃね?
悪い点
悪手というか機能の限界というか、以下のような動きが見られます。
- 魔法は使えない。暗殺ビルドもできない様子(短剣スタートでも斧に持ち替えたり)
- エルフの大広間/Elven Hall、地下墓地/Cryptには寄らない。
- ポータルへ寄らない(下水道/Sewerの入口を選択するが行かないような動きをする)と思いきや、納骨堂/Ossuaryに入ったことはあった。
- 指定された神の祭壇があっても入信しないことが多々ある。
- アビスに飛ばされた際、出口が見つかっても直行しない。
- オーブを拾った後もZot:5の未探索領域をうろうろする。階段に直行しない。
- (バーサークが切れた状態でまだ囲まれているなど)危機に陥った際にテレポ巻で逃げる傾向がある。
- 運が良ければいいが、敵のまっただなかに突っ込んでしまうことがあるため普通は悪手。
- 沼の特殊マップでルーンの上にflame cloudが湧いている場合、その場でうろうろを続ける。
- それを避けるようなコードが書かれている形跡はあるが、うまく働いていない様子。
- まあ、一旦手動に戻せばいいのだけど。
- アーティファクト片手斧が下賜された/自然生成された時でも無視することがある。
■どんな仕組み?
最近流行りの人工知能……というわけでもなく、基本は「列挙された行動リストの中にある行動を適宜条件判定して実行」という形ですね。
6983行目から行動リストの定義が乗っています。以下抜粋です。
plan_pre_explore = cascade { {plan_fly, "fly"}, {plan_ancestor_life, "ancestor_life"}, {plan_sacrifice, "sacrifice"}, {plan_upgrade_weapon, "upgrade_weapon"}, {plan_maybe_upgrade_armour, "maybe_upgrade_armour"}, {plan_use_good_consumables, "use_good_consumables"}, } -- hack -- (中略) plan_emergency = cascade { {plan_cure_starving, "cure_starving"}, {plan_cure_confusion, "cure_confusion"}, {plan_coward_step, "coward_step"}, {plan_remove_terrible_jewellery, "remove_terrible_jewellery"}, {plan_teleport, "teleport"}, {plan_dd_recharge_teleport, "dd_recharge_teleport"}, {plan_cure_bad_poison, "cure_bad_poison"}, {plan_drain_life, "drain_life"}, {plan_heal_wounds, "heal_wounds"}, {plan_cloud_step, "cloud_step"}, {plan_hand, "hand"}, {plan_resistance, "resistance"}, {plan_heroism, "heroism"}, {plan_bia, "bia"}, -- 注: Brother in Arms {plan_sgd, "sgd"}, -- 注: Summon Greater Demon {plan_divine_warrior, "divine_warrior"}, {plan_apocalypse, "try_apocalypse"}, {plan_slouch, "try_slouch"}, {plan_hydra_destruction, "try_hydra_destruction"}, {plan_grand_finale, "grand_finale"}, {plan_dd_recharge_heal_wounds, "dd_recharge_heal_wounds"}, {plan_wield_weapon, "wield_weapon"}, {plan_swap_weapon, "swap_weapon"}, {plan_water_step, "water_step"}, {plan_finesse, "finesse"}, {plan_drac_dig, "try_drac_dig"}, {plan_berserk, "berserk"}, {plan_other_step, "other_step"}, } -- hack
ある意味愚直ともいえるのですが、それでもこの方式でいい感じに動き、あまつさえクリア直前まで進行可能というのは驚きです。
Tabを押すとbot運行モードがオンオフされるのは、元々Luaスクリプト(dat/clua/autofight.lua)で組まれていたhit_closest関数(Tabを押したら最寄りの敵を殴る機能)を乗っ取る形で実装されているからですね。なるほど。