・もげRPGさーばーとは。 http://mogerpg.pcgw.pgw.jp/ でプレイできるゲームを、標準入出力のやり取りだけで 攻略するAIを作るゲームです。 ・ダウンロード https://github.com/fusuya/mogeRPGserver/releases ・mogeRPGserverのオプション(win・linux) --help を指定して起動すると以下のヘルプが表示されます。 Usage: mogeRPGserver [-h|--help] [-r|--random-seed ARG] [-d|--delay ARG] [--no-clear] [--ai ARG] Available options: -h, --help このヘルプを表示 -r, --random-seed ARG 乱数の種(非負整数) -d, --map-delay ARG マップ移動時の表示のディレイ(小数可) -b, --battle-delay ARG バトル時の表示ディレイ(小数可) -m, --mogezou-delay ARG ボスと中ボス戦の表示ディレイ(小数可) -a, --all-delay ARG 全ての(上3つ)ディレイをARGに設定 --no-clear 画面のクリアをしない --ai ARG AIプログラムを起動するコマンドライン --hp ARG プレイヤーのHP(デフォルト値:30) --str ARG プレイヤーのSTR(デフォルト値:30) --agi ARG プレイヤーのAGI(デフォルト値:30) -F, --floor ARG プレイヤーのいる階層(デフォルト値:1) -W, --buki ARG プレイヤーの持ってる武器(デフォルト値:("なし" 0 0 0)) --heal ARG プレイヤーの持ってる回復薬(デフォルト値:2) --hammer ARG プレイヤーの持ってるハンマー(デフォルト値:5) -L, --level ARG プレイヤーのレベル(デフォルト値:1) -r 0 などとすると数字に対応した乱数の種で起動し、(AIが同じように行動するなら)同じ冒険ができます。--random-seed 0 や --random-seed=0 としてOKです。このオプションを指定しないと毎回違う冒険になります。 -d 0.5 などとすると表示ディレイが 0.5 秒になります。--no-clear でマップ表示時などの画面クリアを省略できます。冒険のログの確認のためですが、clear コマンドを実行しないので動作の高速化にもなります。 --hp 40 --str 40 --agi 50 -F 50 -W ラグナロク などとするとHPが40,STRが40、AGIが50でラグナロクを持って50階からスタートします。(この場合、レベルや回復薬、ハンマーはデフォルト値になります) --ai 'ruby ai.rb' などと指定すると ai.txt を読み込むかわりに指定されたコマンドラインで AI を起動します。 ・終了の仕方 端末を落とす!! もしくはkillコマンド ・勝敗の決定 100階のボスを倒したら勝利です。 ・AIの作り方 AIプログラムとサーバは標準入出力でやりとりをします。 AIプログラムは最初に名前を出力します。 以降はJSONデータを受け取り、アクションの出力を繰り返します。 ・出来上がったAIを実際にゲームサーバで動かすには ai.txtに実行コマンドを記入すればゲームサーバ上で動きます。 ・AIに送られてくるJSONデータ ・マップ移動モード 地下1階 Lv 1, NIL : HP 30/30 力 30/30 素早さ 30/30 ロロロロロロロロロロロ 武器[i] なし ロ 宝ロ 回復薬 2個 ロ ロロロロロ ロロロ ハンマー 5個 ロ 宝ロ ロ Exp 0/100 ロ ロロロロロ ロ ロ ロ宝ロ主 ロ宝ロ ロ 薬を使う[q] ロロロロロ ロロロ ロ 終わる[r] ロ ロ ロ ロ ロロロロロ ロ ロ ロ ロ下ロ ロロロロロロロロロロロ 上記のデータをJSON化すると以下になります。 {"map":1,"player":{"hp":30,"maxhp":30,"str":30,"maxstr":30,"agi":30,"maxagi":30,"level":1,"exp":0,"heal":2,"hammer":5,"map-level":1,"buki":["なし",0,0,0],"pos":{"x":3,"y":5}},"blocks":[[8,9],[8,8],[6,8],[5,8],[4,8],[3,8],[2,8],[6,7],[8,6],[7,6],[6,6],[4,6],[3,6],[2,6],[1,6],[8,5],[6,5],[2,5],[8,4],[6,4],[5,4],[4,4],[3,4],[2,4],[6,3],[9,2],[8,2],[6,2],[5,2],[4,2],[3,2],[2,2]],"walls":[[10,10],[9,10],[8,10],[7,10],[6,10],[5,10],[4,10],[3,10],[2,10],[1,10],[0,10],[10,9],[0,9],[10,8],[0,8],[10,7],[0,7],[10,6],[0,6],[10,5],[0,5],[10,4],[0,4],[10,3],[0,3],[10,2],[0,2],[10,1],[0,1],[10,0],[9,0],[8,0],[7,0],[6,0],[5,0],[4,0],[3,0],[2,0],[1,0],[0,0]],"items":[[7,5],[1,5],[5,3],[9,1]],"boss":[],"kaidan":[[9,9]],"events":[],"ha2":[]} walls 壊せない壁 blocks ハンマーを持ってると壊せる壁(壁を破壊すると7/10の確率で宝箱が出ます) items 宝箱の座標(宝箱からは,4/7の確率で武器、2/7の確率でハンマー、1/7の確率で回復薬が出ます) boss ボスの座標 ha2 中ボスの座標 kaidan 階段の座標 events イベントの座標 要素はそれぞれの位置の(x座標 y座標)です。 playerについて {"hp":30,"maxhp":30,"str":30,"maxstr":30,"agi":30,"maxagi":30,"level":1,"exp":0,"heal":2,"hammer":5,"map-level":1,"buki":["なし",0,0,0],"pos":{"x":1,"y":1}} hp 現在のHP maxhp 最大HP str 現在のstr(攻撃力) maxstr 最大str agi 現在のagi(素早さ) maxagi 最大agi level レヴェル exp 取得経験値 pos プレイヤー位置 heal 回復薬の数 hammer ハンマーの数 map-level 現在いる階 buki 装備してる武器("名前" 攻撃力 HP 素早さ) ・バトルモード時に送られるJSONデータ {"battle":1,"monsters":[{"name":"スライム","number":4,"level":1,"hp":8},{"name":"スライム","number":3,"level":6,"hp":7},{"name":"オーク","number":2,"level":5,"hp":10},{"name":"ヒドラ","number":1,"level":6,"hp":6},{"name":"ヒドラ","number":0,"level":2,"hp":2}],"player":{"hp":30,"maxhp":30,"str":30,"maxstr":30,"agi":30,"maxagi":30,"level":1,"exp":0,"heal":2,"hammer":5,"map-level":1,"buki":["なし",0,0,0],"pos":{"x":0,"y":0}}} monstersについて :[{"name":"スライム","number":4,"level":1,"hp":8},{"name":"スライム","number":3,"level":6,"hp":7},{"name":"オーク","number":2,"level":5,"hp":10},{"name":"ヒドラ","number":1,"level":6,"hp":6},{"name":"ヒドラ","number":0,"level":2,"hp":2}] name 名前 number モンスター番号 (敵を指定するときに使う) level モンスターのレベル hp モンスターのHP ※2017-11-28追加※ ・バトル時の敵の行動ターン時 {"damage-info":1,"monsters":[{"name":"ヒドラ","number":5,"level":2,"hp":2,"damage":["hp",1]},{"name":"メタルヨテイチ","number":4,"level":10,"hp":3,"damage":["no"]},{"name":"ヒドラ","number":3,"level":1,"hp":1,"damage":["hp",1]},{"name":"ヒドラ","number":2,"level":5,"hp":5,"damage":["hp",2]},{"name":"ヒドラ","number":1,"level":4,"hp":4,"damage":["hp",2]},{"name":"ブリガンド","number":0,"level":2,"hp":11,"damage":["hp",2]}],"player":{"hp":22,"maxhp":30,"str":30,"maxstr":30,"agi":30,"maxagi":30,"level":1,"exp":0,"heal":2,"hammer":5,"map-level":1,"buki":["なし",0,0,0],"pos":{"x":0,"y":0}}} 上のバトル時のデータとほぼ同じですがmonstersの中にdamageという項目が増えてます。 "damage":["hp",1] プレイヤーのHPに1ダメージ与えた "damage":["agi",1] プレイヤーのAGIに1ダメージ与えた "damage":["str",1] プレイヤーのSTRに1ダメージ与えた "damage":["no"] なにもしなかった "damage":["heal",5] 敵がHP5回復した。 "damage":["all",1] プレイヤーのすべてのステータスに1ダメージ与えた ※このデータが送られてきた場合は、AIはなにも出力しなくていいです※ ・装備モード時に送られるJSONデータ {"equip":1,"now":{"name":"なし","str":0,"hp":0,"agi":0},"discover":{"name":"もげぞーの剣","str":1,"hp":0,"agi":0}} now 現在装備してる武器 desicover 発見した武器 str 攻撃力 hp HP agi agi ・レベルアップモード時に送られるJSONデータ {"levelup":1,"player":{"hp":30,"maxhp":30,"str":30,"maxstr":30,"agi":30,"maxagi":30,"level":1,"exp":0,"heal":2,"hammer":5,"map-level":1,"buki":["なし",0,0,0],"pos":{"x":0,"y":0}}} ・入出力データの詳細 4つのモードがありそれぞれAIが主力するアクションは異なります。 1, マップ移動モードのときのAIが出力するアクションは "移動方向" or "HEAL" という文字列です。 移動方向は "UP" "DOWN" "RIGHT" "LEFT"のいずれかです。 サンプル println "UP"; //上に移動 println "HEAL"; // 回復薬を使う 2, バトルモードのときのAIが出力するアクションは "STAB n" 敵を一体指定して、3〜(STR÷2)+2(小数点以下切り捨て)の間のランダムな値のダメージを与える "DOUBLE n n" 敵を2体指定して、1〜STR÷6(小数点以下切り捨て)の間のランダムな値のダメージを与える 同じ敵を指定して一度目の攻撃で倒した場合、2度めの攻撃はランダムな敵に攻撃します。 "SWING" 敵指定なし、1〜(STR÷3)+1の間のランダムな値回数だけ、ランダムな生きている敵に1ダメージ与える。 (一回一回ランダムな敵が選ばれる) "HEAL" 回復薬を1個使ってすべてのステータスを全回復 のいずれかです (nはモンスター番号) (STAB,DOUBLEには半角スペース大事) 2.5, 敵の攻撃時にjsonデータ(damage-info)が送られてきた場合は AIはなにも出力しなくていいです。 3, 装備モードのときのAIが出力するアクションは "YES" 装備する "NO" 装備しない(捨てる) のいずれかです 4, レベルアップモードのときにAIが出力するアクションは "HP" 体力、0になったらゲームオーバー "STR" 攻撃力、敵に与えるダメージに影響 "AGI" 素早さ、1ターンに行動できる回数に影響(HEALでも一回消費します) 0〜14:1回 15〜29:2回 30〜44:3回 45〜59:4回 ・・・こんな感じで15増えるごとに一回行動が増える のいずれかです。 増やしたいステータスを出力してください。 レベルアップしたときにもらえるステータスポイントは1〜3のランダムです。 ・エラーメッセージ 1 AIプログラムを起動できない場合 2 AIが名前として空行を送って来た場合 3 AIの予期せぬ終了などでパイプへの書き込み、読み込みができない場合 4 サーバーのコマンドライン指定がおかしい場合 $ ./mogeRPGserver --ai 'hoge' Couldn't execute "hoge": そのようなファイルやディレクトリはありません $ ./mogeRPGserver --ai 'echo' AIの名前が空です。 AIから名前を受け取ることができませんでした。 $ ./mogeRPGserver --ai 'echo -n' end of file on #<TWO-WAY-STREAM :INPUT-STREAM #<SB-SYS:FD-STREAM for "descriptor 6" {1002DFAB93}> :OUTPUT-STREAM #<SB-SYS:FD-STREAM for "descriptor 5" {1002DFA763}>> AIから名前を受け取ることができませんでした。 $ ./mogeRPGserver --ai 'echo AI' ストリームエラーが発生しました。 Couldn't write to #<SB-SYS:FD-STREAM for "descriptor 5" {1002DFAAA3}>: Broken pipe $ ./mogeRPGserver -x 不明なオプションです。-x $ ./mogeRPGserver hoge 解釈できないコマンドライン引数があります。("hoge") $ ./mogeRPGserver -d オプション -d に引数がありません。 $ ./mogeRPGserver -d hoge オプション -d への引数 hoge が解釈できません。 ・モンスターの種類 ・オーク ダメージ : 1〜levelの間のランダムな値をHPに与えてくる。 1/20の確率でハンマーを落とす。 ・ヒドラ ダメージ : 1〜HP÷2(小数点切り捨て)の間のランダムな値をHPに与えてくる。 ・スライム ダメージ : 1〜levelの間のランダムな値を、プレイヤーのagiが1以上ならagiに与えてきて プレイヤのagiが0だったらプレイヤーのHPに与えてくる。 1/20の確率で回復薬を落とす。 ・ブリガンド ダメージ : levelの値を、プレイヤーの一番高いステータスに与えてくる。 (プレイヤのステータスがHP:30 STR:32 AGI:18ならSTRにダメージが入る) (ステータスの数値が同じものがあった場合、優先順位はHP>AGI>STRになる) (HP:30 STR:28 AGI:30だったらHPにダメージが入る) (HP:28 STR:30 AGI:30だったらAGIにダメージが入る) ・メテルヨテイチ 1/2の確率でなにもしてこない。 1/2の確率で ダメージ : 1〜levelの間のランダムな値をHPに与えてくる。 メタルヨテイチには1しかダメージ与えられません。 ・ハツネツ 1/3の確率で ダメージ : 4〜(プレイヤーレベル+11)の間のランダムな値をHPに与えてくる。 1/3の確率で ダメージ : 4〜(プレイヤーレベル+11)の間のランダムな値をSTRに与えてくる。 (STRが0だった場合HPにダメージが入る) 1/3の確率で ヒール : 4〜(プレイヤーレベル+11)の間のランダムな値をハツネツ自身のHP回復する。 ・もげぞう 2/5の確率で ダメージ : 6〜(プレイヤーレベル+15)の間のランダムな値をHPに与えてくる。 1/5の確率で ダメージ : 6〜(プレイヤーレベル+15)の間のランダムな値をプレイヤーの全てのステータスに与えてくる。 2/5の確率で ダメージ : 6〜(プレイヤーレベル+15)の間のランダムな値をAGIに与えてくる。 (AGIが0だった場合HPにダメージが入る) ・敵の攻撃順番 上から順番(番号0から)に攻撃してきます。 ・一度に出てくる敵の数 初期値は1〜6、プレイヤーのレベルが4上がるごとに最大値は1増えていきます。 例:プレイヤーのレベルが10のとき、一度に出てくる敵の数は1〜8です。 ・50階のha2ne2 中ボスのハツネツエリアとバトルします。 倒すと必ず("ハツネツの剣" str:12 hp:12 agi:12)を落とします。 ・100階のイベント もげぞーの剣("もげぞーの剣" str:1 hp:0 agi:0)を100階まで持っていきイベントマスを踏むと もげぞうの剣("もげぞうの剣" str:30 hp:20 agi:20)に変化する。 ・マップ移動 2階降りるごとにハンマーが一個もらえる。 5階降りるごとに宝箱から出る武器の確率がちょっと変わる。 (しょぼい武器が出にくくレアがちょっと出やすくなる) 7階降りるごとにモンスターのレベルとHPが上がる。