ver0.1.16に対応するよう改訂しました(2015/03/07).
ver0.1.15までとの最大の違いは,RoleAssignPlayerに挿入するPlayerがPlayerクラスを継承しなくなったことです.
AbstractVillagerPlayer→AbstractVillagerのようになりました.
ご了承ください.
今日は
人狼知能エージェントを作ろうと思うので,その作り方をメモしていく.
まずは,
http://www.aiwolf.org/の資料→人狼知能サーバから人狼知能0.1.15をダウンロード.
中身は簡易マニュアルとjarファイルが4つ.
aiwolf-client-0.1.16.jar
aiwolf-common-0.1.16.jar
aiwolf-server-0.1.16.jar
jsonic-1.3.2.jar
Eclipseで新しいプロジェクトを作って,これらのjarファイルをライブラリに登録しておく.
さて,人狼知能エージェントを作るには,まずRoleBasePlayerを継承したクラスを作るところから始まる.
とりあえず,面倒なのでBasePlayerという名前で作成.
BasePlayerは何をやるかというと,職業が割り当てられたときに,職業ごとに異なるPlayerを起動してくれるのである.
人狼においては,占い師になったときと人狼になったときでは,プレイ方法が全然異なる.
そこで,職業が割り当てられた時点で,職業ごとに対応するPlayerクラスを立ち上げるようにしておけば,一つのPlayerクラスに付き一つの職業についてのみ考えれば良くなるわけである.
ここでは,まず村人から作ってみよう.
というわけで,新しくMyVillagerPlayerを作成する.
自作村人エージェントを作るには,org.aiwolf.client.base.player.AbstractViillagerPlayerを継承したクラスを作れば良い.
package org.aiwolf.player;
import org.aiwolf.client.base.player.AbstractVillager;
import org.aiwolf.common.AIWolfRuntimeException;
import org.aiwolf.common.data.Agent;
import org.aiwolf.common.net.GameInfo;
public class MyVillagerPlayer extends AbstractVillager {
@Override
public void dayStart() {
// TODO 自動生成されたメソッド・スタブ
}
@Override
public void finish() {
// TODO 自動生成されたメソッド・スタブ
}
@Override
public String talk() {
// TODO 自動生成されたメソッド・スタブ
return null;
}
@Override
public Agent vote() {
// TODO 自動生成されたメソッド・スタブ
return null;
}
}
今のところ何もしないが,とりあえずこのMyVillagerPlayerをBasePlayerに登録する.
package org.aiwolf.player;
import org.aiwolf.client.base.player.AbstractRoleAssignPlayer;
public class BasePlayer extends AbstractRoleAssignPlayer {
public BasePlayer() {
setVillagerPlayer(new MyVillager());
}
@Override
public String getName() {
return BasePlayer.class.getSimpleName();
}
}
まずは,ここで起動してみよう.
起動する場合は,Eclipseのメニューで実行→実行構成
名前はRoleRequestStarterとでもしておいて,メインクラスにRoleRequestStarterを選ぶ.
さらに,引数タグを選んで,プログラムの引数に
-n 12 -c org.aiwolf.player.BasePlayer VILLAGER
と書いておこう.
これで,実行.
Agent[04] request no role
Agent[08] request no role
Agent[01] request no role
Agent[05] request no role
Agent[03] request no role
Agent[10] request no role
Agent[02] request no role
Agent[11] request no role
Agent[09] request villager
Agent[12] request no role
Agent[06] request no role
Agent[07] request no role
===========
Day 00
======
Agent[01] SamplePlayer alive possessed
Agent[02] SamplePlayer alive villager
Agent[03] SamplePlayer alive villager
Agent[04] SamplePlayer alive bodyguard
Agent[05] SamplePlayer alive seer
Agent[06] SamplePlayer alive werewolf
Agent[07] SamplePlayer alive werewolf
Agent[08] SamplePlayer alive medium
Agent[09] BasePlayer alive villager
Agent[10] SamplePlayer alive villager
Agent[11] SamplePlayer alive villager
Agent[12] SamplePlayer alive villager
10-2
===========
こんな感じでBasePlayerがvilagerになっていれば起動は完了.
その後は自動でゲームが進行する.
ところで,ここではvoteでnullを返している.つまり投票先を決めていないことになる.
この場合,ver0.1.16ではランダムに投票したことになっている.
別に問題は無いが,せっかくなのでnull以外を返すように変更してみよう.
変更するのは,MyVillagerのvoteメソッド.
@Override
public Agent vote() {
// TODO 自動生成されたメソッド・スタブ
return null;
}
まずは,簡単に
・生きているエージェントの中で
・自分を除いて
・一番最初に見つけたエージェント
に投票することにしよう.
進行中のゲームに関する全ての情報は,
getGameInfoで取得可能.
特に,最新の情報は
GameInfo gameInfo = getLatestDayGameInfo();
で取得可能.
GameInfoからは様々な情報が取得可能だが,まずは自分自身のエージェントと状態,職業,そして日付を取得してみよう.
GameInfo gameInfo = getLatestDayGameInfo();
Agent myself = gameInfo.getAgent();
System.out.println("I am "+gameInfo.getStatusMap().get(myself));
System.out.println("I am "+gameInfo.getRole());
System.out.println("Today is "+gameInfo.getDay()+" day");
と書いておくと,
I am alive
I am villager
Today is 0 day
と表示され,とりあえずちゃんと動いていることが分かる.
さて,次はいよいよ投票する対象を決めよう.
生きているエージェント一覧は,gameInfo.getAliveAgentList();で取得可能.
このとき,返ってきたエージェントの中で自分じゃない最初のエージェントに投票することにする.
@Override
public Agent vote() {
GameInfo gameInfo = getLatestDayGameInfo();
Agent myself = gameInfo.getAgent();
List<agent> agentList = gameInfo.getAliveAgentList();
for(Agent agent:agentList){
if(agent != myself){
System.out.println(myself+" vote to "+agent);
return agent;
}
}
throw new AIWolfRuntimeException("Something wrong");
}
自分しかいなかった場合は誰も選ばれずにメソッドが終わってしまうが,ゲームの仕様上そんなことはないので,
もしそんなことがあったらAIWolfRuntimeExceptionを投げて終了することにしておこう.
さて,コレで実行するとどうなるか.
6 20, 2014 4:24:48 午後 org.aiwolf.common.util.AiWolfLoggerFactory getSimpleLogger
構成: ログ設定: LogManagerを設定しました。
Agent[07] request no role
Agent[04] request no role
Agent[03] request no role
Agent[01] request no role
Agent[09] request no role
Agent[10] request no role
Agent[08] request no role
Agent[11] request no role
Agent[05] request villager
Agent[12] request no role
Agent[02] request no role
Agent[06] request no role
===========
Day 00
======
Agent[01] SamplePlayer alive seer
Agent[02] SamplePlayer alive werewolf
Agent[03] SamplePlayer alive possessed
Agent[04] SamplePlayer alive medium
Agent[05] BasePlayer alive villager
Agent[06] SamplePlayer alive werewolf
Agent[07] SamplePlayer alive bodyguard
Agent[08] SamplePlayer alive villager
Agent[09] SamplePlayer alive villager
Agent[10] SamplePlayer alive villager
Agent[11] SamplePlayer alive villager
Agent[12] SamplePlayer alive villager
10-2
===========
中略
Agent[05] vote to Agent[03]
6 20, 2014 4:24:48 午後 org.aiwolf.server.AIWolfGame vote
情報: 0,vote,5,3
6 20, 2014 4:24:48 午後 org.aiwolf.server.AIWolfGame vote
情報: 0,vote,6,6
6 20, 2014 4:24:48 午後 org.aiwolf.server.AIWolfGame vote
情報: 0,vote,11,6
6 20, 2014 4:24:48 午後 org.aiwolf.server.AIWolfGame vote
情報: 0,vote,12,1
6 20, 2014 4:24:48 午後 org.aiwolf.server.AIWolfGame vote
情報: 0,vote,9,2
6 20, 2014 4:24:48 午後 org.aiwolf.server.AIWolfGame vote
情報: 0,vote,10,8
中略
===========
Day 01
Agent[06] executed
Agent[01] divine Agent[09]. Result is Human
Agent[07] guarded Agent[08]@0 guarded
Agent[11] attacked
======
Agent[01] SamplePlayer alive seer
Agent[02] SamplePlayer alive werewolf
Agent[03] SamplePlayer alive possessed
Agent[04] SamplePlayer alive medium
Agent[05] BasePlayer alive villager
Agent[06] SamplePlayer dead werewolf executed
Agent[07] SamplePlayer alive bodyguard
Agent[08] SamplePlayer alive villager guarded
Agent[09] SamplePlayer alive villager divined
Agent[10] SamplePlayer alive villager
Agent[11] SamplePlayer dead villager attacked
Agent[12] SamplePlayer alive villager
9-1
中略
===========
Day 02
Agent[10] executed
Agent[01] divine Agent[12]. Result is Human
Agent[07] guarded Agent[01]@1 guarded
null attacked
======
Agent[01] SamplePlayer alive seer guarded
Agent[02] SamplePlayer alive werewolf
Agent[03] SamplePlayer alive possessed
Agent[04] SamplePlayer alive medium
Agent[05] BasePlayer alive villager
Agent[06] SamplePlayer dead werewolf
Agent[07] SamplePlayer alive bodyguard
Agent[08] SamplePlayer alive villager
Agent[09] SamplePlayer alive villager
Agent[10] SamplePlayer dead villager executed
Agent[11] SamplePlayer dead villager
Agent[12] SamplePlayer alive villager divined
中略
===========
Day 03
Agent[05] executed
Agent[01] divine Agent[04]. Result is Human
Agent[07] guarded Agent[02]@2 guarded
Agent[09] attacked
======
Agent[01] SamplePlayer alive seer
Agent[02] SamplePlayer alive werewolf guarded
Agent[03] SamplePlayer alive possessed
Agent[04] SamplePlayer alive medium divined
Agent[05] BasePlayer dead villager executed
Agent[06] SamplePlayer dead werewolf
Agent[07] SamplePlayer alive bodyguard
Agent[08] SamplePlayer alive villager
Agent[09] SamplePlayer dead villager attacked
Agent[10] SamplePlayer dead villager
Agent[11] SamplePlayer dead villager
Agent[12] SamplePlayer alive villager
中略
===========
Day 04
Agent[01] executed
Agent[01] divine Agent[08]. Result is Human
Agent[07] guarded Agent[08]@3 guarded
Agent[01] attacked
======
Agent[01] SamplePlayer dead seer executed attacked
Agent[02] SamplePlayer alive werewolf
Agent[03] SamplePlayer alive possessed
Agent[04] SamplePlayer alive medium
Agent[05] BasePlayer dead villager
Agent[06] SamplePlayer dead werewolf
Agent[07] SamplePlayer alive bodyguard
Agent[08] SamplePlayer alive villager divined guarded
Agent[09] SamplePlayer dead villager
Agent[10] SamplePlayer dead villager
Agent[11] SamplePlayer dead villager
Agent[12] SamplePlayer alive villager
中略
===========
Day 05
Agent[07] executed
Agent[07] guarded Agent[04]@4 guarded
null attacked
======
Agent[01] SamplePlayer dead seer
Agent[02] SamplePlayer alive werewolf
Agent[03] SamplePlayer alive possessed
Agent[04] SamplePlayer alive medium guarded
Agent[05] BasePlayer dead villager
Agent[06] SamplePlayer dead werewolf
Agent[07] SamplePlayer dead bodyguard executed
Agent[08] SamplePlayer alive villager
Agent[09] SamplePlayer dead villager
Agent[10] SamplePlayer dead villager
Agent[11] SamplePlayer dead villager
Agent[12] SamplePlayer alive villager
中略
===========
Day 06
Agent[12] executed
Agent[04] attacked
======
Agent[01] SamplePlayer dead seer
Agent[02] SamplePlayer alive werewolf
Agent[03] SamplePlayer alive possessed
Agent[04] SamplePlayer dead medium attacked
Agent[05] BasePlayer dead villager
Agent[06] SamplePlayer dead werewolf
Agent[07] SamplePlayer dead bodyguard
Agent[08] SamplePlayer alive villager
Agent[09] SamplePlayer dead villager
Agent[10] SamplePlayer dead villager
Agent[11] SamplePlayer dead villager
Agent[12] SamplePlayer dead villager executed
===========
Day 07
Agent[03] executed
Agent[03] attacked
======
Agent[01] SamplePlayer dead seer
Agent[02] SamplePlayer alive werewolf
Agent[03] SamplePlayer dead possessed executed attacked
Agent[04] SamplePlayer dead medium
Agent[05] BasePlayer dead villager
Agent[06] SamplePlayer dead werewolf
Agent[07] SamplePlayer dead bodyguard
Agent[08] SamplePlayer alive villager
Agent[09] SamplePlayer dead villager
Agent[10] SamplePlayer dead villager
Agent[11] SamplePlayer dead villager
Agent[12] SamplePlayer dead villager
===========
Send finish to Agent[03]
Send finish to Agent[04]
Send finish to Agent[01]
Send finish to Agent[02]
Send finish to Agent[07]
Send finish to Agent[08]
Send finish to Agent[05]
Send finish to Agent[06]
Send finish to Agent[11]
Send finish to Agent[12]
Send finish to Agent[09]
Send finish to Agent[10]
Winner:werewolf
というわけで,ちゃんと別のエージェントを指定して投票行動を行っていたことが分かります.
ただし,三日目に本人が処刑されちゃったみたいですね.
しかも,最後は人狼の勝利.
投票行動を適当に行うだけではやはり勝てそうもありません.
次回は,他の人が何を言っているのか理解して,占い師が人狼だと言っているエージェントに投票するように
改良してみたいと思います.
できるのかなあ?
ちなみに,今日作ったMyVillagerのソースコードは以下の通り.
package org.aiwolf.player;
import java.util.List;
import org.aiwolf.client.base.player.AbstractVillager;
import org.aiwolf.common.AIWolfRuntimeException;
import org.aiwolf.common.data.Agent;
import org.aiwolf.common.net.GameInfo;
public class MyVillager extends AbstractVillager {
@Override
public void dayStart() {
// TODO 自動生成されたメソッド・スタブ
}
@Override
public void finish() {
// TODO 自動生成されたメソッド・スタブ
}
@Override
public String talk() {
// TODO 自動生成されたメソッド・スタブ
return null;
}
@Override
public Agent vote() {
GameInfo gameInfo = getLatestDayGameInfo();
Agent myself = gameInfo.getAgent();
List agentList = gameInfo.getAliveAgentList();
for(Agent agent:agentList){
if(agent != myself){
System.out.println(myself+" vote to "+agent);
return agent;
}
}
throw new AIWolfRuntimeException("Something wrong");
}
}
BasePlayerのソースコードは以下の通り.
package org.aiwolf.player;
import org.aiwolf.client.base.player.AbstractRoleAssignPlayer;
public class BasePlayer extends AbstractRoleAssignPlayer {
public BasePlayer() {
setVillagerPlayer(new MyVillager());
}
@Override
public String getName() {
return BasePlayer.class.getSimpleName();
}
}