YESNO
14. SkipContentBuilder() : 様子を見る
以下で定義される定数
Content.SKIP
が用意されているSKIP = new Content(new SkipContentBuilder());
詳細は,
aiwolf-ver0.4.4.zip
(1
つ前のリリース)内の「
0.4.4
での発話生成の方法(修正版2
)発話生成の例
//占いの情報の取得
Judge judge = getLatestDayGameInfo().getDivineResult();
//発話の作成
ContentBuilder builder = new
DivinedResultContentBuilder(judge.getTarget(), judge.getResult();
String talk = new Content(builder).getText();
今日の占い結果を報告する発話を生成
talk() の実装
1.
占いで人狼を見つけたらカミングアウト2.
カミングアウトした後は占い結果を報告するtalk() の実装
public String talk() {
// 占いで人狼を見つけたらカミングアウトする if (!isCO) {
if (!myDivinationQueue.isEmpty() &&
myDivinationQueue.peek().getResult() == Species.WEREWOLF) { isCO = true;
ContentBuilder builder = new ComingoutContentBuilder(me,
Role.SEER) return new Content(builder).getText();
} }
続く
待ち行列の先頭の要素を取り出さずに取得
talk() の実装
// カミングアウトした後は、まだ報告していない占い結果を順次報告 else {
if (!myDivinationQueue.isEmpty()) {
Judge divination = myDivinationQueue.poll();
ContentBuilder builder = new
DivinedResultContentBuilder(divination.getTarget(), divination.getResult());
return new Content(builder).getText();
} }
return Content.OVER.getText();
}
待ち行列の先頭の要素を取り出す
talk() の実装(全体像)
public String talk() {
// 占いで人狼を見つけたらカミングアウトする if (!isCO) {
if (!myDivinationQueue.isEmpty() && myDivinationQueue.peek().getResult() == Species.WEREWOLF) { isCO = true;
ContentBuilder builder = new ComingoutContentBuilder(me, Role.SEER) return new Content(builder).getText();
} }
// カミングアウトした後は、まだ報告していない占い結果を順次報告 else {
if (!myDivinationQueue.isEmpty()) {
Judge divination = myDivinationQueue.poll();
ContentBuilder builder = new DivinedResultContentBuilder(divination.getTarget(), divination.getResult());
return new Content(builder).getText();
} }
return Content.OVER.getText();
}
次は他の人の発話を読み込んでみましょう
会話内容の取り込み
•
会話のリストはGameInfo.getTalkList()
でList<Talk>
型 として取得• Talk
クラスのメソッド– getAgent()
:発話したAgent
を取得– getText()
:発話内容(String
)を取得– getDay()
:発話日(int
)を取得– getIdx()
:その日の何番目の発話か(int
)を取得– getTurn()
:その日の何番目のターンの発話か(
int
)を取得会話内容の取り込み
Talk.getText()
で得られる文字列は人狼知能プロトコルに準拠例:
“DIVINED Agent[04] HUMAN”
この文字列を
parse
するには,Content
クラスのコンストラクタの 引数として与える//Content
クラスのコンストラクタの引数に発話内容のString
を入れると 自動的にパースされるContent content = new Content(talk.getText());
Content クラスの使い方
戻り値 メソッド名 説明
String getText() 発話内容をそのまま返す
Operator getOperator() 発話内容の演算子を返す.発話が単文の場合はnull
Agent getSubject() 発話内容の主語を返す
Topic getTopic() 発話内容のトピックを返す(COMINGOUTやDIVINED等)
Agent getTarget() 発話内容の目的語となるプレイヤーを返す(例えば”DIVINED Agent[01]
HUMAN” → Agent[01])
Role getRole() 発話の目的語となる役職を返す(例えば”COMINGOUT Agent[02] SEER”
→ SEER)
Species getResult() 占い(霊媒)の結果を返す(例えば”IDENTIFIED Agent[03] WEREWOLF”
→ WEREWOLF)
TalkType getTalkType() TopicがAGREE/DISAGREEの時,対象発話のタイプ(TALK/WHISPER)を返す
int getTalkDay() TopicがAGREE/DISAGREEの時,対象発話の発話日を返す
int getTalkID() TopicがAGREE/DISAGREEの時,対象発話の発話IDを返す List<Content> getContentList() 発話内容が複文・重文の場合,節のリストを返す
会話内容を取り込むように update() を修正(1)
/** GameInfo.talkList読み込みのヘッド */
int talkListHead; // dayStart()中で0に初期化しておくこと
public void update(GameInfo gameInfo) { currentGameInfo = gameInfo;
// GameInfo.talkListからカミングアウト・占い報告・霊媒報告を抽出
for (int i = talkListHead; i < currentGameInfo.getTalkList().size();
i++) { Talk talk = currentGameInfo.getTalkList().get(i);
Agent talker = talk.getAgent();
if (talker == me) { continue;
}
Content content = new Content(talk.getText()); // 発話をparse
続く
会話内容を取り込むように update() を修正(2)
switch (content.getTopic()) { case COMINGOUT:
// カミングアウト発話の処理 break;
case DIVINED:
// 占い結果報告発話の処理 break;
case IDENTIFIED:
// 霊媒結果報告発話の処理 break;
default:
break;
} }
talkListHead = currentGameInfo.getTalkList().size();
}
修正した update() の全体像
/** GameInfo.talkList読み込みのヘッド */
int talkListHead; // dayStart()中で0に初期化しておくこと public void update(GameInfo gameInfo) {
currentGameInfo = gameInfo;
// GameInfo.talkListからカミングアウト・占い報告・霊媒報告を抽出
for (int i = talkListHead; i < currentGameInfo.getTalkList().size(); i++) { Talk talk = currentGameInfo.getTalkList().get(i);
Agent talker = talk.getAgent();
if (talker == me) { continue;
}
Content content = new Content(talk.getText()); // 発話をparse switch (content.getTopic()) {
case COMINGOUT: // カミングアウト発話の処理 break;
case DIVINED: // 占い結果報告発話の処理 break;
case IDENTIFIED: // 霊媒結果報告発話の処理 break;
default:
break;
} }
talkListHead = currentGameInfo.getTalkList().size();
}
実際にカミングアウトの情報を 取り込んでみましょう
カミングアウト情報の取り込み例
/** カミングアウト状況 */
Map<Agent, Role> comingoutMap = new HashMap<>(); // initializeで初期化しておくこと public void update(GameInfo gameInfo) {
currentGameInfo = gameInfo;
// GameInfo.talkListからカミングアウト・占い報告・霊媒報告を抽出
for (int i = talkListHead; i < currentGameInfo.getTalkList().size(); i++) { Talk talk = currentGameInfo.getTalkList().get(i);
Agent talker = talk.getAgent();
if (talker == me) { continue;
}
Content content = new Content(talk.getText()); // 発話をparse switch (content.getTopic()) {
case COMINGOUT:
// カミングアウト情報の取り込み
comingoutMap.put(talker, content.getRole());
break;
case DIVINED: // 占い結果報告発話の処理 break;
case IDENTIFIED: // 霊媒結果報告発話の処理 break;
default:
break;
} }
talkListHead = currentGameInfo.getTalkList().size();
}
カミングアウト情報が取り込めたら
•
例えば,偽の占い師が現れたことがわかる–
自分のカミングアウト前だったらどうする?–
偽占い師は人狼か,それとも裏切り者か・・・などについて,対応を考えてみましょう
補足
Player の各メソッドの説明
• initialize(GameInfo)
–
ゲーム開始時に一度だけ 呼ばれる–
サーバから送られてくるGameInfo
を取得• update(GameInfo)
–
各行動の前に呼ばれる–
サーバから送られてくるGameInfo
を取得• dayStart()
–
日の初めに呼ばれる• finish()
–
ゲームが終了した時に呼 ばれるPlayer の各メソッドの説明
• vote()
–
投票する相手を選択する• attack()
–
襲撃する相手を選択する–
人狼のみ呼ばれる• divine()
–
占いする相手を選択する–
占い師のみ呼ばれる• guard()
–
護衛する相手を選択する–
狩人のみ呼ばれる1
日の終わりに呼ばれるメソッドAgent
を返す必要ありPlayer の各メソッドの説明
• talk()
–
全体に対して発話する–
全員呼ばれるメソッド• whisper()
–
人狼だけに対して発話す る–
人狼のプレイヤーだけが 使用するメソッド発話のメソッド
String
を返す必要ありGameInfo
の説明戻り値 メソッド名 説明
int getDay() 日にちを返す
Role getRole() 自分の役職を返す
List<Agent> getExistingRoles() このゲームに存在する役職のリストを返す
Agent getAgent() 自分(Agent型)を返す
List<Agent> getAgentList() 全プレイヤーのリストを返す
Species getMediumResult() 霊媒結果を返す(霊媒師のみ)
Species getDivineResult() 占い結果を返す(占い師のみ)
Agent getGuardedAgent() 前日護衛したプレイヤーを返す(狩人のみ)
List<Agent> getLastDeadAgentList() 前日死亡したプレイヤーのリストを返す(呪殺された妖狐を含む)
Agent getExecutedAgent() 前日追放されたプレイヤーを返す
Agent getLatestExecutedAgent() 当日追放が決まったプレイヤーを返す.決定前はnull
Agent getAttackedAgent() 襲撃の成否にかかわらず,襲撃したプレイヤーを返す(人狼のみ)
List<Vote> getVoteList() 前日の追放の際の投票リストを返す
List<Vote> getLatestVoteList() 追放再投票の場合,前投票のリストを返す
List<Vote> getAttackVoteList() 襲撃投票のリストを返す(人狼のみ)
List<Vote> getLatestAttackVoteList() 襲撃再投票の場合,前投票のリストを返す(人狼のみ)
List<Talk> getTalkList() 会話のリストを返す
List<Talk> getWhisperList() 囁きのリストを返す(人狼のみ)
List<Agent> getAliveAgentList() 生きているプレイヤーのリストを返す
Map<Agent, Status> getStatusMap() 各プレイヤーの生死の状態を返す
Map<Agent, Role> getRoleMap() 各プレイヤーの役職を返す.ゲーム中は自分の分かる役職のみ(村人な
ら自分だけ,人狼なら仲間の人狼も).ゲーム終了時は全員の役職.
付録: GUI によるゲームの実行
GUI によるゲームの実行
•
サーバの起動– Windows
の場合: StartServer.bat
をダブルクリック– Mac/Linux
の場合: StartSerber.sh
をダブルクリックサーバの設定
• Num of players
を5
に設定• Connect
をクリックしてサーバを起動クライアントの接続 (1/3)
•
クライアント接続用プログラム– Windows
の場合:StartGuiClient.bat
を起動– Mac/Linux
の場合: StartGuiClient.sh
を起動クライアントの接続 (2/3)
•
先ほど作成したjar
とaiwolf-client.jar
をJarFiles
欄にドラッグアンドドロップクライアントの接続 (3/3)
• Jar
ファイル,接続するプレイヤークラスを選択• Connect Agent
を選択• Role
欄で役職をリクエストすることもできるゲームの実行
•
自分のエージェント1
体とSampleRoleAssignPlayer
を4
体Connect
• Server Starter
でStart Game
をクリック5体のエージェントが接続されて いるのを確認(