View Javadoc

1   package cz.cuni.amis.pogamut.ut2004.tournament;
2   
3   import java.io.File;
4   import java.io.IOException;
5   import java.text.SimpleDateFormat;
6   import java.util.Date;
7   import java.util.Iterator;
8   import java.util.List;
9   import java.util.logging.Level;
10  import java.util.regex.Pattern;
11  
12  import org.apache.commons.io.FileUtils;
13  
14  import com.martiansoftware.jsap.FlaggedOption;
15  import com.martiansoftware.jsap.JSAP;
16  import com.martiansoftware.jsap.JSAPException;
17  import com.martiansoftware.jsap.JSAPResult;
18  import com.martiansoftware.jsap.Switch;
19  
20  import cz.cuni.amis.pogamut.base.utils.logging.LogCategory;
21  import cz.cuni.amis.pogamut.ut2004.tournament.deathmatch.UT2004DeathMatch;
22  import cz.cuni.amis.pogamut.ut2004.tournament.deathmatch.UT2004DeathMatch1v1;
23  import cz.cuni.amis.pogamut.ut2004.tournament.deathmatch.UT2004DeathMatchConfig;
24  import cz.cuni.amis.pogamut.ut2004.tournament.match.UT2004BotConfig;
25  
26  public class UT2004DeathMatchConsole {
27  	
28  	private static final char ARG_UT2004_HOME_DIR_SHORT = 'u';
29  	
30  	private static final String ARG_UT2004_HOME_DIR_LONG = "ut2004-home-dir";
31  	
32  	private static final char ARG_BOT_JARs_SHORT = 'a';
33  	
34  	private static final String ARG_BOT_JARs_LONG = "bot-jars";
35  	
36  	private static final char ARG_BOT_NAMEs_SHORT = 'b';
37  	
38  	private static final String ARG_BOT_NAMEs_LONG = "bot-names";
39  	
40  	private static final char ARG_MAP_NAME_SHORT = 'm';
41  	
42  	private static final String ARG_MAP_NAME_LONG = "map-name";
43  	
44  	private static final char ARG_MATCH_NAME_SHORT = 'n';
45  	
46  	private static final String ARG_MATCH_NAME_LONG = "match-name";
47  	
48  	private static final char ARG_RESULT_DIR_SHORT = 'r';
49  	
50  	private static final String ARG_RESULT_DIR_LONG = "result-directory";
51  	
52  	private static final char ARG_SERVER_NAME_SHORT = 's';
53  	
54  	private static final String ARG_SERVER_NAME_LONG = "server-name";
55  	
56  	private static final char ARG_FRAG_LIMIT_SHORT = 'f';
57  	
58  	private static final String ARG_FRAG_LIMIT_LONG = "frag-limit";
59  	
60  	private static final char ARG_TIMEOUT_MINUTES_SHORT = 't';
61  	
62  	private static final String ARG_TIMEOUT_MINUTES_LONG = "timeout-minutes";
63  	
64  	private static final char ARG_HUMAN_LIKE_LOG_SHORT = 'h';
65  	
66  	private static final String ARG_HUMAN_LIKE_LOG_LONG = "human-like-log";
67  	
68  	private static final char ARG_UT2004_PORT_SHORT = 'p';
69  	
70  	private static final String ARG_UT2004_PORT_LONG = "ut2004-port";
71  
72  	private static JSAP jsap;
73  
74  	private static boolean headerOutput = false;
75  
76  	private static String ut2004HomeDir;
77  
78  	private static String botJars;
79  	
80  	private static String[] botJarsSeparated;
81  
82  	private static String botNames;
83  	
84  	private static String[] botNamesSeparated;
85  	
86  	private static File[] botJarFiles;
87  	
88  	private static String map;
89  
90  	private static String serverName;
91  
92  	private static String resultDir;
93  
94  	private static String matchName;
95  	
96  	private static int fragLimit;
97  	
98  	private static int timeoutMinutes;
99  
100 	private static JSAPResult config;
101 
102 	private static File ut2004HomeDirFile;
103 
104 	private static File bot1JarFile;
105 
106 	private static File bot2JarFile;
107 
108 	private static File mapsDirFile;
109 
110 	private static File mapFile;
111 
112 	private static File ut2004SystemDirFile;
113 
114 	private static File ut2004IniFile;
115 
116 	private static boolean humanLikeLog;
117 
118 	private static int ut2004Port;	
119 	
120 	private static void fail(String errorMessage) {
121 		fail(errorMessage, null);
122 	}
123 
124 	private static void fail(String errorMessage, Throwable e) {
125 		header();
126 		System.out.println("ERROR: " + errorMessage);
127 		System.out.println();
128 		if (e != null) {
129 			e.printStackTrace();
130 			System.out.println("");
131 		}		
132         System.out.println("Usage: java -jar ut2004-tournament-1v1....jar ");
133         System.out.println("                " + jsap.getUsage());
134         System.out.println();
135         System.out.println(jsap.getHelp());
136         System.out.println();
137         throw new RuntimeException("FAILURE: " + errorMessage);
138 	}
139 
140 	private static void header() {
141 		if (headerOutput) return;
142 		System.out.println();
143 		System.out.println("==================================");
144 		System.out.println("Pogamut UT2004 DeathMatch Executor");
145 		System.out.println("==================================");
146 		System.out.println();
147 		headerOutput = true;
148 	}
149 	
150 	private static void initJSAP() throws JSAPException {
151 		jsap = new JSAP();
152 		    	
153     	FlaggedOption opt1 = new FlaggedOption(ARG_UT2004_HOME_DIR_LONG)
154         	.setStringParser(JSAP.STRING_PARSER)
155         	.setRequired(true) 
156         	.setShortFlag(ARG_UT2004_HOME_DIR_SHORT)
157         	.setLongFlag(ARG_UT2004_HOME_DIR_LONG);    
158         opt1.setHelp("UT2004 home directory containing GameBots2004 (System/GameBots2004.u) present.");
159         
160         jsap.registerParameter(opt1);
161         
162         FlaggedOption opt2 = new FlaggedOption(ARG_BOT_JARs_LONG)
163 	    	.setStringParser(JSAP.STRING_PARSER)
164 	    	.setRequired(true) 
165 	    	.setShortFlag(ARG_BOT_JARs_SHORT)
166 	    	.setLongFlag(ARG_BOT_JARs_LONG);    
167 	    opt2.setHelp("Semicolon separated PATH/TO/JAR/file1;PATH/TO/JAR/file2 containing executable jars of bots.");
168 	
169 	    jsap.registerParameter(opt2);
170 	    
171 	    FlaggedOption opt3 = new FlaggedOption(ARG_BOT_NAMEs_LONG)
172 	    	.setStringParser(JSAP.STRING_PARSER)
173 	    	.setRequired(true) 
174 	    	.setShortFlag(ARG_BOT_NAMEs_SHORT)
175 	    	.setLongFlag(ARG_BOT_NAMEs_LONG);    
176 	    opt3.setHelp("Semicolon separated name1;name2;name3 (ids) that should be given to bots.");
177 	
178 	    jsap.registerParameter(opt3);
179     
180 	    FlaggedOption opt6 = new FlaggedOption(ARG_MAP_NAME_LONG)
181 	    	.setStringParser(JSAP.STRING_PARSER)
182 	    	.setRequired(true) 
183 	    	.setShortFlag(ARG_MAP_NAME_SHORT)
184 	    	.setLongFlag(ARG_MAP_NAME_LONG);    
185 	    opt6.setHelp("Map where the game should be played (e.g. DM-1on1-Albatross).");
186 	
187 	    jsap.registerParameter(opt6);
188         
189 	    FlaggedOption opt7 = new FlaggedOption(ARG_MATCH_NAME_LONG)
190 	    	.setStringParser(JSAP.STRING_PARSER)
191 	    	.setRequired(false) 
192 	    	.setShortFlag(ARG_MATCH_NAME_SHORT)
193 	    	.setLongFlag(ARG_MATCH_NAME_LONG)
194 	    	.setDefault("DMMatch1v1");    
195 	    opt7.setHelp("Name of the match == output folder for the results.");
196 	
197 	    jsap.registerParameter(opt7);
198 	    
199 	    FlaggedOption opt8 = new FlaggedOption(ARG_RESULT_DIR_LONG)
200 	    	.setStringParser(JSAP.STRING_PARSER)
201 	    	.setRequired(false) 
202 	    	.setShortFlag(ARG_RESULT_DIR_SHORT)
203 	    	.setLongFlag(ARG_RESULT_DIR_LONG)
204 	    	.setDefault(".");
205 	    opt8.setHelp("PATH/TO/directory where to output results (does not need to exist).");
206 	
207 	    jsap.registerParameter(opt8);
208 	    
209 	    FlaggedOption opt9 = new FlaggedOption(ARG_SERVER_NAME_LONG)
210 			.setStringParser(JSAP.STRING_PARSER)
211 			.setRequired(false) 
212 			.setShortFlag(ARG_SERVER_NAME_SHORT)
213 			.setLongFlag(ARG_SERVER_NAME_LONG)
214 			.setDefault("DMMatch1v1");
215 		opt9.setHelp("Server name that should be advertised via LAN.");
216 		
217 		jsap.registerParameter(opt9);
218 		
219 		FlaggedOption opt10 = new FlaggedOption(ARG_FRAG_LIMIT_LONG)
220 			.setStringParser(JSAP.INTEGER_PARSER)
221 			.setRequired(false) 
222 			.setShortFlag(ARG_FRAG_LIMIT_SHORT)
223 			.setLongFlag(ARG_FRAG_LIMIT_LONG)
224 			.setDefault("20");
225 		opt10.setHelp("Frag limit for the match.");
226 		
227 		jsap.registerParameter(opt10);
228 		
229 		FlaggedOption opt11 = new FlaggedOption(ARG_TIMEOUT_MINUTES_LONG)
230 			.setStringParser(JSAP.INTEGER_PARSER)
231 			.setRequired(false) 
232 			.setShortFlag(ARG_TIMEOUT_MINUTES_SHORT)
233 			.setLongFlag(ARG_TIMEOUT_MINUTES_LONG)
234 			.setDefault("20");
235 		opt11.setHelp("Match timeout in minutes.");
236 		
237 		jsap.registerParameter(opt11);
238 		
239 		Switch opt12 = new Switch(ARG_HUMAN_LIKE_LOG_LONG)
240 			.setShortFlag(ARG_HUMAN_LIKE_LOG_SHORT)
241 			.setLongFlag(ARG_HUMAN_LIKE_LOG_LONG)
242 			.setDefault("false");
243 		opt12.setHelp("Whether to produce log for 'HumanLike Project' analysis.");
244 		
245 		jsap.registerParameter(opt12);
246 		
247 		FlaggedOption opt13 = new FlaggedOption(ARG_UT2004_PORT_LONG)
248 			.setStringParser(JSAP.INTEGER_PARSER)
249 			.setRequired(false) 
250 			.setShortFlag(ARG_UT2004_PORT_SHORT)
251 			.setLongFlag(ARG_UT2004_PORT_LONG)
252 			.setDefault("7777");
253 		opt13.setHelp("UT2004 port for the dedicated server (1-32000).");
254 		
255 		jsap.registerParameter(opt13);
256 	}
257 
258 	private static void readConfig(String[] args) {
259 		System.out.println("Parsing command arguments.");
260 		
261 		try {
262 	    	config = jsap.parse(args);
263 	    } catch (Exception e) {
264 	    	fail(e.getMessage());
265 	    	System.out.println("");
266 	    	e.printStackTrace();
267 	    	throw new RuntimeException("FAILURE!");
268 	    }
269 		
270 		if (!config.success()) {
271 			String error = "Invalid arguments specified.";
272 			Iterator errorIter = config.getErrorMessageIterator();
273 			if (!errorIter.hasNext()) {
274 				error += "\n-- No details given.";
275 			} else {
276 				while (errorIter.hasNext()) {
277 					error += "\n-- " + errorIter.next();
278 				}
279 			}
280 			fail(error);
281     	}
282 		
283 		ut2004HomeDir = config.getString(ARG_UT2004_HOME_DIR_LONG);
284 		botJars = config.getString(ARG_BOT_JARs_LONG);
285 	    botJarsSeparated = botJars == null ? null : botJars.split(";");
286 	    botNames = config.getString(ARG_BOT_NAMEs_LONG);
287 	    botNamesSeparated = botNames == null ? null : botNames.split(";");
288 	    map = config.getString(ARG_MAP_NAME_LONG);
289 	    serverName = config.getString(ARG_SERVER_NAME_LONG);
290 	    resultDir = config.getString(ARG_RESULT_DIR_LONG);
291 	    matchName = config.getString(ARG_MATCH_NAME_LONG);
292 	    fragLimit = config.getInt(ARG_FRAG_LIMIT_LONG);
293 	    timeoutMinutes = config.getInt(ARG_TIMEOUT_MINUTES_LONG);
294 	    humanLikeLog = config.getBoolean(ARG_HUMAN_LIKE_LOG_LONG);
295 	    ut2004Port = config.getInt(ARG_UT2004_PORT_LONG);
296 	}
297 	
298 	private static void sanityChecks() {
299 		System.out.println("Sanity checks...");
300 		
301 	    ut2004HomeDirFile = new File(ut2004HomeDir);
302 	    if (!ut2004HomeDirFile.exists() || !ut2004HomeDirFile.isDirectory()) {
303 	    	fail("UT2004 directory was not found at '" + ut2004HomeDirFile.getAbsolutePath() + "', path resolved from configuration read as '" + ut2004HomeDir + "'.");
304 	    }
305 	    System.out.println("-- UT2004 directory found at '" + ut2004HomeDirFile.getAbsolutePath() + "'");
306 	    
307 	    ut2004SystemDirFile = new File(ut2004HomeDirFile, "System");
308 	    if (!ut2004SystemDirFile.exists() || !ut2004SystemDirFile.isDirectory()) {
309 	    	fail("UT2004/System directory was not found at '" + ut2004SystemDirFile.getAbsolutePath() + "', invalid UT2004 installation.");
310 	    }
311 	    System.out.println("-- UT2004/System directory found at '" + ut2004SystemDirFile.getAbsolutePath() + "'");
312 	    
313 	    ut2004IniFile = new File(ut2004SystemDirFile, "UT2004.ini");
314 	    if (!ut2004IniFile.exists() || !ut2004IniFile.isFile()) {
315 	    	fail("UT2004/System/UT2004.ini file was not found at '" + ut2004IniFile.getAbsolutePath() + "', invalid UT2004 installation.");
316 	    }
317 	    System.out.println("-- UT2004/System/UT2004.ini file found at '" + ut2004IniFile.getAbsolutePath() + "'");
318 	    
319 	    if (botJarsSeparated == null) {
320 			fail("Bot jar(s) was/were not specified correctly.");
321 		}
322 		
323 		if (botNamesSeparated == null) {
324 			fail("Bot name(s) was/were not specified correctly.");
325 		}
326 		
327 		if (botJarsSeparated.length != botNamesSeparated.length) {
328 			fail("Bot jar(s) and name(s) numbers mismatch. I've parsed " + botJarsSeparated.length + " bot jar files != " + botNamesSeparated.length + " of bot names.");
329 		}
330 		
331 		botJarFiles = new File[botJarsSeparated.length];
332 	    for (int i = 0; i < botJarsSeparated.length; ++i) {
333 	    	botJarFiles[i] = new File(botJarsSeparated[i]);
334 	    	if (!botJarFiles[i].exists() || !botJarFiles[i].isFile()) {
335 		    	fail("Bot" + (i+1) + " jar file was not found at '"+ botJarFiles[i].getAbsolutePath() + "', path resolved from configuration read as '" + botJarsSeparated[i] + "'.");
336 		    }
337 	    	System.out.println("-- Bot" + (i+1) + " jar file found at '" + botJarFiles[i].getAbsolutePath() + "'");
338 	    }
339 	    System.out.println("-- Bot jars ok");
340 	   	
341 	    for (int i = 0; i < botNamesSeparated.length; ++i) {
342 	    	if (botNamesSeparated[i] == null || botNamesSeparated[i].isEmpty()) {
343 	    		fail("Bot " + (i+1) + " invalid name '" + botNamesSeparated[i] +"' specified.");
344 	    	}
345 	    	System.out.println("-- Bot" + (i+1) + " name set as '" + botNamesSeparated[i] + "'");
346 	    }
347 	    System.out.println("-- Bot names ok");
348 	    
349 	    mapsDirFile = new File(ut2004HomeDirFile, "Maps");
350 	    if (!mapsDirFile.exists() || !mapsDirFile.isDirectory()) {
351 	    	fail("UT2004/Maps directory was not found at '" + mapsDirFile.getAbsolutePath() + "', invalid UT2004 installation.");
352 	    }
353 	    System.out.println("-- UT2004/Maps directory found at '" + mapsDirFile.getAbsolutePath() + "'");
354 	    
355 	    mapFile = new File(mapsDirFile, map + ".ut2");
356 	    if (!mapFile.exists() || !mapFile.isFile()) {
357 	    	fail("Specified map '" + map + "' was not found within UT2004/Maps dir at '" + mapFile.getAbsoluteFile() + "', could not execute the match.");
358 	    }
359 	    System.out.println("-- Map '" + map + "' found at '" + mapFile.getAbsolutePath() + "'");
360 	    
361 	    if (matchName == null || matchName.isEmpty()) {
362 	    	fail("Invalid match name '" + matchName + "' specified.");
363 	    }
364 	    System.out.println("-- Match name set as '" + matchName + "'");
365 	    
366 	    if (serverName == null || serverName.isEmpty()) {
367 	    	fail("Invalid server name '" + serverName + "' specified.");
368 	    }
369 	    System.out.println("-- Server name set as '" + serverName + "'");
370 	    
371 	    if (fragLimit < 1) {
372 	    	fail("Invalid frag limit '" + fragLimit +"' specified, must be >= 1.");
373 	    }
374 	    System.out.println("-- Frag limit set as '" + fragLimit + "'");
375 	    
376 	    if (timeoutMinutes < 1) {
377 	    	fail("Invalid time limit '" + timeoutMinutes +"' specified, must be >= 1.");
378 	    }
379 	    System.out.println("-- Timeout set as '" + timeoutMinutes + "' minutes.");
380 	    
381 	    if (ut2004Port < 1 || ut2004Port > 32000) {
382 	    	fail("Invalid UT2004 port specified '" + ut2004Port + "', must be 1 <= port <= 32000.");
383 	    }
384 	    System.out.println("-- UT2004 port set as '" + ut2004Port + "'");
385 
386 	    System.out.println("Sanity checks OK!");
387 	}
388 	
389 	private static void setUT2004Ini() {
390 		Date date = new Date(System.currentTimeMillis());
391 		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
392 		File ut2004IniBackup = new File(ut2004SystemDirFile, "UT2004.ini." + sdf.format(date) + ".bak");
393 		
394 		System.out.println("Backing up '" + ut2004IniFile.getAbsolutePath() + "' into '" + ut2004IniBackup.getAbsolutePath() + "' ...");
395 		try {
396 			FileUtils.copyFile(ut2004IniFile, ut2004IniBackup);
397 		} catch (IOException e) {
398 			throw new RuntimeException("Failed to backup UT2004.ini", e);
399 		}
400 				
401 		System.out.println("Reading '" + ut2004IniFile.getAbsolutePath() + "' ...");
402 		List<String> lines;
403 		try {
404 			lines = FileUtils.readLines(ut2004IniFile);
405 		} catch (IOException e) {
406 			throw new RuntimeException("Failed to read UT2004.ini", e);
407 		}
408 		System.out.println("-- " + lines.size() + " lines read.");
409 		
410 		System.out.println("Searching for UT2004 Port and ServerName ...");
411 		
412 		// 0 -> nothing
413 		// 1 -> section URL
414 		// 2 -> section Engine.GameReplicationInfo
415 		int state = 0;
416 		
417 		Pattern patternSection = Pattern.compile("^\\s*\\[\\s*[^]]*\\s*\\]\\s*$");
418 		Pattern patternSectionURL = Pattern.compile("^\\s*\\[\\s*" + UT2004Ini.Section_URL + "\\s*\\]\\s*$");
419 		Pattern patternSectionEngineGameReplicationInfo = Pattern.compile("^\\s*\\[\\s*" + UT2004Ini.Section_Engine_GameReplicationInfo + "\\s*\\]\\s*$");
420 		Pattern patternPort = Pattern.compile("^\\s*" + UT2004Ini.Key_Port + "\\s*=\\s*.*$");
421 		Pattern patternServerName = Pattern.compile("^\\s*" + UT2004Ini.Key_ServerName + "\\s*=\\s*.*$");
422 		Pattern patternShortName = Pattern.compile("^\\s*" + UT2004Ini.Key_ShortName + "\\s*=\\s*.*$");
423 		
424 		boolean portFound = false;
425 		boolean nameFound = false;
426 		boolean shortNameFound = false;
427 		
428 		for (int lineNum = 0; 
429 				// IF lineNum == lines.size() 
430 				// => perform one more state switch to add possibly missing keys
431 			 lineNum <= lines.size()
432 			    // IF all set
433 				// => break;
434 			 && (!(portFound && nameFound && shortNameFound)); 
435 			++lineNum
436 		) {		
437 						
438 			
439 			// current line probed
440 			String line = lineNum < lines.size() ? lines.get(lineNum).trim() : null;
441 			
442 			// sanity check
443 			if (lineNum < lines.size() && line == null) {
444 				continue;
445 			}
446 			
447 			if (lineNum == lines.size() || patternSection.matcher(line).matches()) {
448 				switch (state) {
449 				case 0:
450 					break;
451 				case 1:
452 					if (!portFound) {
453 						lines.add(lineNum, UT2004Ini.Key_Port + "=" + ut2004Port);
454 						portFound = true;
455 						++lineNum;
456 					}
457 					break;
458 				case 2:
459 					if (!nameFound) {
460 						lines.add(lineNum, UT2004Ini.Key_ServerName + "=" + serverName);
461 						nameFound = true;
462 						++lineNum;
463 					}
464 					if (!shortNameFound) {
465 						lines.add(lineNum, UT2004Ini.Key_ShortName + "=" + serverName);
466 						shortNameFound = true;
467 						++lineNum;
468 					}
469 					break;
470 				}
471 				if (lineNum == lines.size()) {
472 					break;
473 				}
474 				if (line == null) {
475 					continue;
476 				}
477 				if (patternSectionURL.matcher(line).matches()) {
478 					state = 1;					
479 				} else
480 				if (patternSectionEngineGameReplicationInfo.matcher(line).matches()) {
481 					state = 2;
482 				} else {
483 					state = 0;
484 				}
485 				continue;
486 			}
487 			
488 			switch (state) {
489 			case 0: 
490 				continue;
491 			case 1: 
492 				if (!portFound && patternPort.matcher(line).matches()) {
493 					lines.set(lineNum, UT2004Ini.Key_Port + "=" + ut2004Port);
494 					portFound = true;
495 				}
496 				continue;
497 			case 2:
498 				if (!nameFound && patternServerName.matcher(line).matches()) {
499 					lines.set(lineNum, UT2004Ini.Key_ServerName + "=" + serverName);
500 					nameFound = true;
501 				} else
502 				if (!shortNameFound && patternShortName.matcher(line).matches()) {
503 					lines.set(lineNum, UT2004Ini.Key_ShortName + "=" + serverName);
504 					shortNameFound = true;
505 				}
506 				continue;
507 			default:
508 				continue;
509 			}
510 		}
511 		
512 		if (!portFound) {
513 			throw new RuntimeException("Failed to set UT2004 port!");
514 		}
515 		if (!nameFound) {
516 			throw new RuntimeException("Failed to set UT2004 ServerName!");
517 		}
518 		
519 		System.out.println("UT2004 Port and ServerName set.");
520 		System.out.println("Rewriting '" + ut2004IniFile.getAbsolutePath() + "' ...");
521 		try {
522 			FileUtils.writeLines(ut2004IniFile, lines);
523 		} catch (IOException e) {
524 			throw new RuntimeException("Failed to write UT2004.ini", e);
525 		}		
526 		
527 		System.out.println("UT2004 Port and ServerName set.");
528 	}
529 	
530 	private static void executeMatch() {
531 		UT2004DeathMatchConfig config = new UT2004DeathMatchConfig();
532 		
533 		UT2004BotConfig[] botConfigs = new UT2004BotConfig[botJarFiles.length];
534 		for (int i = 0; i < botJarFiles.length; ++i) {
535 			UT2004BotConfig botConfig = new UT2004BotConfig();
536 			botConfig.setBotId(botNamesSeparated[i]);
537 			botConfig.setPathToBotJar(botJarFiles[i].getAbsolutePath());
538 			botConfig.setRedirectStdErr(true);
539 			botConfig.setRedirectStdOut(true);
540 			botConfigs[i] = botConfig;
541 		}
542 		
543 		config.setBot(botConfigs);
544 		config.setOutputDirectory(new File(resultDir));
545 	    config.setMatchId(matchName);
546 	    config.setFragLimit(fragLimit);
547 	    config.setTimeLimit(timeoutMinutes);
548 	    config.setHumanLikeLogEnabled(humanLikeLog);
549 	    
550 	    config.getUccConf().setStartOnUnusedPort(true);
551 	    config.getUccConf().setUnrealHome(ut2004HomeDir);
552 	    config.getUccConf().setGameType("BotDeathMatch");
553 	    config.getUccConf().setMapName(map);
554 	     
555 	    System.out.println("EXECUTING MATCH!");
556 
557 	    LogCategory log = new LogCategory(matchName);
558 	    UT2004DeathMatch match = new UT2004DeathMatch(config, log);
559 	    
560 	    match.getLog().setLevel(Level.INFO);
561 	    match.getLog().addConsoleHandler();
562 	    
563 	    match.run();
564 	}
565 	
566 	public static void main(String[] args) throws JSAPException {
567 //      FOR TESTING		
568 //		args = new String[] {
569 //			"-u",
570 //			"D:\\Games\\UT2004-Devel",
571 //			"-a",
572 //			"D:\\Workspaces\\Pogamut-Trunk\\Main\\PogamutUT2004Examples\\04-HunterBot\\target\\ut2004-04-hunter-bot-3.3.1-SNAPSHOT.one-jar.jar;D:\\Workspaces\\Pogamut-Trunk\\Main\\PogamutUT2004Examples\\04-HunterBot\\target\\ut2004-04-hunter-bot-3.3.1-SNAPSHOT.one-jar.jar",
573 //			"-b",
574 //			"HunterBot1;HunterBot2",
575 //			"-m",
576 //			"DM-TrainingDay",
577 //			"-r",
578 //			"./results",
579 //          "-n",
580 //          "MatchName",
581 //			"-s",
582 //			"HunterServer",
583 //			"-f",
584 //			"5",
585 //			"-t",
586 //			"5",
587 //			"-h",			
588 //		};
589 		
590 		initJSAP();
591 	    
592 	    header();
593 	    
594 	    readConfig(args);
595 	    
596 	    sanityChecks();
597 	    
598 	    setUT2004Ini();
599 	    
600 	    executeMatch();
601 	}
602 	
603 }