はじめに
Expect の manpage を見ると、Expect ができることの例として以下があります。
ゲーム(例えば rogue)を始める時に、最適なパラメタがもらえなかった場合、最適なパラメタがもらえるまで何度でもリスタートを行ない、その後制御を人間に移す。
昔 JNetHack で遊んでいたとき、主にWizard(魔法使い)を選んでいまして、
初期装備にいい杖やアイテムが出るまでQuit&再実行を繰り返す所謂リセマラを
地道に手動でやっていた事を思い出しました。ヒマ贅沢な時間の使い方だなと。
汝、今こそこれを自動化せよ
なるほど、やってみましょう。
JNetHack のリセマラスクリプト
CentOS7 + nethack-367-src.tgz + jnethack-3.6.7-0.1.diff.gz の tty 環境で実行しました。
ここでは ~/nh/install/games/jnethack にインストールされたものとします。
※デフォルトでのインストール場所は、昔と今では全然違うんですね。
#!/usr/bin/expect
set timeout 1
# お好みの 職業・種族・性別・属性を設定してください
set JOB w ; # 職業(w - 魔法使い)
set RACE h ; # 種族(h - 人間)
set GENDER * ; # 性別(* - ランダム)
set ATTR n ; # 属性(n - 中立)
# ---------------------------------------------------------------
# お望みのパラメータ・所持品を CONDITION に記載してください
#
# 強早耐知賢魅のうち、強知賢が11以上を希望する例
# set CONDITION ".*強:1\[1-9\].*知:1\[1-9\].*賢:1\[1-9\].*"
#
# 所持品を正規表現で記載する例 (今回はこれを使う)
set CONDITION ".*(回復|識別)の魔法書.*(変化|無力化)の杖.*魔法のマーカ.*"
#
# 組み合わせる場合は、パラメータ->所持品の順序で記述してください
# set CONDITION ".*賢:1\[1-9\].*魔法のマーカ.*"
# ---------------------------------------------------------------
while { 1 } {
spawn ~/nh/install/games/jnethack
expect "ynq"
send "n" ; # 職業,種族,性別,属性を自動選択しない
expect {
"職業を選んでください" {
send $JOB ; exp_continue
}
"種族を選んでください" {
send $RACE ; exp_continue
}
"性別を選んでください" {
send $GENDER ; exp_continue
}
"属性を選んでください" {
send $ATTR ; exp_continue
}
"これでよい" {
send "y" ; exp_continue
}
"More" {
# Space2回押す+所持品を確認する
send " i"
expect {
-re $CONDITION {
interact
exit 0
} default {
send "\003 " ; # Ctrl+c と space 1回
expect {
"本当にやめる" {
send "y" ; exp_continue
}
"識別しますか" {
send "q"
}
}
}
}
}
}
expect eof
catch wait
}
魔法使いは初期装備で強力な杖や魔法のマーカがもらえる(こともある)と
嬉しいので、このスクリプトでは希望の所持品の条件を正規表現で記載して、
出るまでひたすら spawn を繰り返し、出たら interact する、としました。
他の職業だとどういうのがいいんでしょうね。
所持品ではなく、良パラメータを求める場合は、
set CONDITION ".*強:1\[1-9\].*知:1\[1-9\].*賢:1\[1-9\].*"
のようにすればよいのでしょう。※文法上、[ ] の前にはバックスラッシュが必要です。
当然ですが、絶対出ない値やアイテムを条件にすると、永遠にプレイ開始できません。
それでは、スクリプトを実行しました。
武器
a - 祝福された+1 六尺棒(手にしている)
鎧
b - 祝福された+0 魔法を防ぐクローク(身につけている)
巻物
i - 呪われていない地図の巻物
j - 呪われていない解呪の巻物
k - 呪われていない罰の巻物
魔法書
l - 祝福された衝撃の魔法書
m - 呪われていない識別の魔法書
薬
f - 呪われていない超回復の薬
g - 呪われていない水
--+---------- h - 呪われていない回復の薬
|.......{.... 指輪
|....@......| d - 呪われていない耐毒の指輪
|....f...$..| e - 祝福された +1 体力の指輪
------------- 杖
c - 変化の杖(0:7)
道具
n - 魔法のマーカ(0:44)
Megadriver 手品師 強:9 早:16 耐:15 知:18 賢:8 魅:9 中 o - 呪われていない目隠し
地下:1 $:0 体:12(12) 魔:7(7) 鎧:9 経験:1 (end)
しばらく待つと、このように所望の品が含まれた初期状態でスタートできました。
末尾の wait
はプロセスの終了を待つ処理です。
wait しない場合、以下のようにゾンビプロセス(defunctの行)が残るための対策です。
megadri+ 25188 0.2 0.0 134200 3120 pts/1 Sl+ 21:55 0:00 \_ /usr/bin/expect ./jnh.ex
megadri+ 25190 0.0 0.0 0 0 ? Zs 21:55 0:00 \_ [jnethack] <defunct>
megadri+ 25195 0.0 0.0 0 0 ? Zs 21:55 0:00 \_ [jnethack] <defunct>
megadri+ 25205 0.0 0.0 0 0 ? Zs 21:55 0:00 \_ [jnethack] <defunct>
megadri+ 25209 0.0 0.0 0 0 ? Zs 21:55 0:00 \_ [jnethack] <defunct>
megadri+ 25213 0.0 0.0 0 0 ? Zs 21:55 0:00 \_ [jnethack] <defunct>
megadri+ 25217 0.0 0.0 0 0 ? Zs 21:55 0:00 \_ [jnethack] <defunct>
megadri+ 25221 0.0 0.0 17704 2236 pts/2 Ss+ 21:55 0:00 \_ /home/megadriver/nh/install/games/lib/jnethackdir/jnethack
さいごに
- 久々にプレイしましたが、懐かしさと新鮮さが入り交じっており、JNetHack の面白さは
昔以上でした。鉄棒(#)ってなんなの? - スクリプト作成よりも何倍もの時間を、ついつい始めたプレイに費やしてしまいました
- 初期装備が多少よくても結局リトライしまくるのですが、初期アイテムが良いゆえに
止めどきを見失いがちになります(自制心がさがった!)
関連サイト
- The NetHack Archive ( https://www.nethack.org/download/ )
- JNetHack プロジェクト日本語トップページ ( https://ja.osdn.net/projects/jnethack/ )