人狼知能セミナー資料20160507
- 5. ビルド・パスの構成
• プレイヤー作成に必要なjarファイルをビルド・
パスに追加
– “ http://www.aiwolf.org/ ”から「開発者向け情報>人
狼知能プラットフォーム>aiwolf-ver0.3.3」をダウン
ロード
– Zipの中身
• 5つの.jarファイル
• 4つの.shファイル
• 4つの.batファイル
• 1つの.iniファイル
– 開発に使用するのはaiwolf-client.jar , aiwolf-
common.jar, aiwolf-server.jarの3つ
- 25. 設定ファイルの記述
• aiwolf-ver0.3.3フォルダ内のAutoStarter.iniを編集
• kaji1~kaji5から始まる行をコメントアウト
– 先頭に#をつけるとコメントになる
• 以下を末尾に追加
sample1,org.aiwolf.client.base.smpl.SampleRoleAssignPlayer
sample2,org.aiwolf.client.base.smpl.SampleRoleAssignPlayer
sample3,org.aiwolf.client.base.smpl.SampleRoleAssignPlayer
sample4,org.aiwolf.client.base.smpl.SampleRoleAssignPlayer
[適当な名前],[自分が作成したパッケージ名].[自分のクラス名
(例:InabaRoleAssignPlayer)]
→ サンプル4体と自分のエージェント1体でゲームを行う設定
- 40. @Override
public Agent vote(){
//投票対象の候補者リスト
List<Agent> voteCandidates = new ArrayList<Agent>();
//生きているプレイヤーを候補者リストに加える
voteCandidates.addAll(getLatestDayGameInfo().getAliveAgentList());
//自分自身と白判定のプレイヤーは候補から外す
voteCandidates.remove(getMe());
return randomSelect(voteCandidates);
}
vote()の実装
↑getLatestDayGameInfo()はAbstractPlayer内のメソッド
で,最新のGameInfoを返す
GameInfoはサーバから送られてくるゲーム内情報.ロ
グや占い結果等の全ての情報はここから取得する
続く
- 42. vote()の実装(全体像)
@Override
public Agent vote(){
//投票対象の候補者リスト
List<Agent> voteCandidates = new ArrayList<Agent>();
//生きているプレイヤーを候補者リストに加える
voteCandidates.addAll(getLatestDayGameInfo().getAliveAgentList());
//自分自身と白判定のプレイヤーは候補から外す
voteCandidates.remove(getMe());
return randomSelect(voteCandidates);
}
/**
* 引数のAgentのリストからランダムにAgentを選択する
* @param agentList
* @return
*/
private Agent randomSelect(List<Agent> agentList){
int num = new Random().nextInt(agentList.size());
return agentList.get(num);
}
}
次はdivine()を実装してみよう
- 45. divine()の実装
@Override
public Agent divine() {
//占い対象の候補者リスト
List<Agent> divineCandidates = new ArrayList<Agent>();
//生きているプレイヤーを候補者リストに加える
divineCandidates.addAll(getLatestDayGameInfo().getAliveAgentList());
//自分自身と既に占ったことのあるプレイヤーは候補から外す
divineCandidates.remove(getMe());
for(Judge judge: getMyJudgeList()){
if(divineCandidates.contains(judge.getTarget())){
divineCandidates.remove(judge.getTarget());
}
}
続く
- 47. divine()の実装(全体像)
@Override
public Agent divine() {
//占い対象の候補者リスト
List<Agent> divineCandidates = new ArrayList<Agent>();
//生きているプレイヤーを候補者リストに加える
divineCandidates.addAll(getLatestDayGameInfo().getAliveAgentList());
//自分自身と既に占ったことのあるプレイヤーは候補から外す
divineCandidates.remove(getMe());
for(Judge judge: getMyJudgeList()){
if(divineCandidates.contains(judge.getTarget())){
divineCandidates.remove(judge.getTarget());
}
}
if(divineCandidates.size() > 0){
//候補者リストからランダムに選択
return randomSelect(divineCandidates);
}else{
//候補者がいない場合は自分を占い
return getMe();
}
}
次は占い結果を投票に反映させてみましょう
- 50. vote()の実装2
@Override
public Agent vote() {
List<Agent> whiteAgent = new ArrayList<Agent>(), //白判定だったプレイヤー
blackAgent = new ArrayList<Agent>(); //黒判定だったプレイヤー
//今まで占ったプレイヤーをwhiteAgentとblackAgentに分ける
for(Judge judge: getMyJudgeList()){
if(getLatestDayGameInfo().getAliveAgentList().contains(judge.getTarget())){
switch (judge.getResult()) {
case HUMAN:
whiteAgent.add(judge.getTarget());]
break;
case WEREWOLF:
blackAgent.add(judge.getTarget());
}
}
}
続く
- 51. vote()の実装2
if(blackAgent.size() > 0){
//blackAgentがいればその中から選択
return randomSelect(blackAgent);
}else{
//投票対象の候補者リスト
List<Agent> voteCandidates = new ArrayList<Agent>();
voteCandidates.addAll(getLatestDayGameInfo().getAliveAgentList());
//生きているプレイヤーを候補者リストに加える
//自分自身と白判定のプレイヤーは候補から外す
voteCandidates.remove(getMe());
voteCandidates.removeAll(whiteAgent);
return randomSelect(voteCandidates);
}
}
- 52. vote()の実装2(全体像)
@Override
public Agent vote() {
List<Agent> whiteAgent = new ArrayList<Agent>(), //白判定だったプレイヤー
blackAgent = new ArrayList<Agent>(); //黒判定だったプレイヤー
for(Judge judge: getMyJudgeList()){
if(getLatestDayGameInfo().getAliveAgentList().contains(judge.getTarget())){
switch (judge.getResult()) {
case HUMAN:
whiteAgent.add(judge.getTarget());]
break;
case WEREWOLF:
blackAgent.add(judge.getTarget());
}
}
}
if(blackAgent.size() > 0){
return randomSelect(blackAgent);
}else{
//投票対象の候補者リスト
List<Agent> voteCandidates = new ArrayList<Agent>();
voteCandidates.addAll(getLatestDayGameInfo().getAliveAgentList()); //生きているプレイヤーを候補者リストに加える
//自分自身と白判定のプレイヤーは候補から外す
voteCandidates.remove(getMe());
voteCandidates.removeAll(whiteAgent);
return randomSelect(voteCandidates);
}
}
次は占い結果を発話してみましょう
- 55. TemplateTalkFactoryクラス
• estimate(Agent, Role)
– Agentの役職はRoleだと思う
• comingout(Agent, Role)
– AgentがRoleをカミングアウトする
• divined(Agent, Species)
– Agentを占った結果Speciesだった
• inquested(Agent, Species)
– Agentの霊能結果がSpeciesだった
• guarded(Agent)
– Agentを守った
• vote(Agent)
– Agentに投票する
• (dis)agree(TalkType, day, id)
– 対象の発話に同意(反対)する
• skip()
– まだ今日話したいことがある
• over()
– もう今日は話すことない
- 58. talk()の実装
boolean isComingOut = false; //既に役職のカミングアウトをしているか
//報告済みのJudgeを格納
List<Judge> myToldJudgeList = new ArrayList<Judge>();
@Override
public String talk() {
//占いで人狼を見つけたらカミングアウトする
if(!isComingOut){
for(Judge judge: getMyJudgeList()){
if(judge.getResult() == Species.WEREWOLF){ //占い結果が人狼の場合
String comingoutTalk = TemplateTalkFactory.comingout(getMe(),
getMyRole());
isComingOut = true;
return comingoutTalk;
}
}
}
続く
- 60. talk()の実装(全体像)
boolean isComingOut = false; //既に役職のカミングアウトをしているか
//報告済みのJudgeを格納
List<Judge> myToldJudgeList = new ArrayList<Judge>();
@Override
public String talk() {
//占いで人狼を見つけたらカミングアウトする
if(!isComingOut){
for(Judge judge: getMyJudgeList()){
if(judge.getResult() == Species.WEREWOLF){ //占い結果が人狼の場合
String comingoutTalk = TemplateTalkFactory.comingout(getMe(), getMyRole());
isComingOut = true;
return comingoutTalk;
}
}
}
//カミングアウトした後は,まだ言っていない占い結果を順次報告
else{
for(Judge judge: getMyJudgeList()){
if(!myToldJudgeList.contains(judge)){ //まだ報告していないJudgeの場合
String resultTalk = TemplateTalkFactory.divined(judge.getTarget(), judge.getResult());
myToldJudgeList.add(judge);
return resultTalk;
}
}
}
//話すことが無ければ会話終了
return Talk.OVER;
}
次は他の人の発話を読み込んでみましょう
- 63. Utteranceクラスの使い方
戻り値 メソッド名と説明
String getText()
発話内容をそのまま返す
Topic getTopic()
発話のTopicを返す(COMINGOUTやDIVINED等)
Agent getTarget()
発話内の目的語となるプレイヤーを返す(例えば”DIVINED Agent[01] HUMAN” → Agent[01])
Role getRole()
発話の目的語となる役職を返す(例えば”COMINGOUT Agent[02] SEER” → SEER)
Species getResult()
占い(霊能)の結果を返す(例えば”INQUESTED Agent[03] WEREWOLF” → WEREWOLF)
TalkType getTalkType()
TopicがAGREE,DISAGREEの時,対象発話のTalkType(全体ログor囁き)を返す
int getTalkDay()
TopicがAGREE,DISAGREEの時,対象発話の発話日を返す
int getTalkID()
TopicがAGREE,DISAGREEの時,対象発話の発話IDを返す
- 64. @Override
public void update(GameInfo gameInfo) {
super.update(gameInfo);
//今日のログを取得
List<Talk> talkList = gameInfo.getTalkList();
for(int i = 0; i < talkList.size(); i++){
Talk talk = talkList.get(i);
//発話をパース
Utterance utterance = new Utterance(talk.getContent());
//発話のトピックごとに処理
switch (utterance.getTopic()) {
case COMINGOUT:
//カミングアウトの発話の処理
break;
case DIVINED:
// 占い結果の発話の処理
break;
}
}
}
ログの読み込み
このままだと,update()が呼ばれる度に,その日のログを全部読み込む
→ 一度読み込んだTalkは読まないように変更してみる
- 66. @Override
public void update(GameInfo gameInfo) {
super.update(gameInfo);
//今日のログを取得
List<Talk> talkList = gameInfo.getTalkList();
for(int i = readTalkNum; i < talkList.size(); i++){
Talk talk = talkList.get(i);
//発話をパース
Utterance utterance = new Utterance(talk.getContent());
//発話のトピックごとに処理
switch (utterance.getTopic()) {
case COMINGOUT:
//カミングアウトの発話の処理
break;
case DIVINED:
// 占い結果の発話の処理
break;
}
readTalkNum++;
}
}
オレンジ部分:追加
赤部分:修正
ログの読み込み2
- 67. ログの読み込み2(全体像)
//その日のログの何番目まで読み込んだか
int readTalkNum = 0;
@Override
public void dayStart(){
super.dayStart();
readTalkNum = 0;
}
@Override
public void update(GameInfo gameInfo) {
super.update(gameInfo);
//今日のログを取得
List<Talk> talkList = gameInfo.getTalkList();
for(int i = readTalkNum; i < talkList.size(); i++){
Talk talk = talkList.get(i);
//発話をパース
Utterance utterance = new Utterance(talk.getContent());
//発話のトピックごとに処理
switch (utterance.getTopic()) {
case COMINGOUT:
//カミングアウトの発話の処理
break;
case DIVINED:
// 占い結果の発話の処理
break;
}
readTalkNum++;
}
}
オレンジ部分:追加
赤部分:修正
←自分以外に占い師COしているプレイヤーを
敵リストに追加してみましょう
- 68. //偽占い師COしているプレイヤーのリスト
List<Agent> fakeSeerCOAgent = new ArrayList<Agent>();
@Override
public void update(GameInfo gameInfo) {
super.update(gameInfo);
//今日のログを取得
List<Talk> talkList = gameInfo.getTalkList();
for(int i = readTalkNum; i < talkList.size(); i++){
Talk talk = talkList.get(i);
//発話をパース
Utterance utterance = new Utterance(talk.getContent());
//発話のトピックごとに処理
switch (utterance.getTopic()) {
case COMINGOUT:
//自分以外で占い師COしているプレイヤーの場合
if(utterance.getRole() == Role.SEER
&& !talk.getAgent().equals(getMe())){
fakeSeerCOAgent.add(utterance.getTarget());
}
break;
case DIVINED:
// 占い結果の発話の処理
break;
}
readTalkNum++;
}
}
オレンジ部分:追加
赤部分:修正
ログの読み込み3(全体像)
- 74. GameInfoの説明
戻り値 メソッド名と説明
int getDay()
日にちを返す
Role getRole()
自分の役職を返す
Agent getAgent()
自分(Agent型)を返す
List<Agent> getAgentList()
全プレイヤーのリストを返す
Species getMediumResult()
霊能結果を返す(霊能者のみ)
Species getDivineResult()
占い結果を返す(占い師のみ)
Agent getExecutedAgent()
処刑されたプレイヤーを返す
Agent getAttackedAgent()
襲撃されたプレイヤーを返す
List<Vote> getVoteList()
処刑の際の投票リストを返す
List<Vote> getAttackVoteList()
襲撃の際の人狼による投票のリストを返す(人狼のみ)
List<Talk> getTalkList()
会話のログを返す
List<Talk> getWhisperList()
囁きのログを返す(人狼のみ)
List<Agent> getAliveAgentList()
生きているプレイヤーのリストを返す
Map<Agent, Status> getStatusMap()
各プレイヤーの生死の状態を返す
Map<Agent, Role> getRoleMap()
各プレイヤーの役職を返す.ゲーム中は自分の分かる役職の
み(村人なら自分だけ,人狼なら仲間の人狼も)
ゲーム終了時は全員の役職が分かる.