├── .classpath ├── .gitignore ├── .project ├── LICENSE ├── README.md ├── lib ├── aiwolf-common-0.1.6.jar └── jsonic-1.3.2.jar └── src └── org └── aiwolf └── server ├── AIWolfGame.java ├── GameData.java ├── IllegalPlayerNumException.java ├── LostClientException.java ├── bin ├── DirectStarter.java ├── RoleRequestStarter.java └── ServerStarter.java ├── net ├── DirectConnectServer.java ├── GameServer.java ├── ServerListener.java └── TcpipServer.java └── util ├── FileGameLogger.java ├── GameLogger.java └── MultiGameLogger.java /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /jar 2 | /log 3 | /jsonic-1.3.2.zip 4 | /bin 5 | /build.xml 6 | /ServerStarterLog.txt 7 | /.classpath -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | AIWolfServer 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2014 aiwolf.org 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | AIWolfServer 2 | ============ 3 | 4 | Server Applications for aiwolf.org 5 | 6 | Latest update is 0.3.x 7 | -------------------------------------------------------------------------------- /lib/aiwolf-common-0.1.6.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aiwolf/AIWolfServer/5f67e27778ce56b53ecdabc619fbf930dfe96fac/lib/aiwolf-common-0.1.6.jar -------------------------------------------------------------------------------- /lib/jsonic-1.3.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aiwolf/AIWolfServer/5f67e27778ce56b53ecdabc619fbf930dfe96fac/lib/jsonic-1.3.2.jar -------------------------------------------------------------------------------- /src/org/aiwolf/server/AIWolfGame.java: -------------------------------------------------------------------------------- 1 | /** 2 | * AIWolfGame.java 3 | * 4 | * Copyright (c) 2014 人狼知能プロジェクト 5 | */ 6 | package org.aiwolf.server; 7 | 8 | import java.io.File; 9 | import java.io.IOException; 10 | import java.util.ArrayList; 11 | import java.util.Collections; 12 | import java.util.Comparator; 13 | import java.util.HashMap; 14 | import java.util.Iterator; 15 | import java.util.List; 16 | import java.util.Map; 17 | import java.util.Random; 18 | import java.util.TreeMap; 19 | import java.util.TreeSet; 20 | import java.util.regex.Matcher; 21 | import java.util.regex.Pattern; 22 | 23 | import org.aiwolf.client.lib.Content; 24 | import org.aiwolf.common.data.Agent; 25 | import org.aiwolf.common.data.Guard; 26 | import org.aiwolf.common.data.Judge; 27 | import org.aiwolf.common.data.Role; 28 | import org.aiwolf.common.data.Species; 29 | import org.aiwolf.common.data.Status; 30 | import org.aiwolf.common.data.Talk; 31 | import org.aiwolf.common.data.Team; 32 | import org.aiwolf.common.data.Vote; 33 | import org.aiwolf.common.net.GameSetting; 34 | import org.aiwolf.common.util.Counter; 35 | import org.aiwolf.server.net.GameServer; 36 | import org.aiwolf.server.util.FileGameLogger; 37 | import org.aiwolf.server.util.GameLogger; 38 | 39 | /** 40 | * Game Class of AI Wolf Contest 41 | * @author tori and otsuki 42 | * 43 | */ 44 | public class AIWolfGame { 45 | 46 | 47 | protected Random rand; 48 | 49 | /** 50 | * Settings of the game 51 | */ 52 | protected GameSetting gameSetting; 53 | 54 | /** 55 | * server to connect clients 56 | */ 57 | protected GameServer gameServer; 58 | 59 | /** 60 | * 61 | */ 62 | protected Map gameDataMap; 63 | 64 | /** 65 | * 66 | */ 67 | protected GameData gameData; 68 | 69 | /** 70 | * Show console log? 71 | */ 72 | protected boolean isShowConsoleLog = true; 73 | 74 | 75 | /** 76 | * ログを記録するファイル 77 | */ 78 | // protected File logFile; 79 | 80 | /** 81 | * Logger 82 | */ 83 | protected GameLogger gameLogger; 84 | 85 | /** 86 | * Name of Agents 87 | */ 88 | protected Map agentNameMap; 89 | 90 | /** 91 | * 92 | */ 93 | public AIWolfGame(GameSetting gameSetting, GameServer gameServer) { 94 | rand = new Random(); 95 | this.gameSetting = gameSetting; 96 | this.gameServer = gameServer; 97 | 98 | // gameLogger = AiWolfLoggerFactory.getSimpleLogger(this.getClass().getSimpleName()); 99 | } 100 | 101 | 102 | /** 103 | * @return logFile 104 | */ 105 | // public File getLogFile() { 106 | // return logFile; 107 | // } 108 | 109 | 110 | /** 111 | * @param logFile セットする logFile 112 | * @throws IOException 113 | */ 114 | public void setLogFile(File logFile) throws IOException { 115 | // this.logFile = logFile; 116 | gameLogger = new FileGameLogger(logFile); 117 | } 118 | 119 | /** 120 | * set GameLogger 121 | * @param gameLogger 122 | */ 123 | public void setGameLogger(GameLogger gameLogger){ 124 | this.gameLogger = gameLogger; 125 | } 126 | 127 | /** 128 | * get GameLogger 129 | */ 130 | public GameLogger getGameLogger(){ 131 | return this.gameLogger; 132 | } 133 | 134 | 135 | /** 136 | * Set Random Class 137 | * @param rand 138 | */ 139 | public void setRand(Random rand) { 140 | this.rand = rand; 141 | } 142 | 143 | /** 144 | * Initialize Game 145 | */ 146 | protected void init(){ 147 | gameDataMap = new TreeMap(); 148 | gameData = new GameData(gameSetting); 149 | agentNameMap = new HashMap(); 150 | gameServer.setGameData(gameData); 151 | 152 | List agentList = gameServer.getConnectedAgentList(); 153 | 154 | if(agentList.size() != gameSetting.getPlayerNum()){ 155 | throw new IllegalPlayerNumException("Player num is "+gameSetting.getPlayerNum()+" but connected agent is "+agentList.size()); 156 | } 157 | 158 | Collections.shuffle(agentList, rand); 159 | 160 | Map> requestRoleMap = new HashMap>(); 161 | for(Role role:Role.values()){ 162 | requestRoleMap.put(role, new ArrayList()); 163 | } 164 | List noRequestAgentList = new ArrayList(); 165 | for(Agent agent:agentList){ 166 | if(gameSetting.isEnableRoleRequest()) { 167 | Role requestedRole = gameServer.requestRequestRole(agent); 168 | if(requestedRole != null){ 169 | if(requestRoleMap.get(requestedRole).size() < gameSetting.getRoleNum(requestedRole)){ 170 | requestRoleMap.get(requestedRole).add(agent); 171 | } 172 | else{ 173 | noRequestAgentList.add(agent); 174 | } 175 | // System.out.println(agent+" request "+requestedRole); 176 | } 177 | else{ 178 | noRequestAgentList.add(agent); 179 | // System.out.println(agent+" request no role"); 180 | } 181 | } 182 | else { 183 | noRequestAgentList.add(agent); 184 | } 185 | } 186 | 187 | 188 | for(Role role:Role.values()){ 189 | List requestedAgentList = requestRoleMap.get(role); 190 | for(int i = 0; i < gameSetting.getRoleNum(role); i++){ 191 | if(requestedAgentList.isEmpty()){ 192 | gameData.addAgent(noRequestAgentList.remove(0), Status.ALIVE, role); 193 | } 194 | else{ 195 | gameData.addAgent(requestedAgentList.remove(0), Status.ALIVE, role); 196 | } 197 | } 198 | } 199 | 200 | gameDataMap.put(gameData.getDay(), gameData); 201 | 202 | gameServer.setGameSetting(gameSetting); 203 | for(Agent agent:agentList){ 204 | gameServer.init(agent); 205 | String requestName = gameServer.requestName(agent); 206 | agentNameMap.put(agent, requestName); 207 | // System.out.println(requestName); 208 | } 209 | } 210 | 211 | 212 | /** 213 | * Start game 214 | */ 215 | public void start(){ 216 | try{ 217 | init(); 218 | 219 | // System.out.printf("%d-%d\n", getAliveHumanList().size(), getAliveWolfList().size()); 220 | while(!isGameFinished()){ 221 | consoleLog(); 222 | 223 | day(); 224 | night(); 225 | if(gameLogger != null){ 226 | gameLogger.flush(); 227 | } 228 | } 229 | consoleLog(); 230 | finish(); 231 | 232 | if(isShowConsoleLog){ 233 | System.out.println("Winner:"+getWinner()); 234 | } 235 | // for(Agent agent:gameData.getAgentList()){ 236 | // GameInfo gameInfo = gameData.getGameInfo(agent); 237 | //// System.out.println(JSON.encode(gameInfo)); 238 | // break; 239 | // } 240 | }catch(LostClientException e){ 241 | if(gameLogger != null){ 242 | gameLogger.log("Lost Connection of "+e.getAgent()); 243 | } 244 | throw e; 245 | } 246 | } 247 | 248 | public void finish(){ 249 | if(gameLogger != null){ 250 | for(Agent agent:new TreeSet(gameData.getAgentList())){ 251 | gameLogger.log(String.format("%d,status,%d,%s,%s,%s", gameData.getDay(), agent.getAgentIdx(),gameData.getRole(agent), gameData.getStatus(agent), agentNameMap.get(agent))); 252 | } 253 | gameLogger.log(String.format("%d,result,%d,%d,%s", gameData.getDay(), getAliveHumanList().size(), getAliveWolfList().size(), getWinner())); 254 | gameLogger.close(); 255 | } 256 | 257 | for(Agent agent:gameData.getAgentList()){ 258 | // System.out.println("Send finish to "+agent); 259 | gameServer.finish(agent); 260 | } 261 | /* try { 262 | Thread.sleep(1000); 263 | } catch (InterruptedException e) { 264 | e.printStackTrace(); 265 | }*/ 266 | } 267 | 268 | /** 269 | * Get won team. 270 | * if game not finished, return null 271 | * @return 272 | */ 273 | public Team getWinner(){ 274 | int humanSide = 0; 275 | int wolfSide = 0; 276 | int otherSide = 0; 277 | for(Agent agent:gameData.getAgentList()){ 278 | if(gameData.getStatus(agent) == Status.DEAD){ 279 | continue; 280 | } 281 | 282 | 283 | if(gameData.getRole(agent).getTeam() == Team.OTHERS){ 284 | otherSide++; 285 | } 286 | if(gameData.getRole(agent).getSpecies() == Species.HUMAN){ 287 | humanSide++; 288 | } 289 | else{ 290 | wolfSide++; 291 | } 292 | } 293 | if(wolfSide == 0){ 294 | if(otherSide > 0){ 295 | return Team.OTHERS; 296 | } 297 | return Team.VILLAGER; 298 | } 299 | else if(humanSide <= wolfSide){ 300 | if(otherSide > 0){ 301 | return Team.OTHERS; 302 | } 303 | return Team.WEREWOLF; 304 | } 305 | else{ 306 | return null; 307 | } 308 | 309 | } 310 | 311 | private void consoleLog() { 312 | 313 | if(!isShowConsoleLog){ 314 | return; 315 | } 316 | 317 | GameData yesterday = gameData.getDayBefore(); 318 | 319 | System.out.println("============================================="); 320 | if(yesterday != null){ 321 | System.out.printf("Day %02d\n", yesterday.getDay()); 322 | System.out.println("========talk========"); 323 | for(Talk talk:yesterday.getTalkList()){ 324 | System.out.println(talk); 325 | } 326 | System.out.println("========Whisper========"); 327 | for(Talk whisper:yesterday.getWhisperList()){ 328 | System.out.println(whisper); 329 | } 330 | 331 | System.out.println("========Actions========"); 332 | for(Vote vote:yesterday.getVoteList()){ 333 | System.out.printf("Vote:%s->%s\n", vote.getAgent(), vote.getTarget()); 334 | } 335 | 336 | // System.out.println("Attack Vote Result"); 337 | for(Vote vote:yesterday.getAttackVoteList()){ 338 | System.out.printf("AttackVote:%s->%s\n", vote.getAgent(), vote.getTarget()); 339 | } 340 | 341 | Judge divine = yesterday.getDivine(); 342 | System.out.printf("%s executed\n", yesterday.getExecuted()); 343 | if(divine != null){ 344 | System.out.printf("%s divine %s. Result is %s\n", divine.getAgent(), divine.getTarget(), divine.getResult()); 345 | } 346 | Guard guard = yesterday.getGuard(); 347 | if(guard != null){ 348 | System.out.printf("%s guarded\n", guard); 349 | } 350 | 351 | if (yesterday.getAttackedDead() != null) { 352 | System.out.printf("%s attacked\n", yesterday.getAttackedDead()); 353 | } 354 | 355 | if (yesterday.getCursedFox() != null) { 356 | System.out.printf("%s cursed\n", yesterday.getCursedFox()); 357 | } 358 | } 359 | System.out.println("======"); 360 | List agentList = gameData.getAgentList(); 361 | Collections.sort(agentList, new Comparator() { 362 | @Override 363 | public int compare(Agent o1, Agent o2) { 364 | return o1.getAgentIdx()-o2.getAgentIdx(); 365 | } 366 | }); 367 | for(Agent agent:agentList){ 368 | System.out.printf("%s\t%s\t%s\t%s", agent, agentNameMap.get(agent), gameData.getStatus(agent), gameData.getRole(agent)); 369 | if(yesterday != null){ 370 | if (yesterday.getExecuted() == agent) { 371 | System.out.print("\texecuted"); 372 | } 373 | 374 | if (agent == yesterday.getAttackedDead()) { 375 | System.out.print("\tattacked"); 376 | } 377 | 378 | Judge divine = yesterday.getDivine(); 379 | if(divine != null && divine.getTarget() == agent){ 380 | System.out.print("\tdivined"); 381 | } 382 | Guard guard = yesterday.getGuard(); 383 | if(guard != null && guard.getTarget() == agent){ 384 | System.out.print("\tguarded"); 385 | } 386 | 387 | if (agent == yesterday.getCursedFox()) { 388 | System.out.print("\tcursed"); 389 | } 390 | } 391 | System.out.println(); 392 | } 393 | System.out.printf("Human:%d\nWerewolf:%d\n", getAliveHumanList().size(), getAliveWolfList().size()); 394 | if (gameSetting.getRoleNum(Role.FOX) != 0) { 395 | System.out.printf("Others:%d\n", gameData.getFilteredAgentList(getAliveAgentList(), Team.OTHERS).size()); 396 | } 397 | 398 | System.out.println("============================================="); 399 | } 400 | 401 | 402 | protected void day() { 403 | dayStart(); 404 | if (gameData.getDay() == 0) { 405 | if (gameSetting.isTalkOnFirstDay()) { 406 | whisper(); 407 | talk(); 408 | } 409 | } 410 | else { 411 | talk(); 412 | } 413 | } 414 | 415 | /** 416 | * 417 | */ 418 | protected void night() { 419 | 420 | // for (Agent agent : getAliveAgentList()) { 421 | // gameServer.dayFinish(agent); 422 | // } 423 | for (Agent agent : getGameData().getAgentList()) { 424 | gameServer.dayFinish(agent); 425 | } 426 | 427 | if(!gameSetting.isTalkOnFirstDay() && gameData.getDay() == 0){ 428 | whisper(); 429 | } 430 | 431 | // Vote and execute except day 0 432 | Agent executed = null; 433 | List candidates = null; 434 | if (gameData.getDay() != 0) { 435 | for (int i = 0; i <= gameSetting.getMaxRevote(); i++) { 436 | vote(); 437 | candidates = getVotedCandidates(gameData.getVoteList()); 438 | if (candidates.size() == 1) { 439 | executed = candidates.get(0); 440 | break; 441 | } 442 | } 443 | 444 | if (executed == null && !gameSetting.isEnableNoExecution()) { 445 | Collections.shuffle(candidates, rand); 446 | executed = candidates.get(0); 447 | } 448 | 449 | if (executed != null) { 450 | gameData.setExecutedTarget(executed); 451 | if (gameLogger != null) { 452 | gameLogger.log(String.format("%d,execute,%d,%s", gameData.getDay(), executed.getAgentIdx(), gameData.getRole(executed))); 453 | } 454 | } 455 | } 456 | 457 | // every day 458 | divine(); 459 | 460 | if (gameData.getDay() != 0) { 461 | whisper(); 462 | guard(); 463 | 464 | // attackVote and attack except day 0 465 | Agent attacked = null; 466 | if (getAliveWolfList().size() > 0) { 467 | for (int i = 0; i <= gameSetting.getMaxAttackRevote(); i++) { 468 | if(i > 0 && gameSetting.isWhisperBeforeRevote()){ 469 | whisper(); 470 | } 471 | attackVote(); 472 | List attackCandidateList = gameData.getAttackVoteList(); 473 | Iterator it = attackCandidateList.iterator(); 474 | while (it.hasNext()) { 475 | Vote vote = it.next(); 476 | if (vote.getAgent() == executed) { 477 | it.remove(); 478 | } 479 | } 480 | candidates = getAttackVotedCandidates(attackCandidateList); 481 | if (candidates.size() == 1) { 482 | attacked = candidates.get(0); 483 | break; 484 | } 485 | } 486 | 487 | if (attacked == null && !gameSetting.isEnableNoAttack()) { 488 | Collections.shuffle(candidates, rand); 489 | attacked = candidates.get(0); 490 | } 491 | 492 | gameData.setAttackedTarget(attacked); 493 | 494 | boolean isGuarded = false; 495 | if (gameData.getGuard() != null) { 496 | if (gameData.getGuard().getTarget() == attacked && attacked != null) { 497 | if (gameData.getExecuted() == null || !(gameData.getExecuted() == gameData.getGuard().getAgent())) { 498 | isGuarded = true; 499 | } 500 | } 501 | } 502 | if (!isGuarded && attacked != null && gameData.getRole(attacked) != Role.FOX) { 503 | gameData.setAttackedDead(attacked); 504 | gameData.addLastDeadAgent(attacked); 505 | 506 | if (gameLogger != null) { 507 | gameLogger.log(String.format("%d,attack,%d,true", gameData.getDay(), attacked.getAgentIdx())); 508 | } 509 | } else if (attacked != null) { 510 | if (gameLogger != null) { 511 | gameLogger.log(String.format("%d,attack,%d,false", gameData.getDay(), attacked.getAgentIdx())); 512 | } 513 | } else { 514 | if (gameLogger != null) { 515 | gameLogger.log(String.format("%d,attack,-1,false", gameData.getDay())); 516 | } 517 | } 518 | } 519 | } 520 | 521 | gameData = gameData.nextDay(); 522 | gameDataMap.put(gameData.getDay(), gameData); 523 | gameServer.setGameData(gameData); 524 | 525 | } 526 | 527 | 528 | /** 529 | * 530 | * @param voteList 531 | * @return 532 | */ 533 | protected List getVotedCandidates(List voteList) { 534 | Counter counter = new Counter(); 535 | for(Vote vote:voteList){ 536 | if(gameData.getStatus(vote.getTarget()) == Status.ALIVE){ 537 | counter.add(vote.getTarget()); 538 | } 539 | } 540 | 541 | int max = counter.get(counter.getLargest()); 542 | List candidateList = new ArrayList(); 543 | for(Agent agent:counter){ 544 | if(counter.get(agent) == max){ 545 | candidateList.add(agent); 546 | } 547 | } 548 | return candidateList; 549 | } 550 | 551 | /** 552 | * 553 | * @param voteList 554 | * @return 555 | */ 556 | protected List getAttackVotedCandidates(List voteList) { 557 | Counter counter = new Counter(); 558 | for (Vote vote : voteList) { 559 | if (gameData.getStatus(vote.getTarget()) == Status.ALIVE 560 | && gameData.getRole(vote.getTarget()) != Role.WEREWOLF) { 561 | counter.add(vote.getTarget()); 562 | } 563 | } 564 | if (!gameSetting.isEnableNoAttack()) { 565 | for (Agent agent : getAliveHumanList()) { 566 | counter.add(agent); 567 | } 568 | } 569 | 570 | int max = counter.get(counter.getLargest()); 571 | List candidateList = new ArrayList(); 572 | for (Agent agent : counter) { 573 | if (counter.get(agent) == max) { 574 | candidateList.add(agent); 575 | } 576 | } 577 | return candidateList; 578 | } 579 | 580 | /** 581 | * 582 | */ 583 | protected void dayStart(){ 584 | if(gameLogger != null){ 585 | for(Agent agent:new TreeSet(gameData.getAgentList())){ 586 | gameLogger.log(String.format("%d,status,%d,%s,%s,%s", gameData.getDay(), agent.getAgentIdx(),gameData.getRole(agent), gameData.getStatus(agent), agentNameMap.get(agent))); 587 | } 588 | } 589 | 590 | for (Agent agent : gameData.getAgentList()) { 591 | gameServer.dayStart(agent); 592 | } 593 | 594 | } 595 | 596 | /** 597 | * 598 | */ 599 | protected void talk() { 600 | 601 | List aliveList = getAliveAgentList(); 602 | for(Agent agent:aliveList){ 603 | gameData.remainTalkMap.put(agent, gameSetting.getMaxTalk()); 604 | } 605 | 606 | Counter skipCounter = new Counter<>(); 607 | for(int time = 0; time < gameSetting.getMaxTalkTurn(); time++){ 608 | Collections.shuffle(aliveList); 609 | 610 | boolean continueTalk = false; 611 | for(Agent agent:aliveList){ 612 | String talkText = Talk.OVER; 613 | if(gameData.getRemainTalkMap().get(agent) > 0){ 614 | talkText = gameServer.requestTalk(agent); 615 | } 616 | if(talkText == null || talkText.isEmpty()){ 617 | talkText = Talk.SKIP; 618 | } 619 | if (gameSetting.isValidateUtterance()) { 620 | if (!Content.validate(talkText)) { 621 | talkText = Talk.SKIP; 622 | } 623 | } 624 | if (talkText.equals(Talk.SKIP)) { 625 | skipCounter.add(agent); 626 | if(skipCounter.get(agent) > gameSetting.getMaxSkip()){ 627 | talkText = Talk.OVER; 628 | } 629 | } 630 | Talk talk = new Talk(gameData.nextTalkIdx(), gameData.getDay(), time, agent, talkText); 631 | gameData.addTalk(talk.getAgent(), talk); 632 | if(gameLogger != null){ 633 | gameLogger.log(String.format("%d,talk,%d,%d,%d,%s", gameData.getDay(), talk.getIdx(), talk.getTurn(), talk.getAgent().getAgentIdx(), talk.getText())); 634 | } 635 | 636 | if(!talk.isOver() && !talk.isSkip()){ 637 | skipCounter.put(agent, 0); 638 | } 639 | if(!talk.isOver()){ 640 | continueTalk = true; 641 | } 642 | } 643 | 644 | if(!continueTalk){ 645 | break; 646 | } 647 | 648 | } 649 | } 650 | 651 | protected void whisper() { 652 | List aliveWolfList = gameData.getFilteredAgentList(getAliveAgentList(), Role.WEREWOLF); 653 | // No whisper in case of lonely wolf. 654 | if(aliveWolfList.size() == 1){ 655 | return; 656 | } 657 | for(Agent agent:aliveWolfList){ 658 | gameData.remainWhisperMap.put(agent, gameSetting.getMaxWhisper()); 659 | } 660 | 661 | Counter skipCounter = new Counter<>(); 662 | for (int turn = 0; turn < gameSetting.getMaxWhisperTurn(); turn++) { 663 | Collections.shuffle(aliveWolfList); 664 | 665 | boolean continueWhisper = false; 666 | for(Agent agent:aliveWolfList){ 667 | String whisperText = Talk.OVER; 668 | if(gameData.getRemainWhisperMap().get(agent) > 0){ 669 | whisperText = gameServer.requestWhisper(agent); 670 | } 671 | if(whisperText == null || whisperText.isEmpty()){ 672 | whisperText = Talk.SKIP; 673 | } 674 | if (gameSetting.isValidateUtterance()) { 675 | if (!Content.validate(whisperText)) { 676 | whisperText = Talk.SKIP; 677 | } 678 | } 679 | if (whisperText.equals(Talk.SKIP)) { 680 | skipCounter.add(agent); 681 | if(skipCounter.get(agent) > gameSetting.getMaxSkip()){ 682 | whisperText = Talk.OVER; 683 | } 684 | } 685 | Talk whisper = new Talk(gameData.nextWhisperIdx(), gameData.getDay(), turn, agent, whisperText); 686 | gameData.addWhisper(whisper.getAgent(), whisper); 687 | if(gameLogger != null){ 688 | gameLogger.log(String.format("%d,whisper,%d,%d,%d,%s", gameData.getDay(), whisper.getIdx(), whisper.getTurn(), whisper.getAgent().getAgentIdx(), whisper.getText())); 689 | } 690 | 691 | if(!whisper.isOver() && !whisper.isSkip()){ 692 | skipCounter.put(agent, 0); 693 | } 694 | if(!whisper.isOver()){ 695 | continueWhisper = true; 696 | } 697 | } 698 | 699 | if(!continueWhisper){ 700 | break; 701 | } 702 | } 703 | } 704 | 705 | /** 706 | *
投票
707 | * 708 | *
Vote
709 | * 710 | */ 711 | protected void vote() { 712 | gameData.getVoteList().clear(); 713 | List voters = getAliveAgentList(); 714 | List aliveCandidates = voters; 715 | List latestVoteList = new ArrayList<>(); 716 | for (Agent agent : voters) { 717 | Agent target = gameServer.requestVote(agent); 718 | if (target == null || gameData.getStatus(target) == null || gameData.getStatus(target) == Status.DEAD || agent == target) { 719 | target = getRandomAgent(aliveCandidates, agent); 720 | } 721 | Vote vote = new Vote(gameData.getDay(), agent, target); 722 | gameData.addVote(vote); 723 | latestVoteList.add(vote); 724 | } 725 | gameData.setLatestVoteList(latestVoteList); 726 | 727 | for (Vote vote : latestVoteList) { 728 | if (gameLogger != null) { 729 | gameLogger.log(String.format("%d,vote,%d,%d", gameData.getDay(), vote.getAgent().getAgentIdx(), vote.getTarget().getAgentIdx())); 730 | } 731 | } 732 | } 733 | 734 | /** 735 | * 736 | */ 737 | protected void divine() { 738 | List agentList = getAliveAgentList(); 739 | for(Agent agent:getAliveAgentList()){ 740 | if(gameData.getRole(agent) == Role.SEER){ 741 | Agent target = gameServer.requestDivineTarget(agent); 742 | Role targetRole = gameData.getRole(target); 743 | if(gameData.getStatus(target) == Status.DEAD || target == null || targetRole == null){ 744 | // target = getRandomAgent(agentList, agent); 745 | } 746 | else{ 747 | Judge divine = new Judge(gameData.getDay(), agent, target, targetRole.getSpecies()); 748 | gameData.addDivine(divine); 749 | 750 | //FOX 751 | if(gameData.getRole(target) == Role.FOX){ 752 | gameData.addLastDeadAgent(target); 753 | gameData.setCursedFox(target); 754 | } 755 | 756 | if(gameLogger != null){ 757 | gameLogger.log(String.format("%d,divine,%d,%d,%s", gameData.getDay(), divine.getAgent().getAgentIdx(), divine.getTarget().getAgentIdx(), divine.getResult())); 758 | } 759 | } 760 | } 761 | } 762 | } 763 | 764 | /** 765 | * 766 | */ 767 | protected void guard() { 768 | List agentList = getAliveAgentList(); 769 | for(Agent agent:getAliveAgentList()){ 770 | if(gameData.getRole(agent) == Role.BODYGUARD){ 771 | if (agent == gameData.getExecuted()) { 772 | continue; 773 | } 774 | Agent target = gameServer.requestGuardTarget(agent); 775 | if (target == null || gameData.getStatus(target) == null || agent == target) { 776 | // target = getRandomAgent(agentList, agent); 777 | } 778 | else{ 779 | Guard guard = new Guard(gameData.getDay(), agent, target); 780 | gameData.addGuard(guard); 781 | 782 | if(gameLogger != null){ 783 | gameLogger.log(String.format("%d,guard,%d,%d,%s", gameData.getDay(), guard.getAgent().getAgentIdx(), guard.getTarget().getAgentIdx(), gameData.getRole(guard.getTarget()))); 784 | } 785 | } 786 | } 787 | } 788 | } 789 | 790 | protected void attackVote() { 791 | gameData.getAttackVoteList().clear(); 792 | List voters = getAliveWolfList(); 793 | List candidates = getAliveHumanList(); 794 | for (Agent agent : voters) { 795 | Agent target = gameServer.requestAttackTarget(agent); 796 | if (target == null || gameData.getStatus(target) == null || gameData.getStatus(target) == Status.DEAD || gameData.getRole(target) == Role.WEREWOLF) { 797 | // target = getRandomAgent(candidateList, agent); 798 | } 799 | else { 800 | Vote attackVote = new Vote(gameData.getDay(), agent, target); 801 | gameData.addAttack(attackVote); 802 | 803 | if (gameLogger != null) { 804 | gameLogger.log(String.format("%d,attackVote,%d,%d", gameData.getDay(), 805 | attackVote.getAgent().getAgentIdx(), attackVote.getTarget().getAgentIdx())); 806 | } 807 | } 808 | } 809 | List latestAttackVoteList = new ArrayList<>(); 810 | for (Vote v : gameData.getAttackVoteList()) { 811 | latestAttackVoteList.add(v); 812 | } 813 | gameData.setLatestAttackVoteList(latestAttackVoteList); 814 | 815 | } 816 | 817 | /** 818 | * ランダムなエージェントを獲得する.ただし,withoutを除く. 819 | * @param agentList 820 | * @param without 821 | * @return 822 | */ 823 | protected Agent getRandomAgent(List agentList, Agent... without) { 824 | Agent target; 825 | List list = new ArrayList(agentList); 826 | for(Agent agent:without){ 827 | list.remove(agent); 828 | } 829 | target = list.get(rand.nextInt(list.size())); 830 | return target; 831 | } 832 | 833 | /** 834 | * get alive agents 835 | * @return 836 | */ 837 | protected List getAliveAgentList(){ 838 | List agentList = new ArrayList(); 839 | for(Agent agent:gameData.getAgentList()){ 840 | if(gameData.getStatus(agent) == Status.ALIVE){ 841 | agentList.add(agent); 842 | } 843 | } 844 | return agentList; 845 | } 846 | 847 | protected List getAliveHumanList(){ 848 | return gameData.getFilteredAgentList(getAliveAgentList(), Species.HUMAN); 849 | } 850 | 851 | protected List getAliveWolfList(){ 852 | return gameData.getFilteredAgentList(getAliveAgentList(), Species.WEREWOLF); 853 | } 854 | 855 | 856 | 857 | /** 858 | * return is game finished 859 | * @return 860 | */ 861 | public boolean isGameFinished() { 862 | Team winner = getWinner(); 863 | return winner != null; 864 | } 865 | 866 | /** 867 | * get all data of the game 868 | * @return 869 | */ 870 | public GameData getGameData() { 871 | return gameData; 872 | } 873 | 874 | /** 875 | * get setting of the game 876 | * @return 877 | */ 878 | public GameSetting getGameSetting(){ 879 | return gameSetting; 880 | } 881 | 882 | 883 | /** 884 | * @return isShowConsoleLog 885 | */ 886 | public boolean isShowConsoleLog() { 887 | return isShowConsoleLog; 888 | } 889 | 890 | 891 | /** 892 | * @param isShowConsoleLog isShowConsoleLog 893 | */ 894 | public void setShowConsoleLog(boolean isShowConsoleLog) { 895 | this.isShowConsoleLog = isShowConsoleLog; 896 | } 897 | 898 | /** 899 | * 900 | * @param agent 901 | * @return 902 | */ 903 | public String getAgentName(Agent agent){ 904 | return agentNameMap.get(agent); 905 | } 906 | 907 | } 908 | -------------------------------------------------------------------------------- /src/org/aiwolf/server/GameData.java: -------------------------------------------------------------------------------- 1 | package org.aiwolf.server; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.HashSet; 6 | import java.util.LinkedHashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | import java.util.Set; 10 | import java.util.TreeSet; 11 | 12 | import org.aiwolf.common.AIWolfRuntimeException; 13 | import org.aiwolf.common.data.Agent; 14 | import org.aiwolf.common.data.Guard; 15 | import org.aiwolf.common.data.Judge; 16 | import org.aiwolf.common.data.Role; 17 | import org.aiwolf.common.data.Species; 18 | import org.aiwolf.common.data.Status; 19 | import org.aiwolf.common.data.Talk; 20 | import org.aiwolf.common.data.Team; 21 | import org.aiwolf.common.data.Vote; 22 | import org.aiwolf.common.net.GameInfo; 23 | import org.aiwolf.common.net.GameInfoToSend; 24 | import org.aiwolf.common.net.GameSetting; 25 | import org.aiwolf.common.net.JudgeToSend; 26 | import org.aiwolf.common.net.TalkToSend; 27 | import org.aiwolf.common.net.VoteToSend; 28 | 29 | /** 30 | * Record game information of a day 31 | * @author tori 32 | * 33 | */ 34 | public class GameData { 35 | static final int firstDay = 1; 36 | 37 | /** 38 | * The day of the data 39 | */ 40 | protected int day; 41 | 42 | /** 43 | * status of each agents 44 | */ 45 | protected Map agentStatusMap; 46 | 47 | /** 48 | * roles of each agents 49 | */ 50 | protected Map agentRoleMap; 51 | 52 | /** 53 | * 54 | */ 55 | protected List talkList; 56 | 57 | /** 58 | * 59 | */ 60 | protected List whisperList; 61 | 62 | /** 63 | * 64 | */ 65 | protected List voteList; 66 | 67 | /** 68 | *
直近の投票リスト
69 | * 70 | *
The latest list of votes.
71 | */ 72 | protected List latestVoteList; 73 | 74 | /** 75 | * 76 | */ 77 | protected List attackVoteList; 78 | 79 | /** 80 | *
直近の襲撃投票リスト
81 | * 82 | *
The latest list of votes for attack.
83 | */ 84 | protected List latestAttackVoteList; 85 | 86 | /** 87 | * 88 | */ 89 | protected Map remainTalkMap; 90 | 91 | /** 92 | * 93 | */ 94 | protected Map remainWhisperMap; 95 | 96 | /** 97 | * Result of divination 98 | */ 99 | protected Judge divine; 100 | 101 | /** 102 | * Guard 103 | */ 104 | protected Guard guard; 105 | 106 | /** 107 | * executed agent 108 | */ 109 | protected Agent executed; 110 | 111 | /** 112 | *
昨夜人狼に襲われ死亡したエージェント
113 | * 114 | *
the agent who died last night because of the attack by werewolf.
115 | */ 116 | protected Agent attackedDead; 117 | 118 | /** 119 | *
昨夜人狼が襲ったエージェント(成否は問わない)
120 | * 121 | *
the agent werewolves attacked last night (no matter whether or not the attack succeeded)
122 | */ 123 | protected Agent attacked; 124 | 125 | /** 126 | *
呪殺された妖狐
127 | * 128 | *
the fox killed by curse
129 | */ 130 | protected Agent cursedFox; 131 | 132 | /** 133 | *
昨夜死亡したエージェントのリスト
134 | * 135 | *
the list of agents who died last night
136 | */ 137 | protected List lastDeadAgentList; 138 | 139 | /** 140 | * agents who sudden death 141 | */ 142 | protected List suddendeathList; 143 | 144 | /** 145 | * game data of one day before 146 | */ 147 | protected GameData dayBefore; 148 | 149 | protected int talkIdx; 150 | 151 | protected int wisperIdx; 152 | 153 | 154 | /** 155 | * ゲームの設定 156 | */ 157 | protected GameSetting gameSetting; 158 | 159 | public GameData(GameSetting gameSetting){ 160 | agentStatusMap = new LinkedHashMap<>(); 161 | agentRoleMap = new HashMap<>(); 162 | remainTalkMap = new HashMap<>(); 163 | remainWhisperMap = new HashMap<>(); 164 | talkList = new ArrayList<>(); 165 | whisperList = new ArrayList<>(); 166 | voteList = new ArrayList<>(); 167 | latestVoteList = new ArrayList<>(); 168 | attackVoteList = new ArrayList<>(); 169 | latestAttackVoteList = new ArrayList<>(); 170 | lastDeadAgentList = new ArrayList<>(); 171 | suddendeathList = new ArrayList<>(); 172 | 173 | this.gameSetting = gameSetting; 174 | } 175 | 176 | /** 177 | * get specific game information 178 | * @param agent 179 | * @return 180 | */ 181 | public GameInfo getGameInfo(Agent agent){ 182 | return getGameInfoToSend(agent).toGameInfo(); 183 | } 184 | 185 | /** 186 | * get final game information 187 | * @param agent 188 | * @return 189 | */ 190 | public GameInfo getFinalGameInfo(Agent agent){ 191 | return getFinalGameInfoToSend(agent).toGameInfo(); 192 | } 193 | 194 | /** 195 | * get game info with all information 196 | * @return 197 | */ 198 | public GameInfo getGameInfo(){ 199 | return getFinalGameInfo(null); 200 | } 201 | 202 | 203 | /** 204 | * 205 | * @param agent 206 | * - if null, get all information 207 | * @return 208 | */ 209 | public GameInfoToSend getGameInfoToSend(Agent agent){ 210 | GameData today = this; 211 | GameInfoToSend gi = new GameInfoToSend(); 212 | 213 | int day = today.getDay(); 214 | if(agent != null){ 215 | gi.setAgent(agent.getAgentIdx()); 216 | } 217 | if (gameSetting.isVoteVisible()) { 218 | List latestVoteList = new ArrayList<>(); 219 | for (Vote vote : getLatestVoteList()) { 220 | latestVoteList.add(new VoteToSend(vote)); 221 | } 222 | gi.setLatestVoteList(latestVoteList); 223 | } 224 | if (getExecuted() != null) { 225 | gi.setLatestExecutedAgent(getExecuted().getAgentIdx()); 226 | } 227 | if (agent == null || getRole(agent) == Role.WEREWOLF) { 228 | List latestAttackVoteList = new ArrayList<>(); 229 | for (Vote vote : getLatestAttackVoteList()) { 230 | latestAttackVoteList.add(new VoteToSend(vote)); 231 | } 232 | gi.setLatestAttackVoteList(latestAttackVoteList); 233 | } 234 | 235 | GameData yesterday = today.getDayBefore(); 236 | 237 | if (yesterday != null) { 238 | Agent executed = yesterday.getExecuted(); 239 | if(executed != null){ 240 | gi.setExecutedAgent(executed.getAgentIdx()); 241 | } 242 | 243 | ArrayList lastDeadAgentList = new ArrayList<>(); 244 | for (Agent a : yesterday.getLastDeadAgentList()) { 245 | lastDeadAgentList.add(new Integer(a.getAgentIdx())); 246 | } 247 | gi.setLastDeadAgentList(lastDeadAgentList); 248 | 249 | if(gameSetting.isVoteVisible()){ 250 | List voteList = new ArrayList<>(); 251 | for(Vote vote:yesterday.getVoteList()){ 252 | voteList.add(new VoteToSend(vote)); 253 | } 254 | gi.setVoteList(voteList); 255 | } 256 | 257 | if (agent != null && today.getRole(agent) == Role.MEDIUM && executed != null) { 258 | Species result = yesterday.getRole(executed).getSpecies(); 259 | gi.setMediumResult(new JudgeToSend(new Judge(day, agent, executed, result))); 260 | } 261 | 262 | if (agent == null || today.getRole(agent) == Role.SEER) { 263 | Judge divine = yesterday.getDivine(); 264 | if (divine != null && divine.getTarget() != null) { 265 | Species result = yesterday.getRole(divine.getTarget()).getSpecies(); 266 | gi.setDivineResult(new JudgeToSend(new Judge(day, divine.getAgent(), divine.getTarget(), result))); 267 | } 268 | } 269 | 270 | if (agent == null || today.getRole(agent) == Role.WEREWOLF) { 271 | Agent attacked = yesterday.getAttacked(); 272 | if (attacked != null) { 273 | gi.setAttackedAgent(attacked.getAgentIdx()); 274 | } 275 | 276 | List attackVoteList = new ArrayList(); 277 | for(Vote vote:yesterday.getAttackVoteList()){ 278 | attackVoteList.add(new VoteToSend(vote)); 279 | } 280 | gi.setAttackVoteList(attackVoteList); 281 | } 282 | if (agent == null || today.getRole(agent) == Role.BODYGUARD) { 283 | Guard guard = yesterday.getGuard(); 284 | if(guard != null){ 285 | gi.setGuardedAgent(guard.getTarget().getAgentIdx()); 286 | } 287 | } 288 | if (agent == null) { 289 | if (yesterday.cursedFox != null) { 290 | gi.setCursedFox(yesterday.cursedFox.getAgentIdx()); 291 | } 292 | } 293 | } 294 | List talkList = new ArrayList(); 295 | for(Talk talk:today.getTalkList()){ 296 | talkList.add(new TalkToSend(talk)); 297 | } 298 | gi.setTalkList(talkList); 299 | 300 | LinkedHashMap statusMap = new LinkedHashMap(); 301 | for(Agent a:agentStatusMap.keySet()){ 302 | statusMap.put(a.getAgentIdx(), agentStatusMap.get(a).toString()); 303 | } 304 | gi.setStatusMap(statusMap); 305 | 306 | LinkedHashMap roleMap = new LinkedHashMap(); 307 | Role role = agentRoleMap.get(agent); 308 | 309 | Set existingRoleSet = new TreeSet<>(); 310 | for(Role r:agentRoleMap.values()){ 311 | existingRoleSet.add(r.toString()); 312 | } 313 | gi.setExistingRoleList(new ArrayList<>(existingRoleSet)); 314 | 315 | LinkedHashMap remainTalkMap = new LinkedHashMap(); 316 | for(Agent a:this.remainTalkMap.keySet()){ 317 | remainTalkMap.put(a.getAgentIdx(), this.remainTalkMap.get(a)); 318 | } 319 | gi.setRemainTalkMap(remainTalkMap); 320 | 321 | LinkedHashMap remainWhisperMap = new LinkedHashMap(); 322 | if(role == Role.WEREWOLF){ 323 | for(Agent a:this.remainWhisperMap.keySet()){ 324 | remainWhisperMap.put(a.getAgentIdx(), this.remainWhisperMap.get(a)); 325 | } 326 | } 327 | gi.setRemainWhisperMap(remainWhisperMap); 328 | 329 | if (role == Role.WEREWOLF || agent == null) { 330 | List whisperList = new ArrayList<>(); 331 | for(Talk talk:today.getWhisperList()){ 332 | whisperList.add(new TalkToSend(talk)); 333 | } 334 | gi.setWhisperList(whisperList); 335 | } 336 | 337 | if(role != null){ 338 | roleMap.put(agent.getAgentIdx(), role.toString()); 339 | if (today.getRole(agent) == Role.WEREWOLF) { 340 | // List whisperList = new ArrayList(); 341 | // for(Talk talk:today.getWhisperList()){ 342 | // whisperList.add(new TalkToSend(talk)); 343 | // } 344 | // gi.setWhisperList(whisperList); 345 | 346 | for (Agent target : today.getAgentList()) { 347 | if (today.getRole(target) == Role.WEREWOLF) { 348 | // wolfList.add(target); 349 | roleMap.put(target.getAgentIdx(), Role.WEREWOLF.toString()); 350 | } 351 | } 352 | } 353 | if (today.getRole(agent) == Role.FREEMASON) { 354 | for (Agent target : today.getAgentList()) { 355 | if (today.getRole(target) == Role.FREEMASON) { 356 | roleMap.put(target.getAgentIdx(), Role.FREEMASON.toString()); 357 | } 358 | } 359 | } 360 | } 361 | gi.setRoleMap(roleMap); 362 | gi.setRemainTalkMap(remainTalkMap); 363 | gi.setDay(day); 364 | 365 | return gi; 366 | } 367 | 368 | public GameInfoToSend getFinalGameInfoToSend(Agent agent) { 369 | GameInfoToSend gi = getGameInfoToSend(agent); 370 | 371 | LinkedHashMap roleMap = new LinkedHashMap(); 372 | for(Agent a:agentRoleMap.keySet()){ 373 | roleMap.put(a.getAgentIdx(), agentRoleMap.get(a).toString()); 374 | } 375 | gi.setRoleMap(roleMap); 376 | 377 | return gi; 378 | } 379 | 380 | 381 | /** 382 | * Add new agent with their role 383 | * 384 | * @param agent 385 | * @param status 386 | * @param role 387 | */ 388 | public void addAgent(Agent agent, Status status, Role role){ 389 | agentRoleMap.put(agent, role); 390 | agentStatusMap.put(agent, status); 391 | remainTalkMap.put(agent, gameSetting.getMaxTalk()); 392 | if(getRole(agent) == Role.WEREWOLF){ 393 | remainWhisperMap.put(agent, gameSetting.getMaxWhisper()); 394 | } 395 | } 396 | 397 | /** 398 | * get agents 399 | * @return 400 | */ 401 | public List getAgentList() { 402 | return new ArrayList(agentRoleMap.keySet()); 403 | } 404 | 405 | /** 406 | * get status of agent 407 | * @param agent 408 | */ 409 | public Status getStatus(Agent agent) { 410 | return agentStatusMap.get(agent); 411 | } 412 | 413 | /** 414 | * 415 | * @param agent 416 | * @return 417 | */ 418 | public Role getRole(Agent agent) { 419 | return agentRoleMap.get(agent); 420 | } 421 | 422 | 423 | 424 | /** 425 | * 426 | * @param agent 427 | * @param talk 428 | */ 429 | public void addTalk(Agent agent, Talk talk) { 430 | int remainTalk = remainTalkMap.get(agent); 431 | if(!talk.isOver() && !talk.isSkip()){ 432 | if(remainTalk == 0){ 433 | throw new AIWolfRuntimeException("No remain talk but try to talk. #Contact to AIWolf Platform Developer"); 434 | } 435 | remainTalkMap.put(agent, remainTalk-1); 436 | } 437 | talkList.add(talk); 438 | } 439 | 440 | public void addWhisper(Agent agent, Talk whisper) { 441 | int remainWhisper = remainWhisperMap.get(agent); 442 | if(!whisper.isOver() && !whisper.isSkip()){ 443 | if(remainWhisper == 0){ 444 | throw new AIWolfRuntimeException("No remain whisper but try to whisper. #Contact to AIWolf Platform Developer"); 445 | } 446 | remainWhisperMap.put(agent, remainWhisper-1); 447 | } 448 | whisperList.add(whisper); 449 | } 450 | 451 | /** 452 | * Add vote data 453 | * 454 | * @param vote 455 | */ 456 | public void addVote(Vote vote) { 457 | voteList.add(vote); 458 | } 459 | 460 | /** 461 | * Add divine 462 | * 463 | * @param divine 464 | */ 465 | public void addDivine(Judge divine) { 466 | this.divine = divine; 467 | } 468 | 469 | public void addGuard(Guard guard) { 470 | this.guard = guard; 471 | } 472 | 473 | public void addAttack(Vote attack) { 474 | attackVoteList.add(attack); 475 | } 476 | 477 | public List getVoteList() { 478 | return voteList; 479 | } 480 | 481 | /** 482 | * set executed 483 | * 484 | * @param target 485 | */ 486 | public void setExecutedTarget(Agent executed) { 487 | this.executed = executed; 488 | if (executed != null) { 489 | agentStatusMap.put(executed, Status.DEAD); 490 | } 491 | } 492 | 493 | /** 494 | * 495 | * @param attacked 496 | */ 497 | public void setAttackedTarget(Agent attacked) { 498 | this.attacked = attacked; 499 | } 500 | 501 | /** 502 | * 503 | * @return 504 | */ 505 | public List getAttackVoteList() { 506 | return attackVoteList; 507 | } 508 | 509 | /** 510 | * 511 | * @return 512 | */ 513 | public Guard getGuard() { 514 | return guard; 515 | } 516 | 517 | /** 518 | * @return day 519 | */ 520 | public int getDay() { 521 | return day; 522 | } 523 | 524 | /** 525 | * @return talkList 526 | */ 527 | public List getTalkList() { 528 | return talkList; 529 | } 530 | 531 | /** 532 | * @return wisperList 533 | */ 534 | public List getWhisperList() { 535 | return whisperList; 536 | } 537 | 538 | /** 539 | * @return divine 540 | */ 541 | public Judge getDivine() { 542 | return divine; 543 | } 544 | 545 | /** 546 | * @return executed 547 | */ 548 | public Agent getExecuted() { 549 | return executed; 550 | } 551 | 552 | /** 553 | *
昨夜人狼が襲ったエージェント(成否は問わない)を返す
554 | * 555 | *
Returns the agent werewolves attacked last night (no 556 | * matter whether or not the attack succeeded).
557 | * 558 | * @return attackedAgent -
昨夜人狼が襲ったエージェント
559 | * 560 | *
the agent werewolves attacked last night
561 | */ 562 | public Agent getAttacked() { 563 | return attacked; 564 | } 565 | 566 | /** 567 | *
昨夜死亡したエージェントを追加する 568 | * 569 | *
Adds the agent who died last night.
570 | * 571 | * @param agent 572 | *
追加するエージェント
573 | * 574 | *
the agent to be added
575 | */ 576 | public void addLastDeadAgent(Agent agent) { 577 | if (!lastDeadAgentList.contains(agent)) { 578 | lastDeadAgentList.add(agent); 579 | } 580 | } 581 | 582 | /** 583 | * @return
昨夜死亡したエージェントのリスト
584 | * 585 | *
the list of agents who died last night
586 | */ 587 | public List getLastDeadAgentList() { 588 | return lastDeadAgentList; 589 | } 590 | 591 | /** 592 | * @return suddendeathList 593 | */ 594 | public List getSuddendeathList() { 595 | return suddendeathList; 596 | } 597 | 598 | /** 599 | * @return remainTalkMap 600 | */ 601 | public Map getRemainTalkMap() { 602 | return remainTalkMap; 603 | } 604 | 605 | /** 606 | * @return remainTalkMap 607 | */ 608 | public Map getRemainWhisperMap() { 609 | return remainWhisperMap; 610 | } 611 | 612 | /** 613 | * Create GameData of next day 614 | * @return 615 | */ 616 | public GameData nextDay(){ 617 | GameData gameData = new GameData(gameSetting); 618 | 619 | gameData.day = this.day+1; 620 | gameData.agentStatusMap = new HashMap(agentStatusMap); 621 | 622 | for (Agent a : lastDeadAgentList) { 623 | gameData.agentStatusMap.put(a, Status.DEAD); 624 | } 625 | gameData.agentRoleMap = new HashMap(agentRoleMap); 626 | 627 | for(Agent a:gameData.getAgentList()){ 628 | if(gameData.getStatus(a) == Status.ALIVE){ 629 | gameData.remainTalkMap.put(a, gameSetting.getMaxTalk()); 630 | if(gameData.getRole(a) == Role.WEREWOLF){ 631 | gameData.remainWhisperMap.put(a, gameSetting.getMaxWhisper()); 632 | } 633 | } 634 | } 635 | 636 | gameData.dayBefore = this; 637 | 638 | return gameData; 639 | } 640 | 641 | /** 642 | * get game data of one day before 643 | * @return 644 | */ 645 | public GameData getDayBefore() { 646 | return dayBefore; 647 | } 648 | 649 | // /** 650 | // * get wolf agents 651 | // * @return 652 | // */ 653 | // public List getWolfList(){ 654 | // List wolfList = new ArrayList<>(); 655 | // for(Agent agent:getAgentList()){ 656 | // if(getRole(agent).getSpecies() == Species.Werewolf){ 657 | // wolfList.add(agent); 658 | // } 659 | // } 660 | // return wolfList; 661 | // } 662 | // 663 | // /** 664 | // * get human agents 665 | // * @return 666 | // */ 667 | // public List getHumanList(){ 668 | // List humanList = new ArrayList<>(getAgentList()); 669 | // humanList.removeAll(getWolfList()); 670 | // return humanList; 671 | // } 672 | 673 | protected List getFilteredAgentList(List agentList, Species species){ 674 | List resultList = new ArrayList(); 675 | for(Agent agent:agentList){ 676 | if(getRole(agent).getSpecies() == species){ 677 | resultList.add(agent); 678 | } 679 | } 680 | return resultList; 681 | } 682 | 683 | protected List getFilteredAgentList(List agentList, Status status){ 684 | List resultList = new ArrayList(); 685 | for(Agent agent:agentList){ 686 | if(getStatus(agent) == status){ 687 | resultList.add(agent); 688 | } 689 | } 690 | return resultList; 691 | } 692 | 693 | protected List getFilteredAgentList(List agentList, Role role){ 694 | List resultList = new ArrayList(); 695 | for(Agent agent:agentList){ 696 | if(getRole(agent) == role){ 697 | resultList.add(agent); 698 | } 699 | } 700 | return resultList; 701 | } 702 | 703 | protected List getFilteredAgentList(List agentList, Team team){ 704 | List resultList = new ArrayList(); 705 | for(Agent agent:agentList){ 706 | if(getRole(agent).getTeam() == team){ 707 | resultList.add(agent); 708 | } 709 | } 710 | return resultList; 711 | } 712 | 713 | 714 | 715 | 716 | public int nextTalkIdx() { 717 | return talkIdx++; 718 | } 719 | 720 | public int nextWhisperIdx() { 721 | return wisperIdx++; 722 | } 723 | 724 | /** 725 | *
昨夜人狼に襲われ死亡したエージェントを返す.
726 | * 727 | *
Returns the agent who died last night because of the attack by werewolf.
728 | * 729 | * @return the attackedDead 730 | */ 731 | public Agent getAttackedDead() { 732 | return attackedDead; 733 | } 734 | 735 | /** 736 | *
昨夜人狼に襲われ死亡したエージェントをセットする.
737 | * 738 | *
Sets the agent who died last night because of the attack by werewolf.
739 | * 740 | * @param attackedDead 741 | * the attackedDead to set 742 | */ 743 | public void setAttackedDead(Agent attackedDead) { 744 | this.attackedDead = attackedDead; 745 | } 746 | 747 | /** 748 | *
呪殺された妖狐を返す.
749 | * 750 | *
Returns the fox killed by curse.
751 | * 752 | * @return
呪殺された妖狐
753 | * 754 | *
the fox killed by curse
755 | */ 756 | public Agent getCursedFox() { 757 | return cursedFox; 758 | } 759 | 760 | /** 761 | *
呪殺された妖狐をセットする.
762 | * 763 | *
Sets the fox killed by curse.
764 | * 765 | * @param cursedFox 766 | *
呪殺された妖狐
767 | * 768 | *
the fox killed by curse
769 | */ 770 | public void setCursedFox(Agent cursedFox) { 771 | this.cursedFox = cursedFox; 772 | } 773 | 774 | /** 775 | *
直近の投票リストを返す
776 | * 777 | *
Returns the latest list of votes.
778 | * 779 | * @return
投票リストを表す{@code List}
780 | * 781 | *
{@code List} representing the list of votes.
782 | */ 783 | public List getLatestVoteList() { 784 | return latestVoteList; 785 | } 786 | 787 | /** 788 | *
直近の投票リストをセットする
789 | * 790 | *
Sets the latest list of votes.
791 | * 792 | * @param latestVoteList 793 | *
投票リストを表す{@code List}
794 | * 795 | *
{@code List} representing the list of votes.
796 | * 797 | */ 798 | public void setLatestVoteList(List latestVoteList) { 799 | this.latestVoteList = latestVoteList; 800 | } 801 | 802 | /** 803 | *
直近の襲撃投票リストを返す
804 | * 805 | *
Returns the latest list of votes for attack.
806 | * 807 | * @return
投票リストを表す{@code List}
808 | * 809 | *
{@code List} representing the list of votes.
810 | */ 811 | public List getLatestAttackVoteList() { 812 | return latestAttackVoteList; 813 | } 814 | 815 | /** 816 | *
直近の襲撃投票リストをセットする
817 | * 818 | *
Sets the latest list of votes for attack.
819 | * 820 | * @param latestAttackVoteList 821 | *
投票リストを表す{@code List}
822 | * 823 | *
{@code List} representing the list of votes.
824 | * 825 | */ 826 | public void setLatestAttackVoteList(List latestAttackVoteList) { 827 | this.latestAttackVoteList = latestAttackVoteList; 828 | } 829 | 830 | /** 831 | * 832 | *
指定エージェントがゲームに含まれているかどうかを調べる
833 | * 834 | *
Check whether the agents is joining in game.
835 | * 836 | * @param latestAttackVoteList 837 | *
含まれているかどうか{@code boolean}
838 | * 839 | *
{@code boolean} is contains in the game.
840 | */ 841 | public boolean contains(Agent target) { 842 | return this.agentRoleMap.containsKey(target); 843 | } 844 | 845 | } 846 | -------------------------------------------------------------------------------- /src/org/aiwolf/server/IllegalPlayerNumException.java: -------------------------------------------------------------------------------- 1 | package org.aiwolf.server; 2 | 3 | import org.aiwolf.common.AIWolfRuntimeException; 4 | 5 | public class IllegalPlayerNumException extends AIWolfRuntimeException { 6 | 7 | public IllegalPlayerNumException() { 8 | super(); 9 | } 10 | 11 | public IllegalPlayerNumException(String arg0, Throwable arg1, boolean arg2, 12 | boolean arg3) { 13 | super(arg0, arg1, arg2, arg3); 14 | } 15 | 16 | public IllegalPlayerNumException(String arg0, Throwable arg1) { 17 | super(arg0, arg1); 18 | } 19 | 20 | public IllegalPlayerNumException(String arg0) { 21 | super(arg0); 22 | } 23 | 24 | public IllegalPlayerNumException(Throwable arg0) { 25 | super(arg0); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/org/aiwolf/server/LostClientException.java: -------------------------------------------------------------------------------- 1 | package org.aiwolf.server; 2 | 3 | import org.aiwolf.common.AIWolfRuntimeException; 4 | import org.aiwolf.common.data.Agent; 5 | 6 | /** 7 | * throws when the cliend connection is lost 8 | * @author tori 9 | * 10 | */ 11 | public class LostClientException extends AIWolfRuntimeException { 12 | 13 | Agent agent; 14 | 15 | // public LostClientException() { 16 | // } 17 | // 18 | // public LostClientException(String arg0) { 19 | // super(arg0); 20 | // } 21 | 22 | public LostClientException(Throwable arg0, Agent agent) { 23 | super(arg0); 24 | this.agent = agent; 25 | } 26 | 27 | // public LostClientException(Throwable arg0) { 28 | // super(arg0); 29 | // } 30 | 31 | // public LostClientException(String arg0, Throwable arg1) { 32 | // super(arg0, arg1); 33 | // } 34 | // 35 | // public LostClientException(String arg0, Throwable arg1, boolean arg2, 36 | // boolean arg3) { 37 | // super(arg0, arg1, arg2, arg3); 38 | // } 39 | 40 | public LostClientException(String arg0, Throwable arg1, Agent agent) { 41 | super(arg0, arg1); 42 | this.agent = agent; 43 | } 44 | 45 | /** 46 | * @return agent 47 | */ 48 | public Agent getAgent() { 49 | return agent; 50 | } 51 | 52 | /** 53 | * @param agent セットする agent 54 | */ 55 | public void setAgent(Agent agent) { 56 | this.agent = agent; 57 | } 58 | 59 | 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/org/aiwolf/server/bin/DirectStarter.java: -------------------------------------------------------------------------------- 1 | package org.aiwolf.server.bin; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.util.ArrayList; 6 | 7 | import java.util.List; 8 | import java.util.Map; 9 | import java.util.Random; 10 | 11 | import org.aiwolf.common.bin.ClientStarter; 12 | import org.aiwolf.common.data.Player; 13 | import org.aiwolf.common.net.GameSetting; 14 | import org.aiwolf.common.util.CalendarTools; 15 | import org.aiwolf.common.util.Counter; 16 | import org.aiwolf.server.AIWolfGame; 17 | import org.aiwolf.server.net.DirectConnectServer; 18 | import org.aiwolf.server.net.GameServer; 19 | 20 | /** 21 | * クライアントを指定して直接シミュレーションを実行する 22 | * @author tori 23 | * @deprecated 24 | */ 25 | public class DirectStarter { 26 | 27 | /** 28 | * @param args 29 | * @throws ClassNotFoundException 30 | * @throws IllegalAccessException 31 | * @throws InstantiationException 32 | * @throws IOException 33 | */ 34 | public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, IOException { 35 | Counter clsCountMap = new Counter(); 36 | String logDir = "./log/"; 37 | for(int i = 0; i < args.length; i++){ 38 | if(args[i].startsWith("-")){ 39 | if(args[i].equals("-c")){ 40 | i++; 41 | String clsName = args[i]; 42 | i++; 43 | int num = Integer.parseInt(args[i]); 44 | 45 | clsCountMap.put(clsName, num); 46 | } 47 | else if(args[i].equals("-l")){ 48 | i++; 49 | logDir = args[i]; 50 | } 51 | } 52 | } 53 | if(clsCountMap.isEmpty()){ 54 | System.err.println("Usage:"+ClientStarter.class+" -c clientClass num [-c clientClass num ...] [-l logDir]"); 55 | return; 56 | } 57 | 58 | 59 | start(clsCountMap, logDir); 60 | } 61 | 62 | /** 63 | * 64 | * @param clsCountMap 65 | * @param logDir 66 | * @throws InstantiationException 67 | * @throws IllegalAccessException 68 | * @throws ClassNotFoundException 69 | * @throws IOException 70 | */ 71 | public static void start(Counter clsCountMap, String logDir) throws InstantiationException, IllegalAccessException, ClassNotFoundException, IOException { 72 | int playerNum = clsCountMap.getTotalCount(); 73 | List playerList = new ArrayList(); 74 | // for(int i = 0; i < playerNum; i++){ 75 | // playerList.add((Player) Class.forName(clsName).newInstance()); 76 | // } 77 | for(String clsName:clsCountMap){ 78 | int num = clsCountMap.get(clsName); 79 | for(int i = 0; i < num; i++){ 80 | playerList.add((Player) Class.forName(clsName).newInstance()); 81 | } 82 | } 83 | 84 | String timeString = CalendarTools.toDateTime(System.currentTimeMillis()).replaceAll("[\\s-/:]", ""); 85 | File logFile = new File(String.format("%s/aiwolfGame%s.log", logDir, timeString)); 86 | 87 | GameServer gameServer = new DirectConnectServer(playerList); 88 | GameSetting gameSetting = GameSetting.getDefaultGame(playerNum); 89 | AIWolfGame game = new AIWolfGame(gameSetting, gameServer); 90 | // game.setLogFile(logFile); 91 | game.setRand(new Random(gameSetting.getRandomSeed())); 92 | // game.init(); 93 | game.start(); 94 | // game.finish(); 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /src/org/aiwolf/server/bin/RoleRequestStarter.java: -------------------------------------------------------------------------------- 1 | package org.aiwolf.server.bin; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.util.ArrayList; 6 | import java.util.HashMap; 7 | import java.util.LinkedHashMap; 8 | import java.util.List; 9 | import java.util.Map; 10 | import java.util.Random; 11 | 12 | import org.aiwolf.common.data.Player; 13 | import org.aiwolf.common.data.Role; 14 | import org.aiwolf.common.net.GameSetting; 15 | import org.aiwolf.common.util.CalendarTools; 16 | import org.aiwolf.common.util.Pair; 17 | import org.aiwolf.server.AIWolfGame; 18 | import org.aiwolf.server.net.DirectConnectServer; 19 | import org.aiwolf.server.util.GameLogger; 20 | 21 | /** 22 | * 役割を指定してスタートするStarter
23 | * DirectStarter 24 | * @author tori 25 | * @deprecated 26 | */ 27 | public class RoleRequestStarter { 28 | 29 | static final private String description = 30 | "このクラスを利用して,自作Playerごとに役職を決めてゲームをスタートできます.\n" + 31 | "Usage:"+RoleRequestStarter.class+" -n agentNum -c playerClass role [-c playerClass role] [-d defaultPlayer]\n"+ 32 | "-n\tゲームに参加するエージェント数を決定します.\n"+ 33 | "-c 'プレイヤークラス' '設定したい役職' を設定します.\n"+ 34 | "-c 'プレイヤークラス' で,役職を指定せずに利用するPlayerを指定します.\n"+ 35 | "-d デフォルトのプレイヤークラスを指定します.指定しなければSamplePlayerが使われます.\n"+ 36 | "-l ログを保存するディレクトリの指定.デフォルトは./log/\n"+ 37 | "例えば,自作のorg.aiwolf.MyPlayerをbodyguardとして12体のエージェントで人狼を実行したければ\n"+ 38 | RoleRequestStarter.class+" -n 12 -c org.aiwolf.MyPlayer bodyguard\n"+ 39 | "としてください.\n"; 40 | 41 | /** 42 | * @param args 43 | * @throws ClassNotFoundException 44 | * @throws IllegalAccessException 45 | * @throws InstantiationException 46 | * @throws IOException 47 | */ 48 | public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, IOException { 49 | 50 | 51 | List> playerRoleList = new ArrayList>(); 52 | String defaultClsName = Class.forName("org.aiwolf.client.base.smpl.SampleRoleAssignPlayer").getName(); 53 | int playerNum = -1; 54 | String logDir = "./log/"; 55 | for(int i = 0; i < args.length; i++){ 56 | if(args[i].startsWith("-")){ 57 | if(args[i].equals("-c")){ 58 | i++; 59 | String clsName = args[i]; 60 | i++; 61 | try{ 62 | if(i > args.length-1 || args[i].startsWith("-")){ 63 | i--; 64 | playerRoleList.add(new Pair(clsName, null)); 65 | continue; 66 | } 67 | Role role = Role.valueOf(args[i].toUpperCase()); 68 | playerRoleList.add(new Pair(clsName, role)); 69 | }catch(IllegalArgumentException e){ 70 | System.err.println("No such role as "+args[i]); 71 | return; 72 | } 73 | } 74 | else if(args[i].equals("-n")){ 75 | i++; 76 | playerNum = Integer.parseInt(args[i]); 77 | } 78 | else if(args[i].equals("-d")){ 79 | i++; 80 | defaultClsName = args[i]; 81 | } 82 | else if(args[i].equals("-l")){ 83 | i++; 84 | logDir = args[i]; 85 | } 86 | else if(args[i].equals("-h")){ 87 | System.out.println(description); 88 | System.out.println("利用可能な役職"); 89 | for(Role role:Role.values()){ 90 | System.out.println(role); 91 | } 92 | } 93 | } 94 | } 95 | if(playerNum < 0){ 96 | System.err.println("Usage:"+RoleRequestStarter.class+" -n agentNum -c playerClass role [-c playerClass role...] [-d defaultPlayer] [-l logDir]"); 97 | return; 98 | } 99 | 100 | 101 | Map playerMap = new HashMap(); 102 | for(Pair pair:playerRoleList){ 103 | playerMap.put((Player) Class.forName(pair.getKey()).newInstance(), pair.getValue()); 104 | } 105 | while(playerMap.size() < playerNum){ 106 | playerMap.put((Player) Class.forName(defaultClsName).newInstance(), null); 107 | } 108 | 109 | start(playerMap, logDir); 110 | } 111 | 112 | /** 113 | * 一人のRoleを指定してDirectに実行 114 | * @param player 115 | * @param role 116 | * @param playerNum 117 | * @param defaultClsName 118 | * @param logDir 119 | * @throws InstantiationException 120 | * @throws IllegalAccessException 121 | * @throws ClassNotFoundException 122 | * @throws IOException 123 | */ 124 | public static AIWolfGame start(Player player, Role role, int playerNum, String defaultClsName, String logDir) throws InstantiationException, IllegalAccessException, ClassNotFoundException, IOException{ 125 | Map playerMap = new LinkedHashMap(); 126 | 127 | playerMap.put(player, role); 128 | while(playerMap.size() < playerNum){ 129 | playerMap.put((Player) Class.forName(defaultClsName).newInstance(), null); 130 | } 131 | return start(playerMap, logDir); 132 | } 133 | 134 | /** 135 | * すべてのプレイヤーインスタンスとそのRoleを設定して開始 136 | * @param playerNum 137 | * @param playerMap 138 | * @param logDir 139 | * @throws IOException 140 | */ 141 | public static AIWolfGame start(Map playerMap, String logDir) throws IOException { 142 | String timeString = CalendarTools.toDateTime(System.currentTimeMillis()).replaceAll("[\\s-/:]", ""); 143 | 144 | DirectConnectServer gameServer = new DirectConnectServer(playerMap); 145 | GameSetting gameSetting = GameSetting.getDefaultGame(playerMap.size()); 146 | AIWolfGame game = new AIWolfGame(gameSetting, gameServer); 147 | if(logDir != null){ 148 | File logFile = new File(String.format("%s/contest%s.log", logDir, timeString)); 149 | game.setLogFile(logFile); 150 | } 151 | game.setRand(new Random()); 152 | // game.setShowConsoleLog(false); 153 | game.start(); 154 | return game; 155 | } 156 | 157 | /** 158 | * すべてのプレイヤーインスタンスとそのRoleを設定して開始 159 | * @param playerNum 160 | * @param playerMap 161 | * @param logDir 162 | * @throws IOException 163 | */ 164 | public static AIWolfGame start(Map playerMap, GameLogger logger) throws IOException { 165 | String timeString = CalendarTools.toDateTime(System.currentTimeMillis()).replaceAll("[\\s-/:]", ""); 166 | 167 | DirectConnectServer gameServer = new DirectConnectServer(playerMap); 168 | GameSetting gameSetting = GameSetting.getDefaultGame(playerMap.size()); 169 | AIWolfGame game = new AIWolfGame(gameSetting, gameServer); 170 | game.setGameLogger(logger); 171 | game.setRand(new Random()); 172 | // game.setShowConsoleLog(false); 173 | game.start(); 174 | return game; 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /src/org/aiwolf/server/bin/ServerStarter.java: -------------------------------------------------------------------------------- 1 | package org.aiwolf.server.bin; 2 | import java.io.File; 3 | import java.io.IOException; 4 | import java.net.SocketTimeoutException; 5 | import java.util.Random; 6 | 7 | import org.aiwolf.common.net.GameSetting; 8 | import org.aiwolf.server.AIWolfGame; 9 | import org.aiwolf.server.net.TcpipServer; 10 | 11 | /** 12 | * Main Class to start server application 13 | * @author tori 14 | * 15 | */ 16 | public class ServerStarter { 17 | 18 | /** 19 | * @param args 20 | * @throws IOException 21 | * @throws SocketTimeoutException 22 | */ 23 | public static void main(String[] args) throws SocketTimeoutException, IOException { 24 | int port = 10000; 25 | int playerNum = 12; 26 | String logFileName = null; 27 | 28 | for(int i = 0; i < args.length; i++){ 29 | if(args[i].startsWith("-")){ 30 | if(args[i].equals("-p")){ 31 | i++; 32 | port = Integer.parseInt(args[i]); 33 | } 34 | else if(args[i].equals("-n")){ 35 | i++; 36 | playerNum = Integer.parseInt(args[i]); 37 | } 38 | else if(args[i].equals("-l")){ 39 | i++; 40 | logFileName = args[i]; 41 | } 42 | } 43 | } 44 | 45 | System.out.printf("Start AiWolf Server port:%d playerNum:%d\n", port, playerNum); 46 | GameSetting gameSetting = GameSetting.getDefaultGame(playerNum); 47 | 48 | TcpipServer gameServer = new TcpipServer(port, playerNum, gameSetting); 49 | gameServer.waitForConnection(); 50 | 51 | AIWolfGame game = new AIWolfGame(gameSetting, gameServer); 52 | game.setRand(new Random()); 53 | if(logFileName != null){ 54 | game.setLogFile(new File(logFileName)); 55 | } 56 | game.start(); 57 | 58 | 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/org/aiwolf/server/net/DirectConnectServer.java: -------------------------------------------------------------------------------- 1 | package org.aiwolf.server.net; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.LinkedHashMap; 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | import org.aiwolf.common.AIWolfAgentException; 10 | import org.aiwolf.common.data.Agent; 11 | import org.aiwolf.common.data.Player; 12 | import org.aiwolf.common.data.Role; 13 | import org.aiwolf.common.net.GameSetting; 14 | import org.aiwolf.server.GameData; 15 | 16 | /** 17 | * Connect player and server directry 18 | * @author tori 19 | * @deprecated 20 | */ 21 | public class DirectConnectServer implements GameServer { 22 | 23 | /** 24 | * Agents connected to the server 25 | */ 26 | protected Map agentPlayerMap; 27 | 28 | /** 29 | * Agents connected to the server 30 | */ 31 | protected Map playerAgentMap; 32 | 33 | 34 | protected Map requestRoleMap; 35 | 36 | 37 | /** 38 | * GameData 39 | */ 40 | protected GameData gameData; 41 | 42 | /** 43 | * Game Setting 44 | */ 45 | protected GameSetting gameSetting; 46 | 47 | public DirectConnectServer(List playerList){ 48 | agentPlayerMap = new LinkedHashMap(); 49 | playerAgentMap = new LinkedHashMap(); 50 | int idx = 1; 51 | for(Player player:playerList){ 52 | Agent agent = Agent.getAgent(idx++); 53 | agentPlayerMap.put(agent, player); 54 | playerAgentMap.put(player, agent); 55 | } 56 | requestRoleMap = new HashMap(); 57 | 58 | } 59 | 60 | public DirectConnectServer(Map playerMap){ 61 | agentPlayerMap = new LinkedHashMap(); 62 | playerAgentMap = new LinkedHashMap(); 63 | requestRoleMap = new HashMap(); 64 | 65 | int idx = 1; 66 | for(Player player:playerMap.keySet()){ 67 | Agent agent = Agent.getAgent(idx++); 68 | agentPlayerMap.put(agent, player); 69 | playerAgentMap.put(player, agent); 70 | requestRoleMap.put(agent, playerMap.get(player)); 71 | } 72 | 73 | 74 | } 75 | 76 | @Override 77 | public List getConnectedAgentList() { 78 | return new ArrayList(agentPlayerMap.keySet()); 79 | } 80 | 81 | @Override 82 | public void setGameData(GameData gameData) { 83 | this.gameData = gameData; 84 | } 85 | 86 | @Override 87 | public void setGameSetting(GameSetting gameSetting){ 88 | this.gameSetting = gameSetting; 89 | } 90 | 91 | 92 | @Override 93 | public void init(Agent agent) { 94 | try{ 95 | agentPlayerMap.get(agent).initialize(gameData.getGameInfo(agent), gameSetting.clone()); 96 | }catch(Throwable e){ 97 | e.printStackTrace(); 98 | throw new AIWolfAgentException(agent, "init", e); 99 | } 100 | } 101 | 102 | @Override 103 | public String requestName(Agent agent) { 104 | try{ 105 | String name = agentPlayerMap.get(agent).getName(); 106 | if(name != null){ 107 | return name; 108 | } 109 | else{ 110 | return agentPlayerMap.get(agent).getClass().getSimpleName(); 111 | } 112 | }catch(Throwable e){ 113 | throw new AIWolfAgentException(agent, "requestName", e); 114 | } 115 | } 116 | 117 | @Override 118 | public Role requestRequestRole(Agent agent) { 119 | try{ 120 | return requestRoleMap.get(agent); 121 | }catch(Throwable e){ 122 | throw new AIWolfAgentException(agent, "requestRequestRole", e); 123 | } 124 | } 125 | 126 | @Override 127 | public void dayStart(Agent agent) { 128 | try{ 129 | agentPlayerMap.get(agent).update(gameData.getGameInfo(agent)); 130 | agentPlayerMap.get(agent).dayStart(); 131 | }catch(Throwable e){ 132 | throw new AIWolfAgentException(agent, "dayStart", e); 133 | } 134 | } 135 | 136 | @Override 137 | public void dayFinish(Agent agent) { 138 | try{ 139 | agentPlayerMap.get(agent).update(gameData.getGameInfo(agent)); 140 | // agentPlayerMap.get(agent).dayStart(); 141 | }catch(Throwable e){ 142 | throw new AIWolfAgentException(agent, "dayFinish", e); 143 | } 144 | } 145 | 146 | @Override 147 | public String requestTalk(Agent agent) { 148 | try{ 149 | agentPlayerMap.get(agent).update(gameData.getGameInfo(agent)); 150 | String talk = agentPlayerMap.get(agent).talk(); 151 | return talk; 152 | // if(talk == null){ 153 | // throw new NoReturnObjectException(); 154 | // } 155 | // else{ 156 | // return talk; 157 | // } 158 | }catch(Throwable e){ 159 | throw new AIWolfAgentException(agent, "requestTalk", e); 160 | } 161 | } 162 | 163 | @Override 164 | public String requestWhisper(Agent agent) { 165 | try{ 166 | agentPlayerMap.get(agent).update(gameData.getGameInfo(agent)); 167 | String whisper = agentPlayerMap.get(agent).whisper(); 168 | return whisper; 169 | // if(whisper == null){ 170 | // throw new NoReturnObjectException(); 171 | // } 172 | // else{ 173 | // return whisper; 174 | // } 175 | }catch(Throwable e){ 176 | throw new AIWolfAgentException(agent, "requestWhisper", e); 177 | } 178 | } 179 | 180 | @Override 181 | public Agent requestVote(Agent agent) { 182 | try{ 183 | agentPlayerMap.get(agent).update(gameData.getGameInfo(agent)); 184 | Agent target = agentPlayerMap.get(agent).vote(); 185 | return target; 186 | // if(target == null){ 187 | // throw new NoReturnObjectException(); 188 | // } 189 | // else{ 190 | // return target; 191 | // } 192 | }catch(Throwable e){ 193 | throw new AIWolfAgentException(agent, "requestVote", e); 194 | } 195 | } 196 | 197 | @Override 198 | public Agent requestDivineTarget(Agent agent) { 199 | try{ 200 | agentPlayerMap.get(agent).update(gameData.getGameInfo(agent)); 201 | Agent target = agentPlayerMap.get(agent).divine(); 202 | return target; 203 | // if(target == null){ 204 | // throw new NoReturnObjectException(); 205 | // } 206 | // else{ 207 | // return target; 208 | // } 209 | }catch(Throwable e){ 210 | throw new AIWolfAgentException(agent, "requestDivineTarget", e); 211 | } 212 | } 213 | 214 | @Override 215 | public Agent requestGuardTarget(Agent agent) { 216 | try{ 217 | agentPlayerMap.get(agent).update(gameData.getGameInfo(agent)); 218 | Agent target = agentPlayerMap.get(agent).guard(); 219 | return target; 220 | // if(target == null){ 221 | // throw new NoReturnObjectException(); 222 | // } 223 | // else{ 224 | // return target; 225 | // } 226 | }catch(Throwable e){ 227 | throw new AIWolfAgentException(agent, "requestGuardTarget", e); 228 | } 229 | } 230 | 231 | @Override 232 | public Agent requestAttackTarget(Agent agent) { 233 | try{ 234 | agentPlayerMap.get(agent).update(gameData.getGameInfo(agent)); 235 | Agent target = agentPlayerMap.get(agent).attack(); 236 | return target; 237 | // if(target == null){ 238 | // throw new NoReturnObjectException(); 239 | // } 240 | // else{ 241 | // return target; 242 | // } 243 | }catch(Throwable e){ 244 | throw new AIWolfAgentException(agent, "requestAttackTarget", e); 245 | } 246 | } 247 | 248 | @Override 249 | public void finish(Agent agent){ 250 | try{ 251 | agentPlayerMap.get(agent).update(gameData.getFinalGameInfo(agent)); 252 | agentPlayerMap.get(agent).finish(); 253 | }catch(Throwable e){ 254 | throw new AIWolfAgentException(agent, "finish", e); 255 | } 256 | } 257 | 258 | @Override 259 | public void close() { 260 | } 261 | 262 | public Agent getAgent(Player player) { 263 | return playerAgentMap.get(player); 264 | } 265 | 266 | 267 | public Player getPlayer(Agent agent){ 268 | return agentPlayerMap.get(agent); 269 | } 270 | 271 | 272 | 273 | 274 | 275 | } 276 | -------------------------------------------------------------------------------- /src/org/aiwolf/server/net/GameServer.java: -------------------------------------------------------------------------------- 1 | package org.aiwolf.server.net; 2 | 3 | import java.util.List; 4 | 5 | 6 | import org.aiwolf.common.data.Agent; 7 | import org.aiwolf.common.data.Role; 8 | import org.aiwolf.common.net.GameSetting; 9 | import org.aiwolf.server.GameData; 10 | 11 | public interface GameServer { 12 | 13 | /** 14 | * 15 | * @return 16 | */ 17 | List getConnectedAgentList(); 18 | 19 | /** 20 | * set GameSetting 21 | * @param gameSetting 22 | */ 23 | void setGameSetting(GameSetting gameSetting); 24 | 25 | /** 26 | * 27 | * @param agent 28 | */ 29 | void init(Agent agent); 30 | 31 | /** 32 | * Request agent's name 33 | * @param agent 34 | * @return 35 | */ 36 | String requestName(Agent agent); 37 | 38 | /** 39 | * Request roles that agent request 40 | * @param agent 41 | * @return 42 | */ 43 | Role requestRequestRole(Agent agent); 44 | 45 | /** 46 | * 47 | * @param agent 48 | * @return 49 | */ 50 | String requestTalk(Agent agent); 51 | 52 | /** 53 | * 54 | * @param agent 55 | * @return 56 | */ 57 | String requestWhisper(Agent agent); 58 | 59 | 60 | /** 61 | * 62 | * @param agent 63 | * @return 64 | */ 65 | Agent requestVote(Agent agent); 66 | 67 | 68 | /** 69 | * 70 | * @param agent 71 | * @return 72 | */ 73 | Agent requestDivineTarget(Agent agent); 74 | 75 | /** 76 | * 77 | * @param agent 78 | * @return 79 | */ 80 | Agent requestGuardTarget(Agent agent); 81 | 82 | 83 | /** 84 | * 85 | * @param agent 86 | * @return 87 | */ 88 | Agent requestAttackTarget(Agent agent); 89 | 90 | /** 91 | * 92 | * @param gameInfo 93 | */ 94 | void setGameData(GameData gameData); 95 | 96 | /** 97 | * called when day started 98 | * @param agent 99 | */ 100 | void dayStart(Agent agent); 101 | 102 | /** 103 | * called when day finished 104 | * @param agent 105 | */ 106 | void dayFinish(Agent agent); 107 | 108 | /** 109 | * send finished message 110 | */ 111 | void finish(Agent agent); 112 | 113 | /** 114 | * close connections 115 | */ 116 | void close(); 117 | 118 | } 119 | -------------------------------------------------------------------------------- /src/org/aiwolf/server/net/ServerListener.java: -------------------------------------------------------------------------------- 1 | package org.aiwolf.server.net; 2 | 3 | import java.net.Socket; 4 | 5 | import org.aiwolf.common.data.Agent; 6 | 7 | public interface ServerListener { 8 | public void connected(Socket socket, Agent agent, String name); 9 | 10 | public void unconnected(Socket socket, Agent agent, String name); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/org/aiwolf/server/net/TcpipServer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * TcpipServer.java 3 | * 4 | * Copyright (c) 2014 人狼知能プロジェクト 5 | */ 6 | package org.aiwolf.server.net; 7 | 8 | import java.io.BufferedReader; 9 | import java.io.BufferedWriter; 10 | import java.io.IOException; 11 | import java.io.InputStreamReader; 12 | import java.io.OutputStreamWriter; 13 | import java.net.ServerSocket; 14 | import java.net.Socket; 15 | import java.net.SocketTimeoutException; 16 | import java.util.ArrayList; 17 | import java.util.Collections; 18 | import java.util.HashMap; 19 | import java.util.HashSet; 20 | import java.util.List; 21 | import java.util.Map; 22 | import java.util.Set; 23 | import java.util.concurrent.Callable; 24 | import java.util.concurrent.ExecutionException; 25 | import java.util.concurrent.ExecutorService; 26 | import java.util.concurrent.Executors; 27 | import java.util.concurrent.Future; 28 | import java.util.concurrent.TimeUnit; 29 | import java.util.concurrent.TimeoutException; 30 | 31 | //import net.arnx.jsonic.JSON; 32 | 33 | import org.aiwolf.common.data.Agent; 34 | import org.aiwolf.common.data.Request; 35 | import org.aiwolf.common.data.Role; 36 | import org.aiwolf.common.net.DataConverter; 37 | import org.aiwolf.common.net.GameSetting; 38 | import org.aiwolf.common.net.Packet; 39 | import org.aiwolf.common.net.TalkToSend; 40 | import org.aiwolf.common.util.BidiMap; 41 | import org.aiwolf.server.GameData; 42 | import org.aiwolf.server.IllegalPlayerNumException; 43 | import org.aiwolf.server.LostClientException; 44 | 45 | /** 46 | * Game server which communicates with clients via TCP/IP connections. 47 | * 48 | * @author tori and otsuki 49 | * 50 | */ 51 | public class TcpipServer implements GameServer { 52 | 53 | 54 | 55 | 56 | /** 57 | * Server Port 58 | */ 59 | protected int port; 60 | 61 | /** 62 | * connection limit 63 | */ 64 | protected int limit; 65 | 66 | /** 67 | * 68 | */ 69 | protected boolean isWaitForClient; 70 | 71 | /** 72 | * 73 | */ 74 | protected BidiMap socketAgentMap; 75 | 76 | 77 | /** 78 | * Current game data 79 | */ 80 | protected GameData gameData; 81 | 82 | /** 83 | * Game Setting 84 | */ 85 | protected GameSetting gameSetting; 86 | 87 | /** 88 | * 89 | */ 90 | // Logger serverLogger; 91 | 92 | /** 93 | * 94 | */ 95 | protected Map nameMap; 96 | 97 | protected Set serverListenerSet; 98 | 99 | protected Map lastTalkIdxMap; 100 | protected Map lastWhisperIdxMap; 101 | 102 | protected ServerSocket serverSocket; 103 | 104 | /** 105 | * Time limit for waiting request 106 | */ 107 | protected int timeLimit = 1000; 108 | 109 | /** 110 | * 111 | * @param port 112 | * @param limit 113 | */ 114 | public TcpipServer(int port, int limit, GameSetting gameSetting){ 115 | this.gameSetting = gameSetting; 116 | this.port = port; 117 | this.limit = limit; 118 | if (gameSetting.getTimeLimit() != -1) { 119 | timeLimit = gameSetting.getTimeLimit(); 120 | } 121 | 122 | socketAgentMap = new BidiMap(); 123 | String loggerName = this.getClass().getSimpleName(); 124 | // serverLogger = Logger.getLogger(loggerName); 125 | nameMap = new HashMap<>(); 126 | serverListenerSet = new HashSet<>(); 127 | // serverLogger = AiWolfLoggerFactory.getLogger(loggerName); 128 | // serverLogger.setLevel(Level.FINER); 129 | // try { 130 | // serverLogger = AiWolfLoggerFactory.getLogger(loggerName, new File(loggerName+".log")); 131 | // serverLogger.setLevel(Level.FINER); 132 | // } catch (IOException e) { 133 | // e.printStackTrace(); 134 | // serverLogger = AiWolfLoggerFactory.getLogger(loggerName); 135 | // } 136 | 137 | lastTalkIdxMap = new HashMap(); 138 | lastWhisperIdxMap = new HashMap(); 139 | } 140 | 141 | /** 142 | * 143 | * @throws IOException 144 | * @throws SocketTimeoutException 145 | */ 146 | public void waitForConnection() throws IOException, SocketTimeoutException{ 147 | // int timeout_msec = 1000*60*10; // time out in 10 miniutes 148 | // serverLogger.info(String.format("Start Server@port %d\n", port)); 149 | 150 | for(Socket sock:socketAgentMap.keySet()){ 151 | if(sock != null && sock.isConnected()){ 152 | sock.close(); 153 | } 154 | } 155 | 156 | socketAgentMap.clear(); 157 | nameMap.clear(); 158 | 159 | // serverLogger.info(String.format("Waiting for connection...\n")); 160 | System.out.println("Waiting for connection...\n"); 161 | 162 | serverSocket = new ServerSocket(port); 163 | 164 | isWaitForClient = true; 165 | 166 | List shuffledAgentList = new ArrayList<>(); 167 | for(int i = 1; i <= limit; i++) { 168 | shuffledAgentList.add(Agent.getAgent(i)); 169 | } 170 | Collections.shuffle(shuffledAgentList); 171 | 172 | while(socketAgentMap.size() < limit && isWaitForClient){ 173 | Socket socket = serverSocket.accept(); 174 | 175 | synchronized (socketAgentMap) { 176 | Agent agent = null; 177 | for (int i = 0; i < limit; i++) { 178 | if(!socketAgentMap.containsValue(shuffledAgentList.get(i))){ 179 | agent = shuffledAgentList.get(i); 180 | break; 181 | } 182 | } 183 | if(agent == null){ 184 | throw new IllegalPlayerNumException("Fail to create agent"); 185 | } 186 | socketAgentMap.put(socket, agent); 187 | String name = requestName(agent); 188 | nameMap.put(agent, name); 189 | 190 | for(ServerListener listener:serverListenerSet){ 191 | listener.connected(socket, agent, name); 192 | } 193 | } 194 | 195 | } 196 | isWaitForClient = false; 197 | serverSocket.close(); 198 | } 199 | 200 | /** 201 | * 202 | */ 203 | public void stopWaitingForConnection() { 204 | isWaitForClient = false; 205 | try { 206 | if(serverSocket != null){ 207 | serverSocket.close(); 208 | } 209 | } catch (IOException e) { 210 | e.printStackTrace(); 211 | } 212 | for(Socket s:socketAgentMap.keySet()){ 213 | try { 214 | s.close(); 215 | } catch (IOException e) { 216 | e.printStackTrace(); 217 | } 218 | } 219 | socketAgentMap.clear(); 220 | } 221 | 222 | 223 | 224 | @Override 225 | public List getConnectedAgentList() { 226 | synchronized (socketAgentMap) { 227 | return new ArrayList(socketAgentMap.values()); 228 | } 229 | } 230 | 231 | /** 232 | * send data to client 233 | * @param agent 234 | * @param sendText 235 | * @TODO Whisperの際に毎回GameInfoを毎回送ってしまう問題の解決.必要が無ければGameInfoを送らなくする 236 | */ 237 | protected void send(Agent agent, Request request){ 238 | try{ 239 | String message; 240 | if(request == Request.INITIALIZE){ 241 | lastTalkIdxMap.clear(); 242 | lastWhisperIdxMap.clear(); 243 | Packet packet = new Packet(request, gameData.getGameInfoToSend(agent), gameSetting); 244 | message = DataConverter.getInstance().convert(packet); 245 | } 246 | else if(request == Request.DAILY_INITIALIZE){ 247 | lastTalkIdxMap.clear(); 248 | lastWhisperIdxMap.clear(); 249 | Packet packet = new Packet(request, gameData.getGameInfoToSend(agent)); 250 | message = DataConverter.getInstance().convert(packet); 251 | } 252 | else if(request == Request.NAME || request == Request.ROLE){ 253 | Packet packet = new Packet(request); 254 | message = DataConverter.getInstance().convert(packet); 255 | } 256 | else if (request != Request.FINISH) { 257 | // Packet packet = new Packet(request, gameData.getGameInfoToSend(agent), gameSetting); 258 | // message = DataConverter.getInstance().convert(packet); 259 | if (request == Request.VOTE && !gameData.getLatestVoteList().isEmpty()) { 260 | // 追放再投票の場合,latestVoteListで直前の投票状況を知らせるためGameInfo入りのパケットにする 261 | Packet packet = new Packet(request, gameData.getGameInfoToSend(agent)); 262 | message = DataConverter.getInstance().convert(packet); 263 | } else if (request == Request.ATTACK && !gameData.getLatestAttackVoteList().isEmpty()) { 264 | // 襲撃再投票の場合,latestAttackVoteListで直前の投票状況を知らせるためGameInfo入りのパケットにする 265 | Packet packet = new Packet(request, gameData.getGameInfoToSend(agent)); 266 | message = DataConverter.getInstance().convert(packet); 267 | } else if (gameData.getExecuted() != null 268 | && (request == Request.DIVINE || request == Request.GUARD || request == Request.WHISPER || request == Request.ATTACK)) { 269 | // 追放後の各リクエストではlatestExecutedAgentで追放者を知らせるためGameInfo入りのパケットにする 270 | Packet packet = new Packet(request, gameData.getGameInfoToSend(agent)); 271 | message = DataConverter.getInstance().convert(packet); 272 | } else { 273 | List talkList = gameData.getGameInfoToSend(agent).getTalkList(); 274 | List whisperList = gameData.getGameInfoToSend(agent).getWhisperList(); 275 | 276 | talkList = minimize(agent, talkList, lastTalkIdxMap); 277 | whisperList = minimize(agent, whisperList, lastWhisperIdxMap); 278 | 279 | Packet packet = new Packet(request, talkList, whisperList); 280 | message = DataConverter.getInstance().convert(packet); 281 | } 282 | } else { 283 | Packet packet = new Packet(request, gameData.getFinalGameInfoToSend(agent)); 284 | message = DataConverter.getInstance().convert(packet); 285 | } 286 | // serverLogger.info("=>"+agent+":"+message); 287 | 288 | Socket sock = socketAgentMap.getKey(agent); 289 | BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream())); 290 | bw.append(message); 291 | bw.append("\n"); 292 | bw.flush(); 293 | }catch(IOException e){ 294 | // serverLogger.severe(e.getMessage()); 295 | throw new LostClientException(e, agent); 296 | } 297 | } 298 | 299 | /** 300 | * delete talks already sent 301 | * @param agent 302 | * @param list 303 | * @param lastIdxMap 304 | * @return 305 | */ 306 | protected List minimize(Agent agent, List list, Map lastIdxMap) { 307 | int lastIdx = list.size(); 308 | if(lastIdxMap.containsKey(agent) && list.size() >= lastIdxMap.get(agent)){ 309 | list = list.subList(lastIdxMap.get(agent), list.size()); 310 | } 311 | lastIdxMap.put(agent, lastIdx); 312 | return list; 313 | } 314 | 315 | /** 316 | * send data to client 317 | * @param agent 318 | * @param sendText 319 | */ 320 | protected Object request(Agent agent, Request request){ 321 | try{ 322 | Socket sock = socketAgentMap.getKey(agent); 323 | final BufferedReader br = new BufferedReader(new InputStreamReader(sock.getInputStream())); 324 | send(agent, request); 325 | 326 | String line = null; 327 | ExecutorService pool = Executors.newSingleThreadExecutor(); 328 | RequestReadCallable task = new RequestReadCallable(br); 329 | try { 330 | Future future = pool.submit(task); 331 | try{ 332 | line = future.get(timeLimit, TimeUnit.MILLISECONDS); //1秒でタイムアウト 333 | } catch (InterruptedException | ExecutionException e) { 334 | throw e; 335 | } catch (TimeoutException e) { 336 | sock.close(); 337 | throw e; 338 | } 339 | } finally { 340 | pool.shutdownNow(); 341 | } 342 | 343 | // String line = br.readLine(); 344 | if(!task.isSuccess()){ 345 | throw task.getIOException(); 346 | } 347 | // serverLogger.info("<="+agent+":"+line); 348 | 349 | if(line != null && line.isEmpty()){ 350 | line = null; 351 | } 352 | if (request == Request.NAME || request == Request.ROLE) { 353 | return line; 354 | } else if (request == Request.TALK || request == Request.WHISPER) { 355 | return line; 356 | } else if (request == Request.ATTACK || request == Request.DIVINE || request == Request.GUARD 357 | || request == Request.VOTE) { 358 | Agent target = DataConverter.getInstance().toAgent(line); 359 | if(gameData.contains(target)) { 360 | return target; 361 | } 362 | else { 363 | return null; 364 | } 365 | } 366 | else{ 367 | return null; 368 | } 369 | 370 | 371 | }catch(InterruptedException | ExecutionException | IOException e){ 372 | throw new LostClientException("Lost connection with "+agent+"\t"+getName(agent), e, agent); 373 | }catch(TimeoutException e){ 374 | throw new LostClientException(String.format("Timeout %s(%s) %s", agent, getName(agent), request), e, agent); 375 | } 376 | } 377 | 378 | @Override 379 | public void init(Agent agent) { 380 | send(agent, Request.INITIALIZE); 381 | } 382 | 383 | @Override 384 | public void dayStart(Agent agent) { 385 | send(agent, Request.DAILY_INITIALIZE); 386 | } 387 | 388 | @Override 389 | public void dayFinish(Agent agent){ 390 | send(agent, Request.DAILY_FINISH); 391 | } 392 | 393 | @Override 394 | public String requestName(Agent agent) { 395 | if(nameMap.containsKey(agent)){ 396 | return nameMap.get(agent); 397 | } 398 | else{ 399 | String name = (String)request(agent, Request.NAME); 400 | nameMap.put(agent, name); 401 | return name; 402 | } 403 | } 404 | 405 | 406 | @Override 407 | public Role requestRequestRole(Agent agent) { 408 | String roleString = (String)request(agent, Request.ROLE); 409 | try{ 410 | return Role.valueOf(roleString); 411 | }catch(IllegalArgumentException e){ 412 | return null; 413 | } 414 | } 415 | 416 | 417 | @Override 418 | public String requestTalk(Agent agent) { 419 | return (String)request(agent, Request.TALK); 420 | } 421 | 422 | @Override 423 | public String requestWhisper(Agent agent) { 424 | return (String)request(agent, Request.WHISPER); 425 | } 426 | 427 | @Override 428 | public Agent requestVote(Agent agent) { 429 | return (Agent)request(agent, Request.VOTE); 430 | // return JSON.decode(result); 431 | } 432 | 433 | @Override 434 | public Agent requestDivineTarget(Agent agent) { 435 | return (Agent)request(agent, Request.DIVINE); 436 | // return JSON.decode(result); 437 | } 438 | 439 | @Override 440 | public Agent requestGuardTarget(Agent agent) { 441 | return (Agent)request(agent, Request.GUARD); 442 | // return JSON.decode(result); 443 | } 444 | 445 | @Override 446 | public Agent requestAttackTarget(Agent agent) { 447 | return (Agent)request(agent, Request.ATTACK); 448 | // return JSON.decode(result); 449 | } 450 | 451 | 452 | @Override 453 | public void finish(Agent agent) { 454 | send(agent, Request.FINISH); 455 | // send(agent, Request.FINISH); 456 | } 457 | 458 | @Override 459 | public void setGameData(GameData gameData) { 460 | this.gameData = gameData; 461 | } 462 | 463 | 464 | @Override 465 | public void setGameSetting(GameSetting gameSetting) { 466 | this.gameSetting = gameSetting; 467 | } 468 | 469 | 470 | /** 471 | * @return isWaitForClient 472 | */ 473 | public boolean isWaitForClient() { 474 | return isWaitForClient; 475 | } 476 | 477 | /** 478 | * @param isWaitForClient セットする isWaitForClient 479 | */ 480 | public void setWaitForClient(boolean isWaitForClient) { 481 | this.isWaitForClient = isWaitForClient; 482 | } 483 | 484 | @Override 485 | public void close(){ 486 | try { 487 | if(serverSocket != null && !serverSocket.isClosed()){ 488 | serverSocket.close(); 489 | } 490 | } catch (IOException e1) { 491 | e1.printStackTrace(); 492 | } 493 | for(Socket socket:socketAgentMap.keySet()){ 494 | try { 495 | socket.close(); 496 | } catch (IOException e) { 497 | e.printStackTrace(); 498 | } 499 | } 500 | socketAgentMap.clear(); 501 | } 502 | 503 | /** 504 | * @return serverLogger 505 | */ 506 | // public Logger getServerLogger() { 507 | // return serverLogger; 508 | // } 509 | // 510 | // /** 511 | // * @param serverLogger セットする serverLogger 512 | // */ 513 | // public void setServerLogger(Logger serverLogger) { 514 | // this.serverLogger = serverLogger; 515 | // } 516 | 517 | /** 518 | * add server listener 519 | * @param e 520 | * @return 521 | * @see java.util.Set#add(java.lang.Object) 522 | */ 523 | public boolean addServerListener(ServerListener e) { 524 | return serverListenerSet.add(e); 525 | } 526 | 527 | /** 528 | * remove server listener 529 | * @param o 530 | * @return 531 | * @see java.util.Set#remove(java.lang.Object) 532 | */ 533 | public boolean removeServerListener(ServerListener e) { 534 | return serverListenerSet.remove(e); 535 | } 536 | 537 | public String getName(Agent agent) { 538 | return nameMap.get(agent); 539 | } 540 | 541 | /** 542 | * @return timeLimit 543 | */ 544 | public int getTimeLimit() { 545 | return timeLimit; 546 | } 547 | 548 | /** 549 | * @param timeLimit セットする timeLimit 550 | */ 551 | public void setTimeLimit(int timeLimit) { 552 | this.timeLimit = timeLimit; 553 | } 554 | 555 | 556 | } 557 | 558 | 559 | class RequestReadCallable implements Callable { 560 | private final BufferedReader br; 561 | IOException ioException; 562 | RequestReadCallable(BufferedReader br) { 563 | this.br = br; 564 | } 565 | 566 | @Override 567 | public String call() { 568 | try{ 569 | String line = br.readLine(); 570 | return line; 571 | }catch(IOException e){ 572 | ioException = e; 573 | return null; 574 | } 575 | } 576 | 577 | public boolean isSuccess(){ 578 | return ioException == null; 579 | } 580 | 581 | public IOException getIOException(){ 582 | return ioException; 583 | } 584 | } -------------------------------------------------------------------------------- /src/org/aiwolf/server/util/FileGameLogger.java: -------------------------------------------------------------------------------- 1 | package org.aiwolf.server.util; 2 | 3 | import java.io.BufferedWriter; 4 | import java.io.File; 5 | import java.io.FileOutputStream; 6 | import java.io.FileWriter; 7 | import java.io.IOException; 8 | import java.io.OutputStreamWriter; 9 | import java.util.zip.GZIPOutputStream; 10 | 11 | import org.aiwolf.common.net.GameInfo; 12 | import org.aiwolf.common.util.CalendarTools; 13 | 14 | /** 15 | * GameLogger using File 16 | * @author tori 17 | * 18 | */ 19 | public class FileGameLogger implements GameLogger { 20 | 21 | protected File logFile; 22 | protected BufferedWriter bw; 23 | 24 | protected FileGameLogger(){ 25 | 26 | } 27 | 28 | /** 29 | * 30 | * @param logFile 31 | * @throws IOException 32 | */ 33 | public FileGameLogger(String logFile) throws IOException { 34 | this(new File(logFile)); 35 | } 36 | 37 | /** 38 | * 39 | * @param logFile 40 | * @throws IOException 41 | */ 42 | public FileGameLogger(File logFile) throws IOException { 43 | super(); 44 | 45 | if(logFile != null){ 46 | if(logFile.isDirectory()){ 47 | String timeString = CalendarTools.toDateTime(System.currentTimeMillis()).replaceAll("[\\s-/:]", ""); 48 | logFile = new File(logFile.getAbsolutePath()+"/"+timeString+".log"); 49 | } 50 | this.logFile = logFile; 51 | 52 | logFile.getParentFile().mkdirs(); 53 | try{ 54 | if(!logFile.getPath().endsWith(".gz")){ 55 | bw = new BufferedWriter(new FileWriter(logFile)); 56 | } 57 | else{ 58 | bw = new BufferedWriter(new OutputStreamWriter(new GZIPOutputStream(new FileOutputStream(logFile), true))); 59 | } 60 | return; 61 | }catch(IOException e){ 62 | e.printStackTrace(); 63 | System.err.println("Fail to create logfile. Output log to system.out"); 64 | } 65 | } 66 | bw = new BufferedWriter(new OutputStreamWriter(System.out)); 67 | } 68 | 69 | /** 70 | * Save log 71 | * @param text 72 | * @param gameInfo 73 | */ 74 | public void log(String text){ 75 | try{ 76 | bw.append(text); 77 | bw.append("\n"); 78 | }catch(IOException e){ 79 | } 80 | // System.out.println(text); 81 | } 82 | 83 | public void flush(){ 84 | try { 85 | bw.flush(); 86 | } catch (IOException e) { 87 | } 88 | } 89 | 90 | public void close(){ 91 | try { 92 | bw.close(); 93 | } catch (IOException e) { 94 | e.printStackTrace(); 95 | } 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /src/org/aiwolf/server/util/GameLogger.java: -------------------------------------------------------------------------------- 1 | package org.aiwolf.server.util; 2 | 3 | import org.aiwolf.common.net.GameInfo; 4 | 5 | public interface GameLogger { 6 | public void log(String log); 7 | public void flush(); 8 | public void close(); 9 | } 10 | -------------------------------------------------------------------------------- /src/org/aiwolf/server/util/MultiGameLogger.java: -------------------------------------------------------------------------------- 1 | package org.aiwolf.server.util; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | import org.aiwolf.common.net.GameInfo; 7 | 8 | 9 | /** 10 | * 11 | * @author tori 12 | * 13 | */ 14 | public class MultiGameLogger implements GameLogger { 15 | 16 | protected Set gameLoggerSet; 17 | 18 | public MultiGameLogger(){ 19 | gameLoggerSet = new HashSet(); 20 | } 21 | 22 | public MultiGameLogger(GameLogger... loggers){ 23 | gameLoggerSet = new HashSet(); 24 | for(GameLogger gl:loggers){ 25 | gameLoggerSet.add(gl); 26 | } 27 | } 28 | 29 | 30 | public void add(GameLogger gameLogger){ 31 | gameLoggerSet.add(gameLogger); 32 | } 33 | 34 | public void remove(GameLogger gameLogger){ 35 | gameLoggerSet.remove(gameLogger); 36 | } 37 | 38 | 39 | @Override 40 | public void log(String log) { 41 | for(GameLogger gl:gameLoggerSet){ 42 | gl.log(log); 43 | } 44 | 45 | } 46 | 47 | @Override 48 | public void flush() { 49 | for(GameLogger gl:gameLoggerSet){ 50 | gl.flush(); 51 | } 52 | } 53 | 54 | @Override 55 | public void close() { 56 | for(GameLogger gl:gameLoggerSet){ 57 | gl.close(); 58 | } 59 | } 60 | 61 | } 62 | --------------------------------------------------------------------------------