CPD Results

The following document contains the results of PMD's CPD 4.2.5.

Duplications

FileLine
cz\cuni\amis\pogamut\ut2004\tournament\capturetheflag\UT2004CaptureTheFlag.java297
cz\cuni\amis\pogamut\ut2004\tournament\deathmatch\UT2004DeathMatch.java294
		for (Entry<UnrealId, PlayerScore> entry : finalScores.entrySet()) {
			result.getFinalScores().put(bots.getBotId(entry.getKey()), entry.getValue());
		}
		
		for (Entry<IToken, IUT2004AnalyzerObserver> entry : bots.botObservers.entrySet()) {
			if (!(entry.getValue() instanceof UT2004AnalyzerObsStats)) {
				throw new PogamutException("There is an observer of wrong class, expecting UT2004AnalyzerObsStats, got " + entry.getValue().getClass().getSimpleName() + "!", log, this);
			}
			result.getBotObservers().put(entry.getKey(), (UT2004AnalyzerObsStats)entry.getValue());
		}
		
		List<IToken> botIds = config.getAllBotIds();
		for (IToken botId1 : botIds) {
			result.getTotalKills().put(botId1, 0);
			result.getWasKilled().put(botId1, 0);
			result.getSuicides().put(botId1, 0);
			for (IToken botId2 : botIds) {
				result.getKillCounts().put(botId1, botId2, 0);
			}
		}
		
		for (Entry<IToken, UT2004AnalyzerObsStats> entry : result.getBotObservers().entrySet()) {
			IToken botId = entry.getKey();
			UT2004AnalyzerObsStats obs = entry.getValue();
			AgentStats stats = obs.getStats();
			for (Entry<UnrealId, Integer> killed : stats.getKilled().entrySet()) {
				result.getKillCounts().get(botId).put(bots.getBotId(killed.getKey()), killed.getValue());				
			}
			for (Entry<UnrealId, Integer> killedBy : stats.getKilledBy().entrySet()) {
				if (bots.isNativeBot(killedBy.getKey())) {
					result.getKillCounts().get(bots.getBotId(killedBy.getKey())).put(botId, killedBy.getValue());
				}
			}
			result.getSuicides().put(botId, stats.getSuicides());
			result.getKillCounts().put(botId, botId, stats.getSuicides());
		}
		
		for (IToken nativeBotId1 : config.getNativeBots().keySet()) {
			for (IToken nativeBotId2 : config.getNativeBots().keySet()) {
				if (nativeBotId1 == nativeBotId2) continue;
				result.getKillCounts().get(nativeBotId1).put(nativeBotId2, 0);
			}
			result.getSuicides().put(nativeBotId1, 0);
		}
		
		for (IToken botId : botIds) {
			int totalKills = 0;
			int totalKilled = 0;
			for (IToken other : botIds) {
				if (botId == other) continue;
				totalKills += result.getKillCounts().get(botId, other);
				totalKilled += result.getKillCounts().get(other, botId);
			}
			result.getTotalKills().put(botId, totalKills);
			result.getWasKilled().put(botId, totalKilled);
			if (config.isNativeBot(botId)) {
				result.getSuicides().put(botId, result.getFinalScores().get(botId).getDeaths() - totalKilled);
			}
		}
		
		if (winners.size() <= 0) {
			throw new PogamutException("There is no winner, impossible! **puzzled**", log, this);
		} else 
		if (winners.size() == 1) {
			result.setWinnerBot(bots.getBotId(winners.get(0)));
FileLine
cz\cuni\amis\pogamut\ut2004\tournament\capturetheflag\UT2004CaptureTheFlag.java445
cz\cuni\amis\pogamut\ut2004\tournament\deathmatch\UT2004DeathMatch.java418
		File file = new File(outputDirectory.getAbsolutePath() + File.separator + "match-" + config.getMatchId().getToken() + "-bot-scores.csv");
		FilePath.makeDirsToFile(file);
		try {
			Formatter writer = new Formatter(file);
			
			List<IToken> bots = new ArrayList<IToken>(config.getBots().keySet());
			List<IToken> nativeBots = new ArrayList<IToken>(config.getNativeBots().keySet());
			
			Collections.sort(bots, new Comparator<IToken>() {
				@Override
				public int compare(IToken o1, IToken o2) {
					return o1.getToken().compareTo(o2.getToken());
				}				
			});
			Collections.sort(nativeBots, new Comparator<IToken>() {
				@Override
				public int compare(IToken o1, IToken o2) {
					return o1.getToken().compareTo(o2.getToken());
				}				
			});
			result.setBots(bots);
			result.setNativeBots(nativeBots);
			
			writer.format("botId");
			writer.format(";score;kills;killedByOthers;deaths;suicides");
			for (IToken token : config.getAllBotIds()) {
				writer.format(";");
				writer.format(token.getToken());
			}
			
			for (IToken token : config.getAllBotIds()) {
				writer.format("\n");
				writer.format(token.getToken());
				writer.format(";%d", result.getFinalScores().get(token).getScore());
				writer.format(";%d", result.getTotalKills().get(token));
				writer.format(";%d", result.getWasKilled().get(token));
				writer.format(";%d", result.getFinalScores().get(token).getDeaths());
				writer.format(";%d", result.getSuicides().get(token));				
				for (IToken token2 : config.getAllBotIds()) {
					writer.format(";%d", result.getKillCounts().get(token).get(token2));
				}				
			}
			
			try {
				writer.close();
			} catch (Exception e) {			
			}
		} catch (IOException e) {
			throw new PogamutIOException("Failed to write results!", e, log, this);
		}
		
		if (log != null && log.isLoggable(Level.INFO)) {
			log.info(config.getMatchId().getToken() + ": Match scores output into " + file.getAbsolutePath() + ".");
		}
		
	}
	
	@Override
	protected void outputResults(UCCWrapper ucc, UT2004Server server, UT2004Analyzer analyzer, Bots bots, UT2004MatchResult result,	File outputDirectory) {
		if (!(result instanceof UT2004DeathMatchResult)) {
FileLine
cz\cuni\amis\pogamut\ut2004\tournament\capturetheflag\UT2004CaptureTheFlag.java586
cz\cuni\amis\pogamut\ut2004\tournament\deathmatch\UT2004DeathMatch.java567
			try {
				if (log != null && log.isLoggable(Level.INFO)) {
					log.info(config.getMatchId().getToken() + ": Cleaning up...");
				} 
			} catch (Exception e) {				
			}
			
			if (ucc != null) {
				try {
					if (log != null && log.isLoggable(Level.INFO)) {
						log.info(config.getMatchId().getToken() + ": Killing UCC...");
					} 
				} catch (Exception e) {				
				}
				try {
					ucc.stop();
				} catch (Exception e) {					
				}
			}
			if (server != null) {
				try {
					if (log != null && log.isLoggable(Level.INFO)) {
						log.info(config.getMatchId().getToken() + ": Killing UT2004Server...");
					} 
				} catch (Exception e) {				
				}
				try {
					server.kill();
				} catch (Exception e) {					
				}
			}
			if (bots != null) {
				try {
					if (log != null && log.isLoggable(Level.INFO)) {
						log.info(config.getMatchId().getToken() + ": Killing Custom bots...");
					} 
				} catch (Exception e) {				
				}
				for (UT2004BotExecution exec : bots.bots.values()) {
					try {
						exec.stop();					
					} catch (Exception e) {					
					}
				}
				try {
					if (log != null && log.isLoggable(Level.INFO)) {
						log.info(config.getMatchId().getToken() + ": Killing Custom bot observers...");
					} 
				} catch (Exception e) {				
				}
				for (IUT2004AnalyzerObserver obs : bots.botObservers.values()) {
					try {
						obs.kill();
					} catch (Exception e) {						
					}
				}
			}
			if (analyzer != null) {
				try {
					if (log != null && log.isLoggable(Level.INFO)) {
						log.info(config.getMatchId().getToken() + ": Killing UT2004Analyzer...");
					} 
				} catch (Exception e) {				
				}
				try {
					analyzer.kill();
				} catch (Exception e) {					
				}
			}	
			
			try {
				// STEP 10
				restoreGB2004IniBackup();
			} catch (Exception e) {				
			}
			
			try {
				if (log != null && log.isLoggable(Level.WARNING)) {
					if (exception) {
						log.warning(config.getMatchId().getToken() + ": Cleaned up, MATCH FAILED!");
					} else { 
						log.warning(config.getMatchId().getToken() + ": Cleaned up, match finished successfully.");
					}
				} 
			} catch (Exception e) {				
			}
			try {
				closeLogger();
			} catch (Exception e) {
				
			}
		}
		
	}

}
FileLine
cz\cuni\amis\pogamut\ut2004\tournament\capturetheflag\UT2004CaptureTheFlagResult.java50
cz\cuni\amis\pogamut\ut2004\tournament\deathmatch\UT2004DeathMatchResult.java48
		super(winnerBot);
	}

	/**
	 * Returns list with custom bots (run by Pogamut platform).
	 * @return
	 */
	public List<IToken> getBots() {
		return bots;
	}

	/**
	 * List with custom bots (run by Pogamut platform).
	 * @param bots
	 */
	public void setBots(List<IToken> bots) {
		this.bots = bots;
	}

	/**
	 * Returns list with native bots (bots from UT2004 itself).
	 * @return
	 */
	public List<IToken> getNativeBots() {
		return nativeBots;
	}

	/**
	 * List with native bots (bots from UT2004 itself).
	 * @param nativeBots
	 */
	public void setNativeBots(List<IToken> nativeBots) {
		this.nativeBots = nativeBots;
	}
	
	/**
	 * Returns list of all bot (custom + native) ids.
	 * @return
	 */
	public List<IToken> getAllBots() {
		List<IToken> all = new ArrayList<IToken>(this.bots);
		all.addAll(this.nativeBots);
		return all;
	}

	/**
	 * When the match has ended (in seconds). I.e., how long was the match.
	 */
	public double getMatchTimeEnd() {
		return matchTimeEnd;
	}

	/**
	 * When the match has ended (in seconds). I.e., how long was the match.
	 */
	public void setMatchTimeEnd(double matchTimeEnd) {
		this.matchTimeEnd = matchTimeEnd;
	}

	/**
	 * Final scores of bots.
	 * @return
	 */
	public Map<IToken, PlayerScore> getFinalScores() {
		return finalScores;
	}

	/**
	 * Final scores of bots.
	 * @return
	 */
	public void setFinalScores(Map<IToken, PlayerScore> finalScores) {
		this.finalScores = finalScores;
	}

	/**
	 * Who -&gt; killed Whom -&gt; How many times, i.e., map.get(killerId).get(victimId) == how many time killer killed the victim.
	 * @return
	 */
	public HashMapMap<IToken, IToken, Integer> getKillCounts() {
		return killCounts;
	}

	/**
	 * Who -&gt; killed Whom -&gt; How many times, i.e., map.get(killerId).get(victimId) == how many time killer killed the victim.
	 * @return
	 */
	public void setKillCounts(HashMapMap<IToken, IToken, Integer> killCounts) {
		this.killCounts = killCounts;
	}
	
	
	/**
	 * How many times one bot killed another bot.
	 * @return
	 */
	public Map<IToken, Integer> getTotalKills() {
		return totalKills;
	}

	/**
	 * How many times one bot killed another bot.
	 * @return
	 */
	public void setTotalKills(Map<IToken, Integer> totalKills) {
		this.totalKills = totalKills;
	}
	
	/**
	 * How many times some bot was killed by ANOTHER bot (== without suicides).
	 * @return
	 */
	public Map<IToken, Integer> getWasKilled() {
		return wasKilled;
	}

	/**
	 * How many times some bot was killed by ANOTHER bot (== without suicides).
	 * @return
	 */
	public void setWasKilled(Map<IToken, Integer> wasKilled) {
		this.wasKilled = wasKilled;
	}

	/**
	 * How many times the bot (key == botId) has commit suicide.
	 * @return
	 */
	public Map<IToken, Integer> getSuicides() {
		return suicides;
	}

	/**
	 * How many times the bot (key == botId) has commit suicide.
	 * @param suicides
	 */
	public void setSuicides(Map<IToken, Integer> suicides) {
		this.suicides = suicides;
	}

	/**
	 * Map with observers (custom bots only!) containing detailed statistics about respective bots.
	 * @return
	 */
	public Map<IToken, UT2004AnalyzerObsStats> getBotObservers() {
		return botObservers;
	}

	/**
	 * Map with observers (custom bots only!) containing detailed statistics about respective bots.
	 * @param botObservers
	 */
	public void setBotObservers(Map<IToken, UT2004AnalyzerObsStats> botObservers) {
		this.botObservers = botObservers;
	}
FileLine
cz\cuni\amis\pogamut\ut2004\tournament\capturetheflag\UT2004CaptureTheFlag.java107
cz\cuni\amis\pogamut\ut2004\tournament\deathmatch\UT2004DeathMatch.java98
			server.getWorldView().addEventListener(PlayerScore.class, scoresListener);
			
			for (UT2004BotConfig botConfig : config.getBots().values()) {
				FlagListener<Boolean> obs = new FlagListener<Boolean>() {
					@Override
					public void flagChanged(Boolean changedValue) {
						if (!changedValue) {
							// bot has died out
							oneOfBotsDiedOut.set(true);
							waitLatch.countDown();
						}
					}
				};
				
				bots.bots.get(botConfig.getBotId()).getRunning().addListener(obs);
				customBotObservers.put(botConfig.getBotId(), obs);
				if (!bots.bots.get(botConfig.getBotId()).getRunning().getFlag()) {
					// bot has died out
					oneOfBotsDiedOut.set(true);
					waitLatch.countDown();
					throw new PogamutException("One of custom bots died out from the start, failure!", log, this);
				}			
			}
			
			serverObs = new FlagListener<IAgentState>() {
	
				@Override
				public void flagChanged(IAgentState changedValue) {					
					if (changedValue instanceof IAgentStateDown) {
						// server has died out ... consider match to be over...
						serverDiedOut.set(true);
						waitLatch.countDown();
					}
				}
				
			};
			
			server.getState().addListener(serverObs);
FileLine
cz\cuni\amis\pogamut\ut2004\tournament\capturetheflag\UT2004CaptureTheFlag.java591
cz\cuni\amis\pogamut\ut2004\tournament\match\UT2004Match.java1124
		}
		
		if (ucc != null) {
			try {
				if (log != null && log.isLoggable(Level.INFO)) {
					log.info(config.getMatchId().getToken() + ": Killing UCC...");
				} 
			} catch (Exception e) {				
			}
			try {
				ucc.stop();
			} catch (Exception e) {					
			}
		}
		if (server != null) {
			try {
				if (log != null && log.isLoggable(Level.INFO)) {
					log.info(config.getMatchId().getToken() + ": Killing UT2004Server...");
				} 
			} catch (Exception e) {				
			}
			try {
				server.kill();
			} catch (Exception e) {					
			}
		}
		if (bots != null) {
			try {
				if (log != null && log.isLoggable(Level.INFO)) {
					log.info(config.getMatchId().getToken() + ": Killing Custom bots...");
				} 
			} catch (Exception e) {				
			}
FileLine
cz\cuni\amis\pogamut\ut2004\tournament\capturetheflag\UT2004CaptureTheFlag.java186
cz\cuni\amis\pogamut\ut2004\tournament\deathmatch\UT2004DeathMatch.java169
			getConfig().setFragLimit(targetFragCount); 
			
			// WHAT HAS HAPPENED?
			if (oneOfBotsDiedOut.get()) {
				// check whether the server is down as well... but let GB2004 to process it
				try {
					Thread.sleep(5000);
				} catch (InterruptedException e) {
					throw new PogamutInterruptedException("Interrupted while giving GB2004 time to tear down its connection.", log, this);
				}
				try {
					server.getAct().act(new StartPlayers());
				} catch (Exception e) {
					// YEP, server is down
					serverDiedOut.set(true);
				}
				if (!serverDiedOut.get()) {
					// NO SERVER IS STILL RUNNING
					log.warning("ONE OF BOTS HAS DIED OUT, BUT SERVER IS STILL RUNNING ... POSSIBLE MATCH FAILURE!");
				}
			}
			if (!serverDiedOut.get() && server.inState(IAgentStateUp.class)) {
				// Server is still running? ... This will likely to always happen as frag limit is targetFragCount+10 !!! 
				// Kill it...
				server.kill();
			}
			// server is DEAD -> assume that the match has ended
			
			// KILL UCC TO ENSURE NOTHING WILL CHANGE AFTER THAT
			if (ucc != null) {
				try {
					if (log != null && log.isLoggable(Level.INFO)) {
						log.info(config.getMatchId().getToken() + ": Killing UCC...");
					} 
				} catch (Exception e) {				
				}
				try {
					ucc.stop();
				} catch (Exception e) {					
				}
			}
			
			List<UnrealId> winners = new ArrayList<UnrealId>(1);
FileLine
cz\cuni\amis\pogamut\ut2004\tournament\match\UT2004Match.java593
cz\cuni\amis\pogamut\ut2004\tournament\match\UT2004Match.java735
					bots.nativeUnrealId2BotId.put(player.getId(), connecting.get());
					
					latch.get().countDown();
				}
				@Override
				public void preRemoveEvent(Collection<Player> toBeRemoved, Collection<Player> whereToRemove) {
					if (toBeRemoved.size() == 0) return;
					if (log != null && log.isLoggable(Level.WARNING)) {
						StringBuffer sb = new StringBuffer();
						sb.append(config.getMatchId().getToken() + ": Bot(s) removed from GB2004!!!");
						boolean first = true;
						for (Player plr : toBeRemoved) {
							if (first) first = false;
							else sb.append(", ");
							sb.append("Bot[unrealId=" + plr.getId().getStringId() + ", name=" + plr.getName() + "]");
						}
						log.warning(sb.toString());
					}
					throw new PogamutException("(NativeBot connecting) There can't be any 'removes' at this stage.", log, this);
FileLine
cz\cuni\amis\pogamut\ut2004\tournament\capturetheflag\UT2004CaptureTheFlag.java53
cz\cuni\amis\pogamut\ut2004\tournament\deathmatch\UT2004DeathMatch.java55
	}

	@Override
	protected UT2004MatchResult waitMatchFinish(UCCWrapper ucc, UT2004Server server, UT2004Analyzer analyzer, Bots bots, long timeoutInMillis) {
		// usually the GB2004 dies out whenever match ends -> just wait till server does not fail + timeout + observe bots
		
		if (log != null && log.isLoggable(Level.WARNING)) {
			log.warning(config.getMatchId().getToken() + ": Waiting for the match to finish...");
		}
		
		if (config.getTimeLimit() * 60 * 1000 + 5 * 60 * 1000 > timeoutInMillis) {
			timeoutInMillis = config.getTimeLimit() * 60 * 1000 + 5 * 60 * 1000; // give additional 5 minutes to UT2004 to restart GB2004
		}
		
		Map<IToken, FlagListener<Boolean>> customBotObservers = new HashMap<IToken, FlagListener<Boolean>>(config.getBots().size());
		FlagListener<IAgentState> serverObs = null;
		FlagListener<Boolean> uccObs = null;
		IWorldEventListener<PlayerScore> scoresListener = null;
FileLine
cz\cuni\amis\pogamut\ut2004\tournament\capturetheflag\UT2004CaptureTheFlag.java559
cz\cuni\amis\pogamut\ut2004\tournament\deathmatch\UT2004DeathMatch.java538
			UT2004DeathMatchResult result = (UT2004DeathMatchResult) waitMatchFinish(ucc, server, analyzer, bots, config.getTimeLimit() * 1000 + 60 * 1000);
			
			// STEP 11
			copyReplay(ucc, recordFileName, getOutputPath());

			// STEP 12
			outputResults(ucc, server, analyzer, bots, result, getOutputPath());
			
			// STEP 13
			shutdownAll(ucc, server, analyzer, bots);
			
			ucc = null;
			server = null;
			analyzer = null;
			bots = null;
			
			// WE'RE DONE! ... all that is left is a possible cleanup...
			return result;
			
		} catch (Exception e) {
			if (log != null && log.isLoggable(Level.SEVERE)) {
				log.severe(ExceptionToString.process(config.getMatchId().getToken() + ": EXCEPTION!", e));
			}
			exception = true;
			if (e instanceof PogamutException) throw (PogamutException)e;
			throw new PogamutException(e, log, this);
		} finally {	
FileLine
cz\cuni\amis\pogamut\ut2004\tournament\match\UT2004Match.java564
cz\cuni\amis\pogamut\ut2004\tournament\match\UT2004Match.java706
		}
		
		//
		// CONNECT ALL NATIVE BOTS
		//
		{
			final AdaptableProvider<IToken> connecting = new AdaptableProvider<IToken>(null);
			final AdaptableProvider<CountDownLatch> latch = new AdaptableProvider<CountDownLatch>(null);
			
			CollectionEventListener<Player> playerListener = new CollectionEventListener<Player>() {
				@Override
				public void postAddEvent(Collection<Player> alreadyAdded,Collection<Player> whereWereAdded) {				
				}
				@Override
				public void postRemoveEvent(Collection<Player> alreadyAdded,Collection<Player> whereWereRemoved) {
					if (alreadyAdded.size() == 0) return;
				}
				@Override
				public void preAddEvent(Collection<Player> toBeAdded, Collection<Player> whereToAdd) {
					if (toBeAdded.size() == 0) return;
					if (toBeAdded.size() > 1) {						
						throw new PogamutException("(NativeBot connecting) More than one player connected at a single time? We're not doing this, something has failed, or someone has hacked into the game.", log, this);
FileLine
cz\cuni\amis\pogamut\ut2004\tournament\capturetheflag\UT2004CaptureTheFlagResult.java15
cz\cuni\amis\pogamut\ut2004\tournament\deathmatch\UT2004DeathMatchResult.java15
public class UT2004DeathMatchResult extends UT2004IndividualMatchResult {
	
	private List<IToken> bots = new ArrayList<IToken>();
	
	private List<IToken> nativeBots = new ArrayList<IToken>();
	
	private Map<IToken, PlayerScore> finalScores = new HashMap<IToken, PlayerScore>();
	
	private Map<IToken, Integer> totalKills = new HashMap<IToken, Integer>();
	
	private Map<IToken, Integer> wasKilled = new HashMap<IToken, Integer>();
	
	private HashMapMap<IToken, IToken, Integer> killCounts = new HashMapMap<IToken, IToken, Integer>(); 
	
	private Map<IToken, Integer> suicides = new HashMap<IToken, Integer>();
	
	private Map<IToken, UT2004AnalyzerObsStats> botObservers = new HashMap<IToken, UT2004AnalyzerObsStats>();
FileLine
cz\cuni\amis\pogamut\ut2004\tournament\capturetheflag\UT2004CaptureTheFlag.java155
cz\cuni\amis\pogamut\ut2004\tournament\deathmatch\UT2004DeathMatch.java135
			server.getState().addListener(serverObs);
			
			if (server.notInState(IAgentStateUp.class)) {
				// server has died out ... consider match to be over...
				serverDiedOut.set(true);
				waitLatch.countDown();
				throw new PogamutException("Server is dead from the start, failure!", log, this);
			}
			
			uccObs = new FlagListener<Boolean>() {

				@Override
				public void flagChanged(Boolean changedValue) {
					if (changedValue) {
						// GAME IS ENDING!
						// Consider match to be over...
						serverDiedOut.set(true);
						waitLatch.countDown();
					}
				}
				
			};
			
			ucc.getGameEnding().addListener(uccObs);
			
			waitLatch.await(timeoutInMillis, TimeUnit.MILLISECONDS);
			if (waitLatch.getCount() > 0) {
				// TIMEOUT!
				throw new PogamutException("TIMEOUT! The match did not end in " + (timeoutInMillis / 1000) + " secs.", log, this);
			}
			
			bots.matchEnd = System.currentTimeMillis();
FileLine
cz\cuni\amis\pogamut\ut2004\tournament\deathmatch\UT2004DeathMatchTournamentConfig.java257
cz\cuni\amis\pogamut\ut2004\tournament\match\UT2004MatchConfig.java232
	public UT2004MatchConfig addNativeBot(UT2004NativeBotConfig... bots) {
		if (bots == null) return this;
		for (UT2004NativeBotConfig bot : bots) {
			NullCheck.check(bot.getBotId(), "bot.getBotId()");
			if (this.bots.containsKey(bot.getBotId())) {
				throw new PogamutException("Can't add another bot under the id " + bot.getBotId().getToken() + ", there is already an existing custom bot configuration under this ID. If you need to override it, use setBot().", this);
			}
			if (this.nativeBots.containsKey(bot.getBotId())) {
				throw new PogamutException("Can't add another bot under the id " + bot.getBotId().getToken() + ", there is already an existing native bot configuration under this ID. If you need to override it, use setNativeBot().", this);
			}
			this.nativeBots.put(bot.getBotId(), bot);
		}
		return this;
	}
	
	/**
	 * Sets native bot configuration into the object, does not checks whether there is BotId clash.
	 * @param bots
	 * @return
	 */
	public UT2004MatchConfig setNativeBot(UT2004NativeBotConfig... bots) {
FileLine
cz\cuni\amis\pogamut\ut2004\tournament\deathmatch\UT2004DeathMatchTournamentConfig.java219
cz\cuni\amis\pogamut\ut2004\tournament\match\UT2004MatchConfig.java194
	public UT2004MatchConfig addBot(UT2004BotConfig... bots) {
		if (bots == null) return this;
		for (UT2004BotConfig bot : bots) {
			NullCheck.check(bot.getBotId(), "bot.getBotId()");
			if (this.bots.containsKey(bot.getBotId())) {
				throw new PogamutException("Can't add another bot under the id " + bot.getBotId().getToken() + ", there is already an existing custom bot configuration under this ID. If you need to override it, use setBot().", this);
			}
			if (this.nativeBots.containsKey(bot.getBotId())) {
				throw new PogamutException("Can't add another bot under the id " + bot.getBotId().getToken() + ", there is already an existing native bot configuration under this ID. If you need to override it, use setBot().", this);
			}
			this.bots.put(bot.getBotId(), bot);
		}
		return this;
	}
	
	/**
	 * Sets bot configuration into the object, does not checks whether there is BotId clash.
	 * 
	 * @param bots
	 * @return
	 */
	public UT2004MatchConfig setBot(UT2004BotConfig... bots) {
FileLine
cz\cuni\amis\pogamut\ut2004\tournament\deathmatch\UT2004DeathMatch.java215
cz\cuni\amis\pogamut\ut2004\tournament\deathmatch\UT2004DeathMatch.java229
			for (Entry<UnrealId, IToken> entry : bots.nativeUnrealId2BotId.entrySet()) {
				PlayerScore playerScore = scores.get(entry.getKey());
				if (playerScore == null) {
					throw new PogamutException("Can't resolve the match result. One of the bot with botId '" + entry.getValue().getToken() + "' and corresponding unrealId '" + entry.getKey().getStringId() + "' has no score entry!", log, this);
				}
				if (playerScore.getScore() == maxFrags) {
					winners.add(entry.getKey());
				} else
				if (playerScore.getScore() > maxFrags) {
					maxFrags = playerScore.getScore();
					winners.clear();
					winners.add(entry.getKey());
				}
			}
FileLine
cz\cuni\amis\pogamut\ut2004\tournament\deathmatch\UT2004DeathMatchTournamentConfig.java277
cz\cuni\amis\pogamut\ut2004\tournament\match\UT2004MatchConfig.java252
	public UT2004MatchConfig setNativeBot(UT2004NativeBotConfig... bots) {
		if (bots == null) return this;
		for (UT2004NativeBotConfig bot : bots) {
			NullCheck.check(bot.getBotId(), "bot.getBotId()");
			if (this.bots.containsKey(bot.getBotId())) {
				throw new PogamutException("Can't add another bot under the id " + bot.getBotId().getToken() + ", there is already an existing custom bot configuration under this ID. If you need to override it, use setBot().", this);
			}
			this.nativeBots.put(bot.getBotId(), bot);
		}
		return this;
	}
	
	public boolean isNativeBot(IToken botId) {
		return nativeBots.containsKey(botId);
	}
	
	public boolean isHumanLikeLogEnabled() {