robocode/0000755000175000017500000000000011201531251011633 5ustar lambylambyrobocode/roborumble/0000755000175000017500000000000011130006064014003 5ustar lambylambyrobocode/roborumble/.externalToolBuilders/0000755000175000017500000000000011052367122020243 5ustar lambylambyrobocode/roborumble/.externalToolBuilders/build.xml0000644000175000017500000000177711052367122022100 0ustar lambylamby robocode/roborumble/.externalToolBuilders/Ant Builder - prepare roborumble launch dir.launch0000644000175000017500000000471211052367120031411 0ustar lambylamby robocode/roborumble/MeleeRumble.launch0000644000175000017500000000725511060041602017405 0ustar lambylamby robocode/roborumble/roborumble/0000755000175000017500000000000011124141456016163 5ustar lambylambyrobocode/roborumble/roborumble/RoboRumbleAtHome.java0000644000175000017500000001276711130241114022176 0ustar lambylamby/******************************************************************************* * Copyright (c) 2003, 2008 Albert Prez and RoboRumble contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Albert Prez * - Initial API and implementation * Flemming N. Larsen * - Properties are now read using PropertiesUtil.getProperties() * - Renamed UpdateRatings() into updateRatings() * - Bugfix: Roborumble "ITERATE" broken: When running RoboRumble with * ITERATE=YES, DOWNLOAD=YES, and RUNONLY=SERVER, the ratings were only * read once, not per iteration *******************************************************************************/ package roborumble; import roborumble.battlesengine.BattlesRunner; import roborumble.battlesengine.PrepareBattles; import roborumble.netengine.BotsDownload; import roborumble.netengine.ResultsUpload; import roborumble.netengine.UpdateRatingFiles; import static roborumble.util.PropertiesUtil.getProperties; import java.util.Properties; /** * Implements the client side of RoboRumble@Home. * Controlled by properties files. * * @author Albert Prez (original) * @author Flemming N. Larsen (contributor) */ public class RoboRumbleAtHome { public static void main(String args[]) { // Get the associated parameters file String parameters = "./roborumble/roborumble.txt"; try { parameters = args[0]; } catch (Exception e) { System.out.println("No argument found specifying properties file. \"roborumble.txt\" assumed."); } // Read parameters for running the app Properties param = getProperties(parameters); String downloads = param.getProperty("DOWNLOAD", "NOT"); String executes = param.getProperty("EXECUTE", "NOT"); String uploads = param.getProperty("UPLOAD", "NOT"); String iterates = param.getProperty("ITERATE", "NOT"); String runonly = param.getProperty("RUNONLY", "GENERAL"); String melee = param.getProperty("MELEE", "NOT"); int iterations = 0; long lastdownload = 0; boolean ratingsdownloaded = false; boolean participantsdownloaded; do { System.out.println("Iteration number " + iterations); // Download data from Internet if downloads is YES and it has not been download for two hours if (downloads.equals("YES")) { BotsDownload download = new BotsDownload(parameters); if (runonly.equals("SERVER")) { // Download rating files and update ratings downloaded System.out.println("Downloading rating files ..."); ratingsdownloaded = download.downloadRatings(); } if ((System.currentTimeMillis() - lastdownload) > 2 * 3600 * 1000) { System.out.println("Downloading participants list ..."); participantsdownloaded = download.downloadParticipantsList(); System.out.println("Downloading missing bots ..."); download.downloadMissingBots(); download.updateCodeSize(); // Send the order to the server to remove old participants from the ratings file if (ratingsdownloaded && participantsdownloaded) { System.out.println("Removing old participants from server ..."); // Send unwanted participants to the server download.notifyServerForOldParticipants(); } lastdownload = System.currentTimeMillis(); } } // Create battles file (and delete old ones), and execute battles if (executes.equals("YES")) { boolean ready; PrepareBattles battles = new PrepareBattles(parameters); if (melee.equals("YES")) { System.out.println("Preparing melee battles list ..."); ready = battles.createMeleeBattlesList(); } else { System.out.println( "Preparing battles list ... Using smart battles is " + (ratingsdownloaded && runonly.equals("SERVER"))); if (ratingsdownloaded && runonly.equals("SERVER")) { // Create the smart lists ready = battles.createSmartBattlesList(); } else { // Create the normal lists ready = battles.createBattlesList(); } } // Disable the -DPRARALLEL and -DRANDOMSEED options System.setProperty("PARALLEL", "false"); // TODO: Remove when robot thread CPU time can be measured System.setProperty("RANDOMSEED", "none"); // In tournaments, robots should not be deterministic! // Execute battles if (ready) { BattlesRunner engine = new BattlesRunner(parameters); if (melee.equals("YES")) { System.out.println("Executing melee battles ..."); engine.runBattlesImpl(true); } else { System.out.println("Executing battles ..."); engine.runBattlesImpl(false); } } } // Upload results if (uploads.equals("YES")) { System.out.println("Uploading results ..."); ResultsUpload upload = new ResultsUpload(parameters); // Uploads the results to the server upload.uploadResults(); // Updates the number of battles from the info received from the server System.out.println("Updating number of battles fought ..."); UpdateRatingFiles updater = new UpdateRatingFiles(parameters); ratingsdownloaded = updater.updateRatings(); } iterations++; } while (iterates.equals("YES")); // With Java 5 this causes a IllegalThreadStateException, but not in Java 6 // System.exit(0); } } robocode/roborumble/roborumble/util/0000755000175000017500000000000011107420634017137 5ustar lambylambyrobocode/roborumble/roborumble/util/PropertiesUtil.java0000644000175000017500000000601111130241114022760 0ustar lambylamby/******************************************************************************* * Copyright (c) 2003, 2008 Albert Prez and RoboRumble contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen * - Initial API and implementation *******************************************************************************/ package roborumble.util; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Properties; /** * @author Flemming N. Larsen (original) */ public final class PropertiesUtil { /** * Returns a new Properties instance that is initialized to the specified properties file. * * @param filename the filename of the properties file to load * @return a new java.util.Properties instance */ public static Properties getProperties(String filename) { Properties props = new Properties(); if (filename != null && filename.trim().length() > 0) { FileInputStream fis = null; try { fis = new FileInputStream(filename); props.load(fis); } catch (IOException e) { System.err.println("Could not load properties file: " + filename); } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } return props; } /** * Returns a new Properties instance that is initialized to the specified properties input stream. * * @param is the input stream of the properties to load * @return a new java.util.Properties instance */ public static Properties getProperties(InputStream is) { Properties props = new Properties(); try { props.load(is); } catch (Exception e) { System.err.println("Could not load properties input stream: " + is); } return props; } /** * Stores a Properties instance to the specified properties file. * * @param properties the properties to store * @param filename the filename of the file to store the properties into * @param comments comments to include in the properties file * @return true if the properties were stored; false otherwise */ public static boolean storeProperties(Properties properties, String filename, String comments) { if (properties == null || filename == null || filename.trim().length() == 0) { return false; } FileOutputStream fos = null; try { fos = new FileOutputStream(filename); properties.store(fos, comments); } catch (IOException e) { System.err.println("Could not store properties to file: " + filename); return false; } finally { if (fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } return true; } } robocode/roborumble/roborumble/battlesengine/0000755000175000017500000000000011124141454021005 5ustar lambylambyrobocode/roborumble/roborumble/battlesengine/PrepareBattles.java0000644000175000017500000003430211130241114024556 0ustar lambylamby/******************************************************************************* * Copyright (c) 2003, 2008 Albert Prez and RoboRumble contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Albert Prez * - Initial API and implementation * Flemming N. Larsen * - Ported to Java 5 * - Removed dead code * - Minor cleanup and optimizations * - Properties are now read using PropertiesUtil.getProperties() * - Renamed CheckCompetitorsForSize() into checkCompetitorsForSize() * - Catch of entire Exception has been reduced to catch of IOException when * only this exception is ever thrown * - Added missing close() to buffered readers *******************************************************************************/ package roborumble.battlesengine; import static roborumble.util.PropertiesUtil.getProperties; import java.io.*; import java.util.Properties; import java.util.Random; import java.util.Vector; /** * PrepareBattles is used for preparing battles. * Controlled by properties files. * * @author Albert Perez (original) * @author Flemming N. Larsen (contributor) */ public class PrepareBattles { private final String botsrepository; private final String participantsfile; private final String battlesfile; private final int numbattles; private final CompetitionsSelector size; private final String runonly; private final Properties generalratings; private final Properties miniratings; private final Properties microratings; private final Properties nanoratings; private final String priority; private final int prioritynum; private final int meleebots; public PrepareBattles(String propertiesfile) { // Read parameters Properties parameters = getProperties(propertiesfile); botsrepository = parameters.getProperty("BOTSREP", ""); participantsfile = parameters.getProperty("PARTICIPANTSFILE", ""); battlesfile = parameters.getProperty("INPUT", ""); numbattles = Integer.parseInt(parameters.getProperty("NUMBATTLES", "100")); String sizesfile = parameters.getProperty("CODESIZEFILE", ""); size = new CompetitionsSelector(sizesfile, botsrepository); runonly = parameters.getProperty("RUNONLY", "GENERAL"); prioritynum = Integer.parseInt(parameters.getProperty("BATTLESPERBOT", "500")); meleebots = Integer.parseInt(parameters.getProperty("MELEEBOTS", "10")); generalratings = getProperties(parameters.getProperty("RATINGS.GENERAL", "")); miniratings = getProperties(parameters.getProperty("RATINGS.MINIBOTS", "")); microratings = getProperties(parameters.getProperty("RATINGS.MICROBOTS", "")); nanoratings = getProperties(parameters.getProperty("RATINGS.NANOBOTS", "")); priority = parameters.getProperty("PRIORITYBATTLESFILE", ""); } public boolean createBattlesList() { Vector names = new Vector(); // Read participants BufferedReader br = null; try { FileReader fr = new FileReader(participantsfile); br = new BufferedReader(fr); String record; while ((record = br.readLine()) != null) { if (record.indexOf(",") != -1) { String name = record.substring(0, record.indexOf(",")); String jar = name.replace(' ', '_') + ".jar"; boolean exists = (new File(botsrepository + jar)).exists(); if (exists) { if ((runonly.equals("MINI") && size.checkCompetitorsForSize(name, name, 1500)) || (runonly.equals("MICRO") && size.checkCompetitorsForSize(name, name, 750)) || (runonly.equals("NANO") && size.checkCompetitorsForSize(name, name, 250)) || (!runonly.equals("MINI") && !runonly.equals("MICRO") && !runonly.equals("NANO"))) { names.add(name); } } } } } catch (IOException e) { System.out.println("Participants file not found ... Aborting"); System.out.println(e); return false; } finally { if (br != null) { try { br.close(); } catch (IOException ignored) {} } } // Open battles file PrintStream outtxt; try { outtxt = new PrintStream(new BufferedOutputStream(new FileOutputStream(battlesfile)), false); } catch (IOException e) { System.out.println("Not able to open battles file " + battlesfile + " ... Aborting"); System.out.println(e); return false; } // Create the participants file Random random = new Random(); int count = 0; while (count < numbattles && names.size() > 1) { int bot1 = random.nextInt(names.size()); int bot2 = random.nextInt(names.size()); if (bot1 != bot2) { outtxt.println(names.get(bot1) + "," + names.get(bot2) + "," + runonly); count++; } } outtxt.close(); return true; } public boolean createSmartBattlesList() { Vector namesall = new Vector(); Vector namesmini = new Vector(); Vector namesmicro = new Vector(); Vector namesnano = new Vector(); Vector priorityall = new Vector(); Vector prioritymini = new Vector(); Vector prioritymicro = new Vector(); Vector prioritynano = new Vector(); Vector prioritarybattles = new Vector(); // Read participants BufferedReader br = null; try { FileReader fr = new FileReader(participantsfile); br = new BufferedReader(fr); String record; while ((record = br.readLine()) != null) { if (record.indexOf(",") != -1) { String name = record.substring(0, record.indexOf(",")); String jar = name.replace(' ', '_') + ".jar"; boolean exists = (new File(botsrepository + jar)).exists(); if (exists) { namesall.add(name); if (size.checkCompetitorsForSize(name, name, 1500)) { namesmini.add(name); } if (size.checkCompetitorsForSize(name, name, 750)) { namesmicro.add(name); } if (size.checkCompetitorsForSize(name, name, 250)) { namesnano.add(name); } if (robothaspriority(name, generalratings)) { priorityall.add(name); } if (size.checkCompetitorsForSize(name, name, 1500) && robothaspriority(name, miniratings)) { prioritymini.add(name); } if (size.checkCompetitorsForSize(name, name, 750) && robothaspriority(name, microratings)) { prioritymicro.add(name); } if (size.checkCompetitorsForSize(name, name, 250) && robothaspriority(name, nanoratings)) { prioritynano.add(name); } } } } } catch (IOException e) { System.out.println("Participants file not found ... Aborting"); System.out.println(e); return false; } finally { if (br != null) { try { br.close(); } catch (IOException ignored) {} } } // Read priority battles br = null; try { FileReader fr = new FileReader(priority); br = new BufferedReader(fr); String record; while ((record = br.readLine()) != null) { String[] items = record.split(","); if (items.length == 3) { // Check that competitors exist String jar1 = items[0].replace(' ', '_') + ".jar"; boolean exists1 = (new File(botsrepository + jar1)).exists(); String jar2 = items[1].replace(' ', '_') + ".jar"; boolean exists2 = (new File(botsrepository + jar2)).exists(); // Add battles to prioritary battles vector if (exists1 && exists2) { prioritarybattles.add(record); } } } } catch (IOException e) { System.out.println("Prioritary battles file not found ... "); } finally { if (br != null) { try { br.close(); } catch (IOException ignored) {} } } // Delete priority battles (avoid duplication) File r = new File(priority); r.delete(); // Open battles file PrintStream outtxt; try { outtxt = new PrintStream(new BufferedOutputStream(new FileOutputStream(battlesfile)), false); } catch (IOException e) { System.out.println("Not able to open battles file " + battlesfile + " ... Aborting"); System.out.println(e); return false; } // Create the participants file Random random = new Random(); int count = 0; // Add prioritary battles while (count < numbattles && count < prioritarybattles.size()) { String battle = prioritarybattles.get(count); outtxt.println(battle); count++; } // Add bots with less than 500 battles, or a random battle if all bots have enough battles while (count < numbattles && namesall.size() > 1) { String[] bots; if (priorityall.size() > 0) { bots = getbots(priorityall, namesall, random); } else if (prioritymini.size() > 0 && namesmini.size() > 1) { bots = getbots(prioritymini, namesmini, random); } else if (prioritymicro.size() > 0 && namesmicro.size() > 1) { bots = getbots(prioritymicro, namesmicro, random); } else if (prioritynano.size() > 0 && namesnano.size() > 1) { bots = getbots(prioritynano, namesnano, random); } else { bots = getbots(namesall, namesall, random); } if (bots != null) { outtxt.println(bots[0] + "," + bots[1] + "," + runonly); count++; } } outtxt.close(); return true; } private String[] getbots(Vector list1, Vector list2, Random rand) { int bot1 = rand.nextInt(list1.size()); int bot2 = rand.nextInt(list2.size()); while ((list1.get(bot1)).equals(list2.get(bot2))) { bot1 = rand.nextInt(list1.size()); bot2 = rand.nextInt(list2.size()); } String[] bots = new String[2]; bots[0] = list1.get(bot1); bots[1] = list2.get(bot2); return bots; } private boolean robothaspriority(String name, Properties ratings) { if (ratings == null) { return false; } String bot = name.replaceAll(" ", "_"); String values = ratings.getProperty(bot); if (values == null) { return true; } String[] value = values.split(","); double battles = Double.parseDouble(value[1]); return (battles < prioritynum); } public boolean createMeleeBattlesList() { Vector namesall = new Vector(); Vector namesmini = new Vector(); Vector namesmicro = new Vector(); Vector namesnano = new Vector(); Vector priorityall = new Vector(); Vector prioritymini = new Vector(); Vector prioritymicro = new Vector(); Vector prioritynano = new Vector(); // Read participants BufferedReader br = null; try { FileReader fr = new FileReader(participantsfile); br = new BufferedReader(fr); String record; while ((record = br.readLine()) != null) { if (record.indexOf(",") != -1) { String name = record.substring(0, record.indexOf(",")); String jar = name.replace(' ', '_') + ".jar"; boolean exists = (new File(botsrepository + jar)).exists(); if (exists) { namesall.add(name); if (size.checkCompetitorsForSize(name, name, 1500)) { namesmini.add(name); } if (size.checkCompetitorsForSize(name, name, 750)) { namesmicro.add(name); } if (size.checkCompetitorsForSize(name, name, 250)) { namesnano.add(name); } if (robothaspriority(name, generalratings)) { priorityall.add(name); } if (size.checkCompetitorsForSize(name, name, 1500) && robothaspriority(name, miniratings)) { prioritymini.add(name); } if (size.checkCompetitorsForSize(name, name, 750) && robothaspriority(name, microratings)) { prioritymicro.add(name); } if (size.checkCompetitorsForSize(name, name, 250) && robothaspriority(name, nanoratings)) { prioritynano.add(name); } } } } } catch (IOException e) { System.out.println("Participants file not found ... Aborting"); System.out.println(e); return false; } finally { if (br != null) { try { br.close(); } catch (IOException ignored) {} } } // Open battles file PrintStream outtxt; try { outtxt = new PrintStream(new BufferedOutputStream(new FileOutputStream(battlesfile)), false); } catch (IOException e) { System.out.println("Not able to open battles file " + battlesfile + " ... Aborting"); System.out.println(e); return false; } // Create the participants file Random random = new Random(); int count = 0; // Add bots with less than 500 battles, or a random battle if all bots have enough battles while (count < numbattles && namesall.size() > meleebots) { String[] bots = null; if (priorityall.size() > 0 && namesall.size() >= meleebots) { bots = getmeleebots(priorityall, namesall, random); } else if (prioritymini.size() > 0 && namesmini.size() >= meleebots) { bots = getmeleebots(prioritymini, namesmini, random); } else if (prioritymicro.size() > 0 && namesmicro.size() >= meleebots) { bots = getmeleebots(prioritymicro, namesmicro, random); } else if (prioritynano.size() > 0 && namesnano.size() >= meleebots) { bots = getmeleebots(prioritynano, namesnano, random); } else if (namesall.size() >= meleebots) { bots = getmeleebots(namesall, namesall, random); } if (bots != null) { StringBuilder battle = new StringBuilder(bots[0]); for (int i = 1; i < bots.length; i++) { battle.append(',').append(bots[i]); } battle.append(',').append(runonly); outtxt.println(battle); count++; } } outtxt.close(); return true; } private String[] getmeleebots(Vector list1, Vector list2, Random rand) { String[] bots = new String[meleebots]; bots[0] = list1.get(rand.nextInt(list1.size())); int count = 1; while (count < meleebots) { bots[count] = list2.get(rand.nextInt(list2.size())); boolean exists = false; for (int i = 0; i < count; i++) { if (bots[i].equals(bots[count])) { exists = true; } } if (!exists) { count++; } } return bots; } } robocode/roborumble/roborumble/battlesengine/CompetitionsSelector.java0000644000175000017500000000601211130241114026014 0ustar lambylamby/******************************************************************************* * Copyright (c) 2003, 2008 Albert Prez and RoboRumble contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Albert Prez * - Initial API and implementation * Flemming N. Larsen * - Removed unused imports * - Properties are now read using PropertiesUtil.getProperties() * - Properties are now stored using PropertiesUtil.storeProperties() * - Renamed CheckCompetitorsForSize() into checkCompetitorsForSize() *******************************************************************************/ package roborumble.battlesengine; import codesize.Codesize; import codesize.Codesize.Item; import static roborumble.util.PropertiesUtil.getProperties; import static roborumble.util.PropertiesUtil.storeProperties; import java.io.File; import java.util.Properties; /** * This class is used to control which competitions a robot is allowed to * participate in. * Reads a file with the battles to be runned and outputs the results in * another file. * Controlled by properties files. * * @author Albert Prez (original) * @author Flemming N. Larsen (contributor) */ public class CompetitionsSelector { private final String repository; private final String sizesfile; private final Properties sizes; public CompetitionsSelector(String sizesfile, String repository) { this.repository = repository; // open sizes file this.sizesfile = sizesfile; sizes = getProperties(sizesfile); } public boolean checkCompetitorsForSize(String bot1, String bot2, long maxsize) { String bot1name = bot1.replace(' ', '_'); String bot2name = bot2.replace(' ', '_'); // Read sizes long size1 = Long.parseLong(sizes.getProperty(bot1name, "0")); long size2 = Long.parseLong(sizes.getProperty(bot2name, "0")); // find out the size if not in the file boolean fileneedsupdate = false; if (size1 == 0) { fileneedsupdate = true; File f = new File(repository + bot1name + ".jar"); Item s1 = Codesize.processZipFile(f); if (s1 != null) { size1 = s1.getCodeSize(); } if (size1 != 0) { sizes.setProperty(bot1name, Long.toString(size1)); } } if (size2 == 0) { fileneedsupdate = true; File f = new File(repository + bot2name + ".jar"); Item s2 = Codesize.processZipFile(f); if (s2 != null) { size2 = s2.getCodeSize(); } if (size2 != 0) { sizes.setProperty(bot2name, Long.toString(size2)); } } // if the file needs update, then save the file if (fileneedsupdate && size1 != 0 && size2 != 0) { storeProperties(sizes, sizesfile, "Bots code size"); } // check the values return (size1 != 0 && size1 < maxsize && size2 != 0 && size2 < maxsize); } } robocode/roborumble/roborumble/battlesengine/BattlesRunner.java0000644000175000017500000002016711130241114024435 0ustar lambylamby/******************************************************************************* * Copyright (c) 2003, 2008 Albert Prez and RoboRumble contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Albert Prez * - Initial API and implementation * Flemming N. Larsen * - Ported to Java 5 * - Minor optimizations * - Removed dead code and unused imports * - Replaced the RobocodeEngineAtHome will the RobocodeEngine, and added * runBattle() to run a single battle with RobocodeEngine * - The results are now read from the AtHomeListener instead of the * RobocodeEngineAtHome * - Properties are now read using PropertiesUtil.getProperties() * - Added missing close() to buffered readers * Joachim Hofer * - Fixing problem with wrong results in RoboRumble due to wrong ordering *******************************************************************************/ package roborumble.battlesengine; import robocode.control.events.BattleAdaptor; import robocode.control.*; import robocode.control.events.BattleCompletedEvent; import robocode.control.events.BattleErrorEvent; import robocode.security.SecurePrintStream; import static roborumble.util.PropertiesUtil.getProperties; import java.io.*; import java.util.*; /** * The BattlesRunner is running battles. * Reads a file with the battles to be runned and outputs the results in another file. * Controlled by properties files. * * @author Albert Perez (original) * @author Flemming N. Larsen (contributor) * @author Joachim Hofer (contributor) */ public class BattlesRunner { private final String inputfile; private final int numrounds; private final int fieldlen; private final int fieldhei; private final String outfile; private final String user; private String game; private final Map robotSpecMap = new HashMap(500); private RobotResults[] lastResults; private BattleObserver battleObserver; public BattlesRunner(String propertiesfile) { // Read parameters Properties parameters = getProperties(propertiesfile); inputfile = parameters.getProperty("INPUT", ""); numrounds = Integer.parseInt(parameters.getProperty("ROUNDS", "10")); fieldlen = Integer.parseInt(parameters.getProperty("FIELDL", "800")); fieldhei = Integer.parseInt(parameters.getProperty("FIELDH", "600")); outfile = parameters.getProperty("OUTPUT", ""); user = parameters.getProperty("USER", ""); game = propertiesfile; while (game.indexOf("/") != -1) { game = game.substring(game.indexOf("/") + 1); } game = game.substring(0, game.indexOf(".")); initialize(); } private void initialize() { RobocodeEngine engine = new RobocodeEngine(); RobotSpecification[] repository = engine.getLocalRepository(); for (RobotSpecification spec : repository) { robotSpecMap.put(spec.getNameAndVersion(), spec); } battleObserver = new BattleObserver(); } public void runBattlesImpl(boolean melee) { // Initialize objects RobocodeEngine engine = new RobocodeEngine(); engine.addBattleListener(battleObserver); BattlefieldSpecification field = new BattlefieldSpecification(fieldlen, fieldhei); BattleSpecification battle = new BattleSpecification(numrounds, field, (new RobotSpecification[2])); // Read input file ArrayList robots = new ArrayList(); BufferedReader br = null; if (readRobots(robots, br)) { return; } // open output file PrintStream outtxt = getRedirectedOutput(); if (outtxt == null) { return; } // run battle int index = 0; while (index < robots.size()) { String[] param = (robots.get(index)).split(","); String enemies = getEnemies(melee, param); System.out.println("Fighting battle " + (index) + " ... " + enemies); String[] selectedRobots = enemies.split(","); List selectedRobotSpecs = new ArrayList(); for (String robot : selectedRobots) { RobotSpecification spec = robotSpecMap.get(robot); if (spec != null) { selectedRobotSpecs.add(spec); } } final RobotSpecification[] robotsList = selectedRobotSpecs.toArray(new RobotSpecification[1]); if (robotsList.length >= 2) { final BattleSpecification specification = new BattleSpecification(battle.getNumRounds(), battle.getBattlefield(), robotsList); lastResults = null; engine.runBattle(specification, true); if (lastResults != null) { dumpResults(outtxt, lastResults, param[param.length - 1], melee); } } else { System.err.println("Skipping battle because can't load robots"); } index++; } engine.removeBattleListener(battleObserver); // close outtxt.close(); engine.close(); } private String getEnemies(boolean melee, String[] param) { String enemies; if (melee) { enemies = param[0] + "," + param[1]; } else { StringBuilder eb = new StringBuilder(); for (int i = 0; i < param.length - 1; i++) { if (i > 0) { eb.append(','); } eb.append(param[i]); } enemies = eb.toString(); } return enemies; } private PrintStream getRedirectedOutput() { try { return new PrintStream(new BufferedOutputStream(new FileOutputStream(outfile, true)), true); } catch (IOException e) { System.out.println("Not able to open output file ... Aborting"); System.out.println(e); return null; } } private boolean readRobots(ArrayList robots, BufferedReader br) { try { FileReader fr = new FileReader(inputfile); br = new BufferedReader(fr); String record; while ((record = br.readLine()) != null) { robots.add(record); } } catch (IOException e) { System.out.println("Battles input file not found ... Aborting"); System.out.println(e); return true; } finally { if (br != null) { try { br.close(); } catch (IOException e) {// just ignore } } } return false; } private void dumpResults(PrintStream outtxt, RobotResults[] results, String last, boolean melee) { for (int i = 0; i < results.length; i++) { for (int j = 0; j < results.length; j++) { if (i < j) { final String botOne = results[i].getRobot().getNameAndVersion(); final String botTwo = results[j].getRobot().getNameAndVersion(); final int pointsOne = results[i].getScore(); final int pointsTwo = results[j].getScore(); final int bulletsOne = results[i].getBulletDamage(); final int bulletsTwo = results[j].getBulletDamage(); final int survivalOne = results[i].getSurvival(); final int survivalTwo = results[j].getSurvival(); outtxt.println( game + "," + numrounds + "," + fieldlen + "x" + fieldhei + "," + user + "," + System.currentTimeMillis() + "," + last); outtxt.println(botOne + "," + pointsOne + "," + bulletsOne + "," + survivalOne); outtxt.println(botTwo + "," + pointsTwo + "," + bulletsTwo + "," + survivalTwo); } } } if (melee) { System.out.println( "RESULT = " + results[0].getRobot().getNameAndVersion() + " wins, " + results[1].getRobot().getNameAndVersion() + " is second."); } else { System.out.println( "RESULT = " + results[0].getRobot().getNameAndVersion() + " wins " + results[0].getScore() + " to " + results[1].getScore()); } } class BattleObserver extends BattleAdaptor { // @Override // public void onBattleMessage(final BattleMessageEvent event) { // SecurePrintStream.realOut.println(event.getMessage()); // } @Override public void onBattleError(final BattleErrorEvent event) { SecurePrintStream.realErr.println(event.getError()); } @Override public void onBattleCompleted(final BattleCompletedEvent event) { lastResults = RobotResults.convertResults(event.getSortedResults()); } } } robocode/roborumble/roborumble/netengine/0000755000175000017500000000000011124141500020125 5ustar lambylambyrobocode/roborumble/roborumble/netengine/UpdateRatingFiles.java0000644000175000017500000001144311130241114024344 0ustar lambylamby/******************************************************************************* * Copyright (c) 2003, 2008 Albert Prez and RoboRumble contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Albert Prez * - Initial API and implementation * Flemming N. Larsen * - Ported to Java 5 * - Removed dead code and unused imports * - Properties are now read using PropertiesUtil.getProperties() * - Properties are now stored using PropertiesUtil.storeProperties() * - Renamed UpdateRatings() into updateRatings() * - Catch of entire Exception has been reduced to catch of IOException when * only this exception is ever thrown * - Added missing close() to streams *******************************************************************************/ package roborumble.netengine; import static roborumble.util.PropertiesUtil.getProperties; import static roborumble.util.PropertiesUtil.storeProperties; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.util.Properties; import java.util.Vector; /** * Class used for updating the local rating files. * Controlled by properties files. * * @author Albert Prez (original) * @author Flemming N. Larsen (contributor) */ public class UpdateRatingFiles { private String game; private final String minibots; private final String microbots; private final String nanobots; private final String battlesnumfile; private final String generalratings; private final String miniratings; private final String microratings; private final String nanoratings; public UpdateRatingFiles(String propertiesfile) { // Read parameters Properties parameters = getProperties(propertiesfile); game = propertiesfile; while (game.indexOf("/") != -1) { game = game.substring(game.indexOf("/") + 1); } game = game.substring(0, game.indexOf(".")); minibots = parameters.getProperty("MINIBOTS", ""); microbots = parameters.getProperty("MICROBOTS", ""); nanobots = parameters.getProperty("NANOBOTS", ""); battlesnumfile = parameters.getProperty("BATTLESNUMFILE", ""); generalratings = parameters.getProperty("RATINGS.GENERAL", ""); miniratings = parameters.getProperty("RATINGS.MINIBOTS", ""); microratings = parameters.getProperty("RATINGS.MICROBOTS", ""); nanoratings = parameters.getProperty("RATINGS.NANOBOTS", ""); } public boolean updateRatings() { // read all the records to be updated Vector battles = new Vector(); BufferedReader br = null; try { FileReader fr = new FileReader(battlesnumfile); br = new BufferedReader(fr); String record; while ((record = br.readLine()) != null) { battles.add(record); } } catch (IOException e) { System.out.println("Can't open # battles file ... Aborting # battles update"); return false; } finally { if (br != null) { try { br.close(); } catch (IOException ignored) {} } } // read the ratings files Properties all = getProperties(generalratings); Properties mini = getProperties(miniratings); Properties micro = getProperties(microratings); Properties nano = getProperties(nanoratings); // update #battles for (String battle : battles) { String[] battleSpec = battle.split(","); battleSpec[1] = battleSpec[1].replaceAll(" ", "_"); double num = Double.parseDouble(battleSpec[2]); if (battleSpec[0].equals(game)) { updateRecord(battleSpec[1], num, all); } else if (battleSpec[0].equals(minibots) && mini != null) { updateRecord(battleSpec[1], num, mini); } else if (battleSpec[0].equals(microbots) && micro != null) { updateRecord(battleSpec[1], num, micro); } else if (battleSpec[0].equals(nanobots) && nano != null) { updateRecord(battleSpec[1], num, nano); } } // save ratings files return storeProperties(all, generalratings, "General ratings updated with new battles number") && storeProperties(all, miniratings, "Mini ratings updated with new battles number") && storeProperties(all, microratings, "Micro ratings updated with new battles number") && storeProperties(all, nanoratings, "Nano ratings updated with new battles number"); } private void updateRecord(String bot, double battles, Properties ratings) { String values = ratings.getProperty(bot); if (values == null) { return; } String[] value = values.split(","); values = value[0] + "," + Double.toString(battles) + "," + value[2]; ratings.setProperty(bot, values); } } robocode/roborumble/roborumble/netengine/BotsDownload.java0000644000175000017500000004254611130241114023401 0ustar lambylamby/******************************************************************************* * Copyright (c) 2003, 2008 Albert Prez and RoboRumble contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Albert Prez * - Initial API and implementation * Flemming N. Larsen * - Ported to Java 5 * - Removed dead code * - Minor optimizations * - Replaced the robocode.util.Utils.copy() method with FileTransfer.copy() * - Bugfix: Solved ZipException by creating a session to the Robocode * Repository site * - Properties are now read using PropertiesUtil.getProperties() * - Renamed CheckCompetitorsForSize() into checkCompetitorsForSize() * - Added missing close() to streams * - Added new EXCLUDE property, which is used for excluding participants * - Added the isExcluded() method *******************************************************************************/ package roborumble.netengine; import roborumble.battlesengine.CompetitionsSelector; import static roborumble.netengine.FileTransfer.DownloadStatus; import static roborumble.util.PropertiesUtil.getProperties; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.util.Enumeration; import java.util.Hashtable; import java.util.Properties; import java.util.Vector; import java.util.jar.JarFile; import java.util.zip.ZipEntry; /** * Class used for downloading participating robots from the Internet. * Manages the download operations (participants and JAR files). * Controlled by properties files. * * @author Albert Prez (original) * @author Flemming N. Larsen (contributor) */ public class BotsDownload { // private String internetrepository; private final String botsrepository; private final String participantsfile; private final String participantsurl; private final String tempdir; private final String tag; private final String isteams; private final String sizesfile; private final CompetitionsSelector size; private final String ratingsurl; private String generalbots; private final String minibots; private final String microbots; private final String nanobots; private final String generalbotsfile; private final String minibotsfile; private final String microbotsfile; private final String nanobotsfile; private final String removeboturl; private String[] excludes; public BotsDownload(String propertiesfile) { // Read parameters Properties parameters = getProperties(propertiesfile); botsrepository = parameters.getProperty("BOTSREP", ""); isteams = parameters.getProperty("TEAMS", "NOT"); participantsurl = parameters.getProperty("PARTICIPANTSURL", ""); participantsfile = parameters.getProperty("PARTICIPANTSFILE", ""); tag = parameters.getProperty("STARTAG", "pre"); tempdir = parameters.getProperty("TEMP", ""); // Code size sizesfile = parameters.getProperty("CODESIZEFILE", ""); size = new CompetitionsSelector(sizesfile, botsrepository); // Ratings files ratingsurl = parameters.getProperty("RATINGS.URL", ""); generalbots = propertiesfile; while (generalbots.indexOf("/") != -1) { generalbots = generalbots.substring(generalbots.indexOf("/") + 1); } generalbots = generalbots.substring(0, generalbots.indexOf(".")); minibots = parameters.getProperty("MINIBOTS", ""); microbots = parameters.getProperty("MICROBOTS", ""); nanobots = parameters.getProperty("NANOBOTS", ""); generalbotsfile = parameters.getProperty("RATINGS.GENERAL", ""); minibotsfile = parameters.getProperty("RATINGS.MINIBOTS", ""); microbotsfile = parameters.getProperty("RATINGS.MICROBOTS", ""); nanobotsfile = parameters.getProperty("RATINGS.NANOBOTS", ""); // remove old bots removeboturl = parameters.getProperty("UPDATEBOTSURL", ""); // Read and prepare exclude filters String exclude = parameters.getProperty("EXCLUDE"); if (exclude != null) { // Convert into regular expression // Dots must be dots, not "any character" in the regular expression exclude = exclude.replaceAll("\\.", "\\\\."); // The wildcard character ? corresponds to the regular expression .? exclude = exclude.replaceAll("\\?", ".?"); // The wildcard character * corresponds to the regular expression .* exclude = exclude.replaceAll("\\*", ".*"); // Split the exclude line into independent exclude filters that are trimmed for white-spaces excludes = exclude.split("[\\s,;]+"); } } public boolean downloadRatings() { // delete previous files if (generalbotsfile.length() != 0) { (new File(generalbotsfile)).delete(); } if (minibotsfile.length() != 0) { (new File(minibotsfile)).delete(); } if (microbotsfile.length() != 0) { (new File(microbotsfile)).delete(); } if (nanobotsfile.length() != 0) { (new File(nanobotsfile)).delete(); } // download new ones if (ratingsurl.length() == 0) { return false; } boolean downloaded = true; if (generalbots.length() != 0 && generalbotsfile.length() != 0) { downloaded = downloadRatingsFile(generalbots, generalbotsfile) & downloaded; } if (minibots.length() != 0 && minibotsfile.length() != 0) { downloaded = downloadRatingsFile(minibots, minibotsfile) & downloaded; } if (microbots.length() != 0 && microbotsfile.length() != 0) { downloaded = downloadRatingsFile(microbots, microbotsfile) & downloaded; } if (nanobots.length() != 0 && nanobotsfile.length() != 0) { downloaded = downloadRatingsFile(nanobots, nanobotsfile) & downloaded; } return downloaded; } public boolean downloadParticipantsList() { String begin = "<" + tag + ">"; String end = ""; Vector bots = new Vector(); BufferedReader in = null; try { URL url = new URL(participantsurl); HttpURLConnection urlc = (HttpURLConnection) url.openConnection(); urlc.setRequestMethod("GET"); urlc.setDoInput(true); urlc.connect(); boolean arebots = false; in = new BufferedReader(new InputStreamReader(urlc.getInputStream())); for (String str; (str = in.readLine()) != null;) { if (str.indexOf(begin) != -1) { arebots = true; } else if (str.indexOf(end) != -1) { arebots = false; } else if (arebots) { String name = str.substring(0, str.indexOf(",")); if (!isExcluded(name)) { bots.add(str); } } } urlc.disconnect(); PrintStream outtxt = new PrintStream(new BufferedOutputStream(new FileOutputStream(participantsfile)), false); for (String bot : bots) { outtxt.println(bot); } outtxt.close(); } catch (IOException e) { System.out.println("Unable to retrieve participants list"); System.out.println(e); return false; } finally { if (in != null) { try { in.close(); } catch (IOException ignored) {} } } return true; } public void downloadMissingBots() { Vector jars = new Vector(); Vector ids = new Vector(); Vector names = new Vector(); // Read participants BufferedReader br = null; try { FileReader fr = new FileReader(participantsfile); br = new BufferedReader(fr); for (String record; (record = br.readLine()) != null;) { if (record.indexOf(",") >= 0) { String id = record.substring(record.indexOf(",") + 1); String name = record.substring(0, record.indexOf(",")); String jar = name.replace(' ', '_') + ".jar"; jars.add(jar); ids.add(id); names.add(name); } } } catch (IOException e) { System.out.println("Participants file not found ... Aborting"); System.out.println(e); return; } finally { if (br != null) { try { br.close(); } catch (IOException ignored) {} } } // check if the file exists in the repository and download if not present for (int i = 0; i < jars.size(); i++) { String botjar = jars.get(i); String botid = ids.get(i); String botname = names.get(i); String botpath = botsrepository + botjar; boolean exists = (new File(botpath)).exists(); if (!exists) { boolean downloaded = downloadBot(botname, botjar, botid, botsrepository, tempdir); if (!downloaded) { System.out.println("Could not download " + botjar); } } } } public void updateCodeSize() { if (sizesfile.length() != 0) { BufferedReader br = null; try { FileReader fr = new FileReader(participantsfile); br = new BufferedReader(fr); for (String record; (record = br.readLine()) != null;) { String name = record.substring(0, record.indexOf(",")); name = name.replace(' ', '_'); size.checkCompetitorsForSize(name, name, 1500); } } catch (IOException e) { System.out.println("Battles input file not found ... Aborting"); System.out.println(e); } finally { if (br != null) { try { br.close(); } catch (IOException ignored) {} } } } } private boolean downloadBot(String botname, String file, String id, String destination, String tempdir) { String filed = tempdir + file; String finald = destination + file; // check if the bot exists in the repository boolean exists = (new File(finald)).exists(); if (exists) { System.out.println("The bot already exists in the repository."); return false; } // Download the bot String url; String sessionId = null; if (id.indexOf("://") == -1) { url = "http://robocoderepository.com/Controller.jsp?submitAction=downloadClass&id=" + id; sessionId = FileTransfer.getSessionId( "http://robocoderepository.com/BotSearch.jsp?botName=''&authorName=''&uploadDate="); } else { url = id; } System.out.println("Trying to download " + botname); DownloadStatus downloadStatus = FileTransfer.download(url, filed, sessionId); if (downloadStatus == DownloadStatus.FILE_NOT_FOUND) { System.out.println("Could not find " + botname + " from " + url); return false; } else if (downloadStatus == DownloadStatus.COULD_NOT_CONNECT) { System.out.println("Could not connect to " + url); return false; } // Check the bot and save it into the repository if (checkJarFile(filed, botname)) { if (!FileTransfer.copy(filed, finald)) { System.out.println("Unable to copy " + filed + " into the repository"); return false; } } else { System.out.println("Downloaded file is wrong or corrupted:" + file); return false; } System.out.println("Downloaded " + botname + " into " + finald); return true; } private boolean checkJarFile(String file, String botname) { if (botname.indexOf(" ") == -1) { System.out.println("Are you sure " + botname + " is a bot/team? Can't download it."); return false; } String bot = botname.substring(0, botname.indexOf(" ")); bot = bot.replace('.', '/'); if (!isteams.equals("YES")) { bot += ".properties"; } else { bot += ".team"; } try { JarFile jarf = new JarFile(file); ZipEntry zipe = jarf.getJarEntry(bot); if (zipe == null) { System.out.println("Not able to read properties"); return false; } InputStream properties = jarf.getInputStream(zipe); Properties parameters = getProperties(properties); if (!isteams.equals("YES")) { String classname = parameters.getProperty("robot.classname", ""); String version = parameters.getProperty("robot.version", ""); return (botname.equals(classname + " " + version)); } String version = parameters.getProperty("team.version", ""); return (botname.equals(botname.substring(0, botname.indexOf(" ")) + " " + version)); } catch (Exception e) { System.out.println(e); return false; } } // ---------------------------------------------------------------------------------- // download ratings file // ---------------------------------------------------------------------------------- private boolean downloadRatingsFile(String competition, String file) { BufferedReader in = null; PrintStream outtxt = null; try { URL url = new URL(ratingsurl + "?version=1&game=" + competition); HttpURLConnection urlc = (HttpURLConnection) url.openConnection(); urlc.setRequestMethod("GET"); urlc.setDoInput(true); urlc.connect(); outtxt = new PrintStream(new BufferedOutputStream(new FileOutputStream(file)), false); in = new BufferedReader(new InputStreamReader(urlc.getInputStream())); for (String str; (str = in.readLine()) != null;) { outtxt.println(str); } urlc.disconnect(); } catch (IOException e) { System.out.println("Unable to ratings for " + competition); System.out.println(e); return false; } finally { if (in != null) { try { in.close(); } catch (IOException ignored) {} } if (outtxt != null) { outtxt.close(); } } return true; } // ---------------------------------------------------------------------------------- // download ratings file // ---------------------------------------------------------------------------------- public void notifyServerForOldParticipants() { // Load participants names Hashtable namesall = new Hashtable(); BufferedReader br = null; try { FileReader fr = new FileReader(participantsfile); br = new BufferedReader(fr); for (String record; (record = br.readLine()) != null;) { if (record.indexOf(",") != -1) { String name = record.substring(0, record.indexOf(",")).replace(' ', '_'); namesall.put(name, name); } } } catch (IOException e) { System.out.println("Participants file not found when removing old participants ... Aborting"); System.out.println(e); return; } finally { if (br != null) { try { br.close(); } catch (IOException ignored) {} } } // Load ratings files Properties generalratings = getProperties(generalbotsfile); Properties miniratings = getProperties(minibotsfile); Properties microratings = getProperties(microbotsfile); Properties nanoratings = getProperties(nanobotsfile); // Check general ratings for (Enumeration e = generalratings.propertyNames(); e.hasMoreElements();) { String bot = (String) e.nextElement(); if (!(isExcluded(bot) || namesall.containsKey(bot))) { // Remove the bot from the ratings file System.out.println("Removing entry ... " + bot + " from " + generalbots); removebot(generalbots, bot); } } // Check mini ratings for (Enumeration e = miniratings.propertyNames(); e.hasMoreElements();) { String bot = (String) e.nextElement(); if (!(isExcluded(bot) || namesall.containsKey(bot))) { // Remove the bot from the ratings file System.out.println("Removing entry ... " + bot + " from " + minibots); removebot(minibots, bot); } } // Check micro ratings for (Enumeration e = microratings.propertyNames(); e.hasMoreElements();) { String bot = (String) e.nextElement(); if (!(isExcluded(bot) || namesall.containsKey(bot))) { // Remove the bot from the ratings file System.out.println("Removing entry ... " + bot + " from " + microbots); removebot(microbots, bot); } } // Check nano ratings for (Enumeration e = nanoratings.propertyNames(); e.hasMoreElements();) { String bot = (String) e.nextElement(); if (!(isExcluded(bot) || namesall.containsKey(bot))) { // Remove the bot from the ratings file System.out.println("Removing entry ... " + bot + " from " + nanobots); removebot(nanobots, bot); } } } private void removebot(String game, String bot) { if (removeboturl.length() == 0) { System.out.println("UPDATEBOTS URL not defined!"); return; } String data = "version=1&game=" + game + "&name=" + bot.trim() + "&dummy=NA"; PrintWriter wr = null; BufferedReader rd = null; try { // Send data URL url = new URL(removeboturl); URLConnection conn = url.openConnection(); conn.setDoOutput(true); wr = new PrintWriter(new OutputStreamWriter(conn.getOutputStream())); wr.println(data); wr.flush(); // Get the response rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); for (String line; (line = rd.readLine()) != null;) { System.out.println(line); } } catch (IOException e) { System.out.println(e); } finally { if (wr != null) { wr.close(); } if (rd != null) { try { rd.close(); } catch (IOException ignored) {} } } } // Check if a robot is excluded private boolean isExcluded(String bot) { if (excludes == null) { return false; } // Check the name against all exclude filters for (int i = excludes.length - 1; i >= 0; i--) { try { if (bot.matches(excludes[i])) { return true; } } catch (java.util.regex.PatternSyntaxException e) { // Clear the current exclude if the syntax is illegal (for next time this method is called) excludes[i] = ""; } } // Not excluded return false; } } robocode/roborumble/roborumble/netengine/FileTransfer.java0000644000175000017500000003242611130241114023362 0ustar lambylamby/******************************************************************************* * Copyright (c) 2003, 2008 Albert Prez and RoboRumble contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Albert Prez * - Initial API and implementation * Flemming N. Larsen * - Completely rewritten to be fully multi-threaded so that download is not * blocked if a connection is hanging. In addition, this version of * FileTransfer support sessions *******************************************************************************/ package roborumble.netengine; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; /** * Utility class for downloading files from the net and copying files. * * @author Flemming N. Larsen (original) */ public class FileTransfer { private final static int CONNECTION_TIMEOUT = 5000; // 5 seconds /** * Represents the download status returned when downloading files. * * @author Flemming N. Larsen */ public enum DownloadStatus { OK, // The download was succesful COULD_NOT_CONNECT, // Connection problem FILE_NOT_FOUND, // The file to download was not found } /** * Daemon worker thread containing a 'finish' flag for waiting and notifying * when the thread has finished it's job. * * @author Flemming N. Larsen */ private static class WorkerThread extends Thread { final Object monitor = new Object(); volatile boolean isFinished; public WorkerThread(String name) { super(name); setDaemon(true); } void notifyFinish() { // Notify that this thread is finish synchronized (monitor) { isFinished = true; monitor.notifyAll(); } } } /* * Returns a session id for keeping a session on a HTTP site. * * @param url the url of the HTTP site * @return a session id for keeping a session on a HTTP site or null if no * session is available */ public static String getSessionId(String url) { HttpURLConnection con = null; try { // Open connection con = (HttpURLConnection) new URL(url).openConnection(); if (con == null) { throw new IOException("Could not open connection to '" + url + "'"); } // Get a session id if available final GetSessionIdThread sessionIdThread = new GetSessionIdThread(con); sessionIdThread.start(); // Wait for the session id synchronized (sessionIdThread.monitor) { while (!sessionIdThread.isFinished) { try { sessionIdThread.monitor.wait(CONNECTION_TIMEOUT); sessionIdThread.interrupt(); } catch (InterruptedException e) { // Immediately reasserts the exception by interrupting the caller thread itself Thread.currentThread().interrupt(); return null; } } } // Return the session id return sessionIdThread.sessionId; } catch (final IOException e) { return null; } finally { // Make sure the connection is disconnected. // This will cause threads using the connection to throw an exception // and thereby terminate if they were hanging. if (con != null) { con.disconnect(); } } } /** * Worker thread used for getting the session id of an already open HTTP * connection. * * @author Flemming N. Larsen */ private final static class GetSessionIdThread extends WorkerThread { // The resulting session id to read out String sessionId; final HttpURLConnection con; GetSessionIdThread(HttpURLConnection con) { super("FileTransfer: Get session ID"); this.con = con; } @Override public void run() { try { // Get the cookie value final String cookieVal = con.getHeaderField("Set-Cookie"); // Extract the session id from the cookie value if (cookieVal != null) { sessionId = cookieVal.substring(0, cookieVal.indexOf(";")); } } catch (final Exception e) { sessionId = null; } // Notify that this thread is finish notifyFinish(); } } /** * Downloads a file from a HTTP site. * * @param url the url of the HTTP site to download the file from * @param filename the filename of the destination file * @param sessionId an optional session id if the download is session based * @return the download status, which is DownloadStatus.OK if the download * completed successfully; otherwise an error occurred */ public static DownloadStatus download(String url, String filename, String sessionId) { HttpURLConnection con = null; try { // Open connection con = (HttpURLConnection) new URL(url).openConnection(); if (con == null) { throw new IOException("Could not open connection to '" + url + "'"); } // Set the session id if it is specified if (sessionId != null) { con.setRequestProperty("Cookie", sessionId); } // Prepare the connection con.setDoInput(true); con.setDoOutput(false); con.setUseCaches(false); // Make the connection con.setConnectTimeout(CONNECTION_TIMEOUT); con.connect(); // Begin the download final DownloadThread downloadThread = new DownloadThread(con, filename); downloadThread.start(); // Wait for the download to complete synchronized (downloadThread.monitor) { while (!downloadThread.isFinished) { try { downloadThread.monitor.wait(); } catch (InterruptedException e) { return DownloadStatus.COULD_NOT_CONNECT; } } } // Return the download status return downloadThread.status; } catch (final IOException e) { return DownloadStatus.COULD_NOT_CONNECT; } finally { // Make sure the connection is disconnected. // This will cause threads using the connection to throw an exception // and thereby terminate if they were hanging. if (con != null) { con.disconnect(); } } } /** * Worker thread used for downloading a file from an already open HTTP * connection. * * @author Flemming N. Larsen */ private final static class DownloadThread extends WorkerThread { // The download status to be read out DownloadStatus status = DownloadStatus.COULD_NOT_CONNECT; // Default error final HttpURLConnection con; final String filename; InputStream in; OutputStream out; DownloadThread(HttpURLConnection con, String filename) { super("FileTransfer: Download"); this.con = con; this.filename = filename; } @Override public void run() { try { // Start getting the response code final GetResponseCodeThread responseThread = new GetResponseCodeThread(con); responseThread.start(); // Wait for the response to finish synchronized (responseThread.monitor) { while (!responseThread.isFinished) { try { responseThread.monitor.wait(CONNECTION_TIMEOUT); responseThread.interrupt(); } catch (InterruptedException e) { notifyFinish(); return; } } } final int responseCode = responseThread.responseCode; if (responseCode == -1) { // Terminate if we did not get the response code notifyFinish(); return; } else if (responseCode == HttpURLConnection.HTTP_NOT_FOUND) { // Terminate if the HTTP page containing the file was not found status = DownloadStatus.FILE_NOT_FOUND; notifyFinish(); return; } else if (responseCode != HttpURLConnection.HTTP_OK) { // Generally, terminate if did not receive a OK response notifyFinish(); return; } // Start getting the size of the file to download final GetContentLengthThread contentLengthThread = new GetContentLengthThread(con); contentLengthThread.start(); // Wait for the file size synchronized (contentLengthThread.monitor) { while (!contentLengthThread.isFinished) { try { contentLengthThread.monitor.wait(CONNECTION_TIMEOUT); contentLengthThread.interrupt(); } catch (InterruptedException e) { notifyFinish(); return; } } } final int size = contentLengthThread.contentLength; if (size == -1) { // Terminate if we did not get the content length notifyFinish(); return; } // Get an input stream from the connection in = con.getInputStream(); // Prepare the output stream for the file output out = new FileOutputStream(filename); // Download the file final byte[] buf = new byte[4096]; int totalRead = 0; int bytesRead; // Start thread for reading bytes into the buffer while (totalRead < size) { // Start reading bytes into the buffer final ReadInputStreamToBufferThread readThread = new ReadInputStreamToBufferThread(in, buf); readThread.start(); // Wait for the reading to finish synchronized (readThread.monitor) { while (!readThread.isFinished) { try { readThread.monitor.wait(CONNECTION_TIMEOUT); readThread.interrupt(); } catch (InterruptedException e) { notifyFinish(); return; } } } bytesRead = readThread.bytesRead; if (bytesRead == -1) { // Read completed has completed notifyFinish(); break; } // Write the byte buffer to the output out.write(buf, 0, bytesRead); totalRead += bytesRead; } // If we reached this point, the download was succesful status = DownloadStatus.OK; notifyFinish(); } catch (final IOException e) { status = DownloadStatus.COULD_NOT_CONNECT; } finally { // Make sure the input stream is closed if (in != null) { try { in.close(); } catch (final IOException e) { e.printStackTrace(); } } // Make sure the output stream is closed if (out != null) { try { out.close(); } catch (final IOException e) { e.printStackTrace(); } } } } } /** * Worker thread used for getting the response code of an already open HTTP * connection. * * @author Flemming N. Larsen */ final static class GetResponseCodeThread extends WorkerThread { // The response code to read out int responseCode; final HttpURLConnection con; GetResponseCodeThread(HttpURLConnection con) { super("FileTransfer: Get response code"); this.con = con; } @Override public void run() { try { // Get the response code responseCode = con.getResponseCode(); } catch (final Exception e) { responseCode = -1; } // Notify that this thread is finish notifyFinish(); } } /** * Worker thread used for getting the content length of an already open HTTP * connection. * * @author Flemming N. Larsen */ final static class GetContentLengthThread extends WorkerThread { // The content length to read out int contentLength; final HttpURLConnection con; GetContentLengthThread(HttpURLConnection con) { super("FileTransfer: Get content length"); this.con = con; } @Override public void run() { try { // Get the content length contentLength = con.getContentLength(); } catch (final Exception e) { contentLength = -1; } // Notify that this thread is finish notifyFinish(); } } /** * Worker thread used for reading bytes from an already open input stream * into a byte buffer. * * @author Flemming N. Larsen */ final static class ReadInputStreamToBufferThread extends WorkerThread { int bytesRead; final InputStream in; final byte[] buf; ReadInputStreamToBufferThread(InputStream in, byte[] buf) { super("FileTransfer: Read input stream to buffer"); this.in = in; this.buf = buf; } @Override public void run() { try { // Read bytes into the buffer bytesRead = in.read(buf); } catch (final Exception e) { bytesRead = -1; } // Notify that this thread is finish notifyFinish(); } } /** * Copies a file into another file. * * @param src_file the filename of the source file to copy * @param dest_file the filename of the destination file to copy the file * into * @return true if the file was copied; false otherwise */ public static boolean copy(String src_file, String dest_file) { FileInputStream in = null; FileOutputStream out = null; try { if (src_file.equals(dest_file)) { throw new IOException("You cannot copy a file onto itself"); } final byte[] buf = new byte[4096]; in = new FileInputStream(src_file); out = new FileOutputStream(dest_file); while (in.available() > 0) { out.write(buf, 0, in.read(buf, 0, buf.length)); } } catch (final IOException e) { return false; } finally { if (in != null) { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } if (out != null) { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } return true; } } robocode/roborumble/roborumble/netengine/ResultsUpload.java0000644000175000017500000003015711130241114023603 0ustar lambylamby/******************************************************************************* * Copyright (c) 2003, 2008 Albert Prez and RoboRumble contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Albert Prez * - Initial API and implementation * Flemming N. Larsen * - Ported to Java 5 * - Minor cleanup and optimizations * - Removed unused imports * - Replaced the robocode.util.Utils.copy() method with FileTransfer.copy() * - Properties are now read using PropertiesUtil.getProperties() * - Catch of entire Exception has been reduced to catch of IOException when * only this exception is ever thrown * - Added missing close() to streams *******************************************************************************/ package roborumble.netengine; import robocode.manager.VersionManager; import roborumble.battlesengine.CompetitionsSelector; import static roborumble.util.PropertiesUtil.getProperties; import java.io.*; import java.net.URL; import java.net.URLConnection; import java.util.Properties; import java.util.Vector; /** * Class used for uploading results to a server. * Controlled by properties files. * * @author Albert Prez (original) * @author Flemming N. Larsen (contributor) */ public class ResultsUpload { private final String client; private final String resultsfile; private final String resultsurl; private final String tempdir; private String game; private final String user; private final String sizesfile; private final String minibots; private final String microbots; private final String nanobots; private final CompetitionsSelector size; private final String battlesnumfile; private final String priority; private final String teams; private final String melee; public ResultsUpload(String propertiesfile) { // Read parameters Properties parameters = getProperties(propertiesfile); resultsfile = parameters.getProperty("OUTPUT", ""); resultsurl = parameters.getProperty("RESULTSURL", ""); tempdir = parameters.getProperty("TEMP", ""); user = parameters.getProperty("USER", ""); game = propertiesfile; String botsrepository = parameters.getProperty("BOTSREP", ""); while (game.indexOf("/") != -1) { game = game.substring(game.indexOf("/") + 1); } game = game.substring(0, game.indexOf(".")); sizesfile = parameters.getProperty("CODESIZEFILE", ""); minibots = parameters.getProperty("MINIBOTS", ""); microbots = parameters.getProperty("MICROBOTS", ""); nanobots = parameters.getProperty("NANOBOTS", ""); battlesnumfile = parameters.getProperty("BATTLESNUMFILE", ""); priority = parameters.getProperty("PRIORITYBATTLESFILE", ""); client = VersionManager.getVersionStatic(); teams = parameters.getProperty("TEAMS", ""); melee = parameters.getProperty("MELEE", ""); // Open competitions selector size = new CompetitionsSelector(sizesfile, botsrepository); } public void uploadResults() { boolean errorsfound = false; // Read the results file Vector results = new Vector(); String match = ""; String bot1 = ""; String bot2; int status = 0; BufferedReader br = null; try { FileReader fr = new FileReader(resultsfile); br = new BufferedReader(fr); String record; while ((record = br.readLine()) != null) { if (record.indexOf(game) != -1) { match = record; status = 0; } else if (status == 0) { bot1 = record; status = 1; } else if (status == 1) { bot2 = record; results.add(match); results.add(bot1); results.add(bot2); } } } catch (IOException e) { System.out.println("Can't open result file for upload"); return; } finally { if (br != null) { try { br.close(); } catch (IOException ignored) {} } } // Open the temp file to put the unuploaded results PrintStream outtxt; try { outtxt = new PrintStream(new BufferedOutputStream(new FileOutputStream(tempdir + "results.txt")), false); } catch (IOException e) { System.out.println("Not able to open output file ... Aborting"); System.out.println(e); return; } // Open the file to put the battles number for each participant PrintStream battlesnum; try { battlesnum = new PrintStream(new BufferedOutputStream(new FileOutputStream(battlesnumfile)), false); } catch (IOException e) { System.out.println("Not able to open battles number file ... Aborting"); System.out.println(e); outtxt.close(); return; } // Open the file to put the battles which have priority PrintStream prioritybattles; try { prioritybattles = new PrintStream(new BufferedOutputStream(new FileOutputStream(priority)), false); } catch (IOException e) { System.out.println("Not able to open priorities file ... Aborting"); System.out.println(e); outtxt.close(); battlesnum.close(); return; } // Post the results for (int i = 0; i < results.size() / 3; i++) { // Create the parameters String String[] header = results.get(i * 3).split(","); String[] first = results.get(i * 3 + 1).split(","); String[] second = results.get(i * 3 + 2).split(","); // find the match mode String matchtype = "GENERAL"; if (header.length >= 6) { matchtype = header[5]; } // if the match mode was general, then send the results to all competitions (asuming codesize is used). // if its not, then send results only to smaller size competitions String data = "version=1" + "&" + "client=" + client + "&" + "teams=" + teams + "&" + "melee=" + melee + "&" + "game=" + game + "&" + "rounds=" + header[1] + "&" + "field=" + header[2] + "&" + "user=" + user + "&" + "time=" + header[4] + "&" + "fname=" + first[0] + "&" + "fscore=" + first[1] + "&" + "fbulletd=" + first[2] + "&" + "fsurvival=" + first[3] + "&" + "sname=" + second[0] + "&" + "sscore=" + second[1] + "&" + "sbulletd=" + second[2] + "&" + "ssurvival=" + second[3]; if (matchtype.equals("GENERAL") || matchtype.equals("SERVER")) { errorsfound = errorsfound | senddata(game, data, outtxt, true, results, i, battlesnum, prioritybattles); } if (sizesfile.length() != 0) { // upload also related competitions if (minibots.length() != 0 && !matchtype.equals("NANO") && !matchtype.equals("MICRO") && size.checkCompetitorsForSize(first[0], second[0], 1500)) { data = "version=1" + "&" + "client=" + client + "&" + "teams=" + teams + "&" + "melee=" + melee + "&" + "game=" + minibots + "&" + "rounds=" + header[1] + "&" + "field=" + header[2] + "&" + "user=" + user + "&" + "time=" + header[4] + "&" + "fname=" + first[0] + "&" + "fscore=" + first[1] + "&" + "fbulletd=" + first[2] + "&" + "fsurvival=" + first[3] + "&" + "sname=" + second[0] + "&" + "sscore=" + second[1] + "&" + "sbulletd=" + second[2] + "&" + "ssurvival=" + second[3]; errorsfound = errorsfound | senddata(minibots, data, outtxt, false, results, i, battlesnum, null); } if (microbots.length() != 0 && !matchtype.equals("NANO") && size.checkCompetitorsForSize(first[0], second[0], 750)) { data = "version=1" + "&" + "client=" + client + "&" + "teams=" + teams + "&" + "melee=" + melee + "&" + "game=" + microbots + "&" + "rounds=" + header[1] + "&" + "field=" + header[2] + "&" + "user=" + user + "&" + "time=" + header[4] + "&" + "fname=" + first[0] + "&" + "fscore=" + first[1] + "&" + "fbulletd=" + first[2] + "&" + "fsurvival=" + first[3] + "&" + "sname=" + second[0] + "&" + "sscore=" + second[1] + "&" + "sbulletd=" + second[2] + "&" + "ssurvival=" + second[3]; errorsfound = errorsfound | senddata(microbots, data, outtxt, false, results, i, battlesnum, null); } if (nanobots.length() != 0 && size.checkCompetitorsForSize(first[0], second[0], 250)) { data = "version=1" + "&" + "client=" + client + "&" + "game=" + nanobots + "&" + "rounds=" + header[1] + "&" + "field=" + header[2] + "&" + "user=" + user + "&" + "time=" + header[4] + "&" + "fname=" + first[0] + "&" + "fscore=" + first[1] + "&" + "fbulletd=" + first[2] + "&" + "fsurvival=" + first[3] + "&" + "sname=" + second[0] + "&" + "sscore=" + second[1] + "&" + "sbulletd=" + second[2] + "&" + "ssurvival=" + second[3]; errorsfound = errorsfound | senddata(nanobots, data, outtxt, false, results, i, battlesnum, null); } } } // close files outtxt.close(); battlesnum.close(); prioritybattles.close(); // delete results file File r = new File(resultsfile); boolean b = r.delete(); if (!b) { System.out.println("Unable to delete results file."); } // copy temp file into results file if there was some error if (errorsfound) { if (!FileTransfer.copy(tempdir + "results.txt", resultsfile)) { System.out.println("Error when copying results errors file."); } } } private void saverror(PrintStream outtxt, String match, String bot1, String bot2, boolean saveonerror) { if (saveonerror) { outtxt.println(match); outtxt.println(bot1); outtxt.println(bot2); } System.out.println("Unable to upload results " + match + " " + bot1 + " " + bot2); } private boolean senddata(String game, String data, PrintStream outtxt, boolean saveonerror, Vector results, int i, PrintStream battlesnum, PrintStream prioritybattles) { boolean errorsfound = false; PrintWriter wr = null; BufferedReader rd = null; try { // Send data URL url = new URL(resultsurl); URLConnection conn = url.openConnection(); conn.setDoOutput(true); wr = new PrintWriter(new OutputStreamWriter(conn.getOutputStream())); wr.println(data); wr.flush(); // Get the response rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); String line; boolean ok = false; while ((line = rd.readLine()) != null) { if (line.indexOf("OK") != -1) { ok = true; System.out.println(line); } else if (line.indexOf("<") != -1 && line.indexOf(">") != -1) { // System.out.println(line); // Save the number of battles for the bots into battlesnum !!!!!!!!!!!!! String bot1 = results.get(i * 3 + 1); bot1 = bot1.substring(0, bot1.indexOf(",")); String bot2 = results.get(i * 3 + 2); bot2 = bot2.substring(0, bot2.indexOf(",")); line = line.replaceAll("<", ""); line = line.replaceAll(">", ""); String[] b = line.split(" "); if (b.length == 2) { battlesnum.println(game + "," + bot1 + "," + b[0]); battlesnum.println(game + "," + bot2 + "," + b[1]); } } else if (line.indexOf("[") != -1 && line.indexOf("]") != -1) { line = line.substring(1); line = line.substring(0, line.length() - 1); String[] items = line.split(","); String bot1 = items[0].substring(0, items[0].lastIndexOf("_")) + " " + items[0].substring(items[0].lastIndexOf("_") + 1); String bot2 = items[1].substring(0, items[1].lastIndexOf("_")) + " " + items[1].substring(items[1].lastIndexOf("_") + 1); String battle = bot1 + "," + bot2 + "," + "SERVER"; if (prioritybattles != null) { prioritybattles.println(battle); } } else { System.out.println(line); } } if (!ok) { saverror(outtxt, results.get(i * 3), results.get(i * 3 + 1), results.get(i * 3 + 2), saveonerror); if (saveonerror) { errorsfound = true; } } } catch (IOException e) { System.out.println(e); if (saveonerror) { errorsfound = true; } saverror(outtxt, results.get(i * 3), results.get(i * 3 + 1), results.get(i * 3 + 2), saveonerror); } finally { if (wr != null) { wr.close(); } if (rd != null) { try { rd.close(); } catch (IOException ignored) {} } } return errorsfound; } } robocode/roborumble/teamrumble.bat0000644000175000017500000000024111052312554016634 0ustar lambylambyjava -Xmx128M -Dsun.io.useCanonCaches=false -cp libs/robocode.jar;libs/codesize.jar;libs/roborumble.jar roborumble.RoboRumbleAtHome ./roborumble/teamrumble.txt robocode/roborumble/.project0000644000175000017500000000146111052367066015473 0ustar lambylamby roborumble robocode robocodeextract org.eclipse.jdt.core.javabuilder org.eclipse.ui.externaltools.ExternalToolBuilder full,incremental, LaunchConfigHandle <project>/.externalToolBuilders/Ant Builder - prepare roborumble launch dir.launch org.eclipse.jdt.core.javanature robocode/roborumble/config/0000755000175000017500000000000011054357656015275 5ustar lambylambyrobocode/roborumble/config/meleerumble.txt0000644000175000017500000002422311052312554020321 0ustar lambylamby#=============================================================================== # meleerumble.txt - Configuration file for MeleeRumble (melee battles) #=============================================================================== #------------------------------------------------------------------------------- # User property. It's highly recommendable that you change this to use your name #------------------------------------------------------------------------------- # USER The user name used when uploading the results to the RoboRumble # server. Hence, you should replace 'Put_Your_Name_Here' with your # name, which could be the initials you use for your robot(s). USER=Put_Your_Name_Here #------------------------------------------------------------------------------- # Exclude filter used for excluding participants. Use with care! #------------------------------------------------------------------------------- # EXCLUDE A comma separated list of all the participants you want to exclude # from the competition. Excluded participants will not be downloaded # or take part in battles. This way you can exclude participants that # cannot be downloaded due to web servers that are down or hanging, # the repository is down, robots/teams that crashes for some reason or # cause other trouble. # # You can use the filename wildcards * and ? in the filter. Example: # # EXCLUDE=xyz.*v1.?, *Nano* EXCLUDE= #------------------------------------------------------------------------------- # Properties for controlling the rumble. Use YES or NOT #------------------------------------------------------------------------------- # DOWNLOAD Download data like participants, missing robots, rating files etc. # from Internet if these have not been downloaded for 2 hours. # # EXECUTE Execute battles. Battles files are first created and old battles # files are deleted before the battles are executed. # # UPLOAD Upload results to the RoboRumble server specified by the RESULTSURL # property. # # ITERATE If set to NOT, the rumble will only execute battles once. # If set to YES, the rumble will restart with new battles every time # the battles have been executed, and it will run infinitely until # terminated. DOWNLOAD=YES EXECUTE=YES UPLOAD=YES ITERATE=NOT # MELEE Must be set if this rumble is meant for melee battles. # # TEAMS Must be set if this rumble is meant for team battles. # This flag is necessary, as jar files for robot teams are different # from jar files for ordinary robots. # MELEE=YES as this property file is meant for melee battles. # TEAM=NOT, as this property file is not meant for team battles. # Do not modify these properties! MELEE=YES TEAMS=NOT #------------------------------------------------------------------------------ # Properties for the battle engine #------------------------------------------------------------------------------ # FIELDL Battlefield width measured in pixels. # FIELDH Battlefield height measured in pixels. # # NUMBATTLES Number of battles performed per rumble. # ROUNDS Number of rounds per battle. # # MELEEBOTS Number of robots that participate in a melee battle. # These are standard values for the MeleeRumble. Do not modify these properties! FIELDL=1000 FIELDH=1000 NUMBATTLES=3 ROUNDS=35 MELEEBOTS=10 # INPUT Input battles file that is generated by the rumble automatically. # The rumble uses this file for selecting which robots that must # battle against each other. # # OUTPUT Battle results file, which is the output of running the rumble. INPUT=./roborumble/temp/battlesmelee.txt OUTPUT=./roborumble/files/resultsmelee.txt #------------------------------------------------------------------------------- # Properties for retrieving robots from Internet #------------------------------------------------------------------------------- # BOTSREP The robot repository where downloaded robots are put. # # TEMP Directory containing all temporary files for RoboRumble. BOTSREP=./robots/ TEMP=./roborumble/temp/ #------------------------------------------------------------------------------- # Properties for updating participants from Internet #------------------------------------------------------------------------------- # PARTICIPANTSURL # URL to the web page containing all participants of the competition, # which will be used for updating the participants file specified with # the PARTICIPANTSFILE property. # # PARTICIPANTSFILE # File containing all the participants for the competition. # # STARTAG Tag marking the start and end of the participants on the web page # pointed to with the PARTICIPANTSURL property. # # UPDATEBOTSURL # URL used for removing old participants, which is used for updating # the participants file specified with the PARTICIPANTSFILE property. PARTICIPANTSURL=http://robowiki.net/cgi-bin/robowiki?RoboRumble/MeleeParticipants PARTICIPANTSFILE=./roborumble/files/participmelee.txt STARTAG=pre UPDATEBOTSURL=http://rumble.fervir.com/rumble/RemoveOldParticipant #------------------------------------------------------------------------------- # Properties to control the way battles are run #------------------------------------------------------------------------------- # RUNONLY If left black or set to GENERAL, a new battle file is created where # robots from the participants file are paired at random. The number # of robot pairs will match number of battles defined the NUMBATTLES # property. # # If set to MINI, a new battle file is created similar to the one # for GENERAL, but it will only contains robots that are MiniBots, # which has a code size < 1500 bytes (calculated by the codesize tool). # # If set to MICRO, a new battle file is created similar to the one # for GENERAL, but it will only contains robots that are MicroBots, # which has a code size < 750 bytes (calculated by the codesize tool). # # If set to NANO, a new battle file is created similar to the one for # GENERAL, but it will only contains robots that are NanoBots, which # has a code size < 250 bytes (calculated by the codesize tool). # # If set to SERVER (recommended), a new battle file is created which # will first of all contain priority battles for robots that that has # priority over other robots until they have fought a specific number # of battles specified by the BATTLESPERBOT property. The number of # battles fought by the individual robots are extracted from the # rating files, which are downloaded from the server if the DOWNLOAD # property is set to YES. When no more priority battles are left, # robots from the participants file are paired at random similar to # GENERAL. # # BATTLESPERBOT # The number of battles a robot has to fight before it will no longer # have priority over other robots in battles. Prioritizing a robot # makes its rating more reliable faster as its number of fought # battles increases faster than when it is not prioritized. # # PRIORITYBATTLESFILE # The priority battles file that is generated automatically by the # rumble when the RUNONLY property is set to SERVER. RUNONLY=SERVER BATTLESPERBOT=2000 PRIORITYBATTLESFILE=./roborumble/temp/prioritymelee.txt #------------------------------------------------------------------------------- # Properties for uploading the results to the server #------------------------------------------------------------------------------- # RESULTSURL # URL used for uploading the results to the server. # # BATTLESNUMFILE # File containing the number of battles fought by the robots, which is # returned by the server when results are uploaded to the server. RESULTSURL=http://rumble.fervir.com/rumble/UploadedResults BATTLESNUMFILE=./roborumble/temp/meleebattlesnumber.txt #------------------------------------------------------------------------------- # Properties for related competitions #------------------------------------------------------------------------------- # Related competitions are competitions where participants are a subset of the # participants in the general competition. # # The MiniBots (code size < 1500) are participants of the MiniRumble. # The MicroBots (code size < 750) are participants of the MicroRumble. # The NanoBots (code size < 250) are participants of the NanoRumble. # Do not modify these properties! MINIBOTS=minimeleerumble MICROBOTS=micromeleerumble NANOBOTS=nanomeleerumble # CODESIZEFILE: # The code size file that is generated automatically by the rumble in # order determine the code size of each individual robot. CODESIZEFILE=./roborumble/files/codesizemelee.txt #------------------------------------------------------------------------------- # Properties for URLs and file names for the rating files to download #------------------------------------------------------------------------------- # RATINGS.URL: # URL to where ratings files are located on Internet. # # RATINGS.GENERAL: # File name for the rating file of the general MeleeRumble. # # RATINGS.MINIBOTS: # File name for the rating file of the Melee MiniRumble. # # RATINGS.MICROBOTS: # File name for the rating file of the Melee MicroRumble. # # RATINGS.NANOBOTS: # File name for the rating file of the Melee NanoRumble. RATINGS.URL=http://rumble.fervir.com/rumble/RatingsFile RATINGS.GENERAL=./roborumble/temp/ratings_m_roborumble.txt RATINGS.MINIBOTS=./roborumble/temp/ratings_m_minirumble.txt RATINGS.MICROBOTS=./roborumble/temp/ratings_m_microrumble.txt RATINGS.NANOBOTS=./roborumble/temp/ratings_m_nanorumble.txt robocode/roborumble/config/roborumble.txt0000644000175000017500000002377111052312554020202 0ustar lambylamby#=============================================================================== # roborumble.txt - Configuration file for RoboRumble (1v1 battles) #=============================================================================== #------------------------------------------------------------------------------- # Username. It's highly recommendable that you change this to use your name #------------------------------------------------------------------------------- # USER The username used when uploading the results to the RoboRumble # server. Hence, you should replace 'Put_Your_Name_Here' with your # name, which could be the initials you use for your robot(s). USER=Put_Your_Name_Here #------------------------------------------------------------------------------- # Exclude filter used for excluding participants. Use with care! #------------------------------------------------------------------------------- # EXCLUDE A comma separated list of all the participants you want to exclude # from the competition. Excluded participants will not be downloaded # or take part in battles. This way you can exclude participants that # cannot be downloaded due to web servers that are down or hanging, # the repository is down, robots/teams that crashes for some reason or # cause other trouble. # # You can use the filename wildcards * and ? in the filter. Example: # # EXCLUDE=xyz.*v1.?, *Nano* EXCLUDE= #------------------------------------------------------------------------------- # Properties for controlling the rumble. Use YES or NOT #------------------------------------------------------------------------------- # DOWNLOAD Download data like participants, missing robots, rating files etc. # from Internet if these have not been downloaded for 2 hours. # # EXECUTE Execute battles. Battles files are first created and old battles # files are deleted before the battles are executed. # # UPLOAD Upload results to the RoboRumble server specified by the RESULTSURL # property. # # ITERATE If set to NOT, the rumble will only execute battles once. # If set to YES, the rumble will restart with new battles every time # the battles have been executed, and it will run infinitely until # terminated. DOWNLOAD=YES EXECUTE=YES UPLOAD=YES ITERATE=NOT # MELEE Must be set if this rumble is meant for melee battles. # # TEAMS Must be set if this rumble is meant for team battles. # This flag is necessary, as jar files for robot teams are different # from jar files for ordinary robots. # MELEE=NOT as this property file is not meant for melee battles. # TEAM=NOT, as this property file is not meant for team battles. # Do not modify these properties! MELEE=NOT TEAMS=NOT #------------------------------------------------------------------------------ # Properties for the battle engine #------------------------------------------------------------------------------ # FIELDL Battlefield width measured in pixels. # FIELDH Battlefield height measured in pixels. # # NUMBATTLES Number of battles performed per rumble. # ROUNDS Number of rounds per battle. # These are standard values for the RoboRumble. Do not modify these properties! FIELDL=800 FIELDH=600 NUMBATTLES=10 ROUNDS=35 # INPUT Input battles file that is generated by the rumble automatically. # The rumble uses this file for selecting which robots that must # battle against each other. # # OUTPUT Battle results file, which is the output of running the rumble. INPUT=./roborumble/temp/battles1v1.txt OUTPUT=./roborumble/files/results1v1.txt #------------------------------------------------------------------------------- # Properties for retrieving robots from Internet #------------------------------------------------------------------------------- # BOTSREP The robot repository where downloaded robots are put. # # TEMP Directory containing all temporary files for RoboRumble. BOTSREP=./robots/ TEMP=./roborumble/temp/ #------------------------------------------------------------------------------- # Properties for updating participants from Internet #------------------------------------------------------------------------------- # PARTICIPANTSURL # URL to the web page containing all participants of the competition, # which will be used for updating the participants file specified with # the PARTICIPANTSFILE property. # # PARTICIPANTSFILE # File containing all the participants for the competition. # # STARTAG Tag marking the start and end of the participants on the web page # pointed to with the PARTICIPANTSURL property. # # UPDATEBOTSURL # URL used for removing old participants, which is used for updating # the participants file specified with the PARTICIPANTSFILE property. PARTICIPANTSURL=http://robowiki.net/cgi-bin/robowiki?RoboRumble/Participants PARTICIPANTSFILE=./roborumble/files/particip1v1.txt STARTAG=pre UPDATEBOTSURL=http://rumble.fervir.com/rumble/RemoveOldParticipant #------------------------------------------------------------------------------- # Properties to control the way battles are run #------------------------------------------------------------------------------- # RUNONLY If left black or set to GENERAL, a new battle file is created where # robots from the participants file are paired at random. The number # of robot pairs will match number of battles defined the NUMBATTLES # property. # # If set to MINI, a new battle file is created similar to the one # for GENERAL, but it will only contains robots that are MiniBots, # which has a code size < 1500 bytes (calculated by the codesize tool). # # If set to MICRO, a new battle file is created similar to the one # for GENERAL, but it will only contains robots that are MicroBots, # which has a code size < 750 bytes (calculated by the codesize tool). # # If set to NANO, a new battle file is created similar to the one for # GENERAL, but it will only contains robots that are NanoBots, which # has a code size < 250 bytes (calculated by the codesize tool). # # If set to SERVER (recommended), a new battle file is created which # will first of all contain priority battles for robots that that has # priority over other robots until they have fought a specific number # of battles specified by the BATTLESPERBOT property. The number of # battles fought by the individual robots are extracted from the # rating files, which are downloaded from the server if the DOWNLOAD # property is set to YES. When no more priority battles are left, # robots from the participants file are paired at random similar to # GENERAL. # # BATTLESPERBOT # The number of battles a robot has to fight before it will no longer # have priority over other robots in battles. Prioritizing a robot # makes its rating more reliable faster as its number of fought # battles increases faster than when it is not prioritized. # # PRIORITYBATTLESFILE # The priority battles file that is generated automatically by the # rumble when the RUNONLY property is set to SERVER. RUNONLY=SERVER BATTLESPERBOT=2000 PRIORITYBATTLESFILE=./roborumble/temp/priority1v1.txt #------------------------------------------------------------------------------- # Properties for uploading the results to the server #------------------------------------------------------------------------------- # RESULTSURL # URL used for uploading the results to the server. # # BATTLESNUMFILE # File containing the number of battles fought by the robots, which is # returned by the server when results are uploaded to the server. RESULTSURL=http://rumble.fervir.com/rumble/UploadedResults BATTLESNUMFILE=./roborumble/temp/battlesnumber.txt #------------------------------------------------------------------------------- # Properties for related competitions #------------------------------------------------------------------------------- # Related competitions are competitions where participants are a subset of the # participants in the general competition. # # The MiniBots (code size < 1500) are participants of the MiniRumble. # The MicroBots (code size < 750) are participants of the MicroRumble. # The NanoBots (code size < 250) are participants of the NanoRumble. # Do not modify these properties! MINIBOTS=minirumble MICROBOTS=microrumble NANOBOTS=nanorumble # CODESIZEFILE: # The code size file that is generated automatically by the rumble in # order determine the code size of each individual robot. CODESIZEFILE=./roborumble/files/codesize1v1.txt #------------------------------------------------------------------------------- # Properties for URLs and file names for the rating files to download #------------------------------------------------------------------------------- # RATINGS.URL: # URL to where ratings files are located on Internet. # # RATINGS.GENERAL: # File name for the rating file of the general RoboRumble. # # RATINGS.MINIBOTS: # File name for the rating file of the MiniRumble. # # RATINGS.MICROBOTS: # File name for the rating file of the MicroRumble. # # RATINGS.NANOBOTS: # File name for the rating file of the NanoRumble. RATINGS.URL=http://rumble.fervir.com/rumble/RatingsFile RATINGS.GENERAL=./roborumble/temp/ratings_roborumble.txt RATINGS.MINIBOTS=./roborumble/temp/ratings_minirumble.txt RATINGS.MICROBOTS=./roborumble/temp/ratings_microrumble.txt RATINGS.NANOBOTS=./roborumble/temp/ratings_nanorumble.txt robocode/roborumble/config/teamrumble.txt0000644000175000017500000002043711054357656020201 0ustar lambylamby#=============================================================================== # teamrumble.txt - Configuration file for TeamRumble (team battles) #=============================================================================== #------------------------------------------------------------------------------- # User property. It's highly recommendable that you change this to use your name #------------------------------------------------------------------------------- # USER The user name used when uploading the results to the RoboRumble # server. Hence, you should replace 'Put_Your_Name_Here' with your # name, which could be the initials you use for your robot(s). USER=Put_Your_Name_Here #------------------------------------------------------------------------------- # Exclude filter used for excluding participants. Use with care! #------------------------------------------------------------------------------- # EXCLUDE A comma separated list of all the participants you want to exclude # from the competition. Excluded participants will not be downloaded # or take part in battles. This way you can exclude participants that # cannot be downloaded due to web servers that are down or hanging, # the repository is down, robots/teams that crashes for some reason or # cause other trouble. # # You can use the filename wildcards * and ? in the filter. Example: # # EXCLUDE=xyz.*v1.?, *Nano* EXCLUDE= #------------------------------------------------------------------------------- # Properties for controlling the rumble. Use YES or NOT #------------------------------------------------------------------------------- # DOWNLOAD Download data like participants, missing robots, rating files etc. # from Internet if these have not been downloaded for 2 hours. # # EXECUTE Execute battles. Battles files are first created and old battles # files are deleted before the battles are executed. # # UPLOAD Upload results to the RoboRumble server specified by the RESULTSURL # property. # # ITERATE If set to NOT, the rumble will only execute battles once. # If set to YES, the rumble will restart with new battles every time # the battles have been executed, and it will run infinitely until # terminated. DOWNLOAD=YES EXECUTE=YES UPLOAD=YES ITERATE=NOT # MELEE Must be set if this rumble is meant for melee battles. # # TEAMS Must be set if this rumble is meant for team battles. # This flag is necessary, as jar files for robot teams are different # from jar files for ordinary robots. # MELEE=NOT as this property file is not meant for melee battles. # TEAM=YES, as this property file is meant for team battles. # Do not modify these properties! MELEE=NOT TEAMS=YES #------------------------------------------------------------------------------ # Properties for the battle engine #------------------------------------------------------------------------------ # FIELDL Battlefield width measured in pixels. # FIELDH Battlefield height measured in pixels. # # NUMBATTLES Number of battles performed per rumble. # ROUNDS Number of rounds per battle. # These are standard values for the TeamRumble. Do not modify these properties! FIELDL=1200 FIELDH=1200 NUMBATTLES=10 ROUNDS=10 # INPUT Input battles file that is generated by the rumble automatically. # The rumble uses this file for selecting which robots that must # battle against each other. # # OUTPUT Battle results file, which is the output of running the rumble. INPUT=./roborumble/temp/battlesTeams.txt OUTPUT=./roborumble/files/resultsTeams.txt #------------------------------------------------------------------------------- # Properties for retrieving robots from Internet #------------------------------------------------------------------------------- # BOTSREP The robot repository where downloaded robots are put. # # TEMP Directory containing all temporary files for RoboRumble. BOTSREP=./robots/ TEMP=./roborumble/temp/ #------------------------------------------------------------------------------- # Properties for updating participants from Internet #------------------------------------------------------------------------------- # PARTICIPANTSURL # URL to the web page containing all participants of the competition, # which will be used for updating the participants file specified with # the PARTICIPANTSFILE property. # # PARTICIPANTSFILE # File containing all the participants for the competition. # # STARTAG Tag marking the start and end of the participants on the web page # pointed to with the PARTICIPANTSURL property. # # UPDATEBOTSURL # URL used for removing old participants, which is used for updating # the participants file specified with the PARTICIPANTSFILE property. PARTICIPANTSURL=http://robowiki.net/cgi-bin/robowiki?RoboRumble/ParticipantTeams PARTICIPANTSFILE=./roborumble/files/participTeams.txt STARTAG=pre UPDATEBOTSURL=http://rumble.fervir.com/rumble/RemoveOldParticipant #------------------------------------------------------------------------------- # Properties to control the way battles are run #------------------------------------------------------------------------------- # RUNONLY If left black or set to GENERAL, a new battle file is created where # robots from the participants file are paired at random. The number # of robot pairs will match number of battles defined the NUMBATTLES # property. # # If set to SERVER (recommended), a new battle file is created which # will first of all contain priority battles for robots that that has # priority over other robots until they have fought a specific number # of battles specified by the BATTLESPERBOT property. The number of # battles fought by the individual robots are extracted from the # rating files, which are downloaded from the server if the DOWNLOAD # property is set to YES. When no more priority battles are left, # robots from the participants file are paired at random similar to # GENERAL. # # BATTLESPERBOT # The number of battles a robot has to fight before it will no longer # have priority over other robots in battles. Prioritizing a robot # makes its rating more reliable faster as its number of fought # battles increases faster than when it is not prioritized. # # PRIORITYBATTLESFILE # The priority battles file that is generated automatically by the # rumble when the RUNONLY property is set to SERVER. RUNONLY=SERVER BATTLESPERBOT=200 PRIORITYBATTLESFILE=./roborumble/temp/priorityTeams.txt #------------------------------------------------------------------------------- # Properties for uploading the results to the server #------------------------------------------------------------------------------- # RESULTSURL # URL used for uploading the results to the server. # # BATTLESNUMFILE # File containing the number of battles fought by the robots, which is # returned by the server when results are uploaded to the server. RESULTSURL=http://rumble.fervir.com/rumble/UploadedResults BATTLESNUMFILE=./roborumble/temp/teambattlesnumber.txt #------------------------------------------------------------------------------- # Properties for URLs and file names for the rating files to download #------------------------------------------------------------------------------- # RATINGS.URL: # URL to where ratings files are located on Internet. # # RATINGS.GENERAL: # File name for the rating file of the general RoboRumble. # # RATINGS.MINIBOTS: # File name for the rating file of the MiniRumble. # # RATINGS.MICROBOTS: # File name for the rating file of the MicroRumble. # # RATINGS.NANOBOTS: # File name for the rating file of the NanoRumble. RATINGS.URL=http://rumble.fervir.com/rumble/RatingsFile RATINGS.GENERAL=./roborumble/temp/ratings_teamrumble.txt robocode/roborumble/.classpath0000644000175000017500000000067411052367140016005 0ustar lambylamby robocode/roborumble/TeamRumble.launch0000644000175000017500000000725411130006064017244 0ustar lambylamby robocode/roborumble/roborumble.iml0000644000175000017500000000161411105671244016672 0ustar lambylamby robocode/roborumble/meleerumble.bat0000644000175000017500000000024211052312554016776 0ustar lambylambyjava -Xmx256M -Dsun.io.useCanonCaches=false -cp libs/robocode.jar;libs/codesize.jar;libs/roborumble.jar roborumble.RoboRumbleAtHome ./roborumble/meleerumble.txt robocode/roborumble/teamrumble.sh0000644000175000017500000000025311070001622016472 0ustar lambylamby#!/bin/bash java -Xmx128M -Dsun.io.useCanonCaches=false -cp libs/robocode.jar:libs/codesize.jar:libs/roborumble.jar roborumble.RoboRumbleAtHome ./roborumble/teamrumble.txtrobocode/roborumble/RoboRumble.launch0000644000175000017500000000725411067660462017300 0ustar lambylamby robocode/roborumble/meleerumble.sh0000644000175000017500000000025411052312554016645 0ustar lambylamby#!/bin/bash java -Xmx256M -Dsun.io.useCanonCaches=false -cp libs/robocode.jar:libs/codesize.jar:libs/roborumble.jar roborumble.RoboRumbleAtHome ./roborumble/meleerumble.txtrobocode/roborumble/roborumble.sh0000644000175000017500000000025311052312554016516 0ustar lambylamby#!/bin/bash java -Xmx256M -Dsun.io.useCanonCaches=false -cp libs/robocode.jar:libs/codesize.jar:libs/roborumble.jar roborumble.RoboRumbleAtHome ./roborumble/roborumble.txtrobocode/roborumble/.settings/0000755000175000017500000000000011052367330015732 5ustar lambylambyrobocode/roborumble/.settings/org.eclipse.jdt.core.prefs0000644000175000017500000000242311052367330022715 0ustar lambylamby#Fri Jul 04 00:38:32 CEST 2008 eclipse.preferences.version=1 org.eclipse.jdt.core.builder.cleanOutputFolder=clean org.eclipse.jdt.core.builder.duplicateResourceTask=warning org.eclipse.jdt.core.builder.invalidClasspath=abort org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch, .*, *.xml, *.iml, *.bat, *.sh, config org.eclipse.jdt.core.circularClasspath=error org.eclipse.jdt.core.classpath.exclusionPatterns=enabled org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.5 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.maxProblemPerUnit=100 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.source=1.5 org.eclipse.jdt.core.incompatibleJDKLevel=ignore org.eclipse.jdt.core.incompleteClasspath=error robocode/roborumble/roborumble.bat0000644000175000017500000000024111052312554016647 0ustar lambylambyjava -Xmx256M -Dsun.io.useCanonCaches=false -cp libs/robocode.jar;libs/codesize.jar;libs/roborumble.jar roborumble.RoboRumbleAtHome ./roborumble/roborumble.txt robocode/build/0000755000175000017500000000000011131763570012747 5ustar lambylambyrobocode/build/build.xml0000644000175000017500000005345111124141222014562 0ustar lambylamby Apache Ant build script for building the Robocode archive files Robocode ${version} API]]> robocode/build/.project0000644000175000017500000000026411052647622014421 0ustar lambylamby build robocode/build/build.iml0000644000175000017500000000061711052647622014556 0ustar lambylamby robocode/autoextract/0000755000175000017500000000000011125275000014200 5ustar lambylambyrobocode/autoextract/.project0000644000175000017500000000070511125274756015672 0ustar lambylamby autoextract build robocodeextract org.eclipse.jdt.core.javabuilder org.eclipse.jdt.core.javanature robocode/autoextract/.classpath0000644000175000017500000000045011125274756016203 0ustar lambylamby robocode/autoextract/autoextract.iml0000644000175000017500000000074411125274756017274 0ustar lambylamby robocode/autoextract/robocode/0000755000175000017500000000000011125274756016015 5ustar lambylambyrobocode/autoextract/robocode/AutoExtract.java0000644000175000017500000003741411130241110021102 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Replaced deprecated methods * - Added check for the Java version that the user has installed. If the * Java version is not 5.0, an error dialog will be display and the * installation will terminate * - Changed the information message for how to run robocode.sh, where the * user does not have to change the directory before calling robocode.sh * - Code cleanup *******************************************************************************/ package robocode; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.*; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.JarInputStream; /** * Installer for Robocode. * * @author Mathew A. Nelsen (original) * @author Flemming N. Larsen (contributor) */ public class AutoExtract implements ActionListener { public JDialog licenseDialog; public boolean accepted; public String spinner[] = { "-", "\\", "|", "/"}; public String message = ""; public static String osName = System.getProperty("os.name"); public static double osVersion = doubleValue(System.getProperty("os.version")); public static String javaVersion = System.getProperty("java.version"); /** * AutoExtract constructor. */ public AutoExtract() { super(); } private static double doubleValue(String s) { int p = s.indexOf("."); if (p >= 0) { p = s.indexOf(".", p + 1); } if (p >= 0) { s = s.substring(0, p); } double d = 0.0; try { d = Double.parseDouble(s); } catch (NumberFormatException e) {} return d; } private boolean acceptLicense() { String licenseText = ""; InputStream is; try { JarFile extractJar = new JarFile("extract.jar"); is = extractJar.getInputStream(extractJar.getJarEntry("license/cpl-v10.html")); } catch (IOException e) { return true; } if (is == null) { return true; } BufferedReader r = new BufferedReader(new InputStreamReader(is)); try { String line = r.readLine(); while (line != null) { licenseText += line; line = r.readLine(); } return acceptReject(licenseText); } catch (IOException e) { System.err.println("Could not read line from license file: " + e); } return true; } private boolean acceptReject(String text) { Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); licenseDialog = new JDialog(); licenseDialog.setTitle("License Agreement"); licenseDialog.setModal(true); licenseDialog.setLocation((screenSize.width - 500) / 2, (screenSize.height - 400) / 2); licenseDialog.setSize(500, 400); JTextPane t = new JTextPane(); t.setContentType("text/html"); t.setText(text); t.setFont(new Font("Dialog", Font.PLAIN, 12)); t.setEditable(false); JScrollPane s = new JScrollPane(); s.setViewportView(t); licenseDialog.getContentPane().setLayout(new BorderLayout()); licenseDialog.getContentPane().add(s, BorderLayout.CENTER); JPanel p = new JPanel(); p.setLayout(new BorderLayout()); JButton b1 = new JButton("Accept"); JButton b2 = new JButton("Cancel"); p.add(b1, BorderLayout.WEST); p.add(b2, BorderLayout.EAST); b1.addActionListener(this); b2.addActionListener(this); licenseDialog.getContentPane().add(p, BorderLayout.SOUTH); licenseDialog.setVisible(true); return accepted; } public void actionPerformed(ActionEvent e) { accepted = e.getActionCommand().equals("Accept"); licenseDialog.dispose(); licenseDialog = null; } private boolean extract(String src, File dest) { JDialog statusDialog = new JDialog(); Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); int height = 50; if (File.separatorChar == '/') { height = 100; } statusDialog.setTitle("Installing"); statusDialog.setLocation((screenSize.width - 500) / 2, (screenSize.height - height) / 2); statusDialog.setSize(500, height); JLabel status = new JLabel(); statusDialog.getContentPane().setLayout(new BorderLayout()); statusDialog.getContentPane().add(status, BorderLayout.CENTER); statusDialog.setVisible(true); FileOutputStream fos; String entryName; byte buf[] = new byte[2048]; InputStream is = getClass().getClassLoader().getResourceAsStream(src); if (is == null) { String r = getClass().getClassLoader().getResource(src).toString(); int i = r.lastIndexOf("!"); if (i >= 0) { r = r.substring(0, i); } JOptionPane.showMessageDialog(null, r + "\nContains an exclamation point. Please move the file to a different directory."); System.exit(0); } try { JarInputStream jarIS = new JarInputStream(is); JarEntry entry = jarIS.getNextJarEntry(); while (entry != null) { int spin = 0; entryName = entry.getName(); if (entry == null) { System.err.println("Could not find entry: " + entry); } else { if (entry.isDirectory()) { File dir = new File(dest, entry.getName()); dir.mkdirs(); } else { status.setText(entryName + " " + spinner[spin++]); File out = new File(dest, entry.getName()); File parentDirectory = new File(out.getParent()); parentDirectory.mkdirs(); fos = new FileOutputStream(out); int index = 0; int num; int count = 0; while ((num = jarIS.read(buf, 0, 2048)) != -1) { fos.write(buf, 0, num); index += num; count++; if (count > 80) { status.setText(entryName + " " + spinner[spin++] + " (" + index + " bytes)"); if (spin > 3) { spin = 0; } count = 0; } } fos.close(); if (entryName.length() > 3 && entryName.substring(entryName.length() - 3).equals(".sh")) { if (File.separatorChar == '/') { Runtime.getRuntime().exec("chmod 755 " + out.toString()); } } status.setText(entryName + " " + spinner[spin++] + " (" + index + " bytes)"); } } entry = jarIS.getNextJarEntry(); } statusDialog.dispose(); message = "Installation successful"; return true; } catch (IOException e) { message = "Installation failed" + e; return false; } } public static void main(String argv[]) { // Verify that the Java version is version 5 (1.5.0) or newer if (javaVersion.startsWith("1.") && javaVersion.charAt(2) < '5') { JOptionPane.showMessageDialog(null, "Robocode requires Java 5.0 (1.5.0) or newer.\n" + "Your system is currently running Java " + javaVersion + ".\n" + "If you have not installed (or activated) at least\n" + "JRE 5.0 or JDK 5.0, please do so.", "Error", JOptionPane.ERROR_MESSAGE); System.exit(0); } // Set native look and feel try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Throwable t) {// For some reason Ubuntu 7 can cause a NullPointerException when trying to getting the LAF } File installDir = null; File suggestedDir; AutoExtract extractor = new AutoExtract(); if (extractor.acceptLicense()) { if (argv.length == 1) { suggestedDir = new File(argv[0]); } else if (File.separatorChar == '\\') { suggestedDir = new File("c:\\robocode\\"); } else { suggestedDir = new File(System.getProperty("user.home") + File.separator + "robocode" + File.separator); } boolean done = false; while (!done) { int rc = JOptionPane.showConfirmDialog(null, "Robocode will be installed in:\n" + suggestedDir + "\nIs this ok?", "Installing Robocode", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); if (rc == JOptionPane.YES_OPTION) { installDir = suggestedDir; done = true; } else if (rc == JOptionPane.NO_OPTION) { Object r = JOptionPane.showInputDialog(null, "Please type in the installation directory", "Installation Directory", JOptionPane.PLAIN_MESSAGE, null, null, suggestedDir); if (r == null) { JOptionPane.showMessageDialog(null, "Installation cancelled."); System.exit(0); } else { suggestedDir = new File(((String) r).trim()); } } else if (rc == JOptionPane.CANCEL_OPTION) { JOptionPane.showMessageDialog(null, "Installation cancelled."); System.exit(0); } } if (!installDir.exists()) { int rc = JOptionPane.showConfirmDialog(null, installDir.getPath() + "\ndoes not exist. Would you like to create it?", "Installing Robocode", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); if (rc == JOptionPane.YES_OPTION) { installDir.mkdirs(); } else { JOptionPane.showMessageDialog(null, "Installation cancelled."); System.exit(0); } } boolean rv = extractor.extract("extract.jar", installDir); if (rv) { extractor.createShortcuts(installDir, "robocode.bat", "Robocode", "Robocode"); } else { JOptionPane.showMessageDialog(null, extractor.message); } // Move robocode.properties, window.properties, and compile.properties move(new File(installDir, "robocode.properties"), new File(installDir, "config/robocode.properties")); move(new File(installDir, "window.properties"), new File(installDir, "config/window.properties")); move(new File(installDir, "compiler.properties"), new File(installDir, "config/compiler.properties")); // Move robot.database move(new File(installDir, "robot.database"), new File(installDir, "robots/robot.database")); // Move .robotcache move(new File(installDir, ".robotcache"), new File(installDir, "robots/.robotcache")); // Create RoboRumble dir File roborumbleDir = createDir(new File(installDir, "roborumble")); // Create RoboRumble working dirs createDir(new File(roborumbleDir, "files")); createDir(new File(roborumbleDir, "temp")); // Move RoboRumble config files from /config folder into the /roborumble folder move(new File(installDir, "config/roborumble.txt"), new File(installDir, "roborumble/roborumble.txt")); move(new File(installDir, "config/meleerumble.txt"), new File(installDir, "roborumble/meleerumble.txt")); move(new File(installDir, "config/teamrumble.txt"), new File(installDir, "roborumble/teamrumble.txt")); } else { JOptionPane.showMessageDialog(null, "Installation cancelled."); } System.exit(0); } private void createShortcuts(File installDir, String runnable, String folder, String name) { if (osName.toLowerCase().indexOf("win") == 0) { if (createWindowsShortcuts(installDir, runnable, folder, name)) {} else { JOptionPane.showMessageDialog(null, message + "\n" + "To start Robocode, enter the following at a command prompt:\n" + "cd " + installDir.getAbsolutePath() + "\n" + "robocode.bat"); } } else if (osName.toLowerCase().indexOf("mac") == 0) { if (osVersion >= 10.1) { JOptionPane.showMessageDialog(null, message + "\n" + "To start Robocode, browse to " + installDir + " then double-click robocode.jar\n"); } else { JOptionPane.showMessageDialog(null, message + "\n" + "To start Robocode, enter the following at a command prompt:\n" + installDir.getAbsolutePath() + "/robocode.sh"); } } else { JOptionPane.showMessageDialog(null, message + "\n" + "To start Robocode, enter the following at a command prompt:\n" + installDir.getAbsolutePath() + "/robocode.sh"); } } private boolean createWindowsShortcuts(File installDir, String runnable, String folder, String name) { int rc = JOptionPane.showConfirmDialog(null, "Would you like to install a shortcut to Robocode in the Start menu? (Recommended)", "Create Shortcuts", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); if (rc != JOptionPane.YES_OPTION) { return false; } String command; if (osName.indexOf("9") != -1) { command = "command.com /c cscript.exe "; // /nologo } else { command = "cmd.exe /c cscript.exe "; } // /nologo try { File shortcutMaker = new File(installDir, "makeshortcut.js"); PrintStream out = new PrintStream(new FileOutputStream(shortcutMaker)); out.println("WScript.Echo(\"Creating shortcuts...\");"); out.println("Shell = new ActiveXObject(\"WScript.Shell\");"); out.println("ProgramsPath = Shell.SpecialFolders(\"Programs\");"); out.println("fso = new ActiveXObject(\"Scripting.FileSystemObject\");"); out.println("if (!fso.folderExists(ProgramsPath + \"\\\\" + folder + "\"))"); out.println(" fso.CreateFolder(ProgramsPath + \"\\\\" + folder + "\");"); out.println("link = Shell.CreateShortcut(ProgramsPath + \"\\\\" + folder + "\\\\" + name + ".lnk\");"); out.println("link.Arguments = \"\";"); out.println("link.Description = \"" + name + "\";"); out.println("link.HotKey = \"\";"); out.println("link.IconLocation = \"" + escaped(installDir.getAbsolutePath()) + "\\\\" + "robocode.ico,0\";"); out.println("link.TargetPath = \"" + escaped(installDir.getAbsolutePath()) + "\\\\" + runnable + "\";"); out.println("link.WindowStyle = 1;"); out.println("link.WorkingDirectory = \"" + escaped(installDir.getAbsolutePath()) + "\";"); out.println("link.Save();"); out.println("DesktopPath = Shell.SpecialFolders(\"Desktop\");"); out.println("link = Shell.CreateShortcut(DesktopPath + \"\\\\" + name + ".lnk\");"); out.println("link.Arguments = \"\";"); out.println("link.Description = \"" + name + "\";"); out.println("link.HotKey = \"\";"); out.println("link.IconLocation = \"" + escaped(installDir.getAbsolutePath()) + "\\\\" + "robocode.ico,0\";"); out.println("link.TargetPath = \"" + escaped(installDir.getAbsolutePath()) + "\\\\" + runnable + "\";"); out.println("link.WindowStyle = 1;"); out.println("link.WorkingDirectory = \"" + escaped(installDir.getAbsolutePath()) + "\";"); out.println("link.Save();"); out.println("WScript.Echo(\"Shortcuts created.\");"); out.close(); Process p = Runtime.getRuntime().exec(command + " makeshortcut.js", null, installDir); int rv = p.waitFor(); try { shortcutMaker.delete(); } catch (Exception e) {} if (rv == 0) { JOptionPane.showMessageDialog(null, message + "\n" + "A Robocode program group has been added to your Start menu\n" + "A Robocode icon has been added to your desktop."); return true; } } catch (Exception e) {} return false; } private String escaped(String s) { String r = ""; for (int i = 0; i < s.length(); i++) { if (s.charAt(i) == '\\') { r += '\\'; } r += s.charAt(i); } return r; } private static File createDir(File dir) { if (dir != null && !dir.isDirectory()) { dir.mkdir(); } return dir; } private static void move(File srcFile, File destFile) { if (srcFile != null && destFile != null && srcFile.exists() && !srcFile.equals(destFile)) { byte buf[] = new byte[4096]; try { FileInputStream in = new FileInputStream(srcFile); FileOutputStream out = new FileOutputStream(destFile); while (in.available() > 0) { out.write(buf, 0, in.read(buf, 0, buf.length)); } in.close(); out.close(); } catch (IOException e) {} srcFile.delete(); } } } robocode/autoextract/.settings/0000755000175000017500000000000011125274756016137 5ustar lambylambyrobocode/autoextract/.settings/org.eclipse.jdt.core.prefs0000644000175000017500000000116711125274756023126 0ustar lambylamby#Wed Feb 28 21:41:33 CET 2007 eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.1 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.3 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=ignore org.eclipse.jdt.core.compiler.problem.enumIdentifier=ignore org.eclipse.jdt.core.compiler.source=1.3 robocode/autoextract/AutoExtract.launch0000644000175000017500000000335611125274756017667 0ustar lambylamby robocode/robocodeextract/0000755000175000017500000000000011105671256015037 5ustar lambylambyrobocode/robocodeextract/templates/0000755000175000017500000000000011052312552017025 5ustar lambylambyrobocode/robocodeextract/templates/newrobot.tpt0000644000175000017500000000154011052312552021415 0ustar lambylambypackage $PACKAGE; import robocode.*; //import java.awt.Color; /** * $CLASSNAME - a robot by (your name here) */ public class $CLASSNAME extends Robot { /** * run: $CLASSNAME's default behavior */ public void run() { // After trying out your robot, try uncommenting the import at the top, // and the next line: //setColors(Color.red,Color.blue,Color.green); while(true) { // Replace the next 4 lines with any behavior you would like ahead(100); turnGunRight(360); back(100); turnGunRight(360); } } /** * onScannedRobot: What to do when you see another robot */ public void onScannedRobot(ScannedRobotEvent e) { fire(1); } /** * onHitByBullet: What to do when you're hit by a bullet */ public void onHitByBullet(HitByBulletEvent e) { turnLeft(90 - e.getBearing()); } } robocode/robocodeextract/templates/newjavafile.tpt0000644000175000017500000000015311052312552022050 0ustar lambylambypackage $PACKAGE; /** * $CLASSNAME - a class by (your name here) */ public class $CLASSNAME { } robocode/robocodeextract/robocode.ico0000644000175000017500000006117611052312554017334 0ustar lambylamby 00h ( 00 h^"00 %'  nM h^(0`1%400KH22o&&,J,BS)^]]//ccDDD@wwwwwuDDD@C04` b)"""""""""&ݠ ݢ""""""""""*ݠ ݢ""2"""""""* """""""""*$B*-*$B*ݢMJݤ*bM$DDDDB*&BMUUUUUU*$`ff2UUUUUUY#ff@EeUUUUUUVT` BEU$DDBUTT eETjETVݠMݥ'TErZ&bZLĭZʦffjmZj{jzZݥfk-ҶfZ ݒd'ywwrF)ݠ F*UmUmdDrmuffWJ'D`ff2wrDD'w3ff@BuT:E{$`Bw*{TeZwVݧwZzZzZz tEz ˻˻MԻz ݧ˻˻MԻz g˻˻MԻvݠ B̤"M"$M @M6 ڠ ( @3,%.''S))8C8fG8c\[//PP33""""331HB1UUUU$HB2"""""$kb"2""""&rVffffe&r&b%C""""kD64""""XRd8ERDD%XTHUTEXew̺'uwWwzwwxuwWWHdWxE8EUUT6EUvhUScEYUUTuYWuYZnzXKyxHGXW33(332hk;( 17,+U,,UNNkPPpoo33GG֒ """Z2"""C3337sU7""SU76ESDufVVhe75FeSuV4JDghĈ~ix:Yeh P!pP(0`    # $ *,".+(,15:>248%###%%%) ,!!)))///3##0'':##<$$5++0..9,,=,,5<&222444911=55888=88===AEHHNQUZ]B++D,,I((T((@66G55K22K77G??b d!!h""l##n$$q%%y((}))|22r??K#;L/>>>/Ae|QH ZZZZP)PPPPHHFb,WffY,bF77PPPP).WWWWA6ii2#ee#2iiAiWWWW.{ffff,HBjjjjee!jjjjBj/,ffff{~~~~R0kCkkkk0ee"kkkkEC5R~~~~YADGllll0ee"llllllCYוbDmmmmmm1ee"mmmmmmDbדgEoooooo2ee"ooooooEgfFxvvvup7(SeeV2pvvvvFfaFvqqqvqqq(|}(qqqvqqqvFayWFvqqqvqqq(|}(qqqvqqqvFWyb{{{{PFvqqqvqqq(|}(qqqvqqqvFP{{{{bVbbbb)vvvd' (|}( LMvvv)bbbbV,RRRRRRR(|}(RRRRRRR,(|}(PeSS{SScSSSSSSSe( @  % *,*-1482719=9<#(5# %%%(!!*$$***---7!!3%%5$$:""9&&=&&0))7--:))=((?--000600444?00999<::<<<AEEJMKNQUaF!!A&&G&&J!!I&&M$$A((G++A--J))R!!W##Z*$\.&S))^((B33D22B66G44H66M44J99K>>O<<S11R55T66^22Z66U::P<<W==Y88];;\==d""f''m##h&&n$$f((q%%v&&z((}((a55l22j66`>>j88h>>8C8fG8BBBDDDIHHNNNS@@WAAQDDUFF^CCXFFPOO[HH^JJ[NN^MMPPPUUUXQQ_RR]VVYYY]]]dFFnCCmFFaKKdIIbLLoNNrGGzCC|KKvWKcQQfQQ`WWjPPhUUbXX`]]jZZl]]tSS~SSUUs\\cccdaaeeel``mggiiilllqllrrruuuttxxx~~~++++,,,,..1111??2222<<@@DDLLEE@@IITTTTZZGGKKNNqqqq~~ʇӋ阘~*T~Ҩ*T~&*&T&~& 7777777  + ;??????>"00,&6wXQ؇~/QuQQQQQQQQ/W}ѰUWҫI)}S(% xGY88888888R/y 'IH>:****:>ET(##/VA<..?###+++2&&9''>%%7((:**>))67/555:::===AD@E##J!!A++A,,S$$A00C55E66I99R11W77]22Y==i))q&&}((n81f==h>>r33}55AAAGGGOCCMMMPDD]@@WHH[HH]HH]OOQQQTTTYYY]]]`@@o@@zIBxIIbRRfSSfTThRRjTTfXXjYY~SS```nffnnnynntttyyy,,--55>>BBRRHH֒T~*~T~~~~~*~**~T*~~*~*~*~T~*T~TT~~T~T~T~~~*~~T~~~~~~~~~~*~T~~~~Ҩ~~*~T~~~~~*T~***T*~***T*TTT~TTT~*~T~~~~~*T~ҨҨ*ҨTҨ~ҨҨҨ*T~***T*~***T*TTT~TTT~*~T~~~~~*T~Ҩ*T~*T~***T*~***T*TTT~TTT~*~T~~~~~*T~Ҩ*T~&*&T&~& 2Y  Y?Zh% h`eb$N\\\\Qbe2>M 8>5Q#I46)%Q=ehDF^iid7Fhgag9/F11EA:gcP";'GH);P<>L+([_&+!LLfc.R,]c*S0ceQjKVUJOTVWj_Y7XB@I-XCY?3LQ?sAsAsAsAsAsAsAsAsAsAsAsAsAsAsAsA(0` ***888888888888888888888r%%r%%r%%r%%r%%r%%r%%r%%r%%r%%r%%U888888888888888888888***JJJcccccccccccc<<< ,,22222222222222222222r%% <<>>88,,rrr "5++5++5++5++5++5++5++5++5++5++" rrr8,,8>>>}}}}}}}}}}}}GGG____________///;922hhh1BBBBBBBBBBBB1hhh922;///____________GGG444FFFFFFFFFFFF###>LLLLLLHHHHHHHHHHHHHHLLLLLL>###FFFFFFFFFFFF444===RRRRRRRRRRRR)))@LLLBBBOOOOOOOOOOOOOOBBBLLL@)))RRRRRRRRRRRR===VVVssssssssssss9998LLL;,,UUU80..2222222222220..8UUU;,,LLLC999ssssssssssssVVVnnnIIIEhhh3##\\,##@@@fffhhhhhhhhhhhhfff@@@,##\\3##hhhEIIInnn222YYYHrrr1c 9:11pppp:119c 1rrrHYYY222hhh>rrr4B++gIIgIIB++4rrrJhhhwwwMrrr=,,[[[[=,,rrrMwwwwwwP@66]]凇w__eVVQGGG??G??G??G??QGGeVVw__凇]]@66PwwwhhhRb[[h@@QQ=66=88[[[T((|2222222222|22T(([[[=88=66QQh@@b[[RhhheeeYYYG=44K77I((,,4_LL//22222222//_LL4,,I((K77=44UYYYeeepppKKK8G55<<<+y((h""LLL_RRr??r??r??r??_RRLLLh""y((+<<JEErrr/""c BK22K22K22K22Bc /""rrrJEE>|))0''///____________GGG444FFFFFFFFFFFF###,!!****o%%2hhh///888TTTttttttYYY777///hhh2o%%__) ###FFFFFFFFFFFF444???UUUUUUUUUUUU***,b Y++++H5++%%%pppppp%%%5++H++++b ++,***UUUUUUUUUUUU???vvvvvvvvvvvv::::}))d!!,,,,,,,,:pppppp:##,,,,,,,,d!!,,B:::vvvvvvvvvvvvJJJE--h""--------Epppppp<$$--------o$$h""UJJJZZZ` j##{((........Epppppp<$$............i""ZZZjjjl##////////////Gpppppp<$$////////////l##jjjxxxn$$111111111111Jpppppp=%%111111111111n$$xxxvvvq%%~~eeeeeeXX22^222MMMrrrrrrQQQ(((H22eeeeeeeeŋq%%vvvfffr%%ee222222ee222222222222222222ee222222eer%%fffUUUr%%ee222222ee222222222222222222ee222222eer%%UUUhhhEEEr%%ee222222ee222222222222222222ee222222eer%%EEEhhhPPPkkkkkkkkkkkk555 ŋeeeeeelyc5<&% % 222222% % ;L/>194#(9999993993D33TTTTGG.?--B338C8D33D33D33D33D33D33B33D33?--0K::RDD,vvvxxx*H66I993ZZZlllmmmfff1B..cccjjjkkkkkk8''9PDD7<<<<<<9C559##7!!kkkkkkgggZZZDDDPPPPPP1@(({{{O<''>''=&&JRI%%d``G44;""ddddddYYY***+++rrr@..L44mggE##K?((OOOPPPPPPPOO;((KI `WWP<>bKK`>>mFFTTs\\bLLk99k77k77i88_KKhWWZZ|KKjPP]==WAAK**[99i66XQQl``11222211kYY]VV_33_;;Q44X88***rrrB77:%%`]]YFFW##XFFttqqqqqqcQQS))dII^WW<))?00www:::!!!ZZZjjjjjj600J(([NNonnO55M$$fRRl]]l]]hTTI**R66dcc_RRG&&7--jjjjjj___...CCCNNNNNN(""G r%%q''WFFKIIlllttt<::^MMh&&n$$R!!)!!NNNNNNEEE kkkggggggggg3%%Nn$$++h&&K##I''f((++v&&d""6$$ggggggjjjtttT;;a|((----m##^((----,,p$$Z66dFFr%%,,....o$$_((......))h>>}}}tSS??NNNN<DDA$ ,\\\I88=((67/A,,A,,@++?**>%%E66nnnxxx9''CCCZZZ7((nff?AA@WHH:**ZZZMMM:::yyyC55iXXJ!!OCCPDDE##Z<>fUU}55~55fSSo@@]HH555tttA00\OOW77hRRjTTY>>_OOC++tttQQQXXX```?%%q&&]22R11r''S$$```aaaf==,,}((i))--r33{{{~SSBB>>kZZynn55BBRR===^@@HHzIB`@@fXXn81HHxII\\\###GGG ___yyy+++]]]sAsAsAsAsAsAsAsAsAsAsAsAsAsAsAsArobocode/robocodeextract/robocode.sh0000644000175000017500000000037411052312554017165 0ustar lambylamby#!/bin/sh olddir=`pwd` robohome=`dirname $0` echo "Using robohome $robohome" cd "$robohome" java -Xmx512M -Dsun.io.useCanonCaches=false -cp libs/robocode.jar:libs/codesize.jar:libs/cachecleaner.jar robocode.Robocode $* echo "Goodbye!" cd "$olddir"robocode/robocodeextract/.project0000644000175000017500000000073611052366404016511 0ustar lambylamby robocodeextract robocode org.eclipse.jdt.core.javabuilder org.eclipse.jdt.core.javanature org.eclipse.team.cvs.core.cvsnature robocode/robocodeextract/robots/0000755000175000017500000000000011054242762016346 5ustar lambylambyrobocode/robocodeextract/robots/sampleteam/0000755000175000017500000000000011124141412020462 5ustar lambylambyrobocode/robocodeextract/robots/sampleteam/MyFirstTeam.team0000644000175000017500000000070011052312544023541 0ustar lambylamby#Robocode robot team #Sun Aug 20 23:26:53 EST 2006 team.members=sampleteam.MyFirstLeader,sampleteam.MyFirstDroid,sampleteam.MyFirstDroid,sampleteam.MyFirstDroid,sampleteam.MyFirstDroid team.author.name=Mathew Nelson and Flemming N. Larsen robocode.version=1.1.2 team.webpage= team.description=\ A sample team.\n MyFirstLeader scans for enemies,\n and orders the 4 droids to fire. robocode/robocodeextract/robots/sampleteam/MyFirstDroid.java0000644000175000017500000000370411130241114023705 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial implementation * Flemming N. Larsen * - Maintainance *******************************************************************************/ package sampleteam; import robocode.Droid; import robocode.MessageEvent; import robocode.TeamRobot; import static robocode.util.Utils.normalRelativeAngleDegrees; /** * SimpleDroid - a sample robot by Mathew Nelson, and maintained by Flemming N. Larsen *

* Follows orders of team leader */ public class MyFirstDroid extends TeamRobot implements Droid { /** * run: Droid's default behavior */ public void run() { out.println("MyFirstDroid ready."); } /** * onMessageReceived: What to do when our leader sends a message */ public void onMessageReceived(MessageEvent e) { // Fire at a point if (e.getMessage() instanceof Point) { Point p = (Point) e.getMessage(); // Calculate x and y to target double dx = p.getX() - this.getX(); double dy = p.getY() - this.getY(); // Calculate angle to target double theta = Math.toDegrees(Math.atan2(dx, dy)); // Turn gun to target turnGunRight(normalRelativeAngleDegrees(theta - getGunHeading())); // Fire hard! fire(3); } // Set our colors else if (e.getMessage() instanceof RobotColors) { RobotColors c = (RobotColors) e.getMessage(); setBodyColor(c.bodyColor); setGunColor(c.gunColor); setRadarColor(c.radarColor); setScanColor(c.scanColor); setBulletColor(c.bulletColor); } } } robocode/robocodeextract/robots/sampleteam/RobotColors.java0000644000175000017500000000175311130241114023577 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial implementation * Flemming N. Larsen * - Maintainance *******************************************************************************/ package sampleteam; import java.awt.*; /** * RobotColors - A serializable class to send Colors to teammates */ public class RobotColors implements java.io.Serializable { private static final long serialVersionUID = 1L; public Color bodyColor; public Color gunColor; public Color radarColor; public Color scanColor; public Color bulletColor; } robocode/robocodeextract/robots/sampleteam/MyFirstLeader.java0000644000175000017500000000512211130241114024034 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial implementation * Flemming N. Larsen * - Maintainance *******************************************************************************/ package sampleteam; import robocode.HitByBulletEvent; import robocode.ScannedRobotEvent; import robocode.TeamRobot; import java.awt.*; import java.io.IOException; /** * MyFirstLeader - a sample team robot by Mathew Nelson, and maintained by Flemming N. Larsen *

* Looks around for enemies, and orders teammates to fire */ public class MyFirstLeader extends TeamRobot { /** * run: Leader's default behavior */ public void run() { // Prepare RobotColors object RobotColors c = new RobotColors(); c.bodyColor = Color.red; c.gunColor = Color.red; c.radarColor = Color.red; c.scanColor = Color.yellow; c.bulletColor = Color.yellow; // Set the color of this robot containing the RobotColors setBodyColor(c.bodyColor); setGunColor(c.gunColor); setRadarColor(c.radarColor); setScanColor(c.scanColor); setBulletColor(c.bulletColor); try { // Send RobotColors object to our entire team broadcastMessage(c); } catch (IOException ignored) {} // Normal behavior while (true) { setTurnRadarRight(10000); ahead(100); back(100); } } /** * onScannedRobot: What to do when you see another robot */ public void onScannedRobot(ScannedRobotEvent e) { // Don't fire on teammates if (isTeammate(e.getName())) { return; } // Calculate enemy bearing double enemyBearing = this.getHeading() + e.getBearing(); // Calculate enemy's position double enemyX = getX() + e.getDistance() * Math.sin(Math.toRadians(enemyBearing)); double enemyY = getY() + e.getDistance() * Math.cos(Math.toRadians(enemyBearing)); try { // Send enemy position to teammates broadcastMessage(new Point(enemyX, enemyY)); } catch (IOException ex) { out.println("Unable to send order: "); ex.printStackTrace(out); } } /** * onHitByBullet: Turn perpendicular to bullet path */ public void onHitByBullet(HitByBulletEvent e) { turnLeft(90 - e.getBearing()); } } robocode/robocodeextract/robots/sampleteam/Point.java0000644000175000017500000000172011130241114022413 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial implementation *******************************************************************************/ package sampleteam; /** * Point - a serializable point class */ public class Point implements java.io.Serializable { private static final long serialVersionUID = 1L; private double x = 0.0; private double y = 0.0; public Point(double x, double y) { this.x = x; this.y = y; } public double getX() { return x; } public double getY() { return y; } } robocode/robocodeextract/robots/sampleex/0000755000175000017500000000000011124141424020153 5ustar lambylambyrobocode/robocodeextract/robots/sampleex/ProxyOfGreyEminence.properties0000644000175000017500000000066111052312544026200 0ustar lambylamby#Robot Properties #Sun Feb 20 21:16:33 EST 2008 robot.description=\ A sample robot\n\n Is not inherited from classic base robots,\n uses new experimental access to RobotPeer. robot.webpage=zamboch.blogspot.com robocode.version=1.6 robot.java.source.included=true robot.author.name=Pavel Savara robot.classname=sampleex.ProxyOfGreyEminence robot.name=ProxyOfGreyEminence robocode/robocodeextract/robots/sampleex/MasterAndSlave.java0000644000175000017500000000667311130241114023675 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package sampleex; import robocode.AdvancedRobot; import robocode.HitByBulletEvent; import robocode.ScannedRobotEvent; import robocode.robotinterfaces.IAdvancedEvents; import robocode.robotinterfaces.IAdvancedRobot; import robocode.robotinterfaces.IBasicEvents; import robocode.robotinterfaces.IInteractiveEvents; import robocode.robotinterfaces.peer.IBasicRobotPeer; import java.io.PrintStream; /** * @author Pavel Savara (original) */ public class MasterAndSlave extends MasterBase implements IAdvancedRobot { /** * This is not showing any aditional qualities over normal MyFirst robot. * But it could, because architecture is no more tied by inheritance from Robot base class. */ public void run() { while (true) { ahead(100); // Move ahead 100 turnGunRight(360); // Spin gun around back(100); // Move back 100 turnGunRight(360); // Spin gun around } } public void onScannedRobot(ScannedRobotEvent e) { fire(1); } public void onHitByBullet(HitByBulletEvent e) { turnLeft(90 - e.getBearing()); } public IInteractiveEvents getInteractiveEventListener() { return null; } } /** * This is robot derived from AdvancedRobot. * Only reason to use this inheritance and this class is that external robots are unable to call RobotPeer directly */ class Slave extends AdvancedRobot { final MasterBase parent; public Slave(MasterBase parent) { this.parent = parent; } public void run() { parent.run(); } public void onScannedRobot(ScannedRobotEvent e) { parent.onScannedRobot(e); } public void onHitByBullet(HitByBulletEvent e) { parent.onHitByBullet(e); } } /** * Infrastructure base class, for helpers and boring implementation details */ abstract class MasterBase { public MasterBase() { helperRobot = new Slave(this); } private final AdvancedRobot helperRobot; public IAdvancedEvents getAdvancedEventListener() { return helperRobot; } public IInteractiveEvents getSystemEventListener() { return helperRobot; } public Runnable getRobotRunnable() { return helperRobot; } public IBasicEvents getBasicEventListener() { return helperRobot; } public void setPeer(IBasicRobotPeer robotPeer) { helperRobot.setPeer(robotPeer); } public void setOut(PrintStream printStream) { helperRobot.setOut(printStream); } public void turnGunRight(double degrees) { helperRobot.turnGunRight(degrees); } public void turnLeft(double degrees) { helperRobot.turnLeft(degrees); } public void ahead(double distance) { helperRobot.ahead(distance); } public void back(double distance) { helperRobot.back(distance); } public void fire(double power) { helperRobot.fire(power); } public void onScannedRobot(ScannedRobotEvent e) {} public void onHitByBullet(HitByBulletEvent e) {} public void run() {} } robocode/robocodeextract/robots/sampleex/MasteAndSlave.properties0000644000175000017500000000064711052312544024772 0ustar lambylamby#Robot Properties #Sun Feb 20 21:16:33 EST 2008 robot.description=\ A sample robot\n\n Is not inherited from classic base robots,\n uses new experimental access to RobotPeer. robot.webpage=zamboch.blogspot.com robocode.version=1.6 robot.java.source.included=true robot.author.name=Pavel Savara robot.classname=sampleex.MasterAndSlave robot.name=MasterAndSlave robocode/robocodeextract/robots/sampleex/Alien.properties0000644000175000017500000000062511052312544023327 0ustar lambylamby#Robot Properties #Sun Feb 20 21:16:33 EST 2008 robot.description=\ A sample robot\n\n Is not inherited from classic base robots,\n uses new experimental access to RobotPeer. robot.webpage=zamboch.blogspot.com robocode.version=1.6 robot.java.source.included=true robot.author.name=Pavel Savara robot.classname=sampleex.Alien robot.name=Alien robocode/robocodeextract/robots/sampleex/Alien.java0000644000175000017500000000446011130241114022044 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package sampleex; import robocode.*; import robocode.robotinterfaces.IBasicEvents; import robocode.robotinterfaces.IBasicRobot; import robocode.robotinterfaces.peer.IBasicRobotPeer; import robocode.robotinterfaces.peer.IStandardRobotPeer; import java.io.PrintStream; /** * A sample robot. * Is not inherited from classic base robots, uses new experimental access to RobotPeer. * Use -DEXPERIMENTAL=true to start robocode for this robot. * * @author Pavel Savara (original) */ public class Alien implements IBasicEvents, IBasicRobot, Runnable { PrintStream out; IStandardRobotPeer peer; public Runnable getRobotRunnable() { return this; } public IBasicEvents getBasicEventListener() { return this; } public void setPeer(IBasicRobotPeer iRobotPeer) { peer = (IStandardRobotPeer) iRobotPeer; } public void setOut(PrintStream printStream) { out = printStream; } public void run() { while (true) { peer.move(100); // Move ahead 100 peer.turnGun(Math.PI * 2); // Spin gun around peer.move(-100); // Move back 100 peer.turnGun(Math.PI * 2); // Spin gun around } } public void onScannedRobot(ScannedRobotEvent e) { peer.setFire(1); } public void onHitByBullet(HitByBulletEvent e) { peer.turnBody(Math.PI / 2 + e.getBearingRadians()); } public void onStatus(StatusEvent e) {} public void onBulletHit(BulletHitEvent e) {} public void onBulletHitBullet(BulletHitBulletEvent e) {} public void onBulletMissed(BulletMissedEvent e) {} public void onDeath(DeathEvent e) {} public void onHitRobot(HitRobotEvent e) {} public void onHitWall(HitWallEvent e) {} public void onRobotDeath(RobotDeathEvent e) {} public void onWin(WinEvent e) {} } robocode/robocodeextract/robots/sampleex/AlienComposition.java0000644000175000017500000000530211130241114024264 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package sampleex; import robocode.*; import robocode.robotinterfaces.IBasicEvents; import robocode.robotinterfaces.IBasicRobot; import robocode.robotinterfaces.peer.IBasicRobotPeer; import robocode.robotinterfaces.peer.IStandardRobotPeer; import java.io.PrintStream; /** * A sample robot. * Is not inherited from classic base robots, uses new experimental access to RobotPeer. * Use -DEXPERIMENTAL=true to start robocode for this robot. * This composition version is showing possible decomposition of robot, main runnable and event handler to different classes. * * @author Pavel Savara (original) */ public class AlienComposition implements IBasicRobot { PrintStream out; IStandardRobotPeer peer; final AlienMain main; final AlienEventHandler handler; public AlienComposition() { main = new AlienMain(); handler = new AlienEventHandler(); } public void setPeer(IBasicRobotPeer iRobotPeer) { peer = (IStandardRobotPeer) iRobotPeer; } public void setOut(PrintStream printStream) { out = printStream; } public Runnable getRobotRunnable() { return main; } public IBasicEvents getBasicEventListener() { return handler; } class AlienMain implements Runnable { public void run() { while (true) { peer.move(100); // Move ahead 100 peer.turnGun(Math.PI * 2); // Spin gun around peer.move(-100); // Move back 100 peer.turnGun(Math.PI * 2); // Spin gun around } } } class AlienEventHandler implements IBasicEvents { public void onScannedRobot(ScannedRobotEvent e) { peer.setFire(1); } public void onHitByBullet(HitByBulletEvent e) { peer.turnBody(Math.PI / 2 + e.getBearingRadians()); } public void onStatus(StatusEvent e) {} public void onBulletHit(BulletHitEvent e) {} public void onBulletHitBullet(BulletHitBulletEvent e) {} public void onBulletMissed(BulletMissedEvent e) {} public void onDeath(DeathEvent e) {} public void onHitRobot(HitRobotEvent e) {} public void onHitWall(HitWallEvent e) {} public void onRobotDeath(RobotDeathEvent e) {} public void onWin(WinEvent e) {} } } robocode/robocodeextract/robots/sampleex/ProxyOfGreyEminence.java0000644000175000017500000000462011130241114024713 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * This sample is showing how to free your robot from class inheritance from Robot. * Proxy is just dummy forwarding code, which is only visible part for Robocode. * RegullarMonk is for infrastructure, helpers etc. * GreyEminence is the real brain behind. * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package sampleex; import robocode.AdvancedRobot; import robocode.HitByBulletEvent; import robocode.ScannedRobotEvent; /** * This is just dummy proxy, it's hiding the Eminence and * giving it more freedom to inherit from Monk rather than from Robot. */ public class ProxyOfGreyEminence extends AdvancedRobot { private final GreyEminence monk; public ProxyOfGreyEminence() { monk = new GreyEminence(this); } public void onHitByBullet(HitByBulletEvent event) { monk.onHitByBullet(event); } public void onScannedRobot(ScannedRobotEvent event) { monk.onScannedRobot(event); } public void run() { monk.run(); } } /** * Monk of a order. Implements anything too boring for Eminence. * The infractructure base class. */ abstract class RegullarMonk {} /** * The power behind the throne. */ class GreyEminence extends RegullarMonk { private final ProxyOfGreyEminence proxy; public GreyEminence(ProxyOfGreyEminence proxy) { this.proxy = proxy; } /** * This is not showing any aditional qualities over normal MyFirst robot. * But it could, because architecture is no more tied by inheritance from Robot base class. */ public void run() { while (true) { proxy.ahead(100); // Move ahead 100 proxy.turnGunRight(360); // Spin gun around proxy.back(100); // Move back 100 proxy.turnGunRight(360); // Spin gun around } } public void onScannedRobot(ScannedRobotEvent e) { proxy.fire(1); } public void onHitByBullet(HitByBulletEvent e) { proxy.turnLeft(90 - e.getBearing()); } } robocode/robocodeextract/robots/sample/0000755000175000017500000000000011125666532017633 5ustar lambylambyrobocode/robocodeextract/robots/sample/Target.java0000644000175000017500000000360511130241114021705 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial implementation * Flemming N. Larsen * - Maintainance *******************************************************************************/ package sample; import robocode.AdvancedRobot; import robocode.Condition; import robocode.CustomEvent; import java.awt.*; /** * Target - a sample robot by Mathew Nelson, and maintained by Flemming N. Larsen *

* Sits still. Moves every time energy drops by 20. * This Robot demonstrates custom events. */ public class Target extends AdvancedRobot { int trigger; // Keeps track of when to move /** * TrackFire's run method */ public void run() { // Set colors setBodyColor(Color.white); setGunColor(Color.white); setRadarColor(Color.white); // Initially, we'll move when life hits 80 trigger = 80; // Add a custom event named "trigger hit", addCustomEvent(new Condition("triggerhit") { public boolean test() { return (getEnergy() <= trigger); } }); } /** * onCustomEvent handler */ public void onCustomEvent(CustomEvent e) { // If our custom event "triggerhit" went off, if (e.getCondition().getName().equals("triggerhit")) { // Adjust the trigger value, or // else the event will fire again and again and again... trigger -= 20; out.println("Ouch, down to " + (int) (getEnergy() + .5) + " energy."); // move around a bit. turnLeft(65); ahead(100); } } } robocode/robocodeextract/robots/sample/RamFire.properties0000644000175000017500000000062211052312544023264 0ustar lambylamby#Robot Properties #Sun Aug 20 21:17:21 EST 2007 robot.description=\ A sample robot\n Drives at robots trying to ram them.\n Fires when it hits them. robot.webpage= robocode.version=1.1.2 robot.java.source.included=true robot.author.name=Mathew Nelson and Flemming N. Larsen robot.classname=sample.RamFire robot.name=RamFire robocode/robocodeextract/robots/sample/MyFirstJuniorRobot.java0000644000175000017500000000342611130241114024252 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen * - Initial implementation *******************************************************************************/ package sample; import robocode.JuniorRobot; /** * MyFirstJuniorRobot - a sample robot by Flemming N. Larsen *

* Moves in a seesaw motion, and spins the gun around at each end * when it cannot see any enemy robot. When the robot sees and enemy * robot, it will immediately turn the gun and fire at it. */ public class MyFirstJuniorRobot extends JuniorRobot { /** * MyFirstJuniorRobot's run method - Seesaw as default */ public void run() { // Set robot colors setColors(green, black, blue); // Seesaw forever while (true) { ahead(100); // Move ahead 100 turnGunRight(360); // Spin gun around back(100); // Move back 100 turnGunRight(360); // Spin gun around } } /** * When we see a robot, turn the gun towards it and fire */ public void onScannedRobot() { // Turn gun to point at the scanned robot turnGunTo(scannedAngle); // Fire! fire(1); } /** * We were hit! Turn and move perpendicular to the bullet, * so our seesaw might avoid a future shot. */ public void onHitByBullet() { // Move ahead 100 and in the same time turn left papendicular to the bullet turnAheadLeft(100, 90 - hitByBulletBearing); } } robocode/robocodeextract/robots/sample/SittingDuck.java0000644000175000017500000000562411130241114022712 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial implementation * Flemming N. Larsen * - Maintainance * Andrew Magargle * - Bugfix so that PrintStream is always closed, even when errors occurs *******************************************************************************/ package sample; import robocode.AdvancedRobot; import robocode.RobocodeFileOutputStream; import java.awt.*; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.io.PrintStream; /** * SittingDuck - a sample robot by Mathew Nelson, and maintained by Flemming N. Larsen *

* Along with sitting still doing nothing, * this robot demonstrates persistency. */ public class SittingDuck extends AdvancedRobot { static boolean incrementedBattles = false; public void run() { setBodyColor(Color.yellow); setGunColor(Color.yellow); int roundCount, battleCount; // Read file "count.dat" which contains 2 lines, // a round count, and a battle count try { BufferedReader r = new BufferedReader(new FileReader(getDataFile("count.dat"))); // Try to get the counts roundCount = Integer.parseInt(r.readLine()); battleCount = Integer.parseInt(r.readLine()); } catch (IOException e) { // Something went wrong reading the file, reset to 0. roundCount = 0; battleCount = 0; } catch (NumberFormatException e) { // Something went wrong converting to ints, reset to 0 roundCount = 0; battleCount = 0; } // Increment the # of rounds roundCount++; // If we haven't incremented # of battles already, // (Note: Because robots are only instantiated once per battle, // member variables remain valid throughout it. if (!incrementedBattles) { // Increment # of battles battleCount++; incrementedBattles = true; } PrintStream w = null; try { w = new PrintStream(new RobocodeFileOutputStream(getDataFile("count.dat"))); w.println(roundCount); w.println(battleCount); // PrintStreams don't throw IOExceptions during prints, // they simply set a flag.... so check it here. if (w.checkError()) { out.println("I could not write the count!"); } } catch (IOException e) { out.println("IOException trying to write: "); e.printStackTrace(out); } finally { if (w != null) { w.close(); } } out.println("I have been a sitting duck for " + roundCount + " rounds, in " + battleCount + " battles."); } } robocode/robocodeextract/robots/sample/SittingDuck.properties0000644000175000017500000000065511052312544024175 0ustar lambylamby#Robot Properties #Sun Aug 20 21:18:07 EST 2007 robot.description=\ A sample robot\nThis robot sits still, and waits to be fired upon. Exciting stuff\!\nAlso counts how many times he has been a sitting duck. robot.webpage= robocode.version=1.1.2 robot.java.source.included=true robot.author.name=Mathew Nelson and Flemming N. Larsen robot.classname=sample.SittingDuck robot.name=SittingDuck robocode/robocodeextract/robots/sample/Crazy.properties0000644000175000017500000000053311052312544023030 0ustar lambylamby#Robot Properties #Sun Aug 20 21:16:04 EST 2006 robot.description=\ A sample robot\n\n Moves around in a crazy pattern robot.webpage= robocode.version=1.1.2 robot.java.source.included=true robot.author.name=Mathew Nelson and Flemming N. Larsen robot.classname=sample.Crazy robot.name=Crazy robocode/robocodeextract/robots/sample/Fire.properties0000644000175000017500000000055011052312544022624 0ustar lambylamby#Robot Properties #Sun Aug 20 21:16:33 EST 2007 robot.description=\ A sample robot\n\n Sits still. Spins gun around. Moves when hit. Ooh\! robot.webpage= robocode.version=1.1.2 robot.java.source.included=true robot.author.name=Mathew Nelson and Flemming N. Larsen robot.classname=sample.Fire robot.name=Fire robocode/robocodeextract/robots/sample/TrackFire.java0000644000175000017500000000467111130241114022335 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial implementation * Flemming N. Larsen * - Maintainance *******************************************************************************/ package sample; import robocode.Robot; import robocode.ScannedRobotEvent; import robocode.WinEvent; import static robocode.util.Utils.normalRelativeAngleDegrees; import java.awt.*; /** * TrackFire - a sample robot by Mathew Nelson, and maintained by Flemming N. Larsen *

* Sits still. Tracks and fires at the nearest robot it sees */ public class TrackFire extends Robot { /** * TrackFire's run method */ public void run() { // Set colors setBodyColor(Color.pink); setGunColor(Color.pink); setRadarColor(Color.pink); setScanColor(Color.pink); setBulletColor(Color.pink); // Loop forever while (true) { turnGunRight(10); // Scans automatically } } /** * onScannedRobot: We have a target. Go get it. */ public void onScannedRobot(ScannedRobotEvent e) { // Calculate exact location of the robot double absoluteBearing = getHeading() + e.getBearing(); double bearingFromGun = normalRelativeAngleDegrees(absoluteBearing - getGunHeading()); // If it's close enough, fire! if (Math.abs(bearingFromGun) <= 3) { turnGunRight(bearingFromGun); // We check gun heat here, because calling fire() // uses a turn, which could cause us to lose track // of the other robot. if (getGunHeat() == 0) { fire(Math.min(3 - Math.abs(bearingFromGun), getEnergy() - .1)); } } // otherwise just set the gun to turn. // Note: This will have no effect until we call scan() else { turnGunRight(bearingFromGun); } // Generates another scan event if we see a robot. // We only need to call this if the gun (and therefore radar) // are not turning. Otherwise, scan is called automatically. if (bearingFromGun == 0) { scan(); } } public void onWin(WinEvent e) { // Victory dance turnRight(36000); } } robocode/robocodeextract/robots/sample/SittingDuck.html0000644000175000017500000000022311052312544022734 0ustar lambylamby SittingDuck's Webpage

Hi! I'm a sitting duck.
robocode/robocodeextract/robots/sample/Interactive.java0000644000175000017500000001515311130241114022735 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen * - Initial implementation *******************************************************************************/ package sample; import robocode.AdvancedRobot; import static robocode.util.Utils.normalAbsoluteAngle; import static robocode.util.Utils.normalRelativeAngle; import java.awt.*; import java.awt.event.KeyEvent; import static java.awt.event.KeyEvent.*; import java.awt.event.MouseEvent; import java.awt.event.MouseWheelEvent; /** * Interactive - a sample robot by Flemming N. Larsen. *

* This is a robot that is controlled using the arrow keys and mouse only. *

* Keys: * - Arrow up: Move forward * - Arrow down: Move backward * - Arrow right: Turn right * - Arrow left: Turn left * Mouse: * - Moving: Moves the aim, which the gun will follow * - Wheel up: Move forward * - Wheel down: Move backward * - Button 1: Fire a bullet with power = 1 * - Button 2: Fire a bullet with power = 2 * - Button 3: Fire a bullet with power = 3 *

* The bullet color depends on the fire power: * - Power = 1: Yellow * - Power = 2: Orange * - Power = 3: Red *

* Note that the robot will continue firing as long as the mouse button is * pressed down. *

* By enabling the "Paint" button on the robot console window for this robot, * a cross hair will be painted for the robots current aim (controlled by the * mouse). * * @author Flemming N. Larsen * @version 1.1 * @since 1.3.4 */ public class Interactive extends AdvancedRobot { // Move direction: 1 = move forward, 0 = stand still, -1 = move backward int moveDirection; // Turn direction: 1 = turn right, 0 = no turning, -1 = turn left int turnDirection; // Amount of pixels/units to move double moveAmount; // The coordinate of the aim (x,y) int aimX, aimY; // Fire power, where 0 = don't fire int firePower; // Called when the robot must run public void run() { // Sets the colors of the robot // body = black, gun = white, radar = red setColors(Color.BLACK, Color.WHITE, Color.RED); // Loop forever for (;;) { // Sets the robot to move forward, backward or stop moving depending // on the move direction and amount of pixels to move setAhead(moveAmount * moveDirection); // Decrement the amount of pixels to move until we reach 0 pixels // This way the robot will automatically stop if the mouse wheel // has stopped it's rotation moveAmount = Math.max(0, moveAmount - 1); // Sets the robot to turn right or turn left (at maximum speed) or // stop turning depending on the turn direction setTurnRight(45 * turnDirection); // degrees // Turns the gun toward the current aim coordinate (x,y) controlled by // the current mouse coordinate double angle = normalAbsoluteAngle(Math.atan2(aimX - getX(), aimY - getY())); setTurnGunRightRadians(normalRelativeAngle(angle - getGunHeadingRadians())); // Fire the gun with the specified fire power, unless the fire power = 0 if (firePower > 0) { setFire(firePower); } // Execute all pending set-statements execute(); // Next turn is processed in this loop.. } } // Called when a key has been pressed public void onKeyPressed(KeyEvent e) { switch (e.getKeyCode()) { case VK_UP: // Arrow up key: move direction = forward (infinitely) moveDirection = 1; moveAmount = Double.POSITIVE_INFINITY; break; case VK_DOWN: // Arrow down key: move direction = backward (infinitely) moveDirection = -1; moveAmount = Double.POSITIVE_INFINITY; break; case VK_RIGHT: // Arrow right key: turn direction = right turnDirection = 1; break; case VK_LEFT: // Arrow left key: turn direction = left turnDirection = -1; break; } } // Called when a key has been released (after being pressed) public void onKeyReleased(KeyEvent e) { switch (e.getKeyCode()) { case VK_UP: case VK_DOWN: // Arrow up and down keys: move direction = stand still moveDirection = 0; break; case VK_RIGHT: case VK_LEFT: // Arrow right and left keys: turn direction = stop turning turnDirection = 0; break; } } // Called when the mouse wheel is rotated public void onMouseWheelMoved(MouseWheelEvent e) { // If the wheel rotation is negative it means that it is moved forward. // Set move direction = forward, if wheel is moved forward. // Otherwise, set move direction = backward moveDirection = (e.getWheelRotation() < 0) ? 1 : -1; // Set the amount to move = absolute wheel rotation amount * 5 (speed) // Here 5 means 5 pixels per wheel rotation step. The higher value, the // more speed moveAmount += Math.abs(e.getWheelRotation()) * 5; } // Called when the mouse has been moved public void onMouseMoved(MouseEvent e) { // Set the aim coordinate = the mouse pointer coordinate aimX = e.getX(); aimY = e.getY(); } // Called when a mouse button has been pressed public void onMousePressed(MouseEvent e) { if (e.getButton() == MouseEvent.BUTTON3) { // Button 3: fire power = 3 energy points, bullet color = red firePower = 3; setBulletColor(Color.RED); } else if (e.getButton() == MouseEvent.BUTTON2) { // Button 2: fire power = 2 energy points, bullet color = orange firePower = 2; setBulletColor(Color.ORANGE); } else { // Button 1 or unknown button: // fire power = 1 energy points, bullet color = yellow firePower = 1; setBulletColor(Color.YELLOW); } } // Called when a mouse button has been released (after being pressed) public void onMouseReleased(MouseEvent e) { // Fire power = 0, which means "don't fire" firePower = 0; } // Called in order to paint graphics for this robot. // "Paint" button on the robot console window for this robot must be // enabled in order to see the paintings. public void onPaint(Graphics2D g) { // Draw a red cross hair with the center at the current aim // coordinate (x,y) g.setColor(Color.RED); g.drawOval(aimX - 15, aimY - 15, 30, 30); g.drawLine(aimX, aimY - 4, aimX, aimY + 4); g.drawLine(aimX - 4, aimY, aimX + 4, aimY); } } robocode/robocodeextract/robots/sample/MyFirstRobot.java0000644000175000017500000000266611130241114023070 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial implementation *******************************************************************************/ package sample; import robocode.HitByBulletEvent; import robocode.Robot; import robocode.ScannedRobotEvent; /** * MyFirstRobot - a sample robot by Mathew Nelson *

* Moves in a seesaw motion, and spins the gun around at each end */ public class MyFirstRobot extends Robot { /** * MyFirstRobot's run method - Seesaw */ public void run() { while (true) { ahead(100); // Move ahead 100 turnGunRight(360); // Spin gun around back(100); // Move back 100 turnGunRight(360); // Spin gun around } } /** * Fire when we see a robot */ public void onScannedRobot(ScannedRobotEvent e) { fire(1); } /** * We were hit! Turn perpendicular to the bullet, * so our seesaw might avoid a future shot. */ public void onHitByBullet(HitByBulletEvent e) { turnLeft(90 - e.getBearing()); } } robocode/robocodeextract/robots/sample/Corners.properties0000644000175000017500000000065011052312544023353 0ustar lambylamby#Robot Properties #Sun Aug 20 21:14:27 EST 2006 robot.description=\ A sample robot\n Moves to a corner, then swings the gun back and forth.\n If it dies, it tries a new corner in the next round. robot.webpage= robocode.version=1.1.2 robot.java.source.included=true robot.author.name=Mathew Nelson and Flemming N. Larsen robot.classname=sample.Corners robot.name=Corners robocode/robocodeextract/robots/sample/PaintingRobot.java0000644000175000017500000000565511130241114023245 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Stefan Westen * - Initial implementation * Pavel Savara * - Included in Robocode samples * - Added getGraphics() example on onHitByBullet() *******************************************************************************/ package sample; import robocode.HitByBulletEvent; import robocode.Robot; import robocode.ScannedRobotEvent; import java.awt.*; /** * PaintingRobot - a sample robot that demonstrates the onPaint() and * getGraphics() methods. * Also demonstrate feature of debugging properties on RobotDialog *

* Moves in a seesaw motion, and spins the gun around at each end. * When painting is enabled for this robot, a red circle will be painted * around this robot. * * @author Stefan Westen (SGSample) * @author Pavel Savara */ public class PaintingRobot extends Robot { /** * PaintingRobot's run method - Seesaw */ public void run() { while (true) { ahead(100); turnGunRight(360); back(100); turnGunRight(360); } } /** * Fire when we see a robot */ public void onScannedRobot(ScannedRobotEvent e) { // demonstrate feature of debugging properties on RobotDialog setDebugProperty("lastScannedRobot", e.getName() + " at " + e.getBearing() + " degrees at time " + getTime()); fire(1); } /** * We were hit! Turn perpendicular to the bullet, * so our seesaw might avoid a future shot. * In addition, draw orange circles where we were hit. */ public void onHitByBullet(HitByBulletEvent e) { // demonstrate feature of debugging properties on RobotDialog setDebugProperty("lastHitBy", e.getName() + " with power of bullet " + e.getPower() + " at time " + getTime()); // show how to remove debugging property setDebugProperty("lastScannedRobot", null); // gebugging by painting to battle view Graphics2D g = getGraphics(); g.setColor(Color.orange); g.drawOval((int) (getX() - 55), (int) (getY() - 55), 110, 110); g.drawOval((int) (getX() - 56), (int) (getY() - 56), 112, 112); g.drawOval((int) (getX() - 59), (int) (getY() - 59), 118, 118); g.drawOval((int) (getX() - 60), (int) (getY() - 60), 120, 120); turnLeft(90 - e.getBearing()); } /** * Paint a red circle around our PaintingRobot */ public void onPaint(Graphics2D g) { g.setColor(Color.red); g.drawOval((int) (getX() - 50), (int) (getY() - 50), 100, 100); g.setColor(new Color(0, 0xFF, 0, 30)); g.fillOval((int) (getX() - 60), (int) (getY() - 60), 120, 120); } } robocode/robocodeextract/robots/sample/Walls.java0000644000175000017500000000517111130241114021541 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial implementation * Flemming N. Larsen * - Maintainance *******************************************************************************/ package sample; import robocode.HitRobotEvent; import robocode.Robot; import robocode.ScannedRobotEvent; import java.awt.*; /** * Walls - a sample robot by Mathew Nelson, and maintained by Flemming N. Larsen *

* Moves around the outer edge with the gun facing in. */ public class Walls extends Robot { boolean peek; // Don't turn if there's a robot there double moveAmount; // How much to move /** * run: Move around the walls */ public void run() { // Set colors setBodyColor(Color.black); setGunColor(Color.black); setRadarColor(Color.orange); setBulletColor(Color.cyan); setScanColor(Color.cyan); // Initialize moveAmount to the maximum possible for this battlefield. moveAmount = Math.max(getBattleFieldWidth(), getBattleFieldHeight()); // Initialize peek to false peek = false; // turnLeft to face a wall. // getHeading() % 90 means the remainder of // getHeading() divided by 90. turnLeft(getHeading() % 90); ahead(moveAmount); // Turn the gun to turn right 90 degrees. peek = true; turnGunRight(90); turnRight(90); while (true) { // Look before we turn when ahead() completes. peek = true; // Move up the wall ahead(moveAmount); // Don't look now peek = false; // Turn to the next wall turnRight(90); } } /** * onHitRobot: Move away a bit. */ public void onHitRobot(HitRobotEvent e) { // If he's in front of us, set back up a bit. if (e.getBearing() > -90 && e.getBearing() < 90) { back(100); } // else he's in back of us, so set ahead a bit. else { ahead(100); } } /** * onScannedRobot: Fire! */ public void onScannedRobot(ScannedRobotEvent e) { fire(2); // Note that scan is called automatically when the robot is moving. // By calling it manually here, we make sure we generate another scan event if there's a robot on the next // wall, so that we do not start moving up it until it's gone. if (peek) { scan(); } } } robocode/robocodeextract/robots/sample/PaintingRobot.properties0000644000175000017500000000056111124141400024507 0ustar lambylamby#Robot Properties #Sat Apr 12 14:47:44 EST 2008 robot.description=\ A sample robot\n Demonstrates how to do custom painting and debugging properties. robot.webpage= robocode.version=1.6 robot.java.source.included=true robot.author.name=Stefan Westen robot.classname=sample.PaintingRobot robot.name=PaintingRobot robocode/robocodeextract/robots/sample/MyFirstJuniorRobot.properties0000644000175000017500000000066011052312544025533 0ustar lambylamby#Robot Properties #Sun Jul 29 00:07:28 EST 2007 robot.description=\ A sample robot\n Moves in a seesaw motion, and spins the gun around at each end\n Moves perpendicular to the direction of a bullet that hits it robot.webpage= robocode.version=1.4 robot.java.source.included=true robot.author.name=Flemming N. Larsen robot.classname=sample.MyFirstJuniorRobot robot.name=MyFirstJuniorRobotrobocode/robocodeextract/robots/sample/TrackFire.properties0000644000175000017500000000055111052312544023612 0ustar lambylamby#Robot Properties #Sun Aug 20 21:21:08 EST 2006 robot.description=\ A sample robot\n\n Tracks and fires at the nearest robot it sees robot.webpage= robocode.version=1.1.2 robot.java.source.included=true robot.author.name=Mathew Nelson and Flemming N. Larsen robot.classname=sample.TrackFire robot.name=TrackFire robocode/robocodeextract/robots/sample/MyFirstRobot.properties0000644000175000017500000000075111052312544024345 0ustar lambylamby#Robot Properties #Fri Nov 02 17:17:44 EST 2001 robot.description=\ A sample robot\n Moves in a seesaw motion, and spins the gun around at each end\n Turns perpendicular to the direction of a bullet that hits it robot.webpage=http\://robocode.sourceforge.net/myfirstrobot/MyFirstRobot.html robocode.version=1.0 robot.java.source.included=true robot.author.name=Mathew Nelson robot.classname=sample.MyFirstRobot robot.name=MyFirstRobot robocode/robocodeextract/robots/sample/Tracker.java0000644000175000017500000001047111130241114022051 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial implementation * Flemming N. Larsen * - Maintainance *******************************************************************************/ package sample; import robocode.HitRobotEvent; import robocode.Robot; import robocode.ScannedRobotEvent; import robocode.WinEvent; import static robocode.util.Utils.normalRelativeAngleDegrees; import java.awt.*; /** * Tracker - a sample robot by Mathew Nelson, and maintained by Flemming N. Larsen *

* Locks onto a robot, moves close, fires when close. */ public class Tracker extends Robot { int count = 0; // Keeps track of how long we've // been searching for our target double gunTurnAmt; // How much to turn our gun when searching String trackName; // Name of the robot we're currently tracking /** * run: Tracker's main run function */ public void run() { // Set colors setBodyColor(new Color(128, 128, 50)); setGunColor(new Color(50, 50, 20)); setRadarColor(new Color(200, 200, 70)); setScanColor(Color.white); setBulletColor(Color.blue); // Prepare gun trackName = null; // Initialize to not tracking anyone setAdjustGunForRobotTurn(true); // Keep the gun still when we turn gunTurnAmt = 10; // Initialize gunTurn to 10 // Loop forever while (true) { // turn the Gun (looks for enemy) turnGunRight(gunTurnAmt); // Keep track of how long we've been looking count++; // If we've haven't seen our target for 2 turns, look left if (count > 2) { gunTurnAmt = -10; } // If we still haven't seen our target for 5 turns, look right if (count > 5) { gunTurnAmt = 10; } // If we *still* haven't seen our target after 10 turns, find another target if (count > 11) { trackName = null; } } } /** * onScannedRobot: Here's the good stuff */ public void onScannedRobot(ScannedRobotEvent e) { // If we have a target, and this isn't it, return immediately // so we can get more ScannedRobotEvents. if (trackName != null && !e.getName().equals(trackName)) { return; } // If we don't have a target, well, now we do! if (trackName == null) { trackName = e.getName(); out.println("Tracking " + trackName); } // This is our target. Reset count (see the run method) count = 0; // If our target is too far away, turn and move toward it. if (e.getDistance() > 150) { gunTurnAmt = normalRelativeAngleDegrees(e.getBearing() + (getHeading() - getRadarHeading())); turnGunRight(gunTurnAmt); // Try changing these to setTurnGunRight, turnRight(e.getBearing()); // and see how much Tracker improves... // (you'll have to make Tracker an AdvancedRobot) ahead(e.getDistance() - 140); return; } // Our target is close. gunTurnAmt = normalRelativeAngleDegrees(e.getBearing() + (getHeading() - getRadarHeading())); turnGunRight(gunTurnAmt); fire(3); // Our target is too close! Back up. if (e.getDistance() < 100) { if (e.getBearing() > -90 && e.getBearing() <= 90) { back(40); } else { ahead(40); } } scan(); } /** * onHitRobot: Set him as our new target */ public void onHitRobot(HitRobotEvent e) { // Only print if he's not already our target. if (trackName != null && !trackName.equals(e.getName())) { out.println("Tracking " + e.getName() + " due to collision"); } // Set the target trackName = e.getName(); // Back up a bit. // Note: We won't get scan events while we're doing this! // An AdvancedRobot might use setBack(); execute(); gunTurnAmt = normalRelativeAngleDegrees(e.getBearing() + (getHeading() - getRadarHeading())); turnGunRight(gunTurnAmt); fire(3); back(50); } /** * onWin: Do a victory dance */ public void onWin(WinEvent e) { for (int i = 0; i < 50; i++) { turnRight(30); turnLeft(30); } } } robocode/robocodeextract/robots/sample/RamFire.java0000644000175000017500000000431511130241114022003 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial implementation * Flemming N. Larsen * - Maintainance *******************************************************************************/ package sample; import robocode.HitRobotEvent; import robocode.Robot; import robocode.ScannedRobotEvent; import java.awt.*; /** * RamFire - a sample robot by Mathew Nelson, and maintained by Flemming N. Larsen *

* Drives at robots trying to ram them. * Fires when it hits them. */ public class RamFire extends Robot { int turnDirection = 1; // Clockwise or counterclockwise /** * run: Spin around looking for a target */ public void run() { // Set colors setBodyColor(Color.lightGray); setGunColor(Color.gray); setRadarColor(Color.darkGray); while (true) { turnRight(5 * turnDirection); } } /** * onScannedRobot: We have a target. Go get it. */ public void onScannedRobot(ScannedRobotEvent e) { if (e.getBearing() >= 0) { turnDirection = 1; } else { turnDirection = -1; } turnRight(e.getBearing()); ahead(e.getDistance() + 5); scan(); // Might want to move ahead again! } /** * onHitRobot: Turn to face robot, fire hard, and ram him again! */ public void onHitRobot(HitRobotEvent e) { if (e.getBearing() >= 0) { turnDirection = 1; } else { turnDirection = -1; } turnRight(e.getBearing()); // Determine a shot that won't kill the robot... // We want to ram him instead for bonus points if (e.getEnergy() > 16) { fire(3); } else if (e.getEnergy() > 10) { fire(2); } else if (e.getEnergy() > 4) { fire(1); } else if (e.getEnergy() > 2) { fire(.5); } else if (e.getEnergy() > .4) { fire(.1); } ahead(40); // Ram him again! } } robocode/robocodeextract/robots/sample/Interactive.properties0000644000175000017500000000054611052312544024221 0ustar lambylamby#Robot Properties #Wed Jun 27 23:08:48 EST 2007 robot.description=\ A sample robot\n\n This is a robot that is controlled using the arrow keys and mouse only robot.webpage= robocode.version=1.3.4 robot.java.source.included=true robot.author.name=Flemming N. Larsen robot.classname=sample.Interactive robot.name=Interactiverobocode/robocodeextract/robots/sample/SpinBot.java0000644000175000017500000000354111130241114022034 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial implementation * Flemming N. Larsen * - Maintainance *******************************************************************************/ package sample; import robocode.AdvancedRobot; import robocode.HitRobotEvent; import robocode.ScannedRobotEvent; import java.awt.*; /** * SpinBot - a sample robot by Mathew Nelson, and maintained by Flemming N. Larsen *

* Moves in a circle, firing hard when an enemy is detected */ public class SpinBot extends AdvancedRobot { /** * SpinBot's run method - Circle */ public void run() { // Set colors setBodyColor(Color.blue); setGunColor(Color.blue); setRadarColor(Color.black); setScanColor(Color.yellow); // Loop forever while (true) { // Tell the game that when we take move, // we'll also want to turn right... a lot. setTurnRight(10000); // Limit our speed to 5 setMaxVelocity(5); // Start moving (and turning) ahead(10000); // Repeat. } } /** * onScannedRobot: Fire hard! */ public void onScannedRobot(ScannedRobotEvent e) { fire(3); } /** * onHitRobot: If it's our fault, we'll stop turning and moving, * so we need to turn again to keep spinning. */ public void onHitRobot(HitRobotEvent e) { if (e.getBearing() > -10 && e.getBearing() < 10) { fire(3); } if (e.isMyFault()) { turnRight(10); } } } robocode/robocodeextract/robots/sample/Fire.java0000644000175000017500000000437711130241114021353 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial implementation * Flemming N. Larsen * - Maintainance *******************************************************************************/ package sample; import robocode.HitByBulletEvent; import robocode.HitRobotEvent; import robocode.Robot; import robocode.ScannedRobotEvent; import static robocode.util.Utils.normalRelativeAngleDegrees; import java.awt.*; /** * Fire - a sample robot by Mathew Nelson, and maintained by Flemming N. Larsen *

* Sits still. Spins gun around. Moves when hit. */ public class Fire extends Robot { int dist = 50; // distance to move when we're hit /** * run: Fire's main run function */ public void run() { // Set colors setBodyColor(Color.orange); setGunColor(Color.orange); setRadarColor(Color.red); setScanColor(Color.red); setBulletColor(Color.red); // Spin the gun around slowly... forever while (true) { turnGunRight(5); } } /** * onScannedRobot: Fire! */ public void onScannedRobot(ScannedRobotEvent e) { // If the other robot is close by, and we have plenty of life, // fire hard! if (e.getDistance() < 50 && getEnergy() > 50) { fire(3); } // otherwise, fire 1. else { fire(1); } // Call scan again, before we turn the gun scan(); } /** * onHitByBullet: Turn perpendicular to the bullet, and move a bit. */ public void onHitByBullet(HitByBulletEvent e) { turnRight(normalRelativeAngleDegrees(90 - (getHeading() - e.getHeading()))); ahead(dist); dist *= -1; scan(); } /** * onHitRobot: Aim at it. Fire Hard! */ public void onHitRobot(HitRobotEvent e) { double turnGunAmt = normalRelativeAngleDegrees(e.getBearing() + getHeading() - getGunHeading()); turnGunRight(turnGunAmt); fire(3); } } robocode/robocodeextract/robots/sample/SpinBot.properties0000644000175000017500000000055311052312544023320 0ustar lambylamby#Robot Properties #Sun Aug 20 21:18:07 EST 2006 robot.description=\ A sample robot\n\n Moves in a circle, firing hard when an enemy is detected robot.webpage= robocode.version=1.1.2 robot.java.source.included=true robot.author.name=Mathew Nelson and Flemming N. Larsen robot.classname=sample.SpinBot robot.name=SpinBot robocode/robocodeextract/robots/sample/Corners.java0000644000175000017500000001006211130241114022065 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial implementation * Flemming N. Larsen * - Maintainance *******************************************************************************/ package sample; import robocode.DeathEvent; import robocode.Robot; import robocode.ScannedRobotEvent; import static robocode.util.Utils.normalRelativeAngleDegrees; import java.awt.*; /** * Corners - a sample robot by Mathew Nelson, and maintained by Flemming N. Larsen *

* This robot moves to a corner, then swings the gun back and forth. * If it dies, it tries a new corner in the next round. */ public class Corners extends Robot { int others; // Number of other robots in the game static int corner = 0; // Which corner we are currently using // static so that it keeps it between rounds. boolean stopWhenSeeRobot = false; // See goCorner() /** * run: Corners' main run function. */ public void run() { // Set colors setBodyColor(Color.red); setGunColor(Color.black); setRadarColor(Color.yellow); setBulletColor(Color.green); setScanColor(Color.green); // Save # of other bots others = getOthers(); // Move to a corner goCorner(); // Initialize gun turn speed to 3 int gunIncrement = 3; // Spin gun back and forth while (true) { for (int i = 0; i < 30; i++) { turnGunLeft(gunIncrement); } gunIncrement *= -1; } } /** * goCorner: A very inefficient way to get to a corner. Can you do better? */ public void goCorner() { // We don't want to stop when we're just turning... stopWhenSeeRobot = false; // turn to face the wall to the "right" of our desired corner. turnRight(normalRelativeAngleDegrees(corner - getHeading())); // Ok, now we don't want to crash into any robot in our way... stopWhenSeeRobot = true; // Move to that wall ahead(5000); // Turn to face the corner turnLeft(90); // Move to the corner ahead(5000); // Turn gun to starting point turnGunLeft(90); } /** * onScannedRobot: Stop and fire! */ public void onScannedRobot(ScannedRobotEvent e) { // Should we stop, or just fire? if (stopWhenSeeRobot) { // Stop everything! You can safely call stop multiple times. stop(); // Call our custom firing method smartFire(e.getDistance()); // Look for another robot. // NOTE: If you call scan() inside onScannedRobot, and it sees a robot, // the game will interrupt the event handler and start it over scan(); // We won't get here if we saw another robot. // Okay, we didn't see another robot... start moving or turning again. resume(); } else { smartFire(e.getDistance()); } } /** * smartFire: Custom fire method that determines firepower based on distance. * * @param robotDistance the distance to the robot to fire at */ public void smartFire(double robotDistance) { if (robotDistance > 200 || getEnergy() < 15) { fire(1); } else if (robotDistance > 50) { fire(2); } else { fire(3); } } /** * onDeath: We died. Decide whether to try a different corner next game. */ public void onDeath(DeathEvent e) { // Well, others should never be 0, but better safe than sorry. if (others == 0) { return; } // If 75% of the robots are still alive when we die, we'll switch corners. if ((others - getOthers()) / (double) others < .75) { corner += 90; if (corner == 270) { corner = -90; } out.println("I died and did poorly... switching corner to " + corner); } else { out.println("I died but did well. I will still use corner " + corner); } } } robocode/robocodeextract/robots/sample/Tracker.properties0000644000175000017500000000055011052312544023332 0ustar lambylamby#Robot Properties #Sun Aug 20 21:20:26 EST 2006 robot.description=\ A sample robot\n\n Locks onto a robot, moves close, fires when close. robot.webpage= robocode.version=1.1.2 robot.java.source.included=true robot.author.name=Mathew Nelson and Flemming N. Larsen robot.classname=sample.Tracker robot.name=Tracker robocode/robocodeextract/robots/sample/Crazy.java0000644000175000017500000000600611130241114021545 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial implementation * Flemming N. Larsen * - Maintainance *******************************************************************************/ package sample; import robocode.*; import java.awt.*; /** * Crazy - a sample robot by Mathew Nelson, and maintained by Flemming N. Larsen *

* This robot moves around in a crazy pattern */ public class Crazy extends AdvancedRobot { boolean movingForward; /** * run: Crazy's main run function */ public void run() { // Set colors setBodyColor(new Color(0, 200, 0)); setGunColor(new Color(0, 150, 50)); setRadarColor(new Color(0, 100, 100)); setBulletColor(new Color(255, 255, 100)); setScanColor(new Color(255, 200, 200)); // Loop forever while (true) { // Tell the game we will want to move ahead 40000 -- some large number setAhead(40000); movingForward = true; // Tell the game we will want to turn right 90 setTurnRight(90); // At this point, we have indicated to the game that *when we do something*, // we will want to move ahead and turn right. That's what "set" means. // It is important to realize we have not done anything yet! // In order to actually move, we'll want to call a method that // takes real time, such as waitFor. // waitFor actually starts the action -- we start moving and turning. // It will not return until we have finished turning. waitFor(new TurnCompleteCondition(this)); // Note: We are still moving ahead now, but the turn is complete. // Now we'll turn the other way... setTurnLeft(180); // ... and wait for the turn to finish ... waitFor(new TurnCompleteCondition(this)); // ... then the other way ... setTurnRight(180); // .. and wait for that turn to finish. waitFor(new TurnCompleteCondition(this)); // then back to the top to do it all again } } /** * onHitWall: Handle collision with wall. */ public void onHitWall(HitWallEvent e) { // Bounce off! reverseDirection(); } /** * reverseDirection: Switch from ahead to back & vice versa */ public void reverseDirection() { if (movingForward) { setBack(40000); movingForward = false; } else { setAhead(40000); movingForward = true; } } /** * onScannedRobot: Fire! */ public void onScannedRobot(ScannedRobotEvent e) { fire(1); } /** * onHitRobot: Back up! */ public void onHitRobot(HitRobotEvent e) { // If we're moving the other robot, reverse! if (e.isMyFault()) { reverseDirection(); } } } robocode/robocodeextract/robots/sample/Walls.properties0000644000175000017500000000054411052312544023024 0ustar lambylamby#Robot Properties #Sun Aug 20 21:21:53 EST 2006 robot.description=\ A sample robot\n\n Moves around the outer edge with the gun facing in robot.webpage= robocode.version=1.1.2 robot.java.source.included=true robot.author.name=Mathew Nelson and Flemming N. Larsen robot.classname=sample.Walls robot.name=Walls robocode/robocodeextract/robots/sample/Target.properties0000644000175000017500000000064011052312544023165 0ustar lambylamby#Robot Properties #Sun Aug 20 21:18:46 EST 2006 robot.description=\ A sample robot\n Sits still. Moves every time energy drops by 20.\n This Robot demonstrates custom events. robot.webpage= robocode.version=1.1.2 robot.java.source.included=true robot.author.name=Mathew Nelson and Flemming N. Larsen robot.classname=sample.Target robot.name=Target robocode/robocodeextract/.classpath0000644000175000017500000000047511052366376017035 0ustar lambylamby robocode/robocodeextract/compilers/0000755000175000017500000000000011201531251017017 5ustar lambylambyrobocode/robocodeextract/compilers/CompilerTest.java0000644000175000017500000000017611130241114022275 0ustar lambylambypublic class CompilerTest { public static void main(String args[]) { System.out.println("Compiler operational"); } } robocode/robocodeextract/compilers/buildJikes.sh0000644000175000017500000000013411052312552021443 0ustar lambylamby#!/bin/sh cd jikes-1.22 chmod a+rx configure ./configure make mkdir -p bin cp src/jikes bin/robocode/robocodeextract/browser.sh0000644000175000017500000000357011052367010017052 0ustar lambylamby#!/bin/sh # ****************************************************************************** # * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors # * All rights reserved. This program and the accompanying materials # * are made available under the terms of the Common Public License v1.0 # * which accompanies this distribution, and is available at # * http://robocode.sourceforge.net/license/cpl-v10.html # * # * Contributors: # * Mathew Nelson # * - Initial API and implementation # ****************************************************************************** # Choose your own here... #which="konqueror" #which="mozilla" #which="firefox" #which="galeon" if [[ $which == "" ]]; then which firefox && which="firefox-tab" fi if [[ $which == "" ]]; then which mozilla && which="mozilla-tab" fi if [[ $which == "" ]]; then which konqueror && which="konqueror" fi if [[ $which == "" ]]; then which galeon && which="galeon-tab" fi if [[ $which == "firefox" ]]; then # New or existing firefox firefox $1 & fi if [[ $which == "firefox-tab" ]]; then # Use new tab in existing firefox, or open new firefox -remote "openURL($1,new-tab)" || firefox $1 & fi if [[ $which == "mozilla" ]]; then # New mozilla. mozilla $1 & fi if [[ $which == "mozilla-tab" ]]; then # Use new tab in existing mozilla, or open new window. gnome-moz-remote --remote="openURL($1,new-tab)" || gnome-moz-remote $1 & fi if [[ $which == "mozilla-win" ]]; then # Open new window in existing mozilla (may not work), or open new process. gnome-moz-remote --remote="openURL($1,new-window)" || gnome-moz-remote $1 & fi if [[ $which == "konqueror" ]]; then konqueror $1& fi if [[ $which == "galeon" ]]; then # new Galeon galeon $1 & fi if [[ $which == "galeon-win" ]]; then # Galeon in new window: galeon -w $1 & fi if [[ $which == "galeon-tab" ]]; then # Galeon in new tab: galeon -n $1 & firobocode/robocodeextract/robocodeextract.iml0000644000175000017500000000121411105671256020727 0ustar lambylamby robocode/robocodeextract/license/0000755000175000017500000000000011052312542016450 5ustar lambylambyrobocode/robocodeextract/license/cpl-v10.html0000644000175000017500000003036011052312542020522 0ustar lambylamby

Common Public License Version 1.0

THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.

1. DEFINITIONS

"Contribution" means:

a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and

b) in the case of each subsequent Contributor:

i) changes to the Program, and

ii) additions to the Program;

where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program.

"Contributor" means any person or entity that distributes the Program.

"Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program.

"Program" means the Contributions distributed in accordance with this Agreement.

"Recipient" means anyone who receives the Program under this Agreement, including all Contributors.

2. GRANT OF RIGHTS

a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form.

b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder.

c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program.

d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement.

3. REQUIREMENTS

A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that:

a) it complies with the terms and conditions of this Agreement; and

b) its license agreement:

i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose;

ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits;

iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and

iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange.

When the Program is made available in source code form:

a) it must be made available under this Agreement; and

b) a copy of this Agreement must be included with each copy of the Program.

Contributors may not remove or alter any copyright notices contained within the Program.

Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution.

4. COMMERCIAL DISTRIBUTION

Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense.

For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages.

5. NO WARRANTY

EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations.

6. DISCLAIMER OF LIABILITY

EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

7. GENERAL

If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.

If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, if Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed.

All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive.

Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved.

This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation.

robocode/robocodeextract/robocode.bat0000644000175000017500000000017311052312552017314 0ustar lambylambyjava -Xmx512M -Dsun.io.useCanonCaches=false -cp libs/robocode.jar;libs/codesize.jar;libs/cachecleaner.jar robocode.Robocoderobocode/robocodeextract/libs/0000755000175000017500000000000011201531251015753 5ustar lambylambyrobocode/robocodeextract/.settings/0000755000175000017500000000000011052367026016753 5ustar lambylambyrobocode/robocodeextract/.settings/org.eclipse.jdt.core.prefs0000644000175000017500000000116611052367026023741 0ustar lambylamby#Wed Jul 02 23:14:43 CEST 2008 eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.5 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.source=1.5 robocode/robocodeextract/battles/0000755000175000017500000000000011052312552016465 5ustar lambylambyrobocode/robocodeextract/battles/intro.battle0000644000175000017500000000052411052312552021016 0ustar lambylamby#Battle Properties #Thu Apr 12 21:49:42 CEST 2007 robocode.battleField.width=800 robocode.battleField.height=600 robocode.battle.numRounds=1 robocode.battle.gunCoolingRate=0.1 robocode.battle.rules.inactivityTime=450 robocode.battle.selectedRobots=sample.Tracker,sample.SittingDuck robocode.battle.initialPositions=(50,50,0),(?,?,?)robocode/robocodeextract/battles/sample.battle0000644000175000017500000000052011052312552021140 0ustar lambylamby#Battle Properties #Thu Apr 12 21:48:17 CEST 2007 robocode.battleField.width=800 robocode.battleField.height=600 robocode.battle.numRounds=10 robocode.battle.gunCoolingRate=0.1 robocode.battle.rules.inactivityTime=450 robocode.battle.selectedRobots=sample.Corners,sample.Fire,sample.MyFirstRobot,sample.SittingDuck,sample.Walls robocode/robocode/0000755000175000017500000000000011130004754013433 5ustar lambylambyrobocode/robocode/.externalToolBuilders/0000755000175000017500000000000011124141516017664 5ustar lambylambyrobocode/robocode/.externalToolBuilders/build.xml0000644000175000017500000000324611124141516021512 0ustar lambylamby robocode/robocode/.externalToolBuilders/Ant Builder - prepare robocode launch dir.launch0000644000175000017500000000265011052367444030471 0ustar lambylamby robocode/robocode/.externalToolBuilders/org.eclipse.jdt.core.javabuilder.launch0000644000175000017500000000100710602565032027271 0ustar lambylamby robocode/robocode/robocode.iml0000644000175000017500000000152311105671264015743 0ustar lambylamby robocode/robocode/Robocode.launch0000644000175000017500000000601011130004754016360 0ustar lambylamby robocode/robocode/.project0000644000175000017500000000143311107420066015105 0ustar lambylamby robocode robocodeextract org.eclipse.jdt.core.javabuilder org.eclipse.ui.externaltools.ExternalToolBuilder LaunchConfigHandle <project>/.externalToolBuilders/Ant Builder - prepare robocode launch dir.launch org.eclipse.jdt.core.javanature org.eclipse.team.cvs.core.cvsnature robocode/robocode/.classpath0000644000175000017500000000065211061321340015415 0ustar lambylamby robocode/robocode/ar/0000755000175000017500000000000011052312554014040 5ustar lambylambyrobocode/robocode/ar/robocode/0000755000175000017500000000000011052312554015634 5ustar lambylambyrobocode/robocode/ar/robocode/cachecleaner/0000755000175000017500000000000011124141510020221 5ustar lambylambyrobocode/robocode/ar/robocode/cachecleaner/CacheCleaner.java0000644000175000017500000000440111130241114023356 0ustar lambylamby/******************************************************************************* * Copyright (c) 2007, 2008 Aaron Rotenberg and Robocode Contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Aaron Rotenberg * - Initial version * Flemming N. Larsen * - Moved functionality from main() into the public method clean() in order * to let the Robocode game call the cleanup tool *******************************************************************************/ package ar.robocode.cachecleaner; import robocode.manager.RobocodeManager; import java.io.File; import java.io.IOException; /** * Cache cleaner used for cleaning the /robot directory of Robocode, especially * for RoboRumble * * @author AaronR * @author Flemming N. Larsen (minor optimizations) */ public final class CacheCleaner { private CacheCleaner() {} public static void main(String[] args) { clean(); } public static void clean() { deleteFile("roborumble/temp"); deleteFile("robots/.robotcache"); deleteFile("robots/robot.database"); System.out.print("Creating roborumble/temp... "); if (new File("roborumble/temp").mkdir()) { System.out.println("done."); } else { System.out.println("failed."); } System.out.print("Rebuilding robot database... "); new RobocodeManager(false).getRobotRepositoryManager().getRobotRepository(); // Force rebuild System.out.println("done."); } private static void deleteFile(String filename) { System.out.print("Deleting " + filename + "... "); try { recursivelyDelete(new File(filename)); System.out.println("done."); } catch (IOException ex) { System.out.println("failed."); } } private static void recursivelyDelete(File file) throws IOException { if (file.exists()) { if (file.isDirectory()) { final File[] files = file.listFiles(); for (File f : files) { recursivelyDelete(f); } } if (!file.delete()) { throw new IOException("Delete failed."); } } } } robocode/robocode/resources/0000755000175000017500000000000011124143372015450 5ustar lambylambyrobocode/robocode/resources/icons/0000755000175000017500000000000011061320762016563 5ustar lambylambyrobocode/robocode/resources/icons/robocode-icon.png0000644000175000017500000000430310513551474022022 0ustar lambylambyPNG  IHDR00`ngAMA7tEXtSoftwareAdobe ImageReadyqe<UIDATxXmL[}kcc p 1a8cJ!J&*$TMURih_#Ҫ%ZRNJё6D  llq ={ CJӎsϹdۍa'OMSN9 GN{]'{-(?NlsիWv;j>}ѣGS>lbyybb߽SVB Bz~WX)jMd,5]Bb~:2Î ;w9̭Vwﱝr^Z_JE HX4 PYY7CC/vbiLn#++)L7ssGhL3 oؽ{ݾ nbFcb\ DBzm7KKK7eHHb)} @h䔴]~eٵ"躑ѣGinnFw``w1]&SҘX ]pakB% lkKKKab !F 1ABn|4<+y,O/rFqi2VRS EΖ-C! DQ7hBZ63Bi!IޝϥPXEBnݨ=GVYvㄩ)q"ҥKZ(|>*",e5>PWwڵk>Ij Dgjŋ?{Jk DiL,E֮6C#V,.>ؿۧ7ovÇ rLOKfFkf[ͭee+**DLD4]2 tqyU pwZJJJPGGY@y*9LB|cɮZ7_Rt<7U(*z/~W]-HY_Ԉ^ ‰?7u:$\XCH^総e !b>?3[0\?|Em a .$8w]\x"ccO>% 9>FJ g2) _e(#nJPcc#m!,@eXB~i }%ZT@'J! NFxs4!dE,AqO ,tB%IIH.QNzUst1+fggL ,)X @#J+%@TL!.ؚbQQ'o `:@hL,!H|Z@B9dBH-bޒҜ{Yvv6 - ̀//(>A  *%Њ} .1_|+݃"} !H/===fup`X$e{j4 :,v xgϞ& S<!G  *HԘCp+r\3xql NdץeI: UM(HDX6obB21E]d7 1B|%H"C}xl}!ku(}Y%+Ybhm`^Bb, Z%1!:,BOۺlrñ9!L&ƺ-ˌ0.ٟ]W|e~E)^Vhx2,!e;{ů2qoBЋ\{-s(mu۫ 0SQ,ʢIENDB`robocode/robocode/resources/battleRecord.xsd0000644000175000017500000001617311124141524020607 0ustar lambylamby robocode/robocode/resources/versions.txt0000644000175000017500000030524511131763460020076 0ustar lambylambyVersion 1.6.2 (04-Jan-2009) --------------- = Bugfixes = * Bug [2467536] Robot name was missing when replaying XML record. * Bug [2465580] Junior Robot turnAheadRight() bug. When a JuniorRobot was calling turnAheadRight(), turnAheadLeft(), turnBackRight(), or turnBackLeft() - the following exception occurred causing the robot to be terminated: java.lang.ClassCastException: robocode.peer.proxies.StandardRobotProxy * Bug [2449081] Exception when changing between Robot to AdvancedRobot. When a robot was changed from a Robot into an AdvancedRobot and recompiled, the game would cast a ClassCastException if a battle was started or restarted including that particular robot. However, this bug did not occur with new battles where the list of robots was refreshed (by pressing Ctrl+R). Version 1.6.2 Beta 4 (23-Dec-2008) --------------- = Bugfixes = * Fixed the Open Battle dialog, where the robots were not being loaded, but which instead behaved the same way as the New Battle dialog. * Fixed NullPointerException with the new Record and Playback (Replay) feature, when trying to play a recorded battle. * Fixed serialization problems with scan arcs (Arc2D), when robot paintings with scan arcs are being recorded. * Fixed problem with reloading robot repository on each next battle dialog. Now the user must press Ctrl+R in order to refresh the robot repository as this is not done automatically anymore. * Fixed two ArrayIndexOutOfBoundsExceptions occurring when opening a new battle with fewer robots, when a battle with more robots are ongoing. Version 1.6.2 Beta 3 (18-Dec-2008) --------------- = Changes = * Published new battle events and battle snapshots in the Control API, i.e. in the robocode.control package. * Added missing javadocs (HTML documentation) to public Robocode API classes. = Bugfixes = * The current scoring (not the total scoring) was calculated wrong from version 1.6.1. The current Ramming Kill Bonus was set to current bullet kill bonus, which gave wrong ranking in the Ranking Panel. * Bug [2410856]: wrong bullet power could be reported back from Bullet.getPower(), which could be > Rules.MAX_BULLET_POWER or < Rules.MIN_BULLET_POWER. * Bug [2405844]: gunHeat could be negative, which should never occur. * Bug [2412707]: Replay exception, where an ArrayIndexOutOfBoundsException occurred in some situations. * Fixed problem with RobocodeEngine.setVisible(true), where the RobocodeEngine would hang forever. Version 1.6.2 Beta 2 (07-Dec-2008) --------------- = Bugfixes = * Fixed problem with Bullet identity. * Battle cleanup concurrency issue. * Fixed problem with robots without package. * AWT AppContext cleanup. * Fixed versions comparison problem. = Changes = * Mostly cleanup of code and documentation. * Improved compatibility with RobocodeJGAP. * Development robot version names were visible in the robot repository. Version 1.6.2 Beta (25-Nov-2008) --------------- = Bugfixes = * Bug [2214620]: Robots were paying CPU time for painting. Now Robocode gives a robot unlimited time when painting is enabled on UI (in the robot dialog) for that robot. * Robocode will not load non-valid robots from repository anymore. * Fixed placement of the robot dialogs (aka. robot console windows). * Exception on robot's Condition doesn't break further processing now. * Bug [2335165]: RoboRumble output was spammy, outputting log after the first battle. * java.lang.IllegalArgumentException: Line unsupported: interface Clip supporting format could occur when starting Robocode. = New features = * Battle recording and replay: Saving to binary and xml file. Robot painting and debug properties are now being recorded, but robot painting is not exported to xml. Recording is slowing down the game and eats memory and disk space. You need to enable it in options. * New command line option -replay for replaying a battle record. * New dialog for battle console and battle turn snapshots. * Robot dialog have new tab-page with robot properties. * Robot dialog have green hinted button for painting robots. * The robot API has been extended with a new setDebugProperty() method. See the sample.PaintingRobot robot for example of usage. * The robocode.control package has been improved so that the RobocodeEngine is able to return much more detailed information about was is going on inside the battle for each turn, round, and battle thru a new IBattleListener interface. = Changes = * Redesigned RobotPeer and Battle. Now we send messages between threads instead of synchronizing indifidual properties. Code here is much more readable now. This is big change. * Most synchronization is now interlocked. * Event manager, priority and dispatch of events refactored. * The methods setPriority() and setTime() on the Event classes are no longer part of RobotAPI. These methods were used internally by the game. Events are final classes now. * More unit tests were added. * Graphics2DProxy optimized. * Interactive robots are better detected to not waste time of non-interactive robots. * Team messages are deserialized on receiver robot thread. * Got rid of robot loader thread. Now Robocode is loading on robot's thread, where we got more security. * Introduced new interfaces for code components. * Robot threads have NORM_PRIORITY - 1, AWT UI have NORM_PRIORITY + 2. * Feature Request [2117285]: We now upload version of client with resuts from roborumble. * Robots which are wrong behaving are removed from the robot repository and are not given another chance to run. This is for SkippedTurns, for unstopable robots and for robots with class loading troubles. * Changed the formatting of this versions.txt file in order to improve readability. Version 1.6.1.4 (14-Nov-2008) --------------- = Bugfixes = * Loosing robots were not receiving onBattleEnded(BattleEndedEvent) events. * A new security issue fix for robots that were able to execute code thru the Event Dispatch Thread (EDT). Robots that try to access the EDT will be disabled! * Bug [2210749]: drawArc() does not work as expected. This bug has been fixed. In addition, both drawArc() and fillArc() are now using the Robocode coordinate and angle system. * Bug [2157167]: Blank console window when compiling. Some systems still had this issue, so a new fix has been applied. = New feature = * The results and current rankings (during a battle) is now showing the score as percentage(s) in parenthesis right beside the score points like e.g. '7875 (12%)' for the total score in the results and '21 / 2900 (7 / 14%)' with the current rankings. * Thanks goes to Endre Palatinus, Eniko Nagy, Attila Csizofszki and Laszlo Vigh for this patch/contribution! = Changes = * The command-line option EXPERIMENTAL (true/false) allowing access to the robot interface peer is now working for the RobocodeEngine class also. Version 1.6.1.3 (24-Oct-2008) --------------- = Bugfixes = * [2157167] Blank console window when compiling. This bug was introduced in 1.6.1.2. When trying to compile a robot which gave a compiler error, the output console window for the compiler could be blank on Windows system, and even hang. Now the compiler error is output correctly as in previous versions. * [2070840] Roborumble "ITERATE" broken: When running RoboRumble with ITERATE=YES, DOWNLOAD=YES, and RUNONLY=SERVER, the ratings were only read once, not per iteration. This bugfix removes a very old bug and the need of using a batch file as workaround in order to do the loop with updated ratings. * [2121034] The -DROBOTPATH= option did not work: Now it works. * [2134416] Broken .sh files: An misplaced colon character was included in the teamrumble.sh file. * Fixed issue with first time access to a robot's data directory after startup, where the robot was not allowed to write to it's file. = Changes = * [2022774] Various usability issues: * The list of available robots in the 'New Battle' dialog is now automatically refreshed before it is being shown, when a new robot has been compiled or a robot has been removed. * The 'Save' and 'Save As' in the File menu of the Robot Editor is now enabled and disabled depending if there is anything to save or not. Version 1.6.1.2 (12-Sep-2008) --------------- = Bugfixes = * RoboRumble: Sometimes results were given to the wrong robots, which gives a problem with the robot rankings in the RoboRumble, TeamRumble and MeleeRumble * Thanks goes to Joachim Hofer AKA Qohnil for fixing this issue! :-) * RoboRumble: Robots that read their data file got the following error message: 'Preventing unknown thread from access: (java.io.FilePermission...' * ArrayOutOfBoundsException could occur when accessing the Graphics2D object returned by the getGraphics() method on the Robot. * The draw(Shape) method on the Graphics2D object returned by the getGraphics() method could not draw lines. * The onMousePressed() event was called twice instead of only one time per mouse press. Version 1.6.1.1 (28-Aug-2008) --------------- = Bugfixes = * Issues with the scoring. Sometimes the robots were ranked incorrectly compared to their total scores given in the battle results. * When disabling the security (-DNOSECURITY=true) it would not be possible to run any battles as the following error would occur: 'RobocodeFileOutputStream.threadManager cannot be null!' * [2066996] -battle broken: When using a battle file, the battles were not displayed one the GUI. * [2064834] Robot problem after Options -> Clean robot cache: Robots that tried to access their data file, like e.g. sample.SittingDuck got a java.security.AccessControlException. * Sometimes the compiler window would hang when trying to compile, but only when the compiler gave compilation errors. * IllegalArgumentException occurred when calling setStroke() or setComposite() on the Graphics2D object returned by the new getGraphics() method on the Robot. = Changes = * The intro battle will only be shown if a battle file has not been specified using the -battle command-line argument and Robocode is being run for the first time since installation. Previously, the intro battle was always shown even though a battle file had been specified. Version 1.6.1 (17-Aug-2008) --------------- = Changes = == New methods == * Added getGraphics() to Robot and IBasicRobotPeer, meaning that a robot is now able to paint itself at any time, and not only using the onPaint() event handler. * Added getStatusEvents() to AdvancedRobot and IAdvancedRobotPeer, so a robot is now able to handle status events in the middle of an event handler. == New event == * The new event BattleEndedEvent has been added, and will call the new event handler onBattleEnded() on the robots, when the battle is ended (Feature Request 1878233). * When reading the BattleEndedEvent it is possible to read out the results of the battle of the individual robot or team. In addition, it is possible to check if the battle was aborted by the game or user. The battle results will only be available if the battle is not aborted (where the results does not count). * The the onBattleEnded() event handler is provided through the new IBasicEvents2 class. == Paint events == * Paint events are now put in the robot event queue, meaning that the robots will pay CPU time when their onPaint() event handler is called. * Added the PaintEvent, which makes it possible to set the event priority of paint events using the AdvancedRobot.setEventPriority(). == Mouse and keyboard events == * Mouse and keyboard event have also been put in the robot event queue, and thus the robots will pay CPU time when their onMouse*() and onKey*() event handlers are called. * Mouse and Keyboard events have been added as public classes as well. == Package name == * The max. length of a robot's full package name has been extended from 16 to 32 characters (Feature Request 1954853). * The Robocode Repository is able to handle this (verified with Dan Lynn). == New TPS slider == * The TPS slider has been redesigned to be more exponential, so it covers battle in slow speed (1-30 TPS), higher speed (30 - 120 TPS), and fast speed (120 - 1000 TPS). * If you set the slider to max. TPS the game will run as fast as possible. This feature already existed in earlier versions. * If you set the slider to minimum (0 TPS) the game will pause. This is a new feature. == The FPS (frames per second) == * The max. FPS is now fixed to be max. 50 FPS allowing the TPS (turns per second) to be even faster. == New title bar == * The title on the Robocode window is now showing the current turn in a battle, and is updated every half second. * The layout of the information shown in the title has been improved a bit. == Dialogs == * The About box, New Battle Dialog, Preferences Dialog, Ranking Dialog, and the Compiler Preferences Dialog are now modal. * It is now possible to close the New Battle and Results Dialog by pressing the Esc key. == Ranking panel == * The menu item for the Ranking Panel is now hidden when replaying a battle, and the panel is now being hidden, if it is visible, while the battle is being replayed. The reason for hiding the Ranking Panel is that the replay feature does not support displaying the current rankings during the replay, i.e. the current scores are not recorded. == Command-line options == * Added the new -DPARALLEL option (set to true or false), which allows robots to run in parallel intended to take advantage of more CPU's available in the system. This option may speedup battles with multiple CPU time consuming robots. However, the time measuring is not per robot. * Added the new -DRANDOMSEED option (set to a random seed value), which enables the new repeatable and deterministic random generator. The benefit of using this option to make it easier to test and debug your robots, as your robots will appear in the exactly same positions, when you rerun a battle. * The -DPARALLEL and -DRANDOMSEED option has no effect when running RoboRumble, MeleeRumble, and TeamRumble. == New Random Generator == * Added a new deterministic and repeatable random generator is used by the game and overrides the random generator used throughout the whole virtual Java machine, so methods like e.g. Math.random() will be using the exactly the same deterministic random generator forced by Robocode. * The new random generator will only be deterministic, if the -DRANDOMSEED option is enabled, i.e. when -DRANDOMSEED=12345678 (or another value). Otherwise the the battles will run truly randomized. == System logging == * The system log output has now been split, so that logged errors are sent to System.err and logged messages are sent to System.out. This makes it possible to filter out messages from errors when reading out the logs from Robocode. * The system log now also includes a full stack trace when errors are logged, making it easier to determine where an error has occurred. == [2022774] Various usability issues == * Added "Enable all" and "Disable all" button in the View Options of the Preferences. * When the TPS slider is set to 0, the game is paused, and the Pause/Resume button set to paused mode. Now, if the Pause/Resume button is pressed, the game will resume at 1 TPS, and the TPS slider will now move to 1. Previously it will set to 0. * In the New Battle window, the focus is now kept in the list of available robots when one of the two 'Add' buttons has been pressed. Previously the focus was lost, and you had to reselect robots in the list of available robots in order to add more robots. * It is now possible to add multiple robots using only the arrow keys with e.g. the Alt+A in order to add more robots to the battle. * Improved some menus a bit with better names, and did some rearrangements of the order of the menu items here and there. Version 1.6.0 (01-May-2008) --------------- = Bugfixes = * The CPU constant was not calculated the first time Robocode was started up. * Removed ^M characters from the buildJikes.sh file so that the Jikes compiler can be built under Unix, Linux and Mac OS X. * Fixed a security issue, where robot was able to access the internals of the Robocode game thru the AWT Event Queue. * Robots that try to access the AWT Event Queue will be disabled = Major changes = * A new package named robocode.robotinterfaces has been introduced, which contains pure Java robot interfaces for basic, advanced, interactive, junior and team robots. See the Javadocs (HTML) documentation for more details about these new interfaces. * The main purpose robot interfaces is to make it possible for developers to create robots with other programming languages that requires interfaces instead of classes. However, the provided robot interfaces obeys the rules within Robocode. But it is possible to create new robot types with other methods names etc. from the robot interfaces, and it is also possible to create ordinary robots based directly on the robot interfaces. * See the new 'sampleex' directory for some examples of how to use these new interfaces in Java. * The introduction of the new robot interfaces required a great deal of changes and cleanup of the internal structures of Robocode, but for the better. * A new command line option has been made for Robocode named EXPERIMENTAL, which must be set to true in order to allow the robots to access the internal robot peer with the robot interfaces for performing robot operations. If this flag is not set, you'll get a SecurityException in your robot if it is inherited from a robot interface. This option must be set in the robocode.bat/robocode.sh like -DEXPERIMENTAL=true Note that this experimental option might be removed in the future so that robots are always allowed to access the robot peer from the new robot interfaces. * Most work with the robot interfaces were performed by Pavel Savara that has joined the development of Robocode, and which has done a tremendous job with the new robot interfaces. = Minor changes = * Added a "Make all bullets white" option to the Rendering Options. * When this option is enabled, all bullets on the battle field will be painted in white. Use this options when you need to see all bullets on the battle field, i.e. when bullet colors are almost invisible. * Lots of the Javadoc (HTML) documentation for the Robocode APIs were updated. Version 1.5.4 (15-Feb-2008) --------------- = Bugfix = * The CPU constant was way too little compared to version 1.4.9 * This is a critical bug when Robocode is used for competitions * Now the CPU calculation has been improved, where a heavy math benchmark has been adopted from Robert D. Maupin (AKA Chase-san) * The method for determining if a robot has exceeded it's CPU time limit has been improved to use nano second precision, to get rid of an issue with millisecond granularity. This method was created by Julian Kent (AKA Skilgannon) Version 1.5.3 (30-Jan-2008) --------------- = Bugfixes = * Some of the mnemonics on the menus on the Help menu did not work correctly * NullPointerException occurred when clicking a robot button on the right side of the battle view, when no battle was running = Changes = * All functions key shortcuts have been replaced to comply with OSes where the function keys (F1 - F12) are not available or have a specific purpose, and thus should not be overridden * The F5 shortcut key for refreshing the list of available robots in the New Battle, Robot Packager, Robot Extractor, and Team Creator window has been changed to 'modifier key' + R, i.e. Ctrl+R on Windows and Linux, and Command+R for Mac OS * The F6 shortcut key for 'Compile' has been changed to 'modifier key' + B, i.e. Ctrl+B on Windows and Linux, and Command+B for Mac OS * The F3 shortcut key for 'Find Next' has been changed to 'modifier key' + G, i.e. Ctrl+G on Windows and Linux, and Command+G for Mac OS * When a robot or team is being packaged an UUID is now put in the .properties and/or .team files in the newly generated robot or team archive file (.jar file) * The UUID is a unique identifier for the robot or team, which is generated every time a robot or team package is being created or overwritten * This feature has been made in advantage to support coming features provided in Robocode Repository, which is currently being updated Version 1.5.2 (08-Jan-2008) --------------- = Bugfix = * On some systems Robocode would not start up when trying to run robocode.bat or robocode.sh Version 1.5.1 (12-Dec-2007) --------------- = Bugfix = * Fixed security flaw with the Event Dispatch Thread, where robots could use the SwingUtilities.invokeLater() for running any code they should like to * Thanks goes to John Cleland who reported this security flaw and provided some very good examples of robot that could do some nasty cheats Version 1.5 (05-Dec-2007) --------------- = Changes = * Redundant HitRobotEvents are no longer occurring when Robocode is performing collision detection between two robots * Previously: If a collision between a stationary robot (i.e. not moving) and another robot that was moving, then two HitRobotEvents would first be sent to each robot based on the stationary robot even though no damage was done. Next, two HitRobotEvents would be sent to each robot based on the robot that was moving, which WAS causing damage * Now: HitRobotEvents will only occur when damage is done to each robot, and no HitRobotEvents will be ever be sent when no damage is done, i.e. when a stationary robot is "colliding" with another robot * The events in the robot event queue are now sorted in chronological order so that events that occurred before newer events gets processed first * Previously, the event queue was ordered based on the event priorities so that the events with the highest priorities were processed first. This could cause some problems with robots with skipped turns, as their event queue would potentially contain events from different time frames * Now it is perfectly safe for robots to assume that events occurring before other event are processed first * Events occurring in the same time frame is still sorted based on their priorities so that the events with higher priorities are processed before events with lower priorities * The priority of the DeathEvent was changed from the reserved priority 100 to -1 in order to allow robots to process all pending events before they die * Previously, robots were not able to process all events when it died as the DeathEvent was having the highest possible priority * Now when the DeathEvent has the lowest priority, this will be the last event left on the robot's event queue before it dies. That is, all events in the event queue have already been processed when reaching the DeathEvent * The CPU constant is now measured in nanoseconds rather than milliseconds * Using the new features introduced of Java 5.0 provides more precise timing and also offer better granularity of timings * The "Number of Rounds" value on the New Battle Dialog is now saved and restored when the game is restarted, i.e. Robocode remember that value you used last time * Improved the output of the command line usage of Robocode when called from the command line with the -? or -help option = New features = * The Robot class has got a new onStatus(StatusEvent e) method which is automatically called for each turn of a battle, and which contain a complete snapshot of the current robot state at that specific time/turn * This new method makes it possible to map a specific robot field to a specific time * Added the Robot Cache Cleaner tool created by Aaron Rotenberg (AKA AaronR) * Used for cleaning the cache files for the robots, which is very useful with the RoboRumble client, where most problems can be solved by cleaning the robot cache files * This tool is activation by selecting "Clean Robot Cache" in the Options menu or by running the tool from a command line (standing in the robocode home directory): java -cp ./libs/robocode.jar;./libs/cachecleaner.jar ar.robocode.cachecleaner.CacheCleaner Version 1.4.9 (07-Nov-2007) --------------- = Bugfixes = * RoboRumble participants excluded with the EXCLUDE filter were also removed from the ratings, which is not the intension. * In addition, if trailing white-spaces occurred with the comma-separated list for the EXCLUDE filter, the filter did not filter out participants correctly * With the release of 1.4.8 this bug was claimed to be fixed, but unfortunately the bugfix was missing in the build of the 1.4.8 release * Corrected bug seen with the JuniorRobot, when first calling turnAheadLeft(100,90) and then turnRight(90) right after this call, where the robot turn quickly to the left, but slowly to the right * The calculation of the possible frame rate (FPS) was calculated incorrectly causing Robocode to run with lower FPS when rendering battles on the GUI compared to was is really possible to do with the available hardware * With this bugfix, Robocode will render the battles even faster than before in most cases = Changes = * When a new CPU constant is being calculated it will now take the time granularity (OS dependent) into account. Previously, if the CPU constant was less than the time millis granularity, then skipped turns did occur on robots when the CPU constant <= Time millis granularity * It is strongly encouraged that you recalculate your CPU constant when running this Robocode version the first time by selecting "Recalculate CPU constant" from the Options menu Version 1.4.8 (25-Oct-2007) --------------- = Bugfixes = * When debugging robots or the Robocode game itself within Eclipse on Windows, the Java VM was crashing with an "Access Violation" * With Robocode 1.4.7 a minor bug was introduced so that the robot console printed out "Wait interrupted" when a round was completed Version 1.4.7 (09-Oct-2007) --------------- = Bugfixes = * Some robots did not receive any score even though they won the battle due to Robocode did not always detect correctly that the robot's thread(s) had been properly terminated. * Thanks goes to Eric Simonton, David Alves, and "AaronR" for help solving this issue! * Teams located in the .robotcache dir were still put into the robot.database file. Thus, these teams located in the .robotcache dir were shown in the New Battle dialog * When stopping a battle while recording was enabled and then replaying the recorded battle, Robocode would show the last rounds of the battle even though no recording occurred for these rounds, i.e. "ghost" rounds * When using the -battle option Robocode would run at full speed, i.e. the TPS set to maximum, even though the GUI was enabled with a predefined TPS * Now, the TPS is only set to maximum when the -nodisplay option is used * Robocode was wasting time on trying to wake up robots that was dead * Robocode was blocked for the amount of milliseconds specified by the CPU constant when a robot was killed in a battle, as Robocode was waiting for the dead robot to wake up for exactly this amount of time = Robocode changes = * The Stop button is now only enabled when a battle is running and disabled afterwards * When starting Robocode, and the saved window locations (x and y coordinate) of a window does not fit into any of the available screens/displays (e.g. virtual desktop), when Robocode will center that window into the current screen displayed = RoboRumble changes = * The configurations files roborumble.txt, meleerumble.txt, and teamrumble.txt have been improved: * All properties are now documented and have been grouped more logically. * The BATTLESPERBOT property has been raised to 2000 for the RoboRumble and MeleeRumble * An exclude filter has now been added, which makes it possible to exclude participants that causes trouble somehow * The exclude filter is controlled using the new EXCLUDE property, which takes a comma-separate list of participants where the wildcards * and ? can be used * Excluded participants are not added to the participants file, and will not be downloaded or take part in battles Version 1.4.6 (25-Sep-2007) --------------- = Bugfixes = * The coordinates of a Bullet from a bullet event like HitByBulletEvent() was not correct as the coordinates of the bullets would follow the bullet explosion on the robot it has hit. * Now the coordinates of the Bullet will not change when it hits a robot or another bullet, even though the coordinates of the bullet explosion will change internally, but only for painting the explosion * This means that the coordinates of a bullet received from a bullet event will actually by on the real bullet line * The initial explosion painting on a robot has also changed so it shows exactly where the bullet has hit the robot, or more precisely the bounding box of the robot, which does not rotate with the robot rotation * When Robocode cleaned up the robot database a NullPointerException could occur if a file was missing which the database file referred to * The Restart button was enabled when do battles had been started previously * The areas of the battle field was repainted with the black background with the Robocode logo when the game was paused, and the battle window needed to be repainted * When the Robocode window was minimized the actual TPS and FPS were not shown * When installing new versions of Robocode on top of an existing Robocode installation, the About window did not have the right height = Changes = * The color of each bullet is now independent on the current color set with the setBulletColor() method. Previously, all bullets were instantly changing their colors when setBulletColor() was called. Now, the color of the bullet will stick to the bullet color set when the bullet was fired * Improved the "Check for new version", so that is able to differ between release type as alpha, beta, and final release types Version 1.4.5 The "Fair Play" release (17-Sep-2007) --------------- = Bugfixes = * Unfair play. Two robots with the same code (but different names) would get different scores instead of a 50-50 split * Robots listed before other robots in a battle would gain a minor benefit compared to the other robots, especially if they killed each other at the same time. Then the robot listed first would get a "half turn" advantage over the other robot * Now, the ordering does not matter anymore, as when ever the robots are checked one at a time in sequence, then they will be checked in random order * ConcurrentModificationException could still occur when called one of the getXXXEvent methods with an AdvancedRobot * Now all getXXXEvent methods like e.g. getAllEvents() are all synchronized directly with the internal event queue of the robot before reading out the events * Test Condition flag of a robot was not reset between rounds * If the robot thread was disabled while testing a condition for a custom event all following rounds will trigger a "robocode.exception.RobotException: You cannot take action inside Condition.test(). You should handleonCustomEvent instead." * Again, the title of Robocode was incorrectly showing round N+1 of N when a battle was ended * Memory leaks occurring during a round due to missing cleanup of bullets have been removed. Note that ALL bullets were actually cleaned up, when ending the battle (containing one or several rounds) * One good side-effect of this bugfix is that the game is speeded, especially when running in minimized mode, as the game does not have to perform unnecessary calculations on bullets that is not visible on the battle field anymore = Changes = * The sample robot named "sample.Interactive" has been changed so it continues moving forward or back when the UP or DOWN arrow key is being pressed down. * Previously, the robot would only move 50 pixel when pressing down the UP or down arrow key, which was not intuitive compared to the behaviour with traditional first person shooter games. Thus, this looked like a bug Version 1.4.4 (09-Sep-2007) --------------- = Bugfixes = * With version 1.4.3 a bug was introduced so that battleAborted() was called in the robocode.control.RobocodeListener when the battle was not aborted, i.e. when a battle completes successfully * This bug caused Robocode clients as e.g. RoboRumble to hang! * Removed Windows end-of-line characters from the .sh files for RoboRumble = Change = * Robocode now throws NullPointerException if the condition parameter has been set to null when calling addCustomEvent() or removeCustomEvent() on an AdvancedRobot Version 1.4.3 (07-Sep-2007) --------------- = Bugfixes = * Major bugfixes was done by Nathaniel Troutman to get rid of large memory leaks, especially when creating and destroying robocode.control.RobocodeEngine instances many times * Most of the memory leaks were caused by circular references between internal classes/objects in Robocode. Now, these circular references are cleaned up * The configuration files for RoboRumble was completely missing under the /roborumble folder, i.e. the meleerumble.txt, roborumble.txt, and teamrumble.txt * Fixed inconsistent behavior of the RobocodeEngine.setVisible(). * When invoking the RobocodeEngine to directly run a battle(s) and calling RobocodeEngine.setVisible(true), and then later call RobocodeEngine.setVisible(false) the results dialog would still show up at the end of a battle * This fix was done by Nathaniel Troutman * Did another fix where a dummy AWT (GUI) component was created even though the GUI was disabled causing problems when trying to run e.g. RoboRumble remotely without the GUI enabled * Sometimes the "New Batle" window would show robot classes that reside in the .robotcache folder under the /robots folder. This occured when the robot database was (re)builded, e.g. if the robot.database file was missing * When running battles including the MyFirstJunior and the pressing the mouse button outside of the battle field a ClassCastException would occur * When double-clicking the Restart button for the battle window the UI could lock up completely trying to play all battles, and it would not be possible to stop the battle Version 1.4.2 (26-Aug-2007) --------------- = Bugfixes = * RoboRumble was invoking AWT (GUI) stuff when running, which caused problems on systems without support graphical display or running RoboRumble remotely behind a firewall * When running robocode.control.RobocodeEngine it caused memory leaks each time a new instance of the RobocodeEngine was created, even though the object was completely destroyed * The onPaint() method was invoked just before the robot got the chance of updating it's internal world model. Now the battle view is updated as the first thing right after the robots have updated their internal model * One ConcurrentModificationException bug did still occur with the internal EventQueue of a robot * The Robocode engine was halted with spurious exceptions when an exception occurred inside a onPaint() method in a robot, i.e. when the robot itself causes an exception inside onPaint(). Now, whenever an exception occurs inside the onPaint() method of a robot, the exception is now being catched by Robocode and printed out in the robot console * Due to the bug found above regarding exceptions occurring inside the onPaint() method of a robot, exception handlers have now been added to all onKeyXXX and onMouseXXX events, where the exceptions are now printed out into the robot console Version 1.4.1 (19-Aug-2007) --------------- = Bugfix = * A couple of ConcurrentModificationException bugs have been introduced with version 1.4. ConcurrentModificationException in robots could occur on some systems, which in worst case could cause a robot to loose battles or in best case give a robot a lesser score * Thank goes to Helge Rhodin (AKA Krabb) for help with solving the bug! Version 1.4 (14-Aug-2007) The "Junior Robot" release --------------- = Bugfixes = * Static fields on robots were not cleaned up anymore after each battle has ended * When printing to 'out' in onScannedRobot() event before a scan() call, the the logging to out would stop with an system error that to much is printed out = Changes = == Added JuniorRobot == * This class is simpler to use than the Robot class and has a simplified model, in purpose of teaching programming skills to inexperienced in programming students * This new robot type has been designed by Nutch Poovarawan / Cubic Creative team * Added sample.MyFirstJuniorRobot * This robot is very similar to MyFirstRobot, but tracks it's scanned enemy better == GUI: Changed menu shortcut key == * Robocode forced the use of the Ctrl key to be used as menu shortcut key. Now Robocode ask the Java VM what menu shortcut key to use * This change means that Mac OS X users should now use the Command key instead of the control key * Thanks goes to Nutch Poovarawan for the tip of how to do this! :-) == Improved battleview a bit == * A red border is now painted around the battlefield, when the battleview's height and/or width is larger than the battlefield * Explosions are painted outside the battlefield, when the battleview is larger than the battlefield * The text for the Robot names and scores are now "clipped" to the width and height of the battleview instead of the battlefield == Added "Recalculate CPU constant" to the Options menu == * This makes it possible to force recalculation of the CPU constant == RoboRumble changes == * Redundant RoboRumble config files are now removed from the /config folder * Changed UPLOAD=NOT to UPLOAD=YES as default, i.e. the results are now automatically uploaded to the RoboRumble server Version 1.3.5 (04-Jul-2007) The "Fast renderings" release --------------- = Bugfixes = * The title was displaying "Playing round N+1 of N" when the battle has ended = Changes = == Faster rendering == * The battle rendering is now 30-50% faster due to image buffering (uses memory) * A new "Buffer images" option under the Rendering Options can be enabled/disabled on the fly while playing a battle. By default, "Buffer images" is enabled which makes the rendering faster, but which also uses additional memory * Due to the faster renderings, explosion debris is now enabled by default == Key events == * Key events are now received even though the battle view does not have the focus == Controlling Robocode == * The container classes in the robocode.control package are now Serializable, which makes it easy to load and store, battle specifications, results etc., but also to send these over the network Version 1.3.4 (27-Jun-2007) The "Interactive" release --------------- = Bugfixes = * NullPointerException occurred when trying to open the Sound Options page from the Preferences when no sound card (or actually audio mixer) is present in the system = New features = * The Robot class has now been extended with keyboard and mouse events: onKeyTyped, onKeyPressed, onKeyReleased, onMouseMoved, onMouseClicked, onMousePressed, onMouseReleased, onMouseEntered, onMouseExited, onMouseDragged, onMouseWheelMoved() * These new features adds a new dimension to the game, i.e. you could make robots that must be controlled entirely manual, semi-automized robots, or press various key for changing between various robot strategies, e.g. when debugging * Thus, it is now possible to create robots where multiple human players battle against each other, or compete against existing legacy robots = New sample robot = * A new sample robot named Interactive has been added to demonstrate how to control a robot using keyboard and mouse events only * This robot is controlled by the arrow keys and/or the mouse wheel, and let the gun point towards the current coordinate of the mouse pointer used for aiming. Mouse buttons are used for firing bullets with various fire power = Minor changes = * The background Robocode logo has been changed into green and the Robocode slogan "Build the best, destroy the rest" was added Version 1.3.3 (22-Jun-2007) --------------- = Bugfixes = * Wrong colors when undoing and redoing multiline comment in the Robot Editor * When a battle was stopped a new battle could start before the previous battle was closed down * When restarting a battle while it was paused caused strange behaviour with new battles, and the "Next Turn" button stopped working * In some situations the Rankings Panel did not show the results for all robots * This could be seen if first playing a battle with only 2 robots, and then start a new battle with more robots. In this case, only the rankings for the top 2 robots were shown = Changes = * The Rankings Panel and Results Dialog are now automatically packed to fit the table containing the rankings/results Version 1.3.2 (09-Jun-2007) --------------- = Bugfixes = * The sample.SittingDuck would not start when no GUI is enabled * The Look and Feel is not set if the GUI is disabled * The robocode.sh ignored command line arguments (e.g. under Linux and Mac) * When setting the -result parameter from the command line the results file was empty = Changes = * When specifying the -battle parameter the .battle extension and battle directory can be omitted. Hence you can write "-battle sample" instead of "-battle battles/sample.battle" * If a specified battle file does not exist Robocode will now exit with an error * If you specify the -results parameter the last results will now always be printed out, i.e. with and without the GUI enabled. Otherwise, if the GUI is not enabled (by setting the -nodisplay parameter) then the last results will be printed out to system out Version 1.3.1 (30-May-2007) --------------- = Bugfixes = * When loading a battle, the robots specified in the battle file were not selected on the battle dialog * When the intro battle has finished the battle settings are now reset to the default battle settings. This fixes the issue were the fixed robot starting positions are still used in new battles and where the "Number of Rounds" was set to 1 instead of 10 * The output in the robot console windows were written out in bulks instead of immediately * Bugs fixed in RoboRumble which could cause a java.lang.IllegalThreadStateException = Changes = * Robocode will now print out an error message and just proceed if problems arise with trying to set the Look and Feel (LAF) to the system LAF. * When stopping or restarting a battle, the battle will now stop immediately instead of continuing for a while showing robot explosions when the robots are being terminated due to the stop * Added confirm dialog when trying to reset the compiler preferences from the Compiler->Options->Reset Compiler in the Robocode Editor in order to prevent the compiler preferences to be reset by accident = New features = * Added link to Java 5.0 Documentation in the Help menu Version 1.3 (17-May-2007) Now featuring the RoboRumble@Home client --------------- = Bugfixes = * When using robocode.control.RobocodeEngine it was not possible to play team battles. Instead an ArrayOutOfBoundsException occurred * robocode.control.RobotResults.getRamDamage() incorrectly returned a double instead of an integer. This bug caused problems with running Robocode on RoboLeague * The "Enable replay recording" got set if it was not set after running Robocode without the robocode.properties file the first time * No sounds were played (when enabled) when Robocode was launched the second time * Fixed NullPointerException occurred when a robot is forced to stop * NullPointerException could occur when using robocode.control.RobocodeEngine and the GUI was not enabled * The text field for the filename in the robot packager was way too high * Lots of synchronizations issues and potential ConcurrentModificationExceptions have been fixed * In RoboRumble, the codesize of some robots were incorrectly calculated to be 0 bytes, and hence these robots was not able to participate in RoboRumble battles * This was due to the codesize tool, which could not analyze .jar files inside .jars * The Event Dispatch Thread was denied access by the RobocodeSecurityManager = Changes = == RoboRumble@Home is now built-in == * RoboRumble@Home client, originally developed by Albert Prez, is now built-in * RoboRumble@Home is the ultimate collaborative effort to have a live, up-to-date ranking of bots. It uses the power of available robocoder's computers to distribute the effort of running battles and building the rankings * For more information about RoboRumble@Home you should read: http://robowiki.net/cgi-bin/robowiki?RoboRumble * This is an updated version of the original one that can run with the current version of Robocode and which has been ported to Java 5 * Configuration files has been updated, and are available in the 'roborumble' folder * Issues with downloading robots from the Robocode Repository site has been fixed * Special thanks goes to Gert Heijenk (AKA GrubbmGait) who did a tremendous job with lots of alpha testing regarding the new RoboRumble@Home built into Robocode! :-D == Codesize == * The codesize tool by Christian D. Schnell has been added * The codesize tool has been added to support the built-in RoboRumble@Home, and a new feature for getting the codesize and robot codesize class (MiniBot, MegaBot etc.) when a robot is being packaged * The codesize tool has been taken over by Flemming N. Larsen (agreed with Christian) and updated to version 1.1, which can handle files > 2KB, and which can analyse .jar files inside .jar files == Start positions == * Added feature that allows specifying the initial start positions of the robots on the battlefield * By specifying positions by setting robocode.battle.initialPositions in a .battle using this format (x1,y1,heading1),(x2,y2,heading2),(?,?,?) you can specify the initial location and heading for each robot specified with robocode.battle.selectedRobots * One example is: (50,50,90),(100,100,?),? This means that the 1st robot starts at (50,50) with a heading of 90 degrees, the 2nd robot starts at (100,100,?) with a random heading, the 3rd (and last) robot starts at a random position with a random heading * See the battle/intro.battle for an example of how to use this option == Robot and Control API == * Added a new method called getNameAndVersion() to the robocode.control.RobotSpecification. This method was added to better support RoboRumble and ranking programs * Changed the TeamRobot.broadcastMessage() so it does not throw an IOException when the = robot is not in a team * Changed back the TeamRobot.getTeammates() to return null if no teammates are available. This rollback was done in order to keep compatibility with old legacy robots == Improved file structure == * The file structure of Robocode has been slightly improved * All .jar files including robocode.jar are now located in the libs folder * The robot.database and .robotcache files has been moved to the robots folder * All RoboRumble related files are located in the roborumble folder Version 1.2.6A (11-Mar-2007) --------------- = Bugfixes = * A NullPointerException occured if the battle view was not initialized * This bug made it impossible to control Robocode via the robocode.control package when attempting to show the battle window = Changes = * The Ranking Panel and Battle Results are now windows instead of dialoges * This means that the Ranking Panel and Battle Results will still be visible when the game is running in minimized mode Version 1.2.6 (06-Mar-2007) --------------- = Bugfixes = * With some robots, a java.lang.NoClassDefFoundError occured when Robocode tried to cleanup the static fields occupied by the robot when the battles are over * AdvancedRobot.setEventPriority() did not support MessageEvent * The rendering options was not set correctly when loading these between battle sessions * When using the RobocodeEngine.setVisible(true) the Robocode window was shown with the wrong size and without the native Look & Feel = Changes = == getMessageEvents() == * Added missing getMessageEvents() on the TeamRobot == Default event priorities == * The changes were made as some events "shared" the same default priority, making it hard to tell which event would occur before the other * BulletHitBulletEvent priority was changed from 50 to 55. Previously, both BulletHitEvents and BulletHitBulletEvents used priority = 50 * MessageEvent priority was changed from 80 to 75. Previously, both CustomEvents and MessageEvents used priority = 80 * The Ranking Panel has been enhanced == Ranking Panel == * Now the Ranking Panel contains the same columns as the Battle Results * Both the current scores and total scores are shown together where it makes sense * The column names of both the Ranking Panel and Battle Results have been improved == New Pause/Debug button == * A Pause/Debug button has been added to the Robot Console window * This is handy if you want to pause the game when only your robot's console window is open when the game is minimized == Battle window == * The Pause/Debug button on the Battle Window has been changed into a toggle button * The Next Turn button is now always visible, but not alvays enabled == Documentation == * The documentation of the Robocode API (Javadoc) has been improved a lot == Installer == * The Installer is now checking is the user is running Java 5.0 or newer * If the Java version is older than 5.0, then an error message will display telling the user to install at least JRE 5.0 or JDK 5.0, and the installation is terminated == robocode.sh == * robocode.sh has been updated * Armin Voetter has contributed with an improved version of robocode.sh so that the script resolves the path to Robocode by itself Version 1.2.5A (19-Feb-2007) --------------- = Bugfix: On some systems Robocode could not start up caused by a NullPointerException = in the internal sound manager/cache Version 1.2.5 (18-Feb-2007) --------------- = Bugfixes = * When two bullets collided, the one of the bullets was not destroyed, but continued * TeamRobot.getTeammates() returned null instead of an empty array when no teammated are available * Memory leak could occur on robots using large objects on static fields * Robocode now clean all static object fields that are not final after each battle, but not between rounds. That is, the static fields are now garbage collected * 3 ConcurrentModificationException issues were removed == Changes == = Sound effects == * The sound effects in Robocode can now be changed * This is done by specifying the file for each sound effect using the file.sfx.xxx keys in the robocode.properties file, e.g. the file.sfx.gunshot for setting the sound effect for gunshot * The supported sound formats can be found here: http://java.sun.com/j2se/1.5.0/docs/guide/sound/ == Music support == * Robocode now supports music * By specifying the file for each music file using the file.music.theme, file.music.background, and file.music.endOfBattle in the robocode.properties file for setting the startup theme music, background music during battles, and "end of battle" music when the battle is over * The supported music formats can be found here: http://java.sun.com/j2se/1.5.0/docs/guide/sound/ == Misc. == * The column names in the Battle Results window have been improved * Keys in the robocode.properties file (the configuration file) are now sorted * Previously the keys were put in random order each time the property file was saved Version 1.2.4 (25-Jan-2007) --------------- = Bugfixes = * ConcurrentModificationException sometimes occured when robots were imported, e.g. when Robocode was starting up * Added setting and getting the priority of BulletHitBulletEvent, which was missing completely in Robocode?! * Removed IndexOutOfBoundsException when replaying battles * Explosion debrise was shown in the lower left corner (0, 0) when starting battles and battle ground is set to visible * Robocode could hang when checking for a new version via Internet when no Internet connection was available. Now a 5 second timeout has been added to prevent Robocode from hanging = Changes = == Robots die faster == * Robocode stops painting the battlefield and playing sounds when a battle is ended after 35 turns. * However, the robots still have 120 turns until they are really killed like Robocode is used to, but the battle continues like if it was running in minimized mode (fast) == Options == * The common options for enabling replay recording has been changed to disabled per default. When running lots of battles in a row with replay recording enabled, Robocode runs out of memory, which causes problems when running tournaments. * Added "View Explosion Debris" option in the View Options * Explosion debris is diabled per default as this feature can slow down the game with 25% - 50% when viewing battles == Javadocs == * The robocode.util.Utils class providing angle normalizing methods * The whole robocode.control package used for controlling Robocode externally == Files == * Fixed incosistency with .jar files located in the robot folder * Robot packages (.jar files) is now only extracted from the root of the robots folder * In previous Robocode versions when starting up Robocode without a robot.database file and .robotcache directory, Robocode would extract Robot packages from the root of the robot folder, and also the sub folders. When running Robocode the first time without these files, Robots from the sub folders were shown (if available), but not the following times when Robocode was started up. * This fix was done by Robert D. Maupin (AKA Chase-san) Version 1.2.3B (14-Jan-2007) --------------- = Bugfixes = * Titus Chen made a fix for a NullPointerException that caused a replay to stop. This occured when "Pan" was enabled for the mixer in the Sound Options during a replay * When using robocode databases ("robot.database") created with version 1.2.3 and earlier version in version 1.2.3A, Robocode crashed in the startup with a ClassCastException Version 1.2.3A (12-Jan-2007) --------------- = Bugfix = * Removed a ConcurrentModificationException that occured when processing robot events = Changes = * Robert D. Maupin (AKA Chase-san) replaced all old type Java containers like Vector Hashtable, Enumeration with the newer and faster types like ArrayList, HashMap, and set * This improves the performance a bit, especially when running in "minimized" mode Version 1.2.3 (10-Jan-2007) --------------- = Bugfixes = * Removed NullPointerException when trying to restart the initial intro battle * Titus Chen made a fix for the "robot color flickering" bug, when the max. amount of robot colors (i.e. 256) has been exceeded * Minor bugfix in the Extract Results dialog, where an empty line was following each line of text = Changes = == Added replay feature == * A new "Replay" button has been added to the toolbar at the buttom of the battle screen. The replay feature makes it possible to replay a battle * In a comming version of Robocode, it will be possible to load and save replays * Added "Enable replay recording" option to the Common Options for enabling and disabling replay recording as replay recording eats memory. When the replay recording is disabled, the "Replay" button will not be available * Bugfix done by Titus Chen for the Beta version where robot scores were incorrect == Improved the security manager == * Robots are not allowed to access any internal Robocode packages anymore, except for the robocode.util package in order to let legacy robots access the robocode.util.Utils class, e.g. for calling normalRelativeAngle() etc. == New hotkey == * Hotkey added for exiting Robocode quickly. It is now possible to exit from Robocode by pressing Alt+F4 in the main window of Robocode. Note that the main window must be active Version 1.2.2 (14-Dec-2006) --------------- = Bugfixes = * Extra hit wall events were occuring. This has been corrected by Titus Chen * Teams were not always ranked correctly. This was corrected by Titus Chen * In addition, the ranking scores and final battle results have been made consistent. * The radar scan arc was not painted correctly if the radar was moving towards left * Minor bugfix: Sometimes ArrayIndexOutOfBoundsExceptions occured when adding and/or removing robots in the robots folder = Changes == * Added TPS slider to the toolbar on the battle window so the TPS can be changed quickly * Bullet sizes has been improved * Very small bullets will always be visible, even on large 5000x5000 battle fields * Removed the "Allow robots to change colors repeatedly" from the View Options * This option did not have any affect as the current rendering engine always allows robots to change colors repeatedly Version 1.2.1A (26-Nov-2006) --------------- = Bugfixes = * Hitting wall with an exact angle of 0, 90, 180 or 270 degrees caused a robot to disappear from the battlefield (could be seen with the sample robots Corner and Wall) * The check for wall collision did not work properly in some situations due to rounding problems with float vs double precision * These bugs were found and corrected by Titus Chen Version 1.2.1 (24-Nov-2006) --------------- = Bugfixes = * The turnGun(double) method returned before the gun rotation had returned * Teleportation when hitting wall and abs(sin(heading)) > 0.00001 or abs(cos(heading)) > 0.00001 * HitRobotEvent.isMyFault() returned false despite the fact that the robot was moving toward the robot it collided with. This was the case when distanceRemaining == 0 even though this could occur on purpose if the move was set to distanceRemaining * Bad bullet collision detection algorithm. This has been replaced with Paul Bourke's 2D line intersection algorithm Version 1.2 (05-Nov-2006) --------------- = Bugfixes = * Fixed a lot of bugs that was introduced with the 1.1.4 versions and version 1.1.5 * Fixed "Robot hangs" when running long battles, which was not really fixed in 1.1.5 * Some text fields in e.g. the "New Battle" were not tall enough to show their content on for e.g. Gnome/Linux. = Changes = == Security option = * The NOSECURITY option has been extended so it is now possible to access 3rd party jar files * If you want to access other jars in your robot you'll have to disable the security in Robocode by setting the NOSECURITY option to true, i.e. adding -DNOSECURITY=true in robocode.bat (under Windows) or robocode.sh (under Mac and Linux) * You'll also have to add the jar file to your CLASSPATH or put it into the /lib/ext folder of your Java Runtime Environment (JRE), if adding it to the CLASSPATH does not work == Results can be saved in CSV file == * Results can now be saved in the Comma Separated Value (CSV) File Format * A "Save" button has been added to the battle results dialog == Battle results / Ranking panel == * The rank and name of the robots in the battle results dialog and in ranking panel has been splitted up into two independent colums, i.e "Rank" and "Name" * This was necessary in order to save the rank and name independently in a file == Misc. == * The default browser under Windows is now used when browsing e.g. the Online Help * The browser.bat file has been removed as there is no need for it anymore Version 1.1.5 (22-Oct-2006) --------------- = Bugfixes = * Fixed BulletHitBulletEvents, where half of them refered to the wrong bullet * The the battle results were not always ranked correctly = Change = * The Ranking Panel total score is now updated on the fly Version 1.1.4B (19-Oct-2006) --------------- = Bugfixes = * The getName() on ScannedRobotEvent returned null * Fixed "Robot hangs" pausing the game * Fixed the robocode.sh (Unix) file which contained a ^M (Microsoft DOS/Windows character), which caused this file to be unusable for starting Robocode = Change = * Updated the Common Public License to the original version Version 1.1.4A (15-Oct-2006) --------------- = Bugfixes = * The sounds were cut off after first round * The Ranking Panel position and size was not saved in the window.properties file * ConcurrentModificationException fixed in the robot event queue * Periodic NullPointerException removed from battle view Version 1.1.4 (14-Oct-2006) --------------- = Bugfixes = * The BattleView was not updated on the primary monitor display on a dual monitor system * Sounds: When enabling sounds on-the-fly when it was originally disabled, Robocode crashed/halted due to a NullPointerException * Runtime exception (NullPointerException) when opening a battle the first time when a new version of Robocode the first time * Editor: When inserting text by copy'n'paste or search'n'replace into the Editor, extra tabs were sometimes added = Changes = == Ranking Panel == * Ranking Panel added to the Options menu * The contributor of this feature is Luis Crespo (email: lcrespom at gmail.com) * This panel shows the current robot rankings during battles == Single-step debugging == * The contributor of this feature is Luis Crespo (email: lcrespom at gmail.com) * The "Pause" button has been extended into "Pause/Debug", and a "Next Turn" button is available to perform one turn at a time, which is vital for single-step debugging * Rules class added containing helper methods and constants for Robocode rules == New options == * Common Options has been added * Currently contains "Show results when battle(s) ends", which enable/disable showing the results dialog when the battle(s) ends * A lot of internal optimizations of Robocode has been made to speed up the game * Robocode icons has been updated Version 1.1.3 (20-Sep-2006) The "Java 5 and Sound" release --------------- = Bugfixes = * Wrong 1st place scores for robots, which got 1 point for winning and also 1 point for the death of an enemy robot, and hence got 2 points instead of just 1 point for the 1st place = Changes = == Moved to Java 5.0 == * The minimum requirement for Robocode is now Java 5 (1.5.0) * You must have at least a JRE 5.0 (1.5.0) or JDK 5.0. * Robocode has also been tested with the upcomming Java 6 (1.6.0) where it seems to run just fine == Sounds added == * Sounds have been added to Robocode along with Sound Options * The contributor of the Sound engine is Luis Crespo (email: lcrespom at gmail.com) * You are able to change between available mixers (on your system) * Panning is supported, so that explosions in e.g. the left side of the screen is louder in the left speaker * Volume is supported, so that e.g. a bullet with more power makes more noise * Note: Some mixers performs better, but might not support volume and/or panning * A new command line option, -nosound, has been added in order to turn off sound support * This feature should prove useful on systems without sound support == Robocode versions == * Improved the notification about new available Robocode versions * Now Robocode will only give a notification about a new available version if the version number is greater than the version retrieved from the robocode.jar file * The check interval has been changed from 10 days into 5 days == New setColor() methods == * The setColors(bodyColor, gunColor, radarColor) has been reintroduced * The setColors(bodyColor, gunColor, radarColor, bulletColor, scanColor) has been added * The setAllColor(color) has been added == Misc. == * The Robocode logo on the splash screen and battle view is now rendered using Java2D * The layout of the Developer Options was improved a bit Version 1.1.2 (20-Aug-2006) The "Robocode is now TPS centric instead of FPS centric" release --------------- = Bugfixes = * The buildJikes.sh contained the ^M (DOS return-carrige characters), which do not belong in a Unix/Linux file ;-) * The radar color was sometimes painted with too much lumination (white) = Changes == == TPS centric instead of FPS centric == * Robocode is no longer FPS (Frames Per Second) centric, meaning that 1 turn (time unit) = 1 frame * Robocode is now TPS (Turns Per Second) centric, meaning that 1 turn is not necessarily equal to 1 frame anymore. You specify how many turns you want to compute every second (desired TPS), and Robocode will render as many frames as possible depending on the TPS. If the TPS is higher than the FPS, some turns are not rendered. However, this does not mean that turns are skipped * The higher TPS, the lower the FPS will get * The better graphics hardware acceleration the higher TPS and FPS * Replaced the -fps (Frames Per Second) command line option with the -tps (Turns Per Second) * Now there is an option to display both the TPS and FPS in the titlebar in the View Options == Rendering options == * Added Rendering Options to the Preferences * It now possible to change the settings for Antialiasing, Text Antialiasing, Rendering Method, and number of rendering buffers == Explosion rendering == * Explosions are no longer pre-scaled in 6 fixed sizes, but instead scaled real-time using Java2D * The explosion sizes are now more precise depending on bullet damage, and the memory usage for the explosions has been brought down by not using pre-scaled explosion images * This fixed the painting of explosions on the iMac, where explosions were painted as filled circles with version 1.1 and 1.1.1 * Bullets are now painted as filled energy balls with a size that depends on the bullet energy * The size (circle area) is calculated so that: * A bullet with power = 0.1 (minimum power) uses 1 pixel * A bullet with power = 3 (maximum power) uses 30 pixels * In addition, explosions when a bullet hits a robot or another bullet are also depending on the bullet energy == New option == * Added the option "Visible Explosions" in the View Options to the Preferences * This option makes it possible to enable and disable the painting of explosions == setColor methods == * The setColors() method is now deprecated * Replaced by setBodyColor(), setRadarColor(), and setScanColor() * Added setBulletColor() for changing the bullet color, and setScanColor() for changing the scan color (used for drawing scan arcs) == Improved sample robots == * All sample robots has been updated * Deprecated methods are replaced by current methods * Colors has been added to each robot, except for MyFirstRobot, which should be kept as simple as possible == Added Restart button == * Restart button has been added in order to restart a battle == New -nodisplay option == * No graphical components are loaded anymore when Robocode is run from the command line with the -nodisplay option * This feature has been added in order to run Robocode on Unix-like systems that don't have X installed on them == Added Browse button == * Added Browse button in the Development Options == Keyboard mnemonics == * Changed some keyboard mnemonics in the View Options in the Preferences Version 1.1.1 (06-Jul-2006) --------------- = Bugfixes = * The CPU speed detection has been changed to accept 50 times as many clock cycles than with with v1.0.7. Robots than ran fine under v1.0.6 were skipping turns like crazy under v1.0.7 * Robot text-output error has been fixed according to the solution provided by Matt (msj(at)sysmatrix(dot)net) * The window position and sizes were not loaded properly from the windows.properties file * The state of the "View option" was not loaded correctly, and hence always set to enabled everytime Robocode was restarted * updateMovement() that checked for "distanceRemaining > 1" instead of "distanceRemaining > 0" when slowing down * The radar was not colored correctly due to a bug in the coloring filter * The Robocode editor's window menu did not remove closed windows properly when muliple windows were opened in the editor * Various part of Robocode did not work properly if installed into a folder containing spaces, e.g. compiling and viewing the API documentation did not work * Installing and compiling under Mac 10.3.9 was fixed. = Changes == == 1200x1200 battle field == * Added 1200x1200 battle field size as one of the standard sizes, and set the size step to 100. * This feature was added to accommodate RoboRumble@Home == Battle window == * The battle window is no longer reset every time a new battle is started and the window size and position is saved into the windows.properties file == Robot colors == * The robot colors are now painted using a true HSL color model * The change to use the HSL color model fixed the bug regarding none or wrong coloring. * Also, the lumination of the robot colors has been changed == Robocode SG suppot == * Added a checkbox to enable Robocode SG painting in the robot console * The "Debug paint" button in the robot console has been renamed to "Paint" * The "Paint" button enables painting in general, and by trickering "Robocode SG", the robot (debug) painting will be rendered as Robocode SG does it == Command line / batch files == * Added the "-Xmx512M" option to the batch files extending the max. memory heap size to 512 MB * Added the "-Dsun.io.useCanonCaches=false" which fixes some SecurityException issues on robots that read from files, and also fixed the installing and compiling problem under Mac 10.3.9 Version 1.1 (14-Jun-2006) The "Continuation" release --------------- = Bugfixes = * HyperThreading issue fixed that caused hangs * Links in Help menu fixed, so you are able to browse the API etc. * Hotkeys have been added to every button, menu, and menu option * Help menu updated * Updated with links for "RoboWiki", "Yahoo Group: Robocode", and "Robocode Repository" * The Jikes compiler has been updated to version 1.22 = Changes = * Added feature for Debug Painting * By implementing the Robot.onPaint(Graphics2D g) method of your robot(s), graphics of your choice will be rendered when enabling "Debug Paint" on the console window for that robot * Editor improvements * New "Edit" menu containing "Undo", "Redo", "Cut", "Copy", "Paste", "Delete", "Find...", "Find next", "Replace", "Select All" * New "Window" menu containing "Close" and "Close All" options, entries for each open window (up to 9), "More Windows" option where you can get all open windows * Added undo/redo stack * Added linenumbers * New rendering engine based on Java2D * Graphics is drawn faster as Java2D make use of hardware acceleration * Robot colors are now painting using the HSB color model * Graphics is resized when the battle window is resized * Added "Visible ground" option in "View Options" which will paint background tiles and explosion debrises * The battlefield is always centered in the battle window ==== Robocode was release as Open Source on SourceForge ==== ==== Development was taken over by Flemming N. Larsen ==== Version 1.0.7 (18-Feb-2005) --------------- * Released as opensource under Common Public License * New explosion graphics * Fixed a few bugs ** No longer possible to teleport when hitting walls ** Docs fixed and regenerated ** Fire assistance removed from AdvancedRobot * Now requires Java 1.4 * New system for calculating CPU speed Version 1.0.6 (17-Jul-2002) --------------- * Robots that perform file I/O will be allowed 240 skipped turns in a row before being stopped ** Other robots will still be allowed 30 in a row * Fixed issue with Linux where window frames were outside screen * Fixed reset compiler option in editor (broken in 1.0.5) Version 1.0.5 (15-Jul-2002) --------------- * Updated dialogs for: Packager, Extractor, Team Creator, Compile Options, ** So they don't hide behind main window * Fixed bug where New Battle dialog would hang on some systems Version 1.0.4 (15-Jul-2002) --------------- * Raised max setXX calls before disable to 10,000 * Moved setXX and getXX warnings to only print when max is hit ** Previously at 300 and 3000, respectively * Fixed bug in clearAllEvents * Updated Jikes compiler to version 1.16 ** See http://oss.software.ibm.com/developerworks/opensource/jikes/ Version 1.0.3 (28-Jun-2002) --------------- * Added setFire(double) and setFireBullet(double) methods to AdvancedRobot * Added getDataQuotaAvailable() call to AdvancedRobot * Fixed bug: Robots taking action in Condition.test() * Implemented better method for stopping misbehaving robots ** Basically, to help fix mistakes such as: bad: while (getGunHeat() != 0) {} good: while (getGunHeat() != 0) {doNothing();} ** Robots will be disabled after 10,000 calls to getXX methods with no action ** Robots will be disabled after 1,000 calls to setXX methods with no action ** Only getXX and setXX in the robot itself counts (event.getXX does not) Version 1.0.2 (21-Jun-2002) --------------- * Increased default filesystem quota to 200000 bytes * Droid leaders now start with 220 energy. * Fixed bug that allowed robots to read other robots' data directories * Fixed bug that allowed invalid robot version strings * Fixed two bugs that allowed robots to exceed filesystem quota Version 1.0.1 (23-Apr-2002) --------------- * Team robots will always show in the robot selection dialog * Robots in .jar files without a .properties file will not show * The extension ".jar.zip" is now supported for cases where the browser renames .jar files. Version 1.0 (05-Apr-2002) --------------- * New online help integrated ** http://robocode.alphaworks.ibm.com/help/index.html * *includes instructions for using Eclipse to build a Robot * onWin() is now called the moment you are the last surviving robot ** You can now do victory dances in onWin. ** Tracker and TrackFire updated to reflect this * Context assist will now work inside Eclipse * Fixed bug: getTeammates() returning null for last teammate * Fixed a few other small bugs Version 0.99.4 (24-Mar-2002) --------------- * Fixed scanning bug (missing scan events with small scanarcs) * Added "Import downloaded robot" tool. * Renamed "Packager" to "Package robot for upload" * Added "Extract downloaded robot for editing" to Robot Editor * Added "Press F5 to refresh" label to robot selection dialog * Added small battle demo when new version detected Version 0.99.3 (21-Mar-2002) --------------- * Fixed velocity bug ** Movement is now more optimized ** No more '1 2 0 -1 0 1 2 0' velocities * Fixed maxVelocity bug ** setMaxVelocity can no longer be used to instantly stop * Fixed first turn bug (getTime returing 0 twice) * New, more accurate CPU benchmark. (Updated Linpack benchmark) ** Should fix '1ms per turn' bug on Win9X systems Version 0.99.2 (13-Mar-2002) --------------- * Added a development path to support external IDEs such as Eclipse (http://eclipse.org) ** Found in Options->Preferences ** Simply add the path to your robot project ** As usual, robots will be loaded from disk at the start of each battle * Improved support for RoboLeague * Documented robocode.control package (http://robocode.alphaworks.ibm.com/docs/control) * Fixed bug: sendMessage causing StringIndexOutOfBounds Version 0.99.1 (11-Mar-2002) --------------- * Fixed bug: Some messages were delayed * Fixed bug: Broken RoboLeague interoperability * Fixed bug: getSender() did not show version or duplicates * Fixed bug: RobotPackager not packaging teams correctly under Java2 1.3 Version 0.99 (05-Mar-2002) The "TEAMS" release --------------- * Introducing: Teams! ** See sampleteam.MyFirstTeam for an example ** Teams may consist of 2 to 10 robots ** To use teams, first create one or more TeamRobots, then create a Team. ** TeamRobots will not show up in the New Battle dialog by default. You can change this behavior in Options->Preferences. ** To create a team, select Robot->Team->Create Team. ** You can add regular robots to a team, but they will not be able to communicate. ** The *first* robot you add to a team becomes the "team leader". Team leaders start with 200 energy. (They are superheroes) When team leaders die, all other members of the team lose 30 energy. Protect your leader! ** Team scoring is cumulative, but similar to normal scoring: Teams receive 50 points for each surviving team member every time an enemy dies. Teams receive 10 * numEnemies points for each surviving teammate upon winning. Damage bonuses are for all damage dealt by that team Firsts, Seconds, Thirds are based on last surviving team member ** Teammates can damage each other ** Teams can be packaged like regular robots ** Teammates without a version will receive the team version [enclosed in square brackets] ** Team messages are limited to 32K per message. * Introducing: Droids ** Droids are robots without radar or scanning ability ** simply add "implements Droid" to a TeamRobot to create a droid. ** Droids start with 120 energy (due to weight savings on the radar) ** Droids do not show up in the New Battle dialog by default. You can change this behavior in Options->Preferences. ** The API is unchanged, but scanning will not work. ** See sampleteam.MyFirstDroid for an example * Added new class: TeamRobot ** See Javadocs for details. ** Adds messaging capability to robots * Added new class: MessageEvent * Added new interface: Droid * Fixed bug: Duplicate robots sometimes showed up in robot selection dialog * Fixed bug: Default Window Size not working for some battles Version 0.98.3: (08-Feb-2002) The "Everything but teams and it took too long" release --------------- * setColors() now accepts any color (previously it had to be a default color) ** Only works in the first round ** Only the first 16 robots in a battle will get their requested colors * Robots may now extend or use classes that are not in their package ** This allows for utility classes, when they are in the robots tree ** If you do not wish others to extend your robot, declare your robot class final ** If you do not with others to use classes from your package, do not declare them public ** All referenced classes will be packaged with the robot packager * Robots in the robotcache directory that do not have a .properties file will not show up in the robot selection dialog (done in order to support extended robots, above) * You may now delete files in your data directory * Robocode will now always run at full speed when minimized * New Battle Dialog "Finish" button renamed to "Start Battle" * New Battle Dialog "Start Battle" button requests focus when enabled. * Robocode FAQ linked from help menu * Robocode now supports RoboLeague by Christian Schnell ** http://user.cs.tu-berlin.de/~lulli/roboleague/ * Fixed bug: Default thread priority was low * Fixed bug: Robots had access to peer * Fixed bug: Survival seconds reported as Survival firsts * Fixed bug: Robots did not always receive all onRobotDeath events * Fixed bug: getTime returning last round's end time at start of rounds * Editor 'Open File' now defaults to the last opened directory (per session) * Fixed minor editor bug when parsing for classname * Fixed bug: Robocode will no longer try to save the size/position of a maximized window * Fixed bug: Bullets hitting each other immediately with fast gun cooling rate * Fixed bug: Incorrect number of rounds reported when stop pressed * Fixed bug: Incorrect number of "seconds" and "thirds" displayed Version 0.98.2 (28-Nov-2001) The "Screaming FPS" release --------------- * Sped up performance when minimized * New license includes academic use * Fixed bug: disappearing energy/name strings Version 0.98.1 (27-Nov-2001) The "Ok, NOW it's starting to feel real" release --------------- * Fixed bug clearing scaled battles * Robot consoles changed back to white on dark gray * Fixed bug with case sensitivity in editor's suggested filename * Other minor tweaks and bugfixes * Updated Tracker and RamFire (no setInterruptible) * Added commentary and dates to this file * Added link to this file from help menu Version 0.98 (27-Nov-2001) The "It's starting to feel real" release --------------- * Added setColors(Color robotColor, Color gunColor, Color radarColor) to Robot ** By default, robots are the default blue ** Call this in your run method (no more than once per round) to set your robot's colors ** Accepts any System default colors, i.e. Color.red * Robots are now instantiated each round. ** You no longer need to re-initialize all your variables at the beginning of run() ** ** Only static variables are persistent across rounds ** * Graphics optimizations ** no more rotating images at the start of each battle ** far more memory efficient * New model for CPU time. ** Robocode now uses the Linpack benchmark (http://www.netlib.org/benchmark/linpackjava/ ** Used to determine how much time each robot is allowed for processing * Threading changes ** Robocode is now threadsafe (as far as I know, anyway) ** Robot threads execute sequentially ** No more "busy wait" enhances performance, especially on large battles * Minimized optimizations ** When minimized, Robocode will not do any drawing ** FPS can really crank up (when set in options-preferences) * Minor graphic changes (The gun is slightly further forward) * New class hierarchy, in order to clean up the javadocs ** added _Robot and _AdvancedRobot ** These hold deprecated methods and system-related things ** added _AdvancedRadiansRobot to clean up the AdvancedRobot docs ** You should still extend either Robot or AdvancedRobot * Battles may now consist of 1-256 robots ** A warning confirmation will appear for > 24 robots ** A confirmation will appear for 1 robot * Robots will now appear as they are loaded * So large battles won't appear "hung" * Consoles persist between battles (although they are cleared) * Console threading is more efficient * Console scrolling is crisper (bug fixed) * Console now has an unlimited size, once opened. ** there is an 8K circular buffer before it is opened. * setInterruptible() moved to AdvancedRobot ** deprecated version in Robot does nothing ** Note: Balancing of the "Robot" class still needs work. * skipping turns may happen more often, but is not as big a deal as it used to be. ** with the exception of your first turn ** You will only lose events if you skip 2 in a row ** You will not be stopped unless you skip 60 turns in a row. ** skipped turns can be caused by loading classes from disk, writing files, etc. If this becomes a problem, I will preload all classes. * Fixed bug with compiler when filename has a space * Fixed bug with getting BulletMissed and BulletHit events for same bullet * Fixed bug with editor locking up reading some files * Another round of major code organization * Again, probably more minor items that I already forgot about :) * (Later additions... such as:) ** Invalid insert bug in editor ** Copy/Paste from console Version 0.97.4 (18-Nov-2001) The "finally, a single installer!" release --------------- * Completely reworked install process. * There is no longer a setup.exe installer. * Jikes is now packaged with Robocode as the default compiler ** you may use javac if you prefer, and you have it. * API docs now link to the Java API * Fixed bug: Editor did not close files after saving * Fixed bug: Unable to deselect "display robot names" * Fixed bug: Shared static vars between instances of the same robot * Fixed a few graphics glitches * Minor doc updates Version 0.97.3 (05-Nov-2001) The "hourly release" release :) --------------- * Fixed nullpointer exception when loading robots with no package * Added robocode.robot.filesystem.quota property to robocode.properties ** This is a temporary solution, which sets the default filesystem quota for robots ** example: robocode.robot.filesystem.quota=200000 for 200k. * Fixed bug in editor that caused it to suggest an unreasonable filename. Version 0.97.2 (04-Nov-2001) --------------- * Fixed bug that caused some robots to be stopped by the game * Battles/Rounds start faster (back to 0.96.2 speed) * More lenient on CPU use ** You have roughly 4 whole seconds before your first move ** You have roughly 50 + (1000 / fps) milliseconds to process each frame ** This is more than twice what the entire game itself gets. :) ** Failure to take action in that amount of time results in a SkippedTurnEvent ** You will be removed from the round if you skip 30 turns in a round ** Un-deprecated onSkippedTurn and SkippedTurnEvent ** No reasonable robot should ever receive a SkippedTurnEvent... but now it's there just in case. Version 0.97.1 (03-Nov-2001) --------------- * Abstract classes now work properly in the selection dialog and robot database * Fixed a few Javadoc bugs * Fixed pause/resume bug * Javadocs have deprecated calls again Version 0.97 (02-Nov-2001) The "painful but worth it" release --------------- * I probably missed a few things in this list. :) * Introducing the Robot Packager ** Select your robot, type in a few details, and let it figure out the rest ** Saves details in a .properties file (see details below) ** Builds a .jar for you ** Save this .jar in your robots directory (not a subdirectory, for now) ** You may distribute this jar as a standalone robot. * .properties files ** Not required unless you are packaging your robot ** Built automatically by the packager ** Includes: *** Robot version *** Short description *** Optional author name *** Optional webpage *** Robocode version *** Flag for source included * .jar files, and the robotcache ** Simply put a robot .jar file in your robots directory ** It will be extracted to the "robotcache" ** Jar filename is the unique key for the robotcache ** Do not edit files in the robotcache, they may be overwritten. Copy them to your robots directory if you like. This will be a feature in a future version of Robocode. * Robot Database ** Built and maintained for you ** Allows Robocode to remember which .class files are robots, and which not ** Press F5 in the robot selection dialog to refresh the database. * Robot Selection dialog ** Divided up into packages ** Shows robot details (from .properties) if they exist. * .html files ** Create a .html file if you like... see sample.SittingDuck ** Linked from robot selection dialog * Major scoring changes ** 50 points every time an enemy dies while you are alive ** (10 * numOthers) points if you are the sole survivor ** 1 point for each point of damage you do with bullets ** 2 points for each point of damage you do by ramming (see Ramming changes, below) ** bonus .2 * damage done to a specific enemy, if you kill that robot, or ** bonus .3 * damage done to a specific enemy, if you kill by ramming * Ramming changes ** Damage increased (from .4 to .6) ** Only generates score if you are moving toward the enemy ** If you are ramming, and run out of energy, you will now be disabled instead of killed * "Life" replaced with "Energy" ** A more sensible name ** All getLife() calls deprecated and replaced with getEnergy() * Added getEnergy() to HitRobotEvent (I can't believe it wasn't there before!) * Only Robots and AdvancedRobots will show in the New Battle dialog. ** fixes known bug listed below at the end of 0.96 changes. * Custom events are now be cleared at the start of each round ** However, since many robots rely on them still existing, Robocode will currently re-add any custom events that were created at the beginning of the first round, for all remaining rounds. This is a temporary solution for backwards compatibility, and will cause a warning message in your console. * You may now print to System.out ** Will automatically redirect output to your console * Robot Editor now supports creating normal Java files * Added line number display to Robot Editor * MoveCompleteCondition bug fixed. * getTurnRemaining(), getGunTurnRemaining(), getRadarTurnRemaining() now return degrees * getTurnRemainingRadians(), getGunTurnRemainingRadians(), getRadarTurnRemainingRadians() added. * Added setAdjustRadarForRobotTurn(boolean) ** by default, set to the value of setAdjustRadarForGunTurn for backwards compatibility * Windows now remember their last position ** This is based on the preferred size of the window, so that different battlefield sizes may have different window position and sizes. ** This is stored in the file "window.properties" which you can safely delete to reset. * Added "Default Window Size" to Options menu ** Resizes the window to optimal (even better than before) * Command-line parameters to run a battle ** robocode -battle battles\sample.battle -results out.txt -fps 250 -minimize ** Results will go to System.out if you do not specify a results file ** All other Robocode output goes to System.err * "Activity" is now defined as loss of 10 energy in the battle ** Inactivity Time is now the number of frames in which 10 energy must be lost ** This does not include loss due to inactivity itself, or hitting walls ** Prevents robots stopping the inactivity timer by calling fire(.1) every 15 seconds. * Compiler uses -g option for debugging. ** This *may* help those users trying to use advanced debuggers. * Much improved "waiting for robots to start" * More lenient on "robot has not performed any actions" * Various javadoc fixes * Minor updates to template files Version 0.96.2 (09-Oct-2001) --------------- * Fixed bug in movement that allowed robots to exceed maxVelocity Version 0.96.1 --------------- * Added automatic version checking * Added getVelocity() to Robot * Fixed minor bug in editor (caused the "do" in "doNothing" to highlight) * WinException and DeathException now extend Error instead of RuntimeException. ** So you won't catch them by mistake with catch (Exception e) ** You still don't want to catch them, or you'll get no score.\ * fixed minor api doc bugs * Added a warning when you are calling the setXXX methods too many times (300) ** has no effect on whether the game stops you or not, it simply helps to explain why. before taking an action * Replaced BrowserControl with BrowserLauncher, from http://www.stanford.edu/~ejalbert/software/BrowserLauncher ** Should work on more systems * Synchronized tick() ** Two threads cannot take action at the same time. ** This entire area needs work * FPS no longer displayed when Swing doublebuffering is on * Added getHeadingRadians() to Bullet. * Fixed getHeading() in Bullet to return degrees. Version 0.96 (05-Oct-2001) The "Robocode is now my life" release --------------- * Renamed "Battles" to "Rounds" -- a single battle consists of multiple rounds. * Commented and updated all sample robots * All sample robots are now in package "sample" * If the old samples exist, Robocode will ask you if it may delete them, when you first run it. * Only Target, Crazy, Spinbot are still AdvancedRobots ** Target must be for the custom event ** Crazy and Spinbot call setTurn methods. * SittingDuck is now an AdvancedRobot ** SittingDuck writes to the filesystem. * Help system now uses system browser. Hopefully. Let me know of any issues. * API Help menu item copied to RobocodeEditor, and uses the local copy. * Robots may now use,extend,or inherit external classes, as long as they are in the same root package. ** You must be in a package to use this feature * Added call: getDataDirectory() to AdvancedRobot -- returns java.io.File representing your data directory. * Added call: getDataFile(String filename) to AdvancedRobot -- returns java.io.File representing a file in your data directory. * AdvancedRobots may now read files that are in the same directory (or subdirectory) as their root package. ** It is recommended that you only read from your data directory ** You may not read another robot's data directory ** If you extend another robot, and it calls getDataDirectory, it will get YOUR data directory. ** If you extend another robot, and manually try to read it's data directory, it will fail. * Added classes: RobocodeFileOutputStream and RobocodeFileWriter * AdvancedRobots may now write files to their data directory ** You must use RobocodeFileOutputStream or RobocodeFileWriter ** Any other output stream will fail ** You may wrapper them with other outputstreams ** Example: PrintStream out1 = new PrintStream(new RobocodeFileOutputStream(getDataFile("my.dat"))); ** There is a quota of 100K. * Fixed scoring bug (as exhibited by rk.Rotator) * Fixed threads stuck in wait condition when new battle selected * Fixed threads stuck in onWin or onDeath events * Fixed threads not taking action * Fixed leftover threads * Fixed a half dozen other thread issues * Limited # of worker threads a robot may have to 5 * Limited print/println calls to out, to 100 per turn. * Robots now run in their own ThreadGroup. (You can no longer can see other robot's threads) * Robots now have their own Classloader. (static variable "messages" will no longer work) * Fixed null pointer exception in RobocodeOutputStream * WinEvents or DeathEvents will now be the only thing in the event queue. * Reworked event handler system, should be more robust * Tweaked event priorities. New default priorities are ** ScannedRobotEvent: 10 ** HitRobotEvent: 20 ** HitWallEvent: 30 ** HitByBulletEvent: 40 ** BulletHitEvent: 50 ** BulletHitBulletEvent: 50 ** BulletMissedEvent: 60 ** RobotDeathEvent: 70 ** CustomEvent: 80 ** WinEvent: 100 (cannot be modified) ** DeathEvent: 100 (cannot be modified) * Valid priorities are 0 to 99 (100 is reserved) * Added new method "setInterruptible(boolean)" to Robot ** Can only be used while handling an event ** Always resets to false when the event ends ** Causes event handler to restart from the top, if the same event (or another event of the same priority) is generated while in the event handler following this call. ** This will only happen if you take an action inside an event handler, that causes the same event handler to be called. ** This makes it possible for Robots to turn and move like AdvancedRobots... ** This has no effect on events of higher priority * Calling scan() inside of onScannedRobot() can now restart onScannedRobot ** internally calls setInterruptible(true) for itself. ** See sample.Corners for example. * Robots of class Robot no longer take damage from hitting a wall * Robots of class AdvancedRobot take more damage from hitting a wall * Added isMyFault() to HitRobotEvent ** returns true if you caused the event by moving toward the other robot * Revamped robot to robot collisions ** Your movement will be marked complete if you are moving toward the other robot ** You will not be stopped if you are moving away from the other robot ** Collisions now cause more damage, but are easier to escape from ** This means robots without onHitRobot handlers still have a chance... ** An event is generated every time one robot hits another ** If you are moving toward the other robot, you will get onHitRobotEvent with isMyFault() = true ** If another robot is moving toward you, you will get an onHitRobotEvent with isMyFault() = false ** If you are moving toward each other, you will get two events, with the isMyFault() = true, first. * Damage from robot to robot collisions is now a constant 0.4 * Added getBearing() to onHitByBullet * Added a Bullet object ** encapsulates owner, victim, power, velocity, X, and Y. * Bullet hitting bullet generates BulletHitBulletEvent - methods include getBullet() and getHitBullet() ** added getBullet() to HitByBulletEvent, BulletHitEvent, BulletMissedEvent * Added fireBullet(), which is exactly like fire(), but returns a Bullet object ** I could not simply add a bullet return to fire, because it broke *all* existing robot .class files. * You can now select from the results dialog * Fixed path for open/save battles on non-Windows systems * Fixed slashscreen for some systems * Fixed minor api doc bugs * Updated many api docs * Renamed and reorganized many internal classes * Fixed bug with allowed package names (now allows digits) * Windows installer now defaults to c:\ * added getGunHeat() to Robot ** when gunHeat is 0, you can fire. ** gunHeat goes up by (1 + firePower / 5) when you fire. ** this is unchanged from the v0.95 * added getGunCoolingRate() to Robot * deprecated getGunCharge() ** use getGunHeat() * deprecated endTurn() ** It will still work for now, but you should replace calls to to it with execute(). * Removed onSkippedTurn ** your robot will simply be stopped instead. ** The results dialog will report "not deterministic" ** Not deterministic means that a battle started with the exact same conditions and starting positions, may not end up with the same results. (Ok, so far, you can't test that...) :) ** Added getWaitCount() and getMaxWaitCount() to AdvancedRobot. * deprecated SkippedTurnEvent ** well, it's no longer used. * deprecated all getRobotXXX methods ** replaced with getXXX methods. * deprecated all getXXXDegrees and setXXXDegrees methods ** just use the getXXX and setXXX methods * Compiler will always show output, and uses the -deprecation flag ** so you can see that you're using a deprecated call ** I would like to remove all deprecated calls in the next version * Known bug: New battle dialog not smart enough to differentiate between Robots classes and other classes ** You will be able to put other classes into a battle ** They will sit there and do nothing Version 0.95 (09-Sep-2001) "The /. release" --------------- * Completely rewrote all windows and dialogs to use LayoutManagers * Linux support vastly improved (although fps still not great) * Improved framerate calculation (should be smoother on most systems) * Robot exceptions now all go to robot's console * Fixed bug in initialization - radar turn * Hitting a wall no longer resets inactivity counter * Better pause functionality (fixed bugs) * Known bug: Help system still not using external browser * Smarter dialog locations Version 0.94 (09-Aug-2001) --------------- * Fixed a few bugs so Linux version would run * Known bug: Linux version does not run well Version 0.93 (23-Apr-2001) --------------- * Completely redone graphics for tanks, guns, radar * Firepower adjusted. Higher-power bullets now move slightly slower and fire slightly slower. * Gun must 'charge up' before firing. This avoids the "lucky shot" syndrome at the beginning of a battle. * Added execute() method for AdvancedRobots. Better name for 'endTurn'. * Optimized drawing of explosion graphics * Added buttons for selecting battle size * Bullets can now hit each other (not perfect yet) * Updated security manager to work with jdk1.4 * Revised bounding box for new graphics. The graphics should no longer have a 5-pixel blank area * Optimized scanning code * Added 'color mask' to determine which parts of image should be recolored * Replaced splashscreen and icons * Java-based help, api, check new version. * Robot menu (disabled) * Changed fireDelay mechanism to be gunCharge. Still in progress. * Renamed to Robocode * Added Buttons for framerate * Added Buttons for battle size Version 0.92 (Mar-2001) --------------- * Added getTime() method to Robots * Added getFireDelay() method to Robots * Added explosions Version 0.91 (Mar-2001) --------------- * Fixed bug in waitFor() so that automatic scanning will not repeatedly generate events when the condition is true. * Fixed bugs in Tracker sample robot * Fixed display issues with view scan arc option Version 0.9 (Mar-2001) --------------- * Completely reworked scan() to use a sweep as the radar moves. If the radar is not moving, the scan will be a straight line. * Added fire assistance to regular Robot classes (not AdvancedRobots). If you fire at a robot you see during scan(), and gun/radar are together, and you fire() before doing anything else, you will fire at its center. Version 0.8 (Feb-2001) --------------- * Initial release ** Robocode brought to IBM Version 0.1 (Sep-2000) --------------- * Development started ** as late-night projectrobocode/robocode/resources/sounds/0000755000175000017500000000000011061320762016763 5ustar lambylambyrobocode/robocode/resources/sounds/shellhit.wav0000644000175000017500000013264010477405066021337 0ustar lambylambyRIFFWAVEfmt >}data(      ,LeTM{xp; DC=.Rt^xJgf~YhbD4r ?#W1#@Y=Kdyd =ri1]%G E:t,C<`ax!*2DniC=&q,3{AQTjn#j(O&+% >;* !}$-Ic?Zqn!nd's.%9.X7 59)4_9'9SN%>>H#-> )p7LH1 sS !;!1'B Eo(rNA%=/'GC:C9 ]B;7"=Y )3Y^FAB sJ+' % {bA1{UKI 3K"[I/!RV* 0eVnag9nHDJb=u$Vf@*ogeRe+,1Bu@aFDBCO[BF )6-%qNR/g8<;ByO`x  Cu R9!Hun*q 1 Ehk 5E.pbl}:& - _; 0 n = J  w L f L% E/mw - X 6K*1!{`qyJO+!&VZ4bzI={ yuL1[Q+ 3H-Z y /H*9t?\l*Xa45 XE b B*,d! <!U%$RAD!"$" T/ 3 K,yps*NK = /    dT 5&=7aSWZXN{#bl!I)XPQh [ biy P-&2,+ @xrEz_Q|uCGikrI ny\mz'n> \ ) ` , '/DWw d   jR y0,]  n5} K(+R6 L:_ 9 kU&Z k9K7 !VB @  A f s4  N  U i $ + % 9 + d PT U _ @@f @*f  X : Y j_p [-4 ;:( D iaAh[ K 8   VX;J+ 8P@}5 / Ehy@((u CWN4v*M">-H ?J!H ?{A)W06 n w:0IC&5w;b~jc51Z^Lp ATKZ3o$a<Y>9Lb9jrmzKK___J:.yJ~!8xU ޑ! 8fDq):ޔَn f _UlEnCdV4; V =:M:u O ,; m\ }& ar1  ;&1*-*]/)z'-2&_y&n Y;JT 4 J 6$  hEs~cLm=o r [!"  t <%bb'xL I_1?&Ui3]mZSnL& i  } 5"#k~'(!Y%,*+**+-00+&:&"MzL#   B HYl}dvDեӮR ,5RO7ݐQl=\ I  8u|n\tFnQwP E &T .( Sj m o,&p3 i + x  $Uj\'DcSg"I? KU:m)b$0nD,& l/mz5 e1 \FbmczD QkeӖh=0xr,0\,fSKM A'"'\k@fH 6 6 h "K/C^J];h "\f!_!U#[!T"%""".###$&)O0C3*X"C ,870+u)''U%$%'(#,D o ) {[/% n  !  o $ K Z 4  ~O"  V w ?$D IE1>`)vb zP( b |[XI/C<"HkZ 3/Kp +9*:N{qr޽u= _}޻{8{ܡMוh.NAٿ۲߸zH?"=.Hq,Y tG",q  I B!tG!^I"!QXdz'8- "%5 -X$@)388Y75836_1F&^#)E.T2S2 .' ~H<#L&5& $5k[ _F N kQ .Fk/+jYGT5v5qV?k{\PM#'/dOw6O?6V/ W%mސ1AOߩdy}ߙ Zn-GH|S\K[ua EX_N  ^`E : v 8 +|&H ;f\ B]"$6$ #"%')r+*%'L$5B'039/58Z62-o"V$X)*C)#%#Z!+"!/Ho-  M LK'5>zݬ$/7 Ig*L. LL}CzߟJK?=[A}-Zenۢ~Ԕ/P!ZRa^0Qs Pc2l H7p{   #"< FL  F e }  ]  pi ` `4 q]"rB;;q_3awLWL6G}r{S'Q' ` 4 A x _ Z2  A%Z "}O3a K> M g aqp -~v/  aV ->] ;1LoU!qi  I " O N{ml c3 I f  v ZE|` E J C 9M rp"E mv^Bdw!4 H G_ t571* `VV%Kv*.e+&hXFjc[+ !|zH`PBq;@P : =4kv H!Mx3`!xHjsF% }ިޔߒܐ9^)^7l c . a o T   c,5veU@m!gd-;J9-57Z@7)52 \,h 6 } { o m   +R5V. (5+7buD,#d'NQJ H! BH9 6&ZG/>/x >S]{@=aUzwOR<  . $Sj EP' ) G<  \'# `,[8 'X&#!pD"%#m"!#& !&&%L#<o`"J6Um"&xN !n   ;! y  L AY YvMmz5!ynEM0z']hF7 N  #_ ]8r E==  / +[F6tOQm flRH[D7[%3S -`sL@~+s/>iBXxVx8Hg?U >%=2&-8lTU m{*OHZ,zlp>^l[ 7P{V  0GL D ; 0evY&j8VrMyuE* J F p =e,H R ] O>^w l pVpe.y 'm _  $ }  W " d y { p $  i P< Wu#s\>K& u kdk@*1S}} 3mnu s Q 3 "{ J 4 ( p`RB2buM p >1 0;80n^S9`LN 3Y>o7+s~r8Q"rf Vn?CVF?".1P-/}RAM7Ds@hU$WM wR V7L(P%Ac- -AFy0wFst x ooQ[^{h A3Q\b A b 9='?*uw;  9 %@G%("nHid*`GAi*"$STz  #)b+'! f(Hlq&tk 5.  ` h qs[~ $p>|8 FzkXU C7H $"Fk\5 R\U)uDxA5 [ U "SWX,U\N3$;7}<2W 2wvs"M&n8}i*a)n 0'+6Z3k8 i7ou}njov*m c`9d!vpgEb !dKeRD7R)7:d>t X =0 W$#9#_/*6 ~ ~Jl:x1jxxWUBk I $?K  @M]"\ "   P@M_H. F~7jZJ giQ$y6K~< bsb,L(1:"Q:J7zNib>F U!rz#`YQK4oN*PV: gIU>-0e6K? ! $(G~}U%`-5BN=Z s  f *f%[? /e M6'> T T tl L,#&5)B*P) (6&$!}~N$Yv  Bmmb-4QW2uXNtl } u 5Y#gj} E  L~0c2QG@)fU(cھշ;ݯ%6'.˰vSֿJ,[l-tp^"k v) =-$ o!*EK / D^ ? 4s&T ""#$! C e!!!Z@P4? D g} [hs`s _ %NjPKms  ^J ' m Ty Y =QT2ts*|@\Il\) (m  } ;CVn <<3 j2Ag 9[]4 :=Ow%66V}-[9\a9m$N'[U p `` t"H k&r H m z Ut"''" /!!%*r+%L # #o $!t$I%%"D*|}1z CG ~fNP~:h i,z:Q@mk3d  kb -> j W  E%1>alX FO5*7/ji^ i(&/J  UN H x | [5%%V nVD M6  TFDH X Ib[z q r9M~? f Ft t d ; .~y " NR r y; s']uWqf 8FbG @ \ G  M ,)1t&)f>*~2W 0xs(5QsC7~fvJsMmq :R]Fw%c FW3-ZmS ySK ? &  Y  r v]e&HIf B I `- B 5x FS  R<Cy!p 4 (5y*   #d td#  fna m U z8 =  \b/s,g7"u^N_h SSI?at0m\fݓߠ43< 9A QNDZiQC!i: NC&a;GSe/H*ri=3/GMIn 4 EV  X<1m3=OJ [ r  6 r .  - 4   Y 7 . O# wFdR5TT0/Oo!O"+!x #"$#"@&=xu1+ 2  Y ] > x Q  -3)Ot[ $,hmC!|n * =   x m2eC>(2F `f&Dz;phL>]f+&[Gwgqjtu*]M6/?ݯ,&ٯڀy&~ޤ=9޳i߬m ذ%ڎU  N`: vnNwrY 2 3:A~ y>9`?] m!`! U#$!c s!!U 5 qqhYq/ `5 . jMLX{}#3Gb%PK haN[~y#Hw!3| y - '8vYY"55Yo[6WS>+(Jo\@z GKK X \] 'd I q x F ` C h^Jfnm*DS Nm8)fm i wAw9 y.<=l 3 s  % $ gMWSP?(cvBKR'DL6 Mk pdgS#<E '$ {yZLp,;dN#maBXo ^ ).T@ |*I[([t:oo`,dy^,_j?ENu-; (U\N p H gYtTO=Y]]0W"mDg> <ZBko|a935pSf+U9V4"F#Z-^5a: 5  .  k nEU3mLUvjI QWyOB78~_kik |H0Es[\nFa4?(l  V/Tz7EwSr;- IO*nWS1X ][t% F dr_%8uy"B#!!::| !#$&9(P*b,,+)%5!gB'$U 7*m>7'zdp2iMrdCB7PW'OAr^/}'63E>Rm0_ m7#w|3mYtl|u?/Z ,{DOl=g]. wTc J?s>5+08v 8 @.p,vOsqA[({M iX :Km*$x} 1  ] # "#'cRyp? Y  c y 3 mInGUgjt6ID g Uk Y"3#PO~!/# q Uy it~:P7O-,x*V) Xw'r/<6!jTO2iZ,>SecC7}`BmSW madRH  XI K ^ [  i  !   OhNnAKJ9d&'"F 7 '   ,8+1Nk,O^h )HR6$I45{$77w3 fU-Dj{-Aoe}j!iRC; L4 ? &<{x$RxoKf0g U l w*?4@H~uJR+U BaJ ]H'n3:7 +vD.kq~xN m#o8O<\ O %  % X bRqgY}Il4FVw~WB %޶\WuyZU [;z"KZ|KOeb.J p>X&h1{b +< b&n};oe:PjO~M n[X8 h    K r Am < B | =`w4ds  V O S2b cn Q H N +,eJxW_{ VSzPY #|_yY > 7 R97K#` 8 R9U- i bR?~cv;=>7~w(   y S W dc+P+=_<-i;?> kNfBx_tSrDPK5;:_5`Z*}fR83SEtk?&s_yC[>r=ZI +aJb ua8o+` :SWm]@( 4 i  < *  A " tam x5h>1rV6<]12oUURi?yA/C,.o!#W-PWJPVEb;'?Q+   yp 5V +l % 1 ; ]TX2 m ;W!!ytBXbuxFUjz#m%}NLr*myV]6-M0&C#zsiP@e6:GaL\K??.xcq2\(,n4/ `8Ym|J`/a - + V  p  i7 a o , QW` GRz-g wdtt[/ ( B ?&YRvHJhkn6^ g:rSp4;& L XP_4 m D4dm } JhYPM=u(Ew0xY% n~SR\M,5J?(Rs'\~-xS.de?TJ z\7y9w:t)f"_TX c q "  iB us W E : a  _ _#  #%.|\6 Du(AeeaC/yS<?s:LD3_(*Y16Pjp,)-4?6\ A2BRqCW)K8:tx XPj% W)' Y ` aNk}#5vJd90TMm]?nds>: R=iak r a4X}DZaF)NqpkvkCb?[`X@..tq y2$;{I:S z 1`%^IgpYS{1P.JGxA 3 I+7&zv qrHP\3j\e=-* S $ y  = V (  ?-w x of$/(\ @3NB o,Gu()K\: ~9o5LS[kx9$%Ls7(dgX}u`'KB`@<2Zm@rI7`x"srn-p-Mv:6D ;<U T5g$,:C"S;d~ c 8p c[)}moB]?3l=S-X[0<x3ksQ-   ) YP yWMWyl\6I~Q|:__x" Gajh; o,FQB.8<i7{"!{^* p  m  kBen }Lgy}D^[YxN|5R5(vJ},9rS??YQrCU>G LV'zgpx^#CLCE3~Kj6jJQ F"w*/Y+hMg{;D\Q+ _ aRLt& ZZihdB2{f+iriR`se}eAl:T,2*|MdQ<=KD-xa/@^6Mi!=huq&(1"{;Lsw7?~!'q.:5R@b+p dJ|x?B-u;/FYq%c"I|swW@w5"^cY $ x) V[7CB &6#ab/=sQ(Xnir;r~Vu\f' k # 0 7U$@(heNqPs`uEHu!`&f?zm !my"b&?r40CTs&n^Io ha <34^Da)T*& ]\!H*&8FB3EA1<^V]a P3n}E|F@ 22cz:&$0/*{9^:CY;[.OWLYftAB3'!No-Vf RR>W56^ApV U?' gS]} d J  t 0j[q\'sHN2Y$Jv3b-]n9l*&Oq*8oB)ljZr'~#=$Y=kL+vJuuWopvZ`Az4g FM=j[,sTOfHa y 3 cYfjfd}=P o 9IOoNR,5~2f";ixH5mlvS^,oDM.|94||wA(yI3hL(R#mn' IjP09IAE[ nG%cG@ie3&U> uHNR6#MSR7eR `Mooq6 f B  6  ySgu7(IwQ=uPa(UOF=+OR_u'e{ ouPq"h_T(`h{G(:'C) 3XQ3I<?e0 `:/J<$pd/KMy*4^P~Ex9?gO mLp>QjG')y]dR}zBr1w"bG[b i%+0yp Cx],1kJFZAc}^8Fwa}dQt@k*OPPP*U3y-BKxz*=lSVx,w4]j=GOl>Q>Llj%T[ i s  n I    eeTq[$sK2d#'uK32EUhZ8sD| =Pl=U$Fkx;:i'ey9r{[DNodoq,FC L7y51Cx?`> |ne'=vN.d7$rL{g,~Q)oH_>u?,Y ,UK),G\2FjrI@-|lY:,6Os|GK3Q%Hixb63r/M8Y"85;U6'0GwU[n `$+1  }P1 ]i~KxWP#J-2AJ,Ly!k >g9C8552#$R u"{ *WZ9=C+biYk3^5pG]L#&)0-W3yv gc~G9Rk *&n!f kJ)GP~qxCmn\Jb vK_~s\?H}{ Jq3^>g{B.2q6R3k0DIqBz2, 7WZ0m{I'p"-MnR}fBc]X,v{$824461;uJ2H.y!k=SqRp5hN mK]xf)W'l~X5y8~/YM0e/:Q|C !-)? o9A/S&CferjDO/# *?mSwv`O>J$t 8&>ENi9I803R}9I<F`_HuDMYGji7Wo|Q *uSdEZ7YGV3F`yB?nlgI%jQWSq5SK&.%2c5FK`};r%#i2)?Wr00 U 7r1L8pv Y;9+%EXL*@ f@ud siAhI :^aH 5r@Z#/BVhpu0iV c+9 K" :fl" >Q+6x~bVhyn={}|xt['_Stu"0  R25/8V;a>OqP_ c^)6gdO[4s$xzq? :tu6I5,}peCL XkjW>1j+"N89hRR5A|Y6/:LcU./{| WgPr?Enh,RLt"DdNEN\ mY$]&by|}^7&1HNF@d%ZC :E o4*ClxW,bq&QB$ANZR<&{`j"|D@;n4[wfEe:QH((teB;V9 eEbRsen!LW3 nV\uV@ZFhG*#7\zX8 /s? Xzw]?%#MyJjwiH* 9a<5unlgyQ#jr2& }8G1]q$yY7s:o8 .r `M[k Q&Ds^M ma@QqNl(H{lBL3a, @KHS|o"<5ng9;Yyv\/ "(^l 3_%#PooTP]{o?5 :6!<+PxG \ <I3)s=' 6jUVsqU#fo2_qC &GvTonY@C 8E5l;zz Q}~w`7>#@Sah|&r9 H4hiWm.`qm^H:8=;(`F7/18A?<6.(# *Jj~g:CmQSx^8?( 1<5+7RenhgRGftH 2[X:59<BMW^]VF- ]>UWXXZ`_A"$k7itnr0q8?3 :gvP!qiH5J"GY*0_h;k D{4Nqzqefr-o `<!WT%mY_v:UFL% "iLF 0cFp~sfUF0g7)N`HmX@"!*3>IQXepvz}` .Y}uo.Y\: >91]A5vp5+U|i?08<) 2z.Wu|ymQZ01V!B}m_4 ~uk_P>& B`riCdSE6$e[qBz  6Rq}jM-O {o_?$':H_vK #>K6}neUA( Y?Q; iS[tB^]C'$28- s_h"23"Go;{vqUEVpzm&<o9zZ+rL* K{4nC09?CFDCL_uWg$(TtYF4,D*LG$wpbN7.>[~ {pqtwtk^Z^fny~qdXMC4 %:M`u &>F8wbgzt[KGSjmC"?PZQ<q9 /BMPC5.1BTbo}xk^YTB)":Wis~ yyfSHFKRUF)"?S`fkry|~|vtxn[OOUUL=0-=VrxaNFIYp`>)'3JawrO>EWp{niiuhA$!3I]lpk[NIIWjqgdced`ZQJJSXZVH5 7Wmvxy~xrmfa][ae^J4 0EV\ZTQQOC/c>"  5Lh ,Lh|lL#{m^SOWi6FH>.  %+.35:92'  ! .CYlvoh^QFCFE;,{w !'++,--.+(  $')%  &(& +389988:<?EMV^ba\VOJINV_fjorqlf`[VVX\^[RE81,$         *048AJPTUSQNJE=3)#"&*++(%  &,17:=>>:4,$  $'(%   $%# %(%  #!!'08?BB@<70,(# #"  "##   #')&#     !!   !$%%"        LISTDINFOICRD 1996-11-12IENG David EvansISFTSound Forge 4.0robocode/robocode/resources/sounds/explode.wav0000644000175000017500000005517010477405066021165 0ustar lambylambyRIFFpZWAVEfmt @@dataZ.ł[kGgwAp~}wwsw{}|imllnWQSUWclp{ddOE22 &6CC>II>AGS___afhaq{vpica[YQQQOOMKGMY]je{vpe[SQKIGGKOSUW_chpw}}zsspmhhb]M>.2_wmkpe_[YQOKCOEWYY[S_flghfdaUQUScdjxyqnt٬ky{M>dulbG2>MdxպuirɴeA6Od{shWWW[[ahhjuz~w}{usopiW&6I]pլx|~dQ:& "*6:CKUflx{ͺٝrbA"AIA22:6226:A>EIQW[dipy~žѺ}pjhd[aYY[[[WWUUWOSUWSIMUKYYkxw}uv}spunnrpupuuyspvz}y}trlyѼ_6CYugmyui]][_WYlbl]m{uussl]K:6.&""""&*.26GIO[jgyvɴ{|ulbYSQMI>:::6>:6WeeUC6*&"**266:K]IE]{ٶɾɼn[M:**""&.:EQ[fpyvr_[_Odj_a|ovɝ[ISMfyɺrsqkY>:>K:E>:.>GQK2 :YoxpmrswA[vg_|pW*CefżhAOeuոeI6  ".6:I]nxѾոjSC6"  &26>S]ackqu}yŨ~kYKG:2..226:>CGMOUUY_cdptmmx}uc{͸ᶛݰͰ~yvriegnsA"..26EKQkwcO6A>662."UQYcouy~}ysplehjhbhpml_MWQK. ":OfxkO6"""*2>>KU]_OMGS}Ѿ|~}|wwzxy|ndUQKKA .Mcռn_QEECA>GKSUSU[gnp~žoIOM]ͲWGtS]mgimmstx|vv_C.& &Sžɾ}|{|vtuvqtz{|mjgdehh__kmigb]WUYUO[b_SYuQSA>rhpvK"*ok[O>6*&&"&."2Gp_ŴyfQA6.*&**.26::>KGMUOG>>zɺɲWYK6 "2gOkUjuݞ͠hj~yѴyw[QGACEOS_es}{znrqp[K:6QU_u}zldtr{ɴɾŶbfY62  .*:EA2&".:CGQaku{~xY6"*>W[_K>  .2*" &e}vS& Gl{oU:jѰͬžzx~پ]IbiYG]K"6>Kh|Oenps|yo}ᬀWIKG>66>Y|z~zjC."*>WžqM. .MQ>*2:ESOW_w~m[vɸc|zz~twvWcvͤŶzpaWQMC>U_M6".2"  &2GUO{hvż}wpg_S[zv_KA:*"".*&"".*.:6:>EQ_kqvzŴykk>."*ovfGlaI_wUC:G 6:EdWG:ežɼ;iWSQI2.>KK2 6EWsz~źѾI&""&66&"&* &WY_OfxSd}iG":C.&k}_iiz|vkU>CflY]egt{ŰfA"Czv~E.SOOYG:".YcE2* &6EQeGEI.6M]dpxoShɲkS>"I:QQ]Yph_hu͆W_}hgYA"K|ixn~qehtvl|ŮxKE:EQM>&& "CYMKQa{mj[UUjpl}k~af~}}pkyulhuoS>66OyźgWOU}g[>"UrrS226ACKQmpgͼior崦_ 6cssiW.&UgY".ACGKC>Gm{vwfz}z{WfqfO>EQIG_uݸvu}cG*IS>& .6GQ[vɸ|j[>""&6CddeSISMSjzsŪ|tifjpvݼi_U_qwk[t[I[cj]I*Ahpi[CEUy}yt{]j][dmG> &2>MizdA& ".:YU2::Sk|nxbm}yrmq|wroc_unuhge]YObxɶoimyphhbYn~xɺٴٲyjcY*&:KG.*26CE2 ""&  6S]lik~m}Ÿn[GA.""*.266CM_igbeulSA:& 2KfMEOS[Sbk~mm{nCa]eIWcCCGIYWs{dQQ~~xsoedWMGMOIEGMYhvŮپkWMQWYWA &quihgbUCGUcgWkSSUYQbeYmU.>K[K:6**>UzŸɬwWCG:2"""&  "6OMG:UŨžus}llzdG::.:***& 2OyžŴwtpfjtpyqpysu|_Y]b_W_yͶ{zc>" .."".:IWcn}ѲnQG>..2&&*&  &2GOUQCUbdd_Yrt[q~~œrpWQKA6  "2:6"*:IWdnyɼ;ѸͰ}tbKS_ppjmg[YYQICG[UKC2..&"Iuuesy}ɲѼujelwi[lyvnG. *KmgUYfn}kynd[W_bWG2 ">pվyngdexupY]x[Waw͸nuyvs]>AK>&.>**QG6:MbEWSAMbkjgvպrcS:*" 2:M]mzٺŪW:O_msyvx{_A"  QSKnq_G2OOMOYrɺeG:IgdQ6CWdfewpnhoYU[_[U>>>GOwoMG[ɸ͓Ůw[>2*6>IO_a_[UU][eɼ}cGA: "*2>I_oɸͼŲr___I6 AA2.Gb]O*&6cxY&>WacŨ;ͼnMKkmd{{woaOIC222*6>QM[[k][fbd|twxssnnrdnUbn;|qttWMOKMUcrqrѺ[OdvŬ{qW_s~pfb[_a_ab_[W_]U[]ky|Ѿ}aC:Ub]M[[b[xwrmhrpf[M:&* &::26{嶢YG66&:6CI>>>"*22KwŬ|m]p~aK:EOKIbIIAK[dfUG:AIC>U|ytmaK>..2>Yg妇{}AG>>Yqt[>:*  .C>Kok]G2.AYmͲŴ|tWSA[ys][danrYOQl|vcYUA:.Y}}rpuysvhgz{mżxU2 6.:OdQ_OC[I2.6* 6MIC6.:MG:QW>**6CSWtŨᮖͲ{mŒI2:."  *62**]v{ź|WE]gp~վɼpw_]x~Upjbfpqu][dpdl]ICU_acexohfvzmW2*2G]hd~ͪ}stiWaf[bS6 ":W|~~|rw{vrplc_[22Mwx_6*Kpn_6 .:QO]W]d]K2":U]qw~}toɺݪc6>:>[j}ny}zrsaA6:26>O[pnfoy{wvjajrzyvᶶŸh[>E][hn{hY_IMenkke]QSKG>6&A[tzqxlY>6.2**A_u{]aSE:6E>66KfqŮxpM26ICGUQI:&"6ESgux;rlWOCA::2 :c_MaͰżպvf_[irltmctqgK* *.&*.&6>_wͼxqpaQ>:2* *&:IE6226>KQh|}zjxź~upv{vrѺmaQEMYjz}Ͳ}twrS:&""*CemOS]UCC:26Gk~վkUEIOYWQMQijba]gpyzz|ureUG>CISchsɺ{fWI2..&Olj[UY[dUAIOQK>226>MYeWWEWsѮ|wrrpu|d6*  "&&""2>GE26&.&&>KGOWgzrw}_E:A::2.*.:>Iw}zohky~ɺżbG>:*.:OSUMGIM>::GIYeopŴu_UGGWY]fogdaYYM>>:CCKI]_j}qng]WYl}}ɨ͸mehQsm[IS]s[bU[WQSGMIA:GUG6.:EU_chswzyͤ~Ŧɾɾ}}~p_K6*"*.&2EOKGS]fcaY_zww~zbp{}wm_Wjtyvz}n_]mz[K: """AShkzѼzu~{|}W2*AEG_yѰyxl]YK6& *2>OGMYszźxuotpr}h_gienxkikmyհnUI>&.:IWdt{~͸tok[I>:..6M[WE>2&&&*&&.2*.>>22>GUYY_WWY]bqѼpje_UOUI:""Epql{|vK]ŮgI2  ""6Kadfc_aks}ɼŶyrolgegpxtuy|vռpvplmst{}]>*" "&*2:>A6>EG:>IK]eɼ͸ɪs_K>.&&."2EO_}i_bjokmedp|pcdj_iwwuzzhOAYm}ͤͰ|mU>>2& ""&.6:EAQb_]YOjm_xo~ɼiQ6 66626:>]swe{wrggogegkc]hstrtpdaWQWSOQOcs}vz}ոɰhp~mY_qggYA2*.>::.6:6.:.6AUYaluupźz}|pc_GIGCGMK_jiphwѾ~qoxflqrssz~|u{su{rpk]GIISCKCE>CM>A>ESehq}}{vpqgKGC:AIa~}ɲ~plnu}wym_f_YKIE:K26OUS>2&*.>>IAEA2&**"&*&.6E[qͶyra[]GC.>66SgɼŬz~wr{~tjkam]SOG2>C]M:  &6>K_dspmkbM:" "&*2:GQI>>6>Oapx|ͺ~jWOA>6" *&&2EOWQrяžŴ|fC&6ISSQQSSWYblr|~ŬhWK"&*2>UxxvraSI>*&*6:A:>6>GKCKSdju}ptzlajqeirrol]Wpnokgba]aevlkkd_cfbQSaje]WYY_be|zvŢz~y~ogjvmSYwxfbehopuh][UE:Yt~żnc_[WW_ipokx}|}{|znq}žmuh[fog_OMAO[]UU[UEOMGGQ]zv~yyccmg[WOa_acc[chylyɾsaWe_U[rz}wp_l{~n[]QEOWSbvy~t]C62&"&2AWSGUQUiiqt|Ŵunjv{{}xyppkiQSGA6.&&&2AMG6.62A>::AE>6>E:.:Uajdfuxc[[[OO_qs}pxž;Ŷ{sd]cjqv|kmpklt}yqnvmWUWQKOOUSQ:22AIQbaept|mMA>:62&2CUQY]]fgitծr]Q6* "6:Manͼ{qlhb][UME>>>CQdd__ega]_WUSG&*2Ejq_]f~Ű|px{w~zqohcYW[b_hmhWWgs}wywqruypsgUE6& 6]p~|wz}ͼwn_UA.""  "6Wt~|ɼɸmg[K::OKMYWIQEEGUM>Gbp{{|zfpxylcUWWOSantppu|}UOQ[_s{qiWUUOC62*""&*.26::66:CKQQWS[x}}~~|}uYME:>KUb]USOIUdpu{}y{~{styn[MA6.*6OUWekx|{}uxq_QA>2*.Kovyqqoy|Ÿž|a]YC622.&   u6:>>GE>EObfli[][aagm|}xd[b[Ywl]Q>:GYpwrU][aihm{tsxq]S_p{}{~|m]SIA>IMC2"*2..6.*2ASdu|ix~žoYA&" .>Q_lѺ|vrkhk]OGAIW]d_WQQMMUcouzѰzacefiq|}|ueM: *:GEMKEGQQSWWY_blmmžɴ{wy~{yoljeYOSMUYYMWUQW[[ms|}tzp[}|ɨj]UWSG62.2.2>>AGMOKO]Y[Y||}yu{tvztoq~yhedW[juxwsjhWIKOS_a]Y]gmfUE::GCKWb_YW_cv|nlurqwuuljhjSA2*:KIS]uo_]dda[UCA:6K]iw~{n_QKSYbdf____ecgvs}urj_OOC66:::E>:[rŶͶ|qmg]Y]i_OEC6*2>GMW[[abdbfbYOIMIGOfsrw{ɾ~xzzyy|xl__[MKI:6>::AIGCIG>66:>A>COQQUcciprx~}{pbhiklmtwv͸{l[Y_gppsoklspdhz|sjiprolicbbffffozymjde[a]][cpz|yxz~}{vt|ty{~|ͺten}{gYOOOQUY[_[[_cghmhggcd_msf]jqp{{vvzxvwoh{umqzum]SMIC::CSc_US_ahp|{tzx~|wwvjfe[KIGKOKMQQQ[__]YQKSOU]_YOOY_USSYcccchmnppjddiusutpdWcxwpw~vsqty{vro{xyxzwughpy~}{|oktjkm{migipvy{srs{}~}~~{sodlw{upt~xy}~{vz~rckkv~{{~zupmgipid[YW_lrpvxw|{|onsr|}xzvrpqltteYQI:..226>MMIM[eq{vjc[[[aaed[_dp{rtkbQU[YSKIMIIQW[ghmpv|twypjSC>>M]ou}tkfdhiifhhfcadjld]iqx}}~x{~{žztspic]cdjr{||{}wrqvx}zrvomja__YSW]fpx~~}|zwpququv||tpjiccbUGC>CMWYU[bfksv{wytlkmquqi_]c[MKW_ry{swsssuqng][YUW[]_b_Y_jsw}žż|}zq_cz|~{ja_cYE**:IUaht||snop|nSIKUYY[dirz|ytlnptzzrllty}{gSQYMWfq}ysmlgYSUYUOG>2&ASWcv~yvu}z~~vrv}vphjkhaUUWYaflg[SUIGSSQMQOU_twz}}uqikpog[SA::EEGWcnvvolots{|{}{x~{siedfjjprqrvz}qvnec_hw}~{qsv{~}~zofbgnsrknnuvxxrns|ske[SOICCMWdfdhfnyyurpf[QQSOI::::>GIKKGMOGCAAGMUgw|rfhlt}~~|zvj__gihjjgYOIG::AGKE>CIISY_acipzx{yqmplh]]eolnpspx{vomt}||znbcefba[SOSWcipt}~~zywxvv{yv||~{~}vpqpqu{|}zv}wz{}xwyzpjmjkqy}{xrlferwyxx}~~zrpnsps{}|~|}wqsvvxwtwwqignrwnlsw|xvsvuqpkonms{{}|yvyz}}~|}vmggda]cmwyzzwzwvmdfouywwz|~~xvvwsswyw}}~pnpu{||~|xw}w}wvvv|{|~tiiljedknmprstswwtnkijoospqy~vwvuvvpqrrtx|xpg_WWWW[gz}wqd__dfdcbekmknsxyunm}}~|zw}|vpc]WOMG>>>GOQSUW[WU[bfe_dmntuz~ž}{ttlggkqv{~zqnmicigbahmv|}{{{ypmdYOISWccp}z}~||yyyuv{~|y}|vtne]aa]][WW[[UQWajrsutotvniioqsvyz~vvusx|wvsuzxx{umgfhe__adcehrqrx}tnkkrswz{}zywyskabed__feguvw}{uxwtuvzx~}~xsiebahmjibaYQSQKIKSYahsytv{}}{xrqpuqvrskpz|utsqr{~|tliehnlpsvy{rhf_QKOQOKOUSIKUUOOUU[[aiowy}|~|{zvwuot{zytvvuy{wssvrssvt{}|}~|}{}{zwyqkgjkejostlkhffjkouyx}~}|vsxzty}|wyz}~|~|y}zyww{zz|~~}|qmkmqru|~~ztpgggkgov}~|{yumn|}}{rohjopikolrtx{~|xvtvxz{x|yz~}yvptslihpvwxw||źn_YUWUar~~{zsnfgowy~}skknqpvuwwwxy||~{y~~z{yxx|~~x|}yupmruy{~~~|wvrquwwrv||yvuupps|zurrsxzz{{{|||yvpmojknrw||ym_W]ny~~~vtoigihkqsyz||z}zz{{|vukglpvvyz{}}|}|~~wy}|vrijhffhgjruz~{stqpqpotw{}~z~}zyvppoqosrqvz{~}{{|{trqohijnnpprv|{{{x~|~{xwtupruttpptlcadbgiinz~{}{xquutsx{xqoifbbkmvw~~wtxwpnnllf[_ddkopu~}|||{y~~}~~~zvuruw}yriYOA:2>EISY[dpsuy~~~xlea__jpwxz}}ytstupjlswy}{}|~}yuuvy}||~~yuy{zwnpkry||}|v{{{vvunmghebfm}}ypjbcejqz{}~~}yvy{|ttstuuuy~}}{|ytohbfkux}}}~|wxrplh_[WYY[]dijjlosrrrsrrtwoomlsqttuvw~~zztncWS]gkiqvsxyzywx}}ywy~~}xqnigffhpx}zxyxw{~{y~|~zzwyw{}wvwtry|~~vqlkjilprortnsvy|}}~{usqpsttv{yy{|yuvstx||~}w{x{~}~ztsuttvzxqtvusxx||xwxyxtrux{}}{xuuwvyz|||z}~|}~~~yz{}~}~~{x{|||~}}z}|yxzyvrvqnmpu{}~|zz|}~~xxyxwzxy}~||}~zxyvrmmopqqprux{}}xutsqty~}yw}}|~~~z{{||yuvvxwxuvtrqsurpprttx|~{xyxrqooppppqppppqqpqty}~~~~~|~~}|z|~~|z||z|~~~~}}~~zwx{zvuxx{~~}}{urqprstvxwxwvqqqoomrtxzzx~~}~{{~~~}wuromoorux{|xoolkmqsv{|~wqmhecaegknmomnpomnihfffhijknpqqty|~ysmi_[WWSQMMOQSSSY[_acdjnpwzvrpokhefffijkkopqsrprv~{|usqvvxwzzzuvyyyy{~}zwsqtwxwwxw|z{{{}~}|}~~zzuspppomotx}~~}}}{{z||||||~~{xwxyy{{{{||zyx{~|zzz}}{|{zwwutrvusuxxy|xxwwssqqrtuwxyxwyy{}}~~|yuvuuyz{|}~~~}}zz{~}zywxxxw{|~|zzz}~}z|||}~}}|{||}~~|{xwuwwwwvxwuttsttssppqw|~}{wvutstutstsstuuwx{}~~|z{{|}}~}}~~|{|z{z{}~}zzyywvuwwyyyz|}~}zxxuutsrsuvyz|~}|~~~~~~~~~~}}~~}}{{yxwvvwxzzz{zzzzyyz|~~~~~||{zyxyyyy|}~~~~}}|zxyyyy{|}}zxwvsrnlkihkmmopruxz|~~~}||}|yyyyz{||{{{{|}~~~~}}}|{zyxxxxyz|~~~~}~~~~~~~~~}|{ywvyzyxyxyyzyyxwxxwxz{|}}}~~}}}~~~~~}~~~|{zzzzyxyyzyxyzzxxxyyyzz}~~}~~}}|{{z|||~}|{{zzz{}|{zzyxyz{|}}~~~}~}|{{{{|{|}}}~~~~}~~~~~~~~~~~}}||zz{||}~~|||}~~{|}}}~~~~~~~~}}|}~~}|{{|{zzyz{{|||{|}}||~~~~~~~}~~~}|z{{||}{||{{{|}}}}~~~}}}}}~~~~~~~~~~}~~~~~~~~~~~LIST2INFOICOPA1 Free Sound EffectsINAMExploderobocode/robocode/resources/sounds/zap.wav0000644000175000017500000004323410477405066020315 0ustar lambylambyRIFFFWAVEfmt DXdatapFϧǩۚ%,e&, a!1p~6(i;GE9+.#%S0< B!?45(u 7".>1L NAR'3Uq{|^+6/Xң@2#""o$ EeYq#ۦrߚ2;!4qz I-Ej~u\l:(=J}G(B@:0X$ ~6l_$o5KGul: D۽ܶ*$"t>M=zّۧԣ ̕љזq<ݽD<׼ ȅȡ;W}9OھO{8ޢ7N3DLMwDu@A _`Y'1s9?IB/ 'xf#.6EC:/Y#+" $*&;$ ;- B/   y?cyכ̽ğqĞ >tٛhҀЄێߌލgc}V!ݭߝ2'!w=6dzEی&U<j*w n 5` %gys})' '$ҹ`˗ƿ۾jֿl)'̋8׻!3XfȺ)Ӻ ·~ҘʋMϗԵZIpUjcٽGt*!ܪ qPԞ'd}qX6lv/wr8u.X4Z ` شwZ/ԧ̣΀KxR,%#b K b w%_)'B \ cuB )X_ rbw3=h[K "SX|=Nv  "S /  W '#85 ?  Dw + j)b0(} }+zX,VIۻݑGR?0ǰ { z6ޫT #ѧ4 i\6MeMPБ6G0QMϖ+טJ{ 8)[m AHIZ?R={) 1;^9b }) ]L`n ^## hJ!%#!Pw 30~ & : /SKz91G0OS)d!O#r$x#A 3BH.l@ Qyzy ۋ20BQuC*i4}zmeFܝ8deo Y%q Rhe 9# =Do_o ΍̿t<=V)Wϩ^]S%BEpd>+\rl  CKkB%ϙHlwL6HKAܯ 7Ymwd2_O\u L *XDS0kixeS@JoIs,m7:E_ g| O]߉;C{ F B:& pS *XjL!' Gee#  *S@ *sg$gI ] xsݬp}M c9m[ɹRȢ}׿_A dҊEWMݠɲI }߽V=FLŒ\ߟD 6zq҉ä\- ۨʜpj-}M׻[ʹ11Ȝٰ5ṮYZٱh PW0\ ߑҩ$r2=7. [Mt""W :yʹ; JE f%r3- "24*ux T!0I<?8t) d-3DD".43,"7~O<"] zOAZ9&13+ 0 vz1  3 EupS -5F5 _ vJ\@]}lh j6$ @ _nTR X  r-e,V *l;vS~2<"= ѡXM 6ڇLG [#*12k-A" dB))q6vӺ>NADX W>DI\ A16(B /މ &9>8)G ^7$ :.(8DGOAP9Hk:+v Q$(r'?" %#0$/76*4uMDW[M3s=Y#OD[^,M*,cSmj"6?>6)|s)_=DRclj]wI4$e!+?UoefX>"e,'e@DP~&.+H ?8 P8i@ $21!u Sp!9E?' %! =(: <,Q;2)Bk(:?9*U \)` sL /6a4>) #2:7s) 6'593& !'' qWEӡ|D-V;93( Yϱt'%=F>)HyڏB@p?+~X  &}O5x'"2M?FOE:k)<D .1(s^ '3*1x !*&_, H^B$@Q4zxP +11({h4 G'"49H|MbG8&i=  : Zm4  z R2R$ h^ glDV(qYu >P8QqK"' Ħ~u k(2Q+OJbYcl;iǂauO } B۶dpv`;ޔ8k#ӊ͵ˍVϚЫU$t?$ J2iԆlsѝ,raßѻS /c տɯۼc(/0,$#I o$C(B"}+ѾŮ6&N  $Tg5 ; ʺz "5`S&ٙsF3 aĮ1BS '%`׹uNIdئзRĵAċѽ[ h@6[~ǐm1 #$qFF  <9ֿoO2 |h1j7!R0;@=/?Dd< ]9$7DG>*AWpX5RcdVj<3pݲ@ݪD-(J9A>2T } 6QڤEj<شt  l ! oG{VJ[(Grh_$y9-' RڏW#'/@DS8OݷϷ5y]iyXs㙲iOFWSE0Q aX0;>8,x 3K I#- 4529,s#yb (AS'[&M,-T*K"# $cbrވ B!(("h$ڌIߎ!tou^O[ ( !_*L2@773* e m^&)'i! %D W!'-+*&UB^x+A ,V62?FMQERL@. %@$6EOQ^M2BJ1L+c+F\nlqkRZ?Ey$ߢ4*F9TR_egkk.eZSME@5/,)+(/# r'8G!S[Y0ZVMA3L$  L0PD=VcjjcUFDQ1hp ")-).+'# !<&,156=4.&eU; U4~[(3;=<'70*)% ;!)+7 CKN$K@_2"[ %3?HLVI@/3" 7X#+:/-x)$g#'L**)'% %q%?&&%$$'-7AK"QQQKA4K(_ p t)%[4B\NTAUMPAG;o0&>C ! X T@96!$(+./.*# V Q ?o9 %.4R4.$ -xfq uWL7=PYDr cx6X/ P K{aDmg!$%#UMT% JWOV,#Z$~ WWB5,u:EK&K=C4! 7%gw @tx(> AM)< W^ KA #1@sLRbRnJH G Yp;x /$.6Q;.!=!M1 '\_|:B-K ~[L\U 1!$%"?E 1 aO! fAn=]s 6 )`x JQ%<*,"-4+'#e9 U|CJ TGfV .E ުډڀs+ ) h*28;,;82+ #W 'QZ7 c  rcO -E_QMd< ")/f3e5 65!4W1-3'_ c> 4 ~ c Dan #J$"d kXzc )  ap!#"R"@"d#%s(*++*`)(()+-/13T5q5`3u.&Z- h(Td'!O)F.012b3S4}42 /q){#D!"E!1q>QT;VgSN 0H8 <+#Gc4   r :Q QK0o%EdvAl;.˜˵6!ֳؗڨۯ۽,uY 0A mk8oݮI ^@*lYNRoIQWդс"̖ɪ ̸Ͼօj*ruQ3X ՠEܻI7[YSZ]uݲڰׅB_kɗ!2=ҾQ۱ߴWWNKs{ARu[P"-q6WZ2R[<D.K;cI3NbN Y ~ #l& (#)_))(4((([((((( )i)* +6,j-.w/@001"222210v.+v($B!L9DEZQZ PP !v!!o!!Z g*tn =]*!" #l" *S g${GFuWZD'.0im*J 3/.Y; 9!P!Z fI% m D#U1#!ht^kSa D  7f|n\ kY<)w0 T#[X'C ONt^ jCUZ?ܒگM۝܉Vc2/RA#"b^nPNS2Ak7G:aݥlσmŽf"]9ÜȫKy A (3NqO^u-^Z/b2QXR RbH 3DMVc9z<%t hX @#i%8'(}))(&#Cv mN{0Kd~(\?8vdM(\ /\7]kz{9a vm"Km {`l>*9jtދ8݊݊(A1#x2lsS xM -W}  4 Uc ) .pfMq|a7 q_,b_){ yPZymJbA/gN wM~2^q^(L x!vxT%7f\4w`b:Cq4_$L(CoR*V6c#  ' M D iBpQCވ:݂Rޘsu^K ߣޕݻ۬;YGiI2h5=rݬTֆ\VӀP"Cgыѳz s( Ɂ?]͍аPԆ~ܦUAP݈ܛۜڔٖدC{SLbՎskת\ز١9l.tlAy| !"N$%&C(t)*+,-./0Y11f2x2 2Z1,0.,* )2'y%#t"*! a?" !o#}%')L,.02s4678<:`;Y< ====<;:9m753130i.,*(_&#P!`>E8a!$'+M.147:<>?@?>Z=;98404,D'!j c/~M| ?eX  }"&p*-034 66765742^/),($ cR zTG}IP^rO D&EtC\ (|nBkTudP9,X K)4t20t  |#qOJZy[#IJ(_Rca!g j;&;wotP/7C8uiDgGf8LNu7w2v ZAq|3eO62]TW֖}rtҁѩm/EϿϝфrՖ.{޲ifH݇sݛݛor4@]wuva) ;WEGErF$2GrO $EU@4NFec-" Y x &  b0c;7+3gq8(}B$#0;?=934B[ [,EgEqg$ax VvB ^HR|/p:u `!W"V#P$@%&&L''''d''&"&%-%$+$#"" ! cY:ua8]NFR=Um]'7$GxQ0AAR !""!+!b *U7? z !c!!"p"""##"y""!!  @kq%{Xvn^??Hy$4 Q {  } -qbq[b _  = V Y R E 7 0 '    } y_[q#yhYL?1' XMcdf8 ~robocode/robocode/resources/sounds/13831_adcbicycle_22.wav0000644000175000017500000022100010477405066022634 0ustar lambylambyRIFF!WAVEfmt DXdata!f= >_eU<_2%U5Nmrtdp&$31[-9-q&O,u=r+[#c: Pbl/pYIAb2"L : wzzo}O - }d)n#EOh,3WOPi#KR  Xs 0# hG)<[ )7>Z, !n+L Ku Gz2 .%c# $ 5<44, 1+QOX %<V pPߪ}"F q  xexp3Bf;> ֿ1Ӯi%*%_ 4e0w1VB [8 0Z+ ]gV:Lf! *btT_`   3YU jq78I(q$ !W*#)>+8 0Px`y !;ڀ$2 .!$s ( 9"0eK w h t/. e,$`8_S .- #s ez,U  fk+@W&b  #`=a j=J*"  9 # ^ CK޹fޘ7 ; fjM.?rb M#F>f 9A  ͉+ P!O=JC78WY WY( <5c lߕL2!jB* DK(&#/1*QMn<'wGzͻDD?S 89U$l: ^ fC (\ N { 3K6B3= xP f;.V%a8zxvoG k369."<]'I߱ _o&U;1J N(F _l  A&&Lzk {e\ PW4"Tc4#& L Ra=X 1{'RyJ&Q aX46"ާ5#[hY RRG"#(t  < L8kZ(m |gh`%AfT" _ 7e$-(v!R F l  Iob )  e0Ne4 S$6+`w " o q"y>۹߮"3e3 g- x9A!5&('&%!&2H-`El! 7r  O tw_,l3,T ZKr;  U V+   SSw#|Vh`{Y  <"*:J a c  sv w:o^0D  yC%s{Ko5 7h"`3<(Yj2' *,# )  ' 2Iy: l | 1R 5m :"1 A\qk:rSd_V)cZz&] A N7h i q~!"cuv3,rB dx dv5N^f6r7`%*dn?`1Z-VTSZ{[#<1AD5} F1 UkFU =  h1 5$$"# @"> ukqba KwHt!cNS9 I } sZ=t0'z(z$ E nHZ  p L+tL 2;1 _CԷQ $n|K AjQxIT\lNeO@-*  2DykZ ~WSj{TYIFFRn}^O)} 8 [M  @qV\WdWQ9   \p=}IH-$yQ= }[ +<  YL K A_ 5 p 7 7|1,%tQS62rR-u  uV]zU 0 Xo+W&2|Wg|  =/0Bjw" ` Y   U p4A@Yhp8> ,.9r  Kw= -\O(' v cH S /FV  >W*'XT+0p[P*JAG{6`25>  N? qV P > @ 6&5[pemo7ZgN~ 9? ]! l"h0k l" Qh ;&c'#| 8 9/Kcl8K [| %MoP.h %Bm1=]WZ;jL PcR I %u? y Qm JlWo{R "puvlI* Mp`yHTR\5$ Iz]yG_}|Ja2w'PYcDyHOs`ojj J T gp 8m~AJ0`VbAWu1Cm>JqnV86v@ . ;u|n+u~|`;Ry& H h * 5. % \   h1zh!o +_!Cfxfq=WxE^w& VmZ$ 6Dx_, F&+\laqU2-M/99A 7kHc\l4TpG(-5 bM l (L:r;lYpZ: Fb-WX.u$- f95?(SL\"j.r\y}O0 ;  W* b ,7n:&+D;-M h"Qav@j6SqA5~3'gld0 a,PT%92#0N   T<n^{F 8,(ambr@u]9R9i ]_Zl+eo?   U12YE(Z!U oz L0P{CY$\6s=}0Crb{'7tn4a;,ub ^ A TM?/dGr`fGS"T"xc+\'5LA ^ ul>{ 5+UUD%3 0 9{Dmm3/|ra K6?Y**q m!}c(2;|tEp@4" jY\a  1y8jQ .Ah;7e4h.DTMW( =ZP1v'!WN{A*gDv-  F  pU<7U4H(j36+p{KJ.6D,<hN ) \0 / 2-p%T86z>-  .G"[&L/\`4zf}fXzl;"D]YUQxG -V [~T{9 UJ<gPpcfvx @ pg#9p(-tb4%F"ncn=w}i-C9`jTHv  BKl<%21$THQf +.y" ;P<#;h[]p&=)<-)F_xt<.2"?m1ss-d>mx uW$! k rNM?xt9 } gnm > 7%;Gx`$~/|h|2\0qX=Elj23 {;SG~[BLGfx@*&bCv#(~[P}_0I </GyP*&|P{|\p,sus9*g0|  lof GO76/~ ,iR*q L!l fq %!bB!9 Xn 0K.}eliDEf Rw3 P'V'mS%t-4H2RWs``jd'{Z z.Ka.]<V [3]5U<S o 9yc5mLJo[JO;I]O804XR1kT$p W=o=3z^ ahC5f@CbRkm;bVoY8+p'xhxYc:D\o x!i 'ALNxF]o_ f_-.`R]v:AJr.l- Gv*& 9AK$ pP_5A6w ljpHIQ^#"W"R>pGNY0swNy7'  . .qy/|VbF}FGP<@_,96>< ^yg?v;*P3|.PvHAzj~` Kue 4 %EssHdHr"T-;zhWX+jhbLGg 8;n-~F;t4+yZr$L`<vdlAI"Z60->2#4 8Staj"Q6WEpoc@Uxo5E(kx}_J+])L';"b P5Um\H&JO1T|.:;<21.HL$[XzpP-yuT@Zv%\[H /p ']`[EVE"L7mh MD?cT<M/L],*?xHr - N*T6^lE. |U!z'[% ub4T&c3%4DCVP()w`X* 79 %#~}G\WD 3  $EZfe,c? g2FY7tr2yKX]K@l )W$+Kz76U$  i ,nB94yI:"fq:T Q RCj^7Tip8u:Uag5V!&c1km  $RBcf Y ~i {n%HKv[[r(dwpas(x*s%iQV]1Xr 4t* t*;)[3@ \e('=D)x]/$AZn,l>o]pCP);dIG <%fUyemZTbq\- d/Lj !),,tiS^ eeu* :^b=5]r?-;f*SLLD5Kl_ig>~Wtq~ IDk,2De@$-;&0agvW88oit 8X(ubY:vKTck4^&I#tY{ lz[()&qx7L_&&2n(zrLU!B?8=^N CZDq=cC-!3F~a#Ms(~0dyyf sbcY4I` dbU7&/q8Ra1~,F=YZv0!X 6$=PMRvTYz< W \_{V#N3]m>f:IGG%hS>`xMp,L)%e~2Dq`G8c5uF(Hyjl=Wv].i{. orVsb'[~(Wq=D9K~&kxylcch: 90a&WCvY> \Za,-$/kyZXL 0ofJrTrBV1 UD?A`yuxu ROo'TU#$k,?Q%q(~t|PM+a"*iv"T(3b+.ux#A5W7lX)tjl- ^~~[S ru%Z H(zybDk)ab*7W4#}TIuW|0^xTS9O }lsEYi1=38 gH*VX1,A =s#Spcb7uL 5| y!,'[VA|[ -F=sd0%xA:o#G%lU8{27apl@X_?IDKZox]Bq [D&S 6B#P*7 a[k.}{zW&\3].pTo4h>F&LJ;77tlhXcUL^|=) h5w"=j=!|z\r+}W(V=uh=d2Bv/ z#  )|*o1%TZb4lDchs:wb1c;fiBus}DOdDy4%?y2r} yO\+P ar]'qu PpbUNZ[ r@d"'|Mg`^_#iIf84] P^>g!w@VNN>n,e1xBU"9fXs.t}5#o  P;G3k 99@0.RXP/"qFRe^N[ 46By__rG!w}!IY <1Fr(d'`YNuO<P9-pCpVq &UfZX/~Kz~E6IW6Eb)xY%e<P6u=3+W4-H" T8y;6Y/c's` ji0LK|VjSC$1OnA|3@M|cmX}?dB0'R  St@,1W6FxUC!q@^BoQ/ma3Uq(e4Ev ^Hud=?v9-{BMXlHQRg(z~%b!@3%L&G#v[YlI]=S*z#"%.+ld4)MmmYK=T}Ag ah t\hSx-td\<d a3<f;cu#H22:<$* h _n".*fL7$z!ym *t hF:+%mvY5yz0Ch (jM L" >yn-IvWqTC+-C:EyN"(Qyp 9b9of$d~9  5iv9ES`  (S&f ()YK2Q\_H?@)t @aZ={wG<+\ S h`lEbU;/`r%j1RZ]w6;M8b|h{ fYf3Y0E k h O  uQS|-4F,q0th>P]+  aw~M|mB=ej Ah"v3-wps-(LL-9 @xc lsW1!\,'G16hF+:2]<P k=Ar - 5W H_rs 2{`w` ]fW%/WO:;g}5?BL-l])C|.h+$GX6TPc:f T#G-^+k"lDB!qF'A&I`NPBm3 dr6AO,' z -c9ba&YjB[<+*k[i. W=8Pq,YAn$C oq&_)N)`/ C, ^(rem=v-C!Oze[O [-0pS'&|AD % 8 ^E`B57TW0CyXs4!W-u9&61Y(;dJcVjaqZ#Ld- R^~X4w0*_#z{|B9K45#"6Kq=DGD!o`'Jo_y@lEsR xN=QN[%u7 ~EkRNt$ WD te3VTxFO);I>jekf(T#\Sf~}B  oq* 5 vsI"{:)Ln.DkEzq"j>mJ'2!e=aL];0G&M\zYu|^]e1YPtiIDU%p3t!/Jx`<6ic j=\dd/rE"l11=] qOz. `b'7oF4h\d1*T$3&O_M| 2k*'D&R!k]e>x~/B 4ESMJze0zjs8XnowwG i- ~;{ya ? oEV Mj4HkIr7} L$Iml=J>* vqCPZ}'>Wh+=|S2P\=kW;VSO,6]P(XV xF%` O%]\c5 (@>(B'+JaQS*j2+U=jSI(k~@Jk=/XrZ}[(} Pq : {Xs5WUC"Wmp]XVU]1>a~_ dpMRwv Ql 'fBD+t3>.`)o~cb*>wz8ak; Fg,CS]q4t:lOXvJ4E:%xpIk KL.3!rR&GpEhuAN7b Y^Hi%^v H/u:5^MOoHQg,6W!)9/n(}M,:i$si]0 %=jb |b#[ w }0`v^qE 5Fi&jU #6k$\7BAus*Gyam`r.S- y"rDT$e 2)SKRbaD3L`}*S}jRA]yqa OR-m9sZP+qxx( EGn)xrLzrn?|[eTh@42]~ @)?X|/; HX*5:<2j'E&#&#{_F'uY s<4[XbwYLJBhux#Otv}I#zO |>4T *?,UyntQ8#htyt4X!6C:ru)Et,[e+td wQJ41FN?K<y#"k78)Lv>5t4D no^~$o3za L,"q' 9kdSdUk!,Z1:IxY9GLvn'7M?]s Wn<@O$WiUApP m#8qi;)UTfs<]3O+B:NMRL{l N6xeeD`* X WZE><pl K'1Rb<9&W ++d60$`FHc# vPs,-s&tnHc*"@aGKc +ATQF:Vj$_%TDDIb3#60c s-ut;{LM\UF`M&i8H4 )f2> ?6ZUO.? jw>.=%xp-Pq3ZCF^OM EjSQ!>**TB@1,@Le;wB G~^ns i$s4ZADQ#B\yi<bX{$tS;)1Pg>%wVqPUtx #'CS >h!N=sZ'I '^cPB x,"lZC.pF4y J;\1 M{0\K+lsL.Ug`%GYi[uQ EJ_+nuaig}:` .9`3 E&>{E5`b xh-E>\S]<-\(Gc5R-qaj c EkX?PA8W|AXXJPsCHs .' Y;mEBOEp<0J68Q;5 Z' ~ ^; avY:ibL.- PChTx<81k.N,K5dTRM8Pyb&W (/lFPWpJJy;icUVVkU;N J(ZKZbb)e)g)rF|kCfoF4tmU#W>\^pkA.4+- XVvRHy?C^f ;Z8R z['Ztc^@+Qv5:.p%*lO&6F@Z/DK [*Hz$35Sb4A9 ,o3?vW)a(bXjQUp1|SOcF43qp, cn%;W/!R4[Bku4l N\n|tojibd7py@s )j&R/&F&|dg!w8'ml%5e\>(vs ~H 7j|2W9?'02A| 4gr.rd@> ,4`&:<mkML,9;YejYX|jsRl|zOd68aj1f& 3ac}'-XjjHD`? V\%sp<L sV@R1(1"Q5DY.+s m$S,0Ub2}8;n[I'~$Lf{q'jG=8"~9@OP`!;ISi8Q.Tcs{lYO3V2];, =fq@Rn_:Gs iTg6/ v_> Y#6}/I%a=pM&!U0WnV72Bt&$c56| - j@y]GT~amD `<;q? q\'|#D8v4>^,m*jmP,g;/)$@M ;dvSs$rB*ZNSC+E\=XAUeL 1(}'mj$4_RKJ6|oisd(pciYIYs8aH0G%%/fsj5a|r<j(3skR/ `?ob=s9`eN0 m}|7`X?Ctn(b3EC!p036& 0vZpm{C8,0|\OWdi|'xr{< Fh}\8uVJac=0`eM % !U}2" ->IVL!wX=Q+!u< g.`--=Nv&:01- p*3y apdYZjhUC8Mw'A;w:Q_b`gzwveF)_GN CfdOK`u ,:.5zc2 5_ [_8 #06DQF2(+* !*''% $ nH45EUc}lAuU<)"+0AZed\QQJ=KlS/^{mK::@=<Ff*('\~UEF_eRh9s7nr>a&vF+;t~Z>#% #?z&Wh1p<%"65" 'P}pE4(&$0\ &0**.;KL:fF2$r >\p#Pja]OCB:( ut}fXY\F  Kv}]L1V2;aA}dO9|Y;Y}dgwav4}aOIc  9IuY+ Os: 7_zs|oWICTmYMB;+&0BSb^I7" +Pqyta0c<6{y-Y&7AIF,!Gf 0;(\1 /L_dU/(4*xAukehfehy:^ j|okglj2[5,*2B]DhePH>=R{ n2tF@t#+^Ab_/Czgbcc|?a}tR. |MZny_;xspbO?)_:)GQT9HTp] i2!:R_e_PHF@5' S aD295)6Lb @c*OjT,5YyuB )GT^gp"*~haWA& z:$27EE2& $ zlnyv@~/Zoq|pQ$h6*j9c]/b`rr#Iv1dEa<  x59\:"uB "5=F?#!>]vC4rK~t`Y\`^\bhbV[`LGXen\/;YhjdQ#^IEWe65kgn@ {~C$"+! ,.&e/D ?l~tik^JCK^sgFbTRe1Rv 7R`[E*Cc$8DJG/ Z@%-?Thmmqs|h5  41#tlv H"Fd}|_6 x1{h]]dtd:}rd]ZWi.}(Cawp8}F6*3>8% &/4+" rJ?INb  '@62;=GJQ]U=.#?Znwylefd`\TMXa`ZB Z"5JZVA'nbR9tdW]A]oy|gK=708KSD5&oR7$!'8;2-88% '@nX"),'((pL)".9NmsR. nTHFCCB?<<+ @i5JLHD40Z *+#l_YYWP:%+E_rzvfL3 zxm^O7T2HRJA4 zq| 6FO_jlcQG;03?<,oXE=0&-E`AkZ=$!&4GYaYL<'$:Y{wdG2$   a.  Ea&7B>531/&!#<YdcjntuwqcJ898-"09A?5+2BJPc~l,tR8- #9MVbkqoj]NG8+& !"'0AIC7HKTgp}!4:AIO]ksqfYK?98.!!9Uelt{ueUG6'%1;BLVQQXXPMH;10+*222AWlxe]_ZLIYqlP:,W7# #HjR8YpwxmT3o_K91" xkZG:+&,6?M`qztkhpi^hnaWRMIB>JX\afku},Yv0>EQW`u|uslW5! }y{ncj|\)[; !;G\w8MV_vW3 +9SsrHh?.Wu{p`SKHZ!R{{e\ULGG@@JRRQRTTSJBF]rgWJ/mYODDWivmTA852*"%$%"$!$=Rh|)7?BKUQDAK_n  'AID9+d? W%-58EZi)9:4:8053')FYWF.,Pclr^D#vhH  !Ehx 8Ys~}yqaZRF7120," %7GbsqhWB7BGGT^WXcm~tbPEGT[W\d^VTO?504<@K[l}kWROQX^diaRKC, !+4:8+~-..685@FPddP8?f~tjbNDJSUUN<0'  7GVakw}~va?2+3W}^<0WopbN4 j2) 1EOQTWWWO:34,rV5 As",,8Qevs`C &>MQQNQK@IOE5,./   7c~mM.#t_FAA43:9G_t4Yp_J56Yin~gJ(wjYLC8$ASeuuuuqv~ "*-7@CIKKHFGNZmz  v[F:.! 3>CEJ:ync`aZDDUOCG@@[w&*1/&0;80*uaTMS_iy   "$&.4;8%ub``YO?'$.&#(5Ncy*=JYqysu{uy~wX@* 0Revweb`QPRNQK8-"{vmcZSMCHTNLXUSbigw  ,;>CEA4 qeQ:,Nv"7IO]r|}ztpf[\b`_hlmiZVK9+)%(9GXcXIF?:>;8>9"qc`ei&06918:.#  *48JUalqrl^PKA2)+"  )<HOPJJG5%$"x|qdnxyw{}|xpnpz -94;JVSPQWVYWHISRKSTJDE@1) )8<8;CFFOY_agd[X]][\]VTVMDBA7..,%&$ }qh]NFENVcp-2>L[kx ((z_D*zqmmrmdjqpot~"0AIA5,$*7EUm{~|yxnqhVG3"$,<?=8,! |_LIA;>DLWdp /FUas}m`WC-0EevuzmZL- wnmrpt(<EEEB;." vjinoju ((,*    !#  )7CHGB<64% 6;<Vhn~smlebhlckiPFMH6%zyop| "&-,(&   #"$(&'!$"%)%zly!&.6JXct{uobUGDA==6/. ~*42>DIVZZWNOK=8/" "  (60)-27;:984&"& ##'$+,!&&*$## vuvllz}}%.:@=GURLVbcdg^XJ73'2<?APTJKLA;911*")&#)('(+%%+'  #)664AB=966/$ "&#!!#)"%))/57'  *'6@659980-/&  5AHSY]dkx|vwtdYVI:* #,8EKOJHFG?9CD90'&% #0;>963-*+-# 'GVRU\\UF@>>867AGDCHJD;42.%",01)(9GT]bYRRD1-1//57-lVIB?Lh| AXXI0$+$ ! .FQVVTL32@KboA iJ655+(6Sx " !D]kqkd[aplf_ZP:&G\okG !-3LZTP=rG3,5L`z!27>PQRXVSR]n~x[>)AU^\_M1%!!uZLIRax*UfemfWG52Mqwd\PG>0*%%7<7+}ws| oUCG_#%&#6f{pms}vywhR:$*P}L!"?WispZPEBCDPRTXSD+ )9DBGKKS[XH<-Il}sJ}th_fs ~tv   5HI;! 9clY@('&/965GMNMQNIHE?DT]huyeC' 2/$xghw%0;:52,!  !!%12560+00%)<KVWPK9!kM4 (SZSE<>DGB97<>@CIKE;1*{dO># .Kerz}~y| *Nn{b9  2Jcz~lY9 #4Ykd^VPP?*tu ',1<??>2!+CGD:, !.6GMMQZedb]TND/  +38??2ldi{# &/  6=;:4- &Fbnprwv}qM- #<XiiX=  $.4,/=?FOOMQM0 /Kd|_8 3CUjtxuhWI>2 &>Wd\C* !+Bg|}`? #!xglsu}$Liy{cUORTIC;){lmr{k[[o 0=HWixxn]>"  %.+" !7FGCFWnybG(lTC66=BQfz+=Q_^YODENH1)()*!:Uy}[I=+')4Ne}|_C%}onu|171* $-092,=B5:8117<=B@<@HSP6  (LZQC3  #! (1<BA>>8,4HOMIHYh``cciswpl\LGID?;-{s{~} ")/8ENH6/3<ITd|_7  270'$,) 0ERMRainpruutpfddaYB,# 7UpuhS8 (7AIH?4'  4RWPI8! '(+345238?DFFJTUM@?B5"   !2PZ^cp|}zvtojeVKJR^^cfe_TG5  #',"  &..1735/   ,BGKO>3.$ |  #$!%0=IPTPSC51" !)>O[w~td_RNF+(   $9DJKG<3,%'' !#$ )*-6AU^VV\\[VXRIF>6)%$'2EGQiibXA5$   $'$       " -$     ',22$""(&%05568:793%&+ xp|  $#%18DNSUD84 "*,--$ !') );GSVKMROQMNSYRM@84-   .26COJHOS[[NJLONLSPSOD3!  ! 0>88BNOT]`afcUQRK@:?A935:?@5&',..2-'           &:@CKIGF?) &$   $1?HS\_`ggf^VRPLKPOME;79862("  $" !   #+2-++14/($! )/9?=BQWRMRQPJDGMNLLHB;3+   )49@P[]htwurrk\OG:8=;324302.'*,%   %/:?A<0"   &(-:IHJWa[Z[TIB9.'&  $)213:64.(1-'*251)# ))     " '5:1+-))42+8B>?EDA60.   *:7?PMMUVVK>FE?FEEJKKNKKKDB;*-90*,(#!   "!!{trhaempnmw ++08DJJKXa\Z`kmmmg]OJMD/&&"        &'&%$"''*+.-/+(171%!%7AHHIWXMU`VRTMIG>EK>33)#   '/,/1',2&%+ !*%!,3,%&)"!$  '227@LGJQMCDE8097#")/8>CEE@=A?AJE@?547( %(*/33(#' ##)/15<<DLKLROHD:/25/)% #//*.-& %5ELS[cb_bbY\`]OFIG=3+    !%%*14431-*  "&/1+/8::GG7<H?21,+(!#'$ #(),,08208=7<CCIC41/$%.*"%+00..+ !,+*20-,+&&&  &)*3:;;@FEC<?<612,"$&190(,1*#"#   %$+*$&--))-%$/,2:;<;=GQUQUZMIOHAC?>@6163("!!$'%  %$!*9@A53:DA?=7.+33-+&"$,15,)&!%& "&).5=CB>AIJ?942/*01&!)/((03.+211389<@>:;9/)+& "'*')0>GD@LNNLJHKGB<555354+,6;7/,)+.! ! !!(-6702<CAIOLQ\_^bhmsvtke^RC3.)  !'-3;=BF@7499/+$   #!! #&.1++05771,+($"  )$! $! %"   "/24:>>P`]]hmoptw}||~rmmc\TLGF>1(%  !#!##$!#&'+%)02+&' "%&       '           %(11@@:?@;7=:06?B<.-/2-02.47:=@A<;@@DKRF<A:;>71+%%, %+)%-*    "%%    $#%,23679:;>9671*22-+$      ..'.2)(04.&*2/$!+/(              )+.9:955+"*)  "        %.(+7'         %$#(,013/+-,' (/2..AIACDMQJFEHK@8,"   "-0.3-&())',+*0,#-,"'%%'%    " &$'//-&!        $/562/))9@;1.,"       # ")181.("#"),#  !     #()'$%(+(           $!"0:ABEHQTTQNKJKFCBDB:+")&    !&+) $*0635BGEFQTLSYRIJEAJH=8;<76ACACB==;BBCC@BB:73055.0,$'# $  # $$ !((*)%"%$  $,-"")'#  "$001;ABGMBADD@:8@:01-+/6.*2:4(#*.+&'-4/$&,-%!             $     "       )'#$%#$#    +.  '! "!                    !       "!! $'              !$""+,(',))'('$"       !" #"(!      ##!,-"'*,*"!!"!    &  &        !""'"!#             !%"$(#"#"%$##" #-4+%23#"$(#!%#$" $)#%"!!                      !           #'$#& +2/#"                                                                            %*$ &%%" "! ""            $)$#$&&)&&/72--,.0-'%(( !++"$        !!              &)%&'# !                                                                 #                                                           LISTLINFOICRD 2003-08-02IENGMC ISFTSonic Foundry Sound Forge 5.0robocode/robocode/resources/images/0000755000175000017500000000000011061320762016715 5ustar lambylambyrobocode/robocode/resources/images/turret.png0000644000175000017500000000224410205417702020752 0ustar lambylambyPNG  IHDR60gAMA|Q cHRMz%u0`:o/IDATxbf'O0 FFFvff [lay@qb111a8}||$Oܹsƍwi |@"oߎlK@L ` :4^a. k`YY tN0(>=(%%<}C0ebXr%H #!H @,,dɻ32R D(p6@&Ϝ9CD(ِ ,/]rY f?r @yyyPǥ yYΎʊ,pI}1lܸ&zEܻw} !1C zYG\BP8 l}55\XXXb/@l;0}NNNbPy533… ?48h΃ϟ3`!6l˫Յ?bwC@3;v|عsD`@ GGG$@իlbʋz|/`E1.]z /++p}?66! _1yB  P6ÿH = 3@f8qqq'I.C 3@ @A9   o߂M ~@`AvCL>aiG^X fb<Az!.@L&''8 2 %;ûwr!H/ @HLeX@1z?^#IAf˟?@*lIia\[pQs!,{;{eʊ`$y֭[`0W#X)UVJ J6)1 @zAf /L!@x @V'5@Q@T7 n @Q@Du  @T7 n @Q@ՈIENDB`robocode/robocode/resources/images/radar.png0000644000175000017500000000150110205417702020511 0ustar lambylambyPNG  IHDR&gAMA|Q cHRMz%u0`:oIDATxb€>|e066gΜa (((  0"J5 d&@qJ ^~r b,x @j`3d&@~z ?M>yķolRȘ4|z..ѯ5ZϞ] ; ݵ8۷( e Y8h@ⲲRR:/^\ F[o~m˗ll9>334"%CSS'Oihӧ8ۥ*e>EYY?J `pvw1'Ouܼy `ohi2}a>~|7c98E89=XYU];p¤;/U F+d=ut"TsxyAϟ20wd+WV9b(hd8 #ch5l(77;;?~lY&Ó'^xY @1s 0GXX&>A_ߍA@@EÇ /b8xp0<tQUU] ,222*jjj LLL(cuХOi.A]HH(Y߿߽{7XT@č`@1VB  `쭧8*IENDB`robocode/robocode/resources/images/explosion/0000755000175000017500000000000011061320762020735 5ustar lambylambyrobocode/robocode/resources/images/explosion/explosion2-70.png0000644000175000017500000000031110205417702023764 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME&1HVIDATx1 Om o>IENDB`robocode/robocode/resources/images/explosion/explosion1-10.png0000644000175000017500000004646210205417702023776 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME$/\ IDATxˏdّ3suW=*iba6 Ђ  m+?if]K-R B0~plYɪ̌wcfZbEl~5;|X_/b}X_/˒?  &'k.WOO gvO ҋ޾I>Կx#yUgr5??㿇w wg~~4)yO#x݄wC%'? #¼W?~_8oE}[Ttٝpd\cIvϓ7? >w7$A 0'et |0쿻~z>|A`ӝw|[\xW)\]OC)x~UIלߏOROO_+o5>uU?/? ^ތ_u4A"<aX8<1ʹ7I qZ2,zt4}Go5~)=gwnʽr݄r_<%}/? 7O&ZOOe7Gߣ?pFyʗTNJp *TBS'Ne`BJTa[58U:Sq@f+sLMvI`ccTSW~6X+ l>#@*TWЀٜօ9ҙҙ%INQ1QjAuBMB+&+i^ә&CŸ\7oB'>dN=W= :JeNE$# NǬlDS$T!(ԩLх>H=匝;&L;'؉DZ@JXS2N'Ũ* 26vXf\f f Iꮣ̦+ӶgB?RWf9s7?o@V]D(ʣ ^Q+L)rsH )%Rjt,G.G,:+BDHtl(JИwAP-Y TDЪ 4Yq:4u +PɘL^ P5Ҕ:d,wdP~ nS)C'A~NqP\vk~M`vMG"*5 ijRGbҀ$k@pRD$0R5IW25\A&27[XC4"E&4. 6Q7ƒ-d?me9PB脥"a^)l9@#L=*/hbt}9=' qzv|j QEOB{e̋%i~ ="=b=Ύ"3&:{fQZ\at#D]u$qeEZC8HOBĥ"1SLCs;;O/L"IAQAf Va ;<ӑ¶SjUH)F(2ЙB4h f!ص_]:M Z7>k_;3ܑzŔ1!!< ={6PsFk]M+#Jύ p!N}% 'v6#B3~ͩzvj@U]!HN$F܆#X#(s(H A P|7$L; ^l~|[/Qӿ"0G_?}Vk|7*:P|vEC wM4~&dsbҗ\hd9ct#vHܓ(Feq".wm}#wD2KaB-w)1 3D&3>IqDV,N<;DOx'E_؉ۍ}xh oew oN<3}9Lq{ Gty arEꌨA Hh(E*;LA7h}p3lOKXbt2В);LHu9L]=*d6@ pF- iV)PP1HL!QjNd0ƪB$^fYrFɊLƜOعpSMģ"6Bd&cǨ?˛\Lh@ظ( % f+4%"c[AIhg?QR}z1<5o0We*0MseD8H(ԄI`-Q=DdkL mElaOD+91EpPl\J"$$> )FFPl! STЍLAQ\ALZRp"Ǩ: iRMRVkS>FQ@㽱.+GM~Q&+$o.#4Bwu {yqJ jDyrB 2Z1 \_CKRCpPE]T:b.$ͩ"ـԆ劋#!z%.hl Bb1(I Zp^ )?yMy: []Sxg33`ʋ<5Ugi64|mc@p1.\r`븭{-!iNò( -++S=Xw2,!hn>r{: FK;yI[%d(CǐĢAĠ6F@K"G,4:6RA4dXQ+W?T"wzޅCWPcFDT*v! ct2˹D68@ 6^ Gd62[2 X8GZnؚq<y. x>` & ΤNt.>%h!$zC)9[EMFN l`:7NPBXq(ƾ }SnL5Yg-wkWf F:Z21Jx%ۄPs:1]b d&&FuR.{Nc6Bp$DhL%pD7,|p̡)JŘLQ(r޳=yaё0dRh>PK+iW,Єl9[K8 "(8Ŝ9&9A#ɘr> |(R}6ڙuf'J Yႝ#Mk QE~ N_e\((p ^~iˠJIGbGawD m%K#Y|h BD#0(/<^EsКD%VÑ#i $.h,t427J_y`'a 뤔Y|n8@PShf13u fG>K藇 .:6@u8;Q; #Eec !֎X qND4FHȠԩ yĸh!rlw8sߐzf-vGR3&'̺ $NI9ay 15"69 b ]]_g%>[ )y ՒCw>\G2xBV$t1e~*,#_=yd8ƈ EdL-FdFF]H%vj8t]` '>Gd8Qڝ3NA(&l2a"D)L(N`53Gmhi0FDC9};rn<}*$vA8|<@Y>\hJ핁NY78k~ݡQ6Z5@8H_ҰHtK*";推xBB(}ƀ(=hb6. #GwtZiDD4P:uiTYQcGuBRjc/?~"-)%1IY ČJ QQّV.=(1P7`Y/-06o  v"egֲR$r@+*+vz/LCNfEu ē>WP|A%<5l 9%wBA\D@%($8+Äs*,oVa`O8WkՑtn r0*1}BH ema ß"ΐϘ9y܁9NLl 6t NPTiR%yːf#s P mv\,Hր:IJx Wz*(Vjhh^ K3vx? 90!u䣗9iT4"xTdH"Zg !0D`ށ KQМrQOtO؇sfŲ2hQCPq8t<&$M!l%"n<, 61/6-Xa: -'3QI-lQ ewϹwnpV7{ } vkk㴭|_˫Vlt8vKQˎX[@k6l+}CPzpeojD$J\$JˎgjTvPbi2 ++11SY|(:)y,r;̜Ryg. [!\~E!y@^c,=`ZUw8PtfOct/\mL"^<{3h :_>;%||C .v_^:CAA,=G4 =Sc`$j;l]2U-4MoΜ~E)Jvkz'h M)Mt 3^ڄvErDԡJIA gBĴc̪ ) %_Ӊ&AИD 0rR5|& 賱~wI{6:[]K=]#tcH.8,݃߱ϏQ ;B^"=[M?'7Drv4[zGGFڊ3Dln !:B'LwiF!>?oޓÆ nl;j)(M&,*Hf7]ʓ=3Ξ*H} geoVѪHx,G@-i rBiوT)uL薜J]*z`V'*s&(H 1* N#!Ho"ͅ*l&ζ?P~"8|]ߦd;jhcCtЬzcȼh.cvv-Τ(q$uC䎢/,/٢3rTcشpA6Y) 8Q"+VZvnf*햮w@4 o-ɸ"Ch{%|Ge"9TJȌIb~b*Qt 8_H_/ gN$4lcӘ!eC@9@ w`d="GostyA4 \ЕGr~qH&pHթVQ1fVKkJfjTۆog8({)> IDAT:ω3 r|B"2I'KgvAfdۡyXQ:+zx=,pr>sI]s6^K5”-^F*1u )5'mfZz.C* Hg# =MgR;͡H'3d\tN) 0(M܉d]ɌVZ |v%y| smROGkP{&ѕNH##]E\)pЅœl[9C궧2cmG#! {>!+Pq&tQh27rf3 We>+ω7b}\Sl" Pr['/J 5sAYȘ3ER#J4Wx.sI&s߾I^ q>"19W",4Hc~O{$Qxy-юpSRٱT[bJ3{OSgӂ>oeo 3-{^ɽ&$m̝YNBX0rE6qvYH4zlt]Pg&Hgx]Bp-Nh2wŧ1,w~?{l258{ٰH1X>hʆaU"z("ɖ#̴lz6):KެvhcJƎcyܾzE1m J.'\g& Q\Q :s\gImCbb=nBM;,)AlZQ6f+}^19zBehQ0 LAXOsC>"3x#)GpFѩ̴_pdybQQ߰ѵiv@̩e#02~='*>((v raNƮ9G;"++ G1ыQ1(,7Ş.tLwb\ 56Lh9.މ-!d9Ċd^ @;Jc<ލ`qRXr`qE7w? '딼wA;g߸ٯDsjm-6f'r&L{/ EV6F% ҕ913@PEtbCTߢOxPyG_WXm+!](1MtT xUo0[d> !V:[{rueV NX7z 鳚ZBvDG[,pbO&F#$)hhhՇcY΁Ɠm7K<9ɟw᫝8Gc'h4P/h4QE9F1Mn]z-_Zks}1Lɮ'Al.9Ā#>CSh,KzY*&X+"4X;EU[jU%2r{Y#"?y4\6J%i%$a0 ,H#h5nS+j:~= Mv銵vrG[ QxpP!sb"WCbaU8WF鯝 MD^р&+@DfDV8MhI:XHP<@&;no /1/W.˓l耶T-BBL60w ):A!hCO풀M*7 F#I/ѴC5mԱ3!αKUz^I1zsLod7 ST#aU"#ϖl\Ŕ1 'BW1qqoű6qXk!?ge?^{GfvQnr3/L. "zDjψGBU["$5Hw}LJOhT1=#U<3sWQr'm`nu'I &:;uQJx֕XO2Q#8ay"L:le Ψ|tf3syՈIƵ:Cꔵh$Vds # =!jQ 2*:<%A F}Gl%zrF۰٫omg8وـz#nKP*FlI)LP@Igć,3ArȾǬpnVA!mT -ݔ*ƕ[׍i8l|tuwAW/r@5yWwN H3d4NIeJ"3A$0U$Jl$ ;a$=4+Q;Pu R@ 5b`+%#;ul؉bRjfumOCGjG]#kC4o/x&4((,14nWhCz _ ޣt yw2 j]2?:a=j.XtP A$R۰s{RVa:3m$ڎ M ]17ܐ93i#+ =I_c 8jY(9(&hJP&hAã-Q#ޙ2&Zɹupkgx2pQlz2;E:9;aڱSyO)Pi%ФXPa ҅oQ#DB1g&jiQm7=c#)!H#2E.)Q,mdJ#6댘n*MI)=Spx0S * e3!u$ Rd/I &Jn䢸DG-00\wdb%A"Bca4UZxFdl|LQ0A=?{?I,7&ջݪ8mS7@Df.9zs'ljc¥2X#%qH%!ط*FA_CDmaiJ>X\„U HqO<¨98epk| CWo> 6];x3Jy ׄHjȾF6=@ʄ$D8o9ⲧDA8s rd GF7]kw%.WNh!Gpf-iKQ*FCt$Dak%J-WCLIV;@:`@SæIYEIrѺwxP:w םLw~ޑj4i'$3;T1RcB$&}JHűs{o^^Q<z0дѢBG`DT1KRa_SBsMQ)s@͘B~KqĮh >JkOC`oM1ܹc Yއ[SGukZ{SSzgMrZ J䙵✢ݫG?-\%Cb={B;g&4N@zx^gh7=x3h=g ŕ&ф@ '3FxvPm5j4r4c7QC,oDfe$1!a!5M1=h̡ZdRKcFFK0e X: ^&w~ؽʒBa]ӈawL2#sxxK '噦3xX6L+ i \(sl=4XΥVo3 <4ex^W9.h+pR*‰vuyR{(@6g&Nns*$ 4ɵEѶnE@B-@AV8mfI+*292 G&]HGczc%]U?/5?S|𺒾噒2Da5e=H0Fu|6RB DZ^9^IsNpѯeJ̝?UY:Ί`"BoIM'-Tt^nR%[W*%0VBfZ^^UOv$L[J,T*X6Scⷀ{} OKJs<Y"-07/+RnxxJ 3TWgR'+kw*]"+Ԟ8zg,B* kԍG"q"R%:FZ77|"ݺ QX4#\#LL:aeF9Qcf ] VrYE-t<_wa֛~Wi׉k/w\s GcJ#fںM LX#R7l+ajśj뾼ت Ng"ج?BckO7DԮg^d46=F;kwD܏ОRډvdɎ<D'u%י_ &<WO_wy|1+>M!9)d5\8SœVT$-XZƊJFȉw~F`Z$q j]MQim#VT*kד OI| ɤJN3lM$C1t,LTV#Vį2Ln5=44yVMgKzt%I9gz5M7τHV)3Hc%Ш<mkp rt<2aa V fIzC#',qC IDAT|3nZ98xo~_TЋMw[?_*2(cJ v< {P\omP]9YVQ|&ra,UmH59zQge"AZp$ Ja/tMOz>*'n!;Smq:Eh;Z=,W+|B95'߰ku%+DZqy4~|qN{B&Œ[B'CϮ\F#!SF| -;c eY1cm$IuǓ`YfE(be$﵉vD& *-(<YP0fH ˁjP|;U7'Ry mtF9'^ʯO鰲O 7;ow_M'ť+1Eocas wpUYc3gEh s.#:_7NL(₤n(f&Di6v>1#3Sc9l#{!EtMm '|ag8c!M^JNRJ|zqfD P+. {&F#mh.Vjid7sy&i`J A]6Kpj略bɘá"r{r>p~Mx=/nٰqn*H%9SE9Cϱl-"uO9ؙ1\ddzZT` X1x{wo[S>^>P43id`9O[9qoD}*v*\$|v3%MBz.1 mQ*:3AWܩj2 P<ƜB<;-ʡ)m`n\+5cun4HqY\N9[in?/۟OOvIJ|ӄ+de<~V q#2]UCoNĵ7R#2drK$ Ք 0+Yoqt6|LqmC^$.'}JL7,mT*Svhhrr8{Ɠ_"[7ٵ֛ϔixrzqx?OwV.M*|&< w|zܿw_w~ߏlMw>V](ڂ`.9cC-lڂk\aX8ټR?˻_俸Ab|]y XsîcvUfuF1cѮ",[Jo!'xxs;7օb3󛅵$2˜i.} R:N9;65.+ʥV~xO [>PyB9mٻ*:(&̅˱\1 _\q2iwüwb?oy;ߌkv+O}ɼZb8%ntMnc])){cٜn~UN |+U]BݬYK  qJemo? uYޗ0 Z_Wo]( skQv99vYɌG?俰 ƿQceyo y?\ypupy4olO[L ߿/)oM/^W{.n70쯃S>Λf|&}a x~5\O­E8o/+o~H'n= ؚ_~@߯.Ow8՟_ {;%s$<\?};?&K'/G߳xs|?yNOk G~Uq?F |Ww%+ 4Gw~`[߇^x9^x9^x9^x9^x9^vOJt2\IENDB`robocode/robocode/resources/images/explosion/explosion2-7.png0000644000175000017500000000307610205417702023717 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%(IDATxo\WoOc'IǨ+% 96*peQV q]vϦJBiP"$r S;.PuC Ot's{ADDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDZk/õ/p_b` ֮,x'm~n.-' @_Lk>|0Yv(e>19PJ·mlϘT8̓,AlN!Hɞ&iT-zN7,)Q:Ҧ^k21XPMšFMabKGD pHYs  tIME&AbIDATx]oזwUuWݦ|!> ̃s  P5.s \eh  +X4EQUnH٢j[]k^ZkZkZkZkZk-7y-#/cx|{g&"{9_ 6An=@?8w]'j_C}wB]_Y", 978hܷk?^zsuAn_lH#8Bi +ȷw-bg_+5AnM@{Z xx8ɰ΅pX~υ``$ l< ̶?xPsDx ^eJpszv38>9}=7VnF)?_tM{uE;2_3< pjS?86~v> ىn`+s5w=Z K5ߔU1.}Pp,#Ȕ g+?O'wa)d0+k3w=Ǩ㹻p/xM}M 2Ho@{x7Ma~5Y>DѱB~6wL'yY"7 qܿW%zKW/ Ҟ)&Lkv]Ŀ2Ta5E!x`l`d(Ib&ƚl!Dcs#g;R1C̄oUas?(ӻK&.=֔&|HRd[m gX3#ьrEƤ.&I_#i1 tbD'H{EK< a}`H+ؿj|3ʅ=4S陦T`<"bSgŵ&$I`CYb'P(TfA.p/<~0*@BIVUD2#AM<3>z-.x5`_X314nXc@UxB~! ?G&7;̍8 SajhyzG1 J9 UD@i"剝(Q/er yY_0),fepp9X / Ïy؞z=<2˛}Cya{Z*! X V DgI&N E#'ޟςBR/M7Kna@bݺPP""K"Kϝ3?Xyf֡'*J<`e͢4#jrSVڠY*ԡ`ǝ4|Ǟyz$$%Rщ-oρpI4&n/V> he~H<:|'=iy:_#t>r“X7{%,_m /Zy D{^,)n0p!#BbYⱩNΫw#91X4u3z[1('سzjp00 _j_<:գ:CckxHx~Ca}e"ʅ ߱덀:謖|)kRMlc)<(rks y%VTʡ3Y4D|'YFc"xw,G? N9"֖i$hzt,PZ9FVg +FtKT'l09aM? | 9{fNwMy ߃GO HtOQl/`U9(js8|HEg=7=v䂩[cTMToKS=rCm$@e_7N(y;>D񿆖)6)$;Ʉ[V bYHSgɭ:W%T6.?jH3%;m_%0:?WK1{OsA )L&!Ax$+FCAJʧX_)C1&L8剺#;+,;["k|{Tr(+~G_ yr(Mkt?iG\C(TEUCd aviC8~v׎-:JTK.Y%BJ.c].73%MIXlV~9eиA-~AxzZkZk kwi@7\snhK_ .J뒡%k-*^a)~ mAȻ|f/뺚òVn[ EmI/z@wVw۳؜f\m Q#mY(rxzq?l#"£KAKU#5jn3<*;M}]E4ޯ+[GowL8́@p[Di䙎=39 rٸ,7@sR&+ӾbK cŴd Quk٤qc=eЅm/fI5߇}w #-*4lw4Bk4 ‹՝B;M$gut&3tnỎ~]bmy>G ɉ&3Ƈzx2땠`\n qcDܑY[Ao74 n~ ~w<8!#8+0ϗX!BC*>*H;R3QT^=Dxݐ]apO1HasM˵e<+J6 V{?!o%jtŵ)4.0s!JKO{掣NC%oB)U rW4/_==]?oK J# [NӰcrk(f!H-%s+-9ZvB &7eGAϕ LJ#I A"@X/ZrkOn9B ׭U*T;[Ks$XW_ 7<|Z|O|ym;igO\Mj(. 24ԸYqzf[? <¶anثgFa0 ;xo>Kdh^ˠW ]YC9vKI8 ;>4yH o0:_`ؑwmUgX:;6,t7; 7 NsO$$FEEI\al wmz1D&S L ~om&lmOB QǺ9(vRaVuf<7\cϳK\Kϯ\o5 B\N8IY.saR:YP: $ . ~KGGƒ|Ï>+\s/}Mܱ^%U3_* Vʣ~]e(Gua#_OLgHl,UgYصSPQMl+~v""*{Z-hqTYl sαXڿ`Z2 4ۓB%""Â/6 o K'{[ɰTkZkoj~R9IENDB`robocode/robocode/resources/images/explosion/explosion2-9.png0000644000175000017500000000360510205417702023717 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%jIDATxo]W>}GMq^M"Q!Z B9 !!!0`? ňA' %j&qnhIu p5ca׶v)Ӌ/8vy?͐(6/ -9RQh?=2 T7w%{yHHÕW 5?`v!F;tdyN~{I sS|^}CnV'#Z6b<#G%m_89n"7ZkZ$AK\NǼW8",^ofu,z!hpB4˶ŽT}'ۢkIfYJBR`/`!$yLf2+TFou(87YJxO ?7}f挍5pCד%T;3Wa wPʊxi1r өpI!߂S9pUK,g圬leFα~*w:L߆SD{._%YH̏3nZ͎O|"W>?#Ms&oDdov%X2Ɩ$ h@ gZOi C猍Cdm̓Zv'!`߮= gҙ,y\;A9rv+ Z `KmAՉctеhA؀[ u&04sRzV+rE5@qgZ;cUeh$(e#&־H^I܋,xn)xx|? D*nh(|Fz'(exz!aR2YRH\(Q$AswBZv l{Yu FNFwr~&P'ǧ]$--}O{ȎI`;)CCq6C)t[q1W1թZ #]4 ?SU u}=¹X sٚgZ{ڵ2`oڬb7=ImlIENDB`robocode/robocode/resources/images/explosion/explosion2-8.png0000644000175000017500000000331610205417702023715 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%儒[IDATxog;'6qGJU,U%‘s6'nPoKEUQGjB~vzÉ">vig<qŢuޛk; Ͼ\` Y01na&*%pղoxPp81?3Sd$Qs5Vtg=ȒJYrY­ !+ Y.x7qq}0K͒1spǕ^f'=Dń6"A (mi0NC,%$fiML`9O=L +`5{fx^gxdV@6yw"֖#u^O/dn_%jֱGl_Y4Kw~Q8pWe؉iEwَ̹1iga3@$.0=i&`8Lg x8F(aL;omutu\KÙ #cr n-&M&0 |'~t "_9L'm mg]]iW^ NӸr}Y_o3X~B+9Io͵ϥbG]6;*\Œ&<\JbL/.< 4s_7@\笝:+ 2qjKj`W=gGYml{wt )me3ӄ5qB{{0+U0a>KSёƛ^A#vc?&Sno ܂?w8ξۀ4Zఋ W#K4`c@v6Qkk[ ܿ1rRI;6ރOOvkT)K 9Gl1߹ <8UJEu}/3 DB,T7ᣯ8mwTZH\c-V ﺳ>F7qPZ['aן/9@FL-ltqϽ9WY VV&"o`Γ0G۷nbsLmkMcf\a1rjeϓ?#K@K@ 0ܽ0H!syQs72vFCР}+F S%-a01G"N|z?LHX>]l0r2(ϐd nÍ[z}sfvrkƞ-)_Efxy!}IENDB`robocode/robocode/resources/images/explosion/explosion2-38.png0000644000175000017500000002761210205417702024005 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%2&Z IDATxُ}yw9k,f4"!VBlLrAKLhLFIlv<#%ZdRS\"Y۩:ۻ=\a۲cb~9E}AHCS$! ^| 9Y ) YΧT+,v$8 |wR+s :`nk@%Aw$i%I.ڂ/:]wpqV GZ Xg/ I&hצ$mTE HcC )cWA*O(.$1êU)}>YJ&Q`'%{e^ܺm*5@ƞ UIޕP1 Qȃe8J %pc$*}AqQZP(N =<]Bk*t=kUw)ڝBD;gX{\;GxXbwޔ`* L If NنuLɝ`#^ &ℊXL2' UpÊ+8+H^,X t)3ɽ`~x$'"&M/M-g*WH})c\m-"i֓x&z, ڿc IA +iˀ\J*@+qdёބ5I7`s2 tMylVB g/+:cV%(Y-U bw2`cM{lXج4˔aĭ2!t 2ZhE|Nցזa9EFv_v UȐb -ӖR#FW$^ `,^ 먜(`+.@[3s i2͹9\`5HZ=W?cR{O~ jQVgb7G%cTC%N01IN3qs ]RW"TSE"QXE `_A;] DI>(0ȡ9u`@'Li =A1 F%%Tx:ڼRL^@:쐔3jL ip!$,y8LIT΄ p<\"*l 8"i;'FEPf#/_Epm<)C ,$Љ%AF wԛQY(ͤ@C(G؜"Th#:A Sq g؁2',b)>rz\5np,^{A& րBRރ°Z &=9 «|nVpjNgkU# bI\] ,@h66@h8[FEi0UmBJahE5ȴ^Xb8cf$gp7x#' ^19lx7p9z>7 "K&h6v.:s}`)Dpn Z5c=6K@ՈTs˞y8̉x?&ʩ1qnRK<6p X^sWq.M@.ZVn9.]? Ʉ/|PxW`z9q}[$3zbFxYmXY9-5@ +hrc o0EIS菠?`7LuЏLW4=ݪP7@QF|>@E%NΦAnJS1Ukڦ>*alDTK0AK4k1չkaj$ħ}O10 ,6u& w촠 ɈE]#vDϔ\ZsO ּyG/_PLv[<-LTwyG"URWN@o25> t/|r;0Hi00<iсGUͿ7~q mszj[? 75/*b։5i-Vm 0/X XI/.At^`Y6{瀗F~s4uo$\7iyݘ&'9ĺȸ22[NNXiS_u+ &1%]LU?,%/$d- i{͗l7Q:L4:܈n~hcl(DEXWNbI# &lpC. kUBֈxʶɂ&2)maY^[j7hN7NҤ0gwm}m){͹Y#Us 3Ͳ,2݅cNޣg,]"->ijzIƪ$\Aϯ낻@ΰ'G\ |i?yN\K/xzwFF5OQYG֘vaBLy7F1W0)E -x'U1\l ï8]@jkُ2/qhqG1A[ܚUJnsٺqb>t.i3GN"𦃬 떨[Ӌ<Ӗf?ko\!n M``8r7H> dc*/IeZp +-X_Rќ]}_e!HT o1¸b[~KU›[7.K<_V.%9K3T&&adDJW`mH~a"8%:z?(%X04lXM9WH\ɻoޱ3Mp@"7_u3%An#O/o'[ DQ ۳ݵmsg ίU!+)IL,|(;,ل+6׼%jm=i Ug+zJZ yxio K;pKNjs D-@(^."dBE%RZQt1ɜ-q}=;j>fuY+s}xOבE=+tmyDےw7%/? > lKf[H zXHtHSjhGuqMauhrIxJM5M-U?x"mz EN< =:N5!yd"Ն!)-º> DL"}\sΓL'K`K8j$=)j|iWKΗlg]B#b2],Yy'e~+o#A9" 48$DT|ZAl\ep10?hҴN㸮57IɲڬmMjHF6ΧXS\b+GO<rs$x2I>Q""$ mFeږz=,bh,69e,ךk4_>(Gu0ַ"k S]Jrs4 nK^_HUGOSI*ƹQzFA/5Y>>VTp4Ga(; 0.yo0)aX~Y4^Ȣjv밶sP2[oaL"vI<DJm)=UgQ>~L,JnΗxڴhcm-Տ<Է)9+Dh)AIJ+X\ORG=yy*A޼U !$A"Bi'kahXuu jޯr.),Dyn 2ԝmA_2 h9w9MT5/jKSr^…b I 7ҿ)֫<#?aVC_el@ئ7-N8,!]@(kXOÓ34v} p$u\B(n_w؂ ")Mq!S`側[~U3dz47 O|wV(0ƅP: mX4NZ.gQ=` \T^lMy`/RX]01AG +,XSn\3V ŋރܳUQZOrb1RjLC3ԧKT.`f+o}VXAjfWE &Un>ĔSaOLCm^@e \AMaPG 2L}$y?mk)# &5;nU!U<)_A!>|՛H;莈&2 l~ry{<7saK8G!.Svc'7 BƃߨGY;z:E Qn߹: WcwR}Z"÷rZG<) ] C &$=M9A,p3 ȹJ~ 0 Y9HJ ]w=:8A;!Ke6-ZC#2SP\yB x A|BR"IJIbʏl"#\u^37L̊=4DG!MD1$MX BG]c>B珰fYgxXZ~od| b%b.qDR).>"Z.X{olkA!蓦/pO M0*}tG$&e9`lo;OIЌ(L΁H EJVa9tY(7kMF,~N0g j܅N,#d;zVYȈ-|͎yG TL2} ?A31Dӌ"c.V.qK fe6k4YTթkU2l4FDŘ.+Sm;;s( pV'GrH5҉706e7`h.0Y85k \B l> x31Ngkƒn`cNj0N~B= i[2TaA)^^~0}:>K1SG Gp}E fq2%?f{qRIWbvRA!^&S3z+_0`綌F4N<Lez8ɹc=#;Xtq)_(&Nt3 Ӓ ]^RSEsw˥k 75v*8(c3)H5T>E*CG(JHruy ⍫nX NI+"@d%}!LރazL0nQosQq< hGEwN&,.iP7.=cWׯG> @/xR=zpt@/>;?-l,lo8f Nu7( de 1Ŗf}TJj v$ǃKv𣇁[{ g=Ez](ukzα =BʄDo <]qy 8A>XbGWmga|W:>*dC؏*".zSc$*-R%Q=A"*}'2L`1V 6K&0T2C25yB*ήcdֆHj=c3%+K%+â 'lg7p?߃f3}_5nmQb׼Gdw0 l_Z/@俅#E<1(~HH.JDs)׌bL'.VyTv ;| MIsPvf=kŞq'0#)$5lv/5/?GL(i@}ps ff0< vNJiWR4ySaàXaq\0\9`Lgfկ0.K Ffn7=(FPpo*6*h2UH3c- n[b1-RUX@GumE IDAT~W,F:6S`6Qd}5ğEP&v߂3F9MK7f6G`R]Q1>â?Igcfi1]RC^F!HU3 cYĜMIlLg#eˍ$>qcaq0校7l9IWs:Uo]w|r?ǫ8sRlJYTw7YڬϥFmbE%k @! "}]O -Ut5&4a&:v8E47cbpahNߵs~I';3pw)/FlRQЭ*Dž˄'4 j-d"ɽ"P&˘Җ}\2 h8тP¶q '=H5d\X8S9p (P!u97h6qyWtY l  ag#fCw0&Q;<*,)eT 0[|zP:1:u_>'۰S"~3Q!Ұ23qsǍ݆|w |q n5'{u3fg#^F0ڭA+, ؛ng36' TnMhR:dRؤcqis|"?b$X!|)dgBw+]}^ߎ{gVfPKgQō6 0>U1 n=_nUxyPsZw9 ͏ tfV{u_8Z6̾Ō-bX%c6"9F:N /gj44GHWjɊG`-L<䓺aR R 13Ӫ//xAU:|>">ͯhFV8\e,1l}9` J''U8 vEƈ^3N*Lriο٢zsUhy Px?`{r+XW!UGEt 7a!m.F*w PvaRz +{Jd1%{CON.;迲Yr STg~q@+ .(\&p#٧c Bwa@7S2̣&Q)9|82@r !|ہVeXL(GG4rBC!N |%)D3GX+,{T~v5{_qStҋh`P۔ŹXD=VxS l0GGK.XN Y)ՐTp=NiW' fʸK.T\BX.C'`zv -tPkR!A*Ȁ$}>r'b(K>O"/Rz'*s,ALɬG$|Sd2  -4-JE1¹.7v'(1xC#d&P~o#ʈ&&vLh0‡A=nxߵD)U5B-*PR#0HgPRza}Cb}@p !&m[2WqDZɋmTȑ%-΁3t3éC'N pz̾ްCP#wcCE"wa OeGj ]hY|u*] ɞÏo\$qj%bgF6F/&E\@) D' 2̦C:pphJCd䀬.BN^J>B9:KZD%=lu %KKf%bSAc(":mES08WxOsY$⋒(~"VtQ|,xJv!J=-ܱ|lD/^ w VN9] 4Fjm QK ֕*;(>x!B@JFɈ|b;Ds>6z,%4 Sg(vCr^,rENVrJ=۔B(_vP: qND9ȠSa'8-qe%qѿ|;+s;>= ϫOHGܐ&Mtr:82*FJ6G a#܈v:˺TV ɣ)BBU- MH)#(TP%s9EJ3Qd(ӈ}5UhW2*2eIp豥p[<߽L0Z>= +<tM> 2COYr . "P(/Ci>cT<ƗR=AS4EyN\ܑeMY1uv RIR%XbB}@LoUu:TQD<%Ǡr%-Ooɲ{{ⓞ׾/ij9橎Ϭ*oHCCLMBb B jBhu 1RSuPHz*aQ!bJ9At[8dc;x`kSra])TؼN=ڂ0h~Lɰ/6I)aR<>%lu<~`K@ICE[U聢XP*aadpK1qU A<w|%|Te( Nr9z .I3܊4w_|v) z_AT'()r-nT &7Q͘jx}5pjໄyL_ ۊ&h6!O4&hZmM.%J}=8YJp*r^ڎvŲXٶx僙:mIGŬ^}scKA1Q ێtߩrV91/?3F|dkU2iK(ԢbB(2EܑqeZϝ9[ltrTr劀5ɲ@W5CkfZ;h ͯf`ؖO^g/ " xU?J*ӑ8l6hٯ}LJF3VeODm1?kj>f111111111111111ӧDC+tHIENDB`robocode/robocode/resources/images/explosion/explosion2-34.png0000644000175000017500000002334510205417702024000 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%.2 IDATxY\ur^g Pd@P*T<W5y$*JŕxlPr$[QD=]%608.CUltt߾;\X`X`X`X`X`X`X`X`X`X`X`XWxO }.җp ^ſyK D!<4*F c%Ȃ\Db0SRʩ ;I%. vSLpF:M23khKx} *BRG8Y mTP2@C`aq1y_%(2 @hPRY@q`Yv[{dz)F?%Uwy383\w?p-ij| cV|zDѫX!} FB! mʟF`.ZHߠ֡ +Y,/7Qn{PXd`KW8'P2B]> +;9⻄vT-OO&4ɱn.\ <k"F+σ~v_ :#vNFHA`#<1a4i4$P+J;-X~8[fV2Ȱ6G@ \T&VBmVB_ ĉ #܄0׭Fq@kH# H6=A<^a#s2{C#T g|-b}Z#ov8+x:@<|%FvaeFF6UQi f1RC'2)`C]熐< gOi$4bNM괲n^~8ybO@8S u~^ 8U}ӕץUVDZܞ4jAFӑ!!KA;9ÝN`}o^$XS( 9B W LWprU> S^u6}̻㕪jVWZ ?Íq[2lRtP.9rA#|USž$R-#\ L~L-Ni pc>VYv唽X)0V{~Vi Yix?Aܬ&ۘ2zJǧ a4@P"&N@Éxc2s ]~!J5ȹŚ{C;MBzV9Grp"D&CUTLoRVqC J_{cO_:5zۡY)f.SX֐6 R))Z| <p1PIuP ,fj@=3TMQL:d!1]&RFු^/_q1Ks]~Q_&puh@-"Xc]:2n'8ZKSN7!BnnCd&t)$g3@#D#Us^eI0G\:9wՒ;ϴ]d*f6±J)™a1 UeXn t\CrCKFoomibdQw䈖p87WE>a0@cL.abDԢ@#*ժ{Vl:w<8<[EOUj[- w y X z'NBxn$ml&>G.&s;]ɴ5UYcsHUhE!:oU>b6df<~$ՏVjć {q gl=B>#ysky/{[8RҮJS5Ujyۯ^TGTvDRTǐ:Cx$"D$n~P#d=<IY `p2`QY^.Sc(Rp.:`WWNP hǚeg&dɂ5h aٙ 'bA}̀>5~ c(XۧYmZVwxJ7h㣀:4S:)L%$twHeB$$EX_jWrn9#dhaU /qv`$ʩJгJ[ f(|k+p`86^}ȍ&n Krw 8 GR8&FG(NTQBPiG%i㚚'0e ,blh4șbJË+F_B!DˀQP o C[Q@}Ѓ5ʽvEW1yIv iTcפmH>aHIR W4B1(b ޓVqHmyT 4UU9ebc@VF/ aH\2#x%aK@j.H$\HE*B_yv"S|}Iܕ-ģFbEٮBx4N@ 'A:HB+9aT$GxP9󰵊b•q|leز;bʓO^zw.5=cOnh(0+(>uIXm@]Rq ?:9]4X SxplQC8[|A`Y3O\szJ D4DOVEQBXX#*h  cDY>2c{P$_\i2+XhHq`P[;60GoEI9`k;qPϷpрTUpU+l9<\B|0oTJ4E{&y\w8dx 6Uդl8} onCA7@1IyTJ]嫞 nu 7G!ɤE'(F!0coly5ţfσXJG! 06I0Xu=l<G/,s}swQ 8n3科sw'v |gp6DHݽFeOW)֫4w֏0U`X{cmMCG<3|١^pq}:Cvpcr(EanSc^߮)|y O <-x==biO#˖Lt1$'Ya._vd?;`]TkHMMO(S'&kwUЪ|y~` 4/Gd6h{Uẕ?lf̡N?qVF+q;GSz8#JR OǫpMUUhe^((<冐.N<.־YˋSɡ^9^\++SmhyK;aVuJU)aJyQaJ+0"1$rS͡?z,byrǞa #^|2|zhgfW#J^VKu,[8_' LYr">ӝ8{@xCrC~q#"и:2U3ЮR޷Ay鈐YC4/J.9/Id3I|uXAMA(@( MfY MDoW|b4@9"|SI3mGCg^]sH䝣:&pOuJ<͟9X%yc8u67akn>.̀;:QȺE1AWK(1h!Xx&5ƂA-B:f(6u댋U |%줊[!??TjWVVXnA]6lC}#`$ t{^W`mB Hbz#eTaYkyG1>_+(z]6=;1ۃM!hy M'C>VL0ES!&8UCI7 iQ>YDCajzmR x+3rc?I3ҊlY}u=Zm݃1 fk(Qj"(Pu'q_n5h}:< b,^OX9rXsa;fܥDT6PmGGǽ><؃[{e} `6QjJݤlL usI0ݞ) P5i5ZFuΰ(CFo}Fy@Z m)+ViA9/j[<*c^6Ji% lNas68M&ҜZggĆj t3| -P{)}EYTYSPϪU9V•_gySr M'˒:A*b!S_C^}G0ʛM2N2&##Sw-v$,ԁRmPDcyo}( l`:141jk\t|}*_z< ZbyF>1B8$*V^vܸJ{Yu:x7j38Cߢ0o!6CͨH1o! ӌkx2\.GЛ`'qj@>Eȍ!DBOSHqU<\z77=qD89M#,32NyPyYV Hdi'ƔUDB2DZRp-$opȮcoH BeMƮq0UP/dQrΉh>d;زx,cqdXfȡ"RAO# 1QwcXp}l3_88X!-|I rik8B@*r!49Y9VSlTch " qoB)Ta=B=]o\~ؚ C 9d7IH*!\:f'*\fIDATbA0<^HLI"9%ayRe wqF=A1. 촥{`Rь==Rv1^D-q>DJmb(&X;³s5K&ؤnuo$3Eau8wƄ)}2g_zba:'x&`'+wr I)٬!lјE߻FDyt7'?kW' E7g<>5,Rt\("R2B΅H "Ê}8i0HawŹV>>!_G)R3O?F6DVFGm98gg$5S5F, pB~>=Ę'78so}Ͻ9A1 -g!Oޟw 93Zݰ< hNpC;haiu31+-Z tR?é=PxG]R3&t_(@?8^ERn1 3B&ɈR<#L"Sb5d8Wm7!3,g3l#Z2x+xs$Du-}ʼn˸E3:!! iT-Zx&#y78!aFdvS$ŘlJds"ivR-&U<5)7ͷi)88`+yaNSmD#ь &(0#jNm$B;4ij}NdX ZBhyK?Sn0s纒'[oG1c԰50$$H(+XY͐vS`6T=\Y3!,$jq$r3N 0DF(~'~/\93 =(hHgg:}i uCp =;C;o:vqKq0.]p\x-mHc)&G10@6@s*)iz1&2٘ ΝwcObsy OmC.+F;(?b<-8 4p3 M$ Az:^ k+<\j3\J8`TtT@1Pǘ0Pg8 drdTisNGkXav%xdvOq+:Q&hFY&Kz՞AϹpW9,jgKͻϞ,5kf)/w|GJG?Gϟ+MHcM";ACCYGF݂iKb]\{\BpZOpq,\abKGD pHYs  tIME$*, MIDATxK%W9'"nGjF)Mc< ݸ1{cÌ^oƸwZxmp ҆D46F]RY7#ED~o5KDVFފ;9q?AIG୛ y;r 8"$hn?n7` t$|a{J.a?G[y޾㹅;Dnudy;" l[?B⟬_̹r08.8xyxn=CaR y+v;c~/}yG^En܉n{7pqW!ϕ7]?>W.$rM& Ee؛MQ=fZZ 'DXaDb Q`5+#k?}1Go_{}G"x(>Bx.#훊\iu7|֭^>`XL\׆u5JV22R) ߅%Kb'Q#|fȭLC+8RDA"Z[`1_\ALJRp&r*,eDS&c !iM*\[BCv0 ;zE* YI筛*r;lm QZ8aeBԇHk ̀iYn kX9h&j UsUcAN0j@fk)AD1rbZѨgVsm.m€ٺ⿾HbN+}eMF!/taƷ T,dE@;ϰl p 6`RH[E^0ƫǠVD 14T$S0n5TDq8x_y%g;$6:}&;\7f~kkHghb/fCۼrZVںҁMV1юfLK ɒ5Ц+hv?- uS~iiH$d'3tmkx'F[A? m70 eITg*@0D֊4" =ۃRʹˊ3\ G2o1M4Ǎ&H[ pڷ;0q}/F֋$5y'ѰB+h,Ц D(cZHd#NI\z"IBZ ᄅqg/dՈ6'$q8I F]F7Po\G`CűBJ+.L2Ʃ MY7);E 'h^[n=T\+ 3P9hb즽ƽH_o {(Q6.l4P iJ (hm*LJ`sXȣay)'?Sml"(n|wHG,(ΨeL Zu7oa 3 \<^ dމg3Ras(irl;&!%$|SXL:ǭ@8 >$hф00ՓޝqЋwg.M@b2]u}@rLH3 Fb%? aPÚnhtt7EU]Fw%i[Xa#nFCN(3ú8$h0 kq #oxn%9ںqQӀo5dR28[QS_4q' 9ƅÐIdd0}\)RLaUOpa $&-XZ-"FgtJ6'yl DfDIg&KKSŇ'– m"g[tْK4Dntច.o2ۋ G.($Đ!j6aHɃ!{ke[FC/8LX %Dk^_5վ'[*U Z O :C{Wo5mn<|8𷋖iAdvg8]zXEYFylOmun DHMPpfWoI/I,^֨ɜh0SkX\l^3.Ro'|>p1ڞh GH.D_} /q"L%ʝ>IS3/aQm~G /g[%C@$h{n2G&8P-["s;Eg)aYyԬ~{w1uĨyg8Mog_< _|{-ł{.X8S3}=`o;^I (mIIl_J4,$[5`xBC(8ỵ\480]xy׀VJZ-Kj$Y mIj^%{:@8gJvINQ<j Ql/Ϫ0A^KZW*\RƊqZ|?6 $[.%qQO Ȝ~.E'W~l&VXeM , .IerZ? _ 1?w>@)"Fۚ&mig08 =BZ1"o "-Kb\#N gT$pQ PW.*h> 6dTڲW:/"v=xZ&ׯ'QKT\`9渂Ӌ Fx|Fv^gU r HI & gA^O(*, /a}1 u~|#W M(Qo0ngHCv̓N+lGĎ'b)״$<praXEW0?CZX;cDN+ڬʒ&U)sy[#Dma\Z|  ;+D/r>?/ZE`p{>tnI@!4T֓<3.p0nnui.yR˕&,]cBxs9[E>=8[c+rFxe KZSۆ-UpT,::AODa_TdΰL ;.lA]ͽ%|4I/>!\ }녳H#awҎP e )QT!WSIn-c;v_,M(b1OHʑM l3':b~H+ \ٜ+O}pf!9| Kes UPTE Hv RO6rd[۷pv [µG WyB*#$Эgf(>Ň;>[_nyW/uotO}týU-]ztp^²c[95.@x*Fb/kػyn~sxu!]uu&7Rj`P4u$MVkIQ(DQqM,`zm$q _L0)7<-<)h``^@.r)MX3%^eMo@*&Fb֟Y9lZc!mP;WbX^}OT5O6>wKP-଄ mY`@=$4g>c%’USb0Qa&CW4-AZW99-%/ >.Zǯ~o5pMaBb3Γi4i1JᵠBwi64ʀTIBn MB Si"OLxc)(">F2kZh)в&kVH5G%o|r O< SՖf"M".&2:ZXz+$[5 4+BhHZ 6'fk$VI Oek֩CR_䯴ɑaۖ} ћGo{,{#!"x%$mLH4jR ќyđ'ݙ99Aao'z8;݅a/W(o.NAT*B Z5wO-}˿,,Bx.EG[ojn*VM,K(HIRDMhMP g"3BrzyabKGD pHYs  tIME$3H IDATxڜ˒$ّ9fyAfM z-\b|z . xZ2-!UUXDf hHG  K_m_!ǣ׫yJ$c{77»^Y"{eًx>M4,|])y]+%<>{sg(n"X k|tTmٿ\}I ..L>_nGgp A?83~?[—}<˅϶krVKSƗ%/GJy?Л O{J-9{\v;_SO 'OSnW%BC8&&v}F$/os۵o~6ː>%9va_<埶Ǘ<(ڃq .l77{Se*-Z\[̒bI;:mrv^oSoUxR.(]pŒM!}^;ՒƿK]oQy}_')WLu9;@} :ӛ%> gs&Ӕ_}6{o)w)o_/BxwaUS"8>7VW",d`.}~|?~؅Uy=Do =\}<,]RE 9ws$A5hviUN]y3+veJNP5X%4:WL N]g?&Kߎkx-'!>&~>l3rmZ4|o~|y/vO=_|!ozy[^ }iJs)>9zq:Go5^ 7{]8l.xN=OC@ 19i2<9;ߜ;~/?B.rI^`HƷnoʼny~ R~Hq`vI7pJ_U ?Vn̛sVggX`ιwu)Vؗo]ݐ'ލbJ VIKu<:Ywdܷ΋XJ\/Á@ڿi/Q^!_W ~=ŲCp{1Re=ij;e´ WJS,, ;B )5 sß+эF& =X-M I0 P85 g}FCjJ`"&T!A(2Ѕ .IBBFs5n_U&i R&MHZeD3x%{VȪ" UpW.] T%| gۃQyt?3“uGJ7qNi{@d" 2#2p)Soǖe C9Yv)][U D){#Ƨ2 fFH$W d8.4#83g%҃}OnpQ&^+/P.w Ld)V)T  U!RA2pu+'1@0)OF+ɡ 95toj>z. n/Gc]} .H.8>7N؇zk݄ߍ*6E(!$F *&[v!΍"r0"+-w"&$"#y3RBz~)3EGM&#ngvW,pZWiW3{$ DP>Ѥ 5|! HAQ&Zɓ Ŧz= ?6?=gS ڍbAdڕπɏue8"c8?.G F} Ŋ }StH LS2a>3S(2S DA34"GAB=1QCY* ոG[G,o+Iy'n,3&`f3Ɓ(*|¥P%7@H j+BIJd+T`0uݸ췜{#yJ,B:)*r,pH5(Ҕ2o$QRFBx@ę#]֍d*8;INm٪x(Qԁ |#dD %h= 8_s~7<a&S @S$TuL<~ QZ74uœl q@goxݖ3?!&>~>y{4P7 g uR-Nlژ1m]I!4"ʰb1B "Bj :jwv|C}^1٭=⋲² 90,I@[b6jyS@]Oԋ&:sTTݗ'oLK'z`M*ISG{ kֹ6u:s<(AHA#S" JQ]6ϲy%qr(v}vp&aTGua׌3y BD!}OHԂ)$TAKq4j'$WG!"}aU'ue2n(μ"k);In!,$ -8ksrԑfS e_r ]-F򒔄L‡!P0'd($f%:d*@"P;%Db [W#2HJNFԛZЫTiYM~ߝeP^asWu #N=}5 ]Q$3ȈAʡ -BӥCvd+a$揀tXac$:~saCA$s'I=GvNݸFtIޝ;I1nCsуkSzTwpbNOF^rƏ5rh8;N?FıQv(XI59έ7_lY?~?ګMyٔ[yFX;k;dYɾ̐1ھ9@Hjvt\WYPLNGٵ+ɪgX.B;%hB5^z{35Ua,I}80ޗѓZ6t!7A!Ldɡt֨Hi S$s<)/Jk`DZrׅrW^.r4Xũ 0 'S&5 d4>`L;zc G(6܍5 Ȝ]N]Cb }pBeQVI;~0P$9aR[@}oo]k Tn IwIDbtK,h oE{{x)fGڑiDtKpiao?D4_e3rbWt6Zb"<Յ@'_*9B@T2qM"Bc ruBZ=5Fw:nf-`@r*#-O#atzvk2o=PO:7u'% >>K&fι&u;~׹;Kp|k\Υ9m]_NP,󄪒64OTF Sp9)ܭaxnÔ%eT =¯ ,:u\^s @ "I1YSF:CvNtIn$;s`}YNN3e2ȒU4$-8`}Z\i}g:s;r^6حLsB5v'7w޹XxzӸru\ّtYl 'xYy֨趲fGZaYHPy-gN.Spi} +]*!ܮFaLY&+M,geTpWO:^pJәxjb䈅FNjˑb Gh,eıLgbN4)cȤz"e]Hyۋ3C5d*4KD1kp,0krsoN_Ii%x:og}ɓ6 #;HC0tӕՕn^:8= NUp_@xr\]KcH+R\N2aݐiı\@cV©_#f taNɠZpNudу6⫭ h$]/}n1ՅYQ6 B!M"} hv9dd?;Y >0N&tGu|7<w%Hid9-urjLuA[tAmdByi#N _ 9.Jz(VB š(L rNR4XMa)5040 V>Y-ht~݆`/ c?v& %:y)kTr+kiZ/9 >J|`Yq;W%8`*8M!oQΕ;5SA2[u?R^+mTU" KLRA4́8!,.G"pF s$:91ܺw zhp%ɰ^>,&.9H7FYpdդoD.p!s ̀,¹k ;GjTCIy9z> v_?<}/_,b_sKΖ$'qi+_{u?BqpqWVP=M6qSۤjsmT?}pè\MU3cnP03iaQd+s|IDDBDU©mAlx[T[}xsvMsGzԃ!,؉Nʺ/AAܮxO. A-xt 8v|C_b?˺Yka~fkdM~<cFi iK}ƳL5YwGO#wcJĽb LXR&U酒6T* eX r"af%=S>8(!aX@mۜ]7 A {DOBL2Zpπ`B8?&&;㨃7pԫqK EaA IDAT%pՔˍݬo _G}?iӛRf7ŜbMwK~9 #K.1qU9L FQCDςKA}B,# 81J]I R:YG ԭLb\7~F=Ugu]U>J|5oU}2zKCp:Zx? _n3a}7/!f>abTJ$iLQhV12 sD1BRI)N Y̠IG1YGǫDF-U6b.`Zpeȃ#IuN DRs ;>9 OɭN[`.Ai ?pnZl4Z8b$pi];&`54yr [+px*3AXRcBšJ®&t/HDQ#Ftz$S&=2b^)-v#J$(krupgI_#V{v謘(*Xل?aN{ @Xr~qypc²} ~??I3'%,](gף}w֣2Q'Pn1"6PxC4Mz,P0\l̟ɞ#,$2⧌9Nk<^aK 6ǍP9J$.YJr:# LIȓmb#,(3Nx] kTBKbp;*Iy+uq&)_CRx\wU dč iKqlQ3[`r[ݢTɃH4ЛvcU9ʍSU>f &4ZQIf%V $D>:# r#> w(ՃޓH.#L1o~.gpckX)U+OJ [Y zk_2u@Ge@%D(SQa/K3\ޟ)q[;L)tWzjUa^I$Q) vѹƶ*x:w>JogP /??޽~P/ d ŋbt sQF-(A#zKItN=ѝ "#払 %cB!'_*KsБjz? lp}',VMlJ+XAL|ڊXl{ytL6V~3Yr/HI篅h,uPv|d,Gz0z*:C 3o'{KЎpmgCxa܅cgack͈ID؅iLJ!|Fedu>Htf%'$fIPur]kVԯ.vɼ!ߢIKaW "q#P hfVŒ)^Px(ilJ։7#phkcٶ9MeSp?FY#wdgA)NEscĬ'2 NG!u%SX /s}ܔ٦gc,)ib'(`E$2xmf4&*v 2K$Я6% ^ kfg 6m~~z21TT>-S tZQJiP5v3SQ&S07 ?ٶ~Z*xmCQwv12 '5݄q%D4 :D-L2Z`֤K-DJr^;#\<SÅg;L'@BYkAёu5:f}Qf{g ~&[{?S.nsUKv߱drNLNðׄR1*6F$9eQC )v ~}? k+XX0v]S 40BT?UԪ]' aQ,h '`q 9I ֑9޿} vӨu<֗ɳRyps,I$7µ+MLi;%Ӱz]mZ uLY?]"`%F̷(V HL,2LׂP⦠FS+\'C^8Lit+lNqpmŋ=q2R48HTYɾ#ܐ#ERdi:KGk꾵7˹9)gN9ǫYp4hܾH98P5(|eߎeu[+">dfUj# \ a`_~GsS!̗̍B QKT?ŊUl UEfgfb}`hK<[9 6/8o$8 ɕ^:s'wCQGiF#m*҂R,PU}j/,._jpB I9`)dNi~+=R s0n tǖ:йm|8hax @A3C-bFDoq_z5hCpzpȡ}tuA_G@O#E,O0???G?"%=) ŭ=0 7ILѝ1|iZ+xwpl7s3;z=M>/:_|X1Z5lt!TydH%YFO[zbԯU%:LJa)c`]8< [C v^o  4,k.i] ,eZ#t'3";BG^ƎCY*()b 7;7{l78ܒ򫛚"w56*M梫zz[{'}cg>`ܸW?@c <#l5~`J3=[CaCkRA7|V/no[VK+H&ɍĘ4E#DT&' *D 6qZȅK:a<2Gy8Y4h8Ӻ) LJ~$5(8.7d ǖM4$;WuuԹ(F+մk&s)E5i`^ⓤJLxJAXB&)+gM"J-:ـoUX6! ?oN3DJ?›8biȸQ9[i\ k< ljeO]%:/h;:߷jf͓:_~W~e3>5NKO0fȓ9ĺRDz=Oi,enMԹYRss3F>lcWĭ|y E3fIn8^s½g~C5pH(ְ8lsJWY 7tu AwPpBz6BӬ)=Ćr 5rf |38?7>ML’4(?|ȞIFrŹDF,B-32Y%Geq$(͹;WVt~V>jV&ܵ!ٛh>[ jںN2;y\ E4AH>:PܰZ(Elb34xwOeՉ{ĸ9ep8wjp+o ~$XgK'ʪtQE9J${Y5@jBn엤2%#^k^CCû@Y/EY\p5N-hĝRt> jZF"`PEk18l-ܳ,[ΛυR?9Q{@}4(*.E&]X"pɲx+M ;%j hq"ُCo|{ ;py_?Cx3A),tĔeqYf{VF*R(PPb<[j}˶Kf`[(͓:N@_mb8^gQ(5O`J.܉ !qφT_ r`XK~?&)iH,)fy)DbkfWgĥF(QbɭRTxM ξ8ӿNqI|s._<% ˋߤWs _ï_ æQK!֊<Պ M-⺠2R#^adzad;CzΫ0Zs^;Q$[V&lXbHF]HBXc53SK"dJB&;ťP{WQ]'cك/;y)DE Xj 1 եP N!l8 b.E9z u1p9vطETE (<;/PɍVx0e{U)qʪ5b_XeePB ˖=J@ =8K91X1m{ .Gx_"pL%X?OA`z+Z{]}K&%+L6{.|ǘ!ӂJm9܃y8J\*pVeβ-E'v\qwUSG a* k`-=J eE[υ[V~p{X4ZmAeօs}zag^YݔEc~a~t֮87h`v;`V*$= N-8ro,%5cnAwp6jpY,IjJ%qr鼞Z8QNr$1#L3 g?9.Q^6ܞ uy!dHYUL)&LTSJ'Ӄ2ʺ˒ Yι\b)[;^ zj*[ӝsAL,mBR5+.ЕԘ_/F gSC wJu{}M_e1(7l7xPpdi*9XQ6{޻,UwIhtl@dv͑8 x,;L JgA" |'Ò^:5oH́5XHxACf8 Of.}8+vcit2)8نX׆ IDAȚO>CK̬9dr$d?KP~_?wv\;܇ 3SؗróffBCpiƋ:nA}1kUQ#ViWhuj\Ue,e/|1k v$g1G<'i7SAQx-)=˘1ǯ{ue);`^J2^3UdjwI'i!>ixyjGw">|Hͻ9w;?&sPϊV!:~-5s#L2Cp<\kdqeW} x-{Sîs㯂w9W^2({ >h>X.Ƙ2!Q+^\fe`x9AC&!9Wt1F*K8B;6dr:geH7>R6x"z6U_ck|$\U `)t >B٦,ב/&~笛6l}_ HpJ"N4M!A^V$9Ԣ 9V6-}/3J_ϻ~ђ?߳2@8LuA-W#?1ɤ\<~5'vAˑڼ>;;_>cζTe\<菚GHzCUZS/cy{9( xwp~C6१/%ն5ۯTm/-=s)"YxdxfLӔENC*>5FTFQC2N,Sly,XTtL,8NwaQug A}{ ZM]]a',HQ4wքo yN W 'qzqzspnV?ʈN廗UqxU6/x;Bl PL<<*\d\xCk6`S ԞE6>APc Y@dZV%9H^od`k[|c~VGiӞ-@57&<&]ڋ)v4dkHų~R_Nv5L%([>$F6Vi;C'Aٕx2m\ ),%#߂y8/竄spdzƼQg a%N!aog'f\b-lB9EOZMg`u8X b42Ѡhg'8l+0Zuűkq{[OC O| Tqc]hQ%5 -zNݟʵپ߷`Ivl88h:p8䵨8!RpYJTJT)YI϶,hi>UaCǑb>RMC{NzJf\vɆeI7k+h͢Sf\mgl ղ'`--L[ay:!ܚƅ޾ʁwioZc|tb;q+VXT o3$ uӫЊaqӼ, Z`/yeҒX ^1XF 1_^IoãpEЬeڮX7Lk%cctgh z+V K()9`:{ҲB -\5Xs $3>[{n/o]8\<?: x~FFi{66gXfx-/#n7|4E~DCs?u5Qwˇ{1'Vꎑ " S4 r1ul w.v%7k5b 5pYKj*gz~ A2y;܀JVŃFܾ;> NyYC:zKx!?}>1OrH+/x9ra!j ¡kunߜ^/7[/>t|+yƛ&x/d -irUK1lE) - =aN[j,s2'o 4{}tzpIjwp6F^'mxAʽ+E:+E*Kmc%B)y&Ҹb45ZGbmV(?FXe-CYB3c9,cc23y))t82JbySҒ5kw C<A1kxJIs9Zri9vE)pԫѬĸjRm+ډigY({ҽ`u8~8)*iUY;x#!V*8Lt*Y "zQ'ѵ(Ku>oJ O6|\A4 5 Ce;RmXxѧ`eJ%o%x6A#Ш Ԡ>vJWE+ny75*1߬PG1n%µLG·t?{S".[keߔ/+؝rVes6?)}Rt!p59KqEQFX[ Z(*O@[;=emtoM< x )7P9N)XIiJyRtPw\Rgpq86Agxfsi`X+I޼I*Hག֜6c l┻Axffy$:jn~ g?v@8W+H鑪1,3ʞR"9lsX[UJ)Fnyꎊj/yի_ _Z~9bwzorj:KwQB<~Gni&#ǽqlla☣GݔH}^`a Qz ma7X!84.ٚcsOm.>#|#go}ICoϛ Z)ΥGw.kpd<%UG v*VXnX&a8"i5-HlL kULO,p<痔@g%% +FX&99k#jC)J ! KsgEV@[!xƳ(i-pg7yss34`ϋ6(O_:-y9` %R-Pw*,۠2]97W֒U(:hn]"N -S7RFآaj-lWҰ p)K?[ 6/N__kcJͮJ]vy4f>;VHCYt$dFN݌G1F ֛l 8(pYHu|wOǛ _}½ ) Ǭ $.Q(Y^h`Hq 4Ona);NcT@XBY(TV4쒑)JIwx6njpy$@܈{HUŧE̶:f NXϘz5h<4$Yshƹ!yƦbq^N=US׷υu/._ x R?vpi3\= 9'Fdz_#Y=b!!M(i@P)NN:E)-W+wWLR%?x wAN=5ADR$&\Bɂ_iva<:V7iw"d:3޼~h#%;Tku|( ƾ%M$, F eY7?j]>נٍZ|t 9$%R;EVdyry-aFl\[)p|TeQgDʴd !Ai8>uT?N(Rl&Â9'B*.Lh8)81PK ^IDAT L̻Dv =+Ԃs)).2Bu@S7yiNmNR &'Av0x#_boRm 7MӍʖk!rZVj9jE͐ڽ֩` 8^?PPڠk?[gߌY{V]Tjc IiVs(z]DQ7h&JYEbˈisuP-kiKnsjВuq6D()RNv3ɐ cmBpJɝe4LU*2Ԕs33JQ_6̱x3}pg- lL ;[@b}$_YČfO*}9GjƇoNdVh>$R+ 4m bAClS &mA$3+ܔxމzs$ ^n_6 zᎰ6oc/{ _ʹ\G b@wWyN,?:p?&sH=XAA{ss LXy(^VVƒ;o^ax?"G[}DNgݞ 9ViB'}[EoW FEbe7UN$ᗅ.ۢΥ 8E`/v=Y{V8//#/u'gttcbb.`X)Зr̬{D~[k@ߞ73phᏢRʲASw6#}ϟ{v`}b#?:B8wBę_Ucqe,)" -_GEa_NFu|v <w G#f1f3e7*7Wn/\".Db6GGo r/U_~~~_>6w;;{eִso/ojsy77]GϿ i^czZ/pJ yܾn`|u_,nBi Ͷl?n[L¿q_W0V v_.fw.amjgXHXf\O{p܇<(^K՗Wk&Q|U@?McC ݈tsT >+>C[ծ2_ aQv9S__C<7 ko߸jzg?u`9FBS}g26!NaVj$%WR@IENDB`robocode/robocode/resources/images/explosion/explosion2-45.png0000644000175000017500000004201110205417702023771 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%9Y} IDATxɏgWvÛ~sDdsbr(UdVZ*[. p^tjmxkPµa/,@dWRK*IdU$Lo~e QUL2 9z}^_z}^_? k?` WZaq"=8^\._\ QWN]pO[E¹}ɬjZ>xv {a(m*?6%_)_A•(Bܾ,$7 qVC_d k±˖kx+!x+W$[{"~-BqoS-c8i a=0%Ξ7X8]WY ٯKǼx秀K/_lOQ?a4c؛a ƺ 'G WyA1ʱut=!QR ޥ 8%/Qreox0`L(SKuoTV0\{{ZQS}cp=SA\ ?>as ebqDS O5W0*^"%dEo?,g=m ?V<3,W)O5KЧ<=1A!ΎIR>3jLRkxwH[9^/1/Mp-IVh :ڣ {VpJ6ӳ#IqWro83NPFQ!hܜqQؐ ?MõkIBWoFc[Hb=ʳL3hd-3D~*@=7B$=|3D13Ρl`n0(uveh-P4`c1dD'~+ hIVx&: -xaY 12јڿPrQ)?tm*ַxI~@𚧛mRJ59HJMs@LI=Ȟb MG, D 2F1»N  Zl0gyy67Y4G#(GXcPj]Ip?#7 K_)(|!ITV12K2VkoudFZ\eqHSE^@n}tvV% q6z %f1G[ H6V,kEMViDz'kMV$IGvBqb 877@1΍H6acXحaf̚ghc&"٧89'3%A"8+ 8IeTVh`kHÔ ycRe4B47[Sf;6^оFU)TU7lN% #Oc*!A!!D,QT>XYCnF!mEAxb4& R&|\ 9XTR)MDT}#ю*- 'dBwP)4J׌lc=F{=,l6ϩ>YRὣ<x^wqWG M`«+ϒߤ/bskv'dN[%X!1 3<'h1ĻG& b$])$,=ܭi&吙btGGr Om KU/Ba׈D\K Գx2If "ٚHҏv ڣmIYX><'|%-عf^'  GgI.bNnF4+x{2^C9B Qb}sxaO aUa FsI@P)[X59fQO5 |`'ZǸ@=c x F9JR,ӼC <_=KGRoP,wI\Me(;JfʶhAUUW'x~K:G):N ! ^o#?)P/&H{`ĺ|+ hNe,ιN=$< aK{Ey,qv 45;iH7X6A/R}l=PC.YpPuI vH1y+̪e+sæ66[83ܓ$\\KВE/{~m?YM#E{XQ;|)(p}[T-sy 2IQ ( ƂP9&DցP0c> 4@cJ_%F_K'&$( Q>d *X"#(adspc!S<(,=Y*)@LzpL* PK<9\EL%~vVg%$ld Tؽf+ rI>C*& X7%SA$H8.aAۀ{KhkXNuT ^c;9pFsO%VY1=KZZc|VՌ<ƫoU z+M<;wA|c ç@Ʀp~"E "C?B򅄞Ilx. ) L*(-HZA1Q͂{:8^t5X q9B 0!=` 88wEkD#؇g} 1Z' !٘ n^|0I Nb^K U6RK O?ZZ`ɣD0=` `e&0*9$&Fda5Sҁm I8 lNyz)Ї?䌖8jI:^+1#'䗍@ ZIDY(̪N4&kp ~;Q8I7w($ QeT<~[O(s9A pD@>.!QЗ=BBG;*CC=lp_.(L@bmmTlu'̘w6\WW>Vx(ݻ1S&Ӕ}գN3EBi@lFfU%c%d:97RT#:iQh/5BE>ђT sZ@SUB怍AEHSf';Пy\ʶlI/b)>K.CKeh^ل Q*2w4$i( )(Tw ux[G!SN &'[?WQЫLҝ= ^Ë`ÇpQ Cc.Q)C#<\̍+' X Y-9'$Vd8}FƗnscqL*~ 3otov׈N48,>{na>|3ZU H%Pbn >7T|;d I=Ǖ5>%x|%'Zpe:(_.B!]/ W?zU '.Cɹbn1]7X9|BM)E&0{oLn&ި5po^+xqvu"1t^-M0l|;c#+T\H+nא6ߺj|v%L<޾"x[h%dWcu Ki J >C &Q9}L0#stU) \D8;jѷC{v"( /8qwB}lJL4`;TX ^r- o|6|_r~ΙGfa=oQ K4._DNBoT+4< pQeu-۷_ >eR.IF=S^ώ.shV}lyX9~?piO^pNWפ˄@a|BN"žC0ӐIHZ`/ QG^E*xFAwHPà%/a MxѤ85%Qd:i&wq*_{$T-ۂ_pJ?dۊjRM3 S)Y2 psYI[wU#[wAN˰I,\w_IMҌH6ߡ2X}2CSjJ 8W9n'Y=kHϣi?o\M[Q<G'T˔ͼ1XQ^hv11D:X y*;&J ⮮:>kN:GrRb p[}0渺yDits)yX@Sgy-s/V%G)ykW2+ap%L9Ѩ>FNHN@Nx!0>xPw: E"yX^'e]ΣEg<k8Rp\݃/}RbJX&%ݲ{Ȼ+S {EY)PiI%{xIq$ {w6قUhȎ/Nj[1*X^Y$^G F$l1!Oa?,ҟ65 ±7< ԏ_`J:i(!ƎAQ %;@Pk1Gt;s "@߯"Z Dz)ؖig }q4AR5u_UsTS /v>'H 'vP}.]sR -;–?0;RIpmthn04t<33FP&%<Џ Ղ`s)X1MHF،%4ާAԎqo%ۜQCuAp5[S Q鸏䔕Whx5fFQ%kYj$*aRLɔ$[*^%' .lM Q+Da5)%!+o{w cM-ӑGaƛ!:./:L`G7߯N]Ftr wˎ)~ ئ1zهj,ch,aYEh0JL#sR0ԒR/T|00E)ɜ:RB!BR{gSp )Uղ#L:iKhAAm=`&;X~ a>1Fa6ҽ}9C#jvjBX0VAJBٴXXFbI\~\ p^ X0Ӹ )3*]NwiE(UG(۱`عQN[t2m]r*OE-)\(e-] H[ fMJ } MޅyVJ{"x586ʃ>BRʭokM(ЪIL_k*µtX']J.*X1zK lkڠlj*sL4'^&X-`sԞ9jՐF4XoQ#xa0̑2CY6P eïQSp>ᄥKMxIm; ʎ/ҧj`夷$E[/kTGaI#Wu춣 OeP51 sa!VͱzUg+?ἡGXDs\#mw߁^`!(jN^auJrjUeB݄Q 8k{?>AW|:kݱPS0$4cbPWAN{52 T5JBDH}A]8v 9gMǿy?٪`k7^\[LdE,+)>ª;TY*LVD6<ok@.;/_I609Z0:\0t3DwR e=Je@vIYrּQrg>Ǩ]p#aQ͑z6Ӱays.-F'*uYuze9SI~'h3M^N;!C-3"<};M>e3iVd ?ٲ|\ћOGV++ZTD$2#T? 8K gwKu&~6,f-x )s3LaD|W#!!ѓ3{J4UTZ(r|(YQCsdAc;nwvJQ*PBv KrҐ2aI'%B', 0bD WX`!)}=g,X˒Uɟ_hZW="&jfMgg 4 HIBx;l$_#0n)} ARDm_U4mlTΤ1(C1YvXɼǃc6Df^,Jb|7?Oy#^sAU<55o@; 瞥i 9 d4~x=((y0eig 뼦"z\QByCchI r9@!:gWs֮b!L8^z߾k'57 |`(5>dKl$a8#ȩ0}(fslsr@{CK653NPNG<;~Tx-` 6{adWgjL 6)IJ^}>+~{`!|K;Z0Q,~(Weu{I(͋N=ݣ=4BG~q#xxOI|V;.Ը"#yF{0[OpzDy𚝥'b/^κ|s{QE--S",z sZfmu/>5TvI6&uW|rw>(kϠd\Re$.D1-%?}U6+#}``2xkQjkjI8on .?C(q2 ժM^wD%tEsRUԮ}ꡏ[)Wdy1A* !aŐ\5ۚ[/(^Nybc`UHXHUJP)NV4~y܇A5\8L"gFAhVxp8ÃڿڃbEe/&V Bv&=h2]e];<j4Jc ɸD IEM-?fmN2*`T@oF=8Faל2S?G%e/V4~{f\{O){8ETi!7G ގxa wWBZJM,R[ K[t3+3<FYeGmŬM' V޶=G[K :[[")A wdڡ'P׉B*Sd#{`f0P| uWB LqP>[Қ:^J6=GDfUI5#5a 0I ?MnI繶Dwmɥt~ӱ.O,BxB8NG84HR9gЏs x!` x1OȪ7ΠcLlÞӌzys%8N-(lor[N ѵaوy'P7DcTf^94'fTrHuT8|v p ]» pCp34SF /ϑ1'g/>R̆ Äu WXcsݤKxǧVXRTF*n<Nf Oys\3=L99 |{jwt1J(/G0ۃ jgØWD(B{{~i@8,-ŭ<_Zqv`Tp.Kk?JʤE_6/l=)k=Md1. x+v߯N>HtRϭbF29;{HrYmOaw<~7[ XV/:BÒcP0qß$D'x!1&f o%4Vj#h8J82ȴ#qna|v0*p.!'m4-` "1u.Sp 7pw zln`8{._!EIjci)֗<Jf-r`Q[X;7{ hfRA"#p aU,L¬%:VWW܅>*4eB^s.LZ7\CNN)=$ړ;'os7Y=G1=<8͂:]S5}=!!w:T\&4ŨO<ξq~M0 I1t0u"eޞtդm]9; P p n܃58W印᭟O:dnճquh{ݪ$qMeyĐ5X{ ~.ӨYѸ٨!}3}IA}JaB V 4gغ ~\ K!Ka7p 5 3yH RU"PMTtW0v'c7pjz}lRa`Z< {سGߝu&^c(R8,CR+ \Ak2ƅᄄBB2lڀmMn=Lpv7kp(~|9O+FRy@12G h[|{^7SVPژڇ[:h9b[uj="`c @4n+!UQ4Tr9F0-C+ͣ95u="qgIC\Lfp}Jܙ0o£j,q-P!~NA.Ä0HFg%$#{QS6pQK&94McRxvg7O> Ƴ f]L_*#1҆Z(@.^vתYvpk]]C-vᲂܣ%~f (q2aQG$SX#A-`e %];v~5*dN0ג|8I\y%"fa<Kj-N5LaQ(@gXX R{:'qYƅJǛp-P' FS; D%] zNS3۬ȋis6zBPei0+:)0~>IP`'400N-bw+@9!^Č-hDE"rK]q;3p,Y i6 M__Bҗ*{#*{/M(D, 9<\Rb(DRZLmf1SztURؕx P"sql(0gIq",{u=9u ;$ڣNgtqsH BsozZ5x U}a])8k!~YV9^cC(#9"> 7}(mF򨢱2„za;~ WT~N%+ڠ9grЀBȻ(V-Qͦ{UOO3襉1fOm4KӃo V Ǩ6BRʼnP(Bo 5}h֌f=CIi:Gt'}h9}hs6cwݡr![XyHȌx"gTF}ZEpth>ć#ZRc^"1|(tĪGMR1@)c]1J5_nׄm =Ȥ#jGx?@(H%K@mLvRlpC(V0>YZ+k_7XФPp}’[py=?qE6poqE4=|!'dXjEƈ4` G;mVqm&S4Q:Fc6Kb 0ZMFMG..nYF .•ݯI%U݆$H]l4 fd8H2&@ː7ʲ]B\gxN3T`[¬/]ROKwp,dvJAJ'c!,3k<&ˀsn\H#bb4w -"BdfI\y 8  JI%Zs.Dž~= A #vw=QlS0HjkWYQđ=fC$󄓼*̚>N뿪K3h 5;x j&mS1c}hѱ+B " qpP4-lLhS> $W8<qHc̯}iFkS-;S8w!rzˁQm48i@>#&yEݲ30 \@7 QEIÆASèºaT-B)rG]f|"uBCĄ6%IO;+ePиr}8<?YрnHFLjnb94l ۀ^ ="@$YPUS.paA=EÜjV|Pv|3 @5C :y.cIRIb0:9 @.#?9liw^ |(p  *~B=>dQ:(ȴ]IA\h#%ڜY>-ʍ]㍞q~`F囎zlKf|I[ ~5A2@p2R!"dFx?eMK[Ɗ#ig}l |kñg9'5\Ca Sm{ Riƙ)QphW; UVYTU*!2Iw3[<Ӊd+o{݃Rz&ό\)^ZXXBˁǐD2g j4T`qE1i+ƣ[w~0E*Վ#ޞ#xVCǦz._("Pƀr i"FFz?ȬGw‘+)Dg|(dh3e3{ch.([o)qQ%UI*{OCk{sKy .P%Za4C+,dJ\p z '~IDAT sd2Մ"4#'rhi2Nd~vI7^^8W vݿcoCvs2m"+}a˕}菌Z+Y~QIi,:0 _kI*a(x} ;W=[MGIHE:'[SDeCXk:ZIbsgW+g[*{?د.:f -Kڰ,;-']ǻM;Sag,^RتWx? -IENDB`robocode/robocode/resources/images/explosion/explosion2-3.png0000644000175000017500000000216210205417702023706 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME% gIDATxoe3;ťPDPc 'Lě ' '׿MԋƓ 1&^0(D1b (R[Zhvۙc$^LvL0y;3 """"""""""""""""""""""""""""""""""""""""""""""""""""""Z^~؟ Dbix L9,TZ>ֳڴ|:=K6^{덱1)O5(K1f#ULih#vigfٱP-q cU5O5n◩1ӿ$äC1 ˨gqnw~!%fL4a;)v,l(֟%N0 Ёn >#ɦg̘<(']ux?RcTo({Gq8pl ;`p /rcmxF*w] @ ao?B{% P {a Kd'u*\ܦ~Bծa ;=̟!x 6~bzEIæhϓ;͕*n!5r_p-(bu]RZR!fFdqbG-H+gSUqj&ğosHޝ%9OcMX 90 =Ja{' db]"oEt+[Hlh54Lg_9IENDB`robocode/robocode/resources/images/explosion/explosion1-9.png0000644000175000017500000004105010205417702023712 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME$.+T IDATx[lבޙYs!)ꑄM[04>܏l`̋~G1!GV%$\꒙{VVJ0tg:U+G$8/΋8/΋8/΋8/΋8/΋8/΋8o?[@03wN7w2wXIoTx>?~'O~M{e;^Bn3-'*W_׀GeOy!xe]w#>7|[Ƨ7۞#/~s0'gcv2 ?VT}l0w&p v9oyMwx}WGc}rF~ 5? ~nC?tE?VY p>*IBU.ɉl+*55£,O~絟~7x?#߉By?4n^>xn?~P?9KDZ'HidՄZnNQALG f<x˕qpkKI>p1 sB*P30s&^ۑWQL) @oPfȫ>Ȭz` $.Q9#1m6 d"FT (5ZzHAco"h*hli,nV $VV6$nQMX"jIqO'X#X [!U WAL+L+o5/$^/÷w>T#mؠi†s|K;X@ m;vND"Hf Gܢ P y5D\"H8-=!"M,Hj>CG:$h`t"1P &- BӊhXY}vˋ)ݍy%ěWy>idH[WKθKHF.hv旈!r #& Dp$)d/CVkh{B+p K*!Bn@$YhL `R )B͈ jhdq,ƆE#^'"$>p AHQOQhB":#F"$$: c1Ey5^p@zm7|h ȼ9cX|IXR_!}F< Tvg,_n{X`⌘"r7B4ekt p`#2>jh„MB$XoI!2K7ʀ̘(K>]QPo*0VRC!(#|IA{J ` $F4(oآ2tûax0QL0".Xu h"$3 h(M!֞bTy*Tj "<$ 0 6jHR*osw7_=U.&֑y6m [Ɠ!7'p7Ck ~ӇSY0Z/Aʰ IzM,>F!4a4 &GI4WD+fo!iHJ C hiMHh>t2eNj 8^SsCe)q|2a㖍cH^GI~Ӎa08,tYjށa$1B*xrh@DC1 uOՆzpwL11^Fʎ ҺH_栅Ed,5pXEjM,clUo(ߺtZ>lb½61#lG։zW%*x/xGN0.FҩZ;Uã\Sa[NAhPRb%X0[p4`Goj;QEm Bҙģ{6 ZpZWTYR ;U I]Ӄ0^)ᄅK'awPG=c]FC洖v*b:El'tКOt㽳gz :;skZ 4&6mL `+:H}@ido&K?>iBU2 c 'yUc@HmSH!=ߥORam][4҂3&{*-f/Xh:~Q1.1s iwX , Gr@%!jꊶ@[%3Gpffi$GX(TŔA8Q.V_)ᆱ <8v`ܺpfQ-qЁP1S"D^oȭW_\^=xqt( vMe$ [\ KKd1p)HZV)IfDw9Fר ZK90`'0mvМpIi{DhQ=i!tJb= U{Ni6g(ǀSKFmDH:;~^)D^xyvJz!*ٯY-%`Oc!PbF@(„L[J5,9g>J W(BKAv%Dhݘ)5gXQ J'Vg;4 `tizf/#ρ 0@jJ %Vo\9ۻ;;'Ie޾Hx[ #^dA1!xS"dTD`:ZVIrEc.4k!۞hGV*NGj(ƀ藢c‚PQpv1g~I;QjBd?sB&R1ܺ %mj=׋P@9Egr{z~;R+ALp.+Uکkvik'y(.? %D)+tpVV{ :2'P1g:wZ:m[*Oة98|`p/{n8<9lN[9;"Jҁ;krB|Ӏ#A~S w/3ܬp8^NAVW r).t[TG$CJZ5r.% !G(vdPUP`j3|Drc3N{LOE&(y]:RcG'ea X04hs0g+\'ܭ !/FgTn]8^QLjHyU{ot!Ɖm'֯U8 ̭@ǬIj&҄D|Xedb'JФ,@= _!bLP)>4H3wuh,8BSe6ٺ q,7FL9$s#yMgGןkcso*-U39 %1(_}FڴnصAg[nȠ O iSg K,Tw EɟG%YtqE ox# بQbS ::(iz!:R[%L+ S=Ddh\`*Pb(BOdD+Nmt&drE#(1IDAmKMD& u?'Q_>RofǞ4.piI '5 qzH/ $^jw}',aR\:/b҉f_;hBd<ZK,̌^QpFk bQZ%0)MqMVr!Bm:pI>U]38*yy˼^&<Ƞ>/lƝ_6n.C.ܫ{.Ph˳RO{hD nf/J=-nYnXȬsR%&BZ#D 3c VV)&M%5] l F!< !BqXJ%M3FZ\F0&tP(2AI{iuGaN uEܘm v`.+W«?| d絴 OuNo~K[`FeҺQ?1?nWȌ >cHu=z݄C3BrT~ >iR҈2ҎWi#P *-Hlh<7n\m;4$Є f0p wra/&?:ˍ=̜ QRi2 a$S &G8C,-(B4dFbM)Ōg@=9]I3~َϱt[\ed#LPckD57qPh$X(e" `#ISW F$D{W1UYL }r9{ sGqXܕ%%U;1GS㜦I|-w/;tNb% ˺ H+yp(muGK_eHh-/ F#$UWLk=6t D+{WKlۄm IDATu̞PeuGDTz@"ݽQr;TL2"v҂lX w)8;o"!9oyi;sgDY19L ʆE[V%*Hh} \cv`YRZcLHP|J^`v.9v5:3h}'d$ꖦ#ڻvTa][&ԛLDShNRyWWʒI6CZWPG5h4wT BHy-zn =n?qx"m8gJrcncBKRI V{[&II6~;s\#qh[J|mDvUjUF?t"^A`\{,V0=Ǜ" 9=F[N` %P"cQE(A𨸯6y%nyTɺS]:;׮:_A=g?jÏma d=H_GTs%SbJua*44Ky-BZRLuG=6ܜŀ_vFHf"9cܧDj_< 1řKf'D.Qi4ZS4M2SJT"̘:A_]8z b٣YW7ۛ4qi)*aLV%4S}l'e9>MIEpq݂>7Goei"AJK4t1i4k%mC3D Sn{JϐzEQFTҼ-uVu~RV13܅W@d]gBVj*z@G9uqcwyO> 2,W 'jч),HJcK-5e{nA2iHD3+_A>nф,]"~[ XeO4a l]@15DH;@+4YPAZ04T zT OIr@dF҂k2Fefhq(H]z)̑*7L,+-/?:/`ȳ8ZrBnvK=,+ kaPR2t {FM B "YaP%a.4q=` K1EفS Nc_09"#5@`!U^(bB/ψ(r-\=׭Qwz&揞ۻ<lV{8k)r{X9l+:wwU;8_y/x0;BWHk u&B;Չl]@|E\DIP/@ոL_/s9qaH{1'c~$0QsT0Ȩ{#!B& JmAX([eɕkEnRehOAa0a^%̀ w?1F`g4.2\%"֚Y j SY +!+O+"VXΘ Fg r!X}eV3!OcG^n;86A%87sx1Ũ>/e­` 嵷/[Aom5hl YSh}!Q۱pTptDI *PD;$??#y [h%SJX3W:5( "Tdec6pkQL%+έZ|eCa kCW7ԗo!DxFpԡ/PQl$/(4Slg!y6W}vL)*D-Kcva9}PM!R cG -жUwB B@1fLFFd6T{GsƟ3UT:xỵgg4AJX[:hƙG¢Qx-¯.cUhC 2{h= @J olح5&ybя1n!ܤo!wPAҎLjaoz5vU("TiAZ.@cr&X7c+Nw(Lp6_SsyB,e:;G9j>O!n] mFؕ.׶z)KѲU80iNa pz8ۋY!6SBɅJ6+k, m$Z#HjhQymN@nje0$k<K(oܟ Ny(F46Zx9cNS<}ʧt\`f\9 w8 d8u 2_WJ@A"l+|zֺti]k '5zn(PiI"hqO~@Ѯވ8 %UDV(D5f iu{}eꡯd KSӯ CeJ256RWeQkcp*\PJCsR]h 6e[He6Ax DRݲ_6v I'4P"X+3+C-c(r($sV+W^"<|k( '8gLX!EqE*=Jɚ[=N$1tG1nDf_yI,1/=`hn9 N˲/˭ҬHTP[2)UI԰BZ6h3_FΕձ2~%)lıiB$d̤255Ra#VGnQ&C)kPYUL@v‚]ӭ@ua?ir1@oOAX"dX* \+'r7LF<*)^^ +q ?T{<Y+Jb,6+JiձCfZ 6Q&VIGu옽p(b$)U,:Ը&ӲYZTcj;JKImg) z%!][U:5E +F1gJ4@QqFĭudءqs-`• {½I]e: O#+i1"¬ 1 &A׈Rf -QJp&tYE_Kv\6Q^n[}kF1@^揠8/H=$'rFgK H;[.P lSV7 ae_w5CxPx6.8{Fށ*ƙ]jR3vk&,3&rA9̨\da$nd͠5G(%ip!,Mjss l jNvP`=3,l4j l5P(]np\P/ň"M %+G\:XhZ"0yĖ|@PL ;\r?zʄLqɈ #dBE z縞1 ;8;Q3 'g=3]խ+= P\HQKT&;4V5S *AGT,k)5SCj >).k$!-Ɗ:qX&Ru#14¨ե$`BՅ Z f,Ux=6ߓ[jݑvb̡fl|[:|q"darP[Wٴ 쀕c~L:Kv#{+H);3:T)(֠&dB]OM^neDI4پI¥hg5JUv7uDقlqvTFGm"M4͔ymSo8c}ʾO_|xfa; }h-t{aZA -mkzyA{)'aqXcgOPK޴TlT=ѝv3Z&/$bWya0xc72RaV*WhMqDДEB0߃yK@aG9fVkW~CUW+ 'C/wʏ~=27'XyL(!PM8V^j[W.&c+7+ac=6,䧟=JީO*np !ҍI4:tP82:IE<eA/0f#}3LҌOFB󂖉t021p#Y73o31m{b|ovOgx"?8u>x<ù"7Dɺwa~EIDAT& #󝉟>.|̳/_ ;+|6NcåmX'gCsnGk6o?p~+ɛ;4q;)fiAYwCcO1dv屨7$xѷ?}.joLʼn8\;|{#b;m^oA8^;oώG|u;W/r}Sxi ,q{P߹f/Uz 2.{G/߬;p <|w~_(//ܠ?i~Yg7:*N_ص]۵]۵]۵]۵]۵]۵]۵]۵]۵]۵]۵]۵]۵]۵]W~]OIENDB`robocode/robocode/resources/images/explosion/explosion1-13.png0000644000175000017500000006633310205417702024000 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME$2? IDATxļݎdGr33w?UE-, z1Wy 0QSҒ%Uq텟*hH $"縙os_#|KWeag~3 AGa : B`/j/OοM7$|u{-/><%wnkMK.yi?|Bߗ?G!F_|$Əmi)QaPLExqV)wGEq.5wJ>"ؗ?`}|D .%#>_)/r0 iFB,p唊W!R :? 9mΫ#a;?O8"v6)jaFC Ufʼn?9%ǿNH>c} /^yW.w?>:3?{#o_(cl0FXSaXUUH)x*#V  Yd%>60/7O_,|rq)/NP8{-Oq`O&y878/>w?Ϳ/C%-l|י~C83_s~/:B8jrS/KrW?.!ál-<9^ C+ ф[+\z%PF!RܙTu:l\Qucc<8/v1^?T8*>OkR4T<O.Mr8X9w{X%_A8? &8;^?P~3t«gJw4]jԂ~\n ^B¡o XZѨ zEk$;^vE/Wl<Ǖ/rワ:/O_ gLڗM2.ՈRP+ ф+I{ u-oq n? ^=e$ 0ꭀhl@aQQP*L1Y :B2"qO +Y/g<qhK wʩVV׆l 9 F X.Z ɵ&iͶ A8 -1*yB- HP<@N31:Ǖ>:/'<{o? lP?˂lBIuSx9Oȸ灛E^pL$oخ wcPKC   %!ظJ}}@OŎh E uQ)d $Iǥ#ec Vuz|JҺ!ahNFWD @bDDv!6AW(F0z2;&#fIbWB Ū2Lkzb+`d 2s>+#VFd5Cs0^|iNI/|/7vnwp8"yDe-f78#A(B ѹ#Gw8#L(+aB!$ЉsMH!4q -Q(áw eT6TbT U7BEpS̸s(wμ_Bm0;"zF%Tle9PqȤkE#Q9`t!͹NoFԆEǯΫcpR~v>~FG: Go]!c4!0 `w %IUT  #!h$!N W/^d.H$SRP$w7 b5Yhl©n ѹE]  fBVlF0 a OŐaX( f3+B4%}d%8@D*@Ioy8{$VC2 . '$|oG/82Il7H nq@ p"YH+hTpc 0L!)#N¦2ُ\ k$d7 H*ɤgĵP;Ѯ8ಒ,rT`ׂuvžNBQ] ,MPQ1a^H@ =Hᜏ z6n#xz^|RBV~zCU#F vD 7yh!c@tҶ6#đlR`rADQQ|8mn׫NHvA-f*kp `!+ZTuwD2`Lg *;a4HuFS誐H%H5xl&m:8PDT9J`dPsC/>+ߤ{#3Ua5]RO,'Dи!h&a LLS_^tdR@ D&*(AT!(l1Ę騆"V(84.SIEO^%$"E1<#ebĈv 'sFT iۆaDS6u`UM#'|9w%.rm5J#؉$0}X g= `H) Q pR蒤J*C 26 3/ DZPј[*Օ~tZTFz_Bv K& P T&(: t6ʶLUNQ2#c2 g޴2 !Y, 2sf5" &GXuuIT0DU I HE"ձI?]n59x 1TDW|e/T\:nR{kĈI1]!9awd'&)0æ3|޶n,OrUqi/[Mc,Di[(9!XpY71)IG#$ 6wt$֑>ˊ'9f2iLL.H I̗nP1shqnUݐ" R KAqԅZ;$J1'*ݑh$xC4a;n*q]-)UI27&.>%ڃ0yӧcՀ“K򍀅,H M(0(Oq( 'ҏ,$ xsDrd҃ I} foEd;X z4)'bdWJTfBA+DbƈBu:$a<0F$"(Qʠ1v-0F*bA@!b}*2ytZQr5P%3M +_W2BCRGP,8pi]H_^wZ Zy.!)ʉRP9&\rtg$#'J`r՜5=\PO` ԠT eܩiXHj: ҸM&!:Y9!1mвSJA|]>.>U|S*N{k?UpYu*d$c$C2U% |:" WwƃU*ǭFďvW5>Y@9&lfxau IɎk $&x)tZtVSNc8UL)΀@eLEVB5&;#.?|ՔvTĕ96$LUW_QCR@R)Brk}u)h{-D(E-.sͫ)?]%R`6rm!LƁ'-{YYْI! KN2e;X "7$HJ ԓ`rCHtV W+:ʺ"VV)@ 'Y4$Q$:%CmMy JObD0 $uYd.^WZzqJ+ĕ'ٛa\P RlM+d J#6"AR[GMЮZN|9x9pƛ"pKRxx\hTUюt;@piT)36 ޖ؎L? \qo2 IPr'u 6(DIэe#X\uq9(͉~4 ĬgSH6aIH Fa^X'``䁂LbhM4h[GtYQ47(%9oaGʋ4guVE⯿%PjV: *SaNA'wBs ht^xwK$u^iQcg ~Eب\@/^Ѳ"t471V;[0`i\[ h8^rNBD")t^PS̡5u+-hPÉv沬 B ů,< e<yꏨ>A&c*NtOZUiYo8 œ;7YN3[;`g C&(h3:7ЧW2:I٨ `0HRsc9ҭQtU4c6@;"z 'r':LhSYuԃdil5>FC7_ /TK>ܪq8;s-qXBY7e6D-6@p6騯dP`>zLH<օm<#O4x4 C1bSX BC2 s7YxY h$S|ХAXi:˟]`@ ;055W $pdJN L>!JpLԂ7}uJs)9wy/eFKu=O؀ \IAHp!PαL:s8 q߾cG|w AbJ!S @ 26YQg/f<29\19\8}jwȍԎF۠oAl$NbDMb.6&s3hĄ6ɠ }:CBZ! #fJcKsE x שV_O)&isN: >tMz YV/A`69.XCY:܄Qr{Z92rCeȐeo[O%R)6lt<7$ΰWʈeP: BW؈cζ@HoO э!YE$NoLfDcW=*γGCVrjs ]Q9P6=PӘRLw0"%. 1k]u4t&Vy F|cxu)jŨ/6eBQCu ka;yi!IomH!4(m$&PG"؅0`Z.Wn2p*Sy^cr Tߕ䚘u2$J1BXճ2LGj,@.t\hrfHl,Jh F'cŐN>U8lS1ӵJ.Is"bNm%Q "g V1:Qآ`ps>gG8 ^ OR9^)0"[u6 [ #ok1u3ur9 ww\|:yv\4nb` ИBf$G;z*6;9eQS9ka eJ4P}*g 5/hxYg*",Fѭ8C]!t.V@#6׋ \ ƕgu DL<C}`KL1~J֜#aqM< T'HdD%u Q%g: 4 Ar-TKpZQF%v{ 쏑!{3*t{xj K4Z- ]&CDOdYN} ,eÆ3`AHz{:hbR+\UrxmH6 ۮ͑i(E:kW9VB76\p\ʙk\Clul{2¹)1 Ima݆:*Dl6tECAƜOBDLrf:}NdLAvpno 5i*X3z+ )I" qfreeJA (=TFeGiRX^(O4g;^u}͸^gDT7f;~ll tĩ{ 5I;}?1yycm4K3="9_fVU78#r4f6mZ̎70KZ+]B72,d3%Q0 ğn_Ue~߉w#I$I*8'}K,D9QOXVzcpO<׿}vCS#V-rP20q|+0CLr be3!P OӇ;GRTOXZFC=UE.لnVT1vo:WI<%=mve:S:(:`6_FƘ*MKW/ ?G'3a;kgNfIvXO_;p|YD;W9 lBP}P#{C;Np",pL=u-?m3_BYH9tQGzwGW (Bzۣ!؋\))-ڙިC^U룲ќKf]wH9]Ⱥ1){UhPnl)mJemh VeFM3KWJj9E("G'I)tr,&HG?[|:%u{ܨI-~K\IkFYs,-y/U-zeId?݂ Ȫ~у'+Ńɟ>%7r1(̖m舝`9*bx,`EҴ#bӓ՜mCt'nFk\ oz#g:Z!t :5׉L LM΄4"P̨1cJ['i-ۭ,ekr[ҵ_-}-wD)4Xa06CD/ަ.C_m]nO`Ddw69kGB?o8 M:F.uR.+SQk1zR}t!&G :P&Nd|Oo=x7WZ Jp`Ⱥ)DuRs|y*: S#]>SSZ`y~kjyI{ӦVVQIC=;&4 Y F88Ũf#lol\a׻kc)+?G!g.4 >u'?8SLvJh|,J`AhF$!sj6Vn%[-͹o+^wհ]8 ;]`kudeP(wDQt:a[*UWX:";msE)[-X/D JV!&BDIHQR'[hxx`0Z &,kyUK(r~CcosL 9 y7f\ۯع30Ɣ ;"eYdS#~1Ho\N>tV}6x9ӄ{s|)qxjfM%Rl!$HN^Q X_G}[,wHbc}κMpIJ|wJ<=Ն̪45ev*KPx0^ߤl%>&u'b.upFoʕ!|Օ] <_E#,+ to1[WNTlת;IPYZRqWmQ:"' dQ8j+㳭ѥlrkg=}>x{vA(S1T\ͪ;NJϪdGK[p!i_N" 2T'Cl\72πE@Z(}񎟉YA" ْ)Ae|gIA~h&`JzO[Ec$< b~s`pA.>9)A-I%)PaRDRmf (7[4rkyva}rk9i6hWgxU1-[aomT 5 u=Sh,E3SXt iZb='Ԝ 8q HP%J3d RVV0s"'\(HUVYWTfMSfH6[R}\]M x ;"ZRfV#:!4- c eJ}`zXl7lLNntnŘ8 ^_`ǟuD5nŕeXH" a,)KDe 4(oeC3l;l%}=SƓ@Ȣ\/Y۪ &*'"f&PJ"q<4'R<[Ӆ$<<O':G#ܲU3&$ip.~Bكcs&MJ]1f=YMp%+zfI~řǜl{}U5϶«ϝKQZ#kCೂ>YJRD(2 E(T~ ps]to:ޓEl_ ̖Cb *d@R|STty9pmFփ^5u:pZUX5iɔWA9Ni椲oOOX^m@K`HP n!3LZ|Rě'PLGHU̸k'9 ۍ= j{n!_B]I!הm51Vѣ\PUb^qZj4 sf5.96)ZI5i7 yqn\R9U^lǂ׼ kY!8;*uMܘ bzS&fIBOM ńYȰMͦ}ـ&]Q'? s:oe9Y7 )9x[fL+\JGM&Ƽml?Zɜ/}  wW|w},l|HAՊʓ"Gس(|L(ya j=sl|$0ccwKGTO# ;݅mO]}`Kmw5eJMԉ^7nMl]VcFI|0d8Iq6 %"A/έ9tʏ=FyǏqɢnRyxI؋sҺH9hF\fpz*ro 6Wv xs (ʫ;a)ҏ㠵 t'Fw\sWiT Ml"Є97gRfъtqc{CEy-l#yk,iDVꚕ^ P1Pڬ"$rBT56xG30ϣZe2͓iNODv}y GWƵ xj\&m#Vf>]=2FCy֘&OSoKV.RAI=̹Kg{42F (pwOmҥ<ݍ㖾b7() λdsrWq$'{t4xK2XLF:6RfNd5Y&{L-Ox4n.ZWO—oJڄXrhޤ pԚ ,EP߈RmchK&4)pndU34av BZ9w`&b^z-`9$ҍשL/ X/8ȷ\ Isܺp2AeCeYL0pO1iϟpȎ\8HL*mf¶tIm|D-#:( >҇QOƉƱfOb?B*<~Zyq^/6anHkx0Sb=]zx:*zQ-2rmLqƚ,;a枠Hm0W6%*uY_R&ȦN&}m1- Z(1E@er@4ҿ~)C؝\7a6E-wEF bNF\(~͜o5 H֢[@Qv|R#7z;h"a?Q*k%^oTf(ј4&xr/PǗ˿'8r=OO5h^]r?uze-'QefKnHȴ\|tOYԅ؉L.dJ.AzLUȝ4WOO{ f^ XYΆ%2 痾mO9d_Z3-aKf5*[&Or"ouX.=w=%o]RS9A~g>䫻ɭM1m!#R.~F ݁6Dw*6*QPLc~C|BF1eTkj([JB) PETh5,iJ])bU |=-G;JmhqU6+E.̾QC3߼RCiBT&`,I6J!fM|X>h9M=ͫїGr>1pK^+$kaŤ1͆͆Kja+s_(vǴ;8mc;p ͐rc7Eoo顿ٞrU)GK70&-5y~EMR2yS+hV˱ 1UΤfv$`RՊ׵RRDJWAB1|[; }Y|_5H \*6wse l^o]ς0K>BPT+Qvo4365%`xzYnLJ>wo¯iPl*w`oJon:5V!YqSʊ+MT2CWdH$ (9NI ؖwm@eZGL6:iXGR O3#Vs&M%扴I(#ɼ > K/hv.mz)P2x' ck»ϖ:bʼOk<h,52R05Sm2y O0݄tjs 7g[6^Tmruu@ɬ= 7 ZNDe,ESpHnG4hޑ-$Ga%0ܶI 6 ttLeY^le ON3&RӪV1Kr7,J") ,7Y50C\5b In\԰\)li"\*oޕc 1BV3sILf+y6FZ"ɨwM|r?'woyc[1NK#-Jșzv%"2~ uub2{zS3W8A/̱̰s%ldl4I!wo>ud|,b-R%Օt^ 79-P .C[ۨBY\ ŜÔ*N^megEeH iZ痸:Kl`@ Uïe1?;.T!s ܜJ@n]IkfQ#;~A$™_q 3 7Ϸ uf܄fdHK9NcQMg+[0UK}rdp4y%llٻa$j; T&:v-XeuIe$HN`#мxQ|KߵM'0\pyݠ__|= >zFA QNFp ܳ<kxƣ))G&^q)Js,12Hش7kC]$PB:En`^,7ׯle3! Z7\Y,wnfњ E^6To) ߉:ē0kꜻ򤰗}?8jk'Ҕrhj6ip{RkLb=x|NmąU `tAs|Gx폑o_iG?W@50u4\ 5 FHpFDlh[FD:895Ӷ7G;{l=nzHN ͷg^C/eSkl܎Bk4 n%SSZR ҖҦbl~l+Mcc\%_0T#)l2_¡kYLg‡?q>|.\v͗^s3&cF:1)W7<6'W 6 #MJecr 1NZƠq!ʐ|@K[k^w0bBhwFi蛖~#Z#[M*ʤQVJl5Ge:w6])XX/7gR6+O\x- e{W>]WStj_:%X5=yws6D TςqUVDUǽ#D%äL*~NVz0`TyZcQ D" "*j̻F=ZТTvF4f4TMKB5ۉVW&=1K3$s|3Vt<q݃B_Lono#`~ w.۽`{W$)ⱬW,RStvHe: z^I" s 9-]c i\\貳׏bĤFї&:wjp~L=kX=;4#rRS=ATv ZfJ,Qԅ,g.RxudL=KⓌȉ~iҒ_;yWHVAN%Gu<"KuѪgT i2rNQN)ݸmAr\@kj9иgo^Q#x .$.DES󀖄NjaxB:ET,jHhb̋@ˆRhe̖;,htżu%@ÍXlywZR+NT[6~&[BҸLe>l?ĉ\lpɈɶu9ZNTCP0k|`K6i4-[~$Ī}4/:S2@JK2Jh Axrtf_O M,ўX82i>x*y}d[OGM~?Eo ;op|g{'<=q!n\TCkЭeҬPVcX t;nBxev{b<cr24Zx'DL^m)f?^($DcDAGJʥ0i*cjR4JčѓkL< ig̓D7FINs>yՔz/G?|=?Cx[BH|>^yBaM3~`.VP|cz{~LX҅o(a\\L#UrpO"8Mlg#Ri,Ϳ>',P"@-y5a;t`'ͣ6uFoӑmRD$dǠy?z˦T #6c<9q?yp_~Fз_7WۧWQT]&}:ټr9SV2JEj!3'dlŖ_y#@KiLѸ^W?W!i-i,Y\ȘKmgdnIR='A_"rP.id9Q=БU-vM91uc: zB,p9c͋u'G{xTS셻<~\g鿫`ps`^M lWD*2SG' E_n \ *.T@0O4\Yo?%?o@XhOu@X1(7T{ATKJ͕.BV$I&K ")+:uԯ[3+7ܰG2 &_ɱ;g~/_o?Eys?UzmlqF|̕car> gI:._r `<Ӄ6И/YDJT<5,o{#JR?­HknUΣ&$B&"XB%07q<&:)Kg3]o9I>IIq"<~R2T:-:QFgFnsdR}<}O޳Y#'VnJ{SB{Գb q+MGA9 !P[iܕ+HՐ\5o Nt6L4Ww.uuϜs YV.R*Re.+~ }},"UDpȑdxsZYL2"C觎@0& XQBߐx:B"bSY67](6j祣V{j]%XECnEfe.ft":: %ڀeSDX3Y.ctE;(ţɿ67!$2]7=׉LM.LHΜ <9j:|+Σ8RʽIʷ01H r+ai튶9;9"75ro,f{"0T }2a޷+X%4gr^{ J|`\1M}hdHZ& 1J\.(kkt `"td VB& T p) Pb!JmIEg1Ղ>P8*Q# |؉ VJƋHV4#NbޘYU\`Iëe%V% ܀ I#GG-T۹zЙAĬOZp ^ ZԞkY-kRuʄHk6Z,q#32~ds2.zZ饹sFB!KR>l[L6ޘTfV5 V˥g6+U_2/-_/Fτi(tќ{dT⫧⍖5VpumE"v,Q+vnq#{f N-[M(96.!6D =#m\9/1p86%a@dF.Xi(ֳPE3}ks5ӐP;E+g!(,3n8S\I} K '(R ͅP4J P{hF oqC F$ ݮ0m&Oӄ DIDATSyHD28%pz: \.a)Reu2d\oR8/âUj#7q':TMEXj, {  6VxUI}氿ٓN7Lfa'Ԩ5m5ej+[/2nµVv m&S% H\m en+Ի#}G YLH]m\7eQLf>6D3nDri' cέKn_9>> 8YC*ߧ$|_M>YE#SurW%u,5ر>jLem"Gt۷LtQ)N؛/ͷR0YAK%̈%Ωyl5Q&c Z`"Ntjf[$5'栥J#xZme{,뎟uE]V6ֲW7}%¹fQɃa(dTXȈO6Y$m#d0(cgbl:3\K$3h&ԄuQt$VGRݲ7JFKERN8 PS .' MoU k}+%Pv54,FXu¼w)5w2>zm զQ ö3l9p|jT`%P$1:Z(EejdXDjHMz=%gg ꄘKPK&2Q–~en$,(k;ۨTX bnPq`Օ´M^ vקLoke * !LOD띴:qc\ YcN"^BK%ps0&s݉Sa<2!։lWRvװ ~  )#j$1DH=Ek~yZːH/tp+%Wyrњ63@R;i>;DFj X٨QJ4ė[ЪCSX}LagݗAn63Tr.6gxG*_w]RJ\L\ ńKz%lErFur]([ Qc-]3L 6$ъN>3Oܬr'7;5:[VSaZECF٣K_^Y4u2+9V*a[V*9̰O?Bx7NM8jZ.>4&gW;1,NF7T/+T' C&a ;s.ԹmP9'7ۇ*pv-M"%8jDn 9o:+7RܩJ>u #' Oވ6չ )R6t˰~w,3( |^xjᆳ9v??rn󔌤m.CT#y A~^}[Vޱ#"lhy]? \ _ GQȇq Z46[ۍ8gQ)L*ǿ\>1n9?s?o>]_s֙.YEk An:Mȥ/*Cm]_`]?MY}0nn+NM -]ǺڍmP*7]jW"h0ƾA Î*O3_{#9ƧCJ'Mޅ86BUgNWqzyv/33wop2w 6F^( u+Y<1Bg FEg+T}/I{27G5cﷁ?Jr.poѽ|GGk?wϝrkp:F 50 SGlΊilё2U%- o[:[*'' g d}ħ0GUe9j Q dS>E~8_ E r Ck\7/>^HXS~ؘvָT3'9^|PN&x .F{ oTs_"㲚ٻ'l߀+- yiw$۝wov>;iG/U*>歟kAe0\}~xŹڋaYQbIENDB`robocode/robocode/resources/images/explosion/explosion2-12.png0000644000175000017500000000467610205417702024002 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%@ KIDATxoT̹+@b HڴFm4R%;R*!"UXUjTh4IHlnlm{=>ʥ(`/J393B!B!B!B!B!B!B!B!B!B!B!PY)'R|ݹO-bdTХ?kX;d9.B0R"EũIc{4.Y*⚥m >i51i4UT$`MLI1p4)7@&tIn0e=ЃmtRX)h5QH!C*j zv=qG)ײ'^*b(F&nBRh]bnLrw+ZNLin*T"#G5j\a?9L8CAOaT-ľG+rK>K7\ݨ~2M`x*E3dZ.K׮'v`f{F"{셨cnźU +YFY2iGSwEdT,~. M@O2PG9u\J#HZIcLyAn, xP#3P`teJfO_$NI1l LWQE44Ph9yLx$0z3 ?@ (p~B9y@'( f& 0bh>5MjM䔈ET9D.j]w`f *VlAm9HK ΢ 8Vb(}Md@KZ[`Ӑt ?K}<:55&s#5Tdf?^,X)-_ +;a3[X%p Qx[ֲ m7K<4$QRj0TabN2:MwGRd 06*o|3t9_#=< lR5rFiz8fb5kc pO~ ~'ڏ OI{6ha/)`=0 **DXZs RX3d(Ȟn?q} 6MtKf`&5# ZZ 5#ɢ]_ǪwPI SIҏCpcь-/K|Xf5Ea"Uc0U=AL3wPПF:B>=zm8FsROWr8@.,W =بt8/Zɲ\`kн2 ܩR$D)դ?JbK'L\BX%_ 8Oۃx:b]gBZ ļ?``|gд/24e:TQKS8AL+2$)ta2mWGY: a%[vyHŴDm-<>T;$Cho#FCM$z+.]@{e Xu0Z&PnjlY9zjn?#~ `{n7*Ha؅o&JȫA]vlpl 7Qn\0LX7oǞH@qxʤ)Gut >FK81<$Q"eZIpP괂1f __a R=x xq%U,IU5 5'qyg.EPv:Q}D~'x/K;{N=L5;hi=n %(牼:*7 cb88RY@[?WpXӗ':۰9T &}ZyNI&7 uܚc1fIpڂ2XPԜ̓ЃgƘ3瀞abKGD pHYs  tIME%SȹIDATxKpywcߋŋoI&DY2%Nv%q|%fWrx-7V!pR/Ci k ,ytw3T%UVHKjj[ `f3 888888888888888888ξ#>+jA` mq| ҲZ;܌\ ,x5ŝSAUPmR{1K$JbTҼ9E{9P9*Y Wmj H%EU2=&-ݥӊY?>‚XkscOo$B_OMJ%햢Fb[xa $415>Q%O~m}^-JnoK՘{ *[~i.Xy]4T4cGMF%UhP fѲB =32b2$gZeK^lE{#⋖0$%,1cտt0vkսrAq~LyTXm|51e[(S&i dF+=tfd3~mORUMHѝo@*{оs :cY]E$} :-gVP :#i,MXsVxnf$`*eI/[,6H$(I(GG760٠Fck/ZXr}޿q7yd$j 9u@ 0RM$ S)l79 QA!1;>5hnA63(V&AH~7\x's}iG!3`Im0=ϡSdih1Yipd>knBf\pR $$7AhX!ۻH1?` 8N _ 1#D)ː~.d?N B'Z j|Zlֆ.RHwy^v^1p.`솁v\\8# '//U4X[| 8WF(\_ :u"isڻlE]ff˛d,a-wk4ezu>UM\ XHQiԠ?yLh[E'ɼg#䧍:I8K;y{W-_G/fPRwIp`F#oMmEwڟYJ}]Y0$2ykX> eL±Ӝ Dqp<- {[yh0iϡIceHio*޸eG1O\1(~Dhw)}> L{{0Yl`/(21 ύkx?]zQwC_Z~?\(tr])Ryrv|;K͟3Ǵ#壉Z$V"mrdr'dbi^ܜer"OlQ]=MNJ{sRIJNH Ya]Sw$mN¢ڹY0\CUv^ Yq>Qq(FL%09x_ǎ9 z^Z~l }R8?vٴM43b?Mf^l1fܞ- kUPY[b*'g_"Q j5fˋ2f0ٔɲܫbPPg%@tIdHP=&|M4w/3 Th_ds*9w̞g(U'!tŠ*Y(&g$^ϒ?bnc' @j'z#E[Jp E `AP[)^ĔBdH""!aeX~ɜS|QR(TAx駄5CڜݏK{C,#>l1{42ql[Jy$ 012}hN|j_[hezm6F/͏0 `!͸K]ɂA5eaѺtYG|ER-&^$4! {#G-ş~òh뵃c3ϽK9 ,V>`u؎oR~ ޢ H)_,xd t?E=F\cu#zusO7u2&P_F7/ cT,/ @ֈUbGi>$6H@ >A͋dz BՖ̄u3A7o3s*"?£A9"2Cـഀűgx X 6MKOrf/+U%'?!VoO?D)<,&-3=>]`*<4B(I1cɯh$feFx܂۰'oM|eY83V`z6:Y@Y|" yAaW }Zⱝ71+[pG#(M_o Cg6,k).Fmc[ ONHx+` ? m| _h>Q?1;=LDXJ"u$~ a$-&{px5EԲK,5afu{FmYev8RBp pg)jbvRU^ThwPIY HMqF1\pH-,X|^iFP'SDZn"kTȴ7ۂQYH /GEB?قCu83Q .nw"jXn]u-6ĐAzzTMy%c [0biNc,f%<,{F>o|`4dć!gV4vdYG+`}Y@D(y4ZgXaRج)&UA{ ogCH0^ iȲL$0:.B/d|vGm[$MP+AmupSH W2D\q]4\[l3R qKMHla Hij{xb_X2=G0Mz0a Q'Kc<0J4 ƤԷͨF IќeF dEXLOF*AD13J `ODV1$K2F'r(&#JSmeOc(%G&5AT:&{ /ޡ\hЋ&'on%;w旋jX1׶>A'?|;mzctZ s.  J$<\O#X2{X[',E`^p%v_a-~+q( ťKS!~No qqqqqqqqqqqqqqqqqqqgOdʽ IENDB`robocode/robocode/resources/images/explosion/explosion2-17.png0000644000175000017500000000712510205417702023777 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%d9<6 IDATxˏ}oUuv>$ŐW"9i8"64[ ) K90 q{X%R(jHjXw8f$AIĕT}b_WUW888888888888888888888_ 밓"b/_^`A %Ų%ɹlUfCaܳ\~URl-Ír3%@: '$Yt#؝QKo m@' ث%|#_ݮEuH Vo'C}8fZĉFhJno0:K>{+t?],|SUJeɊ~VB=V&O6ɓLaCZ&X2&yϿg~ɱDYœ> {mqRW&ӕ8;aL/X/C1a(aA(l8Xs^UƼVHX\xyyBѦR]ĆXkQywtMb-#"2j )Kz)1t\A*m&^moRQQ3p-LF0mO>K/kW,-lxsH2XY!iY:5ch=I(ƈi9IPzH="1) 8B%ᇴ%ڡ/'26ڌ`5 W=97 7H'ęhNcBv?9-_su%\]|QI|C{h_B1"aAo I)dcFHNj}਴J%ʊhǣaנZ 5ɱY`8uXTO΁x?l14S'Y~dM=bA1dj* ՑCY6;Vcro!}2GDPi ġ$Eɺ#L0ԞF&TG:xr- a UB 3IO!:,(Z^zk*p͜9IX*|J$֐t,T\x~vj*ԕF&&2=5u`r~5k@ogB;4#D֒?5*vz\б:Hn;H45bN_>@+KEK;Ңo>?cl7Oit ;^>bﺆ<[k?k82m5Q3{݇[ t`fvOH&/.g.@$n՝$!XzR6G>u,gPBsNt?d'뗉bN27t c#w :*~-D-NG{F0`,d]"F]sy9,kϞM98W:Gch:qcjg[kw7QmgOg0y9SL  v=6}*>c<w=YqC^nH%@/dv=:F@,ӎmA &i9>:K` ؅-P}Ew12ɫ( ]k,6hjȣhf0f5=~ypЀǫpc`I;p4@,5 F$v쀙Óϓ5BO!k Y!xwvi[t**;1zsewЌQ~a}^f,;]Z]&J{&g$W)L"AA"16h4J>KBẠd3NNT&] dpN| ?C$%}a{OGovjTGL$nxW+̥_Xx9de/f,%-dBuz=M$#6)Dw?QDiz!`,]$ |(l6)d!v;M>`Fh Kk戇Ж>EBV4[d)HdsaSm ) xx-@4v KeBjcT,_# o '`E3ihH00!?k6xc >IYÊ#U,P,V,=eT;2z߷G ,vA-Em-·lvЧvYy҂O+Ȳ(-q'1׋~{qqqqqqqqqqqqqqqqqqqqq`k(uxIENDB`robocode/robocode/resources/images/explosion/explosion1-4.png0000644000175000017500000001124310205417702023706 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME$)\0IDATxˏ\uzW?f95(ʢl8c F3H /Lg rBB & ʡ,Js=G}Gd'E! =}:unU]@ @ @ @ @ @ @ @ @ UqZ{53m|ɝ= {r{&zw6m_eW'Mɥ]BbY*{ s4\sTb]Zbû9 )8ic1s82ڣp(nr% r(85Xopc?%#|90T>?i^qgð9#}B_Zdb;dC\se\D6Hc@TF pB mpc*oX\SK1NI(44'~nyu'$ nqY4O3аN"//RMa4Mq T>aZ& B" `*xo1bBRv)}Hla#E&mgr+a' ks  V*YXقX+?މ^Ȉ-kDUӍsgU\-:h EGN_\s{ aXw|\өDɪ1\?# +B#MlܞGiXFXNs_#`tDz@2 !+$5*2e'bH n=f/GK[fGTps2ھorf%,5FZ-:2Hh FKv Ǩ*f,RfD\*66 ߚw\icķ4fyS@ (^puI IC ]ߡ/EʨC$vUB*$É_C\!5Fa^5hЉDosP>ܡ p5҃0mT—-2P+$\scfeAY 9Ebt2Ƙ8:/"jU2> IߝsX6Uwc PxܬF9+V$Y$%+BxQ>b><4T\F%_3G3N{Wf;Śm|wyZH`Rzb2W,T^LOiL~e89R J4vG I%-)%W7Cb܀a𝒨Q./m/+).Zx /8H٢M&*k4K[蹖nLWfB$q#&0U/Q:Z @@xB1s KE)&a*y#g8COVT!q)+z/֒= wSTH 8iI'X-Ϻ~8%71~X}~ GǵRXO[)5 " 8KJg7=9f<6,F[v Fi}$1y~δ?ˠÿN5MEp*J+Q`ǎ p)!3-7ڃFxT~\eo"rڤ,9G5֑]~yvMB<@}<&w񲮷Lx:@zK}Z~LUDCm7 ò2T~?qدA653*+Q psuFn޴- iOi0f'/d:-L*}|1f9ƒ]ٝ~2"qyǷ1iEmn6  N s8z(cqX_`L'S w={28SEq<N`{ ?.RscKl_]u\fyR<1`iOS!iq9vT^E>9>.y^0Ԗ<^CiKpVKeo@=>a|aξGK iY2lWg{iɈ׮M{ѳ$IgoGR$Clۭ6~:~v1WcƑe2<_:8>I*EjG:=dTA=xEWih{#CR0( q=u2rSw$BF:AfKi.^~pG^-ӥ`I_GLwG=%.>,{9B!"Q-g}Xe]ӁpXoFLʄD)GI_u;HMگ0f!uGhOLrTH1(b嗎؜Sf׿'y48FM#$M( `Nl|~7| <'S<]I=*#&nXuIrWɊ^ܜ$p7ɍ+=b:laI\ (^hޯ8} a~ŅE\%GVzz7->ك鼂$pxԇ']%|?q|F.8 κ#\!_ $I8+)WIVL41a[%H<]6ެ`T㵂<A(1B|*+Ovhᣂ[n%Nq67%4I`3|a|2R &2G*yQz-.U< _<v?C|6tq~=BTyBPtw߳BNopw1ƑXCWJLdXF%Q9]DߣtK|{{gOj4 )(K[u=p8Ā90=rb51o\7u,a/5ܼ\S22VBj5#ZJ BF)i-E!NZh"tFUXizKA%Uq9@"!eqU{GS?5ܺNֲ'#^/+ PRFy5˝f3P\jK"ÖH*ijhHbO"Gf*R=  !o+7C/m;K[Nvb$"(^ WIPSA筼WFcsϸT(Y\"+Ƀt$ʳ(,GCGT½--Ý^lddwؼx#ARq)6DÈ2DctRbY6>[wۙSMt~"[;H2x2ucv͟W6'kMڏg%5)ܑB~*X0L &c{u4K- `xW:pMxoMLsWs?㹺3J?m)X;_K\䃩qܱn{[~gsu{ xܼ78j!|h_;\.܂~'Lm}6y#+~@ @ @ @ @ @ @ @ @ @ _O]AqIENDB`robocode/robocode/resources/images/explosion/explosion2-48.png0000644000175000017500000004705310205417702024007 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME&q IDATxُdW~9b˭2k#HvfQH=,x$qØy6ao] 4`mO]^ X)x, uQn5Y$kͬ\"3"v?s+Oe^F@ "#oD{~\t/ʟ.+RG?~  }M>vսǯmύ7<Wį,_!ǷU8tRsUBܟk{SnȌ ~@_D-UQ/N?b?}ͥ į_Cµ '/;}M;ch$E%Xtf!S[;5ˤWvqp(Uj|Dx^-2z!iB,4Bh*8FbrAA RYχGcKc,`u ^ypss?=ڻ] eKMA_WZ0w Ewѻ )ª +Nc+An%(᱙Eiˢ7(ӟl: +c9_=[/Yxq?gwDOY ^$_x]#yD-^[V?zUw/4_ ɯ[J9KMΪ)K͉+)rM5+BơF@Xyqp`4 q0//z=7빁<ܼ6#xOp$y07o9ޘz,^{;[/;H.ڹF0,P7K{]ç+=j6Kl^tlw2O@P * L$T .Fcޒ9Ï:kp/'{߾&$3#a7[}tIl ɷ4W eT8Y1G4b'niװ+-( ~8@98B9[T?cu7c-l-35xy[rH6})XDF0,rǁ,+OV $=M5Z)*S0~jWLvZv=292;_o*rOSNAs ( ~z(Xù-z`^Υub]!ňщbٔl"(X97F1mXgA>8L>!9<_2K4H?nmjٱ=XTrf]IT&N`vPңG-b=:[(u)X&x7Afr`s765,?Zg~'x3A}:)z8Wˌ>?f8/Z`WI1#|71jarfPS0@dHO X/AkaPW~&`'8j o,XBclEgPie $)L9xkѽcFzEfS45NhGsS#\xӰ; 0Zn)3Mf z/dykxJ+@ad +2t_1d3~6jrב~/gcZC*bbȂ"Ttpnc`kW9dR5YaRP 29^f.]yրǓ}7Aً*^l}woXdXď61 څb02Oٵ[2eYַ-Տ}A 0-KkQ,ww-M%>/#B B{::ʍ9?Uo؆5~p%H* 5(6( AKY${ᒤ- LK vᣃ(HV=,U KtdE8*{2qV,_V]~.$s%+gV aV5 KjX+`ߨ8$Kȃ `Z>c` U;K*>\>poyg,Ƕ 4 ky>Awp^w.(y.ܺ1\|/+gB{7$\zƽ::@2gQ_F7ٙM88ZxxC)M0ѹq˸2nf$ g؉ Goks.VſU$SPO[0ޔwE8o"l(%:]$*>`l& _{x02G,ʜ+_.ozO m/G cӪ$Aj4iSJH40 z>帄&G==(rgS+Y^ }#DEMj($j]%D2~6zF1Wg؃8 + ?BxS ȝ~(2^3(EX,rF*#z^rU3/F Ŀow迡Pw J6Nu94G7خr6* VYP6x7ƑPͶ hDGmK-">Ƒ >ci mp {s d.-dd@`q'@nX6[d*Qo5{9ʸ/Z~Ҿ=ʂiӈOY5F&Mr -V3/eM\x\݃qa3cOS1Ya%F߈r9HpEg0?&>9$2?#X^_Ocr : u4od ,eI#J&4&cyu"y{Gr5&xFx=(BkԎ]N$GR3UVJ{;rHn̬6`3 ɜ6z*B#ܛE !U/t#" !$A7ȸMrؚpoOYC?B~B;p:yU2v 57п$PFNb!;D5YVcMHU;LK lWޞibdY"QmdUed5 x2\B|ŋ?D,c^A.GG?dV,q8EHԺ $b.}S#3Ϗ~,[-sQ'1<V\:e)*53+& +gsPL :sx } ]D<KT/CL(821L*~~I!"2nufy((Ya#v}9WC{eRDqrF׷ @Z@0D+9TNQ*L?FX35c,^DB ֏|aBE҉SCpC#p@]݈;P J$Q@$h,84-THOSWAYj萺2W=wь=' |~k2tN+F!uFh # ^NQ"Gi3:}Hm7^FcF}yur"χ"9XL@2 "D%l,Cc9~އOT@e.>P} z1w\]@zuh+!:LP)fOcB'D0_ RrWirRWޕ8U e !rlP &Q+^ sZFb[m'El>~VM)P֙}7$GN. ''2PxeZJ䑄*hnɪ Zc2{r)˹'T\FVQ@YFUd>K$r/"DZFUPEl灠*v(icWF K`Bxl أxn 6 ~L4S ixet~{'wb唑rVzBtn'l .w+u j,X7LlF#r+qD!G &K/MX/CglsPG7աuJ362JAq`%=;us95lzx7%[OBDDm\757`!8j7b#"22J*-%dϭ -A5Au_dm2t+2o gs*`* j(d' f)9D>V$, 긡rrI,'*B$ U| % d">dr 2Sk 杻II]$;^* ܼ h_ nג\pXJF0;%R2wHfpag>NRݙčLulMPV( IDAT:iä&o8>~4I- M1722@:Mbbky-e3hL׊RJ XB VFBq >C QNIw:55c!H JlJpzwFRd[ 7EB$D ye|J yjhd._0,wji`˘OR+0m 8Adx{Eb$f{G<}2΄sI€4B  2,@,$<`ΫOI'p22D,&%WybOIHCO "q{Mr[Ԝv8<.=]XJwZEf:t$B! \G?\Jau'AyaBc%^Fx@,"ukjppqpֆ uN{qM`iep59| z:d:cN a7XZYGğo>x==C*1R:>U| \tcv P9O/r,$wlp78 i<&KFS0h* 8޷Q l$TĶИ؅fcIL[^[N4(joЙ!7[Z|->w[0=s(g;j,d=R8ӡ|Q gFx?9f!IYPE`^B 0CN,lY% )5'(qCȀ% ')L$","# Cg${eŬIAۜpGI!ݻdzBֶhC-qef=k}V;xzkqUceϘ:p=VXi^eg4q!Sh}Hy" Sc۞QO?[p}4pOeg.V{'5uC+jhoTTl\tMw[bmRi0]&ROR&ig#o&@ RXږF :'Gt(M(OB,AMƅN #Jsɀs?9ęz|f8`c-z6 7.5IT0WM? I-I`>.2bǧk l.ۼ>"ׅDgo0"-w!ݾgwݰИ'G4@p}ۂja'% -餤@8mP ׏rJFF&P^Ţ힅 6>Web[eb\A"*ALdWIY<Ĺ 34D3X!x?OP>`(yWZֲlz$ zR{qXn{o{no[ʦGtj[ %r(yXuq߲$o?= %PطV^ELj *o;SxyǐEgPʸ ?#X>Il!O|CJwȇt J V+]K;w{`?.pRM'w{:PY'w@)b2$R&4lh|ETgõ9瞳)`8eRW%J *1E+i,Chӧ]DwGL4+aZw}kE{tѧzC0kn­1td5ep=0-4 B%d=N*nd,~wSi%k{C'Ј:J!:T2K N.P.?Y-sw[66w;_=xxbd㌲Pܮ }16'ӠIO>8t ~h$F'IN4wt<>Y;6wIZ{&yq;CgnfШ{'ymnVrD Ε5#⿇}ցQϴkׯ#ɷ$#u>HՍi18(xMfKMF. ٸY ­#*2] ڒg=msO#?Y⏈Z)Kd͒b(= w"=M <\7y$Wƚ\_Hxpl:2|zŽ% JZ$qё m@ L^?ER>6g?H bSj2q<2/xzijV`."#V_v;6U?~u/ Fp(.uZ/zF1K%~LkO-#X1|܄xCadtN¿qbl,%xKޞ׫g,4Mad }q(y89s+_NGUKOp}&'8vP}JSbYG9?wqDyƅΣfe5rzHlD)$H!°glsq}LB.aEzH4Ӡu\\{4*8ͷ7Xsdn_3E?? pZ^yuįKF= +KCc ׯhŒ)\ǢIȋPǶ)'쩧{$wDOC$ɜ>>)"]B}Ⱊ3sd'GA͊MEF&4k>9*X~:vomײ/oд-nEDOa:J'1jjDXXe,䰙٣lp݃S8\ HI$0Wp>0i|*!H/H$zI亖$&1(bݠkn;)0Vl$ bbCg$F >P,@WnM?bJS4a/m@Ux<f"$Lg {Og,NiGډE~ul¿i.q 28wīs;\3R{n8UƆVVPV\s̀<X{;2O6t$/n<,b?U 3تˆӡ$y2v&oi7I~_!|LȤ*>'J]NE d[Uv[(U/dts1i䓦|) ɢwރozPW.]- fXLqL\" ^K>abŧ {"}CFSBpYpڦ6T'B338 #)<˱by [63`|$y[{~d, W=-'m27KzX0eRA5ߌ6s?Q]i&!LThY$1"', &~֛L SKwF[1RYP/6NNо`es.(v?QL7֛@_9p+fCYM_fh(b>1=N.lUppQ *'ToqZ'ijMB!,BxFM >lmB)AF2|}H;=/h(GkW] ]9s_w NmH |˶cC?x_qOX(6F{Yc>r)lkL6Ҝ.1Nb½:YMlgx|Hvxe'&tEo2Fk{{^ xGֶ䣹{MMVVCn ;1n̹L3iƤ:9aǻXHJ"xg鄱)\'~ #-#S>sh5|:LF`k_[^c\еGpn8 _^=gI]ɼU\ؖRUɲRbaߦMSBjERNCGL"<>%ףye?DSSƄT%C[I:4jT F|i޺&_.Y9uΈ"/0~c 1Fz2c]b G%icGO}M :p(,6i&G*Nk >J:<ݎ&cxh 0Kʸ"64M^*0*`'[]u{yn<I)v$(ch6- H2ǾKXҗ>0CatVmْ(<:g˾ۜs<}#Z]ؤ笽01 bj<96Rڵ ?(nH~塹>IxA.1VNi!n}Ts_YE'9vpCќދE0%7/N6WEޥ$|<%_hU y /oF{$b{s?^w g3m>1q%窹d¥ev0u-Z{K]atMcA[+o)w}Wzr eأ (1NIƾ@a ò䷶r{ 2Ib[0.S YLvsOTHèpw5u[p1&64v@׍xfd3:g!=g  u{|j*4"̀ 2pE6eHV!e&Y 7zi8fN~AE){6,Y'wo=<5'p?Fۆ-H\-_sWrZkG'pϺlW=7ϧtPq*FhmyQBIj c gkE!P9fzC-;X.yppc+?c˜lc8 2Xُ(̪UNզжY4*d 1#;ŇSVfPִ1ҫ2J}Ss1|p,|H3T.4Y q$?@sxw/w)9  Cť)P V6jdsc+}M 1š. h z }CQg ӯGY&= <~5#m7Ã80T'W\&zyV3l\`tC9S=÷Y3L 4EP9|^4w:O$̀A& M3Wµ\A9-J"&X~7l1SXn¼qCro(ª;S VH-:כ)eO[Lqf &[au1*sH#I h$^Bj,o!Ubc6]H4XiFℒ))Pk#Xe2Րqxs3XFkWnpHr\50 :\r»:^Cj[SEs@/5c h<\XnN)Zv(j=A jBhtl #:[}}Cvt,"\dνC[0m"lC<q3D4fo vSclMii0YPS l&y;eP >r]3^9F,YKr=ɏO{˒+Ey? -<06bmDMB-l YLv>m)٘6fsB[meRnyB0!Qk] : IDATPَ`Ux} NieȜ%*9kaeZMS8V傎mv9bOQm4$Dv& b( 4ƺ+qa"}x;4/X/ڪZ;O_HGcM1fpGX8zGJ -!EM6!V@!lXM.ntK] `c ~<s Q~;qWޣ G8 Fį*xBSs-h)j.V`3p )5ήHa`J\ iÊam|WQx ۨypS?|܆^V֧ʢR"zbBXc-P0"B"I\{d!Ă5>2 xi؂ HĻ33TjNHT/Qlz3M-,Х < ex#$D4Xm('s=3KTfšv>_CQ5m%>Dl@ngmE6?Å1KHQ"  |)pGp|idA xS&{w$a9īޟׯ=i ' (3=h&_COL3~@xBZ~CD~1(f)Qh˖>2]eXt,CEkX|{L0Z#xc%nD3ľC%F;b\HRs=蔢9ŕ3Ĭ'*'P /S¸f,pxGjO(&xβZbg |Iwtq+-Z#($XU !LLߛchq5X6`Cw)ƞkǠ֮MwФz1N  !XG9/J,{[x46?jI.`'#ĞsJK4BM58aL &54A R~8'PgM}$Ly&MuY \p?/2{؍rx3Fk#;@k A#B+yT=]9%R q 5 4ns5. ,0rB1Ơ1bMGKjY 2g,XRdH@ľ3vM,#m w_yNr*ش>X-p;iW-$7CP #:|ڍ)IR0c=X5tp툩k]tMފkUͲxz.tۉ{rE1,?IoY(麛8?@O0%ͼ&rd(֎u_G;*gÉm VJY[J!BL!kJT"? 7Wׄwoo;/[^>o9^:d1Ph vg !H) @-{btx5M#Jj%QSŖ8l0µ[7GʿoJ:ҿ8u53(J|ѣhPK\*I`F=՚,2y!1CKt;qAU aVJLk噔ۥ|,|g|:D[caWӂ~uD,QFClP?m*L4toy r6o魃r5XBe)`J(ԥ0; 䱗;7Oηb[7_*O|rm!6~ş*Uݻ?l-S0thk7 %C唲Pz;P2O;_HpM >Oj5 ~snyXO2oLS*Ud۹O݋o 5z#.i x5o?\8Ko+gu.L^(v>hOoxNgx;$}>[gVIENDB`robocode/robocode/resources/images/explosion/explosion1-3.png0000644000175000017500000000661010205417702023707 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME$(la IDATxMoG~oUPpvM s24V-%{ .<$ɯ_̰߽ƺO]nc>Qwb$ه(""5y8:k>)66jgl|_$I522?X9 7:_(!Ր`i~Ep5"/1#ۤq2&a04Ok66.[2V\[./$tM_>^l7XF"78B#TYTQ lfhLd^.siG<-vjZA۰4<%Vi1̀5d( pb V[t2p<iɿ[t4}>9fXzELPVq RY#s1^yXx5=r8M piRUų y8 U,(^]Z\A+1[FeR)N4YiǷN`yYh-¥ypn"XV66H%"|N^I%=EIITMp <̤s&NjSSo%<\`GXJ@AX^NxWi,S65ix6bd:z3x]bܜ-Xgu$!(!t6$!ľGI3a&L>E&Be8=k $!'նw c:;^tF1 c.S|œ9Q$w(LsfDZt+V?T {,1;IMB'`$IԚ$دVA7wSMN(]ݧGpsKcMj 8aW3sj_>0: 'JJ_Ҳ}ꪠ6oȻG• ϛw ݢ]FzĽIvN ؂SDcM2wY_ DmGY>>{N*8@# W̓<}+y{q(,A}b;v_1lgǎ|Vx`}]pOLh;t6}P;H !!z?(w,U/?g (klԈء0=zU^>Nvct>C >OCle{<<߲/uC=;oDZ C_44)ve :59KyZŹU$9Պh` " ȡ[^:]ӡc G ~-y1 ~z_ +:껖$3H$%y =A9kBُq)qrXx<^0cE!Z ('9&!_Dc4\y|4D nDl Mbb~Qv)cmʬeF 2/5>"!7FۜɈOJM8n-b~ .DZ ]Q 3T!LDH0ә ))cXT~SpKAðeI J{sk5Z5~5mˍibZ11H@H->6* a?b6q5j;F}Źa<$֡edhl;`q#*'U5ۊR_G5%qNRCP’AXr|n_pe#ϭπcB§nٸjzsw{$knKn%+KC#I({vw%G8:޾=y+m&?ߘvܼE`?`M~[:Z<8{X-X~Mnu lvwηnkH<~V|wnAAAAAAAAAAAAAAAAAAAAA7RIENDB`robocode/robocode/resources/images/explosion/explosion1-7.png0000644000175000017500000002610310205417702023712 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME$,şx IDATxɏeם7Fdd2H&5P͒dעa @ 2xe@//0Ozр50(ef2Kcbf;s~?/΍P ;xx/^ppppppppppp|ӍrvR ]':|΃]=xozGΩ!Zoa}L?㳷8j.J|G_(rmCon3o<щ2;f8}O'WO<OKo)iPgk? "?u%RCA$fL2sA ׽ǐ5clIEbΘ&-;g 'ό?4?v#[OƟ?P, _:?u|NwP掳oÛp{UlGZdlَ3|`!xl{bq i+z] r2d΢3mgl_Qf{c3"pA&w gp6WN aޫʟ|d|l&R0qw̓p D~t4cŀ!)qN[Zzb Y$a!1ckM%ifR.7;so'&؉ s'L EbA8 }R gfha(?ʗ K!?gHx+"ڲ!E,,@1;V]W-+ZTA"@#W"Hɶ% yäl`&F B)^&DWyJNBj`&LM1tQHHۑRy *<iӲD +90.7':4(Hg$ ^\T(gwv]qĘBT 1 K'df8"EУAaf{\QTđ@L{-G#NXF>1X`2@x#o9]Ya,qnKF֤aAt3,I~/-l "H Y)'k4@8H0ȎŸA$3􆋅 Q\=_8 xA@̡>B Б\aCg8z4:`hxrG)|r_u ދ}Z6~#kd<1A>%œlcqeCÑ0M8I1 W2#l \ÞFwd_id!PỸoi}3ٔWYI~W^N$_w= efMePtVRc`+ϰ @V.48hj2H"-.xpQJ 3Ǭ *]DIxIRz{.xCrq=]~+y F4fA(K4ӫP^{6 X85Du8h{F!..23@w5%* b3CXf34;D(DAP`-\ Pf[p ( `՜q \QE7CK ь8q2@g?g_ON>f_?(.|Y0 +:9"#S NpU?yJq”}n k#bQPsBa_`h`>@@Q`ւ"J@]F, Hx8KA(fA<3 .G},Hv^8>_;ˈڌF 튨K\ɒ6ql"pf XNljAt[7p@3~j&r xP"^Z5h^M&'yd*3`ך8(P#g->{sv''GYFZ]9:kqcW¸ۗv"ڿnLni h`B&2 D<"qtOKXG#gD87"j$jyX%!_ SKѓsyV[/f^" Bh@i\b!t-E!TU%qk[֬c}-7΁w՜.F3R} 'px3a81-a֠Pq= f`AQ ire,6;<0K5Jcwpq*ܶP]2Wmrg&n{גoI|~/cRCDɀVUop䦄H;X@fM$V `ZiABQ+H68͈,81l/^ɔly[zv#izMPdg9-HyN!B9ybnhVb#yn؇+/I-*J$8vv.@٥MTE\'-S z``h,%ՇRU3I!IjW^8rpRc ~ k,kqa+@hs[Cs6;q<oO^\Zgr{Hs3TUtD43M޺{w+R܍ ]<9H ?*f k E*4m洆 da.cMOcҏ͈Y gj'VJ {+La@t3FYj% QAԉDDI-[a?yŵOj0:,rS?eS#Me_&q)'$FďVpRR4.֎ Q"^#l#)LqYE3ChJ"Z>DaRcL Չ[-ᴅ7׎kK6DjKUҗm-jVr9up5tޤݔk3ZilcT1,;E^>YcXlHJ#2 I*w]kLZ@o=[ K9SeU ڻ+poQ K&1[/j!i5 7m!Zgf+8/8kVvI3!o笭MW+ U|kC}Dt~]Z5Pj_xELM[?IsVhvq% \ vA߫{_svրWϼ z˹~>ðTxura8e󸇧[b; 'u|jUqcjk[ FJvQ^ nr(./VcO9.FR)n15Y"WԬSn@3Mu:WrMBS\kcȝ孯碹&: l:ME#6JO#;kEẹ6zjhX*"h#"`ze(bD1t?9_ZsN ]F@([Ԟ)#sұɐ53wU``\$Ɖ&?sWL9Z(Z\/tcS_TA|w7n, IajyT&17"H69<3Q*ʔ*`77~L !(_{-; ߀~gkvCj|cm]GLY| m){akC ~qVof&` Wp'on 8^U+0eW0_T_x2@_jLoUd11~3.F.R%B*M;W:_"#EG쐰'gB㘱Y\fG~j.I)t8#^.Q$'(OAaa?&P&{gXNZ .㚱2L0(F??;8ߛQeL||@,!8INvt%,%t>qdVʟ7uȼp0h},FvH`C ]aRv F$]1 澦kBz!tD\| ?ˮFp f&T/mͅ:}'c:b:lġh@{\PM8cf~x830+,v 1Ҳ'\yE*vwL aST0p 1tӛ@sVM8ZU33)ϤSX6qyҧVDG,c2Cå-p ~sp1̻ck侺&j4 iIS 4D:9:YCɑ{,w1Kܰ@_P9ӗ*6BO v14._P9R.H+X>UN,fi"-_L"^f/&1}n_=~*?LZǡfXU{)q慅)gα~*Sǧ:jl!WN)bp3#D?֡\q64>G7M͊n?L~դ!&71 b_wԸߘKjR?{q)D CM "Z21$F+Tp?_w/ OJ=T.r-8 :xCί?bX*\5y9GW(; &#N;LdGүn<]`ݎa[=m%⺯^s>N]<VxYcVjSU_'fV% (q)\Ȥ.cC!4*,W#/K'¿{.7J IDAT3bi\Ggu҇9Z[2Ru#mu25w\O(j']miTaJ _[WCv3b$ %&Uf"3Yk{ܨO:W֎_9ŎL#Q64qba\!l%&qn/ f[PeVZXSC- or E'2 NzSR Bz\iwhI >1qp/&>Go KO4pqhc\(6$fExbcĴ%뚢 ko^wNbpV;ݮv*\KH'.fmվ 5@Z̀>竂)#FҖ7QX= 'ƣ?ߒ~Թk=1F޳[Ϭ5v#I AaHLWn"N l2 XGD4͍C-쇪S]c& 3 t( ,^6+;Ff6ʎ!sɹLxXx:Oр=)g\Qȴ` XcOɅWI]3%RTn|?-*CJ&ՌPBY 6Syp t<^+:U3=2숾GD ˍ\W>x(pM<͙'c̃g#LKCKP𶥸b`h -];~oS#uȻR]Rp]1\B\Uۡos3/;llz)y4ԩS7Oj&\m4!E eg$ Fܱs뎙4w{'86| '| O \_tưIē%yC ;T#3s7RD+X& cD 0VgՁ]2SgTYT}yTzH#ʄz(6 ԝg$xx/ʞ=n3Hw2|j Grn#agEcgƛkOֵ-ϙyG]z8?1>>/R1 z\϶w~7x#Wyݣw V;cyMn_1bW?;ƣ'G܌OnH]l$=ę!Kpppppppppppp6_2%rIENDB`robocode/robocode/resources/images/explosion/explosion2-42.png0000644000175000017500000003525610205417702024003 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%6!`C IDATxY\uÙr3&$R$A+<]+TZ`# K8*Zp?mڮJH ̛Ù{$He숌7d{'x2'x2'x2'x2'x2'x2'7e"g,~OKC7\r:}[wq Sf'W$秂O$vXD"߀sѲ\*#/%; x*F)l ^9QV2lo:w=܀[ "~_U} hF3?NV5#937+(2/cl ERE2vf-/'-\s>F7ብAp5{ue;=߹A|)JIʪI(ӜB%@3Zm3D,kPIKk+2`]U pCZ. ^ygx[-xqT= [7|uŹ-.<;u;νf:{TLX3@؏giӜ^#d)@E9%rdaGg8NTLKtS>󽼦?jx܈YAsW4_]`^:d>X7`ؐkM6 2q%ɵgZ;R i&Wu>~Ep%p .uy:/RjQEۣCt6Ļ>D .É4VR?4cTGX3=GW pzwOH/VfF#8)#'m̀'_xY |E[Y*L_#׌{mCvpo[s K1q pg[ Vn .*xgKz_)2B*R oHCNWQv'>'*v힥A3=\ !]FR$葠lh' | Aʓ4Qe8j*3*)38VjBci)ŰES ?B >^%^ZK9Ӄ߂ b.h(R?Lo|KQؙ̨g)J2DQ7[l-^gk1lɀ/=m8G9ȯ!ympƼmÆx4 Tl)+ +CMr  >F+'繐& ~N0*\G 2IVg@{4v`+)lpRi>^)B\N"̥v$kٟ%K+^0 '%+Q7 eޣc8s^]YO0C*R~.z88$+VppUyGA+{ c.P K|жkJWfw8Ϝ#/yOxv$HXT#%`%,BIyVrT2Ȇ^"fsx-F{A+ZH)hG-wJ@;KsSK;f=P!|C"=ggdJ~$ Aq)qk) ZLf_m{y&]>fjDxe'a`Wp":!}OHkxy"Sh Z@`R,x/.bUECP{*$#@%8ƑDp$FƊn} E?ФsRo#GP۾LPY8u{w>~68h{PǸבR=3'6i3=hSgϑ'_Vn#$<5gW20 X a-fҬc&JH+KDӐ'R!B"!QX+AHZIlcw ,8%;K٧/>pv̜ɡٗ-&8H` ib|R " [s-RArĄ-~ eJrjH]DDj *7'` H /`BiVW;s'djF,4hX<k H}8;<3RbI`!{4v@ة b67?o.{7H?N<5ҍi Vs-LpD!|exllXnlóz\εwod*x~_ "HjZ}D LFۛPe[)zp\C@C:ƒ 0̂X/h`<@'1ړ 8>j 4&9CÅJ{+%,vf\?ϰ&]:av/ܻV3ΞAˊoJo~\l9+娂W7AFp~^X [$aW"(,xh@M _`8D$g2[pqǰøIP^^߽Vyp[CJ u ?:d$ T&۞Ow?4f`7NxA:abZv1\18AL.J|/=D]U'9 D52~c bz 0Q,~Vf~rصa4yJr91[n?ܪſ{t`7H޼x)U 4B& f`!|t CG #a/[E$Fqb-ޕ_.G59 gנ쀋VE rnQxf G>K2RrpFr |ˉ&e_Epd+ӌMXZYz:w)  8_BR>*y3}%]u#Ny:IpH@^Fd*8RVlkG+ igL ۊM. ޸U><>׮v֬4O'$u°M=JY&H]ز+b*u<(>iK;9l@D;MbcH0A<p2x  q NAj۬Nrقl;ߞV0 Co^쿥Y}A3R1CX%MWqY@핍[fmp8 Z"eϗpï05Q40@"@ᨆ6U 5 O)! +(ye~P{7D[gܖC7F$vjOU9џAwawxjGm~w:}E}!گ3-},~tg8)O` T‹| o/dz ?\  +΂<%~w%P4`ܐ| #_B>1Zuf#E%I(^_@60q^g~Gbu1BOOEs ,V51l3o=34+Z3j%xu-kϭI?Tuz#U]KJ&wZ~w;8+&SqpgkaA4:t=ΗatE2:2Cxm0 G? r8$/ .9~j^ל<P٩˖kFa@} k/X`\7;_pPOauVu!ziO%kiSk%Hu,o"傃0g)dk!7%o\OMxp.wsiWhli(5 k:s*`#Y+qg=E#dzdM`#CR@:0fg7QrmESﹸK K} (vUC9 d.I;Tu5eגOO5&l5-ZW \W "=\\ \08Y$Sg[OfX"?E=EQb|-F̓#qGeH+<,u3:w VXڡHfjFSRxTwK8Sl]rfK,pM,kDŽl60p?IANHeN{8uLYU mɭ5 Lּq< `C6\WyH&BℇvUq.>>uIb4vᣎf`w4,^d6^= 0̸׍᠆*4#c J!1;4ـ\M}xn- f?Z|fb%@W훒\Vt,YYB؄H0f ܫx*̱IDJ y:fT6flq"j>Y-QpB 9]ퟡl`{xUZ'&C=-䙤eRsoy?33}%K^{Wrг0gdIwI9;OJ)@TXtniGy?\[FK3HӐ|$^B β=3pyEWCc(e3@>a* 롔!A Idq?~`Gt|2AvV!Dt[V|ר%,pyRHw98?U`Cs&#'"mHE+{dc|0izSKj@,!ykܼ|Kx% EmB sxY +ʜa[m3LSLMB%َ<$$YCz2C\;!±vH2`\Ļydމ%g$B/{mإ$ Wᕍ z&z;nH81a,9AɶI5l -K~bR-IT4:Knp 4ޮɳlʼnnCܰKK{NtQív-"hE1"(\9uxpn ,4|eM kHF(' H$kk0 *絭\U@'W=UUN4BCc\2C as[ 8C3%1rՒKN^d -uL?Њ%GT^T@DPsab; }z`d"_JEO'2L3V e8Ò 2BV$ "QWK&^wJ\N-FaqB}GƼ]uGuNP@hӧ#PIkRN k#wy_[ A46GA)+Po8*IC+1ןHؓ%oj1:5Y f9KA+R8t9I(!5!XP7i W>u%HPA-?6|8-`Z%([nP)6IHHC% -&gհ~Br]/\.-+M.,u ,"N(\>3!!5!^0mR 'D:>$F~OJv$ 4`D%x DuZD5F8]4D~.:F;;f\ĝEԁEZb4zTcc(@ƄUdBKh`N[ӋOo|13Hc{Rxwo(IT0 #D$W8M?_zX-O7]@Gm5:1۠eK=9]8虼D4(<&Pǝo] q- (jhiaY۰#U/{ ja-9Ve"khATc1>A EA_WπZw;s"RkDл%|-6OiAItᨂy_A .08(7T [uq8^zwK]/='}Ϲî5.zn JC(\?; 2*s-!v=OEi1:r/y.ݟf^,mv|Nx p{ e0 , !D4P4UIyT t-sG5HyӰZ>y35>N2M~]~>U;zIw~: |i^K`]Uoqj:۠M4* b&9b}PXʨ}:1@73[-RV_R9_KZj)_{K2CypbH'6QN~TϕOucN "3IPt3AJL-zw1.NE#4ctb0]7p%w?}-Ϸ?زDˉTib!1, 5&5ܛ/CaӻITXN~R!J)6%hHRX[f2VW" v &}9͊Sgx㥑cE[&up;qy4\<ԩT͒)Ң0Aԣߨ%6$VYDЊn:@Y7q G[Hs+wq)fΝEL[^9SP>cp󡸂x ;[P2 z琷ƴQ=$gPqMi_`w]ty<<~rf1FyL: Ϻ9Bn6f{1θ+~|z((@{9j49N3gio,A) S=c.9G=k_я;+Q2t-뢷rERycG Npjγ*{?t<Їb]A_d>-_%_GaM+5yieH) '}Vap..P9ݷu=XBv;U^2^7Sm*Mkhzxo>F'&3=Qdm$ F CeG k-s)=C|36%z &J%lMF/DZR0RYH$ӊƗbeņ?5Cm$p$_yA0k#1]$?G%3B"]%5gYհ*"? "~gy&L.qK^.Zy| L`vc'q![KdS^q}Oj]QcIp&)64TZ>]Ah4RV5vyZtK,y !s;Q}V PR fXw Wq|- .[yv޸=KQg 80c؝I+pi$rO/F]`7q0hN`@/1J|֛@H5MƦPJ"VDsM .7[IJ}T=>xH>A~W$*"74?%`yݒ"M.%ơ*xP@6Yñ}0}zCOE9nVgmKOt_;=\"Ċ)w"t9ֆ#X> ]4XsNAoڃ(]˻f۳H;*'m~kKQQ\)?+#+"< AODty}]FP/-hk-uth 4䩦jFh'kshsz:c} /ZCϷMɿ[Zfq}_YIACt].anO L*[>Bl yC4gsPl  _ !Ԭ_$g#j-Eu  WYp^P/ Ǯяz~5.TviA `wɞ]Qis!Y"|\FW/[}xn'evcnaI\z!Y xUU.X $50ShD0u=nN/𲆍~%GrM^RwC@ ŒvE!n.J @p70BR|_뎷z%@BpyKRO4C;HI MA((A\?Tְqwx p%=:T޷̒ndO]d9;d"&5VCǐ.;- Ir-ig ?׮LPE_1˰mQ}"ǵ#ZĸGniE tّ5XKˢwAb׎ Cw2uhY< z?g]'%,3]G ktkC+Bǜoߔ$Ф.g1άU"y'XgS` O` tE!]V\Y 旐w#93fBْU%#4&K~#K ,1n|{1lüY PCeBy [%ȣ]$L$g "]J"{*Z#y_=()&UJ?@<~rtzW.>(MQqZk8;B]y1Dt+fuKcHujw7f6BgXџϘaTO݀4?p>0WciQգ^ HQyl})(u$NL~lfJHK;y 5 ExX Փ d%<oC:Y<|p wN`{e4R'{lB۴dIቡ8gc `k_[Li,$fkxw.bBz?aaӻ-zm gNC.(UE( Q(R` Z83cO఺V8%x8dBFҝE(JThl~*XԠY0;ZP9B?UI>}3HƴfkP0+x+sf+E :L@ Vxr&Wq/m R~*uMn+Hǰ= uRL׏x0js{r D;Lq B^`!5൜X% Rz̺),ZhOqD {$#0=m.ao*h{%Ϧ=/Eɩ[#ҠwP΅d!$X+(BeGRӆ@ePLA5 x^̈́4Mi.$p6(}Î)ԳCD ڦ9d\ J&C:(q Qnei֌IA(K4Mrcȶ rǕ N.]pcaoۡ)![!E :&җ ȥ Wp2!c(HfDzcnQD"yLޤ$gKyBS[ &x3c&] II& jQ kWW <|6▣) ڵB;X7跹1Yz\8cQ8<Is)&#Qlcj|q o0Y6`*?ś1}N^l ond=A.`4L@ UmӺ#8XKL?[Xc$b]B#HirJV˦jř6yipqaR>|O*F^~(R B+ ]"RP3zRh: t8hrR:&xs)N6Ȩ[]@!u*=6KCm'qm GO6SP ^ i\ʃ`1RM )S":N t1a.bEKx 0w>oKOrևwr7 cJ8AG!W H^ђI3)) ڃ Nj5>8*ʫ){^t c"vѾ$A3,+1.AA}\הcm-GH5֮#sov$i@s)lhy];T>a.|Z3ǸG8A9̒8z׷<%طL1d3Lz I4G47NZY-R^sT p1WV}fב> M:V[[jn cJ^G>I; fRiM H\X4 ee8cQ!ZZGx!q\qZ VoWT@>5#+Y;A}_=`x4<[j&oIB$"{$B#w9N <{Q/Ծ#]cg1w,|R+ąbc~^P&!)rde,Y>)l)?{6k-ZmJ2O.@EhWM$8E4"r%]-1ԭo IY*hcrM%2/K _9.b\YlX8dҦ' bx .p -_x/I|[$2 7d SdmbFu!`p.!JjTxR`=%C02Vr7q`EX4.Ӥ]CZ}ISBTXq}T˞ItSxh[Ԇ,Hf"uA,Ė{bl-ԢpEv'-wX8zcId<t mAi*$%@4H`(__%TvB0cx/F&1R'RJiBIk<#RyYTXSݜN-*lZ.>pGF%HPH.$?td`cu5?Qm/{OJ*wlT!*/Uc+o9v*Ow %:N 5o~?-YO^I^]{,~ >?\<\ %q%p$ozƴ6Q"Y> 9su,O4|Ͽ">7B 5q[O0e0˗[%Q;u\9 {ԟFuqj_n* iMꇳ/bjCkB8;66^Qϸ;H4hРA 4hРA 4hl#ƜGIENDB`robocode/robocode/resources/images/explosion/explosion1-6.png0000644000175000017500000002121510205417702023710 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME$+[= IDATxˏdGv'"#3+"9 E@C CBa@hl^+m S7,EE{1hZFpnvu#_޸q$5z^Tq~Efefey|q".1bĈ#F1bĈ#F1bĈ#F1bĈ#F1bĈ#F1bĈ#F1bĈ#F\DQ|_|wx/ ~)NR|N=zUPw~Gxr3Nt*#шG{SG߷dž7 \Z Mז,)iⓉF>xp꫿Kz' c0ۆeCe-G_l ~e`mjS@G6"GoDW4L[!JiR3Yflj{s('C|@~ ^C#ƒwϗ«s'l g9^f}ITrKg/WHg)CAHT= i"a~l(j!. E%/1$}ģrj#M{|Uρdޱ[:@{$3ks'˂ۅRZ,9 Y>%VtM;(a`$ #Pʆ`:Rq&ta8ǝZ lYHHW(߮Cs+%|&afFsI$]7ȵy&_m p\`31d g0YYnYbJQH?CC- ZPLzF1NS85PM$D'p H*ꘘ6K$-f*Ѫ,$s:>ۿcڂ4RE_l|^,SK-3,ҖǚIYmOD5F(TH-i%]I٣.r6.0+yT6@E]QYE4* ZDH:Dr)5"' ZbVMxg& [vJ%/P[R.V8S$j16 &chQZbkL7."dQ,M9 O$@eRPHdCgne`uRQ$NNu()ݵrw ?8/֌|z6G# U[$ڗ9vH*Pb]8xXM$!A N%vKR]˦W$FGH%[25i`m@SږSfJt &5y$*R}??QB6@ÿ^sǚ}vJr!Fo` *HH11I&`bl$+s uAip j hA=P!PH1+RXspA2k[v}2kZMܵ tёj3By S{$9(mD@L!=$: hDbhuPDOBF.QK4T':G E(@(!)bz '. eIQjIlBd^rY('raz^ɛ'H3'HMn$Gl+T+`MJOrlSФ&T &zI H걶g%44($)>8$ M 퀈G*P .R,=k7Nm],ޮDpf`1*A_q(pF!G3Q|,Lk(->2@ACІ9[HccDZ4AMK ISn C?/*AP86{G&~$pS/`n0Pw@a69 o{ M Fh5bXLãZp8R DےH@h*q&R6Ԣ[ ?~} NxrbۗwWQw:9ܜaC=éT7Tpe/4}yOKJс &VXiQUk&[HKc54YxApy K«%ߛ)f1n2=ۇ4V؁-gMwIG|iaBNhKʔ=:}MHĢahITIdMim*ҿfg a2S_@ >[*Z[u}+փ?f'V0fOyKoF3P D!A'iM)->HBE|E/Mpp+6|EQ $"LqfΤYn0ގ(^uy @#eeN[ioCnc!& \@~ԗh%l ѝ?:`^Rr)A(NT1d1&; G5w4q@PiN k UuCp)s+TㄤHa;lk@+Ũê α쭄{T :pٱe-c-h 9"_NJǶIA#@;#fNΕ(mݛ$eeUGe/D$`PD脠 ?-ᵽ4Y'A}F*ł$5)"vgg;#{ĤM Wk$zvxB^X(Z}b3 `JTёT1Cӗq[ >7̎ * \mB kr03^V+H\aq;`I!v `9BcWgיZKhB ( R.;h`͔ 6HRSR05Du, + /фXd-kiζaǥn'!(xvb @?<ᶄ%, `y :$6ebpoaI !.0v"+ZCAѫ:/186{R"%X ;n F5`z逗x>㽕m(;a'ɰ X-XP[C/Y_jP>@an `LmAp1\^.0WJ[{JVҼG7H+ H9gw8J%6ruBTeaD{K/_G84<ŜĐ LL`z:u`rrt eÛ۲E?z-p=R/P9ESItvo ↿ÎvfvgC×[T sBD b.C^A#$ &YDK)ZG^{έOވ\vHf(SRz:TJ3s'a0vw `4xo ~Vwd`jG9bvBݙwCUav K!)$wBQD %R.n݆^6wɉ^8pabRϙ5_RggTz :4۹Aah񩇰tE[z0Ɵ@[əеYX)ā]ʥa$B\Q-A ;I=>xVk%G)ƜNkLZ!fE㳛 NҗQlG2Cv>d;F`6k#l<Ղ90K,:U>GIVѪSs.<\'ۯw4NK;u;^ch`:t"+IDH}V(CXdh: PKK  鿏^׊_n ɻN^)5aǺtIKW\trcn0bg4ԭw8z'aT DO/E%Ŗ*^DYpʶHhW?󾀛SDka2LN$gvE.A_4̣H#tkv;+ߣ]l/ 8%҅H$]%',}84{RmSny|x|$xplK+7PT3S7C5=NJh6H%"Sz0;;'AvASHl {]4tv xy^dJ^_C xxDdx|LrmG{X{tmi!zT{ituS崔y'crs>:Oư_vtg #:9ŚG7uɛ0e`AQ+8 &Q[EcOiy_Bi@gђLIiHZDqI &!"\ClHVS5j#7$id B<|b7,ik+Ol a'&q|j[? =o2ܿ/𣉥g,%ҒZ{pQ &\8;H'az=cq6_Ixy#=#`͔:q~'>:Q4_+|jaz :ổr l.{8:UD}ޙL=ࣷ;}_ 6$W = /ކg[{p۟(p?WWu%~ =w'$7Q۩mUgM#Y1bĈ#F1bĈ#F1bĈ#F1bĈ#F1bĈ#F1bĈ#F1bĈ#FK r-IENDB`robocode/robocode/resources/images/explosion/explosion2-40.png0000644000175000017500000003223010205417702023766 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%4o IDATx\yvW{SDJ3tHrfıA7ـA@bL4A1<!gHh4-V7wwlϒ)4HpPuVs~߾>A@s[bU) 6$C4Tt2o$Z< T֑ZN N0-l9.^sIZ#S|;%[;g&^Hs^sb7ت"NӉƭh|-%(JPZ64qE5l諂qTc65/|oî h%w;;[tc}tqq:/ *P S)Nm2hI 3T5c0͌(苒uW߿o$ \uv{4Stw<쵏߹h\oݔĻѲ 'X_L`U8D{8Zt8ȧ9yS>Q.Ck2t|gjbQ4:D5ʹ4cf @bp\PH6m\ N%}ū_lKEe5jڂH%46\a* đpt[ۛsqs tM aи=KC`;z8n5Gy%^Z!>ulJ5T,%*PHVJ{'ǤUU;4v exMS) $Kjvlyk\sS |j+mcmXx 9|[l1="ۥPhG= M!{hDz5cJeG˘$)Cv28QyfĥTIo N0='H=2H0ĂǎH/s(S;$]T4cR5F\B+(޺ BűI_Hd8v<(/"M5RfuY3e]CU[CDɱ85#Dr )Wqo5@ JGo%Ǥd(# +p^KI/uo@Şh,Zҡa+NWH2HwT}gi8qCxK OߺS,'< rUIJ$]cfYmFTONz*^->G8ߣ(Gct%d6:5;y!r.吉ʈ CD@k1I\d'EW)T{XRaňRV8VWho:C>E 0Ƞv؏$애2 u2>jd}TOhDCf$TbQ#bQ^} ʦ'".SD A۟cGx60%9./; ;#=  ?Cm?BeHK(Ji`PĢCN!d N["^e8?Q %xƒcw]YB(к QJ͑JBxlNNSVͯc b}oMlyYbxȨ.<0\Ӈв%"YiREޑ9%@  YH&O[IV ` a0IJg[e` P)p Xkư5[x1R y三L tBW;[ \"+f.]EG+4o'@U ]L% ,0X F N:1p  }`\ò A=Kj!߯ DSв.wOS&JM& d r}E x xEvD 3Un6̚V<9D(Lg^ ZnzIg&;'0!Zx>d&pu^%~` cYljx+a;fW*/v2 x[ \N'!Rz{}<di Nd6U@&P 7H~- *,D50YA< [2&_tSd22]ϵN뒯ɠe*-H(g8=lWpgqRQ'́j`KہpnMW"\բ Ps(I +9O!Fyu]2#"|?x*UULzJd1l;gЈׁ."bDщ~ZNӅЦ 6~ -*aV51JJkEGkHr9?} k7Z9 IrXFIj`)|? L'z|a  9׋eI N f #)Or}JFp<|[;޸Wyف8+29h.e51"y7'CڷU@?i}m N^2,xjV(zv_-#eCwjH~v?4=ˉIlry&b~手<"^yW>ﱜ:s-k}:px5p8NഔOkiHa _|jwG859U'5Y3ifï4|o.[X?z\Yy <}PK,~'אIB+IW¹xJAo\t eG>| 3)9N)OiXJ*=P}Uxw_Ŵ'myS|ܸ*8{~t#wCjշX.>E BDqOstl!|+ՂUt,&!$ڊ:GN8MxZ}Do`'jc*:L").m @X0&u{~]Kԩtdj*h4Vu.Cc hTPS`+Xs ppx>wTVr0lϿmΑs(Y;D%걫3Cf+W/5 O[~ia<#bA4ןG>#e(覐HH"e FG mte .#pWp;t `HEz>>j..7֬ߔqE>-%TmO~ϿX{V1k":dEJ%D9 yn  Q?: ܁h 3F _55L^Tu4JJ7Ʊvhك7=o!<{t@qC14u7̩ۘɰ!bY~[ѓ~ s;_C8nk!>݅f j>?2Z#AӑKltK޹)qS7 #ݥudBS|}{G2No )Ӹ=_.pZpMx/d# ᜳ!Ai֫א^ -Mj $iUǛ]0o#S7-}b*E3jקJ]Ͱ:C9`e[E tłWy0QuQJxȋw9=N-WY+{E±5;wVu$ǸNHNdKCD}";@02=J>F܃N~JaNl qmHO7D,k XOYǰaaX?BG#݌lĥ}!/`H`[$W$h r>A6PIZݬ͘u;rBM+T8:!6WC^l{+p|Usyqtb͇"f}p%YUcd!eQӐlhu/åk,pO NJp+Jѧq]21. pvU߸">uV&ĢP"' t)PijcC|%nk\,tu?r' Q $G q2x30z8lh+P%D UBR$ HzCfq8H|Jh?oJ:t(zWh`uu k!ú}/'tIts`n $nSGPۅQb`VCm2<,^mLezhF{H*Вs{om<%p}I#P#&ƹDZkfFLBȷZdjn|B WƟ EZm= 'v+7EzZ"4N1FE?_JϛF!@j1+1^k$tےUέG.6<m t 6A {^gsp?dsnjZ0?qfƷmk^ZERPz$U&՝%AA/:D9Ƅ0yI`˿{$pYp=L?%)0'·v}kq£  ]j#zQی8Q)`#ݗn |v܄cXV= ;_̰ jW]ܕA%A)E 火an  ڦU߀pxቕCKS(c$@VzHJOmMt u(ipRNJN KI sv~Yx> jv Pkm[s:0@ A84)@;xYxq+uԑ B4xmBȌL c]H!˂f!3ס[r. M BY&p=j^nV-&]AmCRM(Y-FyҮeg1wtTu7*ǝGE53q5 o@+Kv:~ ּc^m$9aBY ~yt=&p+x5IiҪBcZԻL bmOnъ ke+O-M W`clIxen{s1,9l>ʫKN>o__%9ʡqDs%~Bqgvz7Sİ毭c4@#72IQŸ}M%%b0$Q"c-ᆽpVxfϯZBpMa"IB$|uyF 耞pPTR\xj%+-`eB#K*B}or/D扄||pS`Yȯ0] B:mXưT YkFڂE%߿oyڛZ=-\&@}H8;F\6*Ȇs`'/{&'Dܥ0}VEYksOU$D2ix 46"U4%Hq?gk!܁_ n^u.{^48Q2.g )ˊצÿԼs=R;JrymKe:! P$&|)V 6 1bTPX8:+ v*: fӨبλY*t Э IU>T+nJɺ)ؕʰj#g̈l =u"P Jxn7 q [e;gJ滖XqJd|0)9g)((q 9D3n>sUfpM%z/r2Mǵ,\ 85??-֖`UmIy|nɄ@/y2IDAT]Ky{y%l~?Jk^"~.f yTlO1 N[^ U. Qp1hT7{޹ b' )Sbneq8ׇķBp8 lFFVK8ڙA{t"2^RtuJQEk.]~f[H<\u7oCFMx4N A BLȣp:׳Gqk'ǫ({ d""z&Nx_ _"}4kFQJ149)di;c^+++;牢*1ua8Ó} =ɧ@V2T2FƊ>_-0[yP/D&' "H2.6,|? )mk61s;r DU ,g;/ x 7 ~0]B*2I'HP`#mh|Afi(K ̳QT?S뒋HN)"IMS#>uiPh!B8'x@h>~A,X1GE7^Gn:S7<>܆[{pgBQC}S!jA^`o\݉` 5A̴ΉM8nqU9bd06P/́I_.u mlAoGA/o8|LX/w]Zf^Ӹ !ly)1}h95b4\x߳ 8.m{$E(ù>B.:zZ_W*6'iǓExBt0@p܇qM tvBY p]D\P sdvOGnttBE0~HČ>y w\08'TLRJ{a/ Z'0 4%kyݶcxwn'Bj8 *7G!ش;:8aF@؃yͰ}dan% 3x8i{N [f2$1B1q5q̾絞_=Gs/$"byCf0+|n-T5ETMF{m\X)bq tvHĹ uyzm6-fDk]\Z&^ UȓtZc9iǾaQdaװF%TewP}d.3[6 =kug xޑOu*!)3u: 0^ ;nێYr ^Xhu$ d|ێ̏~a2nO?_:Z aa֬uN} h\{guQ=wʖUu] ف1j4)LN*+U8@r帟=~y|4>F9rIMKQ1EH0L`vrJآn%|JnQ q ިGm63?%cJdt/^ 1Q96m+̵R*V-{}P0X!HgfI-ݥIgCʨ" TOЭ"EĖ7ㅔRYO]oqw2?oK|,j)f)۽{-M _dw?j;K{+W׮`T۞JC. ,fWK vZ< bHģǡ7+t*hv0Dn8n^7pPðtX;D\fM 5CJs,&d=| ⲛ4BG#9CϒHm8'Ikܮ1Na!e8 MTRcCd#34#5#lmֲϦ"BԺIPe3AmDz-AxCCRKT0.˛qDPYIm];tylʀg+.Nېl4tBNI] %9V{XhU4Zf>FVompWS/1ś1R$·Sfej ;(i%e!;xc1RKha\ci xg]b9AEHl`l'~55M6]vvس랍 DZ{3$ = rOqX\i26 R)kskhuo:tc/!vjQ&Q6*X]vd{Xa4z@QڊY?g\ygsͱ5ojl_E|`#A™'V 5VwZ o}~Հt/TVPw V+\4(/q‚h0>A/B4x ҁ3-]l 11UT0fxcvK!I7DAɔH$xD2j9Dm 0pU1SQSa5S_%5'}dYpvbR {ʈW݋3K3{ *M^bBY|=o.#Z9+1Td΂,vLcQ)I.J1RqR)N# B''H;BP&tqi8*Ә4{IJdnhS*T,(fB}F.pIűIJkl֊kXIC R0qoH艡I{͞ˎ\>_b|Orlm(*HP|e2Q^!-΂sQ!a4D1"! 2`ɔlnԜWq槖 9.Jqvfٴ5cɦUe":N?ƚۜI B#JEd$3$cر!y!*?8^9ϱ I 6L%T#f>OHl¸iR.'k^`@*+mGoFM. [tky ێ\wyA34R*l!)`9uSϣPV3r h J/6iͼ)z_q/R\'y@QX3=@K)km` ޸"M&]tJ)z1>!q|r#;k@6H_D%Y*vfTñ زvk5 % U_A}On\H#O-OMpGu(}Eq<*#ukn71 mF|b=zƮk^zHus-R Rncs)^?ڷp^=udiBP8Ug?q]8&јgM7PԀNZ;/҂8]ߺQi!VL;Ez+ 7?|Zq\hƁ*W1lM9aL6SY@97GO)dH6i      3! $vIENDB`robocode/robocode/resources/images/explosion/explosion2-32.png0000644000175000017500000002157210205417702023776 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%+B IDATxٓ\}?gK3=fsH" ahQrȮzJ΋!o c*UKT9v,GUz,PIf.gý)'fH{nOw{~r~w~b)b)b)b)b)b)b)b)b)b)b)bO+gO_)>3Zqm7n5^๺'#&E͚9\%8{N1xzX.8G"OqE>bήq]P: YXɘk[v=kuy! w$[_~^EHcF4NJǚGKA&Sn.a֢u'Gp!>oIh>jƳ!QD,Do|!F9yhCi\2`)j);uk@d0A&8Cp<ЩxVE~LDUdq(ƈ:c_EW1 D@ 0@ܵ!ާtv;1T΅]8ܬI!u ^gqsecI4&猥_wlmlenJБp.VFS*hYnMk" A^,ڿs3ƈDzx!.wI9QXu=` /+<.[[@sQ4f^$*$AJd\>:4Vs*dmW3FרS-l&RX*SGkd"gjpmp9?$׶0Y0P@@N7\ -oٞ,w jѹþdߕ ׈Ɯ~HszڑHk+sY>J ]95B[²d㈐>jh8Q`g {T p!֒Tk(pTfbsRB?Bn"4Ѯ2bSB{Ai*>C9|:f0#ሱ n"ðI&gx#~e}#5* veC#"$ (S,rX)p,:Y!I㗨{J)Pi $Jo%i Y>>*uX34{xq̽cLfUudJC*#4+tɳ(wFgn Y8(9KhnIHE=d,"Zg5z !> 8^"; Dk"Lه37Cێ )>8QGE%"ZGm_?COP dgA3rU'" NHx^!a&&4# 8[44$+t f >oZ Cjw[d!Ĥb!à1`oRd-œkIkoD -"v f~_|6]xUa4Bh+4Vj5 T)QXFi~^gC8k ˈX*0B叡!Rf,ً99o;񕣓 ::Xv (H ,T1[~_ u83{n/ 44*p zSؙd+JL &@ix"" Z*,?"Wv;_AcL͢?~`99s9X|K?dy]! Pzw@8vy{Df-LPjj{̛%/RE. ^=DZ#zJ1w KϯHei-DŨN^k"\ /x{L 3:g!^*5yg ,:,-Kbd'A߹\ 9/J%(iVSfӘƶM0;+ţ^ȿGb[s |"Khz i톌TV`,īDH2}IvC?|,o߇󧀤) ˇ-Nk=OB@0S?Nno??]' W x#<@$gs<-Ufi𬖏觬* <#~Hz8䦅#2,=~E⟪^~,)+t+D5xG VMW `r[eB@P2fgTAJJG^ܪԳtu=jӱ0'H3NU狕'Yj{MzQΡ8X_>`0DCM/2"."ÃҔ9v7nx &wPÄ,u*,c4Y&VK 5T^5Q@s(&n@\_ \5FzQrŰceL)I~_z}y69Xh_ 7Py[ Ctx%tW߽!~np\uəH:F1a\#13 8 kۧҳ`|}0.d( Eu0.EMoĸqH5(`{YgqR2 $q QJ*F{E`[  KaI$:dI,B <q07VDD"jMb{ i]|pZ^i z^PT|\ kb2f2ϯji &6 Tf_]+JBP+ T1ɩ63OiWKHjMc!JEDظ) Q,-QB)Ϳ*fؗ!&#aqЂ P` ]V\+]\*$! רPx`J#((ϱZZ=Sv`Gx/ N *ғYAԐxOCC:cxtZOZ|bKCo-K?IG6!r0IKR5G*aqܥ2L`dro#.c}(Uiqq҇3E\-R~aGSsj^{E8*>:pƃm,;z4ŘP}΢ϼ]<{hb(=dgAe-Ipb`Rv zF9lz)IMX퓒ͦ+:dQW!U_{ :5 ]gn^9`F^rqe (r b Y ?B F< ۄCo8&)7oy~gT ?{p$zsDu8H hH綹  '>) dT"&[VJ `b}jv*р>&k͝o->gO[i B'\L0IaջY'3J:$Wd;#>2SS9qJ[+MlOFx!Տd9Ji?6? ׯ[mׯ:$w4_W2 uhS'JL -=[m9E=J{rc1A2en/HY~G-3cG ijeWxLmYɢP0/#h*&QsdVBt`5PGMtkxnyj3,R?߇܆qCW~LIFu8Y/`t2M,0[ š:fB=[HGwdO,LsJ&*([`[|׉tbXe^SE!62TUay2HT@boO_!W̑$MRqj6ωjq%/A1TP ʿ'9ި&-RLp[UK0["yrQG1D"vE2wF#mLY܃mlKJ 9X&=eV9mp[/4 p"0˄ Ej^?49C+c{HFàhɸ1][ov^Ԍ8i8XmsX\j8pR.V)Ũ(oD)HT1E$5%J@T z1aU2B,b3}N̿gVxԔm :%9Npa8~r (@7{(_)L-@ɘ67Λ%5u=!29fIu`rV /cASɌ 'YN؆ɛ9L4yMo70<}ۆIO7x0_]WYXϗ71\W2SSӐLVPKJD AQ?2;!t M9/P+IW$ävoԕ)q'['={8d2NNx%ڇG=Oq b6h@S_=?.;7kf1 CE4sv ;DQc_EӨ'U+`}R7 YkSN9Ō9hV-3+M{فaTh|{t;#Kf03 ˌ ߱C?bA!^WPY8ր#!vü(Sjw@&a܆WbgnQe}'\Z }t`')(͊{8[x6@x`=5Laz` P 1SVbǡF4EPʢe KS,?}:͌T"<"z@f`al@. K$]v>mkWlB͇Q¸bi!yiA.*ל86K7)Ĺ3J29apzH^}p!,,CaF3+:uG X.B*xQZ=x/ y.NolFw"\Dvba{wGM$WN(&& m|vb>G0~BO;*ADn5}Ň#kaKp p~ѳ DUGah3d>RAG00pC 24H47ǭdcF&*zw@tFs ԣSc: c$s {3v[HHx >6n'w M ,y0(Ѭo+o?vG]|}q'R lL-zp2&,9sx Dl{) 6§x$J3)cR6i d5TD@6B.nR#DGb6ϟ?L$"+/Ҋ#NTNw}CŻ kb"#UB2fVE2-NSx<1[o֊|bUJ6nbME!!VCjdr Cbs 1uy !R}(Gu|~tqrX>0R(jXWYip b&탑 .LQ>.Keч+9.{xҾmgSoŇ4%pU p*@Ƚx!t'?º(1Ɗ[xCCD+s(G~HB1m H}T쀮] O,?zn:B {; fFױ1 I wmDPbB.;6攡ofFE 0t1*C'0.EUw&JѲK{HkMP'5̉ďne6H#u(H1ㄡIj贂u?E!V%}p@=O-$U}H^9Ē3b7&{@3 XA1.bT͸Yz!W1.ަgs=ЁLG(:3b'5,2,Czqqo8~g?[R]D5O*vo,T#l-FȨJO IDAT TL eRp ɣP 4BTJT#t@͒lj {?ߥREEGTD :̓DvN& n8#c?lLdJȺRs' %wr5Sb)b)b)b)b)b)b)b)b)b)b)9 _Clc9IENDB`robocode/robocode/resources/images/explosion/explosion2-11.png0000644000175000017500000000440310205417702023765 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%1IDATxo\׌g38Ii-F*.C2J;]T}&@Yv]]TP%%JbS;1$c7]حPU-F(39i4,{w!B!B!B!B!B!B!B!B!B!B!B!_kQV/}AlYqP(F{-QȈbl $: x"rY128ly˰i9t:fE#K-=7M?n[1%=.Ige;Xkg \C8EgG f RT2@1a?Y%,)"z7)]DcE[fH'q($ajɇ9DITW7MɮrJ;e՞~F93uJ -xTxG6U$d)|vz!:z [!ÏR>PdaIXcDvC,Bo7@@Exo--΄ln/BT[,SP{ir4|s; @(t8LV~ R]K)]R {dCF14 HJܢ O;jexIܥ]L+_@gPXJ p)ՄBQ+˖ganoFcp?AvZ`|D1`3*663Nx EW"d^&͎ uFp*YQsO'_,ic{y89Z L Zp$]Ǽg运Ù IP_[`*}8AeiqgPew7`lKNi2wVX6 PUS`c;o| 3kWȨoJZh*TP9: A4'.t74ˤfZ&z0vU_o h.zc(HgQIM[?D YDblT"e(w4enI; hqyŁ r}զ/O`*ś1E:aZ'gU~cNh Pڛx:7qA"HuuF[dpfQ\~}[G6^$r`%%T[?QTvҋ<ؽʝMCaj _"nq=r>BwiWOd$ÊFt!k z ,SY;QcV=w9j>a'|A9GnsD=[E0yĬ\6:-kNI|NRAܟlB!B!B!B!B!B!B!B!B!B!B!B| O IENDB`robocode/robocode/resources/images/explosion/explosion2-26.png0000644000175000017500000001470710205417702024003 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%$_ TIDATxُ\}?gK]MVl.2%5%يEDa0`^ x^e6`@3c;رVȫBtEͭ[uw;ýMvk](YuQu}lPRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR >7@\Zᕥ>0$X\t}]\x8s\\rV!__4 6pC0zt#7>x.̽erqq|؄ >0_zWEmk*J2r*zvęlfIB &e,-x8xX믾84HfeZJ@g \fԐnoB#ew<0 c@'C@SWOkN4:d|A i|KM)8!cTVUb]Rǹl bv-pq}#%`cgʆ N'OpAx|FZe7:iU'>JBd̡$^ƩMBʍZ#3<8߼h/Xs,YܔGEg+%[xc9+KwKo}ţ䛑D,*L҂hO"qU>Hqi iNx #>OuGꍙ'ԢlcǙś5jCä3^#A$MrědY'X$N'0<8CnDEA3g-DZrtα,Rso'*GG0sYpOn(穟(o}#91+Gɡ ab× LHLOlMb<.MfG 8@C@Y" SGfc\kՑ8ĊPߜzD}sU:>Q`4 P&:dQ3h{~FF6'A6n!>>H:C+ QdGem֢[`W JƽR0נrI$O#C3!uFA6r*;:Zm3A gNa,hG38Gf5wKhF 7髯A'Q7ia9 egS!NBb&7fH&uT Cthqf&)>,@/!ov3) "HbaXp9EB}>&ʑT˦_.t$'>ֽ6Ӽ{oc. g9 0;̱ 3UXíݼVW4'hBuPQ J! @g : 2#Ulr_5Or47 vY!]89'K~׎H~{^ {`OA+@8Tq`+wQV] B-)3B(\1"82Qv,w}BL_>`*0r%ݨN]APk¢f性y@># p|\]=*PW~NˑZ,P,~Zc[z-I%zUs}M B*^Fb[܋'̏+V}8 ,{:/wkyp$`g&?hLDH"=Fs1Dzꌿ\h0=JbEc^#0z0VXS9R , fI1gi Z3abLzsY:LT ūe!.XC7coEBeQ/7.Q!p&=n(a?L?LprLdԈ@NSd4Q_70#񎒈|w +HWkk3fLp{#%pףwQ65[q[&Cv =Xd› B'.\شu,Ɛ0F~LQ#5?SCa~s }~ =Z\xG*x4,o,гk"U p[p؃%s0c~8fD*CaH=C2ˉF_ 5w 6@5$$i_0Θ`/8H/0u qq ~g/c6VG ߉ EPjE, prM ^5޼;Nv΀y*Y\8Ay9mp xҙT#GZXI)yɢyA m•{KV~3=:G7IegW=:>.&:L(~^>+Xp>T4LwHv&phyQb6z] ݛSG(d0Q`p|+fZ7PDh;Vj`Fi=%<4}tIڂI Zt;Q)j\[&8xr_)-BYȔ L?W^yl%TI&i6C5,~agvs-EFZ"Y!2)N02Q2SIUg=dE`#5˳o⡇%~DE䳎4'@`sպ \F$U:{hN^A $cЪƈ|ؼ8@:M>:(!sHEnb fTtLfz>"8UpMfO1Ύ HʄAs(˽BYRKtS6e9pw+07!qJ]閦O`pAD(DWX lrCc8~K/C[ 222P n!{;*u i%t$H]J@Op?!O} Bɇ}j>~,Rla,VnuF/%ɋVJPB@qo0G* ]ܯw  !P1܄Q5}l|qˤ~`.7->$H"CDbc$gNunzKh%oCHTtq\rG+~sЉ&<fowA {UQ+@€w$n#t0x|;l7!0<@s' mAb'a+eNa+{ej5q2^~>n3Law xhn@U 5 *5;A73pl|q d+T/|EgQrTOw#n7,/*M ůYgC0H@[dvvݡGX%M|0i(7M8:I qFwNΑy}zBFHL OA(budKMN cRP7nvα,7UKQ$e2y'2&53)e}}f1qXpS,΂=6q_/n=Gy;>=i#EqvU,q}ZGut_4"Ϡ.f|ǹ$ӲaTn|okH=GGaP`E#li?^ V~ eC m&gi`|ԻkH,&ZŨM0VbqO*' _c0oJN`hZ,Z{ &Qw2>/fQT1MF ṈA`22!"mm+ܺ<t]6ʈQu!RJ2[%_7GC@$cCGػT1Ҝz~1Lh_A.C(_䗖9vʱhJg&vlFLv`c8qMTm =>NlǿD/rmm2SGJ2v1QmV$[:qF-&vLE>|If.-|Ft˜o2 》Kp52V[x&`HCaSpFnb1^P ux09_Ŧ+H EaGā$jYZ(c=`Ϯ"F "Q-FOzF{ds)7Óu&Kӓ%o_a;S7ujc]MH*Ha@8 #铪1֋v1-j8>?!3ؿKcm&b;Ɛw͘,r(D`@SOSpѦnJ9ؗ=V:!aREdU"/DGAJH8FttN H6BZ& Z1 gz'yg3DTYҏV*f2MדԀТ+1 6|y$E;ggI/)N*Q{0;>8_SIr$A cfאM:qB+ *3Kn8,#ߩۜ+P|hGvr;C\Z,БP+Fk hL;LcR4|KU×"RdŃ2Sn.X^j4$'6d{Q~ÿx''⊠{S^jėJ8ZՆշ,pX"-K^/Mɷ[abKGD pHYs  tIME$&%JAfvIDATx[le;3J-AP"]qQ4Ĥj0n׸ ViM< OF/1CZZ:3E =1tNx1'8>b_9;"""""""""""""""""""""""""""""""""""""""""""""""""""s9<+&߽Έl'lhtpQǢyML|4ԇe@]pW 2&cCo0yk<@ P!}/f0;x'ҿN}Ll\4VQ',9 VoׁOTTWh`!.N[]N(=zMi^O͢4'k ȧa0 ^Wb}i 6l?(-Ii L6ɁMĦVpxa3UsXoWC` G$aZk19gޓ_kx")e?%O7 ?r[0/e!L" G݆>Cet'ndkx?pq< tu3(JʩS"""""""""""""""""""""""""""""""""""""""""""""""""{@IENDB`robocode/robocode/resources/images/explosion/explosion2-6.png0000644000175000017500000000261210205417702023711 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%IDATxKh\﹯yiFk,YU;R[rHiiiM%Ćh*B!}v]` 4$EKHڐd0Rْ%ydk̝:] )m.vƿj9p?sADDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDs ^W瞜`0baV}˛G7ca';K8,]nN%%2i?7Mϝd:ܥ~g HNgg!2kmlQ%9Pq.\s>g8y՘Q @\j=`ߝΐDh# k)bu6 .Qϔ 7y"y7nc l+Wug()a^du9hF ~ wJ,.lC~٣GxgﰇSp@tR5 mw(ۿ5$Ez<ˇ\`$4 ?1a w!tDWl-~)8>_D8qJm"^ r XǸ\/zrZ!vi #:i׉?]`onSmiҰ T,CQ׉wzxB'GcVɌA>]wc~J|&pZig"=(y()V0Uz%bUց_B1t3z$<XR$z!z+] ĀG@`Lw1I{YkyF ݥ-U}߱q8qR!!8._:{ӛ#IND`d9<"spc mw RBBQ91/$#b!AC^mQqwxpր-d9RkMZZo24\;aQ(Y9|osC}͘4Rd vói$DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD7"&$BIENDB`robocode/robocode/resources/images/explosion/explosion2-36.png0000644000175000017500000002547410205417702024007 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%0ȅv IDATxُdW~9b=+k!ŵ-2c -cF@ <24?Ѐx ahinɪZ=+3rng{2j EdDdD=~ 30 30 30 30 30 30 30 30 30 3E]^ۯX͟?t-o ];x}'YuM 1=% zs`w6=- mkRu}Y  dwUʶd 8?lP znlz~?-tDx" =7\$ )ZY=V4mFyMK=*2t>MǾ2Zz˞K_.m XvQB$ЬDm^e^JBO$"u,J>J^|\Vp2\&CkF_cD0 K&JqٝĜi b!ED(YL,%yДHÒЧ*CS =rϹ Z޼qm~.\o=$܊Hؒ8/{_b7#3D1g5;2$M& T!dL QH[`]qj dGAɭ-*y~|M0`asٛp^~⹎\{WO$nK{Rk=@{{MorQwZ'ba'cF椅 [hZ BGx#ewME C72!ewƨvIW f /qW0vr잫fә5rsbI/&`Qy, mj&V_$~MPzdG&QK#X6lcm)bJ:(}7O#6˟qlR]Kt85^ i /+ϭPhO ݐ&7@i.\xd, Vq?к0]d-E]Ļ9x mm M_S"2RKds`mc ԆxAp|>AoD! bsmeΞF1 HL7^F;<( (HK퀂1 b7ੲ2{ KC4'pr $\#Kx*#wy5"266JL' ZӨ5/RS\Qf S$."J<â ~Sh-@ BEhXЯ"] c޷QmkxvW"JM =B#h@YH8y|v2ڡ,c ~r+X=+cM=^$z'2fP ݐ$!45( zxBAiJ8$Ex(r 8& XiOI: y 33|bT[}Ɏ*)9QħK~vrE/"ݗW!t 3 RP,W?|QZ<&+kpn#PwX !H[_gkA  pDDz=° r0 &%|nX.@:-C/P!қz찐˩3z!CȋequC_֋l 6ЂuT%eZ1qh.. J)vJ֢ད-/Ke(Hpyux#՟ǃ.iZ$qEQ&jMN8Ji6MLz̡P *vxLeD?>+M뗎GC=y`]AHwQ>%6c~[wb5.Km&kKfTG&`9#M,QRil`eɵ9͒gĦ%s$8_{bi%y2 ?it1:%P#JDBx &?Qs9[92*;g/˭'h=tk|6 oY [f+NJ/Iȧx_4/_Ř"K |eF$Q.o> UQ+y4hn>~CR$D )2Ozƺ\q˱24iHB4@ rFP-֬T;c@G:[JlƗ%_C/ D' %&i*}ˊ_i~}"URjޓyҢ.x8iN:IzAujB Z3ĵ >u=YWao/ u\tb*ܲݮ?LI'n vCrcoVV :K(J>NbeBZaNٗ+U;ܓx޸`|SnhHۚ- mA#yPk urf qq<Nҟ^9*B,NYBD !obg[q3I3ѪC^-Ӯl_\z_;~QMY=Fр;z9LJ|O}LC.>I }Ï׮y<; =;ߕ,|W5jTцm_`AG<7gL[Yȩ=o3Oݫ_~ި̗0р[ %]D{ NJ.W Wo ¡Iʱ"cHжM s4j/ֹ\؀%݈*QԷS[&b67hN50EW&Df1$^{WdpE!&Hė]JNe G^oNz?DiYXx0c:uh[9"D}p4*욀 SH~q\GC M%I&Q:1 <; 9Vٚ cL;!"7ć9 [i~Cc='<FdNK† oިX׮ ncA$ZH *ºCH@W:3Wٵg7# ܯIVWz0 W"p/RQ8ADV\it5ON *)7jCSF8pJ^@t`=(o҃JG>Z p8"ONz(Q>ƛSHh5x_nN >q7jg0l]]dA! V:B OzKXmxrpՀw""C*<YyD),UA%K8h&]G6 t򍭈,H>K;'< [>QjϨ倂H_/VڰJUP{X_/>VTkE՛0R2Obca2pē纩ԣij:1E2puFisr%(XN\ju4ogkaoԩQ-zS@:b!f 3+Eg1#= ze GKMNr(h7:UB:(,y܅K F [(,F cAJRl t#xF˞#O9J]22!6J%uJz]6[2é1&YyR ,g7 -dwctPõ{'v{n4B#.Noa3iZi;]AYsz=Z<,}WbI{>oE{H96%+#/z柳xh0xvsmxr GC]2q5۬;ߍq +5UFJF47X/oQ|(;).*Gˏ;Y~CnK򎧙 UJЮfR&=4Ā2tw*YڟiP @^oeaЧ3o2ʠϟ.{l%}u-.&ADmⴅtgdbv%em>2߭o4ՙ˓<\$LJH̀@ƛ ی" Ny:H%3=s=V V4Oc2* &9S Jwk[ǵ׳ZFufm' Эam@Ub=PHInӒƄ2Ȱ6hN(`>dN3L`~ JJ!lL>/nSm0Z |JPx\C㎩9V.ó](MD.'u"7fՎn?>?::pZr=QM,qa$e5T@zO ӕ>`!)̀ݡ2ܛd*w[~GJ_`YKK07B$,9O#G;GqOgxjQk~JSG;r Jn$&M7 yݒ (4e.=E%Eo"j"ؔ"h <'U@jOzSjIدí㈢uIx8;FeƠaʰ9aGy ?b~!T2qs ?K2vn:A-R +'}F>~o k68N`) R㽄1t3D۞w(HZx׽X`UȡR( !9:='*5nCt,6j!O8(8h 9n!&0H \@*$%\HpSPіC-Īj[c>;UTsZH뇽u.`VdD%#! N"H\G9 mDԶ'rZ|414ZBW@8TkOӭk|"dMMχHyǨ0J>{.#y/}X& B4'2_놼Q2W:ǯ8gՎJ*tA aUV«Gk\1|A&y)lXC.jT'T?kO'nߢ(wb C)R9)x#swn ɨ%Wh))psP_9,E}_Ri?fBj'~zx ^I ˀۚqOP ~2b~" B1{/##8eXnlB87p 2-堇Ĵ/`~vaM+a< 9<{W CM eʺ~~1<7gb=ۧ]7ӈ >mS5a¿FT">Njݣ*m_=@YKɐphYVn,K Hֶ%fG odrFZSV5gdI l;w!:Nnsnޫ?37`0߳t.+ܯ֝}3ٛx1J9:㼥*Ex [m4JM0n#C%T  evP2.wOտM414]x mGVgvۇ>S=A5fCӴAztnlíMՇ|?l@[hZFczK^ ADqU L l>OC{Zӗߩs5>W}>@/!as%p.xs""wIŐs'8!Jܱ9[WN @Z(dlʧ9>+0=M!!N%d:1t7|xHNMt&R3O/GjpW{YD(yfvV2Sxz# aPT{M`lrNJhz6#4YK i3t#z V(@;E!}˼8kUS IDATMvgzqN 3(NW;t҃R6msS&:dG{/q"iJ5;1#8Iut;[SyHDԃ m{(="wmÈ!1j|VЛӜ-(j1h$*1T 6eRJG"Da:E"ϗI,6<)c['s&'w&$O;4/^Fse) )|i{ MVZ;V(!rT#M@8{(MAKlI$C0X`qemxnl:РG|2IXqgdz E8 !;.qucIucA$hjlK~zS(V0~D))2ߘg%Z'P|%!l `=T0DyQs/;XzݘHx?#|t's8k6%w1cGKh!W"]9C&(`(;`C|1clOp-̉Fun.NF!)ROa[䅧e;s{%{k˞K ʂl7B (^bE Ei=p<C"Ra)4"s?z EOKf42)&oA&j1hA.9ZpQ~#ed, ` lR1*pq5`G#\Lx@>_,@<{o{6G b=IPH&8vD"qBOyoJmH ,@W C @j 0b,#X xQ' i>S@1 ϱ9 YU~GBOr9"g# N<ʱ"d9mW+h> mOeVV@ : QsHC dldL U/n>cl'~ Yn Ab=KgwIN,a #!Ô8` ibR=<= b/X2\GC}b-CYiwid ̈GRzG !Q$Qsž@9,]L>¹B%)-8L ] ۔~'/GH1J(3JadKrU8)&BF$me)N>E4Ad#&*# DZ2%Ɛp2rLJю$ck-yz( uf Poڂ"G[;TηPBPR"oqHUb|J@=Q9&caq^ܨZ 2E3r~h$n$=I٘#ORve戨Lq.ZRE6: Li5Kڍ֠n˲p±c=]%x7IGf}V4ͽp>! D\$XNaPESxgDi$%IsB+xg K$mHq%Z.K+$x *%;-rpZ"d/hdNO^X ;qK|o9> ?EA~G`Qs'Yis!Y*c6^X13c9 ֌zBH ->ܽWgG(&lȃ' D| k_D`/)H)]h'g:FɎq]Ceuǣ}; q4gkW$ᆲPfD6F qtD<hI^xAd*SJaEhRe|ze vn9yF1F&i,A <_ bz?lqΘ+4+Kq!hvx>4=ǎC}cci! VߕDGZG` $DaJE@D2gJ(8Q䌛%۶$68kEɻwQW1N2ȳ:^x[ 1H(i {Ю7-?&Y >mɇY΅v%掫W˞ TGy4%_\㣀IK!vDhr- p,%enֆn=4dezSYHؒs}q~s'x0 9laV2?_pWƕ*D\~\' 8? Ruey (8ŜL2ʫ/#4`IgKz<.ڃ=TCGw_VYnX_? ҴpЏ>KxHw+1$e  [ٮm-ckjC՘8/,>;+amX|uD׵E #S~#zFϋ;+Oefafafafafafafafaf[eHIENDB`robocode/robocode/resources/images/explosion/explosion2-1.png0000644000175000017500000000134710205417702023710 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME% y,RtIDATx_nUFM TxEKm&⡑*!rCB(u= 6';: $I$I$I$I$I$I$I$I$I$I$I$I$I$I޽뇗RK; 꿸ٜs{KVI?=N+Nibnv˫LYQrƊiۗp/nWW&fg>{@$I$I$I$I$I$I$I$I$I$I$I$I$I$)ma~IENDB`robocode/robocode/resources/images/explosion/explosion2-47.png0000644000175000017500000004527210205417702024007 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%;_W IDATxɏ]ם9Ý)JdKL3]m$V^TZVUz)oh n4Ѐ P)23;9Q$` o9܈ð,Q)ە:Ëw#{o _/b}X_/b},_M/ rWDlpwC3qBWpW; k%3k׀7xݸsԲ;v'Lqg ~k 5"<7\`qqd,-{,7߰yL ~kW/.}w_s\H@* @k R KZap|brP8wܼj:A|Ŀ5 Pl+KI"JEk:+VPkIteGW3cYm6,ˍ!az/u\Gk$'7ǚewGw4[Jq\eTjpkTh#N0,(K\ӱR-E`pw1^[Ӂ}?]6&6 'DUG9 S_\\vK[xu{A5я5ߺ,xͽa†U5K0)Iw%8 P`\t5Ft]V[bjGj˗r ;!xt~9wC xx=qquO3`*q\9rM>)&;QB=H׮ ~HbfX%vt1iPMK2Ʈ`)qF6!3Y,saY4\)jaIhD(^yOK׬WI2[b 1l[ǎcc-xV)/S6.+(Ő!#b6S`;!9Nzfv!ytby>tb-g;1Yb-Ғa0BA'O br >˺q\Ж*D&**3Ĥ2A͌*Җ+Zn\5|ko^RwclK8M0vjhS44APhݐݤcaΡg89AM@-dj%0ȡH`I\rܾ@'tnQVϐ:sP4tJ& HM4KB"(#pAjpRue5udL;t{SCL$JD;r{H]1tUށaN~2'UcjMZs:g;X]%=µ X0FFb[t31ŽQnɈQ@|HqAe!K8X ne3)$#*k$l"Y .#QNbM O| ph&" [_*,&Y|ot+p"̌Cq1ǎ xxwyS+t`e& V"h#x6&CYG%r\ y@HqH3nKC8Wx6VqրP6n@l!Inn`A#j5!& VAU .A(M8IKLF[ӐHCA@&9@U joӰ Y% +\y&t)$(ɕ \FL]&9&Kɒ;`$35gks$[<Z:vRg ,Zߣi>@yyò 0SX#/ݫdY c,{=u` sűW]I!H$܌f+(amyƫv MxyӇtx@ jq!WM9zxڟ8˖;zu1^rϷ5[Zqo;E!# Ǟ ؐt$0*<:^< U &"1 Z`±ixi`$ w.duoxzWR0N1MawIGR:i9WN9 Ǎb:2ZػV/tO2_w =Ei5HxOFXʔgRLWP>q"};i8?6zMFmD^oL6lGW ߓEZ' ?jdwUCyt1QRJ0PY]9G3[CS4aOd}luYq}b筸F?hHǚ$+eb- PVޢ:UT#VlVמ0wuf XFF s lMΑA чAT)R#+=pika۠RÜ+#UWr'>wݩbKk^0 9jR Z7bS(7;L+n70l 3xvmt:XceD$2/ ?qCOQu*'L u 5/gEcVNVԣ}?_eh/] $u!gjhf]JlsЍ)#7QIJ*s\!lP)\Hawƃ76U 6Q3\P@?6mkhwz~C@l#{Q!TI"c #~; lUF$- _E"-J"²f^glS\WְctpGς9myΥAO i("pow pm.alk3`5ٿAҰ`cˆD-2S+5'\\o|)HJdltXE?ޡS)&xPa\C$L@yn#8f@v|q dt3X XkwE\ mo{o@m2} c~8B_?7pk \#<8u`f))F7`Qocp({SP.O(dK(}L|OANfwAw y5 &'b}_0Fz&0F`#p{ *p2Yv % kxljRp}w߿aމLorXa[,[h1tN@<֯֫EC?0/m<$i;lj/a"2;^Ut{"M~֕FW>g5ss'QjJ&y&6.Qu Ӎ2-5H^&(>_y]5ݩ ǼV)/0/hK{Wńq&x*+Szfmqi[4b Ƒf+"j7;|=op5G0v)xS A"O:Vd42Ar |29Mȿ7֧^R Խ@y{Ipc8g*910 Ry-,}ahSTbZfV*V4s?Y M[n7\3}HyeG̛Ij:K7|jV8΍S_ux$p%'T)ùðy" 6Bt0F^.9LW0Kf vPTmS RH7Ĥ9-sMV䝵5;Q@?x_ñb > 5V7t&eԥšT&lj(+vdm IPVnFo]aVp=/oAI8"( ]"8-`? TcLvH02'3S$rqݍ.W^p>~ idFZMSg$2s:CQ X(h]VL$cBFX[lQ kCa}I'e"IWQfg^~ N6 $N/bcwv{t.K: Z ]3cOwj aup~h#)(RÌt& [Q!N`<}q D"l%(p/Ax,^$ӨcTm(4,}Qau/6rl/Ql#i*HK`5eˢhR'x2rP|d[fTytLMr{F8#J@ΧO`4vZ++hm`D+x@4@(H< ~t޳;8X!H ! z`ygװ=\\n^sȇ#YJX,UhS1b Jeh e$8:oB6e0(&HQ40?#~馺_#'m+氓% C'LI:b*}@$?ퟭ 8ӴyB[bzR@[,)]aF 'f|mI\b(l N`X( 'LN}յxA:B>O9|I3T,J~8g^fa&I(EF) l:@BX k5Z)0"ɐRK*{?)g0~WBoz}*0~pMe w335p m2bG ܚ, 8FenFaSٲfR;5?T7Qdd5%RX[ Es9  XI"ߺ9&אkfɔor 0}yq7dQ`Em]|KD^R-ۄ<ACqMn m-sYs' ñ~.%+פ̐"ÚB0R!  74̷gWk9 9^o"5"FH‹PKQnK~X^ÅN!'=' 8&C,|%Qm1ĕ@w)Er#xawKDBNZQ dX!FɔNJ\8$ M"a@ _kOD"QeO@`}FOթ-=) kÆ{ ;$l{sڏ4W9ɩ0қ׌)V  -ɄbPܭ ۙ ^jP0IVTZF+:@"Hqh$|aY 2d'$\I=Sճ`^bF$Y8#m'2 V^Uqm]ú' pcftbT #+)ฐ`{kp22|V$@6,*$hOlRbD8Ei NDE9ZP!Dս˲gy#}r%E ,ԜTr#nx}&BD8V_EiO3iҗŕ5^R _\WcF30*;@#\? W@B P8X'QN`V-|/ƏNj ion3R_"lAp 7yt3!dŸ\`开6MH$aeRa;u I,F=S )AP IDAT Hb)X!@cV.>9޿>Xgw!%?֩ĸ)Lx"_t#-㻍j u%XsߤB *wuR`?ETF" | +k+dͩ zvAN'GN*lV=K"L_FI~\/#?D>WQdiף*0V]F8oSX(Idid-3= tgI萭CjV927? x a`ej,lTDt4B$VT3m#?C;ykf`k7\`@yy "qu }ծ^}Ql8Gnv6C{_co5waxX@XJUEm,k ׎>xx}2ڑԎ&\C ¶4Ƣe'e|RG:Z IT՗ l۷oS;х6Ci1Q}Ƅ2B]=}6LBgFPt/+Ng* Um;녦`jt-VZ:m cc?RǸ+΁`gqqxkjpd UG=6 6X\J ]ab@4>55M A9ㅫsr`rN5vV27q&2F8h+#Շu+NڪrQы=u 9מEn3`LDĭFu5ݰ#i -W&rOK{dॱcwxÛڐXúЮA%VuHҤR-=TW6T :t* :H sZGQYPN ЃE(tX" w2޹G(P6J( ܷ<<~əbND 0td33GmNn3ipz㫂 GBfƮlM5 jH8n0\ D]i9EOTSaȱ3<*x`v]_wgLuD^L"s;Hq//8T>L{|E moC%Z\`  C[ 5eِ-+ ctt}T[CǸ3TGaڤA.rHBtgS>b̆/aВ4Z\xmF8AMez 2]ʳ=r`;Y}?w5rߵ5Kz]I#>|Dk=S5Pu}9Y!UtԠO~'k?-/Xr%-EVQ.h'8fW!͚Xpg.dMSPm{M#""jI܊c xQ5(cxSQd3 UÝeb껒i)ŶI &kDZ#!CbK(L7PF(\.*ؗH N(}:RmTw.*rT0MíP["pLtE6dGﳖ?yq?WP?yߖV /L5OۂeX,]EɊ!Ru_:-"q[x|RcZ>ˊþ]d7q G2 wHķ]i%EJD#Y1Dķ2+SwG^HFONmeZ2t ZGH]J(Ygo e#0ڣi~A k#k!u4760£6B|xH_AGUJMt,4Y"u~=Kxf&wH=nN&j10hG'1+/fpQlǤH? !,CfN5h0&#I˝5<N<ݵ}ih IeH$]Q-ӗ{ZHrOgYE`5`L,C 5 wZ3q+6Mɻ[ [e%at&)Ru8 ٣VTȮCh)7o& xoU V姄mBsgyظ^RW"Rq\ T˳⒭xDR;uf>&G6g4N_"t#̣yI^A,!;W#_gէfm/aa-ל\SVl\^LCFkZUV+$<1\}_ xi!g0tPL9)-ñU \H*?DN02u`_xm$#3@vj>9ܨ2k>kp[w;e"[C@ y%V 13W' rCUdʨ:(.Xۗ2̣4ϊ,3 ITis̆x;l1n=A4%i#3ת?pukoǖ yc\ZGS#5/TӜq-[?#tS]N4DO. \&!=;6K*8큸 <@&HuS6U2D1]gL ^2%\`|"UK jᘣN 伍Xe?qc(J&Ftl7Q%Q~-9#2AyD(quS\a;Qu7$fP΁[gd-݅;pO;co:gI;ڢ&M 6x* @Y%tZN*(IKX?GEk8E fקO&2K͏_4m$q;Cl3 I36eԌ W ɭoN l1B@xnm-[Lv+h+G3{5lCqsY%Yh̙DS\>vQS49V2*iƊ|%پ,·p}^aGؑfD%kG]T 9}Y(CIP"k&gb0}}NF8@y"ܠO~-Y=&jϨ^@6F2σYJ/nf~+C F1.$wW ԏQ[KA(EQ%, )MdԂ]q젭]N'h43glYe16]!TУjȑ/"fE 6/H W`SX< +Pme'(E MpISh"#9YQ`1:!0Ŵ-UcP%nīLƞa6]e֑CGj<4 iIy`EiN :53ڪWm#31q %u ʫ9%'P $AE^y&>B#:/dd.%sU2 QCSD>n*{)9^<`=`:!kE:xcc PriP%z/H)^,2ui!<8ȏ("GEpui8:n§os?Sy ?p13q.i0| W\3Pƒ!Fqnv&'dZ:cQjMkoCGZ*}t (.ϨT֬zcb,7W@ߏE)8t& xpN;3ܙ~ ¾U?CtQ=rI+j-;K9׀?++T33,#u9M;!:ɀ1۠#CLw*|H{Wea1iwSn`1k ?h߯Sߠq>L[y@GZ߳h"ɶQ, Uwz3]5H6F~wr=f֤{cu_ҧd"M[Za q<@柘gѯyO A"ñ)˔MQ\e]jicR<}vժU T,R?l&`-aL9_+Jk8γ^mQaQ{&Gˆ2&Mظb[IeFUg4̷ϹӐ> % .Uq1O 5߃iF)]^VEvf*[Y k0_(?"`1=440G.pJ%螲ކy_XMT%]2H`IR5r7($c&I0MEUAj*%IXb&OCYke'y {b∦~6ϻxF6+jD xeC)Jt8} ]+~~-י,먆\I.NHцδ`=ruxr=Fbi9Oϑ{#…uKH ۼ_i/*fwy/2"xmB_E^!R`Na׃oì'~9$gݘvh7bΥ B=l-|&?o*1zuq z5&O,s ,ռ䤃Q'A#LvA4"1\&K9H wC lڱMtc&|{34pG7S[L&W(PfnWP Ɯ?'tY# K~gRl$ =7vR3AFF,G] M@#j2F49>=F]qĪMSb̄,1k{x&ݣQv#֫yfp'ϼiuX{?ę#Ja8([U&A#1bh I}B#1 Elj@C^uB,)91Tby}N[vv?u1H9Jlڎi42BE)Y5 ŨCcE2 UtDPVEgnnj0LH1:ތ19߇~uCB< KKhX1xv1ɱtSJ;!V+hʯ8]Gt 'XZW*|l(H#r#ԢtdupjCwxR(eB>pΥpct9^b?E6D*8!ZNbd"hh 0F!Yn+7VI}"Nh $01$8o1]F^(g6PGH)2~7t= .ʔDPYA%!fbs2Y-0Sɪ""'DS!hbB͂BOUaXDQH OU޹pmHsej.IMKIDdA'Ũ`'%0&ԛPQW|9H>}ɕ%#&8E#EZPݒIb qf]L<"u$.~cN6OϰLgl=ӱsT`-;|7;$vkN1Ҥ BbNI,H4fI5*56u6()>,Ւ|eX.#й, R`WT U/ୋ D_fһFSE\$DMWDSb$֚^M'0:65#nM>nHs{Ĵ}?F$̘?4 ĢC> %薴xIX )4R#kˆdװ:e@^vGm5fIՒ^jY|Hlnh&0iU-cM Bw0raǽʏ"7+R~|CȓY`cSY⢠!cIpGII͒Iv}%1+jAXG5Ǩ?IXRLlH.PS@_x7S  s Gg9OLku*]){bhQT#Zy|gzZk BGUw9,fֱ# B;$vܼgBs)'Ҳ?g'͒7tCpH:ݤ+7f=# (/-Cc-C>ԡi8%=8E)K3a!e3O(s$N$.-;İ7d 9 Z)MIݝ [K:K[0%@z}4T8LO'=H <=:NH/v,%Pmގ&^)|_I-ߍ:G,߸Xtllb ! 먮c4NJp$PJ$ JkY EmCN:x3Aaǜ5qQN3h6˕ŶEAqPg(ˈE+ 25P3(~k2\x$Ă-MApXQMALEC ąw%?&޺3 ?T~`ؽپ/< i(A=0ҁEKJ%Ay9R*+A*5Q $%!saEa@ݬ6 N_K݇ޅ|3}I"{)}eDl!]F}z [L#$fBRBIP#39@Qxj82 3 lUܿD.*񿶔ʟ2K|Sv^[ڶp`Д-eE>SM%0YLЂL0:u!h)eqdjÃj#뉝[;|Uɳto!"l;aG!\!? \< JyVg yANl}ec=Nlg:,oy /[3ވ6ܺc2;)_*oD޾D!>s3gxvQџ%jڿ 6Ɩ̲mtKFxeHk5 |}-}K^/J#0{mag,\~L N+g8X&BSzSmF +od$-,|_n򥼄g Lpd!,jNA]*èy)w^ڒ/u'9;x,eừ,U$Y:Cu1=,4|#abKGD pHYs  tIME&b IDATxُy;۷ĒKUf7l6"%=1-j/Y| ܰvZ굺ؾ,8'*OEWs.D$r">sNoooooon7Ňgߥx~qߘ | ~c 79o~_hoe?}wipXU,^x^p}qr湟9xnEv@^0-oMNpsY-sY@ *MySI{^p2Y0:x]M!77o黒b!j2zkRb ƽ(I,e\x`<Ǎg8? ^pܻN !Ad ovSq o| nwx=:7^#x'+_/{nۯˆ ǂ%/M%#q*B6bнZ 'QA@@N{W!zvw-L B߾SSǝᥕJzW3* t%P@Q+񦠶$Ciu-N6t_ ̔gV9ȥV:4Ǟ|xLr}*YFr͐)u8 h ;rINp4^Pk%^*ptnp`-l,Lpy1xƿ%G'+{`(ҫ n8%Ǹfގ n"('TCS28]QT#-R#FV9=^4x fen0bJk`@ EQ_=DYI^NP8 0M`d$(T`  VVb|_0hk {YNw-pY@J~ ~]Kn`ԁ eI*ݣ730A3:@בb%kZ}>Phu5 ƍEE/kPsZQKLi~ %5Ε|((/N ( W!  ZYzffM]\~=gR[>`As]<)/4g3A!8ki?d` ~5R_*I'(+Qb0 GN院dȍi>RLR]ʴcA-xAB%b*%|2S53_#:X7v KzM8T +JR0C/Q_r#ktnGLShϊx?Ps ?j֎NP pM^@˒9 EGxpE)\ }-_3x M.FPb-(1r%j h]s}X@X8)K:֖$1ݧ`A)QQ 0&"Ts< С;K&\:{ JW4-άQ}C#:aσ7hs$ι8T+ ;HSCЧx[a١5hn/0p~u޼4x2NPDMGh9P010.A0VPu -#ߡJ hX{(BBg`p>HBp -F,~ #zi У}"x@Ȱ2W,"TZ2.R`%<ņ )tm=SӲ|?0mOσ ~Nm 7:]`$CW!fPA"^=P \& w 0ű9 )^aR@(`Ai uZ N0:n<8C |31g-!sBۀ$@Qe\'LGN[8jG*ja-jLWzQBgx~ ~*J-F=K2 +˰;! A[cMA+P2F*F1\N~e4>F)<uj}0XZrA=HA!NH)\D@j; hbkrLS\*N9i:P옢h.+77A`x`r1 :_"{jW?W$x8HS(eJ*:1uWf%j%N; g1k_ԑ3c6){T":q;Coaqfa H]a2,A?Fp=&Y|½5 6>g kfκp9p鸂کdj-~}<^_qӨzC%.԰`\t߮hpOly:Fh;: .[n\ lQj)U/LBv |4\Y{c9܅PPWPupEവ0Rߣs5|O/';7kke{)HpK5D˒֏+ L X᠅%)h Gk#NO4yj] W`&'X^2M>vҧk*9IK"K"YC !|:f+)c6;@,ഄqk'5<\8񅡟\ +  x"x5}$w(=׬*Jk0F sjWGBCdkh+0븈DIgѪDke6 2}MzlV0IN4i { Ɉ;9n|%6:Ec:yRF.7Z%KLh 9n n#¯A#.'GӒ\Sȓ/Y%BD0o/pid454=8~I\ȵrӸ[qS.}7PȮ;^HӒc `@JxEN)~ "o"s;8# 0F +W vW+;j!~SDںb ̨@45<!%&.Q 8(ྋeZqWJF)͖#0*. =d8Ƴ`eM&PəV)]x ,m|B%;Zq%#/―EJŗGuY0ZIFS%vߛ[ou /xu!x+_Vts a$Jf(fk3x%P㙱cj &UnS ,=ݴ} Y]zL'C_MKdͲTNȢ?=I]JRxG&UǖKxļ%$,7/]gF/GYVؤp2\!Sec5Cøq?yL2q]T2+rʠ[L*X cm Xp8Iu!x +ޮ \8_éW;%q:+"*S8EdN6=magJFm1614s Ӵ , VO2@M9K)o~gh;qlh6Bzƒ $`o;LĴ jWҹ9^z^93m7o ~I~=p2ՒE+Bb%J+4Qy,)J‡TCl q_8yRGk"<$~&[>F<)`zܫ 4ndr(g$a_aJ1:,cM$_%AM%į^~Zri_6r`!g,8 Z\PxY |RH@cUHR /lHy!,tJ~nt,3GYv3¦u3c=K2e;L<+K,Ӕ| HǰPW +e5R%xpfya7o8޸-E~L~KSh> i#) 81AKZL" , G7=u}=8x/:K>3y-Gv?9{eT2g8/3 :e3 {%/8k˩P ;8sn&܂__8MO2Q L D( C!Y)[q2&Q0J_cjE(vH'/YK >_z犗{jX=;;QϚ.ߔ8u*\+U4B#@h ʝ6 4&(<#n C\RtA^sXùUd2,8?WE~i@dF[2#d4E:]:@M hoZA)x4-ZP9^){|&8;m~rOjŗ^o/S ;G%t+ ֛')^FQ@/"cFyث x U((G00aA*ʬ76ZC?c!*F֛MFp@eGkW0@@NrX:t=A#89ǎ;<)? 7]/SU\L ⼤^)F^AVJEH[YuPNJ݉ް>*f:VD Ph.FA6| \FѸM1@9\dx`fUWK-A:e"ҩbͮɢ-'xqM?;d cG1An*&/OIc(Uc+~N*jSq`,:>=qڹ_V`$K`<ƶC ɹ|ZP[Ob9)M tMpFFPQ4a2;w  IA- CVFkNJA{%'7޸-Ӷg:z&oւ?+VV1.paĤidB& v2!i&h(^K#W( N"ěA$O7"g%!\OPdfm\3a#tBx0mT 6fu'JBKzoL9;L4u5p$~w>>6*KVNJbܰK U@0 G K "Lp)b*!M`-!je#aõ3hyL͆BlSoǐE榄|^˺ 9;,cO[ep3lEbMٌM\|AខYeap@!e@/ܹ)1RR:Q@QCH1"HrDX5R" !$!m@i`M n **BA1maJxqFu4&S ˌa"Koθe2$k7pn]FA"F|"T>x@Ox^B5vhjke\6%K/ E}TOʀN__/|[ΡDg#M"k,@$-%HAES3|{E1RB⛑*@vm*\*#8& %cǽemt]6.9N5)M2C~[ "|R}"UYJ ;_&3Gs\5`h0z#"氝6|%j㕢)qBѻ) VR1xC!P`P:>K2,`"*i[N,BL"U $$٢,#E,`f N,}6Qzd8.Y.cS34CzDwYwcTSFsn%N3 }:f_8@~Bs AJB!F9@P"Ļi>HHa)ZFi[]F8qDM.dH,pd}hD@1tZXTT~ֻ7[tfȳʸ}"42shK!v򺇇j# %+:?%Š9Z08 >z_p p+?g;c$^[KW`0AE )7A"9s*tnI;L Q 7GHud6getbVpM5|'F9\`FaY ޤdvKTeqb4M֒L.B]&&e<%`d}?o Hr4Oy;w?$r^A1R4haJF DX(ɣ ) T˳zgt >r阙G |RHgz*5BڍҖ'bMLե7tIӻ %2~`Q<>\:-౎'^GxU!CN Yh&Zҵi: cx'i]Pi$THl u0b;䍆lX,bȯX2qU$Ɍ0ڸ>sӡBl36Led3Bg6,#>{#Y2:(9`|=UjF3TFSYpbaԿ8QI$?Ow) (Ha>-aA`Rzl@q:id52k|F4yLN|!g)wȈMfi2@kf;dy/݅tuM<`>@A#".BdOl8VCR v F%6DF? l׉2x=A}/>AF@I`iฉ/ `e)}_d'ti"udnމ,i& _fH\f)22!DeágBjߥt8>M?pX.D6/YD7nxS>r,V9@:|^ a]sD ̧glƽJFJ,Jdl 'lzH휥kV&>_1d̻ o2 RZBN!) .^X=R8釸K߼~qAp} '^o֡viJ&IWC*086“ #PWGT:!>_}NEjK\2#&m[1>C:s,r ,.;erWFfgb(ٵq>^Ect1]/G'F4(߬́rz[#ϿxYr}8\upx{1GR KC 5RhASP֎ [g,֬tuF=d̨2|egn"r1StPY$>Qps"햼k''~P29)f>C)«)!d rRtxa<*SXή MZ.=w<%t˒o?Y30+)t]WH;"z'xXxxˋ!p]cɺڌ[Sd䑃" 6 6*mz )Ga# {gtbA1,i5U۳^ ^zS?eY@p .[ΖJ1ZPvJ!$ FHg`wi;8Kg$ISp@"CgŶ 8bH3E&E/xďa lmnhweβ&7.{-MtUt:ְ͸aAfCʼnU—P)TÕI3EfLb ~lRXfif| h~f:"WO3L/YhC 7gJM;t{'q۬&U#cd_`a\Y:e٫O?UT?cRm<7oKܴ_r3YrBxbjBq!ð_`#_&VF)>^a3-.Bl2ˬNO3(ۍjKPۚ6֩"e&54qG=_?t<qϲS(U<(:dh9 D] [*.])^0IlգG8gD|΅Q`?IDVnY +iFhDXkO[8|Ųc3-mq})_(;`hKD5yS4+bg}EnĴuKJw!}usz_ `oo$ /y:7m0l[-#;.)zXxg(q+"arr3ow$fed:B!HVv:E6(>]I-ЫIh̓[yGl܄qE7z%KrO[> @+e{ ~->NϜ쥖ET=v"=4`c^C \MVV-s?ց#= ]tѣ7BB- ,D%BA#?>{Y Zڔۖ]59;Y%i^KhAT▽Bj;]k[Pnآ{}*vۺ=w7IQ^a:L!s-ାF)>a͔9c:$ͮ=؎h~N P T"5DSrF<ܫޠژ~ U%E̶t l4% huCYj~5/iwxm&ic:/&&@d >N Wip˭7Ѯ-MW_zJ ݵp \/˹ߨ{W[Ti B]B=փW(!ーtY ?[.nᑁ5xMp6f[&Ґ[l<䥤9XZùOطiV=~һ{¢bWD+侬ײ#3*B,!tÜ:UW9a$EC co_p%$FnFn"xϭwo)JwERٜoKp9& \ERI3a꡷^cdЗ{]sicA-f? 6'^({3HQr0%Ĕ+d(p9≮QY|s=¿fH0qYÛ0"¥:p*Gߝ֩RN}IgzW[&0˧lL6LJ:L*ǀMc,HCBsB1.o?Os{"n\H'y??> FpN+>݉r&q%8ο}ۤ3p?ɥ8>6M=},S4n{o]Ӫޛǣ f B(Y ɬ%ݵSP m"m@;S@*og1(xO̬/ .15Nt/Tv$vCRwJEԻ^^o{#L{>;xC0zT'{47)Z=KTMi趮pb^㌼Q|2PFxI}YG4D֑ԚiVT5,@r6Z8 (]jk1b܃gULݱ,Z_wdÝӌlOf,cA4lIDATDr )y#EBuk{$/ttA/)LuG%;~n17Jg=wVqW%뭞ƦXp&&B_j'_C(1Iqh2QgxHSBݶTc$"^[ dP8qpݡ]7v8ܱJE{Խn̶Q =`îwY ~sgco;e})|D\B^KX85!H2+]h嗺_C p4M$o*Zyƒ`@NP̌$Dy(l7@I8o`s y{H sii sIh#w^ .װ37aŅk݆ʹqg<-b[)?Jo^h.!A;mGVRԂ7 < D~~ӬZQ\l0bSD()1FǬ: e F CW4 BȘ3UQ$M,ĭlNѥ^D[,!#8.;6!Dž lS{ nQJXП%(!Dꋍ7_'[%4cY[ ] C[#6 l3>-o /*^5vQ ÒrF)WRÞL D u+UbI:_~&lROK3JBB9řM}E}}Eڤuyr<}B+*e )Tk8\NWp!9" 5tXCg4~\%ɑziiV ) !Qx!qCbEǘ0.m'PI(w`)yΈfUd"NnG+??i"<~]eoGD:]Sj;]P?m Ƴ^a=bnQ:, ngK8#6A51}*q<o}Eruj9 nEKD5%!.@ MI "u1˪+6L@u|)u'ڰpEI#{ЇKCD"2 Bu>:M*f9-Kvv;"Yftvogq:lYzco#饁>tlӆ<Ң-+a4!"9ĹQ5ACY54E ENy۾b xj$:\ ܀*8E}bPCɯ3,)².D¸+F[(EZ|ٝL ̥qIQnML2:L>Y+wl9EZ)0%:,~Fմ6Q-\]'ĦgE ".SbB.Wpl >Z1!Q,*,Yh)MS!K#YI.ꂡy5EI9R\R{b3,[m Yw p*mc ׶Pi`La*mvpU'8QpD-Ziv:>  gV%ʥ*'p\dPU}4F(PM.:s./f#6'j@J'~QC>GrBa[u Of}{5sǂT`$ѺSB^aMFwh݂[oY4˶lbJ2l7ls"C<93Qr\hrTǔ9AX /7 N0-袁"̛ Z'c aw`oµT /6kS%IO["x'pDTqb⼰8+w"P Z kEC\FdT‹tzJ NZ869aX+Er:2 [,]QֹfYtӴ$7wTRAT,mD)y\l`#nGr{o!v-i>FQUICQ)";khP*KKyuN_uQMg#8CqJP'8D9!Ԍi@@)#: Z_p"%|}ዧ΁ZJ*z* |u. S;ÚT0$"a/tG:]1BLv֧i!.t1-~h,Pzi l.UX_3eP'T"PHcL9^r/2TiZap Ă P3#r(x}i)SJ[v cQk_1V9V̀3_`D56x&#BI^??w^Hӈ83, H]; : ZEC 9~㐩;=VX2.E@LLU* kX2k*/ȅ'X%."Z89W]7ydN8Q hv"vsBB}KȐ=ՄlN*> 0kW + 1YQ:99Z9'1Z$saܹ^FF*OFu c2a2Cƀ 6&c$.ƥI gyy<R~t>ES\9}D5BTXb J5A9!{F]y*G+ h 1O#j3DF `2HbG. *Hp`DfbH%Y<@ޟ 8G31& C# V ; S<AyL,GF{(8\ྺF&qq"Db DyI T6!N%>ۤT!cC :K-A+Du^£ՈG1)5la|Sm>PwYGFe5&TZ ơҟ҆oٜH cChQ"UP#BXV l@D !xyDxIE>XKo732p6=vEkxHay2$DDLDb#nAjWl>M"M* &Mjmg*ӬuηIG&^jQw#gV1oR h.>Fl:G{ᔼtMVxJ#ɕ–-m"=%=莈c*3Iҁq zHdUP-(0DEXZ0Pc**`b S$cCBn`n/ b@Dxہ,q hU f()"d% br =^J4(ѓu0Y"{v:NJ_lEkĺTD?5>,m8$q?G;{ =H{JgMDykɪ9qL\2ySkuX} V.NC" &DKB" Q>Y)Һ &#,I;4ރfW[ꌃe(PiVCbAbKcE Nq8H!jȨ ?yHHڀa:nVA3s G"=WDD>A@#2 zap"$CK+^+| - ֳR5<:AOkϏ=7/=.?nChQCƎo)DڭQC)6A!GĈƏq^U7.Chc53xDΈqR8Q#݇Ȣ!+dA+cdXaR1cX9>*P5-41% 3G%YkUsk/f@`Lg8\Щ'(-DCEK!f-* z5!b kK,h)(Y rJ/01 tm3m8+-LQY9*.&C!Zb >Z2$׏XB8paD%%?})ہf xp" R^#-AfN*X3PkTh'5ڒiGeNp~SGO"@K+Ml/!#^͉2 7J3EK A5DiΠ| n)WYJoXq_{u sUB< pQ j{^`4KD&VH#9D]X+~DT"͵ qqDn6:M1砎 )YrNi̊zEÚ*z!T'؛ar̈jgDOaɰaVq .x'MJlAkd[Ja-zS=@BO!s**#,5$MECԎ-Ǹc q1fㆆ8w] vNR8}C=sޘD9|IW-K T ¥F8$8O=RE "JRdB cbdfHp X4qE7XgLKq` ˑ+xàdbŞ 4a .Ff/OuGcCUGi ucQ2gd:' ( %Sh1`d`MQa%M#8:wqW/EnF[ŗЭ?ܧF+2W29#=`%bHaSCb!T}SCOB 5hHвA%A5(@ǚB-Ěר7Ԧe6,y>%~r x=?j%I~M`` L$Yht*?~?Dˏn`yKvˌy3В"x^(QDLWUQOmJ>byĩ#@yYxsi/yA{I%Q:} xၠ(X  ȐwDRsDPĎ;(D] r .c9S={5<\ib-NVV1FЁim`Uνёw< bVQ/~! ű࿣ǒ^ͩDxC=%r\V l9F E"wD :V ߎUK4-RHZÆ5 l h21[ʝ߮߮Ӊyđ8~[v.9s`Q ^(^"tKV _p~焗 s2֒ws^KJQ +#ɽ[\EO<x>#WO#oj9$_i$zܖ|J#36d>'fi3rɅ$ 2A{YlHZ`Ŗ8caH{p/ynD^xLN8\[gW_<+ɵ}Zi!.4VM8%;ӯ~\&PKꉠu77it4юgG槑Y Nَ_} ZK3Bq}Jͬ- rJ0`OJV!!^^yLADq2$ڭZ ̲>DwCo9- ~rE*$\h꠹*L6bQ(h 3@H6cTZzvG)Kn,a-V3o=;sϷ˞z-.j|\7RZD; /yX`)^ NԲO>L 1O,lMpX 7j.+abKGD pHYs  tIME%(] IDATxُW~?g[wْH )G`616`l@@?Aͼ100~!"$Pv̘3P[ݾ}.%UMR8v}%(܅ا-w~WPF5jԨQF5jԨQF5jԨQF5jԨQF5jԨQF5jԨQFOgOFg^Y}x}7n/^,UxdBϜ௬ n? p+]p-yo^uO*>Qj5ɉ 9ɭM LW0H?q=Xi;<²s|m?D 7%9CPKh#.lYH X),mrѳO,S(h_!1 WEPHR)iLx2oɻ`?a+9kKW c7x*I|풢$i$4HM 1r!B-qF,0:7?LYiFsc.WW@+ZIyoo]rjU>F!Q -tަE"h ^EHڈ)B4x7?;yY޾~E77b7:.9Xk$b]unPpY˒=&9f"tE'm3]#Ѻ M\@7P<|)^ }i~Ďϼ,lF '([<:nYD/ ޻1"hH3J^rjӄe3 =qn`"…6a1u2"GH#]Eh/'?~eG[ɘٜ}'h@hYph4 Rq`1)Ƴ!lB^6w moٴY=Ղ_E{;dM&8" Bf, b) ^j6B6wpBr:>~#RM7`%*(9tF17opITn-0>%?{WC~َ;LbtEP}Tp: F gP11pbR 4FK(HL6>e+IaNP38v*!=q O]8o^1 2"3L@i A` ZB X6a8Q^ ڍ`XXRxC"1,(l0 0N9H#{ AE~ F%"P|'w9(kħIds&qF's<" $6lx{?c/~C?I_EQ@R|`TKy&58פ! - M QQ gpoYQ*6(4=ލbt9wK1~ށAWp-mΚ2\i[!9?Gq-]K'Aα1./G*h*kv  <= V"".ca vS~&m)C7Ca@3p}b~`9dn$kroJvrsS5r^E'QW.1+) ¬pxHe1LhP@ ؇t1 (rpyu^|LLv߭Tc psnq;7!\b̿yǃi)ce'OSKև_>D:3pq 1?Gbޡ)ِF2ߧk3Iށz@o8HԻc\eICG©&#+x ~peUxV@|ICD=CȧiDXN5?9$GvdU2i\Z9evg оID;U-9nx38һ'?]q,*C[ 7rP(Ot*+SBCTaq@/@-E }*Uz~e~&i#DEM\B:#Qy8EU^bXL X3y4}!.Mh1p<-%fA*;{0%9!h#IN#çY4p|zeMʅ^MH`|m:Pc%|~LCx,׷kh#ƴSwI^XڣUpMIΡСEEçxfմ*~$32sPWLz " *ȩ`σ'Og|ĸps)x/COKÐԶ v2ݠҨrKz8g;ի* `<]!2lp?ǒaC] c ZA`vGj)2MbBJmuJQEi prO\Ia-X@GxDjX1H?j{|nD/ *!\ۧ\5ljAY7)la3H@ ȭh)\&bG7װ$ EA+"hhlieEeSP Q5jعFrșP((-hb{VpRF b=hhJ.`RJ +%cQbxQ?+3m6GmU Pː- \M\iؤ2Lm ʟ?t9RfXYd"#V9X8 N%=x_ҕ#ZM)W'FU A@jC9:Je^רn^*2 ֚2E}̄TpXv4듶(ıs\Xnx풂8Q #x97BC.H Lo ي~l}fDSf>I {\b' l#ROm3 k;Oz7UB>4}`soZ*X]+[R5G.K 1X>, ?ڬ2ӂrM-Y"e8iG;XSAoIriIaBAҥr\`F h V%&KwJl{@*c[`{tȿM(o1V2^g\yg bsspl~ VnwiV5%I} ]9zȃ U7$~_kCO et *yEʂFuG?ty5\Gx|hs7*(d\F6'yc y;C!,|f!&5rF]k@'{01aYa8ATqðԬr%IuJ\JHQn>l-لbwQr~0*GyqIQaDX4YѧߙI<>x'R5 ah(# md)l$`,B'(fjtE*(#|p՟pKW.\5nlAHH>M!»PC-xrgصE%U8?v=qE{Tt7)7va"dC0ޟ‹)Аp;A.8l}$?2gqû7 u {>Y4&yg̸_0;#(W勞|P%O O[ؕ=Co < `PT!CHpBӔegoۆn>8h%Ϻl*'dl o0癸#,_m;T(1ױf0a?9AL%jr߸x٣z*;mGm $7! bTw]j1{\W &E-wlpQZL w3d6,!^ί!>8XhJFT[bNecfwv r!;MpRg~V,oZ cA- uReTMUշBG*0  }b V91>.[By؂.Cs.>MaBbUL= $+`-18Mn{hhy=RW9%$Ce :&i1 t7V=W.yNw~X&HZ R-`D|>D{p5krD=+~/zX}l/A #5C~_PC80osKF8#E gvBO/;RqEX1=gnBd?&#\cR׻1U0}fdF{y`x W^)deU*\KDfti @23mrB ' K.ncr!$*ǐg)\Yc>,۪B/& ;4ŀ,?Bz`cbaLV6;MZފ=,;pwu6 X]bR6:1 U+;93h\*G%H?@Y RZEB22|>'ߥ; id' 2B&-|7a=gNJ1!Ga9vħg0a9uN.iFQ@#AffeفǴD9_AQԧ&p}C*6$[L<=Ku<CxW_t%oXӜl75 cE>*۫Ɓ%Z 9fWҒ ˧=G",Eoްp^"hvgbv~N\}[U6j_~ZLI*ݯ+݊ن:(X`$551Mhq wkK7uwWVn޹Ş+ _$ÈbҞa;㌫KiO>wl8nIZcA+X{Xix}1Z,]s 3p#xJߺm>5*xrMrb(-~UOڒ7O *2ԌeI25ĚB-5jԨQF5jԨQF5jԨQF5jԨQF5jԨQF5jԨQFO OKIENDB`robocode/robocode/resources/images/explosion/explosion2-5.png0000644000175000017500000000242410205417702023711 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%~KIDATxoTe{L;m%m-U$&te! $ƕ.رʭQWw(&p . (ހ)mz\.J7+Lfqγ8;O;g@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD`vik1IVsowϤhO)%&ًIbǏ 7ċw L c9p7C\@e,4&=KT扜(ԷT7a_&%Lasx!H>%w,,ɺ<6 Az;=@ݓ] W'X3=y??lJE ^g0v8?:=Fkzt~е:jZz~Vj/ŶVL;rӸ~"k 釠rb/7OK}{8aBU40@ʄ0O4ڵ͌G)B 8J5cY _#F eHeĻ#pSPnʜJK @iYUG~2K>o0W1Mڑxжt}+#K}5ȭqca߀MjgRN+.P*=< elS|2aQ2ImQ_s(_t u-yWw㽽֍ P=Os-M4WݾLXIyZgIjC\"qivP|fVj3/3 $/O,b3ZD.2Jso;dAabKGD pHYs  tIME&\x IDATxIeוnGF)RDR%*4`L{a8E~{<)j22MʮRRʔ kosy))Fx7n{9{Wsw=~w=~.(|5 C×)Qx&Q|G­~zty]>ΏpÏW]IB}!]7>?OC6"3H X"x`)v /n`Re#(աGeioȊ Nwo n +fVvh$lW90K6A:u],?? s`=pqv)%xW<^Ү@RJdRZtxJNtn.q^PX/Cזq<ʳ``;/ ܽ+y3;Ekq/_>]ӵbgi'I4PTJHIoR=Mc9Z[N}pO, ݟM,? lO>'@>ISN4@:,o;Gy;\= {E1KN fkTE 5PІHA Em1~@6=mkX[ÁesY97ǁsoF ! f6-/y݃(#w<D-?k?Hέ[/]CO7TJa;  fد$ my1 $.fSRA>Aه4{&c w.FAY%u@XJ' \ka=XdϽsT|=*3 )Vmc6J-(6m(&P n k`uJ@E69,#39c3ԃAU5m3 7tM Me0NR{qn%zJR´.'V ^Dn&A D9v=\P/lܒ|9)f^%TM%j`87e%U2%fS .L3|#;psH+vnqe&rnÛ &X n/K4KTNQ7U?AKBRkdUR~31)LТA FNf5kJܺff,TVėz}Bx IMdQц|Qn8 -3j1۞$3TL%zC]JأTsxDiKPB8EH^"(Q &հТ5x-Gg Cc; `)X v;I]-9VATJWq p Dy vvFYz2-z֦A=&̨Ō!jR %4VLh%`caPJC]B6[j8yBpbXC!=8!lP AhPuf(2&X(x^p7&|BkN@6) bYky2w\+yO / lH +4%K|0G!)RXMn")S^_3Kw[h]Ө.v XTE[8AIp> ^ U C#A{oP)>C%RX')aG! NK9@!T ")A7X')EPS~-T=@ cz^cC.ZzӱYZز\;<\ymy$y$OŊLI1!6 +X_g>Lܞ 8BL-[h )`0   e-a%@wփs00԰l't++x6o H|@谶iQH!(7%J]Qs`IOm ggܛ[~\|$8{__X1LD N `h/P~ ;7[ Vx'P$n3KQ&:tM4镊;TPְr{600wDJ.Dѻ 1`€ЧF NX7x" ^)yi=h&NSz64Զb+LeRi^y\񝯜wۼd~!%£9^ B4/~/ϾFl25hLS B@Aʸt҃7HmPo༃3C!U Bзt:\t0xA-kJ6XZWu):)+R 滑 *} EM!0cOgnJſHb0oIK&NF\>w?] @t;艦*TФ]\Pi2taV–Z "613/=&aJD@2X6;z'}OI:*O!БGE'pց+ࠂ3t@cPl\,?t@|eK'E'=8~*ߚ%>W|U a@bRWMb\8XF8p߮Wp\$![Y<-쐄xvM_$eD2OL&J"@[7>ND!,"߰ܛ<'?sp× ^MJfYWNgd~-p0 )J \[Rm4?|RˊfV0xPs Tq<ĝQ JmĂ($aj+Q?96I $dg1C iWҿףRlsMWpf͹ 0ZzX5.R^[2Z]8p 1FB8A Z{}EdZjv*dE[HzD}>2Iͣh .-vvNTY%Y?IR$D$hG\cYgN~[67+"&lH_1 \42ZK RZc94 #-<_tM >l1)mz5k]1OX7+VeDpU(B3Y'S^ʤ:?y8! L+=*"1$^t m(G%BԷ4Ee/Tupn??oC4鋞 MAJt7[-@}+=%ydS0a3ʢʆ@I0 { 4Yظ{RD8a&AC2&vӫt.{=dYdQ"/zIt6SFnb,w޶֑N lnY}M,xa -3"d|;L5jS {Q^C YO1B@v%xO-$!eI!Nt_v XR[Vu=S]?ഃ^Lj-\7[CՁxѲh`pq.[: /mnj嵄Fɦj( &"L !-(`.Z dg:x {UZi/G>LK(1rwY_͓EJst5;8} ;O`gt)6#!0e]~{OAZ|a'=<'6>D2V@ o N$Lu*OmSx)E)::;1*xyS]]$tdn,-{#Y'HrW'f+&eFq©f൩ᣕ;on7oίn ~9x ^Q(D)Rsx< =Ò O8kz "U3b+چ&&Q28.-nU$:"#k8֡ xU g,:)bu"\K%(kNɨ>0s%&LxemϏ xsN&!+Wn+'8i$ۭ`$mQbIpCX)*Re.ҡ'm$Ij9\ډk(M2[I$6 cTY8b:Z&XgKqm:"YyyaY]`]S‡,@mjZtX'z^r7<~sdU(&CUTnX.)N20A$, 4TE9*ZkM$6<3p"&Uv? (-j![.C#pSY87Y_'-2I^FdntAFv%gWxġGϐ a=t;T8qӻ[ܖ 6_ z+`.7%덤:BPWЮ"9BL1sv'pc{u"l'^?G-\vxzecǝ%MG 2>S)@ޯ\ȔO3,285u$pY2=LژpNcU+"V=d|)I|>:h292S-tLQ.(c||;xiƺQq !} XF.}Kv,E"- ' y*cbY;L`@@UCJ\-d`F9.bɒKI{q[psiߣ4k$Gۚɺ䡨؟i.SiCACg`j^B=#BDi=\`.?X7K99+đ".#"̤e͐vY܂(EȟG@;6&Q)2 q7 LG Al3! M;|2^ޑHclZl 7(>֬6CnSvd` #%';+`d4+\U'=>R>&HZbrȧZ"KH/$ݴ* ̲XЬ# S[,xs"h! [r5WHU`K8e? |ZɃNڔ %,1A0CWsz@A͐ymBA@"ez?r}̍#v Sf&SEį:p6f` m2MiakAŕPy8&6g1O`Rz؝Ƃ<^! R`@a< 1-[+ow]?_ .98(n\(&Th7CSEB(@ "'(a;z;kB$Bn# ,NҮKMAYJXg~w3_g|ispc'ML5-'㊧אDZPc C#1~q7GCS/xJfONNQv3\F )= ԀqbF]Ɩ,WE//X!"O`|ڨC$19tFT:dgW"Y%h߄;_RE*WFw@ISg>3be`Ұ UX E񤬙m bn~w?~ ĴVu%a!).̐~A$,$5B;x:^\,m4h^ IDAT !DW!z&鍭[FD*x~veq'RiEe{!d9[W+l=L 2Zg᱇iW #mV-XH ;1"3|?Ho F1 J5&)B%tvJA ק1W@!)>󴛇,Krfgؤh5:q\x Lj.@1k ulr Bp5P5^A)]*LfytG7?&ʹXh4F45q…BT'8 k/ g y͝BS>v&^ SM궧uYUvbz%TY1I_T/<%ٟ*M.H=ެ#&hKfʙ=ą!TǔvJIK,1oOyrWuG×{uM`LӺZ DP%>(ƒ%RWPłnCzn2c;bj[p"*r( vuSr-:3CV"Q .4!Y߀u`#Ra*$pC¢yp1Q9a/`& (^z^W0@l-kAcm+iRJ/0D\ 818/8\+& {o[ HJ݀wiuh Q^++nՄΘk2:"h}'\%A2]gedod;6YJ6q:,).̑"q1*-AJR  9-$m)B C#[5qN '+B-qnPk>|ZÍ9:R.oK/>U ɟc\ׁǩ`>WgEЙ{u\H/༏\?!D7Y)hEp BlаSOg7A/7Z `J8 GKA%H%hy%nL / L07σuZt.BAW'w1Y?f L`>%׭83[Jc 0>]Rؠ)8)A""hRƳ:>}Lc/>.Z%2 `yƸWe=! }bT/pe1J{ KyE:9iSzm JIWx!QNb}]B|dPgŧ>C| I$V "B~[y)p IZZEibd2M_j|Moey%{ڌ .cGrhTLgf:d]'UpU:Mzmj=_\DZHJPA$z" \?\E EQS A MBJq/xX@A2sTA;u.RQ*C.3Jvno٬er $Qi&"oTf⟥S[Wm} Q1DJ#(#Ycj~AAA'0me-XơXsA(C" !'(xd֨q줌dzĈl^_glte Yv3g%h6fsҿw~ԱK 쮜wP$!*Ou.Vru8Zz(RH5gYkM薁Aҡl@:3Gx#Z9`5DfEV`jۘ82[(q%KFߘ\ w{4\e2?2.!/* t' ?lTUv t% b%0ޓX1v4 W@-Tg  u1qhtҳ83 pX"ґP"QQ0)ҼF8K 8_+ɼ3angɄγk{$uR2[x6f@Vί l%^AdE:)2L}'\bH3%6`ƼHhgt Do"QuU@ RY'@JVTAL(fZ2f$1+d\T u mTfuV[<͛Kf~r:2Ksld#x\eYX Ŋ`F@--+> y;ۂ67\#³-i(zC9 r - `#DXᰁlǴ <#ek7 4+*Op\`q >[c䰕y;]v̱QqzBqDX Nl#v|)ŘJg}w92 ixa6g Ё~F >tzz`_, l.~|ӳuxb=8r@t[P"| (DdI\fR|w4"׍`kj]4M \f~Y.ki4@r?* <&3.g $sn2>e=t0ү+\D$ܤWLWl_iHg4cm`>#aʤƓ$Xd/́<5=Io\~OmOh&|ʋļ-SB8Ɖ3 q }=px ngwj0ptXA(mj |PqbH'eU*RiG<36kg|Fo`7ؽqrd[eJb2γfn ܍6Ô*aGp|G7XA#>ŻsBb&V, P[--w;ɔ @"uy໏q ז B,񾢢b`+7"yXZw'~Ƌɏ-M@gdsv6kv?m6qR8ӌdjoT=r6F3|eR,YHx(kc~6Dؐ@HDq<3&. w=oݟy')R  nb8hHd0d;zl:DYWe`r@2?Y&hBKem :TF8eXa*xϺ%CDeCRnz<ċ|!?F#8Esdb7ޯ X0|C.@L ˰e$^E~?( +(b-r&$ ])/)0s'F!oB5$?=LasZL3P=MbI$tϤt:(><$'),VǮ :x~xy10xO7q/ |,y'<"2%Dxˊ}'pm /PEz/LE$bHx_ӬǫCf@|Ʉ_uSe$>j2,θqvyP S˼RiO>>yGxO0- v:}c'v?Kb >xYVʠW" 39„h>ļ16j{3>w*SE1lEcdh"/+'x1) _ SqKĬesѣ ñ;p繅rg0|dǏKKSGwf W0G'26KU+2-]j" ^Ī\UVUfl:YڸB)^nT܀MbγԑG L.&B7Dg9!>!#\"q9vlg:1<YEwlZݷw{V0YV'[Bc,nuxu찁0aRyp{mK[L/, :XnUDzѻRtMRK`g:=n.ְLsȑ q|xjEO~{7Yvr/XD*f Y^.* Wg4p1}M%Z1HOn86\A"Nq2v),*2!+e_* n_9^TMm,DgMby<S5[(xCYRfTȂHU{jPٚ w9Pd 4Zzh}=p P7#z2p/o0V8=h v>/T<Plg3kxUT;ω4,*bwq'f:}j۳5m4&c6hm^&ӥFU~sr1 `:0h29Q SvPF {-v)iw p407`.ʶpܸ'WP72۰G-B g#wO!xӪTp)X#2dlyF]z“03$d{CSA}~w\gzPP.>f5t6lY }r ,US2TPta5pץޯE>^SOް nJtYb1[3E1WXE9^U0ZU7t~Nc'R ;n.|Gs't1[bЩr,2.8S E:~A(ϥ,=$o |?8T\ۗ5W?*08;8Gs*PJ Q?ǼH͞i K e"B}կM:$uLE3=py~;Hbv[=<͠ ݃ hWW ^eBO3nNt5c2$VIDAT/"o㚆8N7;ݗ.ۯu_le:б LQ#9X80 Zfƒ%-; MgbHrۓFe|b*M4:MP ^}I[?9R*M꘨laHgNj]L E> X5|KF+W}5pō+(#! C3K jkTyej7&M 9+RQ j@a TJO&Ꙋ'He $5!mB߹sNw(`UY$|JBxÄeNot m.4oA<.}թCzLXt?QC*u{V+j G]ऊ)@89dLss%T3F+`,J_BTS< ЏzYHځ;ڥ񨒚2=N/(& MhzA{g'psMx3kpvob/1\mq~LQyӓ5O䢧GIqSRDgP)L2K3]]5mѤo@?PwqrD2]huK;/ WEJ^xTb! s|(QKLE&}(ct~QZI/IzU cugc׏%#:m,6y-,#  1)m"["ޣ{>։蔑 ̪lTg(ݲI`ܛu>Ҙ*4!r2!.;4+eJ"Y.nG/(}[ zz >T,Ś#eyh$d[ų/^YJQ·/:8@D YmW}iKHȻ48zXKztqvMD0j@ n"N80<"cK`4B,X?=/LSq:&،<8v#{h]_&0%%+705Yi]S5wFwr 'pDc%4LimDjIb^T*~͠'.FkZoQD,F^3xm/C;|\ 5(.!uw͚Ÿ}Ϗt#MC9kN &1E| ^Q#˺8&3Խ<.(3?FekT8;( )ޱQiSt=+X!G ʟ!Q-lqL(ak嫊7k%BFaK"Ų~Tm"8, yBEst_zG^+@ mzޜo^o34% Zj؂%(m7DbPx;Pl z2wx,+h=OעFdPc> B@CO#TXbc:}D0+fA[,1adMEM䕐ZV2@Ư 6Te:Q-!ض5VIAm >`TwcFS,^$m"z{f.yC^Kڠcv.T i#'h sU7qa | #aqstx9rc/:PzV+D%FNJ"wh],#9a9$O>'7 idn*U$N.zqXq*^)Z#fU F "ǜ78@32ikJU㔁(ĸ3 b\0fwr7p'(n!Z؟{xdkÚjWcEԒB h -*ќ PC-SC"Qv&vxGz>IůP"-}Ǎn୏~xP8P:"pr K|aQ.srJDAFCP!P! N2J|OJ-g6[lĨ Ѭ1MgxyT]  {d}Ǖ:4엎f9 UTh-KXZR lV e1thܺ| Kք#-[G[䂴sya":sv_6:`PMlzeۂjU)XɌ`%TG3dDG#! +9 K%#0hBmEaAPhN9D)N/0~AlaM;m"30Osdr1 YNa鱢 .j:hVb:U#ۘ#yV+$:%('ic֎vdg1Q2fB~>*W"?y'~z ѧ_b/'8ݕf3G%TH$~v*!h Af0B^Р)d(QPڡ㊨r@Hʘ*m2JiQ0:+"h㈴d"PZnE̶xYaԆj^wds˕n-+U'Qfy6(ͲLuO;6^BO g]4uigkbYTc\Zbz F > -mׁOV6>"3t382w?|!Oe}C#{zqK79KjSaLgѕXˇAGK $5t#m亦 66hooriy9EGU8ttw_t}XfvfMP˅0Xu5v_;m£SC 1xdswaZJLV)c/2rQL%!(<<]1!3]t4㘆;N3EG9~:px"';#<(#7{ 1e|߸; nѧj΂{̓2-3biY;!CV0TwE<7O~P}`hTYKSm8X[XjC >*|CFLLS/3(2a~湶X` |] U^|WUz-?^j*x{k Mh̰(46l3j5!yDUif:בȵ !?vK-ЯK|-ō|R|j;P-4ST^ьM eD#\X ;_.*`2O^泫ohUAMuqzq%r&L+YJLԵO/R߸ 8g ؏;8bџ7BCxEL DžIENDB`robocode/robocode/resources/images/explosion/explosion2-18.png0000644000175000017500000000752410205417702024003 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%]IDATxo\}̜eIDI۲|ōi4-Em'}kCE-( i$SǁȎ#%IKrs\4  Lk8=g~7󛙳yyyyyyyyyyyyyyyyyyy#vYaop?dzu_z,p`wYT,8_?SG, ?%8&ް|KF7~O*NFFAΖ`Xbmi(Q8\jhG%ć)ItvcZDvLBD:-GlkgX cJM^IU BԱ>OKINT"KH]&&΢rSB4ˆooC6_#8Wj(_u@)>4gvc 2`#tN`"CaDJaeՐĕmkDo; 0 .,7wSt IAhsV( F` Pk|B[r@;#rmrFkJ|KGsREf&p0Ur ׯ S2VAR2t % NO(qӔ#n49n g[$*ƺ(&G016NhmB0d"pVy(B*!Epz-aG"g,h eifma]&UXqHRۛS䥗N$ fܵ F 4wHe\C@J*#8'm$@**9Lm[{CB %Iǁv!\Ye_ "`Nm_#M-"x(ȃ{(|P5.zUځ^`?`hG` gNK! Tw0e;_ %hX<V{1~$< Fu }-Z{%oȣ/dL{3HsrHN+_>຿RNP~ 'EσqH#0f=щIxx? DHp8sؐEEYpٌ,G} iI-TV xYzIJ f a$Y L\$7w3v+:%.CkdvD v'x}_G [5RB(A0q9}3<}R̈ pM~-VSRm_2$p fG!cH1 \C 1ILұW#KEy?PÌro_~0 ;8nc@Qj@B-9Mgh (#8qJ7   !HtLp3dѹП߁cQ3P)2!*i%JS3H^n' $%r7Fԟ{Pv4E0&!"JBWQHJ'"(t6UFz]@5J(`804"dg(4%4a\ĶwEzS{mw2LŠLRvq"LVP"L$qAqNB ߠcob\w7뽉=ݨke״m\\J0><_M ~j6[AM)2lui׆JJT0:%M3r >/εXwcmFE;")JzA'*2pgv%d Mdr2, <8O8&RK!FJ}'צ{Fg5w+dlHZ 'ZqpD5jyi<[=ߣٯ6^{]_`ڥ3t?V%i\G_5r;PV 6-.73  A+(aβ􈣙9I7H=|m`X5p&# J.[,kFQ98Sn)"Y@ n JoSm +5/oD},+sV ]g/%?@%`C{w'?- g?͢-@KқDHI̎dB r LB @2Y O[=}5z37hkGt bڥ8dD]$WpemLzRo ?#oξrwqHF[#RIi4t@naA?ՆQr%N@iô_ƥ \/[G4z 7[ή"E$S8,Nnv?r|PKيe#qeĐ"kG>sSpnfT=DXiz5ӗ+Ɖ/"[[Ng5dp3HòRsdVQH}b%r|OqHVZ5XٺKNŻh$K2C* / vUtg:e^?%|dQ3rƺw@w`ax-su2og('"+ %b12 2{8}ۼ+K sjr`rgOV JKV)dp) Ce493InRΒO3I6BK# ljq1~}͓tWɅA%-m/ @=eq8 6vXU9WЁCg Z;mRr{ gnco"&uɁPH]2v"q>L݁6#zlDg - φT; [&M4.: H:'5ø3H$D"hµ( V #jU0k]Ld4FKǦsuɹں>~ApՊ VDC:F|3\:.}IB17nba0H.tSQif)뭜z/wuMmޒ,G3B%Q!A|WJ9e|Pݠ1䥗 "ׂIL՝Wӗֻ *G&l /HN_֔t=ZH*)˔צF3jw_q3^% WK\ޗKzZs{!W^,Xu_x?Y8yyyyyyyyyyyyyyyyyyyF/=_sOIENDB`robocode/robocode/resources/images/explosion/explosion2-37.png0000644000175000017500000002647710205417702024014 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%1 IDATx[וۗVSB"RDˢ,#eLःt@=%t iM<MD ӍHq"nDI~Kx4ܭCR U,V{^kmc9c9c9c9c9c9c9c9c9 xn߱Lo zi.nU|Zo^q2A<1k4姾Q}k mkRy}Yg{S7%A%Q!;I)h s 4LNZv6<ڊWMtDg>X2ZQ(F`VBYkZBQԞV蹭"|ɴcE*?螢?9*DC1qj78֑e0L?G>Wg ׮x.S7t*?GdⱝoӜi!lRʀ( "DP& xl\$D1aXpk*xZ~?^$]eYz\Fkw7c^sђ@<_WB0B1"dc2eB04X!iG3)B1, C)[^'۞WW$;cs.Ds XQ qyaDp|jg+ -ǟ ]k Ћ1RBE(LE 14Q>^¤q!VL)\JTьw@NiNK&a%سˎm^!Q.hG-`e 3 llyFIsHfءO@+Qi#IɫI#;ɋ-[WVݍ`'!ZJ. e*Bhbki})B Q"K8~(hlӱ)4C8W &RQʡ,(Mhd򸖥<59X)0@JJ5"lo<Vr>>2`eKd^)HmxXM<)akkO+/#mqGh@&ηr|o-޺OTkn| NSfò݈X%(֥$L$HRFag B9d(p fn:Z9 $z5f'"mPXpe W(#%$擭Q)xIEF`d"|E:8n$.IТG0(HQE$cL&8B6e1BSW.Ĩ%bHnĚrBG8H  Tr,z5kĖE6fr )+[!o%dd!hG޼${7CJ/Ěl {1@俆V]3"h*FkQH2EZ"]]h#md $/VAΑGA7cK,z"k(ה"  T`%J[ vI )j@Le=O+;L#xs*F4s"r;D3{h3B Q"UB{H(Vq|Vv&M!T;˔rR#O .D "FjICt!jBv6 r)<6 1؏(}tTK[DeTW^F¹Kt DG(AE_ƩWx֐"FB.D\81+hĐ%Y " 2hB!GxF㜦!ns)uJt/@Km$ge=y{ W\Z0LhEa-Exn.q3nvZRN@^@i!5Ү0,CXMG: "o<+=0>sn-DqI0%RߵzP»QE8RHXC8ۆ~F~ Y‡T#(WNzRk#A Z !"! -Ȋ;&ͣA4]rϐS DI$ X gpSN+DnDߣX 锑Ȅ%ն_%4#tBF4y3glW1"ׁ'd'6n܁ )BAV'RUCQݱ`}EAEF1Kf0)aE&P  Dp B JCZ`Dnoqk,3 螆߄E6zk?NI>AZ 8!V j]^Lq g)`}-*o?+a gCt6pb [{ k{{мG4ox-~&yed̝ )E4P=%A0 #6}y<9 NFA'fwI2p 8 I,UK:FvaRT<` lB#Ot ZxY0-vŷ>2Oxq3޵dgZ.q l9cAۤj!.Zk_J`UUIL>pHhM`ai&J8pR@cve2ץ3ad%͖%A]y}jYpGռ0Pq;yMnmIl09rX3YMv-VQZZ3~+kֿ+2f%50+_CͲK7Ne} U\|_kuH|"Q$>A/#7Os3]^3R'^y'jĵp&-NT^ lҖ5DzCW|qw;I'wO?[tNȩ^b"IEhpxF{R%A5KWjAnՏF;wnUMp&@T Hf]=@KVݭor˼Ol1" |J0F3D(j_2sڡPMBI?L.-ɿx_q^<P=Ia5=#b=g^ ""=Eaң ljFRn팝}H$wwTkNյP{.޾D)Yo;SnYrwRpl]\yn Hi>DSpfDK i5ۨhjo&f2 ilZpOSEQs;ClG ? CM{8\,8 p~Bug DSd JRS:*NkU(GsFܨu!/He*t͔F2n *C,҇5/MK[jcGN61"HMLBxz kۨGyM/Wo}+Jt$P!$ӆS< ŷ|8k Ȗp,069"nv5_S?LW/ Dž^9/X-qi2kx.cV$J2mM/oz@xXSp>^*= )0V K4hz9)`m^ tC"xVu%Y~*s78v GOZTIRzz^vۛ<>uqYI~MML1$"+:8QnA{A`0[c`]-)va=M'H:f@UyPV9 #BT%¦ΰoJPg W*X pQ_ØҵnИeP:°Gqu_p~%Ooųh{ Viv0l &U) C%xd}J!Gyڠ0]E h"ZhЉ5qV;Q=Ï8|`jMЬ &p.I q8\򳵗bPFC W<<0p}$Dq^*6B⅘%M@'d]ZQl01Pwg/As' O:i/i e w/ѴMc3ISgK-S|=?D2(tɲhJ'E ipn^=]zK™8~ʚĭ*@R \.W;cU֓t "MHMM*l/j5 .{8L B uhBr`hΠW{ s|${TrD `k[V`ROa8 nu6UB43ET~@ЫsT \&1IMip1DŽRa'+a-ٞh?A=vm|:&Ї"2,64R-ͯ^_UbDt$J%zג*FI`->鱟j qT\= lS&[=箺M/ #ڲJqg`/o4yدMhצkXZVBwQDN"G `sx}<ЂGGx0XSdrWS[ULYM=Sp^_0~~I2An[32;SSpcp.Zu$]Kn>8س=VrgP>"T MV2Vjaz&:qa~ܩBe EBLLpnL S-gZ[]`;s*)E)L~-"XN mM Gy%`ׁ[ n#S  81˜=AMQv+rqn #$IU mϰҕ m28XEM pU IF0fF?Fndvsp UpO!JD %F(MY쀼p{e5SVzVz>γ&UK EDjK*Z@(6VCqro3IFQAs}˰Vo~ GAՇxгp1jD#.-fb ; W::^ٝ#:;XB؄fT9Z&q)o=[bH"vJ˔V/QރSp[[ʪY-S<;8d'o˷YEPTQ`?p" Ug`w# -=1ygKҡ'o~-e7:*s!,$mDLFZbFWw%T, Qn/uO+! -([LŘv9U Wp p5Ak gi1DVf 'ؙ9}{ 6+/x<\GUmΚ5E[.4& ܐN4Mjk|eBjGp}IW#Kh-V%Li2p*R kO[PmW U$l!6B )oYOOI%+ mA6ArN1j{6_ ZآvN=@zP̒BdtYFOLH1(?9nɕ0N` O1bL(PEN\@Yn`u_߫氞K&{C.c -RqS7 W^c{#5n@{dQ< 0C=鲟"6ͅMQς\6PMB?, rraG%?Gí cߔXypgYnF||E~ǩrO+.Cbp)?)e@9ܿPJpIv])juίZMZ ,ukg:4abσg"xB d#q1fH,4_#S⭋Z+^X ьMDZh@SȘϷځnS+Y lagMknWzl:bA-Ä0F[+ x@+c'f%R$e@R`)Ea;%%kН43D7n {Ѹ_|Ӛn![{bY-BaTa7~FteK09'h&! bDE,l$2[d%3NʃgSQ`vwaxa8y ޫg{݅]B-[-9ۨ>_L l> Ӫ*0^ P&o ]B[lR 9 H@O 6= .!2\8%77Hp6ee#48ӨP!uՁ.:+ o@zaB*[Gw@G1&=Uy0Up~V9Ym`|)ViGCn%7LY#0'. G4OAXlcx6\hr ۞pPiFg$OOl<@)w"q :ngZjE[_ .Zl㸁( Stt0/p"A/܈H|LBK@s=xqv(HRTj^U+9 (L)^Nu$h [HF?`jp`wfN6 F D!Zh8b‰57J.t)o;{>S/ЮC)?2(n`%Gx_`I@&uQ4'[ՉRJQ@h87mZvLZCx1!w!œŋGkcp`6'p2K2$"F#)}P8Jh~1aGS-4"Żu# >EC#Ѫ5劒ubyO{H'(aD~Ć4ŒSTF)z4UA:6ƀw>BlEJM ܘaӉ u[إWnƸhپ'݅'2KI1RlM@1e>I=0Dx lFIv i.^>^a&c=&0l%,?ʟbMW%p+~ EF6`t,yt41I6 h#! {?@h/+K|tBx` Ȑv%?e]q qh^.$sOҐ^ Xƻ^HB8B#|%Pu#>,(;(CF`,sRE"Ϡu?hg2,HC`$;SG8RHɀIhQ7Qa7Oq:E ҏS"RJeiO n[K!#XO$'JA:򓆕޲L._#hjJ ,2*MH06@ 9QXHoKO}\G{٘HImu5EecxFv'~ 1htЍrbXe/U$ qLg 1Q(@.LN4]FfK\n:-ZmY:HqǞW߂nJ.spq>4}-pCGY@KH].Bt02m|BT+#XZZ(]mN3C"9?$#53%"j^H״YL):b8 -TD~.X *=dEqSg\0bt i%AGEnQX7Y?'Y|ڒ ڣiPrĕ:]AǸzjpxa(m9.2G4RL>E3: q}KYzKjuDEv BB p/>DOqܗ,؂KAm(pT"KIu}C/ܺ:q(~$NQR3 b" 4UP'!XQ0 m!)SN)UFKglD!g[%OK~Z^x˳훚Q;644q,mA I0 Co)xQخ㥦}݉ĜLC'E)oK4&?C"uD" @( I)tI 2[MsۂZ%װR]dyI*NHg%qVA?u\;$M& 6XjoA9WBDIK~*I:ߨe]B޼f#/@GVJH`%\㣀2֐de@uP'8|naR[ 7KJpl̈́?eWo\du$\;xaWGx)BE5-yZJ藨R>/yw>/*\X-qZg,U谺Pyve)-qn`i-/e?(D. ~JM̵b%ɭΖe*vo6yt4[ےDr:O%aִQ=w/YYj~KFFG ^:koWj='amk8^ݪk+ yv[^:j m);;s?Ka;s?Ydcc9c9c9c9c9c9c9c96 a_,UUIENDB`robocode/robocode/resources/images/explosion/explosion2-41.png0000644000175000017500000003373610205417702024003 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%51 IDATxُ^}y{dQ2)ۉA==}cM$ SE餁nx&RNznGlI%.bz׳=\^9vn)TթzOs~߾֞໙j4lKJ0{DؓǞx񣝆-\6g %f&i%qGpt6)jG_[ķrgYٻ258LE؈LJZՐ;IuedIԤ*ǖ5bg?n@1bj痭V{]jT/?{=Ӽ{S1I(XdyL*WJP/Ъ{%Y0g$,ȫ[pV\+puwl\|+x?ɵgžݩ`2׀k?Վۂ ˽;[x=lGtٖVf)"KeF&::H2:ÓTv1Vj_'H7%UbZyy8?k^٨x$\ rAVv#p feރ_KD&WHRY{MνiŕK.nx޾xEp5/]ps'&&36:1a*H? |R$ ^uVD^ 8Hls7aV5;L2Je0,YGሗ ow`qzT8ED?*{O+:V'#'j%CYѡJ$рhukHG z813D1a=9}2gx9E0ck210gKOK3gU^֤"%3w,A#=0ËċMR'{M*xkw4iBNm ]덱3>ݠ|_LJΌDCYԥ(5 [$j":ThK4U@~,=X,`[-Lc-Tr@33xJ̾e74 +ż>Rr^%숨!^kxN>ɻP[ JR2djJpZA`2(>% &Σu*QEyR`\g,! dܞ>I7ȭi\N=cPMY$ق4->6 8%ǟxWwt:Rsdz1'(x$熰=ӗprrJwdjH\nD[-xlV 7` E- rr[bEJbFichnv@X0T( bj;" j\zqE 'o5%,Ly.ntZŕ?e{H{~ù>tSQ4\Ġ5d@74DBAAi"/}sgVAG4a\CüJc>3ߧYHYa@AWs]88d FU |<%A`دW8^yӯy(EtӼ >D) Tku _a09IH"{1H ЀF^Es>n>tp`FL*P$x.t!Ue < J_o07وւ o;vD>mtaЋ`7.'µdp4yo"-㌁;Oo.8^Ss7 MV$ߕ*2p fڅphjb'F̓+n3prX^8AJLPZWu% /a3H{qTh%3yʸϪ\;U{}#>D@F+L񿼩Q?\!Du#Y|] :bXl%GO"'pāWù: @v=@K3@5 \O]G4J Xh=ƪKN)yWq1yY }?PYc:c5;ROy(4gFvWq-i@It $ 5?4O:ydapkMGYsd&9pizͫRDߋ@ jQ8Ne}: \Fn65~А׍!(:O/q e F~Vז V QgTCpH*1dpa#8#Wׯp w(v/#V꘼θ[# !/QeQsG`ƍ^ztDh'X۟[UqNi̍,d"AB_e`S/қ%)S{*5׮)1TC|#U^u!ΥbQ]VxB v X` IùRC@<" [JQp_w=^f`PVT+MX)!0U簷=; vQ,=D#A}G)xj3 X^΋VѶ.we!7x5?DaB)vP`wχ|a~ݿt|>x!+ͱ9(ޤRq 6xV D* (,{ &7ᑴ޾xSW=:<G #Tr=(8ہ- Vӥޯb> + ! /~{Hݏ/z0yTxHrZ g$8]"-稶DjHO@-M bq}FGk2ܨqY?"}J[w$ϣRn}w'kY8(145O˂LgN\ԄQSyC|ÕXt@ >B>R4:0PBfd!|) <bWӖ70|x8B ]f>#ˌ9N#ZVV5S'/ ~ L&dkTILFtUD?i7: K wܯ<.尵8qG򈨁p; 0|Cn C*;6C#$A=4y1:ܫ_哪ӓM 7?ېbzܲ#a3l9־懍gUKߗ1L|B2K) \Aw*E릢&۪8 uGqvamRX5><8 Kt g3Xk,}w3^ <5v~-|Tk v(Ā~}Li*lBNں>t2apRF/Zr?Gq X zFw`%/ '9G;C2zQD؎X;#6iHq=(1Ot P K-:(+1R#}R~)qӂ-e@h ڼAhB2Kx֨qT;V]?Qo+2 ^9/+Qa>O_&ؚ =G{jb0%1b!Rv01vnNHo//Y!O$[⯇"G ~ i؟b%lp'xg 8栦 )9L'G9JI'Y;Xk-xiOPD݄t %QJ{X`_ BH P=`kimj:j@Jф/9{{0~-!\dsfV# `$Ơf<[sG^D)%ɐ" X?B/F)b⾭mEg[|!TD23" 4lKu[πoެ\4䊽fvƮ)W \#¸;hH@F(wRQVMf8Cw 40)(HQ1Rj !Yufa!m/R0QTLc <Ī$dj5ʈ$:Ơq>%v7g]Dp)'nU/Mt|Zp?pZxQm^2^A bfR)@,4 vzc V))+WMKZDJcPPIl$P.OŅ?#+_.<'Jx/(&]UZ0z8 @ȖtfFۊy!d>}G=244}-PN '$@4 Y@ J .’ R!gh +MB:M"$^Z51f8O>̕p83hJsӴY7Wae+,b}?6ӈcOy9TTcD3 L [X2sC9?ZlgH\. A-%B0 w0,epBS ]ľ! _]HW4S\"'Jju*'K͍ 2OEZG(- jK x}bM7iʿ*|ǁhӥ`JdD#NZnyd&spOpVr ׀%Z8Ubx-:$=w?} nj)Hxi*TRzQ(,iZq$]:Z _A8i򫥊? ot#p4T&5k x1% .FC5CoĞoM=sq簫5]uHKq@ahHJ8׃ ֚a'9Y-~\[z_ݿIA8 `]؞AQ!ݮq!*G %8r¥ p? {bG-*(GX'2#^Y#H:^DDjKIA1=D~,(`v!qgB)s|Tj;f'*}@F}gÓ#wjb&/ J㙢8}$z`ot:z!< +^CNF'~S O2>0hBxwF=b3F$sJ&݁e޳?dxAi-jE\Wt܎Q!69pWÖo=~&T _/tu5 SZaR6NA|6ś-elÔGk_k zڻXw,)HƖO'N߽"yi* %L$vLT`!O8-%RzKGuEhAܗ!\.4]Fч6.&.(1g)W|gXc_,;٢W)EELgP␄I}#OA.{xӆ@&3B*);XOXcz;Iق}܀SsGLy6a((YÚӑ穭dk"Rj"qޒN· :/Ew^|:5\XQ݈ZE7Q9t.2tJK27+f0τ $JvO/W;`$\ @QOYlScfg 0_IDATo_AG)HDz[Byr˜2lsk@P:Hڹ}%ðܝ55qRB&h*_d); `~IyxrIP$6F,H`.pͧ !\85lyM nj5YRUTs6mߙQH(H8夘#N}{a NC "PE'R>LH ؓx겲โ%wwct}8wE5k&O4o,۶tII_]|Tbmus' 4ma!ԢV=\nœ˯QcyuCr_ =.So 5;|yd%k-&D/q]̣)v9^wL3jjpr"#bQ(I5mۇt`gbɐ==^*$mjFt[:짬|Z(whHuz`;Xޏxi~W䃰G%Hiϰ0qӴEcxj6,}nۏ9b,8٬Xp2AӘ); f3 bU#vU ?>]&0x&*DpTjϭ!?=ms4Fdf%pI"4V -ұ:nN0k]_zuAK8Ǝ(uNѳ<F$^ܛ)FO ,&N;f#`~wvBn5*趓S/8)ê|>D`ZBb>']O[jEEǝ}i?(~H~zIG;Ύ-#&1gQZ5Ѷh+3rKjEk~pރl7eau.CaN0u,3+>s I 5$1I!]RT2KJϏv֑η]e2' NZ2NJlM/~Qa/E9)]odKiA6=܇` O֌5Ž- prcnKVWG:"`QuTZVcaD T^+-ۢ$r&pɶƠ$5 1ӎ NzZ-YѪ\Sh}5٘_w()Fq=u<yrg,jG fĶ#@[CaG ui6L%9D\yB%˾X#8s7x;[)rd&Zr%%WBUKEZga>9'3q\wc:4)uMb~v$ƞ`i#Y;xzHIPBLm7CGY/B'S@%KYKv2"p]sA(Xٍ̬0 m@4t~. l1n3sO&ZijW蘮0'DDrǴts?JZJ$QIeDiD`xUspXz49O3V W(3e3SHf)2]:g`؅k6Y$OǍ6x vV. `msKfwyu8(qWc13@E$k?O6,HW| D&YQYW]7;k?Lq 3ؙ7CaP/qR܉ )2h=nr ݭ IrxXٸM~CdN\yڃ洩Zj7NbD&ԇaYǨ;D.ޥ;Sa\N-ӞC,oƋ+rEϯcɹUOxDX:| z`fEpGCB4=tmmnn6T Y?ۇ[Aoɿʖ() +XaRvG --.{!D# jpEcnMbl5Aw[&t >bb(NPFPk<}lA'1)Xe3KDZ^,1]; XT1I=PU$'Elt yDaY}m_,kF]b AC.9|4۲9i0("e-}Lh*,*gp9@#ˑul΢NԐ1.J3J)!E.Z[ q%FI6]b6IfӅiY_XH!܌xf$ϑzLTOP*xC_#^,;a1k}ώ v=b1ӞQsQq}T!QLꔨ{iM amaQqgfbBQRuV%K\b.{'(!xaUS?hB-TH6#oP5u9)3D2F++T410%F2Ljч?Dw]\ګ:+}N"^YS9i6cwXA&/l-J+=y<1zEHDCEHn6[.}cyz9ܠx.|wjf>B)? EڏxozxnN!!Nx3Czr9D1Q~L PSG+ЛMhλJ!}nlP&Z(/݋hG??ǙKHr@K^5lI đu#NJS#ߣHU!-1NG)8W2JUOY0%K0.}7.ޯ#)ҎT(xq?ۆ23DьeXYb})%C p"B!Sfn޷k1\߅ATE]L-zj,b7w(<]T1gx[##ˢ f]k(P6D~bߣx諼|o{xPrcFmt6>6z5d^RN}8H:oj.u%ϋ{76O8"L ^S' ->E #p8@Tx_]`*ݢG7PC&TogDI\%hF[J([2, :wtE Y5i4tSnyC錌cAJ('xpn$b'Qb]b:3ʙ%M YLf$PEDq5(l! $3 qQLt0Io2( *"QP9JD:]ì$d7ʚөZu܈=[5oZq7EH&$c ~f'QXϨL㩼EJ}H]D7#j7H;G1clYP=Ekfg8Zt4Dc ޹+qDa"Dr9+p9)P>r 2Nډ!peKu3 E@vlSSS}fY+kIX*rthJ}ǒф[ɂeEkn9V%ZF/ nGMEMh̔ tteIPq6D+B@+!CD!RH!p@7IG}jχ 39-֊a}×ֽNPKbIYH{ip! w$d)*MJa8N.DJ1, ҨM;0XmemG?r#RcUU p nH6GLDX"d\+8Khln f`HSd9wf3Z`Gp"5P/$ʢ>L:ڹ UDԭ)aN$AƷÏE.ڭES;:"NGF%]=bXYqϷsgƍ{_Nb4BL/B!ӽ=1qbIf$ r pDBkrq4AJj9{]㒦Yf&^x[yJC@Q SzWausCr=߭j!bL ?2m VZk3ŒTG%ӐPB[r%L ihQ'zU7ӎfNjb9:1nwEF@@s&<ƱeWmܲ JU˰^4mD[$aoL+튤B1[$(=hAۜQȕ[1RO5s_ OwQӤ΍NDes" (wQf׿w=vEd{]I ZkAT4|l A؝N?aW<C?mWLP?K=olY;>i XT pUF!|V;,W'oa9ll+GA{(0{F/x<x<x<_v`wIENDB`robocode/robocode/resources/images/explosion/explosion2-21.png0000644000175000017500000001132110205417702023763 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%cT/^IDATxɯ\uSw78ίN:n]p8p8p8p8p8p8p8p8p81OEZ؏zG}~.\&󫂷獽b~Z"T"y`uIн#Anc-Su# `[K(^8)(*]?Bx -YlRAu!IQNxn!Ou+EgӧF@ko!bB=Rϼ{ 1݇1}\ɬDLȔh2 @)xV@bg Vk#M;\µkӧs^ں5ﱴ.&._?dx|2FOLy1zcH RQ&$C K nG 2̘]0U miY/+S*HajQ ^(TiJ!4s''f U#{k* $NʋMR$MXvEsҼ{aߏ!lPW.;{^aZMaGn i.Qe%sM#(Dm B3AC> 0ƪ}Z e3)`0,.6i3sҭ->VT|5bc<$ܑt| bq&* <0v#&\C)hwN2qR9*v= Œ,0Bfo@pRԀ ^6 FM#^P EJ60>Y2RV1`>|4E_A31yra`u&V7~cAv)$m'ZF@a/9`9Zm4ߤsoWQF 8ҩН\‹_÷Gb<M +dy|!7F^S0IiMۃ,נу[(/10 '^fK.G'k7dAzO#ah>_>:Zrt LD05Kf^P?Mxz rbs?Jk<R_?\h h%$ZD`rK, .+~?( By- |Esj ֛_C9r/d"<Ĺ+> ڝݥ%<62;KZE2_<>w8^  T>h6N! !$xo5:-XKY{dOI=J<}/H* {9a\n#k֞=^  LG(* ~XϽ d @#ʲi2{RG-ւ K^|>͸'\K T 6zr@0NK#y@PTxA+t)tt{c%i+cfwp`QC_-́| !c!Hq3X}ɇ|ђ~,EB؂EhZICvx+py6'T#XeOb8GܘYV)q`>4Y`,ݼ0L lj>/+%T/\:/>T`@!a4;|16\P[khhW--˜Wh CxŠdx10]}AMEN..MPMn4 V=THK^x AE${qRaXǾv̶xi zf-+Oxt$3Yb"(p%mb|!% GzhbE~kUKs`k t/I0I] vOw]r>r 8 72J z9{6, w |j'aۇ5㨒O(xA.=sl kaMx /MyN6 N}4~" H׹0N^Or u)l. yJ>hO]/$}8A6ېw1'(G㖎Ճ<+[NZ- hh >6aȣT@"W-nvA?`M2H>iQpc-ȤXFkʷ<^HҞOa͟xk;%RO! ÀA#vSD>[րF̶`m '$vO&d /jY#߸\ p0D9K! E9TzW"6=A&#ħxHr Lo`V v`wo/GdUdUVJW0H!E~vؿgga:!(&=m*ydkCX$Uԏ E IAn=j2qb8IՎX\eFr~zrrGlx42'aU2M26Jv*BrfNߛd7Hk%nF(AUPȴR"8"4P>fPan RiX |s-'uk ۥZ3ALd0 n62MQy>B3Y\!1AJ$2z#P@1Shs ˾ j19rc8QI1{ȑ[)X`.DiPTl~H"<c44dY: hpD5 !͖xXp {-`$ .#:Q^&B&bLt;>(k0=.% THX o#[T//,Jߡ7*6e(f"'9-1?ɨˈoG^Z%l{4zQ@e.PjطlW""`?N ؆nώX4LgPOKOf[,XL.|׀eG3p@Xk1\[&X'C ~әV+nbYоQ:գ"hkI ;R ~A ހS\lz_-ʅs(_.ց:_:O3"x탐 dONc`Glmi?%oSs8p8p8p8p8p8p8p8p8p ) yQ+767IIENDB`robocode/robocode/resources/images/explosion/explosion2-10.png0000644000175000017500000000403310205417702023763 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%!IDATxۏUo۹͝JqP6Zjcl2&Mc'AxP{҂IjjkDi!qt`psۗWMLX%mgO_9=o{ J)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)R#ā|yR%9Q)HҨ# *\MbWyvȗ#}dd^ٷUǞd { _|X+Z.=^>S!5S$04-C%s-sjTk9}4#Gr- SFJ0PKY D-K{I1 Sg1PN *>/O`>-oS_yC{/ n]r̳*o3t7Y6U!L?bT n9_`=&᳕ʲq=b% Kd[LDVIZE\ xEk:sVFOԴǙ?ՆqO{S#gۂ熸kF!LU#L]y aR)Z|^c+Ӎ0Eh2BDү]ɽہ^`G"-鐹ߢP1]Y#!ZkM7< 0pqv2i;J;H5qE&[ `=zZfDا8կrv` s\%aͪs)"N `~.z<[|猸B?\#KMN}s"QG;>1  }R%ɟjc3Zy hAL=Hj”<[+ë*j:bKʓdna6P9pw ׏wSK-%fn5TgtO]%'Iӷ̣Xj?<( $~2c0&R=5SFQ p (# jkkX&]aS z Yz`[,iX?kƗhŠ}7|Ak$nK [舷U'eBϰܸM!MA%l.wbyfhŠ-dv8;^fQӳriiXWۚ=x۳ [Vl 괲dEG"/gxD} Id`F=e 9mO/_l-p.^{ZrpdKNepD6c) +5ʩ%0qm^^d y2p*_ypPNޠqkk5oA+Ν?n dPKHڠ5aM'D=nj,de~=![$w80~O-:p n~+kUuN_ek r;ŒHgl 8wDDGI0-įo(QY 8SCRC`f$%ENa'Ms_s\d pWН s o7iBWf g||ss]䫆8\`j f!qrIprz8nq/ڋc{{-EBK!Y['& sBW0e N/MP)VSnk/6yiDwm3_iEYmسgZ td\UOYa.sL?;GaԲr*)+:.Ks?7PrXϕ(z'˜{fKG`sn=wݛ?QRJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RJ)RU1U/}IENDB`robocode/robocode/resources/images/explosion/explosion2-49.png0000644000175000017500000005052710205417702024010 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME&v IDATxˏeWvۏϸdLX,VeID {`{=j&yZi=J@7 ðeA.aV]|G}~xbdI.n{gZZ<<<<<<<<<<!; _^5ǭ SV+ < }\Yu>3<ܳ=I9<K៚᧦;?ԙЗBьPpq` V(Kq38|Ԗy1[QP<7J^ooH (W#LQ)Ͱe( h1GAe8ZXQg۞[Z|k4<Ʒp3#N"AFؓ>RApM v+qL]:~4Bݓ@O?+h$yxJLSm H] (QD 3868٠5\7͆ڶpiXJO[G-~԰W,b.π'0 WuL*lj ϽHʇB1/q@ h`c;f jf,Bg."Emzt|0wf jdWҮdVLEj)O<<& 08' *MUWHpmG'֘aÎbm8b7#x„釚o(RVI-yp/yiN9|ݱE[~b}&gw6%A=2m'n&C,25'd~gbsAb;#:"FP#S_B;4 쨍azQ0o>7ۭ/@cg,62yuvJn1HZ-(Zک`R r^rM9Em&XfX7"c<#ᅑxaK?=/n Ghy'آfܰt![;+kDh!bk2T& &/khߒ<{@k6sSh?_. R3vn"-B@q\N+ r-0֑Yv3.`mD6F JL1@6eJ ƃ YZ S0Pvk;D1FTh?BcnI瞑o.9uBɐ,t F1F:Rwx.6|H+2ΐ/zMZ4gW<7_*nl?Jگ & OI\vL' ;K2Y~75D'.j3aYRH &G5JúS0߹%³uЖPt0·,kt5WS9;ZաrOfkLjLvH/NⅧm++rU~(Ϙa@8X$+`l(k5mm(v,_;s-;{,&RPd{`G'u?dFȨTemx}M|4 -7H~gr\P +]5:di2 Rg($~N:S]E1h߷1S|l?ހwB嚙VG<_ό@[Θ>oIHZ_,T΋*cn+DWЎJeN2| lX$6l밑 @)t-1 tFw.uz%r4*C^h{-&Ƈ0SF9h,6Y8RYE :$.Fl^ mF3\rN.O"cD;exndJ/ܫpawpuev%;{.^Z??J.~>q^0ꢂ%05t-li{\ <@ p6²^D^%w0nXx%+b':G)5;xQa݀tz(p >^MX¢7(t$+1(ޟE7Du)5m# ;%uEu;8n^ H!4k$su;L9T :e['\lkcEÄBJ_FYE6PD Yu Qmryܙ{^i],Gv+K-`;UTU=>v+UF>wI0B{nguFk`._&.`?vzFt-~] '5*aچi;f5 EAƝ~ .q:J,*\!>c( o(p |x_g >4C0;0qrY|E_/%7߾7n-%>`\Z0Z%J0(5Dx@LB'>LLHL ;4Q{윿6Q4ruRAg@Upiܠl#?ce-QR܇{;}ރw_a*" `e s/Nr[HTb=$Zx^|&q3ebpA /C^psecl7ǚ-Re΅ah9YVզ- U 3 ?l ǒLP(ϦklVˇX/QFm0J#+FXHQ:Yq?LP"Alju5 ,+8YEqG̀N^ (Ԭۦ`` r3Dq{p}d 3?\2}Cj-yhT`%K12Vdʐ^::+p^2,>^$P>;B5CPNVIh:"Hv#EWXy E9xXCJJyV"S 9mjA'Q '[p(~6wozW.}c2 1jNUIJ!%*/J țRB-/ąsE!GwɎ&JLqH+]gj2XH oT]֢`NZv ǒb=xVT 1={[)6'9 ͺDd`W0(2aYp̣$D.^,6:'F.FYMA5O4,k)/ϕ=ʠ kjy (LjH#ƔlI#rZ tcz>piϲw+{N9[u΅, +2SRbQlYeLN2fJ tΆr`Um 3i'uQ|&.v =eAyy7HJ[9l0Ϡ.@YXWߣ[Rd"$C'i3hdc20W|xr}?4rS|@ xoO"IW%Gy!ctTR꒣|0`1m>E3bBkW87$W9E}"TE I><[Zzo7Ѹ Iyx%c"u%"i-H k]ʩӄiaAZ҃o@lb'>ӷN.(dѯȢ dyW o@;؍9鮅.ζT-ՠÖJQ?î!|"п~?~(i td( -Qr@8+ɔ3>@h\M|1GJCǼ BM5(*E*z%DRVAxy hvCӅUβul1-rAf2haPGa}i%_,ԊDqqi|u% z#qB#Kg\xK,@_-.*a{Q] *rГ$kb$1K"pt 6*&)gEhak2 F9\R!J2YXB@+^Y d@G+^Kj;hme]A'+r9^H1@@ɀOfKӛh2,I׉9iB5ɎwH,}$&O?NP粔Q2E, qz4 ]Fw씓;&X9G! 7(JtswU|(PR╦h -@W |\-b_eW "24jؼU`͈cr>;*3rURA 4MӮ_IB8t ǡ8W2U6<lCO heN K .?t7A`o_ 5krjBdsW8r|lDxaTUJ+`V 4bڻN[ k' IDAT^8 ?ݝ'σ%E/w =x_Y|I"Q:F&ȳ*0kJ2ogH111y^İIQ,eOk@V HFr '206iem+ ]bXn%OvswΧIڵIXaYPO"I(ڜ9Ю!$"E]Vk/JX9BIВ ϲ}w[riKUP^JWx!9CUwslXۊliK}_LM@$9Dl]]<+(%u$FYh1 BVie&$Ch`|j4VfiT.^`Pa+ΕdBFZI4*6YWaUD$JMEEb$''ýTis ]BC+%s8RI8,:`:Nh$Ä#b%%̍·qtс2hoAе K ?͊?zxS(Õ ,---B8Pw1~W3p`6z5sJ'N Yd$H=0Du"t^i碔gpв޻ljEZ' p 쯂ЉBoٷ>(5$D Vx2OͩS((\=m&%!E:\a(a0pX!d>PȐQka >:JLZϒ;:ĕ$ԉ]bd!ǜi;׺ԉuC&8N.u3.d [2|-ܰ2;'C#/,ucq2V Kp6AbdTX11ԁ] }ޓ@|UHy0w\ Ӿeqt;`y[dBF 8q9 Y)Dws7QluEz:IJ>(rQ6⧮ nX Xo6(R,G^a)7Uxi@7{^.ucхڎV(قkQ^ Tl}B6ZJdyrK${M}8&>I\L'HNpM2wwؾʲ׵N\Nր?x %ÞYcW`WxF۵زc[Ƴ=pMǿ~ǟޓ-Mx-xkvhnؠ Vq6c[tJP)Vy䫗maw ,,\~,>w ;pڔIy߽3'dDaz(ct_{";B>H6ZV$< t*wQ62!0G(ql E]av߲q08y]GudɕA oQƹ."\!o C".`d!_B@>RN{.$L^sQ0) JӜSIk(*3QvL2!ep6ڵg$Lp\)/8ӄ8W!dZ x*BsKz]./O^URIȃ$gP&f]%JL0M] &$W!S NML5F‡:MG̴Aȝ;?} 542t1"Wohq9~2{8=w9~8upl-EG6ԶF N,=y|(G[Ds5A۵Wp)SANaw,9eɓN Rg3& ATDOܤ|gë0Ix9n ^ܕ8ӧEOu5O-uȄ&X@'){u&Ѫ.N=q2'Deˏ;ޤsY`7hOwpHZi$ʘ u)^C՜E0]>r$a#:w)?>=ft bM5ǝ_uێ?1 <-bu!xupx;Õ4,)Ct&ʹ{7 -Z:1vjFM$k$dO@\,G3Di8q!:8H.0d"y} e]=OTԛ5mRB=4u_b:zF֏B*NQV͜Նr~֕o뀈S%mH0UGkX E7C YC,'T$S IB]ހ(Iۦӎ[$yͳM飏D!xb{{ppor[pã++PÙ5Y1gYPKD`Քf u˻qg6NV?ӵ~srM2b@ &C*zѢ5YRc4t6dNv=Œ@ܳFp9ɡ =%,&q#aw<9Rė1HJel\&OIx>7\x+ܔBxKjf/7m|d۟^2# 77Uoڢl@X1El#r|;dR̼xX΀6O+xumfp.oҴI>kȤ0Ji/窔[x30!Yͺk]Z}B?ESn~ 7(K'X:J7891X*3|!QBh+3L/}x]iw:BDID)#X87ȰNE šwqw0\&w<9$~}v, Qs6!|ixrm6e vWʰ^1.gz:=z8XX"ǔ>B%fD|.Fnhud+;,:lk3.990G'L@"<d,:)ͦ>eН@T/ zl*ms5t70zeM3U)V˜mcL>ْ߽8K%'Z_x񣹥]l܆mZqp k(}h ĆcښbF '3 00j d+VE{KH)0eޜ$4X$𴓔$"h0WֳJW}k'5MJL2, #kH93ݛAýU55lZ.moxд/v6-^Wd2UmdM|Z_%> TIjwߗ ,9muVT/#(l$Ԓoܼy˻8Z.pPuv|paq4qW(d <~|u)ģxFC,mZ"mszvM`wV&fM[R\[?ohEF}Rvގ܅˱F~ x[tL(`/یE#Mlxqǭ[;,G-G=# wX/ur5ƫxi/1DVԫ[Y;C0N@"ID}~ຄsoߝ+< `<9=,3x,c&ϕ"e{2 ƅ@)Q9{@%\Vs6W5p<ڃr(Y: %/`wBIJ~ m &qlQ\uH¨.b^?cO!'ME'd1z ۉkJ -ZКrk^#sCc3;=_ 6@%hjI={n}gnu<*ƒY4}朳uRt1 jϱ{]RVyaD $OC3LKI"U*ȵq+dDDŽ9e_/9: ,M?vT&DCjJnBPqv!=޾-FəE6 Yu`yUG׉hP-2J(wTzγ< R2et[IJjs  9vG;연kT2=ӧhf7L:@kں(O=W? .z+}>(6UXtpKg|TFg]tvZld;BPjş.zJߗDf4YV!3C2*,raXh_xsG+tQݤ}:68>:ҷQFB?5Ѻ3cۍsi6@p9ZW3+hc }5VVџ=,گ8W*Nj FY~DlQm朞1ib5b8=I6Ofsjhl Ӭ(@8l~lhyu6QzH$RO7ɚpkїӴTSw0_==[ѱBӤO_b5o cɪ+316lc1>uA. )|Lms8AL۰:B sڤ!YuƮɆ6Td4 5r48tT Lוcc [y 8Y¬AO[(hGEdnBWvfٚf )1GTQbbC|xG糴RqhS#\NK/&26}mT KzUL#[3;k߼_GzS}b]mA?t6tm &jR4D!h}6imzkR[¢ϩ!}qHp{̧ETz- wfUzh `q 4꾻Mv!me!_|p&ڏjXT5"§zn(DlbmυR-7Q\(1ʖqRR2 %JׇcMB=QDYvC"]`N|tivhmw_;ď9ÕA" KlUeZƒ{pԦC+W~;92쫒1mEr22Qǝ԰]>DXbV 2u$d| ڳ` p)Ff2t 0n o7ɭtԥ߇'xk]?ˤ9ic#*J4p/f >˄Y8 fK:} pR3ɰ~ģ+U𦇣937[(]yYZw+ F ]v '`L¢!Gh?HH<4MdܿŇpmG< W 42 [0oO*4X99~WЦ5AD,u\odXS5yЧM:ֵXuC>U+ 1~M:`JV sä*<ܞk\5[Pc8*dxV)p OMBނ/Ą:C"GA="J[%s#Ɗ5Π^^7pR*lThbMNf_|c7D-|0_NaD( 3UqU4c̄XGaT֩UkhbD|zIDATAm> ̟QS,dnU9O%Ox5FGpՖ,՘(=Ȟ 1z0LJ+$t uv9D-!!c ar5mt0Phư7TN B@>v+R0A6E =.t"C)W$Q~ܗN;;tåt%-dFs;ŚQZ $Ԓ KS#*9)Uph>J%Cncr&8:ضgqV8OP5J)bDkP c8eʖX* 2Crub5M A@!tFhZ<,1bȽj&o0>РA DKA#_&OiXU9$SђKbG*l"*KĘVxjPGTDL9EKA Z5ò@ʊsXё +h%x65"?;00QD=P.N>LP$l_CuN "jpBdtE ;J1`B=Ttx]⌮'p㭗^~|MqKGƶSa$d:a ږog|eINQc⬆, T%_dJdr]"`C]NcKsb+p?!c$0A] tkCatd!SDc&&f _12 U21P[-\>JJPZ1r.F]ց| . !A,":t8&b׵hӒe5Qز-lGWaP…W?\|RAJܸViJ,d0Fvf#b Gt$WEDd9!Zd1$(u#GpBǔž$aD7'e;gz:2#SA]ա6 m1'@[iLi hr4w* W}A lZ, с53;8Lhґ18;#tS .pjd8"@1 _ p#w_f7p |V7"\O0xPg%5R7@!J@ 'VbCc:h2#AީX1"3 YoW1f 7GCaf0t8QmUvmB֡#d.d3Gvm :]`<&ʽ+r֬xɕC[rh<+)[Y`:cv&7#] *D xW qi(V9UQآ(v evjcKč0@0Ϊ 9JƠ !* L:kء9pJfHBhZq-ksXyU6 L(d~6X z+']\BXٷԁo<&4n'ZMPvd_+OT/$ׅw03w4e8cͱ{9V ƨl Q/ $*C0X ht(!&^/ Z/PzvW7l_z.| ͅ[r+^ [4MPAD۠Xdr ~f  ~u &yd[y&Sť}bi9)K(kDd# E4>ReO%4ps~>y!P{]kµD>xkx5{|#H&K`tDU(R`C&Y,*$nBlD@yTPRLCh+r`Yv L,(tqrN ?8yϹJsbg?fA&de7 tdGv& NP<բcZ4*h|g0iE -(p.ƀ:Q䣝 Ņnzm/| \(5_]f,˂,W%z\P4%Q`d@%A-&J짩<^b-׈8 fo2zlY:~y㗑T&?DqB~οT\? c0!Ez')܄8N<^f0R`Y7 (A+춑f!;w3^aJi|sbƃ!&GsJ辉9C,brF >9֣i1%BjڎabBtؕc}'[5RH7i;ث_\ЌN W 9QG nE(ZOs?.׊_X3_RS{3xD7+$u}0c}_?wxf<˙~[dYrr teŋF՚hTB[ET案x:\08ʢn_n7wabKGD pHYs  tIME%:(P,h IDATxۏe}Y};d"eKhƒ@&g-̣BH^<pJ4Pf<"yl%K)}꺝뾬K]eJl٤86Ωsvb}X_/b}X_/b\o'&ALdwS|1=m$\;_H} ?ffo_/; ^ \lNm\E ;[w\ ߭UH2oVNmyK#Ǫݾg\yv|5ˍSFsCTmɏKv..=l@\ATYAg1oq\,v /fn ܧ z,O|ھR\ )V'B8M!V,Zv+%`4-=bcd0cap-͞eǟp_NÈu=wB|: >7}w+ŎR).UF6B!ƪNJ Se,fѩD͉4Zgs7m3?|yvv/:Gu7%_O$χRs^{#O9U1rUlm2؜aڜd\Gz3TK֮a)j Nxi=hg8\8nֲquֵ-?:} M*! 3 o* ?PL. XdqA{ek\@ޖXqM=2rRb}(71!22HrbSkd,mͺm@3rLN{mñ=y}c#8 7~ Z?Q?oKC m hG8^[Z_f@|}q%~6E\\WĀPf-lp݈AxV`Uk y~eENX9So$o||boS>oz$uu،\㤒|p<><_XV3}(y8#V IRP;6CXw p ng9xx,M~WtN0 @6TpaװZ^+Z kxʘc'Q5֝`tR gN7^W#5X; `أ/X"NΙ-^,YvP;xdϷvb;lV VIP8$+N)1r DW-Vs%Z*2 wN dKt8 xv)K8HS>) 2n wAѨAcyy组s\syAIŻEk``s%]Д KѾ,CR lS%K6d5=( փsӴeVPja9^֣r84( <$r`=ϸsMXbf(hwj078Kpg?[O$ erd tG'$א0޿C!e(3GU䌀py h8n F # P7069'헨+,fP8gq%9/=iT#2WQ[\ CA'&~H&< l5YEgv,|v8cˋ0Kl9F+t n ~˷\ ҟ`E5.+3X4#<Y73YO (9L3K ^ X ڇxU[.` x|%7计ɴAY Q˘LT2\ǹE߮u_{-ie-/]6{"yq!7eϣB5 lz*`m.1Qyy ~q^ϱU¹+>\_r( Pf94/a+ !lv VCå?d_"?-sFrq7sSXvyib w{Qô UUK:[-7&WZ 8:*p60дp"|o<+ 5{k8>t[#ZwtJ<1m89]4J"jg\p  a ¥<`@fAVQzXF fV|N`!E@4PXж*ҧ_9ᰆ\0'ύ G8O4R;kǏ6t;<}(O<t?I{@!(:7t08q s@gyb`;[l;ԇy$t A%(=,{?Swe$^]݇wO@/aم{qUU<(0=u${< i">~?*~B|~ x _?jw4X BzvP;(S&{~5U>VÜ`GIk7ܧ՟߸.s (š$'99ZP#NZXE۹6_GLgpDЦD Kv$.mo;~xXP"^PGvA+="If΁zieca6 |M#U*۠w=o-ן}Ĉw+3~RlM2NL-YFgkasqW&xΝ=HQH2e$ 6a2̔E:"&:lɠ2̚r?!=kܲi9O6|rs|ǾkBٖ(擌0>ncv7c`&G)+˟X vFC5Id"(}&;Os26<2/ 62LƹΣn`̿ G EmڣgнT'?vuھy׋@dl)r4Ìو]Rf(3*uYcTc6W&pym9`&Qi8 [Z3vKbg=$D+U߰\CÅ<="i|QBz pr7 Sp|:?ՙk#FW@j \^W0rz\ {.C/89R˂E{; KԼ/vM⟬Uh[׾ 7oqܙ *1nXbD82O[z׎xa .W0(\緢O4Eȕ*2 JWQ mqI$3@zKDFhj]YQfӔ㺅ea:K]o_΋ {Q-xEŹGbba&ka:(x PtDKC;C˻pu߻{C}zͮ[svņvzj&X 8o^,_z@,пz[zYI6Jq***Y Ud3" z:Q׉T$;[2u<|9O ~)uÃ&ܲ"+UK!h*16bvllͦcs}-?&C_; \\12GisyJ~Y R TPU Qm4gI=$Lęܳh"hejZ֯ tFaGx1CYD9c{oT-?ࣘ?)K4x$VˌnN*!Cr?y dQVHY(zL{}ALQ{$ΟN$~xgQ e>%c D@ jzv)#cl;"%*ctH.㑷,Xx_|TS?ܺ%,o'[9/5RF,)D#)j:s]̃C.^EvFR7@otc7>\_Ofџ\[!5pns{M~)Jxax^{k`OGTʹL*rSΏ Cy0 X%K9]KwQrM|=_EưIqǯcH1 bsmuV>xr$a,+1Kkj7Ji RvL'Q(!( o!@NDa, vypW1"A-@6ba)07OF[֭0d%di5huAD0@!^T4UO@<4jH8T'5.Q=g/[>>#|"1 ͥM4fЗ| %u4[6J 硴{PoIΟq|  #q{p/F"j6)~ SJxI Oίa7=x9ǘzdgIjޛi{0 (X̯JP8ٴu[EI!2hѹRKW' $tYw)5*]Pڌ"/^ ˇ'7K ߯OJFF99FX;@ )H/Q^cQ2|5hOr_:QYm߻^&1y'П H ?? {A}82 gX3ٜ0RQv![z8 N1`5jZ*Ԉ苮ݜ u/mG_LB7$K|BH8}uO(0`U-0H|pz_p2xL/_u_&,uhc jB+YpkiM핂*4_N0q4>LL")ɄvI!j݄2MtXXJi]:)#;")|4*b~"G_a4z P'lu6 V1RZ &Bx/@QyI)h,F+ܺ 0Ff uBz>#!S^| ݷ&4sWeby63ODR o`{Pdza82:$Y]G?  -g f X7XB@A' d P$qދd%W1G#[7^|(x9SBѹH&KN:ģ͙bM_O/8J 6I1$QŚBoڄhe aᨽ`@)t8Ѵ -=bqңz)&kAB_ c7[(d}FTt T92rK-z,L8RzH~NFX;A*BB aj&!^оk}ۄ=4j|CO IDAT?-6ԉ1Q#u*cı񸢩#8\68A#1xbGk<,WϮ ayct#-Bt!0ô{e"L`PjDS!顲Z f}a,k~9'~8)QRhb*!O4O<>9袊?Ly>k/{=c@sTg4Iu&Ǡ>*?@?˂ Gm255\윜é-\{0q:3Y |Tg׹Dҋ$#I…ȔDiȗp< Mt1Q/6JE=>3'4fI%kו;˞mA@pO_ |sXv& LS!b9Vp=nx2.t8 Mb$ %y&;Og`"<.elW4k|}9گ8v ۪OzV#[  s(Qtnii)!p`gJ߯?8sy|0DĆos؜3,ʓ"=3ilm'kT/(8dԀKm()v`Dfp5btct.D'S&Z=G!B= C~a;޻SwW6^*?;^nr 7|X Z vޢ$hyvڸu{ BX% +C1QJF#'g+N7xIBO$};}h71<ĉijv~C ړ&If}W%ƊK~BUKxi )`ڟYAm**$MU{eIG ?m {Lq/\ɶv3fB 1Y)x[Jt'1#7:l\@ȤGޖ أa D"$&e~ >,Q2D8A q}GQ!@*:!y ߏ?u"##s(Ҏ*X|YT[>;+囂+9``%8C:.|}cHͣۜuuu9}estŎ^rW˧`>2}teO ‹^֕,Mι\DھlgAp K2×vsn΄}QBMh ah1@9Éf}_q"\:O1`\H+3vp+%3٢=oKUnHB>ϝ$G?0VaV=1ތd 1ܠ &#LR`Pih'/~dMFq^du"{D@1n5 5вDㆴb㠳Z&C5b42Eŧ>y-Θ%$&&EۜaNIX$җW5[mn=yx8l*W۬!ݡ4rɺi\0s<Ўwo| Mn?gCm sYb imFKH gfO4fgڄ[z%*^^D}'2b/`9}e4Bc4FI$?ə[ݒ4ZVl9* P~HrL)L%,aQN@崘$L'}%IO1 ^NK}ULe5v~I(j0KBt}&'<\DE* ,hw5ܝC'g/ GF+dQ bU o*j@l J;+TϪĆ3KB58~2N(}u0~!&}8yӷ{7U̵D#svcxuF;±? {kSN]AUUE vFnVжE=|nY 4%B {(̑%Y5&>]J|A"r>*s ~K#N*x9gIUc'ar%aݏp!=5Cߑy˼t +%age ax2%py1DtCm Cp }ť-kh 2Q5B.9lF1 60CyNV0Q!`s>;F |y~V[N[5H}5< [6AWwCƘP֦U< a&Ɔo:7ю7ao#O+}Zw(nP9. 5{gkU_gcv' "Dd<5__P\1Nh]oS߇ kȲ$csC$8"5t6R[<:Opύ6ωH"4=#eO23'g1hCG={vPBi`Iڛߜ{@51zG"c|[r7~qEBBcս A71+xH! eNՇK1&c}."Ѣ#Q93EtA2|LSl^@^!E$C;F&Cmfyb/!Џ;;c,"xΛ  WPP0)Å@(k&534pyO;)g8DјI#EWk3ӑ<1x*bPaY -F8R &`%ԁ "RPmzDU^5CͰiaz3NQcl8fN9 ;񼨑ߜü2pA?9ION\-2mero::l-6h)QDTӁ*BM32,3(SJNeS`ʐSbNĢXވ!IDATyeNdd[ECWaW^0ޣ$So̐(e;Ɗa]cY LZO]% Dxx|3a4I@9/gK{|4s#~$3 4쮭͊\:Few2 N(#2%PB2H$+ɶAY@^ ғ&JXaAhWbK2-]@GgGmoxz(L-JJ @.hϢ+54c|`+te[0K 9)#.qBH%D#F"eN%F΍{2N~a?syo{D- \nђ`lZ;,9rQS İR ހ77MM>?Ҳ{L—)7;EfB[ufƘ䄐ҟHtX(sl1SB8T'cN|afYR%!ܨ&+ :r4Q^e=TK%l$mDVIN2R! W>`>j8u\>UIul#Sf({6):ϼ I -nyVg/)-Ȏ{G"~Atave,WޯXڒe=d0*D<䒮*T!ւ$Y4+FHX<1Te:tc8̊sĭ gB_G[/`R9cI D}lw]R͜fV"ng^N֡B!tQ)B,v 2)zne2ʷ7ŞcTY/\2-]WrW <)Q))MAJl$3F }]X]T iģ7,g=N ]G-FM*؊KʮFA2_{!s_݋FxoxluL|u?:SBx֡e,n`yT7f!0DfUd"yabKGD pHYs  tIME& ڤ IDATx˯dו[qϼ7LI$RՐQ dn=(<B?QC=*ᙁvЦK-3)d2y7^IJ*%YjFPt|!OomǷc>+܁ۤXkbko>m 7k(?DE~w+UG_zC1,2Sy-G\}'Cyv[׎=5wowx}|~;?}SEۖۏ KvϱHܝ$x=;*o]}o /+הq4Q*(vʩSu@%~d8o:Ѝr:#Ƿ?Қ, 1QXΰ SV^)v  gy/|ܚm;e?܊쾯8D<] ) 27)yuhtw#iP`n&[LThÒ2mFÿ~[[AX`LkN>QZrYTFaslNl?ፅlc?Lw} ^8VC؏|r OoߴI#_v^>ɎP_HIeY'N5Iy?[X⨯eQG 3g{oE{;įr.b?-dž^pa}U8o z$ 25 E. C-I*4!z@E:Uȍ"q97߆Y3-Gc俱0_:Nw"xmYɖÒÕCw_\roc ix _g 3Y;>UMIHs8 "w%G}oݳ%~W8X[BK(kXCj@n!'+Ko)G"_hÜx ,MF8k`` ۃ%$ab+,"b*l_S&} p5JT@[,lG:ػaׄ=\3̂paf *w LRY\ncJIvA-S*{e\me{|-?21R^lz3\C 1̖N"9l:W,ޖeUG#x| K 7 +,ݍCgW_C8{˥q&HM"?}S]wTM ͧ$ wI3?X~ew0XKC; ,ZN0awTj% J QLo#cv@d'.osmz#,Fa=q2'~b\_barD>CR >?p }ydU(ݩGH zKcǛlY1 ϥ _L0FjzvT]eK׷Gubyjn'O\-&'{{[&~ۿZ[f0`D<6,Z'Eucjh [vn3HM CX))F`v1Z)R6p8g\%2 C@ B OpUT_çńZGUxN"R?k/zcN[5r]lxg8&~Es~;$Bc<);R&SKI;fD߁^Qn$>\gx qTN/$NgZb+kOQ<,d֞rQU<:lMJ- BejDK[cu 2jj CLTtY0'n珄& W\E881L"Q.ה{C:zư%zO(JhX&HU{ț79P!aNH "@/x̠Cb, ߙ+~a}x!abcS[-CpnX*4]"1ćzIm{L,`aM%V-5;ڡE*˲(p +TwD0R"v(9#>F>s\)nibR+1^ [ڂsxQKApj;+`\ {a' ~l-PL-kxL ~5v0`swmP5],I1>dK Y_/b,;2rV$&NIbۅVS zW2-P!aĬ{pgLKnB':{`'XENٖ @ I|`)PThSP/Q g-P,Q))N$zhy4+[£(9Lx`+9٣NsX [šd"0r=Z@jtӭ{$t̻O{q;6c?8'?TH(j,uⷈ '6QZO)XQݣoP*'D?ԉ4 ?=fF+~>8nxf7ݧ6Q!%]Q*q$qHΠȺ(z0 "!R֮EM[\F9i`uJaV8}ӵru7QfgB)Iځd0 H$l|M:!>7{:P .rBa}$8nFo:q:p AٚP>2)AW )pc vF_%oQ}K l| 2676j.vx5T# 7@7An2688л6!n`A$0xEZ.A'^D&BO%\61q g[jEjp<(Ջ] P8)9~Ee  &Tz4~`*naw:#n2~&a/Z%n@!)tB->&F!??+]ҤE0v2N&m}IH2R0cQ[(ϓHeMw((u0k4͒غ7R)l1J/$#";Q5~sɼ^ l*[$CQ?W"*o`廘T#|H$@LE |.lpH{t>n,ZN~xgoRVx^\K0hh#bzv90`-=* Ve[OYc%ωNfz0xQRE"PMJo`!H0QHf6ʂ&ǚC<{T1"ǷkuqGP0Qqt>QHp$"s>TfpiH%g%.RƘkl- eB8rFc ND>$.&VZ\V ~񿒄֦T^x>Y֕֊Ԟc0Sd$^Ao܆ҧ8{D$w }OVIۈLIshװ]Mרu}-_t*4`eC'h TXH^mM5@nju*9$6D!E*?Bܧ^QrlXbXUK4b`ˁD8P!VtsaD朤 1G8klRq4t5\=o"! js9a0!wEj 3g!%>gF+)b=&`\bÔY;%W,6Ei%cf,?8cc:2e38j=HuC]LExelEjC"9ݤMp:P7{|ϐ(D M=5ܘlU,#\}3t.y CUZ" D9༆}1Tig`JJZ9Dž,. =!436h(Yvk@A௿Pou6?6_j mm=0I1F'5Ƽǧ @6NjJ%_0s ^.Sث jE6WI ˮaH=(G"O%ʀ#pe#E~U 7(R fD-Pb(E oV(DƚǸ>|X>8ן;7fn?nr3[lj̇cB7/@֟b>:5.5\:#5W8hh/aKkHg.!5 yL'fLW&olGLE堶v1X(5Ǖ#IydŚ `'X* zRoq;T MpB#Qin?)P x^܁O/&|| 9b[tSV3,{'vG0&GU_ T OOp!NHZ:$P]3c3m(E8`So8Ǜ gd S1^` {AЅl*ef- HTXܜAG j[%l0utg@.8Yb\bjBGEKe0 $7 `=Nؒ~dnpw})EOlKqohh,Ͽt:K`nao|G1\ ;C=qjdѦ+Z B->F#-$&$xpE`p>DQQ407[RKF3+8qȎI@`,Q O+l vfKIN\vYDh,;*"у)jcP;Hoq cw:}xJ+zaCĮHD,<\S8Y*= 3bӸ"|`{YGGWTWz 8W)hB EGop95J&/[}ybXYPTs&FBE%}=mrz DDR1 X,lyRg-3-zL"|ʀ1Phn yÍv[$A2mt] =N#9С&R9`0:!rgWajW9"2@~eWg R/1^\d]T;05E%[| 5h < p+)qM{;'0 !DSWD lܟ^~#B 2aL!>aH+4('a Yt`&b:C!w2\W=lMF:B9zEƨ].O)ejJh+`=5vhJ`aC z\q`}#}8s3H٢ Dy>ôSye}g%Ku:${ Gcsw+S=a(( y C)A8y!9Kj ţfє Ř%jaа5  NK%ns&9# QbfNȘK FaHʮ] νO`PƧ_[> HPB%BSxp֑;Ϯ q~;S;X+%^{62I`,u j,&t \\#Ds%WHR %$Ut #p+T)囼 ߞAUeH`3dtBg$# LvN3M,",]#ͨ#T 2Nq_K'6 vjxei3[)BaoW , .s1CSQ%DOIiNZB&Np>L9݀OAv8Py,;|>G,E O1 1 X%>i e-`0XPwn4A 6=!pI{'ىqXr=70L`dM9[lpw1'CZ8@81Aʳeοfa87\%uZ9ɔHgĴ G堏$=1]Л}IHk ƕ-W0A㰪xn7{XÙ$. IDATXweMބM01տ`;|, |Q%e lL-5c&lIjU\J$ƒ?xcp"pu/m38'3U[0F`Cn c̏n [Lݏ=-p7/|Z`. 9 g$vDdV8}oPs-g =9M11o@6nxB(/3 >F:۱ez5\3=drQA(| !6!q:ͨ9#Ǽy5J>7>,<j^`VfeYlR8PK,hr9;p1?ř&X⌈P&!+th-3Be(yhd<_8옢(mvbA9͐*S.3A“?r?6kdGK67:_p/('hyii T{{Xyf ;?zװrtS lkzĦ <ੁ"E$sb|zxcr>7ɂz:/`n':!cu_!|;ʼnə`o#Lg.mv2!#Rz@%6E1vLX/%߮V0-caDX7|6IhD12V$DL1#1]z\Cs3K2:-\EL"P nѧCQC.Ux{2.}6nݟ(Y\dC6]N-WYٜ#4Y[XЌMvWra[n54cri[tM}.i5.5$08E%(:a13\Y ~Y7k21|P>n(^Y;ZpF#+`6tbiU D>48.sG^kH|3cC-Ԁiisf1"P@nc#DWi'`Ⱥ`r&PubF!HvV/MAv3JdIgt㬢VY z2M4Qj^_>ǜY@ьͣK=!Oc ;d-e!3ɟ( #<,)?zv p|,O[7p ]@a^Zifܝbcbi}l-`m(#.k~pˆU0L/"J VֆGSotGJSgԼŗd2 CN6br'uyuzfdıKr9!( ExFojʆC Egq$]S5UTvl?eg$ZHe-}/oxuﱗ/؅ֆ3(e\԰nae0JOt}Â=Fo ?,f ǔ-}X$Mj!mb=&Hi !wԊ"P%r y|SUPF(FQGF.>u"K*%eT(]84pPAAt~1c.?FtFŁ1D3*B1 qRoLۓyE_ ot%,-n*lՆ! g.q-۩m}` DH#-11Bhd.[~?w sз|K~Y0侀JVNwN1i "ƍTQssp 'kY$;H^Poo~ ~ jg'1e"d2#5 R2 eI)DbPlD!1Ǐ7o ݃Hk|fmy2XRs2$O)Id =I"β$fbjP\QR3/[iZWٔvJ/)>Ag4ypmBNCݐ~9Ɖ'MjT߮Wف{`1GGpcwI1Y8+#{J W묘8gR.+O!e9'Y%)NXu;L b&&``7lD9) E§N6#ì[Ke,dIIPk];.یԽM7j*qk0C$Dz6ELpc*6%,"xBZ_@(̊!}1.H7l^2 B@{tHpk2&tYٴYN] Lٞq4$LI! G n лh2:Lm,SК=D 8MJytwo8b-XqnU)Y_2~ +7f$R,eov2DhVJHCd::eH RD|7.H_P5b'`>: HXQږ<\,!L3Ҫ15;MbrWFE.Al {C=>T`vz2-,x$(x]c_/eoc[rVD yrsխI"iM4%7l~j/ >w?mt-XeJQdnMw1,?ȺMJMp*9#bZoBNzJ(]ݞy%+ϔϟP>k; 3 Ab19N,J߶.s-F"[OBxJz('|@.݅r8!F8ha=@vBG҆$5NkloX@ѯu&L;BGnwZ9o.nK C)VɬAI(@ܥ&sraʕK<<Μm, \n B &Kߴݟ'"Bd9Y]Cㅸp}81K }Q6G7nqLk`ˢ-&*>wA3RNxQ$[RvhHxm-N=" TD5 |hg^ 3X Z@]kMJIलX{!B-ક]Tyg|guݤ3^S&<6\E.e`Oy3ϸJ!v,'`9fW?BS'5Kigmɽw:MHc gGp*mb-E lT'mIBa[%b!eFʆ-0Cw2| 喦hIPd?]i*1Ptg8}6Odan{[s{nۈ]ڑ1d{STB5pLW|qaj($_פ.pwlW0%_=C^fhZZqAhM&8vtIH0Ȏp2i&~!|,Jȑ2mWYPWI5ӏ(r xqFS\@m#MTT.A* qfh3/׀8, ,vsz2NTSc 3t} X;ŪiFB o!Q1YuQ6G(), 5ZwʲQwqGh(8wF!: jPQ-?$GS;ee-e ddԌc78iK$^[mO GRq9\&-ᆜPd(T/iB+PR"Ԫ rHK) ^ZQm!:xå) K=a;MC<rR,fΈ"_@Up)X`+f8 v7m[ z]/Wa UބN쀫p9DSKMWѶ㊤œZmCy;Aŕ=ȡ-Z`3 >ùO(l1ER)h~JO:Җ=ژ|)Ī)-I_2*BN w; 2"\f{9L. *B>^]y޿oW>Bz bQWfaՇ\YE@UI| 1 wp$%xS8%1}k*#^?0"ƹʎY YIa&;x@9B'8yv.#H&Oa"k@+1J*|[K:فz@ 0U/U$hj]a㘭˸H%!j!ZjWj E2R9^8#nWx9E/`Z^D+h+ߐ]K)KiPNVަm~, e&|7C·cdFz S,@[ 3e[Tr63_8p稻hDԒ 6$8!l{[`6AS7N^dߐsì1bj o:yM rJe66o,+CC-/z G?q q$ T.h 7CaL?y䨄yYQ::1rᅥo1RcfNaXO68~ .) !Li#6=E w/ %/髪ݠo9{8" 8|*8(ΑtG#7θ I]$c Gboq}]|ԏ5!dV\e E+hY?#Ke'tぱĶ0P>~_W7%+×%)4)sWUp"hP{"A|z--mpBG=YГtB U@φ\9x&A SdvJ"D+;\`j܁&5N8vg mj3ɻI,TbGɖ´XjC=Ə!}¼}F=Kb~'ΝǗʆyNy&LWŸ)}=4^tӗN lc <@q#3y 4 p=~ia@V+ I<FhR荄3۰.H uWxqQPQ09RF\b; &u5^ Rcr1u %c9#'߯GmbN [La5 &aV5 i!mUfƖTF8#li?7*D~89b9Yq??}=4F#.>fLB!P〦-^%8;X=@}h]RiiSs/(ejiCeANgDdEsQŧB< M$ף5Gr1D 53!1=4X: u͂EXǎ = UEE x${$(9]s6<ykdwE ZPdpsM2oq}%>@rTi`{3BzBпa7|Ax sfo|vmӡycJs 4f-x{nh!'xwBQ8臈<ǻ[yT c)n D+lsm_ЄBaҖrqM<%hFwme ~ bh6Uajͮ"'xi用HYr͙]7X.ߣEA32'2LS"lg?A:+ BAF+z:9)'$W'8g*#.&cd_P!Ov+\O&J`tOt;r %E1dQ,k>.p1yoՙ9zh7]՗p CR"@3:7%KCHwL)T'sE˶J }T.A?|W)dZqp+q~"M42\UNSxlo45oF+4/hn7_;t_t wqm&=&Ȟ,O 3$^AI CiUAFĽDs>.:#έ n!"3beJ)V.wˮZ o2Q m+vfh6gh 8+0 &7@̽%^J܎& /)i9n-]L~%IORKЧ>/&R4$sp4̗o̿{TO:8;pP8F3,3liG3>?@:E/('20hͰ$2edL6ut IQ )Dw-A G'x1uv ];hǂŢa;> ykisI2uts %_hYѵ; ]P7!L16OJ0ZOƸ TGJ85##s7d|J'3ećH _ 2;$_(G6'1VB ”3Tp䙵CQ~֟rI'rId)\d8y8?#%L32,84o'-[#z!m޲{ʨ{W"@KJȜu׵vNw/ُ Hq84Dž=-W poL{>U}6a_yſm.ܫϔ҆l(yG׬qq%BNg4 |Ed}Y&>2_3!~|w?VOOn`2WA^|AcbWaRa 9WR*\Br=kPȺka*C"hĨ~ IDATr7)H,kZs4s2Kqȓܒ6dt}%UU7vZF򊈐YR} 9 szgY9,xfX9xU{MSe y8mk;XyI)(@.bؑbC@#qM{- ]3g2% $|33@>.l׎_6ːk"t84;z78}O!x*2"BC2$&e*xŧ=H$hJGC湒4/R1m){9inwb 0skDN /β}'-"'H| ƀmn2IJ=3v@L+М4-Av9cʸam~O&M9jv^(o\ܺAc AYn 0'e ;A8ڦtR]ΈCS ѷ3:2p8ϸ;7Ԯg -Rx9C pd-(FPj~}e;)nW>ڽUBS&RQuNQ 3DҸH&2ɗ  tj"E{`Ѧ$;NwEaOڨYh$i)sҶ4VM[jMIm3dtbީ@84>7V~R<{7p`Rxok[W+s*otk\B(]4F{vb_{a(Mq bQx|n'<(:.<@S3V߱O}KØmɅJX҇$ד?pƁFl -9lmYꋳja-A2 mhG"Ǖޯx߽mkm]5[(m@gx?݀0k͝yQ*:U+Wp1ՁU=Vb'jgxJ2(RnA=$hbH'Ve,ub[mqXn]`w԰J `<.^U 3J|99:1v`!#@N9HC3D2󟰟NfL|jpA."͕(гKo QǀSV5a[ixՎeG_3˂}Y:A[4:\-䷍O{;C fw4Z91hPɺ}]Ib\HuE:,chxr^ny_x 'G)?zuS@/{=:34yV:?#Ҵ&,)S9={KF CBx@=9G6ϼZ죅mxka}."ʁ"d <=Y!8#koWopš65t/iL77`9LjQSBS^Yx_`X>M Hy4/P9 a@ġ2/< Kfo[O_ ~nýp)GOc mA)6m]bEVr[gBȢ4D[v$&vM\uߏz 9SS81,6!v$5+|kC j1Kjwc+7eI WXee+f>C. 8v4'6:^!uV[5p2drAd2pv z˃MXOߪs4UIgXGwua|0,așf+>hE֙ṶTES%C}9v$ 6"'Z?qw[M#"?EMI8q \"ߒO&fLasLiA K7V-$p'Lr C0f)2j ajQʣPPĭ*[h㆚W9n%g#9w*xY}Ec,kogC[7GSj/"jhg]G̑pNHt谧97#GC'o&^0#Fۙo@|+}?1Wgmnϔ8hCH H3!ߢfBݞK@bxwqoQ(uOV-o*va֕st.QJJr5_z1 ]hkw7\Vv7Vo.԰F}el|oME$WWuM vM;$:DM)q8XzNpvKGM͜B^|_|[iPn+'<2DB+D 5oԨbZJP$|0Ĺ puc :~ʾKxi9zgFv|ĭFf^_ka ws,3B)5H>f^m]^{ en薡f>'D >+- ~nDNG[ZC8h@#NT7}a4YxTkvjq`אT {x2.ͲVMaS' Րz[_26<*8sr)ÔĖvs/8|&q& ?ᛓp۰Ex |˼‰&0'qY5ΝX8[)GSf9(N<;&FT;m%l[3Gx\.ѴgT*ԑT"́ ֛ϥO٦.+asqzF0v87sBqSP>YlΠCmJ5=7SC)߷LzE"VG3o,`Z93$hՓCMWmUomE"9=zSL!qMl]ႂ[׻,_Yxn@ iܒ~N[#)EMyyu'[mpgPsּp>"%{JtQ7*K' IڀOrE7sF.qn|N Q%z@r,8W%+.Tf`@ΚMђ9Q`й:WؼhgTU||r<}gL 9ӑ#HO'w&~zxmc$w00<|mٿȜzEN90=#>ùh͗M{l9gN'ڃuߤ0F>3pNqZE vDHrL, ލQ"͛ `j*Z[E[|JF~'82/Ѐ3b=ի`ZUMjSCu~X}j߷sA3{LLW!NMHL:p(s*A/gFG+ x@ָid, a|KvtFȟt,)H)"Ⱥw'f69Fg:J̖Sˀq#D)EAZǞ~Ӓb/zK6ct7ʶ]ٲjm{wlV3*Oy`c`|:f =lrgnãW,3t^ϮwQk?ӋVV!]kJsiO;D½b{]oevU@I=+T *f2" ̏»r̳oV#/ȒѰEՆgs4Y=MGd)kO(ҽEo~9аGLl2GRR椲$ 4컭Gn+Nqc0To gSEhRDD ٫J^v KXl~XI|Iܛ9ށ}\[M53P}@p7iØL#1MfCdq  ^Ȋ5'$228嫳g@sK-w(> [};́A;\pmKb@ԷM=>3m / Md#DZgS':O7-B|U 틀kͰ (Pe}mʹj +G6E&T#T6|mÊ&+ډ)KJreI/pE̛kdc:eVkO}qU]"s´F?ʜ%yB):}݇ʴQNO2 ѽ l#tev;׾c_ZvωTE'#M}DdOZ|Ʈ툹i2(L"84P\f !}U6d nNք+fYB 3qp }k˹ vp{eF-כjXSa;0t5rx nO 0wf^I>O,D "*8:?Vû'5'jGrx )}.ۂus:2ޟ fJ$Tg :8 Lh#gtBef%#8'4^%S])|s2ED-ykf!N`R.lkok'M=׮_Ys >R]/d!B E@j ~ܾ=0+e2{(h9R5ܳvğnj|S[_rJ_^, "RDž?Cm!-%߁694[\zg&MܴY(=E"nel=pHtSb١ab?-<Ϸ~G+(tr8qzfN8J/ܑg3Xt: 5ecuƒ A_o6p\S?,X]p0X2ucMj`P\/t3ULBUkKRuЌ7#!1"?.G?OTAX&x(O57QH:.;)!=?$ KŔS,p(_ùoӗqnF[O#o@<'뮉vtچ!EBHI)%# HQJIdySw|b]jdIZ*+LbɤC}Zok[{v:KG\pį&no|YMtFA7"+4~[uW*xcknhd5 PZIw\=X a ]}>& 9BOGO3fK{@6iixcדC[ ƬɓoPGt9e p?޼rp=A"Z"FPDq#ҡ!#0#DYx'LʉM*W8CER1b06V2^WfẈyϗh wPҫMm&WY0Zr$oHu)7n[f}_ٷ*CՈ:@xYP%64􇀛95d/ gv\u'2 ļG.` uQ[#SB0y4ZlY=RSٚpTP>ES|k`*5ײQbLXʫZ^];cke-ub4hRffruDf%4yαt||~#}P$1~9\1.+#vl{urA|H}yG!#@ڮ^LGr3|Sx& O]Z2 ,eBGli"Қhf>⇗_x r6T&&ꌔM4-_WpWlr+X lZQJM8oh:ħ:Ek3g[bUE7 \V(3\L9 2 P7Qϔ22#3lִA3$h'-#򄺉TŖGCؙ$K .M [_Nc hђh)#SЈc&4(q`CDGfHDE-ljuB7W'$6oꨗ ;JcDsD6tZŌ6g;6.|X+okq_UZk_m䐢(S[4l W|| S oySX@` c8[CJD9̙s{kwUz9CKNd~91{Y]]]T` 1x2GdkX2rd6)}? ef_xȹ*~ i-TotOЩEU uKX3_-KO E]PWc\޽(c´#SQ!W54Ua*<ή|$\ʽ~k Ngtp.E(p1]5H9"WKbfsaWZJ_*3k3̶u -c[g E.vGo(QO~plm^"{BU [bzEIDATV@M ѧ;/C<$ %,b^]Gf&hb}*oXxM$vեaȐa\5Uݶi_>ҬfHa G%U=M//Ӽ/N2W%J9^cR^Zt3lwniOE7>2.~#cI"ĵvCC0Fj"+'P@}pMR I,Jhl#[w&yi?"KK&9xV4чXDl>R * 37BI;PLPv] ז3h4ςP6;ڀRίS٥Iԥ5BlF-Cɛ0d&Be GI, ,ÿ ,p>px&<OX;kTgxvYAsOSڂwx,nsG<#jKf _p2d7lҜAGA,ؿr.i} IwhYDA It.l{xZ_Z.-ro-/1~KS VökCn-#͕; _Ͷ_UjNfÌ&6T):dF:,܉Z~)sR6?7lw,ϱ/~NWp J!$\2OE-Žq*s+c>,~o4𼃳L|TDyX>^tWv1AP6~xx&,"6ߋ>:׻ۼFԜ76 2_?nXlFK71/e<2 TE_mycΜ珞`W r7'ʗ Fs<0}N}#$(ыŮd:\4d܍,X ޠ8f#Xbn.d^B\FLT#%LoxZØzD!c\>+3l-+&RuuSs fv>gW/~& t }VlR8i81X= 3Rݗ: I2;NV}(\˓mAj[T?&?eӄ mlNk.{Nx_by-nm`qKY<[8J,dZF"$%#Zv^3"I^ֺy9f5{ZuΒvQp"WfNMb>a{|m4f~0Wk6}</x|OC 3] Cmo|B 3Hs/-.cS2C}| P9g [$ ^BQ $ω#R⣸0 hh~Xs1Ao0$]ǹr>05*O.!qZEhl}c϶K'h|C7 wo H Mq k+x4M2՞ӕϑe` T@SLstWg~i꩷k`|n[({m";7 .h`F1uh J@"7c~kwq,cv0]-"bl\y޿TXO+/hl2!_N'8_TOPy[TN j#g1}l.3UyC3Ei ۗ$΋g ;" p<{ԯP6>Q`f,w# ܞ"$y8'9q#2= S?;/3F'_zEFeMSk!iRb}MEŔ6T#diT*e^邺1̅㘅rDb%=&&>} r g38Nҡz $u8'c^`wB/dY/5wx+ѣ>OFxӋs,5S疃0ٳ 6i=v鈐ר8k-} :N1?ҧdyspLN-k"UyyenVƿyYZ#1ʿ|Oɹ2u :pt P vƵ.) T{dW-qAn3< x¥x"ΈʚdD&NgB4lB>n%#'v͐h5 7ť|9"|ªS4<))h.R0D4H)"a*ܻqB)D:B=y* l\cziWX"y`BsH( ANصEL-25lkH,d户K¨-t66D/|H3& # YI7H ؆O#*s*#tnT΋G? "FhS,䥲?ԌaIk@E ,@ s%0gDܩpeLβb5R09U N):ZjW꘰lg 4CҚfCbز:RA"3' AC!dab+RHarP;= b}FֈF焦sx1av\\ڥ8Xṟ )^8cZz=C>zjFˎiלxE*Hv*kbZ!D4t Mۈoa) Pٱ8UزG=Bdl^/,$*@"H*@ CLFQ qǥɕJT!! US #OF{_9GH)Q@/:Ge1Z;lZm}\+pN$ǁiu1/PLs.1LAkjwpbYFpZ/xQ Ȏ3ZIZ?D'L;vxa>{x1+P+csODs|ʤ,% Oy$dgLcF[|7f_!ۧx(P̪4P%*+ ɟa&OQ{hKǜj:A˰Oj<%[7Xz El1*qsk'7wH~mJT!r5f%SS2 ςAG0{!Ss0nمc|;g\ 'Ê>LAmKUU>"v$6_\$N41Ȁ1<$ٚdN%O ӈL*4SDlB*EB׹5Kh%DFEk$4S0 `%.i.MDfIE[{ y =.hİDFiRɎ,ǸC ^2f`hǦxF)-Ur~4MlV CoQh:K*aw9g9zI')~kU >#x1TA.Xȍ\0ѤXLUIs*ngV%_oR!S\vlJToA֓@< az A 48=}UyoB>L Tr 93i[=UZ0/09GѾx$ꏁ/1 s}vUmg@*`v8=Hgv٠u$웓Uj&ANSGM}7x%Vl1Gt|F̑\O;&XeQ̘‚"fӈxC^bBeJBOg$fxS)y%\v;`fVtC6#N!:=~D&S9p3i%ɬc[wa9 }U>H=*S*cak͌S&l3Ց >t1 V*^#4d!![mKϩCe'[c2hĘ9?v6Mf:^Os-$Rod7޽ѻ6Vh1=,xճe᷌?&Ї{b }>9cR"=;8"@gT*f6I0EVBv/)%WK) i ڽJlDhGK@k OgPЦ'10$!"BD8/F +?cz<%.ORCwFMffTGb5B(Kza 3Ķ-dng b[x]ZA^6˂zsů[ 2`AI8A9|ƁHa451[o@zX:Ɣh)S^zy7iTS326ѨCɹꮘ>6n=0>8'W2^_-q3}f\_e~rh0_ׁ ?}ʳ*$/3ȳA?VROt<ThKG7C8D|KH5hE@07_D'K9}H cFb@-l)ۖزHDK4F K~ 0b sdgsuc"Uw7(UJK}a'Ͷ }(?؞88ne4K{/ػ>@v~nB]hWQ'/n =h0|RNYx=D"iKx(ճ34-_F)M#͆kFIXc֣2Zbu#QGjٶrb8ev;h6DS. YI3ƌ@3&VʹtNK³_zi'yi=q.xt>Uh~}ߺ$`UK3#x^'];y| 7ƚ[ƴa[PMk*]1MFu`5. caq \!œH-#9#-U魣'?膁 ]ycJ|y:Y([\^eB IVŢD ؖxM¹???IcZyg^:}=ٿbGL^#/~0\Eݔ'&R'*$HnT/д"%C^Qr /Q/L@-⢘茈D KH,bAwX1Җo{vė#''ˉL2oV6Q C,,rqvY&N .7v%gH%c'FO?9ÿߓFn/O3!hWߚy 9Wn)l@xUͺqh!ؒN,.k&/*HJX6/ct3Ȉ =h@YW8&4r}_>q~?ӥ"k|Rq,lF vWȐD& WLvz<'>O~{Of-gxּ/ 5_+6,[»)PZe׀ɫKu"HRlI 8 \ TTq"H6!֑|q733|e}t޹w]IX5F3( ,X34x#>$*c%,/wu2ǮRch3?|/XcnIENDB`robocode/robocode/resources/images/explosion/explosion1-11.png0000644000175000017500000005421610205417702023773 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME$0ў7 IDATxϯmq>?}_`4ej8@@:88z= "@M'"4|kUUt,I6e.;lϮZUַփ9~sCp~{ߘ9ჟy_28?x?k{~|~睄 g%DK=V^.;Ov8a~!n"sO_5g?[+[[ʋ]X]?~wv>7F7;i~9C$(/|m>xn؅ʋGiWJS쨬TK<9$o~] W {?|Np4<;@wC÷ýbU^[g!6#!;7?ޝrl V盯gNfx>0v[㽗?)y{˒ܗ}?n@N o]:7_>oύJIn2J>3r7nܥpfC8|8w^; {ݹ|󽸭; |,0Eyu]8ZPmfyJcI~kuS[ =?Fx价𝟩^3Vu:Z{gʸ ).qa|J rLZZPSaX =pmyNoz]$ |ܸi)mKtVN{ޗdXW5pi<~<4x'oR+nJ^{ yW32טZʻ5P/'4^L7 (<ˉj)'z+cυp JNF[> aa;THwWAI~y{nMp,ƾ/dADηz,y>\]B:?Q7a$wρ_#ȯƻG!3c}]8LI(oKx >%Y_GÎJt}+X+D6F MalIHh\׍76>|/+ƝV^ZAT9߇g@cƏ d㧗5-]|ׄq\B{)<P'%' &))q\_UTxq4lW|3vQ5xk^ ^ɸ?W꧅'+=+Z}"s8P ad *Aj dv\( \yXeϿ8-TSD;2q(B*-͝#.S>I^;QyqI'^(ڕpY-;߯6/UIkg{_ȗl|8ʱV+LR({%$'MڞVq3MS)gfR'2DTH}-y S{$OszB?LB#0Cj$eVMZ#pwNGE)m/ldj@8֒łsOq;{q4x:wҿ,'/}oT5orhgvCDpF86aE<(;h85L;}O\bfB )^DLĚ%TtG^a1Ceä'x!*M&DfdX Bޡ¤ DtēNMs\Ze>xA9V'fbn4"8@"ee 1eZ'$Os g _pK)~fJُ􎖯q##j"o RL\;;U=vfQ:Di(I )M2'X]nC=)օ>O]l1q#)$HIs*FPTi>G({a׉VChi@5: +M.p`d~;?q~?%@AH#ߢp>Į3mϘD=Q(v`#p?gPfąĦhv(WT" H(J"!`Jd\16$y,SSl6ЉFgK*E"FPV𽒓Q6bD贱j J:d *ލ$r*#cGٵěɫ;8;S3Ol-̴~"9Y zFDĉwtd=Й(:B,lPEIٽ:b&㣝AUM 2**eu sQ*tELȞOA]P\uf!VZAu,> U y@Ed OUzI jzB$vg5;P;o.' s㿇)~\{(U2#'J=g=Cr@2$y{IF#>5d_PسS@:B"gT,!#46P'&}Ck8~ l%6Q.JhA{L%]a3"" ȎfkR0ā( )]'zԉݨZbcG#'/6o+TXgrO7g`;_gx ;&=A1&\:Vf bf(5Bj"ؠˊR!D;LuNL)tYGNxZ4x^ +)993crG; Q= L` D[*$L!cٙY1} 2G:A;C -N0J$h,tQT76o,["fx0LF%$PEGI\GHd.R0UL5k=5/?^>7G!^N[CzKr@DpD펭9LFZBK)H =1$l#" W<*9B(JiTD$6J PP Jzʆ wT8g8HA$H7VǃB@!gAJh7QAJʎy!cN]: G棙8>)̻EY{Rx|Y31l+3Baz&-19@$] 3[dPTx#L ew/ Vg{&n$H2g@ Ÿ%<@Y2|;_[[a9Vz9# .:MhG8@>uT[Hd F1om%f穂rf#up<:x c5'H@EG&P4Aa`6 L1j," \1FV 82 .ߜbNud".H% 6ŕY&#RPZK%?6R"n)v;RD; Nftzƍ1Q !{b >#"DM" 0NhM5۰ ߸=a#]E+/&'9JƑ{JqF@]QF*d0M0Qڈ Z&!FLN f: :#23|*G1nkA3 SG<ٵ4$BMM(]+gTAd[iTqyQ݆>A1]vphqB) *1#`ŕK7o-rWʗ>io+,pdReM=Y3uYHъjEn b! 7pNؾ(]A< $QFxLj[2;wjA') Ρt$\EdD@#.H Y;9NJZ>|9StDw$;ZF@xĔ0%o@)O~L^? */Dd~BFyP N{~3T5EmBb7hI*L@jrn "8}7_aJ銠xB$ gm^$jiPv\Nt7:_(6ItJ13N! <)"IvQ b;)o/¿/v}oT~0+mza3 er(UnzCopo70$7sb,"#@#$؎J+Žf 8'7 (XocDzcNĎ `8$$ANٜ2Յj++Xȶ~Neq*{2ldf{e(h-(Qtpn,T~8ׄ$A~1/V+7J 9)X1&JtfZL]FeФ^%XjEg!L Fp%"d,nRh;R-;9`}14͑4,L&݅jNwv8vc$mFɌ0͗Ja#R5*Mv"rtzo1xZ#ɢFǣrzMyڅc EuS^p.Fω-gP( yJl- Tpq1tibuз#DC9c@1apȅb.%wDF>"BCܙ5 l,)`3ecP>|aB +5 eJwL:2~Ǚ Ѕ tbp,v- 60HW\WzwWd.큉Wh>P+\/W,7,:Аl7$.IzIݘo)oPW shs5:=MqY\םطea@ )ʼlW,Ɏ  atސݑC+p?ͨGei>ۛBo;1hnp BW܆E-oň2q=_92VFϡ[TȡeFȞ rŧewtӸ0XKB͉9$vt=gЭP=هSʅ<;qh1,!TM"Ctty.%=ɲ;S]Hx2ǖ> @]`k].\JB~I p? }4=P)݈^@dTQgD+FzhutkP6 +Er|%jڎˎ5A ο<> $^ymDž9ܘ:ce6"Iee>96X*BB!D?֠9,ε 4Sc9sVDž=`nsJixNWf:hx,x\h][)}e͎.j>f\$${Uv3=0#/OJK(pkzB#>VX81mdh9f'@j0B ' $FIȗٯx4&Cp>Z}h+-w\hbX$EI*A0DNMc!;O [p]rJ,J ~O(28XbA (Lhrem)<"wiS@q.TIzaMB +FȌO2D܌:\7X:m|eʧ<q!#mT,辒.츏Uo1r`66l z Zdt(,02*5mB1ME@k>~'ԓJ coJ\':X1Xo,lLPRR8 ~K7V$ư |iaRKP+=8hhmfËxIZG)lcj6k y(HX\\Q]Nn`^ s%ssɻ& 7#kLWLOu}XP N;CP !<ǜh2bY]n Ц$7>lWX9[%sm3&XG,oj(Kتr915?kr^_73n=pYVGCV5>FJȯ+$\.| Gn1ti촛҈T,nN\ȪdCuiAh*2i>q'N51:] F*66UxÄ^s":)§aX`'c7['@d"} ne&F9XݩkK㏿Ũ|%d [b ;{Y>F5ǐuh|U#N(`,^|DĂ+?!i",)@W.M G2ul }%yHlvȽڠwNMmG[Ti҅ԍs :CAB}f/3ٍpƒ,U'݌ؘsg2˧ -e%}a'Ბa"~!xJ)"ޘ}p.DXDoho\1h:&|C BhFt@uM8Ɓq& vN)>S)=LHi13Rʄr!g2N'2'Sc+_( ?3_)7UR|?^4a}Ǻe'eGYiPm nH;hdhHn#e4EK|rOA>qe۵FeٱN2{-Q\Q9HIDuHptuC]v +ݸԟ"e3Bu%{"Cn}BjAaM}ncAih8OF}BPӀୱۗ* S,^ЙˆrӼޑ\F;+‚ d$і څmD 'ȴs]4Dt4Y~ed;HcCeC1`u&tvL|t#&؛PLٙ'jl*MYc“Uf@T0H-$3iZQ%>>a44b(_3Gaau㙔 []ޓI!Ew'yR. SY4V{1w,L4ăhPsG el}09ƽ2e#ctق1HT9Ћ \VV!M vL+IKj[Y(eB>S=ґ.\R9^;%'CތU0wז'C$uD儗Y9'\N a!4m\ Ba p ? dw^ϵ_dл_'<+M9ʐؙx Œ!6J fѳ_I$4"s,~a˝䨬ԃ7 V9:+ Rp|QԘS11Yq h12kGH2 2+2($J-'&^69xڅ+cvڱdYdWвHILnc{#N۩l4WbnNSZjGsgnu׊匩sG;T !§~Z-qV 䁤]Q҅D֛L,(SĎNU|ލCX*{sFF#ˑB&)v$-1QJ. KnS0Trlw I [ Ҕh w]9IEZ\?CSXW2d2"+1cFOqD~{].N!R Z72;w+f3?Oxv4NM0lpNmd4KR7 )G֭W!LbbuT5[8w=ͭѽ ɨrS&Dǘ~6.16]י3Ɯs9^^Rl lD5 $HCҭ fL 0 Ni2c*"E~Zs1Fc+ɩ"Eɵ~8<笹s}^nX'B ™.d )mQC~rğ+C?~ ޹5 e flX9rKn8Z[(1;䔋t P&k #R}qtGHSdG+W\q\0{`FaT*SO}E:3Hp\RH s`4Ewsᨓ;V#{7Vhf@'Ds*BLD4Jdi7{ɵ%^k0‹s/y }oK\-1(NenW6U+kZoqPih>讈bTK)vu ~8>Q*'uJpYAj֘ ,7&"o#).Wq~ex~EPה83\E).Ԃ6CR+& ( Es#mE+hNGUI9Br,kT>-|]o<<xsQ_8mM/bN|T(="$Ss 4s!tHᕬTy m(奠Mz *0b+.+c#:: */hq8UN\Ru(>X̉&8 +b *Z)%If"DƋ#!dhGc2A4iSRݓŐ' {y+&N6% DEXQ3bNJ՜瘺e8&+!h4tIX lH󕝕&O. /q'56̒GeYv$V.QXxŨK>cEUaʰ|psumMͰ3S\BeQK$2Q\7HZzeLx sH'@`6g} .<21xNg+ϬvƎ'% 9^`BoUoKdmȸY8|zO'l)ڞqq>0hGzNhyzȱ.O~n~΄>z7x/?z2ynƥ7&UࠓH] "2Dex8°K+ڐC$h&6(gEb;Z*鍑tdQDxvV^PoJQ 6 MʹͼBXhƨ, 1D"5(S3"$I7Cv͑&%Tvft03xo=u^c|Ϝ~ܾ 7@o;/\hQ'J%^:GR7eepnPQzky:\igGbG8|>й&03y=SKBhX(ej$Ż#Qũ?a  鍽,h9RX™1ɜ a\Y[~&RfY6AS䚠iZ\v|=C}usga0ڎQp ǨVشQ-1 n̤@@GeceǕL,&K>x8㕿 {/ވC'WӋA*|m*즴h-V)f Uō9Aez@]4WzOɔҊc-LV,VBZSknxCX2͘5[*,c%bPc1ٵ@ |u8&iQ)oc! Lva#PKxU M R8¡;63_Hj"#u-?4o30~/D|g߂ ᄑC;^x1Vb"qC [Jr~,J" h`C!pnLzŸC0U/siQYiZjTcMm]]&1( ``F[V^uR|r@zf8$iֳ*CIU[*I4LJsG#E.W.Np$)",PbJ(h% /HmX5%Ee˙8MSV* ,xx(U+ғqL{ 闅e)FpƲL xDYh1і3D'U;Q&WOA.֩m`yzX8_!$4 C_8+ӧƽbО (7҆N8RJAo;Qr3!'$ 6L1}N8s?WkΫz/y| O^<ooFV2'J4e%*hT ȉ$oǠr*[DhHC@?@ʭcP4tL0{VjJdvA;ݲU}aq*(er 4*y_ZEojk V&]m0-{f<> NLƳ[3Ƈ3J,C=Fjp@@;B* 12+sB^6*}Jv߄FN$!";$lhTcRjgBDӽa݋Sh+l35{ZhEzJem_X4^IaU=t7~9|~`s["_xN/<9;Ӆ˚#PB)jSkd":V4@[BHBdH{ёIzbd'v;% 6`Hh)TJ^SNJ 7g0&[M|f+ҨrC :W*& (%USߺ*+M GqޖrkWqt: OOqd򣷍%[U,7ok7SބwVC5×S)#>FV-)-ÂGُ![Y$y{ҙ$1kNF`l_#ghnzB}qs6/X\b^8Z+ u\h,=g1+Ȧ",R3TZkxc!%rҌnt>:?~{"󻯔=GYF~M]24I20)Q@$^$SJMcEs& #*ȤjCSSK@3/cnTm^Ni|T2K3,;,Jձ3O)D+I$B`jGʘdް[_m?ܠ|Ka ?z:- `<7}5=[ Je_0zzwN&%BhnP9r4*29+֠ZEcPTRzd](X􅰅Ή*>҄0aٍ 3 SI)7삅S&L)̹ 2weu58wc˫v~yG*]FƦX QtdEI} կ(WJz'g @u \yN Qq/T9St#RK(QY4JR c[bVg4^r@YY(D~X Q'CKODĎ3r֏QozTPW^ yX1x7[j1{PS̰,yjhL8e";-&8dڝJs"̉0Jpf/МX:mpU"L9Uf,hcSk/'ߋֿ#kןK`=2_^(匸5ßk #e0,@0-ȸ xIW^Q3=S ͨPZ 6;I/ Uu2K{8-FgN`)y2%A2+]- a C+@9X]oh A%q@aB'7+-K|k \H@5=%)ye $^RsB?9KB^$.]7ie25UaRT,""Q:ʔW1Sr3*+{1ƊF˂WUZAP-̚3" .=eg08JB/!DFxP\6+Vx&)K}@3)fo;JQ.8^Ytpc.*;XBHCD!:e#//\e`xWA1Hz AVuf7M|nu6ׂs-FHb7LO bT]; GT7dsg)9>M<;s㮼Bt_w<ۜUuCM M)a :7jt~D,BQFlTY~ՠyy"'x״eTUPX 6}9&fF5,@ +&  MMcPFW,;Ui :pW3quhZ2EGh 0H SyÏX9Qp|6MzF35h*Lh8n'c_㎓L-7T~Vӎ%q 7G=Z}F"o ՔV ,MKu) ٹx\GbL%%`QT0hjRCKnڇ`WQ`xIDATO}us"bZAKaΉe (GeAl32ddFK8 A+X)zd'z9x`@e(T d|"θ8+R3)+Pemi 9h4ŧbS5 9V٬"L'3ɤ< o]WF%!ZZ&eTVn$p)F6lNa/dh6c N؀R)r`5G4[U1y`)wlqgzq7<LȜIeued ~luYY V4iH0saϕA~ZV$0yUgQm C3nfCݙ}Җܺ^8Gu参 Oq46fNC;EXBHfAUv,JfPlQQ:&fp}ozDta&I(. EϢUWqbJNLe1puXHv;BxNxE|M)rJ22)u1aFN_V |N,2؟2nbX 9leP p;D^""yۍ?hq_C=֞" )Ox@[3tZq_a)(D[A⥦Dڷfr Q4%VM6rAB%e/X5 cLƚݹg^ |77?G<> Upzp1  1cIagS2)g#";K`aGD#"x歯(Bđ@A^"⃽1R``az9̨3ErAyA"62alJQԻbM"L/̒zcvc&N:vŇEu1.xqw@!y!<^ ]Ӳx)SFg$|I0*p6EdBJFr;Q^k%:H@r!4YX-FT#h@3Vh ! Pfdͷ{fM@M#lХ'"Ƥ׌G48Ο >/:y~[yB=-c+``x]I1fհ0I֞Va]edH5d%SKx`zo &X*]#V!4N!nͿQdtdtUGE1Y(/8 ZJz^ 5D@-r'!eqTԽsǕY6V, z5J~K; ;{BW\za_3$ԩD iFʤC!HOpDVtnȴ7lJlb܄"%pECL q%)3F/\0iQk7s`Yq4<T:eJ>2?;_PYGkʣht^s~K1&k&xȠ1^Yh9)%T)XڭxJBhDd 'doAayt).;j=-cbMz"x_Rnyp[$,pI t \he.gYYIs;wT;ɻ/:}Oۗ|&Nu*\R i4T\GB]}D[1zL$tHtZvt\= )pD& -N#"w,tBhG`$2Qx [6\P^<>:~|xg_t?Z7g_v,51RkV"HMP O5>s*kMUM_3[&+TϜ]{uPL_C+!%a Q1'ȼ kam<ެgNDo. g]#M&!AX2E3L슴+#&tyʙkzf{!ͱq^4m`oM;Ýn?l_xyŸ e|Myx,lF!K%LHWwl#7^EE #df޼~*/~ihd$*t "<R^a59aِ!xX95*W{JYxN̝Ύ̝ϗO񹳛3g=+{_h*o]o.pj( 7Q%LBld( 4FרxQFsJeDy>Y,52ԤR"-Z 5o2+ab ;*SA_b;W z|$ƠEmΡj^u(ecq. ,:R.D=B+3[~jco~3W|#pMAPRUX-AR-r<)rAzՄsdm ydҸ6c89%5Q" A TaGE[#\hWiqTPe'0;W\(k c4]vB bKmXrqb`9Iyxov[twU={5]C]Gk/ *0,mQ@M[ FNaGaPg6IDU'R"cԩ6a2zaml| 62A̚WhT,塨:YbGJL!Qwc|wEmC ?PF$ c;03DsxD_muytTU>/ jڦIam^otXˎUcN[PJ ųi PV3.Vn-%[A :}*0=-'Ό+)u>,h/&]g?6.toXD `DdGQ3a)F7a:||pq?>~on S?mZy>*/`PV<*2S)ddl&%(μ:E)([HiY3`pq+,<,]Wz9b,G*Fm V UAD .)6Ҍzp>>8rM_~_N/;+EH~OGBkHМphq))w8l֊d#:i0ԉ\Cz0 2ۭXJfM~#aLWl\y/+׃w.AgugrB*<6XY 9v}Cڅ`\Թ}77|S,~ߡԮ9('^<G ^y:],P8+2Jzf)m(" OU)cAu90j:3Yı'AGf{n%;W#OOJׅ@˔Qf;:$Fx5bٱr2(c\Kg/oj)\=[Wы3E nti\Vxj!*A1+,igڂ+} W8dcxrCbe4>&^gN#˫+/N;{Oc(׺=@Iz4ynt&|LJIٜy8z~/ TcK8@v0͕Z`9 y+zsi0$,c2C) . <¡+YyָX@?"THHeGu'7]uƋulL6 s9ǠrKRlUTjQtE2Kln WuWY[kw7o _G~ @巔Y['B?W`qӫ~Ųq>'_'WJv}x K`ϝcsqC(]eABhdg c擥8mLlR: ]҇?LǠcL9_~/Lilrw$voN8_;,oc؞ Cq!Wx Qq+ |υ^;u|LjB6N|2ʇk%6ٸr;?Y BhiI!=ߔ1Y^zgσ߮+,%ӏ MM_>V~tҕ^SS9~ ;)xq28v4^u;S?+6 !ۄ*k2 zy11k1֛h/2r?;7ǯs /pxP'TV_邭}; țnxK3O\|` ] kOx_O(`(-eKxwW^u'o%5k f/o|/?_4!ca0|a)*+ :Ӝݚ`=Xߚq77ε}?w 2xv O cu~Q؁cV  >|q's7>˸;;7oOk}G4OZB0~=tx},a|Alm x=qJq3g5! FMqaCM wT3 .ϫ ` trak(\q_ЅP<觮63uSK 7tT0l|jt=̉L ǩ^MH=DB,a4kp|83nUc<)"V_=QtB0S$w\ Fư`:lƁZq"7I\Z+DzI8BfgyoSKV4%e#, prd$Z+B]jdvIzf |.Qf"A _DLd7SܾXi:[#I\ a<>z׊BZW#p.8-(0:! \x $%}K7tmv>zǾGt<;&q*K5_lHIENDB`robocode/robocode/resources/images/explosion/explosion2-27.png0000644000175000017500000001547610205417702024010 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%%X!IDATxo\ם?7PDr"Yq%Σi]]VF@ ,P? (iVv7ñؖH %Y"ErH}RVnpl0ə9|{= (zvsҥ_ϋ+nB>J"zUp-*p/8Tn9q\\qWE-wpyIgU|NPܽ8tu$LhXx˖/ۏ"Y 3Eo u 4SW5/=gXYq% ?AUp(q)Ji#*pRE i33n) l|~@s-ć^/HՎx)D%Kel!)$iRQ ">J ߀pnԣsd-sX.Fxy|72*UJ9:aY0̕,a2H-m;%i5Õ:ҹ:µL އN?򄮑#?!0T>2~!, A&d< &BNh"})HDS͠l(9,v RG#M%) %t KcIBx—P,BVj]Y :(2-4aJ#21 ,N1f_^OP>iL buJD:AsT/yGSmP D )[`=2p ̜$~tBbPV`@VE4Hp.i'fbi_#;w-T*6ObO2Lg dPe M@ك $T D_!vS0B8|5985b&p - |~DDkA6> 0C?N…/ZC gF2*)i5 e` Դ+4 #N<8C# UȌqV\ fa"p84Is<0H~TBkf}j (| F .5I{7a)W_: ddct=]xk>ަU TP jYJN t6~0 LAn\#`g wTj^E!/|uG笆!T}}UՕdQ (cv2C;mpp.G\\`=L< s/B@1p+G=w'iq-ñv_LɩMeJgHsq,,!m77a[n3Io s=̓tsOOSpgyȸ'%jjyy^F4cX(C<A|vySߟGxf? dG*~f \((ԨyI.^~ m0ԶѢ-ƥCĴ^ O#54)75dGh";!љDg8&<$^Ҿl!&f> $@>@̡!iCvˉ5 = 8wNCqhzrWcgVI2} 4@IP\rO~ <W!OpX$B!Jt=o!yĥL:. XӢN2HeSp1Ut-2Y!<>J7K7I ,6a"cRw>U`GHgYQm_>=nZ/1D|?rcB <+ d(H gxk7f{"XF!mecwĵ㎯^8gB{nrLKONr?FR,9?@k!F$!!*XE X%dXX-wq``zB+5i$ ۸8ũ8‰Yh殸 ဣbʓb<N|Gra ;hMB>L XjL]J=r %(z,K|"D dP)y\Ceejm ";TUJo(j\se 4 'wJF~_a'~]d>-y 6|BuAMNBCT~LFUF2 #{\k :g5+9=CH0UnyQ~ < <'1>lp-%aVAʐ$iz,nd~MVϮ 6r{^@EJ~A\g)HeyQhL~C;{0 GxfJ$|$}_B?B`p?WEmn$A A+$+|*RXp/s\v]V?gރa{v;%BH(4t.sE%JeO4p L@~?_p+Ĺwۤ@ r?;T|XHO MWp(C# TG7z3Kjy(IX, CJ#(Mى"i'>I/`WEX!u} -sy>0kɃa 0J |]%fdpǰhi4 VV$ID [̺Q\ƘQ⓭`.=&j#dM6}FtԄڙ[#4`i]$ QB̍?;y7\>yLCjA!-m ~aé뎋%t(@#X0!٣?E0&b!p{6?~x x'Ͼ-As%'JGp8A[wz1{40ցv2@_Qُ6}7$t{({!n^y8hwY!6.51:1lƩ/ۃKh:`elnZuM]h$hH4\^A;^7% 0d~x6J|L]O9pVG;H^{c:Ä|EIl AeÆW4PUʈ ?s٣|p.Ugn;ߚx@ \q܋5?%{N_%|q83SJ̭-0[oc/4N:JcFWsV\:8eW-v/K=c2z=W49ƃPa=Gno|Hxڂtz_,a:~؇ SS8 |ߠ ~ *CdeN, Yb"hÿmLd"(KBS<'uSaSԭ t x%JXYr'g'2wxBLd!m&iOB8_`{p\%ۚhoQQU0#_K0w^ύym3Gp(?"^͇M%bR^g2 aiim{ \Z*It0J~dPo3< !b4_y1).0Y>&\gB.zӇU k]e`kH.XXV' ''}. Nޔt~ Gk߃q`mX߃4Ǽ%?=Min}&+r<_Γؾ\U&wA.Fd'xP.mPT'wsE+x\~nnC14ȯo`/YG;X]j#;8έJʏqpP\R+s1Aۅq+$b`23Wr9W~#,傽{.lݛ.-^ rֆ$ FO6܊m\øq#{&57"xp'VV;0{1 4+2Fe[ȜSJ*divBϕa "맽wL}+̱Ib xLG52óqjԻF{ &PS+_> 7-hRe0f#.NHƌGHz0&ħD)<[k['x?3[Y |߁߅c|i@6VuT'sr͐Z`2-a~Ls+V8Db@s<B83lXC#%(=Ɗu{3XC:/_ W&.>%w9hbېjd$, uխb]uwP&Ȥ 0R W>aDG1v̦LJ6 HLaм`90M)c nO8FJ^ c'0O0.3(w~Ў I8?&t=( U qqu|eZóM=è/"c'YLYLg@ED9}U!c1KJL`Pj- R"ØJ 2U;oQ'ӄwKx++o]FG$G%%tXƥ5!ygH:aZ^`#0fšR,77@7>j\.r. 0x$+ "LR3T~X2< ?b4^=#ٔ2WIm لV2>̷ {aTf#Bң{d]TIwᖥhNIit+ 1}/-KpHM, eJ) RC]L9 iUt~z}fh|&n-Rncǐ =ZX*zLq-~OG/2]0 gںz*l"xa]Ѭx])[QZFzL!d/!H5&cFC!fP "( n&ۅF_Ax=oSIL:Jdu-hI0AdYgSe;8o2L/` ('x1N,)l1 Liu D>aD@C9AQ1w4Ţ7 qPD;-˫_NSLjE 3WP?8}%؂1ŢV} *P?Doqjgyٷ /- ږԪ`9X]\8c7=~p )[M=sie3K ]:JC?`)ٺ+|B<tCg}G:`^.[.h$W${`++AD$ĥd|X/Jqn`\ MGr\;~5?.Lǎޅ&EKQN~B|\rAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAi'.U.:IENDB`robocode/robocode/resources/images/explosion/explosion2-66.png0000644000175000017500000002523110205417702024001 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME&6Q IDATxo\I9qd"U,Jک]4~?jyO0@ G?a l``텍lt)T,Lވs7D(UK.w9q"\vծUjW]vծUjW]v&??m/opz:jA~4wo=ܱH!oG]n7<~|eOWBqY#a9l]5#[Dy QÓ> !,5#NyXL-}p2udxo˾nJcзL qoCG7ր?[Lбpu{5a_~a#ck|3Ku3.a fz!K?\S˿LǏOlZFx|]VZhXᄂMS:SN d@9*w-:nρ& gUA m¿ڳ!C#G/ ʱ$I(uhQx㑱V+`9RK#+eAbwN`ZgP/P1ǡpҫCl#7SKmxSTNzZ%cMXmbk?@WXQv<`:_y87t!F4O6_YvO7oo\go_ kF'Ekemb0-X5{ޅ'|& 4<ձQ)L O+պ;kƧwzVH/ka秖zϵ!ǁ؛X F@h)"cV#a#&G7Ix?M|x:?=M&4 TxcP*7z-rpk^i(o>~9XS&d%+ ^O'a{$‡}q7ZG¨pȪ7I*1CI);%}e}Ue3fw$7wvxx葵?1&gN zFΐ#L* +US8=>ȦhH* TH&N3+5|XTT"'录Kh-R{/%~۷%L[ob~5GApHg}V?󖸬H$:VC 8;  .p@tSUN^3j_di-k P 8GALdr:ÊDXKDl[lߋ#I؂g}8`O'X. OYd"V%UxG;o%XHsgHJ :\qxu9*F"ĈVSHH HՖP#fC >i2j\DL$}6N^쬿qP0b/7iQwUQzBM-\@,鴤,& R8$Q +Ѧ%&F< l4cNFw?#^Ͽמw@GǛ>D4“~/mX9K9{eߣ}"i&1@3@m^PO+ R"1x@9v7O&o(Ts' [9pL^ۢ @,qBKErW+8GZ'3C:7v$<>*^FT%58:1 (S;i>ZdɳUSݎ#,iM"s#R*xG*Oi/6UZ"DJW`O{HU\A I*@TLgъGMPH>VTTDO*eAҬ+竞#7U}ZXFjofrġЀ J=J&PPV B0Dr3^#Ap\:] İ(U`XM]T,xsmf'foc$_z4zb $-IE -Hʆ^Ps2j`W%Q*+dT)'zOSzV:B5AtZψq3w*)Gsx_%. h:_f]GzH#uf+ Zj@O *q76[ OAYte[T4Q0Q7~ae % _Á5u!>r,Б ŀ!"z Hx8?6uwΠ#BԦ: g., 7oJh- @ tfb.A; g$0 jA 9[ia߱ כ kG 5Ξ8+5g8]ؙ#x99zR'2\x /gԡ ebYuis Xx{hcy{ bBTG =ӌ3aAqo svwjI\"F?>~&9Rђ'&O" ν-zrHRڹ˛&>I@s9n\dpĺ9XLdD΄4f9Uao<+BܤJ9eXp?cbҹ$h/HH'FV)8pj(9 /y>N9͓ E n2atÑxJ>VqC9ǥa##1tDG!1bc<=S%Y"Da"j $zâMAt jNq2VWpF^m6*| ' +:KRbವ:=BPXՄEZMMxMDoqMX !-!hɁHVjtş֯0u'*>8úxf8~_fVIfI'fDt52\Pv+}=6gzs-AVRKK *&O#g#|NO0G-vߍuJ\HTR*1* 1S`LH0<mbI$G.RvJ1\0xbQq-zPI$O"ѪzAISԄ%d;[Lz͠.4 N){~TTLfMfN6XpC)$8V:8#ɷdE;wu'oSb4n 1ы)}1F6f#>Q\(H#MОDXD[*(|$ƂGR |7{@cIp#,EHhL$1>1rZ ŎL臜\{`|W$jdr~V폅*DKuNC1$Op̵%t* 4hLDU*kP0PRSOqk5'%>j؈։7-7wuo՜qؽ#Rn㣑+0IO<8qlbџz''w-A0o9kvՠ;#Cn]d7)]:uA}3];ԧ=JZ+(DH%(,!n( .yd$/%H}ð[ތ\5 dn$Ggkdy]Rtw0C{*~?9|G'_>ªc ?,W6 >)0+qɓ||@{5;S5TsӜh2Ec"|us-V7nDZ z~yw3$>zݻ6Y0zެE Eϕ#| `$)B;qku-'yw\+zD[#%N<I]A%wpZF#%''ӆӢ&=i*j[oI_ǧ+wm?K5 |5 #uχ'X&> gOc=t\JlTQUTu$Bz%_UQGFN+yQ$i @rh`oġ?0v2" #¸ѭDK #VFƠ/p/FF7s_`}e FuqIŨN!=i.}f\ sVq`s^"L~i\_UzePco\;;T9+v޴w.5e2+t]%~Հݷ;t'{ϷT-&^][3źU\w(1 ;k6c>-?q)}oCJgdU^Dn5X{i=wka|s7q<븉 -rUȏYAN7%l:)dfdpvphm_~q)a7|Hq檱;Τ{BA+L @.| #BE ' 7@i ڥw=&*<\km޺ 5ώL =LJa;*5-°ۍޙ(…H'#3 ILcvX˹~5~ O>0-@ylcd[%0x+ c֔˜L$"K-#pv ?0j~o7[OTQd\3/cN ji˒`Lg&CcoJcoMoGcOŸ Gg0oۼ}UU7-riQiBaH* "$UE2e:}{˸K!cG3#O=0t~pB t{A.U%3ZM*Qi4XJt͑rX_Wx. <"axWQt\Vׅс/yRUPGxT H69Ji!1\ʗ oQGqV#cM)яi) ,"H0EwwE2Lu#aX󞆟k`{b"KxĻ\IrJ'fӔ<-&ĵ%Ra ݪsV _"$S%dO?yn+GyYwkX+=-H~ڭ$vb$\)mІqBCj$[lФ`BˣU# uPo8>chqy+k*TZ, - zzVỈz%$ ε6e[ nD־qs,ABpl9:@<TU"@)ťf`.$qE=% i=lnE8Vauro \lj{^&YVO[P7cX;z㪀jUB4[Ň xOjmc@YdhNJ$VN<'j:=6rU{D~P Z <!Vnq.V_xnlA[/)SDۼ#]^N5{QY!,ዚ!e0q7۩ 4=L&I,~n ? A͚ҳ=uSS %PSIESr nk'„x!2Іy(^W? \^ww(zbפ͖lH?"L/<競Z BI=ėH, ?>g"Ď)2*㐨i50jVJQ ń['3{Nr`gBݎ :2ܞn<9m/BC'[+B/$ ) ˌsɑGǜz%|7rڱ |1W4 IDAT֫./M{VLdUg`N*jYm FM`DG[u.SJ*`j hpr^h@x4*c ӗMܻ??oogB]av&mdBץ@ޢ*ar GB y|i7~V_jV^7DQs^zὁ?ʱcfW3+폅cXX̱9zc~n]{C|]Qn{?>"ƱҺ鶳jkr~m vn`;I6`"͙/uyP&`M9ˈpq%L㕓a-vʾt ],d.S{YM(L& ߍ3ʥ*'?%aVYIp5gE!Q g7!Lk `l>}<!rO]PWՖ$F sʗCf<"f0QE~ dd"tIgQ @Yj bwf~y/Ѷ sm3\6yLޫn^!t;9+t|~ (ݻW,}c $Xt^+-x{lj`N|"cc(Op`,N\bJ=1+x*_e s&ϲEۼڶ܀Lv(ݼv;ZS{xDėh +Ə̐)j!7M}?Zj J?ǗE@,"M=u50hEL[+X6ȴ,pL7.l)+8ф"~+#!)c) Rl呾@EG".f7k[*;DeַL_W[T[T0>T-ej=IHjkB*Ai&BJ6%䨓Q'UUεyfD Ʒk-V*y0P;GfW]>γWe3s5{*޻PHP9Ѽ~_kqqVq48~1'rS~TIŵ-2t-&;PֈW]WVf2-ܽ ܻ7qxj2k$/hkڢf[RՂWS @ҊHFk)RCFA|K&"mp+u_q `\BOXZws)1 -uhYjZꚪQhF"p!lp-RYP)ˆid'|`ͦfeUKV$n$zP9|rVA*a rJ])#CCcy0y,ߋaI)}IiCS9!eٯ|qNKB@ZJA'hsi9^i-h[g5*yv kв6Gp2YzW%>ٲg .*XlE5sAHˏ+'F^[_h)AӼb3wFi64if4_gz9L ,Ydo?w࣎M͖Uxв"fN˼&K3lNB3e^ŀ9 wE{‘%dk̩qYg=UD_CPl\恿n^{ϐ 3O׹vpabKGD pHYs  tIME%'KV@IDATxُ]}?,w)DKXDn`I"@"-(h >5 4/CC@ĩ,#^"SHp̽wr҇{R1Dseppg93n@EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE' 8<;)WVÕ+?/xB /Kڝ>ۻC u8t=WWU~!/_ uF\qv,%‰G_vqT 1Ś'w,o$  &f1"a943l 8 ~k׸RYOFk'5/Y{!KuF, 9dmjԍDO<-hI-39_~7k˞WF,ktpmk">iq=b.bتd6E8N#&ph6. .>1{w-o  -epUm5W.*- 75+`ы Όr.^6%p'XG1ijQ[x1,決sH[G'kHQԣQBʤ M!X>UsyzמxgyrFY۷+"QG:R1q2U[)_"fgA |թE A Vy &^"BGQ܇igaMUCw){ܵj3̤Wߠ[7iCzh1v 2xGDv(AͯAz؆ƒ`]ٓXC2[@!#PAO0O{ yxZC؉J~^]!SH6 ΐyNV ~1zVH"1VxO-(H 0aP$ƒ~!<%[;uRɐfm]!f:9n.^syYܑ8)r(S0HOS;Є\y5ʡ^/@q)xD:tj~b(ӫb0L|S4nJ~rvr.fFGpyCc 3n!({ԁ3@.j@2uR@1N+@ǀ{jy?? E71-gS82( G~Tp͙ n8OhQ6#暄y,Lr*N'JϕYYG K?33d@ARh W*ÓsIx&64REZl~s$L02C 936CcVi<=DGaR[ ]Oygb+xxxT'@:*ZX ƥe ux4Pp# |g9 xE=H+kh9.8dX!V+hVdw'0?4 K~ heT" zP70fP.QV)OCMPd.*fB k "9~P-c|U3/r7i;سZ*)cFn [9 #Kb!M|ۼ+,_YqJkC]4r-Ijzg_ݗD?a#RC jb蔂i>1n$Tim-0Q8ֱ.D40`s5ڟ8.ͮ0N@/MLj`n0j~41Wf6V^lN!*$B17V "ƍulPp$BulNXʈx{L+0 2&#ӯ 4P&S9?"XFX_WԽbE"&^5Pĥӊ nYeq蠝 @کb;W8#)0{<)\34"Ԉ2*GAW`Ry+ࣇx,ʂ="*ͿtV3RW 9u" "JKp`3R.Sp(@aXa>C B:vH;ckJ凚ImHQCߛr'efgR95 ;COUp>5A XS0-03{No W =5aIu#d&0+G^]g3T< v;ʦJP8, pCH3B !\0R]53 $F ɍ@B S~\6y\YaT 0`Ȁ[XG},(X{|,E\5 p)D^,+m9(@PV?K*` 6 "g#H‚"0;[Z[|߆%mPb)TЕvq7f/3=$9U>6 `'!Za߲umxuG7iOzH(`rpG:zVbel.Nր0`ݢhv:~D*@'X4aQ=r|N2teg 2#xP^ynH'U;~2$dNv2!Ր1A^a*w>Ek:p!>;SEJvk˞Wg>v  hr t{)۫# 6MQGRЛe]; L`s 1nzspV ?3}:xWǵt*;V $btOçL e6 K%zӶvꞄ#\a Z77!C?;pmsinx*ÂB)r߇LLakS[ T2@ DhBoOyāq^>tx^8}ӓ zn_|/G6N@3²Tr@hA>5d%4.g\A"O5̑upC,m?b:<>?)&׈4ze&~\e<;f&x8=}@|ܜGSHKKeuXa{ḇkHr^%8WVӨ Ҝ:ZǛh7H{$̓%ѕ?r7#-;vSp/ FNmYJ>b_~Yr /aIBVh8jt->+X)păuهG+cҼ=+>`}O(x&p)_' nR 3pᧁc.wODGl}z_Bx?؇Qyx^~픾2W^ a)vK򥵙O>la{@np[-|xa™grz7,dzV?WJVPG8FS@>݁t𠀭2]ˀ] ;-wp&rJNuq}tq%iex09 &a{$ŨmCM wmKo0}:^u{sjx+‘P@hAh}l =IpӚ;z=?ʣ]+.e8!?[>L.>o Z]E =(;QrFpkk xGC5#n uԑb=a^ENX'QF$tK3 !|GXVo_IV8M( o;Y"ӄ퐋;6f7O-Aݲd%a3qH^c9Ͽ߅Q+p&K1h # x SGNQޣeL$`>.M08âo|nۧhן $xzx#}LAoEօhzI*Xٙ/ Twsb\͋ٱW7qòRxjlr&xi@)FExkq;O >os33xv9ξ z_/2էƱO?A*xgyncy1⾜z"Iwa&g-|K0}evti=_KB"zK"5('AW ܣHwQƍBL;%v{x`MFx1V4~`)Z.odH9&,|MasybZ?px̼:vZlN$6N)"\ B E? q]1&(-r.l2Wc%`܏؞HTg,{6 AL^1LG|_⊻h 9 Oѣi\74 uҐʕL〵 9E}fp>EPG\e2ق|m'{h1 D.4&nܫdiF?Bqz:bW;D4!nSh&gq#6GXq {:%qEQ>oPa{,ݴ8 p8=2 A`0Y@E}EDu^ `!>A]|O2ܲ -&;E"ǥ8 6z@k4\ gZ%;ċ!Nlʢ2xp ?J9 A׾($.aL+p|$Pi@h9!aAD{"Ǜ\ӷ2I̡$n-:ȋu`̂˹C(X,AO*@ s$c,3VII ͂;/[X\ wt93gX\Plhz!'MB 6:ED Im;} xH4 c ury"{.GzKńX436DmAVłA*8A-GG_㛭!,A|&_}6tGrɷZ~T*~aP&7N PXK@>6r/6/DN"X^q\/h1@ԦoAOsO~RQ(exԎ ^-it7ĬC$-g⹸U˿{(>{/_|+.{.]uS`f?tKs|t/+~t•+g(I6? RVS IENDB`robocode/robocode/resources/images/explosion/explosion2-68.png0000644000175000017500000000377710205417702024016 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME&߫rdIDATxN#9J1+(HIy‘cr h%8r;v7_B!0/"         .D >{C72aPdzt0l J&3=vkUPgMm  âkFPP0h|X. -PP|95^E(, @Fe=+ c ̏~0~|aPP8׏?o Ai]03wwAi`@jgۦgaq8@x!gu9~7\'clO2)u4 8|zi:d.;W3F?pI4_3|0^+Z<9ޟ&c hJ [Fi.xDIm: 93akz_foM,P$|ѿ<}Sh)` ؑL䏕Apn{&~T0zD"2OG1PvOʥ PSpx-T@H.$@QwiĦpiIm=gWPo1UotjCGi~rgzB^vFVUpIzs(j{<&Dı&7󥎜M€Ze`WPB$Yj@r]s8/WH^d 57ѿaej e6 Rpu@4saKšsXm_WZ A0Z4^F>8C! c|)!yB( `l I/V]ZDL| 06 |=_;@AAAtBR!n]!1lӍaB0*s:CCF6_3M;h1'M%i~΃$< "O鮢x@D6XR&EPL$!PUiAgI߹ ~\uAx UG 9-<4:೑T.0џ2$w z tת%]EE[گ],Ty{Fiֲ J0R)+HeYV Uy5$ǯx*&Vs)du(S(]VOAjj6eIS(^q;xKAC7`藀鴔*PR7>~\2r6&6*]-`*q^IȘY/:e` Y弭崶rVK9 J6HZ7QĦЩS`(7^/w`8m X BK`'~ V yr "6D.h7+C/ Kz,,(`I`@t@"!Bb? Tg1UL]ON Q p" ! sbsZbeusTgO sC 08@o4UKYkAAPbx[IENDB`robocode/robocode/resources/images/explosion/explosion2-2.png0000644000175000017500000000152310205417702023705 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME% IDATx=oUnoĎy0 2@(QP!!T|>@% -mM"$(0B8Aڎ}qj5WS9{fI$I$I$I$I$I$I$I$I$I$I$I$I$I$Y$z46c: l|/2K&,Ru^z}lrz2RmA",ŬK!{]VpkdrshV).ͤBަܡ?0Olrz o_uJ1| ,5(ϟ [эyJ21=(8u. "p X7)Y#WX~B&QDLk0er.Tv> tfi&#7QʰS%?yO %OgJeyhr1x t؁c8@8ya@<6rJq3m`:[7]ܣ2a폁a};GDLG&L??Gi͖̜ҫvX~ bc$I$I$I$I$I$I$I$I$I$I$I$I$I$Izꦈ>IENDB`robocode/robocode/resources/images/explosion/explosion2-71.png0000644000175000017500000000031110205417702023765 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME&F#VIDATx1 Om o>IENDB`robocode/robocode/resources/images/explosion/explosion1-17.png0000644000175000017500000000031110205417702023764 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME$68QVIDATx1 Om o>IENDB`robocode/robocode/resources/images/explosion/explosion2-44.png0000644000175000017500000004034010205417702023773 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%8^MD IDATxɯe}Lw|cΕY#J")m6f`2e\ 4h dC lY,V|8N=2I)w'<Ot<Ot<Ot<Ot<Ot<ć:1ߙ%%x 2 U$\;սv7`-C·D'.+aN܆ 7?ppz?G joO; ^ͳjJ>b=ģsAؼd[ s#5=%A R=+ u@ml(ϡ8w/Skon߿|!/_S{rK!RIPb7RdYU‘o=3< /_nu=~'X_`~Ե^U?#%$%m9'-&bZ%T!+qEkmHWEQqofuuܼj"#n^vSJ?bg+kW-o ŀ@V+Bwܚ(SM)2$}bQe8/!EC]tI%KZq`JW% Zξ6j\sׂ'x{&$/077!xx{&XhLkg/=zjxD-~y[[)Rp[X'#5GfS}(#< 5Ε Jr16KLZnJo+ f?_W6L xl~x\;6| ys,)f#**Izdynpcb7}U ^?uD&x'˚,'W*`Ő|M lN=X3GfF*kْe)PG Zq?ai*#80J@P0g= .M< 2#d/UYB>`:\q =\}ܖzM=ޮA-84/9~rlLئ]01Qg9cZ27"1^=`G@`RlbH^Ë2yjUܟЯ%NK tׯ a8qu*LۉC\`D}}1Y2l᯾e7_xE*!v%ɆIҞ`@ꕧg, TsgIȗ9͠`lzL1ʏ~ƭrc u#>peeA/Hlat V}{ '4y ,YOF!SEQ SdHW-vZW-YҍAHDcG"dYO a'_E1uJhD* FjާKŒѺe8{ Ƃi^ SMrxAvLi !)F$ / x!@>HEX[cUJjja# B;78) H%yfHVʐ6#\Bjm5!h@A=ܻ/ *0C-+ɺrl=cy='ޢr3m2  ױ~!pOAxF"F8r@?a; l`:Qx7DC:sH-1A j*22phR0a@(H|uD@-c݋TƣpeYLҰv!+P-SvseH-jk|u pp 0~Eةsdtn6 oQcEh#'uwɭLIƊ!4RDy,a Wz[m3jǙx'-d|b9*gyFULI/!-W0aMaZrY"w4H!<3 +l)E#a" C"~fݲfuYDgYtRPXE0rt&*sx{4xYGy %ՌxI/z^nx{b@?roQ,dQ$*g&#z7Y~H0TJspPyܵW"nw*>w+ETNO8K'`iC߳PTQܔq\=gb`w@-䷀~e&ezT0|J_>RW $GcD5DCTÈ>ʜ8zQ/aUplQ?X9=ZGBpZioE⣌UT[њYua Kܞ RB4sdKְ~3nu0y?qΞpO_RWFQ]%FmQbIIPa]liiX`m-ҍ8HN"AF$O:TT80d3{$~3A L` ,h9bljvD7xv0kj|"x%LVR!B|!cd4}*xQA/yFD~ Osyb&wc@ FpdZ`ކ3د1G6н cb͛H5Ůe暫x^BMGG7/ZPd2ѤN"(pA?C@ Ã"x~z `]l44wgs3;8 Eg. d-YCZ,+GFh(eqrn.|xd d-^<ϧ#y )=Z E9/ .c_l|t;kcUd˿lܾo$~Vǹ%2{%`@sPEAJYJP|o/$OVqk/{ .;f(Ѥ?3E7cFHT2ƻM~ld!rTLdc۷u ycEvEя1Nh(A+Y"5QetM&p>(D=p䝨~*ͬ?oR]h 9w=S[Noѧ1R08>y3[Ht0&8{4!:CB \dNB2f\Z:J!ĕsv1{4U"zAT!*UqDZǞ9V!cT6Ǭf%݌vQ Օp֝ Nןn;bmb> s+ Zoe1oq^I6^w>YR[n$ ~pǷ&'Sux=K, 6A sIТœ>\q/l+Oq[;h3VQ#h,}$1F1^p=IƒEBz\KZ29͛t%83Sk8$B8d1ƑƆk +pώbMn IgtS Kut2^D@#TW(*hbJU;BxRE4ƜWX@gu,FXQ^p:|/i؟%Y[+HbL:2_vLBN#,'9Dz lITMƿ,# YDmi2TIݞPqd8!dB$MRAe=I`a˅$_zID)E!pާѴhT²;3F%hcl~!f[Y}:1:Z鱈|.dq_1qc8PPt 5lH?Gx֡6U-(A}2mDDz.4K2.p e$d!}s:}Iy79Ix&q\bݾ ]u4n KqJY#s;Qdݏ;?V>t1,4&\`m^HH'&KnkD7=!+מPE8T@!p6#[x{h ɐ2'¤utEB yT6/$-kԉ-ժN=QtpRC2UbZãmK'[YeՊk \ !+r'Nz8\{˾]/|B/uGI'=Nz]X|"mz?*S[BS6}2M>ꄆ[KGBX%L':#WHҙ}FO;Zk P!qq Iv{.]ة#1F6XeE Rjw9?\t2zJh3k:z@7[HvIU|o4 zkx_E'A< bQ,x}%!,r,'<ÓQc^p+di=7' &3ƀ0g*ArT(THeɡ M[S (; /_PGNbh=aaUh">I-Q;ۚNMm042 kZ4# Hѐ|?p:|Y4& 44xg%")dhty7hL,!-4w^8I腻W{eMIhJ^! cLto 6 4o!l3ێXwM^t Pz-vd"ݭY[mؤ㌚|y rImceQt1#43Ld*Բ9kyydx8C8 IDATO[=8(SC14\-,1n ~ɜLA_B'P3QWvYӉv\-aFd+;Ӛ| KuV"ot,\¼*Uu Eml`MHcr }P{ nb%i }= "_z}X)*qDK+%TiFv3}"Z)6Ͽ,tnCv,h<~v,*uD@7PzFL1kDP~M D-- h;xaK {mX3y~byy1j&A%Qr@fhu@vƲrg ۰~IO9ub-ˑmo} ny;|x ߏۚIla'ZOy,cpb_DLl,+|&]s.qU3fI> _lW?z+@^y >6جaؔ$MSK=i!=;dap\qp}VK#Bf-"{q9DW YQA{0NBv-`VpmGZo/kgtg xu k0CrRR+p 6b*Q,,!*aQ[l58nHQA1J*h*C__i֡Oae&y ɻ8!rg89'35\,ϴ?#HFQ;7w#Ӟ}HV VK9‹]]sLƝEQT iƲCX E1\W܊3NPqvRq0) !ûCA'$rJY~wӲg>nN~+]dڙ+jAp#EFTcu`qδ #Kw)~_ ~)VKZhsG2>pᇖaN g(۽)_ %x2+@5/.(4p4~$08; a&ZNKTU|x҉gbq͐rĊi}<6mшA8TKzEե5Dqd+dVz0 =8%-LdihZdmysxQڎ`mXV =SMfR2# C\JpN`aw!q7[ՍhΎomYGh:N';-6| ttuStA `6Sxa ޟ[HՒZKR0jOysU#cHX W!Um_[)+E'Xs/I+OXOk=U=%At(;G4HC>v8x-K>T+q2yx 4o^\)87;;g2q9*Ҭ8dEwb. czil &p]~Zuq֝wNmsw8ZEl9A;8 ;O;"u*$:`I!an?-ũp-OΒ.-_' x8"xsOxiVIC@-C`:xEĪ1M'Ui]&t̪KtBt։긔] =N8.f║T|LnIS@hVˑ><; 5‹_ [dɇVK4%fu9N/'\kuC2`6Em*V!d}ئpvV" R }sCtL=ѶÎȶ;A(^m^xhV4'tY\~#Z>q^MagZjޠ-]J3e0phj]s{s,CP=$KHDS9b.X j,5 ,FPX0yDCѻ(r|"6M$wmaۻpTЩu;T_X2fgBk;&|8\ K8XHncx}(~Un{1z],yeWBVT%4:Guh^@( }P$s=8_Uy[Y< 5Q^'"p+(sbS~ɢJS-7 Ipv T"px p;+X^4'W#u0[aL9ݥwBd K@\XX+}Ox{&(RA}'ZSE= ύ5&p\Cy쐡alC Pi,n+p[{T>%u8`{IO.,='cck74;G -6Ri2k4PC N bD! M8pzKk1b.C͌Z"D1LH^Ÿ㞼X=JQ> ss#f,|0he)H+1 G&ռrR}LfU0WR]t٥ 9A1=?`,B=G4c$lcj2Y5Jit;+ky `)g4vA"a΅Ɇ,iX(G.jx9#q?zͣ# ;<6kք];lԳ2*N(f2,沂[G#XFmoCǍY|)Be&\K.)8jVgƖRdF!-XjghR VCi(s"TGVKG5+"1:{3sZ"TMo"ja8-IbU \ؖXġ /pTcfCo`er"ѠyDf(W>vs fSH3]D/;`CtxJ6qQ8X}xqcd2R\.`GbE'H[#(+M? "j@m'J xkt &jHO!91p?7?4+xpK{_s%%e:'K>Dv+iX$ԶF 0d(D fh5L >#P *| f%̫ @NQ!>FK\0ΞazѼ*c.uQMiOHQy'q$M1Oi7kT%X?5xJv/89ųeFbi@JTum:;ǩ^+\!D~iY֬H69uP?s$l7X{9e28#W ׇMW= 5ihBS)CpR"S}Z=!\AO΃ ;}!S|Aehw'm&fLNS7` b b(YPov83030)bZrkQf7$ :G#2v&Sjojmn'E$S|<\s-,,9^|xMe{7rmX;N4E_M)xD2$qXk$%Jf=^+Z"[}_D9)bʘEXOv +'˨}cR HR$-,sZʾǤJ==7#R@L ZWӗD~[$̂<|`|F0sRzԘ&p%MD v2[.s S᪾8տuqEC6s#N#IFjRLFBhrD3$ 'Haw3HB˜%I䷱19s :1B uQ!5<@= 7mi P?&ٻD*RjucKv }א756f!0 2zvK+;w[[K2go4cZgHCVs4TC@ġR`.ZKT׹1a!#"cw'07XdS" suYCӼB?h/*9r,Lěi[\]V̵EA%oyL`4n{ {)QRK_\)U%n'g#mV6~7Đ%LRUƣRcԡ$CPI6\vBJ;oŜi'#>.}c#Zv۔oh-YI t0&G0~ۣY20*xUeN3u 2o"ӑg3rڌLPrϕW+_<ҐZȅP ےy93@:yNkGl> $. FA\g64A&7SNQP0#Ҝh ܂IY?,+aaukւ)a4> .I׮C}pYF9_+Ü&Gb/3TIBEL 4m` "]B41x%l%o*tOO"%&znZ^9sKh tABKZGJ"X:[ud #9]KyC=p-7rO,ڶdž^`$8ʺe =`rm>gE$bmKg X(E9fٚFO"77#gR?Ɏ>6U_`r)IK>KULli!58_㊌Jv)5 b )mhXfQE=oh'-˞/*V7V &n ML[Py!5Z3KyzL @; д;L| G!0 ȜeBAƹD=Pxo+%ʕg?O} xR=,qAfYz,ʂR<8dXh%UD ZIC5sCڠU- \l#_K\?j`pX\ha"zQcuXQ}w*iom 'pzbP,\)ۃɻ6zz`% юI ێ4a^S`Fst nK""#cSÆiĝn ą*µI] V]?\*׷ f6g˨*Я{^77;C{׻\xBq\Z.;Տ;$3ϜO샷-9zΒ^qd3Ksru:|?#36 Vpyd5h|)j=0:H]E)tZpˊNx<x [2|3\UD;WEyXagM?ʎ~\D4?6oZ6Ks&a.T* g&&6RGKK=Ͽ}/ ꪲT'$}5l%x?>abKGD pHYs  tIME& IDATxܽK$ו;^3ssgFFL"%QJY]@uVf3@eo$?|:Emt6j0`/fHLf02YEd$)jGD{sypx<pm|zΟ pp_rΝ[szy.;G}RwEs\w+V3%%^sIpKQڝ);G8\ O'55s2^Fp} cbUz/Pœ)F3yd5ܿSn& dءX)Ž/wx^GXoԛ5PqxUpM˕ɥC3. ,>i pk^UYble9++ pR]?_|ߟҧ .8rCs۷'x=>#-(lo9 eImsйa|w]ϔE)Y{oՙLy17k/) j pH] l 0C}.DB̕.Io] >_AO?pEpS-xqr_st7Jaܕ`]p!c5TH2 Fح!<@8'83bwOx`ɤ'L+%U?p` u |B vA.a(Eǭu8sFɏ8i;U0`Q a dwLK>>{LOsQGG¿u8J aEҞRd+9O1{]>[Sy*6>wy9:{!pxxZm,ugy?ϼ{:L+q(?Tx )3Vef49:uT2{}^[PD&'6n;y\:?GΏ:q}"<'~gŗ)>FNVGz ,tŸ=篲> X8Ł@tgHV,| Տ }l9 K摦eSIMϹt4y$"y1΃kW EBl0ү\ؕ"v^6~fQ&>܎_Y ;灰U' zFnj鹍ҟePe ,'p틬ϝ/t}m{OHUwr tI7S'/O sw t L6_`gyt6 .q}nw}"= <~]X6(7S=a|'Ep8:^A>Wbկ7x8vk߱cNn4*"x.)ftV?! A…d1H!P Zi& $g;l7Wů| ePnpHik# @m=Nk:P+g0NۙaTg!s@226Y/n2i{<2kc(‹YqB|$VWiv 8?ٴ-r&M䈞3.l`O .sg0.:oV;MCWu\g[ʲ BvJ!U6)jO{eg&0(93_ü3V hJE-i'6^$>~e x8FZ){)B_sY;?]/6k1JoIJKlFa@[r=)`ܪ bN9f41QZCEOvJu&TYXƣ:3w̙:[9%]G9'cRʥr{w~,%5vP0da0a &d 3.RѠYX)`(J)C|M1[3 -Ǐv67߄'^g/kLL'>qtۙţQH($$~%,:js 4pXA\d*ؼHKc݄{R׽eWZ*3t6 y fFVGd0RFDZ.37^9@(?<"cZ |8yT!+w\ zSD %6[dVKvK3 ! d+3yQ9ZC7߄..ܨJ -ˎYA|ONe, -_kW2"0YSܳ(j*I#1P:dSX7#p3 mɼ. eN K"-FQi+f+xet#Pex/><: !ł>ay{= MAr.ˀA| Ȣl\10#JJbF"m Qj 1xKH=D7SdPPo^fCIo΂Y8gșvWqq{o._ qN@n cj:ppOh`/|d-38@ J/i .R"# b'W'ݻp=] F`+ #JHSr$zaV@6Rǃ\ȩ'A4TEdU(wzg7F#$ MX8,Ble 5c5Ua(wcCZOo7%z /<.ۥ [H"G+s\5!UPYh r H@5JAB"F,.=UX z(@u+P?FVݢ䓺b C$8+r( XJMA/Ӵm̏KgҷAjR#rpq UM5u̍[ƽ\)bvAGO9>anc/,_ʥRHr^C zT* dAL8 /ֈ XȐ a.$UA@1%TA; uFkZ6ĺW.o,$Q.*(|AsЂȥS 5>쐘Gt|P-=y:p0>>y~za6m=888ܹe?tkgcWI`.3t=,s\TG 8,|RVﯕʪvf)a3F([03 ђ~IdS1lLI+}0>B,ľüe7\#n5YZ/x̫7*݁^K, ӑ6x#=/({((F}/rWxN$\wP"$xq1_h@]{ <-0'~{C%9K2Qtv!O_n8)^Aةӡ`qQ67U+) )F,. xXiMd' .>$D0ՆR$6ʞ3T^ 1e^E_(JA^T"yİp AR74:JuZ ʣU ټ:De ƈJ L\1nF hRdf"=,0.U fX3/uC#K x:ELBX"EGpC'!u+[S8=wUΧǷzVv3Jj"{ u^^/h&wPy˿D} "_fn -1dniP]g$5Ar== pЌxʪWfƠP@BBP5t'AuL &^R.оD22䂺t 8(;J'N R+,ϰ\ѸQs|L݈eq`7 ' Nq콒f*ǭrܨߎkpTKº-{$yTjEc]OBR#Ɩuˢ^1t='Mfjb4w$>l)M XD.Ni@R \P)`#"B%'*Bf0GTYu 5ZCANI Ns= NFh" mZ0X-e,,Sgs /8Mݽqi#Gj,~v6F egX$%N kmc;Y3Xk_`Bցy-_ %K@iϻRR](IDF0$$%XOȉ^ º/N%".x$ 85&MBA#:De [MbM"Tw PΔ]q:ws=N72qhY|?sZI?|.>x2wc(oYi=!ΙfXg1,v:Ju>TGW,G9g2cA'Z yhϖ!xuɅJ`AP`£Ff1Ĕ"2d%JAH3 WD,``^ZG31q+A! r, %)RC:QgS;o=P(+@ ?/VyF+tsm[ӨsT;Mtn/::4~ \޾7?o>NSB&b0rܘ>w ߟ.d+2)XH#DE"֨xЧQ8MQ ^!AIHgAHKÂQZMY;y } HjxTg?;p wzpb18G;/s5%j8^~;II{E EX ._zB5c"Ƀ h!BH9bAk2A !VOe1Z#y)<IAs gdhL3[n,J(p[|XSȿ[ ??S zFy:«;~߸ȹ_CFɗ6HCᕻs UtPBIN A)uMRBZoc҃@H%@ME5Ad6(bļ$Y MPT A1 Dl:NVapA%#/ c#f7m&יOWK/ .o{GOI8;Ynpn},#xt8?xsǃK.3`tҵ&`B4A(-ܯ.8Ks@5@Ò 0%%cT39I&`V\ϣ%>11d:PK$фXn2$s(#:y jb̚~1G ~~9SY v?5~7cs>DjYƋ|)yO46'>K-5*hSجR8dBqכ A&~l_(fY:f9QD)ɩD&IMH a"hxFOD-АV s/O/1]thǘ Ǟ"\KBNM͉[rS[E{a7 닀 !H$pA-iXYu&w{c;SJ?^)y VcYw.Mm2rpPu] QyI! K5 q2F^ 2Hu##3 #f\)BJS6"^nThl4gОvT9Q:pX2+3r?8꿤84^V/ K zỸŰF NJ\yr뉟(@_ gX1 s`ſĈQx%d0w4$S@bF.%%HlAqFF"d 'PĈ@|J * L부lʍVy}S9~]xHDOȺd+t8/&+6 <& ˜T; KE(Hbf`ٟ1#&W\ & Q)?ρMw..H 0 GF95`eϹkn'HEIĔ#)H@ivA{U鯕P S5UGb>@h񾡓ˉyrXS E&"m\PiIi`Vv$0(ό#$kAqkT6p{6 ( ΀'g -vK+_+2Npb}VfnʾrwۼL A][Ư&KЗ'N~jƌe IDAT''#{2 Zahv>(;N'ՒWC;M4٬aNKe,dRdLyL9rMHtn@"یh#Q;b"iPPDɐMsVFɿ >\ .#(z_E0:,rechlA04LJ'RH8;~~saCfτjdjqVY*P-Y W17Sûccӻt Z{xo;tg~!|T^;FPL}r̝B'kXСސ 5h-& =npNbF &!0}|/"ȥH%! &Zq͔$Mfb64)CAZ 뢣;>tW7D}9TAgk$~$PἏh9QuJ V9rBAI#G^@2%#ɌT+D8D< 4  @|RW'f"Ҹ"6*ƯxKo*^œxSQ#ה~ }¹~ft~ L{#x?* {qx,RFiv2eza`[\\ CBSPyF=Q2q4VCyD] $[Ȇ@DHУ>*f/+07%~MyLehEWy!nBB1vcZ -PcEwx2r8)Lf)ޑG!E2Ha\|dMf$Azd]fȐnyB_$ m0VTyM -m(cPdeFSgN3M"߽V6[X$t5Vd`E"w}I3{?>ΛG_%Z J{JVD3i7UCOxy c?fb L\ehǞF@c8{DՈid7fxBc%:"1%hC-󚙮i}M-;lHhQH):۞BIc}}洶q~qȹoWC jЏԘސ򛷡]Gnza >=IP3)1^e3V7*g^(Y8:]"ʚC, 3CH2CsGj/2A` 'Sf~$6FtcMA[5 EǪ5v6Ő,sfGē8Ʊ2Lӷ'͗p:# eifL5M>D#qk_ݴEOR(  F(38ÆPΌ3]چa?w@O;N$?~R;}f ~:̝[v \O6 7恧BaTGlo^fU$v6i.2,Ȳ^kֳ~!q_NC/os}B \xKS|{5ٝ ~.ǽUAsvdYAoupl []kFܥH1Q);!͠XC*zJblWgđ(|ZFzI@ Ң"@{ i00X 8tl!%;h` 4SJ˜IX(Z+F7q#r9׮x~!w+b[~?+_Vn;l%&9mq+$yOw6Ixףe_rv+"İGo,S[$YXGX>gSv 1<Hv$vO+ip_rATyM?4czA@ȐU. ."Ce=g;, SGjD /ʩDdB{` |'˯uYks}V)Rvd# ۰ lhddȤP<<f@pJTe$Kdɺu{V*R%ٝ qo={^뻾lbk5Se1CقJbA|CyS#02GƜļKT|(EBEܑmfd|~A7>Q=9E'&f6W1 P-`){U0B𓅰<--`k2 ulGk+WB܅YT&^&o- 3gVeTS'ro(L!QljLl}@8%@cՉ#Ol0΂LtQXԙu.8㖭C" /i+9Ojz{g/n;;_fsF9љ{"5g8ymlSq<׊l 6JmtIo>A(ƹ:$CB̺3NT: +#!LLi[@Pk˴ޘ]2=Ϥm^QxW'o>7 o?b|p(mI]./%= "VVan<|?[i)%N{vAҟ-JҟSzdfYhoE "xDxU;v6Ʀ{@լVyw"Т#<ژ;9]6r=p#I΂<kԨ0G`ߠNI+aU`tD`(!)P|NFc2Sm2*:B<:`m!8Źsn䅳d~!Pak2PύX/8pLiO])HPD͆a;Jڇܯ&e-b:IWg?!|\7HEJ4&f#kA@F 20sv& n> "sk/>ܸ$W_lj/0ՙ14u$V Z{g~j6plv\OY%g`lVðD+޸-mEGᕃ7٨9s?L"M!}\(y yHugagB9crͰUyL$V!1FK4r$3$lWF-مh>Dn/j~_ q=?-jv~Jkgζ2䳖ʹO-D#'g"l>罷7Vrt>'s̔0F$6/!ASs,|i7=ݿ?ASIu/T(BFh#淧A Hdu0:M~Ft]G+Jx)8gQyg<Ǐ H*?Ug|y~Eׁ\XESh,GVpU-Hh[žGO{a%|X;_6Ndc;?E}v֣p1ron\ la]r 5ŒFlt.7vFuBr21zJQ)3k45vpn<~L5gOi <+w>VXU44X.Lo WM(lKHN0 GubQdb9BؐpK̰s .Ev_ ٸ@kA8)AHmhNflWr"*-Q"3CmSC:jt1'_̅U v6#>7Դ:giKbu}8c ՠ'ƁP_Ć<ۮ.h)o:[гIϰ 7QJG3ŏmtF.d]n)ޗ,e1L D \6^ڿt1CH[[!<ǭ 5J3)\Orn0}i? pSҋcI9#-fZjq*߲Ѣng7ƫѱv oєhl0AyrSpuУ3Rfݩp!C}w?f [pGc2ƭҊbBŘO $44ckFej1W$_~#AЂg&J|c4!; B#ʴPX^^^j09b̐q=&q41Q3.F{_4epIykc3//N#yF^ mb&'ane,Ouˇ}Sq }2 r;sFrL{TLtVԺ"impBt)6iI \dse V[c{$u _[wN~!m%h"p:)XEj!Kր4vBЂ- 8E]=-KRSSgOt% ;(@`]<~Oؼm𴃓#vV;"=\1o BHdҗf-ȃ6AL82!vt~F_+K:0C($l^O&,?^ſ7CxH!~qJF߫Ka B( 9M0!:8>p΢WaXXUdZgR14Ǜ hdP4f83m A9]Twswᨂ^Y$# W2)u4ֳ̘ YdZud<K3LOȹOw>OQNx4*Ȋh 5 d#&\#>+$:c{ ίJ4]n 3Sy y߆ V.7C-wn&lk Ev`DYikЁؘL5IĹ_pNgN7X¹3.LYȭE);M8fhPC8@O{-7?%~Q ~Y[(O + 9{̦'j0?F Rݜ glĽmI澿tzO/ £~uf>#ܙLe76`>,g]0BeH>F{ֈ Gj=T>6mJ`تdM[MB716.0(ZqM5A4RcPg1q8iؓό'~|j aFKBi8\<1;,g? 6I&.ύwִYXROʹfJHw=Ȼbt6 N^fgYfZ0:M4f5@=푵儤[Ұe&TJ<[gKvhJJ*Iġ. ̂Ifl$1tq {[q sv ov1r! : [1OA&ktJxe'f \O/-w'i<[◕3g6E I<#Fxrc=xLpG8mh WL6U ϣ{W?W`Vy::b o 56^ IDATlO+!+mrǠ\O4ݶX*Tż"&ij$ DwT.;3S9AL4H3?U>: Y 4[΃$M>k-}eZxiCuƢ i֜ɑllgtn;' GS|/'.󳕰2 pê(Fɉr7rzro:c[B#E|]XN:%l0ʏ^-\Xds\.CsR/fQ90"BǎJzR^#y<, 5M-LR+TCazwp?AX"+ PUƩ&RBUP! ű~;_8¿ཏKϥ#|m/U\tUă5ʌ<)c\3g]h2?~1O'29Yz[7;(+:({p *~A9wsNʰτ8D%B7fӀ{m%&Ӟ*zk R{z g5QFXqauVB&0rOvRO[Kw~A?"'.A+lFĢ3Y[,>r.bw߾F'e2!o0WEbJd ĞGz3w}3?+J(r#ӵwф ;=Jsz۽>t7%hxD0$7u`aJP-@嗈6/xJ1}0hAr5)zK:|p2۞4ܝF׏3x.v?Q;/9m68803dX -S規7oG'ydv9MؿRXg$ܥcfVJ'^*COSIF v\)N3!߁H+Df}`F=esVqvJ@=*Aax\SUJoJ{T,q@&RMhz8x%N5T7VeDOaNC<=_f?Q9X>a'6q81\ G)\:gM9=бzY 4&x@ܻFg  CPx &F[<܅ ;`\| $Ԛa2bF02ri<>-巯'rSI4'!Cۖ021Gg"3*d06"u$Tj0@Dt&4\rqC-pL asx ({ Sg:@9pd<Ü,\CHgL2oGBp5D9Ù'8/Ҟ%(b(s$TDkQI:$DDˤ–n] R2\ٙPa%Ć8FOdqlܰ;&u:d`?$3GHNĶٳO &Fljо,@6w |_{*|}_xr)tp/Y$9QFL:Yaz"^ar\cTfqBĤa6EXKMe 5Ȍ#f -vr8%QX*A 7S RN׺/vl-7rP L#u 1CʜL:E Pk|AX4Olan0ms3=d\{&T#U0jcB8Xgr4 T!)eF%\Kxv_·|x]_:ϜEm02kX:.+i̊ǁJX@5M"n: 1C+/I1QFc-Ē(Do y%UEv `II %14~P`{B L`+ipX+U.$| 3Vl'эTz9K9le t}dOsU4CB FTdTq-3d0*CP)*HҀl^' })Q/'‡ʃ8~܅:W[z$[<^3s9% B^#]R'>8[`&~zjmʏq԰Jn)kK $ZϮD+,VR@vA"1 _3>%`^j©!(Q9W%"*&Jj DLy󗰂oAuf=s ᔩېG3(>ǎ{讘! ,U.zAlD'E2O 4@TtN F$Fy.yWJ{^v7,ã|FjR+bbK7Ѥ K<-4L=xVkB \ꤩES YD]DW•nAuH*~Aݷ\B8'jy]T@"!Er :}MJ7i|gWPs=pQm"N/tF% 5zljbbH46ea5rB-(tщ8N2'w>~Kg x\;e^*HXp48'cKh9w$8GVPp՘\Ǘ¼1Xکd-dNG:cǩ". p 2B)2nUyD=ب4@(DWsx[]b<L?6|//yI9hZ9TX윭J;8o^vBYRdw-L U1rhB Mꑓ~6ׄ^qQãpرq2M,jtc,Gm.{eHB˦;τg^][ Ԩ\$$-/Dݠ|dI_$v$I@SC9n{M-i*N:BgLO21y~m^r#2d!VFrJwI7IZ5,*a!btFg5kRU&o[dy᥊"j:Rcu:UpX>f4 _".,ڜd Nh36O{%`$:F 6-4>>.-OhL6/yk0_>"G0#Vr3]qF|$p+mT14oZ%LGL39},msu6fR)D2¬y\E-'gB  JtAF-YO; { ʄM1=̒^\I1 Z!1sI[2ZD7Rg#Jerdz2gH^Մ0l[Fad3aIMfya? Ind(/>\} x`;ǾxE1%8׌ڜAb1C:xfKZRg]hۛdrkR͕a'ΝFejk cp5r]g6YONM]X->$h/5Hy!Iqe&qNg3I>TP^>%}Cr xE_BR[8Z 5 1h^ٓPN g8saM Nqєu4|Dbo2 QiFC7)#thcT$N:(ılL@L:23$-3^Ё}' ™D8 P,HSiULG۸6 $S'AYq)D&|;r j7oUY% K/ZJ* gl"04^gmuWC֩#>B''TQN2r3iTɄgt7 3Ly1)).ɛ#O@&O4$tPBE?6Yi GӋ*򮡧ʾ9{9JEa!PF_ |}3GP'cfu&yj5j& |ϐ͈xq+OwSa$R2z匵sfѿR~ϷǙs1Uv!lo*&SBUeQ7@E'bŤLa'/` Fi4*/rh5UOԬg3n53-:`Oϕs1lE:>̩`IxZC+$T0r D2#DH9~j#|sU7(>Зb5j[:hU4:3yๅ1|H{O?9_0N'b&vkãRϗvnWIꄱ8lGf.BK`Б ^%f<0M'>ޛ>_O.s{KptRM$v0 9eBMu <6..K OU+%fPHqg@ ʐF\Vx\f#f?(nf߹)K-.¿|D93e(GԕBBRgXeehNʯ.~>ӳ UA]J Tw&n<\Ѧ5>Hid: ۖ*/@[[22ah_+a,]Qi5Jäs! 댃wZ©Ba(\irXqɊx y 2 - 7jF2Oeu"ZFt:[15ubqCGjXxbԛDwSf;@ݝۛꮲXzԛ18n7ovw[f#z!^ 0PWJ%x6$2GBǞlI&8\Wש!2q4.Z)4F5'a, '@tEB#lHc>-,d'v;J\&FdRRf-qB j =}0V~rwO71qG_qQ\t;r+^Dבd*ULg/\[!u*@ ٨/3Q39H-zSfA\1mHȍgۆ)%ؕ^#'HTz9֮8 6P*QűLCˤ lI( b 1O%63H YSzpGG/Ŀ?L72ſY_wѕNxT6(tIXH1XsPW~>>{oI@!h[fVQJ+ gn=}PsPztVSسʆ%lVk`1YDq~ηY=Q;a -P[x3+vm?6f&RB )c鐩C@&)W3>r޽]gxnXHnu/ap=RXyӛO;ЗMЪo1Z B44ʈUJ՗&3\'qc\VΌ"7?q쎰=vZӁW$xb^ s΢|N(%D>3_2>;?vxetpy-,Fgk9cyD-@2Kq^ュsZ@v~z%=3aۖY 2KD%QrJK&H8"i$-YTSO2>0+"3FeJ/2^J΃ſ1}QF΅|D ? Q؟+a3 _nrtז1R_R Sed$srmd7tzpў3U9߽)ƼtY{#2dti|#~r5z}_d9 p1Ϝ@mj&USڅIzvya#<)>sljLGGSW:0p0̏&?܅ƑS <7c$q,*ӶLnE=Ә0)c,U@TхF(`2gfFF*zٮbUw.q%㾚nQ49Z66f]֚_of!Rmx㱇4Pf?/j>f436з|ҒP4Һߐ 5K4,` L4m,;Vb_([('bShS ǎf4qu -R/g=3޵&GVaZ{]He aesყѳXӇޤvGtu-p♅C!@9HxN.,LFD)y"N,HσRТ:|hh5X25h";>s^5w>@}zvcen [JrF/񡲑͢6i,m$X$vr/ /_gƿ%%@" !0BW^̄ag9͑#ja\=Yd ~p|>-x*}6_ ʫW9*ǼCe<5%o33$b{|M&ɥau#wp\ۄ;;%-'v5mKaiebǨH)+,),E3 qz ǦasOb0qaL(2O$>`)nSy]bmVp@IDAT`L<~vedrЭ?bZԯ:vZ˖awd~^QK#fg΀99t%vIV̨؊ŲM e§ggEgnQc\Ńp23~51=;Qu8$j15|;Q.B%ߋԼ{m\ҥI*U Tur0}8O/k%*e*+F9ˡWe k-/+u}/?< N/u,vM)_ձOM7fE+G +d` rWp="Ưt$Jfet}/ӿV 0Α憮t$7y%"pZ\R>J,vWK_\ +0c;IENDB`robocode/robocode/resources/images/explosion/explosion2-64.png0000644000175000017500000007547710205417702024020 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME&ƶ} IDATxԼKdq3;㑑o&O3IJnb:MIJ~Yh3@ ІFB3Lb,fpsfq=Z,UEB 8ccٹ/8{ {o+ǭpuH#̸8p.wCF"GWHTmu/ndY䳍A^} __<|}~)+PY&Sp_!&cQ< Į$s1I[z woc|1~`WMs{˯k~ƿVwx- mut^k3Y-4AXPyDPQ_xXQFQ9xѣ}=?@ǜ&ޜ'gx ѹAx1*pQ,xgv|i9HBLs+s!|<*;q%:}s$ cf<4B=wo|oHg)eF ad?,扷/=܂4ƒ?ß68F5.K ꐄ$%cO[:wmηwl@>"~8EMqA_EB))?,'*j1~uyq/|pis!p@pPu M:G\Ҟa鏓I^>_] ?; % ؄٣g7? a/4 ݞg,$a,L&w=, 6.b3HWw'5m(x\k389@  [!A.HxĢaZTz؆#_l2@ OBS8;;À{8H<+hD9_)98_|x|ƨ;Ds/eʥ. »bM`E L8Y4w-w|KWb8Gyѿ1)ٞ9]-w ֝p겳:2+8^*:06xG[ &fo r}pùD)o8+|pm) e?PYؾx[IkTcǎRˁrn;Ɠ |y ' g^tAzpuG/#ϫEDu,E"1i0TӧD9%;c^:7OzTm3q-\^'$ $gv]b+WFN^ ~կa|< ʊ&"@:y儮<$N91o9ګr?L7v+H9&zێ)( C,< bTڕrs0^h4@)a]d`DPOKu|W(丛a% e2< )U1ȹ!)Ўpq_gS(*ge*֨_ UԶIC BjT*W+J\5Μ {\Cޢ[r6CTVJ٣gIptsKy0s{SJtC7Qn߂2!Bg'ՠTJ•șR@5 8텪J욑C`Y*ڌ䜸67Bs^̹zd)qmzIdL-;h0pLTMkTQ_ 8Tv} 1)XRe.2OP)A į {B)t<%=AHLdW&د/Ytm'2Vs _s&/=) ׄx&"H-Y{%VTD)t֐m;g42G4α f?ΪA×1y=tL)J5RE 0C5U! L_ģ /\9p #q5T,p؎\TW ({XXy cBΤĩ6fHJGnm03Kx8L*w;?t9=v$ R񌪇6;|B8cEA% H!=#3D>qD9wqٙHUh)YQifLvnԙcUg_C UO.bi^g0eb DI4:F|KHqY0*9fq9RHE$D 2%CKpd2q,(2XO1`2{}&x>[[/K鏝҉efhK,d1'&lZ3s.HQfŊ(rWu^GH(("Ԗ8 p %J)h A{|艞--D D'}?n8!FT)%:4A*2J"GuT:Q*iDᙝs* D"l(b$LNgd8M CPQvb B8g# GR~/<7nek3md[AmrL1 ,;C'XoF3hd՚1pE( ڴ׊#KJ/2SgRXl d\ wH5 A !,d@@글S%#<'3,4[RdBl. }EK kС(zwk KvEƹ`ޢRo~=kGT<I}\L@><4<20TMY053u4XQH'&fVFs E )(TpBJBa5TՁUO/ P cwœRV `xOH.{T F$xp ,?'%!&NbKQBC3SlJ0 9#s[¿~s_$e\2Ѷ-Ji]Xʊ=#A3iF#L RAUf͠wi #vѢT$4N=>2 ` N3s oQlՆ kJ vBp[r$d"-!hp"S4/0lWs H0'ҷt  |ݬeWH\$mn yR+@{g7\P^πo~a{*KM;?ܹYRBxI#ttJ"WE%X_̖x{.8 #~Mf2 ʣk¼) cYᄾI9unTZFg QT$/8K3Tak\XA#u >GB (0 %=զ0!+"S*Đ1HIQJĞQ1WY 7' ^ T$ Ef m \H1q\%u =3tņ4O0w)w; ]|BWJ8(El^cX呲)shOLVeƾϙ󊥬E%C$!\TnBPs# & Y 3J%dI 0 "%%w@l$)cA){1aI@},+tTZ}AA J&@6pv Ks\* Qk-ڡc6y:˯CG;tWwz,בz2aܢO+21QUscU\N%E>uq QV +{Xhȩ D࢘+QLu+#}J5mQv ᤻<QψR0#pTf7lTV@umzd| sbqb-I!bzDil/Kǟ OqK2<.~*$n3tm}Svi3!gM\D#$/^mjT3։+VL0W2aZZu, ɔj9ٔ}6+&h`e-QuA1'WNIiEی( Dpݣ)U^nVS4ˇ;uFmz!^q,ՎRF`@%Q$'VGGIY{S@5 IDAT6BE W ;D~EMT8 (fÚʅe+s'ơ(+%gŶySҫ=P8 s \Q)!X<8nH4H"X~`dqL . ~ aAS@]n⵲LÇD';~ؼ쉘8@ iE1TZ*h (!(lM |z걕Sh7A)maT# *1 br1/S<.ZxQx].b.U2$#x  B .3T€bJx9r;:S \ p*l5iGA&-/Ax_z|G_~on3@ޔ$D"%KO+_k"f?]'T&;:I ]y!`&T2VU}nm\L38}$!l_f+rs W( ω`Ì@Cge1iqˋ(3$g+L3!dqtpF I`eBf<G<$|lm{E|PSq7}MBT)@N8N@sEq9`x'r%d F ΓW nt6i{POY -%:X"LJ.[UQntqdW65!$cU(8x\.Mn%6Q}ĵCTZN)’9otFv+دa&2l7>_PW]O}^:)57p\G #fӽP4RpqtVr0dj3/"_%r/O o#qxt4) N¼g:ö9@ǨϘ_qFf3^%0o9#`w7+W=w)OY[ۨfRGҟb5h[V.}2~F&dG5}9ed5:n*8* .1*`,ptM}:^_9wMa+R(CA, ]Mn<KT^\DTwhxNx\1!x1R槐W41T# Tb/76ťYdwZÍK# 6V14~h(A6c:[EASA] $r.qAZMn:LR%t2j6:~'QҨh(${ >W\ \>}B6Co:y匠$ѝ`*Oq xQSJ H!aa@6C7͂nLR ,|O}DTuZ \~#t0+a7@j݀G&c+l9}򸎡=QZ0mQ:NJgrY mj\z<odm}2l$1~+9wW0Bo"tdLWK+|eڛFH]$R Mوcp;D$e9!')SSgo9z#b+]k|}*gM(s4$eN7]οmG^Hsa V=cbUNxQ S- t]o4tb+'F͔eKđSUs@RyD|V &kzGSеY%8aQ8_ichM0Nm66^c #> ꑔ(3e*E-Ǔs[H|=qt!Ӥ ܻ_>Ů܅3a3'9Neq1 {,i^4<=!MSf}ru9 e,gf8"'`$ <&?g}{Xcz )H1cb$BQlЀ, dˬ*JYFh;#["1f][Ls=nj\@PUϝ9 ՂVxyNF>ES\^`l11 'Cl{Y=(TqTq2Ɖ:~>8265xhɥ%z>AJ@PJE7eA²ʴp}|/_u"n.1As qtc#<5No~^H5?$Ф-F硾-sv-LxϹ#kMvplhJ9U*h5,8^ @g^jrhp`Q,8'b=#Oųύx'a,tYW/2\8iVW}oR>F&x y |MqZO8#! mĠ[A7{t*bXN2n^q:3wFqOqCw6w*ユb~: #U s&Ubv0';x*nQl@Ve!5t:OT`{(q<yAφD/?xx;-p֎涃;;І,7 )oqMt!JƬ@aP%}iB_ƿ:KU~gߴ/i!/P6 ;gY|[8mF 'T,qo· /n8;΋rԷ S,QAA&xn5A8g&=;kzwFx R']9M3?:eO{YoVVF6C slѼC5>_v1 n ?s2띣lt?؟>o r:L]Rfw!A/G32zy NfnPP5+LWpE J-hG2o2 R⇣\!fwҍɡO?W]D|]l:&_E%>;´ŻBT؝ ';W?s9%| y`oX:铎#waǘZc\sʖvh56FPrFe/`ΐG+~0dc[%` )wf 鈶leEǟ%H?z*R=Y׸=Yel_:q`ʊ!] ϥM"V&h9D_ǥ1ɑAN?5} V:~Os_<8Gq2^>X9a\gؙn|2ܝGjҧ$'ft F)x03*"yNLQp .kD W$?#״d< 2悁ĖnrA|YԙQ'Fn~yXt; ͠ln:SڜV3sӂʼ:?j0Yu+dN ]:ЭQzXhN~>2u('81ek,As`BG9*)E-`FxbKaAM. :UtX6Xl9!,J} N>(q.l. b@ Ah2$a940#ހn+:٠K +pEWVf; &Hɸfb 3ԕ""1-q`B=yf+ĩyI^ n߹ݑ&kk'|S*f.l8[;oÇ_+|ǢzψlKavϑpCdζTE4-um[ ric^ UhP1!9qmL]f-Mt&)xi)DgW)cD.QD`lȶf[їj1o挫e֨>fT3FPy :JhiUx~[>xsZxo +?:S'kSj871"m ` pVxJ2#lΔ8딯,YVduɡPJ9Dh5"!) jwÒ1dP`rTQ }H%4PM#2 AjȲyw6*C5Sp)]p/h^!riu ɕ1z,m)1'TiCjZH[n)N_8O8l~Osx|Syc|(_Q~xs"T&/ G@ʋa5 sVC#I8P8V8c`2B $͍+<ݑ8jE.>T?B.f8QmOš0WC}ޖrHzL %wEΩbJ#B_:dJLtN!9^f8&JZmK%;c{vڒ<2!ۖ`cL`C]p>3ɏ>| O+p~4*hܕhcS|X<o"k (6#BqJj9e5@5 k 9(>:IǦSRs(h<^7M q,O o.gOwyy.rxSw)d>j[IpwxۑX5 n.bDǬ02ВW5 W=-'c[g+t^yatXx S<(SQhPeiBpף9srݹglXmNHchqOY–lNT<2@spJ^zy7v ]$hK@sQasX ہ3)LyBGjiɄ4r6ɅfeP9t=W«߁exo\.p*NtF=Ec4tl%JTeqD\32DeM(Ȟy^I1bdYcxC^n"rÆnKE?p`*=GJC>ұ4n 'g>37W]; ?/ϾԷ.&Tj肝tJa{̠Iz`Ktt6f! ^b>J8VFwPQ'5 <--G$k~ h3Y_bKFXE< IDAT 94x bP|4~21*"k4wjsEʼn)iEFe^AgQL珄h:, 5 `2#aqϸCNJp+1?)JG2*ȕ[E4j40ǂI$c)9#Z-TTWb\3n-0&Z^6h\ᄔONIUFEԕwFf9[62?}o,߇ٙ\V&d|֑rKP tAt:GTGO Ԛ:QΡ6:)8]G/)!L!SC1#3L(pDn jvW%1Pl|)BB˔ihР#nL (Th-G B9/S}1Ċ餰}/Μ |x|e}xWq 61v&p8~tږvH٠Z#rc,L>-QYO t%jdOٟ c#5T5zNyizωsT]).=&dl<5=݉`6' k~\8cl1B-2"r@(0C. .ĽUmB%(?pSCj#&v e/@>w!H?ĐAA2@u^( !aV1@p(3 x،8I9T_b #)ҕ0zWٹ+N3uB M8Z DUdô b`g `>LtQ^.ݤOׄ[KFjS}(_B|@S%Dǯf[A` 99D>S=9$*]O:O T8)}Ax܂E鷑2E-DDU^sh"O)5]f*(SfOF1z بʹpzxX#wi eh dtMi_S2ٯ8ZA4TR!NʠR`nP"^O`a8J:,ucBdGĉq7$\`ψ>$0HA>f]\QgFd+kMayN;#Wn|Oѹ{ #t5kE%JQ&5HaN0Rb*T=9ô6T:Z+XSHq$x% '߯ pg9hչ;L(5P0a Յp4\~J7Z DB`ګBwH)}Hl <(OڷPykm"}18D;I{r"spAD ۊ*=mK@5r) Lbb+Ky);4FSa4 [̔GV 0dSaQ$p4οeCC T(.2agѕrc|Vo+[ig$c&dC2S;։s?U6. FIńb,H?O(3Æa"MQ#lQ? -)ba#LKq.~:m )HE@dp.+bΑ r aȧTقgDc&zG3;dAwk9BBCSp{N/;^s,bbEKЬQpfq8 m7JMRBః(1f F#DW4*IY5;F_ͣ`%Rr$ X$E}53;g2 'fs8'K|JoseBf&q;N =ZM/ cStI M"FO.1% ~>FD}!sszx.d(7ۘF9+c&=ButM2;ʶMilLlBu+8rkjb](, ,zء@;)!B(제^4# [P|E%i{ }7%x TLRL()SJFQ&%KLd&qG7dj80āN{fwzG}R:|aZbȽ{pCENOBn__2 LW̴nۀe}Z+Uʹ|YFxS{#TKT9[!i8 *!9 dV=DXV.D1D$ HwE/sތF/ZG8g x$)Q3 eVohcEH(TTE 0*u7:SyG;0i9M:Zxeֱ'<ə8Mnω)h}apTH|K Oǔ +ǸUBw{ON1:;&vPv,-P!:!SB8Aф% L_ZCC]:ڢ׈RRe:ly^%ǰ/9JQ {dab1SD1Gx~8-*;h[EiРܱ wOiaG;j)lC$Ms!s<«f! kf1.@.ZNbRehl hWQ66BGGaK+TY!Uʄy%b'&X?#oPq½SO!  Ik&&Eb! ʢ898;-cV;_jP핰C %z`Ll 1^ =*i̽:x$-(|ME YPNhGhvXnbB[ G3n2!s58i@2Y c椠`(5 1RE *2(n茵t@GCE;QC 눾Ed['D _C.A~ FHՀjxD2H>Q$%a}-lvqS) a?Z7{䠣N@:f2dxŬTLo] V;YSZDa GHQ#'XX92{In]OΫM"NXeJTrH2)z1( -b55!. &6q@+-㡐LxFP8Si5@#1li<w={ꢅ9d_E1Ƣ]1ս5G"3P焤HOs8d­¿z78/6w){!7:%O+І@[%r׮ Oȕ(O!qBQ)}]X %ɜb!E=ϯ[::b(<)m`ZeV1 a xP(-  (j? X995< 6fQLg Ѝ颺02'jBsM0 0FѽuU}㷳e_ =|R8(d< CuLʎ$)ڙqv-4&&qf|e*Z 먾(/gob8 fK<JB)Q-NRMcЕ?g yF/sR~ <[B D.b,̄@"VJ3L(*$6}VW4+Dq\h|4r'a t5FI(.D/ad#^0DJPyF{^}/~yi48q5c5<%#]-9<{Dd}U ( v7J=hYI2,F1l{mf>P@kolfdF#93j$A}>+3#]*l6Aͩũ׽x ُёqHq:Ju+2"T>%7 rk@#j\rb\/,t]*5&'kXA7ڧ ) N2)gê#&8 4=d(U\E0&Fpc,gk/sɲr%pK EZʄZ mJ9%jIuE=c >G&4jd$@6\"(.J;>F,q(g6/`Aw IR-V}FǠuG_ $C4aQξ+,Ka #q߶k!zDd)$3b T*UdR4YeIyJϖ."D=c,.ѯ!r?;_;aYld&%-3Ca7v+6h`=՗BNژxK/yXy0c%HaPD rX w&PLRYFS:$*\%1ªy1il8a%I 1!G, QgvNvo][{/AHEE1'م@LB͐B%PZn`n.'9r&c Ejie^@iSPdL*%!9uRVJlrP T}Λ )[!a .@RImvJŭKCSUmȼ4-.A([fͤ-'+57$pr~d xyGHxCDLL gK@ )7>%+n.)F&"IlWȩKK5;: 5 hLHAm} IGFQ8e 1wrNLVbqj4 )~,Wb+Nm"FC+N6L7éZBFKuH<fj?`{2^yrqYU^pDTt: ]0>Cv:JaᆻA;9b[xuŲ0T=GC^Θw?Ʀh 8 x=lqgTd!p.!@U:)侀{O5Dˆں-#uN%x6ėh,"u)Bm H'"Lvhl4\cuĴ]TgoDx1^r*OP?0)LXv~³`!uk8DZ0iE>_6`)R\XHd԰$kPM#b<?ـ9mxS2$C@f(.(2cx|0^Atո>@&跄njU1̕ͷ4G t|kDD*#ACtQ6iO.`9#.8G;W@7SAޟ_|ώ>rn-txL=yv]S[Nd2 6#dw<4 |(⎖&`'Ψw)IT'{Pye B r Xعմti3*!N9 ]+hr Akt4,emr.s\jBFS--ZWKO^p*NuQaCK|Js{tC8| f_`xcoM8^P)ad 48tSew 1B Ri|M"9`Ιv,\ɒ`XDW(~ @wL&zI ?!ϩPk@TM L.GrIHxp6!:gҸ=SCFHM\ ba)6dDD@t lẁi0NmL`Q&j^Tk'^ Od~is~yy#MǏ 2Gy [,X"jS6Ug)ilr4To!QlT#VA #V&zb2avB '-B5jz BaP]m)3M-w2ݱ{\#feJHZpYPja@~DE3oڣgSJ/8kԼYE,X'Z(>eCgtRrבZBᣥGCx]'{e 7&.pԹuw#eǑ)ard*!Suj_QaSr'WX|siӲ^Q6 5Ċ='r0Bfo?$qBR\ے{n<.;&+Up<.G,1o"+7^^z0TWVsK#IN8R'Kf;R=)eL_/sb`zw(9&;BR&6MC^P>Ǹ/1Cd3PqBܓ!cZqsX 5>8V' ]S "Ƒ|HOd`w2 v5p&$m=5&O9%] Ӗ: q@keKh#uE)хL-#%$S*swmVaJZ=vTWp͞=ߓ>suV֊k+<~eA enoBsn ,X)蚝nYVoYZ{C&N$]6sTԚm2rPmDvtBP"&8h!ԀM13BFx׌̂fvH@sB-T*ψ~X򘹪 TNㄏ]?2pDgjaLH54g󾸡<'"#6x0†帧W])|kQxv0Np۟X;C~_n֓KS֤6Å= ށtM3q[Samr ^n)P c]CJZKMH[ Uޤj]*&٫GՑXwjs\s~9aY8Fm]^|tTe ʮS'x!@ja4ـM" _xÁRwhBpjx=1̿N?n~@FfXFA&LV=5.!*pDF҄cTQ"/eQ}| Yučq.ATkv0odB#v,Ԙ [hA](jtɘ k׶EƊO\Y`0N\lip pl &x9TW'Lıu& _s W̸2`PrjRLKG%#Q5|2ǩL8R@`GI[݁C"3<6sT`q,8F^%ydwWxeL;E&%Ĉ-Tn@w5o.\:zY_uc^T|ޒ _'Y&(Ӂ fGJDcܦD?szlHA2rR_BZ qmVon5΂UyJVuM{ V?%")꼔*!m}r`۬mj"_Y x:3qL[q Ygkj#&?((c^e`☾{7(`' /!FGթ2UʍЊ5/+g긺 %*[w(PIU,f, Xc0JWizb-{ߐSBbu8!LF̰W%%5B?iQo d|vkV\"Ji"k2G蕲qdNﵩ$Ȫ/QMd5IdBLqjNI.V4!Vl*8=<6AkEᾃTZ?Xy< nm,L6L>w#<:.O0I+GI1VWFw9 #Wq1@ Lyyg:0̷:@`pс,ܹ{WIH-\^AXz., (qT4\P &0#pp6Ѳ2hƣL)4J -q[ޅryeߒ l#5! TQ'X<S4,)jM-.)%E0L߰JY-zFLrv_7c)_5Ct->g_3*pRqNG]Ϸ4jeJ&`=:Kꁑ+TXRwLiGyR88GY>"ۨyl}mfOWjzGm"^UKL9ZX%Y*Ѹ!U.M0pfz c0,|1o1P="5a9AǪө#m%6) VqF$^7̭k.+z;Ƶ;0QN0~Y1Dѫ'_j6uxyaB}!+eakk`͇|%Ȳbu4 ,tkL+bSpiԙ2x#dMfi'{Ǔ8*ĹlkZEg,vpTG[ިm#AXoZU{Bw aohH)M,ja Wܷ URlO0 p wLE%p"t^[GJjdkǺBUѹ1]vDkE*~[c3t̯]2q2++sRW 0P5Egd&Njcrƥsۇފl3sX;n]|olpF o?^:g >|M}y8_MQ'ނίn*LKѨ|~RſV{?R¡'eQiNJ:u!8w2:<[/E5*O@|9jrjG".PL %P}_J()m<ĩ^wMM-<:: qdO]U~lk4:8 ҄ӄFLN<_ /r{Oo8ta)]ֿsp]wjnRQh9];{u) a]_juc.#ea"IDWGT;j D hJ<mCM0ۮ#>Skyە⑳G0ζi3C_UnuL/cؿM?>E <{ǿɗ{/ꝿSz;+᫉鍥sCm\7>ApU '/ _g|/ o:|WExө]J&~%dE O+B3k^ũs&" i*쎚E5ObW^;U~Ӎqgi|rn/V_s> qPx v-@nu|z7Nߒ/}|wm{{( xG8/O­"\}ͷ{][lOW?kւ.pvXHlAps w@B,H5 ~/g'azv0Rƪs>yf|Cߵl:u_/W/}c~k| ?;vT"'IENDB`robocode/robocode/resources/images/explosion/explosion1-2.png0000644000175000017500000000452610205417702023712 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME$'RMqIDATxo3/]c1Mʉ JE%T7m|AUU%4-'NzfnKVmSFV͜yv̙!B!B!B!B!B!B!B!B!B!B!B!Pߦ5_9^F` (NX<+ffaŸkx5kx`\8BY\.`Pեo1w^b"L4#ڡ ,,5lB0Rj ?SʀgO'C  \JAT`X\X/  յ<ɢ0-S^X S'QmlF>\ !x'^\?Yw < 3I`q$ckĐmⰎc :^NUp:vT!V$UڵnA-!\:ɔ<_ Ew˛u#?dwV`~,672^#a[oa ˩BO[Xi';+Fa'CD)L2eH?`7:<|<4hC&iCzj1?Bb aP=JExz"5<L?쩽0z{%zep?؉# l@GW_VƎf;fg0<2s8 LWxt74'4wOH褍ձS x\zq~^*b{)G:>@Nz3ꍐ9׉^W@&.Tԫܻ䅥V'/=%ah顽{tZ A,TQLE2G 6ްCLc_&CAq'h>;%"PTT[.=D^ۻO0$X,;G1|;;0 -82ۻoCi(9P4ryl1VP\Vਈfl0I;ڻxЭ v^3S-4cALᘇnSzdG;0|AʐF;t=ӥᤲ+U>AswnaM-ۀvLNw~!̈́-n|@+DGiʭ@")6 [TRcM 4A+)D8'bHR 17B2=x7оϾm`3#:u aNpp.׊)iT gƮӼ;cCk+$648 ((ytP*!sM]3_ۏ}x{X>\OnJ1:?s -SS ek ͟|` \}xM&>]@0>d[M7?9Zy{_?@>g$oPߩ1̞ B~&PL92ni?"j|Nԁ>oмw޺x,N**Օ6<3Kޝ7DFME\$Ԫ ,w?_0aMh|wޠ4w/j\kFb㗅bE1Pp=Z==8m0$˵5F&h4Nfݵޞ` CjCZ+J;D`c:1j>w㽀rblU3=j:if:.T2,A%s$i& tbr|&Ư1[`ZgnXwCΕcI(0((+lJ6R 3X8G0FķHśKRAiEJYCh;6yZʆutnz7p4G NrѴm,W} i '@JPnLTzbζb܄St 0f.UË>I+V\085pLlp[L0]5Lo )u:*+콨UV\xyF,,)V ,++{ ķeW21XAo!B!B!B!B!B!B!B!B!B!B!B!) KOlMIENDB`robocode/robocode/resources/images/explosion/.cvsignore0000644000175000017500000000001310470715222022731 0ustar lambylambyThumbs.db robocode/robocode/resources/images/explosion/explosion2-23.png0000644000175000017500000001261610205417702023775 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%!5IDATx]\uU=3lbkmdծB/ }[dه XȮpQVJiqL{oߏC_J Il=RfשSܺp8p8p8p8p8p8p8p8">'hA` ~NGWWW7oOW-o皖-WVU 9XꊀUz7?'3 E˨ei-'drʊA`?NB9_,Y^ܸ1(ي{tFpz}M)y;f5q 1}t졓C  eE< jIG?$=tGΐ)+Cd1GK8#cWK@@=\,`0)g觧8in;_Ll_eJ7 ƹ?6,џns/[3SI`['.f<wZ% Eʅ0lE*65 <ݛ2'/_ސ$-Ч6dɼ; /pxnPύ,sc5OB<ۭ `#]xC('Pؚ0yxl-bKr[enנޛS=G?zoy0n ‡1瞽`A4OcФPj+xϳMn?0H#bA*٭ynҽ*Xys+?NЦ sboTzf8^ϱaWO-S{EO!K$sBkZ$&3bQZE1w̟#<"jMOFsw140cz *N `E.~?Kۊu1IdzD/x ~|)ADg/-J*BAt&hLZ1#^2XXH@N-WV5lt0{H%L7SgghGOG0W7xqN7NgbiU$>mzEN?^ͽFJvhe5ωzelBD{` by,BjP+z6b" g#ys+L̲pbX5l6ġ`*d2˳&?'h oH؋`%j54k+jOpuUNJ8T$M ^DR:#Pq7 AJÓ *׊)L&8&(BFIj\ I>ϳY" Q <<Ny^0H5[SA>'ԸQ>Tm( !$FzH_ۑvob- BT>;7H1>A`hy:1-Yb~<jT6 4;}#>?nj!k ǘcR/!2Hi{'-]\DHTfT(`ZEFE 51p~PP@1ˆ6Va x##2T1 I j x0q{'BrOS/#'Zg 7[ qLݗTYHU#bX6v_Q| 1@+mR{hzjrebOr⋯ :,wIͽ XhCfC ?Bnh.>QMrj-=MM{TEJAic;pCQ㦔O 0sޤoSٜ2ߍ Mv"H`Y_6l턨hɼ835'hY{]Z=6} 3)-wOD1,U'o0P#BN/W| Š7} ҉i~x;?iGaWׁoa <3 s(CAb&{F Ppkm[Xm䙺9Ƶ6//+4/%gT`םkv^ 6ic94fOVp?kZ9$Ht;KcF`McBa?". ! %㊽G؎!h8 kcC2{HM TGgOsO,+ǷT%H QH&aLĭ>FDi6۰t_]3.'"_]JB J`]Bl6"6{xMwT=% :~TsSV˭A_mF,sV^["M 3Q PƳ'HM y&/4kW,4,4bf({=2=fǑIJ r,[ǚbC"#HȖIul;߄.Ia%$@! єzE;XKP$ U]^ [e hIߣ7Z\S6IWC:R3Mu hcæSo!M"[Ə g%gP7ϠW.1)YOR8hw* I!o{}GfQ}&{{>w!*PWx4}{$!^4Rz/fʋA%U FV`%{HoHlR>@um=~\'2]zL,HoLLl3rX i$.FZр 8axЬe\FJ•`boydnoA"xyU=+66?E,!CrhP)LfEeS" Ea=Nkxދ(6BLa$9hrG, ohE GSGyܚ<6jL*RdRR1CQ 2Þ3}0 NuDX|ąHC-Hqj_S,[=E=*H }X ^KTlnyA, i̓Tx᯿h,K[zhnS~_|"z%.`[9kk?춏C=ܚ.i, 9Xրu ~P~ή\R2eabKGD pHYs  tIME%&>PRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR(!> 7>p\iM|yҲ;O VA~/~׀' kIŁ yE7%s=Ieg 'wohyeg'Qa|+%ޏgͱϴV,̅d2 M щOCN}NIEQc THi5) F`CI[&oD{,՛ qƲb8!u'GW.Y0AEjv:^hb,̒C)<*hS!x4P4hx__$~-*6C34XKU+#I@8a0 B,9MEL6#.N&Q#ae$\ 4B?:ZBn-` SUSnf4Ce0ưs{TddcɌCAJP m(˾Bz!];A˗YuVm $"d (yC[66kGY#noA4 l 6#4h$JH ʼz_# {LJnQx kA*3wSRh VqP(hṓ|f+Bk@JH  2ǙE8bJpΡX;=V_:ۢ+u0 c)Q&^[1X<`2%NO?O(I70jf3<1ơ0AUA@XLO@*A/B_-i h o}NN)[@ N.Bm waB;z[sZH8m8$qba  p;;4,4&7pІi%PZyLLPx@uXcw`i f庨Ip/isaG!9Sk]-3O4FTthSzHyO"" Jr40臆 c @DpoNjԼ&'6l~B+]$}CJF*Ab 퀞PIt {T 11!3{L!qPxA!gcyRyf7(X> q-wvE$ 1UwZ(^E*q U¼Jw0JԈbC?B-Z0_|Vke.>Fb}f<m X'G-6<1D}3x:_GgOb2J@zX#߆x(נ<ނ'PbXBȻdȆ`\E01Hn)|i_@" Dx 96<)5 oC@ q3"." f`jLͽ NEwPMQEy))gj~fqX(}jc\{<01c +qn y:Iֺ.[Dep$"5|n><:. X]% TpwƳ]eX> -w ͏mZIǸHo_.q,,Ztᖏ9S waOBMa3Hh0@R4o>k*8QtrڿX^/tRa^1^i'8= ǎFp~B{Tp'^s/wKP5j[ŁȽG/ɉX^tMeH <2wH9bTr ?k} ۣW$%0Yk,D2 }K9sŌbgT?+:4frxPEP‚~dmZJN4Bo=unN1H9/fQl`u Kb~-"P&AGMnx"O8,v8!LmzX б;iZ CG R>a'D0UUAj$B*D0*ZYXGaQ>҂`]0sNACo<ۗi@]Ia(j03=dQF2"H55{>a9gֆM"S%1T=C.Uxìd?Wu͇XX6C:bTOo΍,_븣L(dmXa/PW'G##+[E[0[>{'Fŵ+Z@MTj}8YI0t+W$'«Tf/x =T0Fv7vnyqC1@Tߣ?z!@=RPnvMk1-McZţ)dAX}A8Cpgo؟qc7,(yRF"[{@`zO<3Pۚ/iN @, clNc0A-ƒl U LΎan[EW9`m&Q‹݌uQfOHF׮gՄ3ZLX1ؤRm&[E-bf\#˷{b :׻lc棄7ojq\Y9]B3(qq2h:Uw4bXҚ!OP+\}`x⚄5Ai#Z2w@M 8#ׁ"69S _8Yo4z#2+~#x=07 @,aYt5;)' cf(Xk ]AY^=`MLP_+R;ΦiiNsYÞRbBY4=T3l<1tS">ȻЂ{!wO1jV`5s5@zQ0Jǖ#Oə%>=H/ܣ!83'[mϡIIbyrOC5˦SzI3؍a SwsK#_] uN5CE{:.]+HJdUjxY; ,PBmtI3x#uRJSHqV IBw076De X2ibg.R n@-cipbt)q1-;<lP>. Ux،`f=O aYEĈq= 2 &I3 7VT>QTù2hP3'yK AzЩ 0e|/ Naн- k9\+đ`~! =p8H%~JҼ0cIe,pA vEkw8㳆VkTC'H֨xkyo zJ)_ WOdIL Ez$u.w{I!/~qBhWZ+ ~8I$ɓ5\Ѻa{#8k乆sߴ  0EacgG:ƚ-y뷷.v?b"6)Q5OZ^._rT*eiFpCdDfe|bUnߠy!U~sLBKA\0vc@Mnš8s:A[, L<]BmBq]c(*N X_b@)t+8w-3sdq2C48`e9%)R`AyH U!Q^b'w/OІY /?{ fTpN:#[] e`(vPafFKDA#C U] i`w뎛 Pk|R21$#i`}frO2%a_(vE,Vy"r-/qgֆ)$)ݯpzdo2uw.AKPr@6TLv3Cgn;Gɛ v #jf} c"T ! sRwvL*b 68rX7ljsX&[&oť?$U R g{dfH {gqߦ̍,^>qRC1Au阀/X C'mcj1sh7M<l`)"3(gm*l2] )ZSTŗUdIrG!TBmq0^ v2&P?`hAy# rϘd'46!ֿGt5G?4qO yTF5l,ҟ6V4Uq k)A1EQMzX/iכF!wh{xE5HZdo K!a:1 N3lLudhU}yqg yE%xʄ8ɋ|ޱ >INO"㍐PT0B 4VH9S}M:f?&(e-^%,ïKytxYQDea!5Gd5ѫ&4MB{'zɾcMٯ.; ]F'H/ںfc^i3SikdAPdBY):«"ƌ$>&ny ĪbJpf (}dz!w4;"kKF@eYk |b;Ou؉`#lzM@Ȫxz$9Lk)&LHcMG`3NP %D73s8Bd̋{gK%趤^Q/3lw-áOC׿8d>Q\T=*dX *I uxi@t7cn?nxk@xɯ p \ܖ2w |$RyeuU ]y!?x_V%i i#_# -񆥋as~3++yu̓<:79!{Ōv¿~܇dGJE|UɫO nJ}AJbvϻp]װq?6B(Z%ŮK,K&=+*>^.lj,kIENDB`robocode/robocode/resources/images/explosion/explosion2-25.png0000644000175000017500000001415710205417702024001 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%#L;IDATxُe}?Uu߾MwOizmRee # @'9 @A8yP$lư6m)qÙ,/g<3K,ƒ}<࠻O߾_j#Ăe][;A|, \\\.nH7>^4,X.Yd[lHYI/9tB%l[>fya7MÅ yL}]rYI*zC8wRpr=e+1f}|^D >;5U?\mœKW8CR2t215 G|1k>aٿ w^'ό*Nu>f/(0e<[DHDAF:qg!Tf xb'ۆ6Lj̋^ƍYSqpIEe`(5Ax/X4W%k.7" C*2A%]\LbYxBsROSV++t=lx@Sc&4eZ#pP&̕@PsX Y!1=79XI~Y_=Sjqatu`X/cx+Qb#͌o% ,Ga&,( 8adxSCk9cbL|k?j Vϣc}SFc$b %Ѣ (e2iIx"(:`LW Iƒđ(GR,&2n|H;dnyHxXG/"ZTύ &G@bqT#(Uو% 1O7t5S"dyE*R<5@}OUKYcIcOc4CwP^h 2+z;s>qHo8C 朝3G18_FǿM68#D?Kl#))2E` +}E$g@* _$'D'@Fq.tcf8V2`wv/c#]|eFWX2wRsyz  [ɉw[8]Ŋ?ϰT'3GaSBjܰH LM@lb +7 ښJ W!6& +ø˵C3<F@@hu?ӂcZLQWidksւ6A<>6[W0IeRpWfEgV8K0 <0eox3@%@=D g: 8`@Z_Vě5x'W4ѐF 7i$lH؀bLMj_lV̌xf f3'(_>y*N>KVv౴٩7A:ǓB3 \z^@Nbn%?|N*Sgk肋gBbåao h< ,'әqN~Px8ɄuJ2Q/e;pe  Rj9Uu`Q.Kx-WC`%!q#!8/V:.dem? Si O3~B,pZu\b7@<]T(gj?(mY1vTЉtF,G:ג)OTL`࢟ʾނSO"XomI9֮I `X,8zg0SsXv !QLײ(|*50 8e:0B0.S'W8Xu> dPPMaE#15^B7 Mß|Lr@:fPcx_@u:Xyp`}OĵTI@PGP(t9#&{XQ 8nkƌJbj1mF $1Vj5w"#(l1.Dh\DhJ`(*v!:HW,&s, ЍKRzV۪YWocG !1XI yq)5[apT%qYp.o0L<D N,Z#frpqK=)*-٩4fEg_D@ 0TH VČ L."xğqKc X a;ʲqttL`t R9: HxhIK`Tw@iCU4n$QvK,f Crc"Tc pㄥgМy*~ *Sg7@EaMm_ߥ71>Ċkh{> !cuMm)YbTr5)w1BV$L(o%l0ޢȴUGL$~(mX!Z8’İׁW6ÀDv{č!"+ knpFZ4AEM@c>N:KܛԌkM<2E=}Uw0݅Ս6yegIsӘq)V5JXe9uibBAqhshξY}i`H$+%Qq!x7! CjLlGh'(F4|=auC#&kf e8C""lmFo-e\7Qd1qOw(h*b dRlNI`@]' B!~ZOԤ~ UAQIv)U\`aK>V I()HAm4Rh0Ca1/p0p/p߼NG96?؟yAD({:Fb6I{(e!JtVP4T*9 B9߉/nl;Z\"( "FԑuؤL7h3Ũ6$x#9QW鎏tnc Q *Q.Wi`.Q\UK?#328&N$15pF-Nlixo }rᒘX`b ֮-H(Rhdb4:B8!hK"c\{ L;mxcu]97'qTIyG%+ -\Ѷ>@2>7qDkchQ&Wߍ^1ßc}XOG Yΐpi. 1=bTIXg} Eb1V*Ęm۠;g+fx;$*q!JA=q*Fpu\5F'אjo[BWwcb`o &;F>}V=BS2u[fx(kJ#uV#CF"^7c^ŲPthxlo).8{:2A{"1a?al.y>=yl|`mMCʼng%4mW)A:`ӠVE@B@5aP,>j0=W W1z1:z!iSE5`0aSx| { '%jXP.#L|B" BMŠ"zYɓأ_( k GX$/r:Ès\wTUmvysh]$벢~ "Iww\Kkl,$S ੊Ąi\K276 UV0v@bkw ?Kx9B԰&/K emKjyUCjy9;<)ۯZVS:$hn%s~ɢqxGuywÅUS\X5\L{`w157 AM_[GD𜜜+[IENDB`robocode/robocode/resources/images/explosion/explosion2-58.png0000644000175000017500000007121310205417702024003 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME& %O IDATxY]WvYn> !uDIJ*D׶\87@X0p p?@c^|)/HnPթJ )iv9\.!]W]6wso^꟟+;ץ2}t.xm|ay畍e6+Գ^D}Wqg~f'wK[ցg৆k4: @i):Jad9^4Et\GG^(瑃BٙYG%5I ӂǁ:c}Gs ACWXLi(Bh-QJo!$Q6]V=!0-n__ž=;Z-Wr R.cEWQaĝo//eS}I^/nO<0gwy1tc2^'Ji.QϢJ 0$|[=0pk/w. B5?`jC rci C4B%bGl~W܆y8V_L~__042WOw,[gޔے~9#zYdL{uN`uȷ(ONԵ~_sC;4y9szib\`"F=W=?Ņ|)%EX̖OV+~q%Eÿj2)YmhN-7ho9NB_[ֲr19o^qHoSc֣5.1>'rgqcqݰ=&BuH9b,IeرՖ0BcY.-GAJ6Z632B/S͌"ۈ}II?BچAy[.%^o Vax#T`>m?S`)eĬ ,eI^@&ďFE6&qH-rpO/,v]w֎ˊssRg*LI_G$F g916a./LRh)Ց0ۋ,ˏ*fñ|%>+.5{{[om,F"j  o9V';^.^5R]If!JNZ y!z1pXBcIhv*0khNv06ⓣsGLgt|ǣٖ=9玍MKx؛ %(V.X; gjVqţuMVq$`mTŴyw[B{k(+ j؝&Jm$ Ͻ;arOZՙFmafqa=v7Q(ۂ9B71raMiMA"AI,8]#3i] )+Z?FyV+ >XB~B_Nj0`)6\R}Y#0vF S²8;! M Dc3Vg2;0rf413l&PՆMho ‘1)Gpp FwJmGMn37B_;bl!Ԗ²l l*(B䐔 #bi h)#$$3`g,c|ߐ:eg6N>Kt>oZ@@0:Uֆc`iZ<\O)bNiN 6͈rN_MIF#$OYDD[6^FV9^0:>o=΍pLi8vcRhF'$DY14T@k &X*-誂4n7(Q8 ḻ+7HENO#6T4t9vbcEJ%Z! 6{k]JJ:Zctolw ]V*Sfy ]|o \K X(VԤ6(uV15tT3s|mQ2.M&(`W˚c/So-5)}5Qt5I(ДHź;|CWttҳ=ĵ֬4E!Q7"s'p:2ԝ3óL̈́46N fBa$Rے=p}>qE@%"UHڲSo؜z. et3eV(*{b emJ2ȴ |$?źtIJūAbD`v)6Li~  cTXJ}[?8 KֻT?q8?D+ DQ( RRlp-I}|SN;Fb阯{zbcb&hxhQ_v:ö5xDQ".ч +ԃkZL׳3(/#H8Ip3/( T~|1cúmK&/Cd~H vpn3+( w>٥xܣ(Lh9z4.E*[E@D=Ĺ5n/QIb!BX^X"GF;$ QMߣ-ZFG6U_4L}Džt9ҎneT+뢠m`TurLCR8ydA ۃ$KrP)RdT4&`R L"O#xb_ܻ 7^ Q?L FXuMBugc)W0~M:Ś)UIt LI{װXsHL7AMlA!Pu . JzQ:hT^6%Hu"DJ:5},ni.e2v\s:a"PnM 鷱 3) 6. $-I51!$&P35=Pns3W3WqU>xG؟*'Kt b{P⸉!oCx:=%2X 'FDw+FR(hhOA:/!k}isԀٯgğc_Ûh*,-)tlX 'Oάc$pN;zJߟ0[_@:Xs¼~m!  6lbz".!.V es|=ζH۰~_\ p|kk8:nB`eW%06Cn,Ae2̈Rbb'#%"jQHj V&PF0EX6"$(:R 61 F!Sz $qҡc~Dg?d6z[2ҧ ъĈk\K7~'h]<@tC,QfDI?[on90?ɯφ?Fx&|V[7-&1o7[SYLAe4 MO[$cLz# fR^M0"s}MHd`c*Nz53 AFP1^ L*xe{%lvXl;Xkb:nّsRqB R0 !v@j vp̍u)!l>EyJO#UfY,4lOOauL\_}oZCæ)xȲФc0{Uko˟@WrgQ=VaqVՅXZcZyh2b6|UfbɲfkJ p4a+pȾh,aa(- L{Xx!G;Pz Rk\Bf0!P%I ;NzɪNw@<ń,;pa -I<lM1mq1k} g150w̟`.>T;_Aӹ/ 'e}*hӄ7۠!qy U1E6٘q Ws$cyO8B & 6N -2 R6Q(, qkqmZuSqg8}r;&gS:BPX#}H%7(اO3h>~ AD2&p8aZ\>Btv8R0N &㢇;~(GϤl@.!#l:xYdMI]k'ʊZxP4mđbޜEeFH33ׯGtgX:lgY9.zm._tF:pvwxLLXX58ӱJL } Mt5-M@z+Zɑxtfq>/l09jQE [2K&.AL96òlaa.΀²v4'}Ql0lRY`jSxўb 40 p[l* sb?6w`yGZ}:S?w<8uK :n]tNY4z]ʆ.?f6D9iV, ?iMꌉSq`=T"e5;X5[- 7AxR[^i/Jx ^MVKj(T6;<(3~UCghc$VB6duCو2`e#U.Gz DY5Mj\G6Gfv7µ\Y#pI\!8%)"Cua2ܩ365,;jCC\ lI錐rR+_? gC$60VJ 7(Mb͒4tl>,z89=; ١ӈcAǚ1mlhl ؅lDnIۺAJ6V;!=L"~Tɞ ֜AFEwp)* 2C-}zvؽOr avL%;ưf(a~qFW5zn#vByM[8ᚅVFMC' I $Ye٤dgUn fM9v' 7g5\͚:g8gy)4Ҙ2e^7&B /SG6`SB2 ko`nf4v'OY)_RFLxB}5=j#8&sOG\O#8gH"pj`ƌ/\&wӞw-d;: kxyg[/:nA/;!W2(& sl.M>x r"+# lW`#fsCG mE̙pUfrp Ҵ7*,]-ޠEVe|n| p<ڙ%8 e(>ڬ~E<cš`bLÃưؕ=C]8:M. t̛C>wDS j׼"Q`S"N&[+Gt wŐD IDATC&™l|2 )'; Aaf +^Lr@?!sٵ׭f|H&}O uke Vω)e7܆qNAcL&pܚ8q]aMRb jcB̄`BJ NAG) ]U|h"$iqv iEJ-V[tI}ٔK gopW(.翫K,% bЍ7~f`2SledhF1pLi~d5$g1i+H̗b\[(ה<<\c똵VR5q2JM)FkTQ]B-j A[C=[[Hs7ğl*U6c4MMlj)7vJ$k9](r^SS iZo`M6\BӯZ pkwȝ#3}18Q (9,$} >FإU':T8b3h [\מ}߾|޽ 2VG<ݸ@5AF'Ad5!\Ʒ}KK6V!*W7yEr]l0aB[ -)*P1>]†5 Exm6 .6C(?5;jnt&w6+xzY1@>^#W׃ }s9aru`pHek7Hk&iJ!cc~6&4 2UF nmzn |E8# b1MEcGd> $ANQH΂Yk511fU, %W 7mIt8lƑ0ji8"9c*$lieY;cgVt()y$6HGI@,+8 F쇬pY/)J)x #|irH2L6*pU,[;6t>" IsBs@ b4Ap4Pÿ~'N(ҥ\:)Icl"2M%=)yTmMS5FF8:,BC$ĜffAg&bgǴq,}ds׹O۳V {=<3꼁&Ò"Q"GWdgCn+sTy JdT5䲒('Dr2$E2y-Scpcaa-Ah"b'C56}Nix~P/rG,ǎKz7L&"zB*cc2)3N!D:T<*$9"'Jd&P]d&Pj,.Љ!1`҄$ЗAw˒My {U.]Pgؘ2jdfWx? !jGczcx%"Ȁ_#_War>(:)fhtQ2JoiIL <6[Fȷ?~ r) Z3šF5T($S^]>$$0mHJMGcAr!iфQ 放>YH>"F j t"%:ze҄2>M h~ {4 L㏇Ϻ+AW+qJ6}~tJ[FygqZzm!0EH.& Z:\÷}xՖNRFZbG3`!ѝ#qh:#Aڒ|ЙW-"b갺!HHq]A`ˏXwC^zY5.e}0z>q "PRE 24.RIf.v0hp%/͗yb*+بŤ)co9ޏoҤ'tqf-(~$hH1YP6Ml7 ޻7ER2*j+qHfLV&fMSC,84_5ℤ G54@a>Hz 7-!<3:2^3Lt(~3P@ h rN*XG_c6B6Hã]˾Ja SÐbl^١}]H%l75J#Jm.#U|E$O..3&c\IA+ J(6zf4iƦ` N@c4&BvuHl&#a@7EiPz[Þ#ڮ˗yI"“6;&a9J@G94zs>` o|I$.1̰rx>PJ=|vY+ÕJ|05F$e HSR;GSNIftfnhRڌArr0qNO>8vĢ6kF=-zH~ISt`HRZeO4˰*D5Htg$SB גhe ׈Dky13~`sr!>\򤱘+Y׀ِ YXwp* si臈Q_ WZWpŸlA9DQS+y> ^#5TU_¬6IsƬsy󸶼07|9n9=.yL#75]T2FJaI,ߐ<bªŤ т$CMh@51#.+IbM:w`M梌\vf ^?__5͕aKw)'wW* w%_0L26;LrրN9>6OHO)&cRaGh1 = w_E(J!*8o`TP|ey& >4y Dx0vn5ԸVbݾ2(0' xhlCeVtVrpyzAydC:Dp]$(5ǣ*YHY._ 5L46!±@5z%Kgeb;8jY`7\ƔsK yqN%KނdVDP1b1aSX\\F!_rPB:e*xT }?' b(Q6j9^嫂;> 5pf?eיo;č!*UfuKhw{h%2B ?ҫ ~_ 4`a[@ jH8ՐCeDFp3aaq")Hd͈{{}bN#L( q+i U/Рuq;l*!5ZuԊyhHU#9S8cӰTh m|pEMo#׺ fB^mQg=\m>! ﰛxc+|8\p8Ua=@r_$Jǻ ѫ~p)D((˻ ~A'kk)অ/k/\*DA2HgEZ{0.zWʸ JFEea(ċkn|3 {H78x9(>MRoz-Isjg[l | Sjzs[ NZ )sjh fiނB;4 (qkTO<ٲ}[SC_ds upnŔ .FDj4 zr;czU D" /IC&%h.PD,cd8A2f,/!| \  dBo_j'r[U,k)~BRK\W(J*ׄ8$sJf]*(lsLA|~$9"S\RyA\dTwڠxk;v4:q 769 aIGQbڠgQ^t)p0zmH$kytIzShHgpktv@:=?pcv)__ v$g=켂B{I'bqa$*VQ跄fb* ݐ dY+d;@̝.Ulwp34>dbĕ<hd"gҔ &ZIp#*S#).TqPB"D3H8#9D#AhӅ`2͌tʋ:b hvIGkc4k`N -Hm_ :]؛6rש#jc'nwyExN&lsR=ae4\]{mρ8- EUQ˭YdzU"ĹnD2Cx_RR 0Co\8GzJ&)MeP7A?h.VTI #\.fjU=A4W3og9S(_ =l-bk6v's Χ_ v{ u^éoLMEŲi`7]ഃp8'5y.B"sMbs+\ hH f'Xww͝U|;ywTDjuv82HpNgcmC5 ܛ;M0 zb_7T׃,Fj[Y;cS dW/+zw|+ ctp2m\p9){UȺ @ Hq9䲯*G{} d?m4vlW }o)lnd d1SPfvBn[ RՉ\&#/uH΃DZH%O } W6:P#,Q%KC|hub̢9vzACdo>(30zEgwxdy0jFjj5dA7ٛKxX"nk#- D ⤧Jj4%2$ !a4 t|O ͚"8'= #B 3L&3k9'R[T^8]~TpiÅ 'Iuq:5`Oh^pZkl1,cF;\ڂuuqPo2CzSj:eUT}ƲoE'A3u/tJhlN4Jy<"~V3jIvlq5\Op+|!as[3?SR\u2, 6qVi#,/K~Sh\H$ ΓjNPW۲:in<@KA y:Rf?88.]KVӋa zi\b%N6|oZ˜]fCg:v|\UZѭu7"gBftU-M+Roli%V&z\q.KuTdR(829'Vd B~C8yT>H W#!ekz$_QD8bqY]xH,!A!=+;'@ ~Syy9 |"sS|y$lWd[+3t 䢖gCOvWg4o]Eߪԥ :#w8Uh.celͩNT{qD2zĬWm R'zID 1Tn+egݾsdnY D\*_L->ځ:SrhںZfjrw/ Ȝ -N{ф{kh^Rgl'yk~}yoŠ'm- 7ű|C#DG2F7Vg17y&-&h)6S6{oQk3fPK*je = ?=h$B*M(T'\RZiF 'mf=2R4Qej*o!C,G"tb;ZI5y(S!W|֐E8hȝDkoøV 6"4X go1bu3gkHޞU;}o~<0Xv:Z`-κX^eFh)5<3c-'^a2SS>sSɕQ('* Rhbfl T8jCb5S1fvׅ7N3.wGzۇٱlyrQz]S ' 7443D\by@VV 3TހPjfH3vI[Kw΋Z 6wJҵ8e{;{:v00A GN|+=i~W4D]o=(~SW bٰB!gFWv#O Ӏ)Ї8V6wK_#}7)Scj֮LKJh 37P %{44M;ZRQ!5ݺ391pϞh)aWE IDATxQ~Tp7FBYlkJt썞8,aH®0fҳN<'xitc8Ԍm4׮ճ 5dndl#L89kn)KO Ub*{^a$M?Jx8(SJ+-GəS!uvLgM ZÊueTK9 F vv0fmg5`,c͂-ܞp3x$jَ {[!?}+x: 6}T·njsCлFfqCĵTnbVJ;dO"W޹^ /_^_e&Y=SyM|6kXNt̙ݶ4'h?zzWű`7bBk`߂+<Q_=T'S4dfLX(/o_w&@Ynќ9FȝBʽ?> kY4{Y.*&{fIZ=uI=#u/9b!Z-+#؊#"y.J|o߯p$p[)oC%FQN df"C~8iY5^5ށd $sj+Q˨` Ns=Abu6j7w$hfY{o 3>ٟSlc0N7daxB:o@)n݌۪E:x5b]o|w n+RXCtn>r*LfH,db̞p~~)dPu>G~cXf΄q0 QU}cd t"w9V<'*O52HҾsp@`C;혭6L;pLuD«J=`Ol{PީƄь"-*&TMv I&YփXhQg7>@JKG&8P .sTB #Ða)?;HGyu|}?gr%Dz@s,܊2V! 3wJv7IY.*Ht )#'m%=̲w>"[vc]<'pVzfUg#rY3+tAmSmtC6C0sTCѴ\Yޓ8‡{,1x̔mLWt01!Gi(*IƟU]'׃q #b, ~q21/:|Oti|[uz-Gx f)Km}Uqo ^p֦s%\ N{bɸ_:crwU-OZb9`]&yi!N,q]l$5nhN l[\1&(ffƏ_ ڲa'\qu$ _GV ?o *v&Pzm\@I3Z0s+S.)Poa[\P AM+|uwLZ֪##[D*Yv]`cSCI(crT&U}u`pr1Zb0m ˆ,FGug6ºWEƲr$hĎd;ĥm}:o|_|NʑYMb ϲۼ.h i ׌> ȒH-H\;%y4dC[38 K_m!n-G3.v_?:f&)U3Ѯjg)U2> 7d'HKϟP?#6ѼpGX^І>- Ϙ L*7حޫgn2n#yw=b90 *"W-묕| ~{p%hSJK9zeiQ>ĵë FwN0=Z|xcDkV3PMƿ䗼A ݑG^Ck[{͆yoD%n49VE'qzs\лKn}G'59?<?}gƠ]LԶrz9 ?D)8rӰlT2ɲv]\q?s5Є{s63ܼ#^&hʜCH)Wmf]eo^tx&}7w6Ѧ=^LVAh^߻Vۨ6,Ѝƀ>)=$/mgۛm* ~!‡?,d~1T&wZ'EAU+<੏;Œ_A>֑V':5; /i8&1D :%tތwwfTk>zNe_<=*^쁛}ޠ[>֦9L(R.?H2$X=<4 0<$Sj³(u+rs, / %Y vUQ]X)5v%'x5ާᄝB~Ŏ%g[ذ?WK;O>=!]v1޿ y_[m>~JxxK95n'dNd=f #M:(^:>ǡQŃ+Zre_m w7Ohis 990) n.aeXqA-PW8?JG)-!d 2k__:b-|z%VȳH8=R˪g[xu6iNSڬ "wN#}~ fVzբ3l3,ߍ^n0ogkxBw{cEˠX3suwVA4ةϙlOBe!m=ۃ2/Ar&Θ/hkYr{֟nv08_ی8f ooJ?̼u9WYF57c7~ N;6M6h63/KҤn^Ml|mϨI9n=ߚmI#L N;_X[+;`M"P 4ЋƢ^{jNKҲW[j0l'׿ m~1ˣʪT/+PO_vE&>[|D7B! D7„ko>Hl)ۘ<M(0Fg^MvQ`rjB a5<5)[S 87:͓F'OM{|c;.ZdzPNd vƪvm+y=Iu-gJ9ɒ" oҢm{=E_O?w6\12۬YtO51-N~NLkȤ1/ Q5InQ[md%D1W5K`"\>;>CF?h1x.>aL4iඋ<- >Wf>-աH b4j\[bYV.Q`Ƀvn& S%`͝d܂LbMLv54=Hrjέe3;RK,a{lvӝQ$^7yS!{Ƣ K68;nV]);j(zT[̪s7f@9g%v=.񿠋?3 gZ2/(?q@<C%0 lo* ˎ<͈CKiFhgN D)ueIJQ :3Hܟp#'kLT<[-Lj ܖmW_e|IMi^VYӒlN%V0Z9nq=&(-ם_18m]Ë2o[v͂lu@K@rWS .Bu]7zoNF!MYVdHƓaR5a7m5 1MK.wp~ iϘs&kB9%؎*:guzdU?B˖z9=N2'q\6JYQ{^-MVcP_%ν.>e,W,-uዞ}6,;< )8mc(MG fE[&'=mpH0dIC& ϓ&e!#Yս%Tꖶ!@BS2҂J4' =k&\ʂxstsﵛT qsH7s{uNlfcgHYÔzFh’.^-R6HA%H=sI?^p:ʓu4›~C8s$p y@ô1?9&7p JOl[PM3 D d$:SWV—SDΌjY mhTmJ?k.VP7@9 ޏ:" 21>'p MdWE R]2%o|mn=|`ʎ[f~X U"K;#yE GШPKG xD.T?Qe-(Q^1+^1 Ywkdc]G0IDAT\P#H~ƫlx~}kn|Y,LM$- $|5ꚛH!rr$‚}Xp&fj\ 7nH)PBћC-BsB PF&wL^1$! M=+o5YKpt45 vgR@~Y%W lmq:O|K!W[l ¿/5N#ED\ED9:!D55Tݵ?]R݆ 'jՁu+U<"ϨZeW8.%͚n(t+qrDP.%e%8Df<8eʏ)i<@R3]Ԟ31*tQSoRν"nX+qCGkp3/V7KK"ߦHʟodVR|n`ͅǻܠtGÖp=N^! [f0W褣ỉQJSHds&I!`R2 HuԳԗHuFeM+,:{Pc"w3|._#_~RfLXPCe!k\&sLF;?*ƽ> mp2!mj|/h!+^M3r8\[D a"HDC,9-yv6s{3®48}bGu1B]5?qrWo{me|YDr2 z Wn6)PIqd\N/8cgx6DZdq6UqaI+.s>"J4g3\>P#cw({  yŕ)f1k (dvrC4)oI\ฦ -Y.3N>֧_pCL.!420s5w|-Mw;槊DS_S}i56 t{셴<;q#lNGHvTHC3}dW;e6ŌG;O =,C(8x=S֨ՑN;8R oiE 2 D_;9⽗KVsFi${6f<}5:`C6䃭 yȡd/U‡,RgȮsV"2l#k7ҵ5~L^~drQyџzxS4gZ}=E(N~mӿaLBOqd*F:m" BLdM0)Vܬ.Zv7ã}+6$+b>>fe<*;͠åQ~:J*OLzsƼƒF&UX8%N"rk$ƑE6~b2h XQ$e-L|p$Q3thH4>9P/4_)+MP1lR}FbIG5h+2AD&JJޣ&DRjI|LHG#I]d{hJ` i;Ӓr螈?7Ln]awCTb8z_eߕ@ w_7qrx-=2㺣)Kֲ1` F*تmaVMDAT#v%)0$ J!BP0XI+TXi/qDf{:uOs>a$PwYMaTK( =Q3O(MJģKD?rw"b`[bmiC!,v:хLD&*s#%x ̴WC巫H9čcgקꉍ)@<%NǙ;Bà;7 ׏-ް=ˆӂy0ռ`b, Ԣ58A*{9t dF)F`JrfɩDqJt~*,k"*D@N ͐5]v3XΉg~/=l~r@Stf|i\D^DJW̜ ' FѰz,MeFe(kY"ՉabT'+2C>)Δ=e_oo-˛z1#i[~W]ho##3;5 /{w4 <.J5$hSIŨs D8;2TB!ZM5 FTE5c6I & U$ {@Pvp,-En}K:1^#6%RCFU`BQ-|L̍rV$\H>qdܵLy塅2QOYe< [Vc[eZdqu~UIL9}}c듈?eȅٍ7~a8k7OE8^@2xr u++d{ N9z (qGX[)L1LisTZc$S"!H2V{z6"}OeoYe #N,q9 5l` Ƒ8i3vS0:7`:p{:VDʢT^T4hG{Xo](4?% #m k/8 QKtJ cUCϼ%%&E@eg߇?~C ]p0^8nR=p.qئ^"PlHo)}cv&-<\M(T_'u\o?J\pp0P pcpʰȎh,/HEA f8l.0/ $:H%&Y؁ⵑ̢8`= fE 駞]˛XykpDlP3up?rFww7\zqPKIM\3rk8fezP燎sA]Zbep Ɛ JJo(%|:`[gj" abKGD pHYs  tIME%,܄9 IDATxIleיgH>X@MVղ6Vw;:d U  ^xջ* @ZA v9=ݭ ʒ\**#x3dq/(;IIqx\)'D\qC`aZ1-4`HNdbc`L=KY)rn9֛8_7o*^ VϰI" W.(~(fE 0 1cDcHP*YPiW}0n#>sMRj2~UԆK]uqq $583u|.\'c#^PZvj-i0 Ec!}  'f*}d~1]R}KcV9O BXaֆIQ7s\]h7"s! ȹ+xdD{= zG{_rt@m=/4LV} c6GK6@ nC BVtE.l zu SS-2 h9 C#`h$+d.]A9zJ+ɭc0+BDJ'-d6…\N}4^rUM<ռ>^H_5Qs!ǒbC|V#m]B%"e q8_Nj#|-wx V.DAdQvX $ \+Ei S\ ΁\4(a2AEV[mcX05L< ')assHBE #( sHN5YXqӿ$hKb݅)u[K4nD_>G!mb|iP`4-cI I i¹gpk !3:,dY;1D0(ȱ8/#@pbx_ N'>}l}TB>`a>BC'+NJ*xr,-EO/b+h70sJ}5 )1!h\*ih<4cX#AsL9L,d9 s:HPc 42$q)FF+64\WNF Y*dmQ.<1F!vԞ?,l,bLNBm@`Hx R`0,x S1'0avJ|IDB3F,^O/ mrl%zݫsj_bf8SC"˾ͭLjC | 7γ> V9j)`Zqs t XV) @ ¨znCo i78A'v|^~ 2akѮٷ}+XX4OoyquBr/ RJ0QmYyiü Gu)rYXhC  %98 < UzڙD-Q=NV6PA3(=Jr,z&0_{_ ӐԽGC00I&|Lsg}Kׯz&_~O":9QD3 ,6ʀV])TY/

=z:4\Zi~oWK"Uǁ;@y@ZYBLKHx ?uN]nY6MˏLϽW5iʈ'-9y>u"ݧ!xJ_h dHK/J+*?w/{g>^)K8h!݆/^'q?+oRI8LPxx֙xXVJ_51 P ^{ tDArRjd:f]G-/7oĺO_ Z$1B/9VRh푋)ĝ6+"t*DѨ;a\iz2˩u;MhQtfuiݦ otӏ\/_ hFӘ 8G)$T`T)r,!*g C.f"ð"ct)L>Hr'Чx PH;?nx 8m@4Ҝehb"%SP+z`8W*t`tY;`܆[F 6IfZ` q&sn݂W:^I 9L<^O@)҂@kT2Y]YGqL{0Eԑ`\'D٢ik4Lİ s+kʣtG;{x޵ܚsF诣?wְjB`:LT $**x'U: Pxwo1 ulfē J^{/#eOshy|Ϡ jVaay$iF r!Jt$t")2sg Wsҭ7 ܅ks{K?4x tgPINM=x_a J羸*K:F׏8 8BʛXM$%CThS& fj'L!kpR]Wգ^OKXC]s?=l0HǜI떯r\Bx> &?02 hӆZEluxYa;!JCq`j5C窱NE~4Rަmpe5(%=#|ͣGl/}eoITL!cW)jh":|a 'ZH+zVU^*uh ^CT$$*"2}IIO98Z_ vN:HiaD ) (֗m[+ozU+* l ~#? 0[yGbc$]>j{ux%5"'`tXONMW ġ dݪ\2H{X={pV#TDG( NIvR6/R3v/X+4 HK.  q68UU:h2kɊwP6ZT B2.pt#="ptTZ'$^2& dU9$!S{zn!ܙs(JQhPa޿?,eM% H 2&V5\d٩*dbZqc+K yip8 BH'h-@Վ睊&u(^e]By$+D>hJ\5䀓Aj@(+Rc;(`hLHjFy~1 cSKR&".eb'$SӃڅoZaZ`a61r .BȊ;^tJQ-p`MjUs'= ILQ4*MY$,UD]8&% hWZQS7-rG0bMr7GOޔ!6.*k ">>(L*zk.m*!ߦ\ SO"\T?ځw6wxS)[s݂\9Gj{cڊQ, ra8EJV|wVP.*8iCak< 3= g"S\JK͡xNxN)nIg`19~@=\QoV,۳!pPu/i ,Qap 3] 7V~Ulj!I!++ fZPX rjbj'~(yZ@+ UG&Jc汩vrBJF[?pQrSط{aCsp0H8!]\TXG&J |;b%P\:ʖ<9z2xM (!Ӏ!Z4$w\\ib /Y$Fbǒ/) 㷛/LCR0"ɚ`^ V <݁0*]nlsJЌ`1:EFi&wNx<#XApE#q7 :PgFsQe⻕CN k *+Ђg`/8϶9QwA̴1<%cs#*n+nB"vh'#%fk:O@#8RyP T1Ax(:NwPت~-mBH\-)_9f/]B'qAIiIR#,rsuد\O 0:<< PS%?o m2LdYr,:/^ܗDMFhtc8m-r=ݍCBև.)9T93V߳{}/q>ym`Pd-6ڽQIg㸇ZּX ,lvV* ShAé^5BzU9اTTIiE*`# ]'pk14h3 v?%U*1Z9K[\4˂ h4:XDE<ЉT=i^Y-tP9TVa%p]x{<\-@2N.<ߩ~{FY$2`$N`X@F 7SuBuml  ޷#עƤ}琄yNw@=p{~>$-n1Kl!L.ڴjp/ˣMvr`2pRrl:Bnb]Л(Tn6C1fZYFNakUWx~JO9긫=gr1&Ou9]cqp-2ȶ 6 1i@db8(F&j@A!,,ɣ\&V˴{hbr+1It ĀQ n CXmqHu"'WSHr!x>_~]A6cw)>GGP$H:Xa׶o= 9@c*z?cKѰbOG5n#c1V6:sh>*tFN,~Ã>+^\nE?@e=VVaMS Cr ޤl`c$؇Mpa2 HT˟#-P[DS`uL6ĉ-XHl60cF0A,GwԋAǜ^p|Ms9*&}QJʦ䪼BH)m#bn &zL.hH+"Pq~D ~w:d 4u쩔 Φdb0uBGm&!>b@tƖI.Ng$Vp|zIDATя%jdJ/٢t7_ǔaA{D2UL%D#ũFq5Qfa"Es)]ʼn=vZ-e{Q5"HF6 rzNLִcYQ E+ψ1q#e`l g [t{da~|ՉGc`q_}SW5 bZA 1m2j!];4>#S:K` \|H FÝmh vDY'{ƿE22BY "E0\۲4(ȒF(Q R +c 2O\p~ Q+.8P¥ s]#(>x/&EPI |X:ΆqR(0b#HORsvHfD uLsRGj-dYJcɲySbwj'Gj~dmc"I#dF`rϨni4!W$纒 QSDА1NFd."Jem.Ë@L m2&-6Dg?W5ݦqS؅bF_]%WŐd7=lHTp3 ػm,柰|9s\aG'\ PQ@;p:NȤh4@&%=C@+C4Q*Cfya~r}4q*f u-9Rj]m&;9aTn xܶxjy14v;?y''fHա+UHs EFSr-ʣ-h ,iwƎsX^-wږWߺ)S5[Up෻1f*I:9e@.򹫄~5RS;q]ؗHTvYvX~1j8}ӖM_z_y~0Hz]Igkk DÁEknO n~ljG*e5s+O~op3;#ߔfafafafafafafafafafaf;=|]IENDB`robocode/robocode/resources/images/explosion/explosion2-69.png0000644000175000017500000000031110205417702023774 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME&BVIDATx1 Om o>IENDB`robocode/robocode/resources/images/explosion/explosion2-24.png0000644000175000017500000001332010205417702023767 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%";<>]IDATxs]ǝ?}@R$%IJ8'!=إd\TJyI/|k&USeo׿ix<x<x<x<x<x<x<x<48`y| un ;3[ז7S7oJ۱t#PpHu0m~{qkM+^e5 jĴ ɋpHu4ndݰ)@|?mEt?`g,o"H*M@JI\z Y E6>JCy|AGK8^˥[g*^Qdu"CI" 0b}-dhkKmˋ ^//xm0Ʒ\R,2|X -#-"z2C*R &WTLgQh@LMtZNz.bޔ lX^psgf12MÄ^ʎ7riB/ SaPQ'-`,B&UqV!D-"6 QM&p@Cô1TΓf껖%ܪ"ACmކtp xSs mokOPt)Ր^F|[@YG1 B\ X`2b;CsPHHr՚ɶY ÔL;vΌx%'שn CrbK e:*[)TI7Q=A`gQa89MSý>͢ybѢ" %NJ$(C\Emsִp0EB5<;U~4?&2^PQ6t#B$AB0E.PE#w[É|8ByI`HkX:E?4q<5 R }#o2LV4Mc_S^ة!1v+Bmpj.Ƞah|[0` I);z( ]%ዏ}NV ?fXy J1i.eObyz:3'1_z^ W WQ*E1^hp jaAslTI8= d84h3覐fIxvh3Tܦ Y9DTc3hV [B"f| ~ӛ3lPSpQiFDͯTqF:0p l.P &'a:Z1sU tOJ)M֓ 8H!V < 'rtvb`H >0@؆>T`R0U@B]|)\Ciry?ZWU txO/uIOF&7h_氾ȝ(z3'JҰ xM/Eb{gNJ<#[z = FU>̠Ӛb1I*'Z ]ByUqiB2U#괐&vA؃`vKÜR7hBaX&$r* Ҍ)JqunyV /Uf" tt-g ybNUA5a.e<`^ ܁e +0rNpzp2Puϔ`rOOĿa@L0 ODlPnpm1ӳ$ڢM w9CMlAs$ӭr7O&'Dsp$<9f@sTs"f}8N1|ZqA`4c-.1!̑T!M -@ ?lAs0ƳzT5=a,ׯ HX80 `z 5ӥ񗊠efc5=Ndg F}8fXBl96 Ii ,.ӱG`|J](0Y x4<{N5ISdu, bTb'v CI+Uzɟ'l ud3xsֺ[X'AD4zXrqe$xYX -!R"lƣ|c@nֺDZ!FMɀjW033납 wUvu BYW ]̣2  @J0("gtH]JjJҍdKy„Y#$dhC+e%)V) 5I2hCyI7;MB&7VxJJqJX FOb{ڑ[bwb6@I #!m[`L=[(RP) HiewTBGZ-\ֵk gta;2͒h zb(Dm@0!ƥ SyUvHڮءGsgW.4cjIBup :*]nX Q u_އ@X.VtREEɊ1g>/JLf9({;K/P-d d9HEC{`:$\ )W"&F|<p%%{Cr%J(K&("0Ij2DwH]ddQ 4zI{%T /ߡ(JK`^ ,4%,T 6I.Xd?'4hyN̾g6yq7 6NWGta* (fB8Dƚ4ܺ42FNB`7{!}z q݄pY<|d sE +𣇯ԟkt|xfܨ 5;39s93qFM8sԟ:_ hs#[&ۨf÷nX_˥%װpX{EyQBQ{E>@k"u.]٣00M e|} 7:E¼K4|/AԥX Zxwi) )ZN皟j(87m9:16}2s4'MZfmg`Ǩ:6xlV4/F";31,[IE% e %J<(っұ懚{)g3zcl`=xha<h!jӿW?X>d 2PBRZ:CF6ņZ9KAeo+vL)g( ;El}I { =~AXw!$qax8`N|9'=bn}P5AC8כqo!h !!<6! Qw9,{N`WzwvgY iz '@{qdCv[Hs;e>P 섎zf@8VOGiB}oc$umK1Q(9Ye 7ۼ_Sك;]?A]x+.a G`8y\>$6.y!&dh.ǜ q n~q8r 5QbH) J=. >p?l ZB &Ϲ7MMhe-t2rm+ϔ`~,o#UFHvgGr!XG->u9d( CuyYڧ-;_u\|B[3a`zHX!.!d +CB1 XwK4x[ѷ"~/]~ꃯ  ϰbXqfm/pv {la6 QV'G;6I_ò&[+wa(|*2E7 &Ә@b=,=?]w0 bcAhqA^!kHSl%4e9*(eLqi=0, /_*8`倌!uRt~uPASctTj +6C&P :"|o f2Ř}CA$u"U%` !lZ<7Sby)[&33ZF :ggeb/J.K!k pM`ʵ"v 3 dpt EF6xCǛsE M$9V`h[Ŷi0U!CSh3u,:SZi f0$|Uo#RK72/%'5I?5QS 27AdaEd(" 9$]l4Dg??"IJ;VTij~g쫐в "9hT°CA%Iz(kEhζ>x,⬤z&v^! a 2ȥ)I)Q19LQOς_dVjO53ykʻbFQ(I Kdر\j?wlN y_WnJU^T$$ØYj!Lr0T 40aoJ21^Ht uRj:L^춅gܝh8ګb8vF+?""U/*V`P גjnY`%x}HE> 9?[NqMbFzabKGD pHYs  tIME&,, IDATxIlWv[9M4۰dKR]HT{ ?Ax6 }Ozhx扡"6\#@xY YR5,Rd.o6ќn7IU")ɲ+@Ddsb^N㗏_>~㗏_>~wʍ/x/ [|ބwn E"gF"7cW#+a?Z O:uY&ny<}>:6|E'm#wyS]}qNAN#]Hpgw``\Obi҄zN&{{Yos=g"9s9V3J>a~MRxǽ$p ?~#8,"f#,A՚଻^HP'; _|% p廾Px= ^ Wλ*ߤԧV}y/[Mє+28oFt^Q(㩭G x1b!Ail?a*<:)>O/zAh$_gs4 ?1y,@EijW;񠸻ЫHD+ܳg}qZ_W&Gohj%흚ӧ0{1 zد#?G|%k£ ;­SB䎡 YvZ-,A =>zTrBgQ.)|=4i㙘+at^8}}c.Wyt7ӅjN&Bu!H?;Ԇ\S/ FbRVÅ=w?Di7&cm'^hυj?r+x{9/=/W_8C"GyśU,uQpyWSIaلΗH]aPE> \@kUM0e;? [:#6=Б]Lb((LقQ)L\ &EN |Zvab0L3Y1,^89wuK-叒,UeLaNn\UsyU`v缈 O"_-><+"w 2)x!X.ۊ籦*J2V P LKV%aCt zf!^C_J! ZZT;s6p5 4Xa(Q0Da2I2R#}K 0q8\#,U1!+cUB-Tu`{3T>)z&V 1NPqеq 9IGqPg$Ph&L8mbP#X1S.7DU8c[-}q'}`o-pcE$ے0 S$&Έ&poqXbbᢅG/Cj`+|(Ymz1) OhSBӱ;&%:@E{Z31̼GE0HȢ:{V]fLAqU/1b45z! _<\qh&Nxe^!X uu +1Jq ᗑsfOsP*D 3L?EA]E_coI?xDG-5 N֔CCoZ 0BZ.=PM/x^ D R 1LvpLk!c\R1>_(08Wsj_\$΅#ۇP0!K0`CF_1pg蘴WIbNSrq'h-"xU {GDx* -<  yJ1lLsB3{#Ԃ`6*gHG|р|?aב¡,& D[C?}^*&Jwh]Q8R 0Cdø}c7 (qD5 (D"hM"x/(|BOq4jJƁUGAa[r ) J"ՄX9]F`4XI*ƃr@; " $FhbBz:Q=N  %MRZ"CT)>E}j=pR\2c%D 5m $F 4Ƴ+ZxV T1QJ{Ly&:0Ù7xyZRZxeIT] 5XC:1)U89B-SJ]3)Xwv*8%pzM 4 pZ !M@\Gr20Ed`- D!bU)w)]p1 T~@Muh6FSy.ZxϽmc5|%a 43TAU ߾w`^Ow8m<1^%8W%ZP5@{Ui:DXy(v ܛYrg |ܤ2!]/J ƀXзkqA38K1^=&K4+x~ G)/N.)}'m!Ft=RJX?h=(q𝇊)7TaŸ)p }`>ka2wO*Wa k`I+& LGY1:u&oӨ5+h%YX(tv kk6?ä , ?_Ko"ƈ(t)AIнO1Pk8Ƥk~"@.>r"7 ߼WI1k_76)*~a/\"( /԰39ShNEAM;%ܚe-zؑLVO c}Oa)oAlpq-Q]eO7ɽp*rƺ7՜,^cL;3-y|}_XbD7\ylyȰ\Ĺr]`5J*tp2<$s~P)iaR;}>>0KgV4AF/́y.Y v"hc.6+KSRdpwpᤄ&ִ^6(_=J[gCՂ``n@}PeKу夨PXG~#ξįl~aa Hia0eAqDQGb8#ſG)*&#< V̮IG{)`HIOv%RWC6HC<:?M>faUͭR<P A%d1!U Lv3ئ.YP$DA蠨bn5JiyC(<$ķRȖD /yC,pe0Tآ`)8@_W/s^l&ۅ$+;UVh] SgT(*%Aߧ[҃3dn_{nV!+OߖY&t)x:]BAZ2]z r a8;e\%Ӳ^8~f59Ȼ8@"dƾrt}eLYGS@;7$ٵ5^­%,7yC5$1.*pSa}PFt-8 [0\u w|A/+A{ /$ސp4Jyk5K~p}I^@z e,|K#osm#=r;z$ E;ER:dbpp:8h`o ˤ6 ꢅvefxh HSh3fC>{-0uB7n Ph^LJNpX)D<Qy4 aI7Ai?KsU0f˔*~܀S`/FoɾςGQ1FMhկ_mH\ ?J-z|8Kcd ]S w?'˚_L#ᠸ{=a(*x %mLPjR p1bBϲ-xZAIRIK ӓ~|e nˑ~'{<;B#G1j[J]ڼoWؑZ/p|lSI@$[:T#8e{ [_ 7*U3CE8DX. =*>ЛN=G:D'` /Lp V]~LËsxmv݂@,e~55&pFZz~tL=r[EG+GA`J FJw_ [ d6:ty _+m}A9xp瞆Gqon#|4WHIajV# Q" JH,Nf) ]'HT/SmBwU [q#wG+2 P![_lan_d!֣kъ뻼s7JE',rOr C*ҷZVo."ϭ#u/@D\'jv;")B1EPe^{8"ì J} mP6!:ʵ@a(0qTA`POV:yV#sW﷏z&m݉9v(>(G N3S][(RQɆ]Ϳ:. 6Ϭ- 7W`T5AUD7E*1)Cy%!j>!1{ 2['&\ۆ\-J752ٌ"82uLHY蟇vt8*. YAr:uƣdAhnЃGo"(<wO~%{7skP`5u~wr3-J+25נg.>!FivW(>BC2[E"Zd/6k8؅v1#[6EG^F&y5HX}2(h Z8c> TK %i#g]€ rќTڳ1|T޻wfw`}YpbXv;dW5Ì8١`BTf~XyN u&=Eh|u!i/S0d!B"C rNr``^j~䋧9#s0rCV:T(Saw!d\׬Ie?uKJWL%1Z2Kp|w>P] ^{$K;]H7'slJ<&]x1A=hlqݨ -l]HK1#֩ʦR(Yu2g6f*nabN(= VͯQ7FJ&H)lzskҊ)-"Z9F\ IDATGd@ LjПA0 ˭%4 ʞ)l ~=`6 bt~NX='gPME4 ;b(_JG"*7|#!q!q*| aLďij E1* rvQfF.𪟣[wxfER~+I p`1ZJ2BA=D(舟E.&gE_ݎ'[gX#r_qL ]mYHET jv~YuI!"( `r;d2. )n! Z3鼓 10Sq.`FwGĎu~GF\5Be=8֏FGJ;"b:w8XMCfd`= =Ct2 #?9~xʟ7<%0NJ[ Ec5 ,&[TK);%)!NP$`APLm8"Fu߀g) QڑF7ԳelyzT:6)p!Q \yO/ @@wγ -sgc.G h}x *(o'h?! !H(3wMQQ$c‏ EO Jmk:)R2#WT!$x4it> ̑A_{YmWv6>$QIٮ\`1Ne jٍ\ aM7Jn4?3@("\w!zz`& c:X= ;,.5oxb+Jn fW RTsZ*5ĠQ%JN͇'ơtTp\R-aeiR(;b J_=-}6 67<Ո|ڌXY42!7':)zN>3˳S<3 0.=qO F(P SASF!4S@(َ;5ZM-X5tIp'Zq%IPm"L$N5sd Jq%n5CHTo2rP932O`QYy2:FF>~ 7“mFrT[n` 9UW|M},g[[0ےMDY1K_ vzAݶ{hAEK5Ӗ(Q8c:X R=nO&Yd'oCb.>Fx79BnC{ՉY6q%\Lsp$s^ATx*Jk; &,5gM+1͖Iy|D$w"H CL)^NO&=H\q/?[dKH+$ӿm;W9K{(|QB2좉.{iM 0 'fT-n+cٌ蹹Q|+I~rV}h1+Iڸ>A&U. X{/߿(_YȢ$Cr%to^D=<'}CĨK=Թ;aeSk ݼzSg˧F'zԬLBhuL&NE:dK~)oy#MUiIv$Mhb%gG" q7 vwBP?R.FtϢ ۴ՙbP!H%FcUĹtqrI}ীYNX`h'sL$DDz9EEP C SeZ6ڼ Dw 4ykmeYC&E*oTIM2!urHmJc!Y"fr IDP9m\tP88;v?*Bg\;`>l*/;h:* PfC=!Dqw(=t wZěd&ì\k"%DL8a)h0Q Deޢb֌R#rwgSS &O~6M:&D$iMظ]S69蕃N$Si\NkLK0CL|[YtTF"ad2Sqj,2tն=H5CC|OTQX30T:D bP$hm)qܸGҘ6 !mfQsJ !G&e;v&}+{m.a(Uj,3_0Ɯz T6&o+m!禽ޮ 8GF*=7l$p`8.M0jkT> @d@Uמi)@N ؝Fj馩[ch U2q+K\B,J4@1`tc}Eɀ̥O. ;U8hZ0*)g3 -=Kye9|~v)+OGT9#Jc=*R8WmAp5ZsgGU>mx9njnl@TE:y6U5SdaE=F*e&1TղB[VO9`|\;2}W,|d@%h~HI")6<>8ӡ(mg O"o`3&ud#EY@Tf'-6 bGKLXQnW'MO7OnIȌݟ$zF&|Wߧ:z71dxKG̹t4 >Y¦ոtm?A>oMznтn3hr}Slru'9 l}jP'}I)k|DPEUClPJz3{. SO=S{*G~+P ā)~hpzM isSaţR!3P>Ò80ik;L8Ǵ6s졮ظμO5eSMF:3IyӬ{F} `7)VQO=*2."M\ W -\e(Q1 X݀ol]O^wDqh5pq8 CxFw_~CŃ]Ok\ą8BK,6 "6 =! $fy7,jlL*hܚP.5ˁRl΍)WMF_)0bH/I*ڟed2:Ú)Fx]9P. :d);j6zAKQh+CpZz k:ߠԚ8\",zGUy''rbsO"?ȽّX [hڡ6Xl0t 1N ;:~,-m%3wҼ߇V/#ك9AusiE%+ڶ px=[50ގݨoӻ#7S2j*QT8R (7*zP)k{ˮ_g܈̌H2IY$Ub(2\pg4hb܀4a(h,5PzTWx9g?{8yU$[$"̌{kַ[5A(F%AmIawT[^<$^>?Ŀ&gkxx#N,Jk$Q"2t$IxT9ù͙|[4}efrcּ^{Z+azA4SD פNrPk,驈WbQ]m1"eNJ$:J%*!6(&%5BPݖ[srΦG?H0>|_&̢J h^0DE5GD?E|G[SG­=\nCظl=ڜب{R,jգq=dw C{w =-{.!TOu@*IoIg]D'5ʧuRP)E\!Hֈ}h Sm-U!SQcxÏ1~{WN\t3#|o{+M!D>,(L TMCd`e8bؘu0ϓ=.'pOW=} p+)Uo^PD{@>:TQ}L0&5d7|q%|B"hA9Dr #W@9+*qA[- #PlNuOދ6/_+AV YP˘3n,ڇlf+d?FUzTaPXXnݿ&}ۭ^ϽO=N9-މ`{X~K"EO(z~ƽfNnv%㸧(dI-A#H^cCʎ$6H -^.Q.ب*-QvŰЄp΢:p |gRI D~8qZp8IZ bD%[aƀ׈8"u bYѻ\P> +hDʁѬ{rA{}O'N}2p]D&.6=b6S|uL.]!NrGĸF./|`͂A`藤n8 "vrd< ʯOYf H}OpVj8kI$I"51I DJ BQ!1-Ò )G:j A xnIQz"}zrOsozTa{Pz9镀 XEҦڞnR^&hUn%A vXcS>%bĵk^ URp\\F껑߯Ë,C{H?Qtcu 63]ș` ?ήOZigײoԷ߁1fϮek洽S]0{U y'8=:4WefG_verIbԀ@m$n=qrgZ/7wޗ,_r)973l[EґɭW -`zgR_0 ܿNX6H7#;+hF,ha׃oUg zDCm/{G-5@O߷N׳'UAX_. [p3FZMe|Uk϶9!\xX~㊍" H}2ph -K׉NLxؼF$#26>/᪹%Ii2Qd]R\7DdS,WQQvv1'{?9^YK@d1U'wT=g]{4rջ|$JYrIRc%^h[k1y?}̯ _f<Ȅc~ l(eq#$*`g:xb k$CTVehnX]Kvр(Y9I^=nO =Hoxwr/uIPC.H'Iy}5,yvBW/qC%Jdyg%f;5\( m4[?\"hfM5ϼw #i+PHEL%Lek.a332ږM`/i@{֬KCϲ.@<^{fу=İoK;tj{2i`*2d2dX<'cbzYCk͢o'~AjD ;bdVKF :S9ţ2w=dyT#R"wG5]kVf6QrUc3J19Ymåv[+ c?V]/PBvVS;]/4dd{UM'H8^A\!ng1aҚ1Zc= oaӻf {]\GQѦ/9d #'E`W; Uw jhŜmd"(px6CҦ o,Un@.K ꜩ2l+>Fr +m^I6TN⥍3tmD+."ɄfTٺꌌy>yڨ+"OYZ;Jtzun5|ݫv}One/%MtJ{9L:lζ7$g0f,nyk9m_3lw"x/1_8>zf? NTʋ6l'cF!=g|}ED5A )L'0ly6FLyV $f 6Z~Zغ,z-*ui= ״qԽrn[_9E /o}(nq=vJTo"mLd|uoK?k[Ϭvkh>o*S33CڒFTJ#qhw3ΤɫǸQ*D1Ʀ6J&[شȹ(}P~Mz>>5:bN13~=ݗﰆ6{DcusH\}8C Q@h1b8L:AE~]@J#SWDz\v wT!F}ݛYo`\pkߚdVD \0)C7.cn$ɲ8ހ wDڋrVo[@ǽw+!~G-ýnxzfϸ_0voxGD]kX A(5&pCXs;n%M%ixOf oH>~QC8Zhl ʰaֺd_߇v̼g~Ϗ8]v`MR^xmLWm2!tT|R,>ӫ(tdoV{ <#o;/ʢ {O}Ov MZGunF%Ǹ4DQiAw7s*R~֘xmTT%Aņσ޻FmwR(b*}MdwN%r2}"tqQíaF]_;é'|] _bO=yY &xzIQuڳ]v<%/4#" ӗ%HζYO^-$Ͽ)yx.HVPWLԧ8~~?E:7yWbV u,Yl#ݕ^@+QɞA!20,< Nۜ<ƲXɠao,#3~`{uB)D>OvbOkh=.~H}a!fDS}gy(|{_  {qBby nkTJᛊqPin #Fyϣ .ż1N5MI#t> 4Rg\ga(mE-SP]f̈SX(xtЈʲ,+M( I>ALر:/.{2OOq=p_=zPo5{WU K^{ U4in2'*z6^2?] 84wd8*Ұ&n Ɗa ^BE)3Acj2@:橀DˢL]vޢxS\$DE#J"&w_z2=a?niEn뽫?]`/4>O%&Ȥd]ةk+܃Ηf+~0*.k,ª܀LPtQĖ97ܙ£"&;~p'Y|CY䲈He`( r&Ǹ&7tA#tFm5V{%ڮ+I/oz׆U_6tf%{&Mζ>A< n{zY{KZ u4yV͆TP~BSNSSSts(.~xyX^|ׇXnߎ2B&ZX-i9yT*(PW463G*iO^/?[hكvO{kL׭ce6 X"ë&eGK~z_)$~ n$u CbЅ!5c9ąP $1`*6c1Qx`+eQأN6,n`(/p e.]1!hn]z-)-9(B%e^<$.q͔ˑh8]d6+~3!PHp+Y!0#AS〤b`FHа X[UL$t̝ȴhw,sUo -3v=>Zy| m&T";>n5먌T$qb %,h>ᤃ[G OyRA=߷('"*Rg| \)"=F3|\R VlZ9 $\_| %[&FeE8CVa҄j$G2C=#VBEE聁AީVBٮ9hF9j,݃tUq YےU`.6s*d턕uh$LMRV~d]5~,r:,ds/ib-̗p<+YPm7t˱&rg˯}܃?)^T[3K[1b+fxD$*H#|H"hõEe>pұeA/WԴy#]I09OWp>IAR z#<貭}sM~F\8v*ρe1\٪.Br=.d\m.m:Fq2hfJ[pxJ"eր_!? >n%kM5]5@ FH cb Hiƶ_R#LB޸ؖA"|}˘90yT+[-6 iZHVicn)!џ8~D5QϷXzdI bY6i[| {Pdsau-P)6dƖ) ,|b;q!RD9Gt[փv4mHElȩ/OGo -C/qAc +G^ńcn? 9Æ}.ͻK"yZ$,YXvKg/Ѧ۩Ė|t3 L9BA@VwLS?A /{s2Hg*h#@2vTgUEG:#umq㋣Hr%6]NX7>9zH9_Y1llk˸su^ L)W%ZJo?/(ZA)>mN&T`;|1uMJՓ_FveT1|k9(}mmmw)bNr-l.Sj,DuILKZ290D^`~[%`[h'!QILDy3ӄk0:o;[ɬMdHzR~ހm\I,p/,InM';e]@EuǤaJpfE?FABA#Li;׮L(Dzm(Xo]dC>Id)Bm(|utb;RfMBWif[aDbI5LL"#WB"m`~>f"ѐ#1E!lD5)ZD S [Uz'a"BKbLxї0G9R.͊K-W jGe%䋹3FRtt0z\ԐTTCK"ȥfS5 CDG$,C:%!mI xbd 6zoS(& M0 Zp(n,7ޙ& Ej@^Knn%"r˩SX G&c Af \^ۓq/X_P}c" J6$ MO+D8!;F }HIftp-R278w* œh!Z/i1|el9} nLmlq7B f/A~JT$K$rլi%æɆQbJ+t&1N&g? "~q"|ʢ7+D9Iݿa",+ bt(Qʒ8_D$(j)տ(it<_Ls41dQfih y!U2$x;t)"oa}7+fO: uˠ8S")])Sˁ8,I\#eCfD  :DĆ[ccGGbKDG[!//ox0Ӊ r ]@HG4_ 7xLP[%IHNqW6y!>FG$ 嫗 !`T~"sC\sh]@$@ I-qC5!=Rg\u.Fc/b!B:W$Cytua MŽjc|a6$䦠A%D$ݻH &jIiK+dZ+[Lsq 8lj[i`򻑻={wI[l_/zHۖсBUzy!5Z+b줲HA!V8qtYlE.RA>!,@|D}BU0DFITcHY!9)c|$9E:0Bh^y]@ -#4% Prcb$P<ĈrA,uZU[ b[ꨒ[(`l{.}t²n7~L+@; m9(h5Cv`q6_~4K$2ORHL#ߋHun̼+"\")B\%!V mZ̖WHAV~`M3A8Sp!RlI#"nC43oX6 ңj:DХZ0BRAI V/:䊠R-8˳ahc- l^>%b9t7  |muk=. Bǡ@!VU"E$EO5J[B$D π$r0BDKRsነh}iWHD-޷$Jwez,bbԁ'tZR ɓ.N6D$ba`X66UwhWQ5i%5QT( I@ŀ'E@;H뎁hmIqS:0zT/x6ķB#i³DVh"{W0,Fu=4! IzD 2#I(a@ֈT`]Q r8@1 45ǿ-/ f*65Xd_Md'h 4]M+hAmX*`MVzK9QLjpF iE AL8)P2 1BDGL=!8 B:HZ.S`(<ϭgHXE}*q$»YqkDyl%oa~(OHn29H2SJuC-" Hb ɐ҈ֈX$XTjeĸB9"-\ ꊮ 2 W.9 ^JdD&^b7-@(`Z+Rh1Ĺp bTX"CU\Tjh9E0`[')p1113Z:ʣgSyw B`ã]G^^D#ljzKدO$-ml [ɪ[#Q%Jhb"2uy*kBܐ n+65 X|CT[-*8AdVy>Չs |+YZɠ Nֹ41(")R_PϘ TlXWu`hb$6 LD#H"TP#h7 X]F=cc٨:x Ҵy.PDl%bxrԌ|+ZbJx@XL(3I y #ӳbO_I .3_ ЄJqBe*1fVT~Ct;)QW$QSSb4"PFR!"#PQ-J[p-Q6(Bd86DљuG1XǞL89$J ͲESLrp+ùK ]>-R}¨^L`βLIDATf#YtVCܵ* L~#qe뺊t*c$ny48){ST0^U`u2x[A@$iQ1GDIy3[$Am)Z0#9&rz,:ȟSIE$qݷϗca#x|GVPjV!Ji %Qv O_xWM|x.-#As PM}:H0-rZ'@ xeexTOY0iO"'1, "x-+ū +o8 t׆ M0J6VUxohQq#JFte>*;hfYY[sld~b~yXi'|~WW~&d|80b-tY|g0?M? :TY+J`WJ1z Y|Ud3iVKGn6ǑRwߊ4kcY^W|yW_}g㿩tmIENDB`robocode/robocode/resources/images/explosion/explosion1-16.png0000644000175000017500000000031110205417702023763 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME$5VIDATx1 Om o>IENDB`robocode/robocode/resources/images/explosion/explosion2-62.png0000644000175000017500000010017110205417702023772 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME&"ɋ IDATxļُmWrXk}<9޼/gY˪Qp7v_Bn@ ~ B~1` Ȁ_ЅeYPdUySϴ^Ca^RyN}^_:¯e qǯh]dm/&{ 70^K5[7w_<ߟ>ό[ !_/k쵯oM웼?ѿo}nnzf ܺ8|\)w:pƳ›;w?5pٚo|.\7"k_ o{) /5a=t-?}恇7(_8c|G/ӽq8]9͗w yW]a8۠<.L~f#0)ܾ\u|Go{*+'I8O²8oyw nb_'~#F9|Y |R|L7fcoLa?C`q?bVfZtX?}0'72oozOߪ\'a/ ;E *(;;V.4FE(VByzS{#W8:懛\9Y9*[{㹶p{Ըja8.5)ܪndc髎] eݯ|̀38yfW3?F1A(Wϕ7>j7vɻw>~8/5#5ksO>Q\]8t8\X] Bi)X*6l'a"9Ƌ_kmWc?I+G:R"P߬QҐy07/̇;W8= A×v>{EtWpו!{es¸Xg3[\a?'KMnD@c)$[V{f$ w'}گvʋ &A9UzW8^9J8΂#Gcй%Za5!, #D3gv:W#뛜-͕cY?h}bO{VCe)#;7nxp󧅷64l_bʯ#Ѣ<{uO+Gk\(M"+LBO]gG8HhSW߾ > $A^#8O}]|ue.]W&c2(gEG([K!!ۖ!KnF!#)Sfg1{QICWS2D LuB#9a }8÷K켰P#u&5Eqg WNE?ok|)MRvxnc+Eg'9RtPYdC#(o=$#$8p]OQ.|Pܱ3S>{a1D“DP;ރW/ ʭ )OGŶ8t *ck?#ŧp38{h53^I-worE1vcǙ59^CyK0gs\D6ή\ȩGdy5) "\h4j2H qA)cNw WTC,H7Džj.H!_QEQrQ|!B5\hVXȖ8Qޑ܈"랫gw tmhyK )P!zHksI r! p.1hlĘD&Ww x۸s7~glB 1ཡd7• 2t[و? .){ cJ8'Pe\`ĆaO#Q2C)}J`#~9Eu-eHy$ Lޅr%F&MpMIo kqcqXpo-0`1ؗI+ ܊G3gl<*]{^=wtNrJ!G,[H&HRb4)>ЗO} xb{dPSPGrP7(~ܜ15uXFFT"lPse@BD}! !`%1NOi!e#by 1ѧ <$1.0ZvW| V)j2Mq1Rb[]0:,˿N [_濖ŽҜ yhk9y֎3{ʷyyN ;Dlǘ#tE_ƌ0$8De6jBE:Ec`pZR3$H$-ŶK)* pN9PGDgc}C2\0 ,p%,5yYSzAҴ2Z 3>) CSHOΈn@91H^Lc Gdn7Q_mgQN&9Li>914K -ȦGtY2Z`n0*h^bzSb٦պZ!%BWz2 P7`8r3ml3$y1 -8O W^Zr>1k=W M%j ڒ,vuRUׂقbDFa=8!A(eIQ0hH uaY kM(}WNV|{c$*- Z;"Q^dA/,;īD]z!>]F +T %lT>~ bl1pgk-!lvFp0~)Ҵ8;ϰ2GܘPIvwqӌʷ@f\+|7~V0o_6-G9o,ٖ}D8Eʛd d8=aȉFROHyu/0m<[;!_awexjR}wh N![G{SbAue8Grĸ(cq *?^){IL /X+Hߠ Y S>1.mk'0LFQp`ZF^8H:c~š=}(UF-J-FɺFr3|}OD3#8`1@_QwJʉfV~`o֔Fj[o c)ZS;s13r3=xvx%t44npav/tZt&RAqݱ2(Ǎ6tZ.tʔ]ߧxRyH1K34P ]5iM9 2OEc`[*Ƃe*4!e^/lWJM9mҸ>~j"2/qpv4u[x)RdJ{4v#@6!)L#S0V0IOVXq8ʈk/b[x4~7H主: ٦b~jI7T Yࡻ8#/XU6yݵzgӰ0#422[e`lY1hX07hs|O=bD nry椸9r*P(p*q/ \dX,FbDa3dv[8ԶA8AQȥ:(Dk4l(ۘ$^ADȥL?C}|yk:x)-\4 R)2EUXw8B(1ރ+[Ҏ@35Ƴ7$X\ }dau#u`:5swAh4'\B$qxޫVMO#1m5ڪY!!.?Qy-TΉ>HWYi+D+(V.ZďA2YN{ZF::86NܣdȮA?eMqGPCӈT J˴U<2Ĥ qw1"JFLaXBҘ⾍ّ1e:e$28-_S }UĪ b`$-3DmkJ*b&vrfVPmN%r WF+׌_!٭@arR ;_8k jClSwTYEe-Ksb"aЌ s59W<Ǭl̓4O0{ & p}k`aϵ&pk0}BP C *Xtƃ){~VS`Tru!$ޘ+ǐ7qk\`[*#و{ga-KF22} s{@gaM FHZdJH.hKDz?8K/ʬa }&uCTpo 0NЄhdFQ'#CBO1q=( Vsb ,\iv]52<6Ub{Kx mZ@ؐ \U $ Mx nI8D5W IDATïsa>K. Q[-' c!-uR*Q֨EP% ]#kclw>q3{TVoJnXsqJw DwzP: "Y|%u^c J0-AyC:FqRĝlU]Wgʦ|V#]\kV7Zl*dVR=~|e$£Sǚ!WpUު~Į7\6*hb 'd0Gl9yF##Fx<@C:7C KG$R$"ڃ90J z/bҘw.s+0F#:G,"nڈl'F.-V?/8Df%,<'0 <4!j#զ65K=i*Cuӊn݃Ք`k k8N5WS~OLҬ^gj*a~UDQ9O[:Ҡ'a[^{+Qs <7Ə2U#?\u@B.ha 5[eߤm˔r3cFeILS1ഃnHY .*w2LO@m;f !N0WRD~PJU2WB|k${-RgLP3)JKrTZ;zZEYQ h1 eFT$tJ捄-262J\I*" pn ?z$ݶ saY:GقftE 4$pFI6m (6FN=AR9!r7}&8M m06"x7&0•ULƤp bjfdRkM&jf7H25[VwoM ADM )H|u06"*םoJӾʋV@n~+cNA]2I1^ø0Fh/e&p`cG+F=јLzVDwQ=C8/A[5+-%.q` M"99eXɶYEǖ.$UNLiSHhJAjZkE.WKE7x]{ MݮV $hlxڍAUm~j*KjyW6٪SSR3[uhp j:Eڼ(Qq&υ -i?}x$1;am="dSX,/X*,΍Qf3s]GccH H8>y &G"!vؐYrSA}@L蝣+HiqjtʄI[{E fe(MɨT4DP"\Tt M|VoCmEO6b`&ޤ JVfc}im;_ 0cʦe:84'Pb=Yp81 j?az:kx3c6.܈F;F13½h}fi! ǔ 1ߨm ݔ;N g=Y200ā40tJ4b(7r8,a QH2`R;{#_kaטH88jJg7M n]<>_u3Ҙ6ȡu62״7(%u"BJ`rk^8Xёl>\+ՄtO.‡k˅L/+q@8h`Ȏ3v$$ZD{tY-Mw`yE>a.pxET g&ZoEºWH- +ߢ;eӖYkPO:|zӦoJ͔Cz'ZwC%iW  jU|<*q4؜$j6f(nOu%ג+82*":Rqx)3ZmlBȟIɪCAAO"@e9ʄJ<1Y0DN{]dVSaVa<<9cףC9f1Tf<<< ;^6tl()&ІlPN6 \:bha 6Q_ϝJ6xJFU g @2Hvٛ=I\g~˽7"2r7!3y_ 3Γ!=MO2e&Y$ ntwvw?G~$4 ˬp|;2!t1ɶ gyk\}%|cS>)77.Nۿ2B‹Vv'Re1YANQ)641>1zJˉ ,'Ֆa& Tqsm }6_!g{%Ea>9\k PTt3xm&哹M8#tIsk\F"cXPJ+C6 B tk݂M|OH !Aei]:6 7s=]ޢaAεm(,kua Cω،֍3' gjI_k;sBIb Vj d)byՒ.N'XyF vFD85\=U핿΀B?[x_z\:ҙhr;frֆv3%nT["|{to%ȩ Ge%H @{:Lz yE =kAV Q`j3}]9_q.!U vcv$bTifJC~28qheM4*cI.U+ ?^1~}__~^;,Recp ONGGZnn&aÏX ^ EԲ\vܚf@vpDNY2{V,}:ǧ9^8ס &푲ye8F\܀K-R #°@!֪fdDrOpy64DR]N霌:ݢs7VRSM;**xj 6sY^5Qk˲iӚ( +唣j5&wazǬxo"8q谩M%0u t N#$>DtI-g RsCh6Ȯ'̵˘9G$RUi9);58)cֈ ,KgLރ&Ǜ\ ICm \_783y m8?rXnz~YC&mgVגqjwc5p3N~[8|`g`e]5ȢX S,^"#Tmk:nF B|Av=@,g71GD8BX={M_w9)\QBOJH_ !`Kۑt! ^OF'sh`# -Z2Mhr/ 2a| 8ct[yEUo 2o_wrfPjf_l61(L,s#sY+Nbq]9`wLߤ ,%H13No{' ۝/c3m3-~CtCoqڼiWt}TŻĠ$9e3 筲n=ա >g 8A\q+óx?%9EsԣG٘g~iqA̬qsZJQ*'h$Ul@DZecc CmuvuPOrWBM493M|v=oR|^*wHXȳ9s}Ad&=)4Hz'&yĖء׺ߐƿz)[`dSN \S<6sv>)٢¢s’ơ;Gs0Rضe/T8 0\:R0q+=f-EF ,1{c;MDAkp')1CnZ\Ɓ4E*SnNԪ{ϢSJxHjfkB6^0#XyJWi˲$n,您_Aq_"$pT7\+^baoh@ƽ p1Lk}_Tvl0J͖[tc)7qޱLJ i".8$K zT"nCp# zd_ШeAՍ{}bEyD5ާ+76VO^f?Txcjۦ#)Z#EXik/W=2s ;d㡡uƤNgݎdϘfZa_&TRo(o'a= 7Bṿa K?Q3c/&9>wز Ttu 8BhrX$Y"%ms#N !,Jɞ'S%]p#A1x4!l9\$`E' E<Ԭ?J"JfyW|T =]_ӛTS2-q.%0M4R@H͢p2%dw4$ZKg GX yv\+|YLpϑ R Og7:VdFw _!l, .7Ӛ뱆eO#B[t#tt1=" T8|c`*wؤd/p%Beb4`PPN(5>@(_ -OX22fĮZT!@K:|2rM8Ot 4w!? ”!QK {ܡ婞UorYCGţj( wW^ Cm {!bij="Q]d+'t>r7pgQ$*Q\MnQ}oRiCr[Ķ80Q ,qڡ/{%&wWxk]xJp(?_Mk6FGaB c涫i$2  ;V!8ED e\ 8AiaM*g4AX5_qDžxP?dHv2G[yynCO\dʑ38<@})^wj5N#6z9fW XyubZ&P'lD?v˞aOWWp|׸ ^Y #؞I +T^+8q DML-m1ƭx75cx94|aj 8lp92%iĤ 1s˦2o/z1(;l)XK%(_Rhx_-j95\,ԦθΕAlUhk8\vGd$'m$7#f$ Sx*,dQ.񽿟vy??[Up ueᕋ^Vs,NXdC?:DzxgWʁFj(|GTw]"#.%/UʥtEpos֞{wV%)?G9I89Otה ]O# cY۶VvWkT pz7MC W1zJihx}}憎*x&J@sؕtMNL.%h#Wu #.*h|iSq/$uC",qlH!SG%PUe4cWoa8cVz瀈Gg@p,K6lsfRϕoLʝXO3:ca '} M0 #I!Qw5>dEHч8DL7(Ɵ?`/ g a*u}$BhbnA.rTrF&v>Req 5;}G7B- K O8_i-a. CWHz٧o'vBamTۣ9L9cJN౒05QG h=\ )[ +=NGpO8bw7du(uGjA&Qc]]%rlƙgѪ.0d= 5'.Z6ӿ?DHxAf+B@Zq#?d4(H;l:5Ϩ&?Ex׍}Ǖ#'t‹'8RB_/"8"sJ™2 ;G"FfDJ5[*L#\tp{Ou)H ȶaZ_L~v̳sg7ߢenUp;[­ ik0J`$h5=Lk&ҩ"s_s'o ph A2c>tKg,Dz&OtYn;x[1??:|ψ _,sOfdyYDk &脱wcˈcЉEE u -]B/LޑgچKD:LBWCL&W2 8r҃?DAQq.AY"$i$;POhQ0ۿ*Rq>往ʡGu~٢}b_|(59e Fkx]4Wu56IGg8Ҥƒ`۫FA>y]⛆/Uxg93 p3p[;DX/ :hbc }&!͓u02'aSJ|DIgt#z!Ӂ gAh+:.rFS=%3Yu1͞ Y-$hD$;WdlIK,gw\Lu0t<,jeՃ~g=qwB 0hC,VUD_bPlt=C]Hx,G2нr:\AlBeAeGDʳc!JI@4_:l N((޽CЉ}O ȤYxVY!8tOiظZywtKnb6˙2&A0qH~OkyT$ϹyC:qfj.bk*CU>3R̘ʊFШނ@릞eSyem1ݟ!S:h\C똘i^ CRv 0qD79~@yE 0ѕ JKƲMR8џKoO\u8  a NI\V`gcĎmh/oxa>R=-|m.P,9&QϤVF8GKĹ7l=rwpqX2-*\‘\¨tC|gL Σ+*ڌⷮyUhy&kq0p!5 ߰iw /GlN8FLJASe 4 ť(ʺ]q Â&?:,r`\x;"c|$#Dz4u;};GhҌ!)Gmkf%v-0p\Ẇo/?WV97Γ}`opnOGzWqjh5] n̈rI&Ĉ䚼Rh&`<Gî}<1?( $2CȄ`\ x"UƼ* I m9h+[qCvx{ym35M&/5|)xIWpg` )̲h 4Qŋ"/!rMoˢx9M-4s82&,/P͛H~ c snwu.p e> ޹bT n7;]ϑ*~9%_ާ?A1lHS'C?Bq(rӀ3^CB LN@H9%bh Q%yi2X:f3FDk]'h :9} Ѷ<ۉ+@~.mc;n*p^%|2u&P K4ҵlr';&\z i^'4)d"^85XJr֗08Fr-#nH8sϬɖfnN&B[/qwBdf1W qZ<%c7YŷYeNw9!n'2G0RˀIA21ڳ́A "-øxP:/arkB@ٍeAv@q!GB<'Z`ۼ<0!Oc)Of&bH]$/4W롘V7FuV:K5Kx' K_5Cŵ+?%y| ?  ?/&fۈWNfO9 xIDAT!g(_a3ܞbKts;Td6h<)օADjf71 M\PlC5/Yz BUq"Cc8fۿmp{U>O!6#Bca5[+'sJfVyTN|_{ryql _it$fz 傱lM;:뙧2rߥ8>y4w׫-|?#1edZ֌ TX0lB ;I!CxW4`!,Q5SV1@TbBdb^̀ x#\COg*OiLSTHdHMg$O"&+I歚<~nJ r-ra p-'+y,L%mRSh7yi0uI"i,Ge*OՊc I)c/M,R(x#dLL$jyaowMh$u\T 6n+$~C[kΉbҠuEVѦIZ/Ώ-:J/,% 2P2·%B9ćy8g3I}- gxXM3f4SWo^L&yaЦ-xEE9&edn9 |kZj/ek _&p^ZJ{֗FUy6yd) *yR r!-6ۘܧ &p7;ps?>2qmG#Vk9YB~с!kQG)ϻw='xhd4-/yZ` Cfb>@uBtrP϶X*S'YAv0 oiQ z젗n+x/}*luUbίPc/W+Nn?./;5ԴQ<M9MM/sḇw !$/7?lzϲ + ?CH+|6BKn c4փe[ ):^\2M-LxL/kKiDCyEwX^2iMNɧ 6NP 0^YjU#S^Wߦ`2pq X 2I) )øNp^г*gid^ F+$_q081 !vy:O2A(ij ” (c*\M'{Y.~s5DWP~gpAT)N;pygvI ;2;@Iq|߻pNkƲw;D)l?%'H,yEJ{0PleU-bR7؀"!3qƵY1]gkKƼG]WX*whʍ-ϷҼ Jwҗk0':rE!:l<:+}Kd&SOot Mꩫ9M`eh- kFmG[>sgF/Eh <ZyGO“MɁ.`45׹5i4Sk/!1:/'>:-DӀ H%8Ӽ_dε,KrE '4xU8+T1-nuӽ"_Mq%4IAq:ɤ\~֯q KD=иel29X  ͹~SZKfcmxkf{~CXRw*F+J#^4- Q)pIT>!p9%\2_phSBn"rK5gdtwx|=C*^Q1|mVS_ .AmHqs08{֗ܿ4L ! X+|I0 { ) _2q^y="_R}d?e/X|37ƑF>?X>Ҝ 7wG'Q6 e@ixp5seN52("= iB4aSQ.LWbɪ;e{(tN:p}Ɏ7E~7-8߀}K;r9$7P?"'P!)4Acea cdS:o~ %?M b}^&|dAϜd=hR^J\GD3S ;FpJq1y#wV=\MZ/?U!(bI+*rkX8#!rZL^UVw }w _MŧW2$ +n 7>E6r#[_/}hKqB#S$pvZiY7LDCrDِc<G@Z5Ozap;{az\-A *͏<1|Ck=4S#>[r+W->efrF0'W 1#ȜlXD*urr#$O'G,[TΐEg$yFO zl[։&Z?}U,‡w_?PbWNP׻.FrE]cC!9ߢQubMܨ2Qym$|C&#.xePe: " &BI K8m$FMDoc25gXuF\vCW Ɯd|TZ2J&}GU ^>"bjªΪX /0'l52 BB)};}s q<#9ſ6,یn2_?-93ץ82lc>3\aI?.!9qvB8H@h看O2!+ < g&ڮ\ P-łbSTZڒ a/r. DdhK$-L'lhS܇[0W |ENQ3y0h00Y%CumiN" !TEiM@Idw ]akۮen!˚NlG5MG^=aNo_ԝӄPӟϏ> 1)i6dS$Y )  *nd+֡j QAblu]I?Yr&PpF a@hP8G!2RhHz9"RAݾG3<نD1uM`J!EʌAȧ !Wң8"6 VmXؐe󋎡v |q_5DX߬Ixd³2dʨC_#;Dfd6ΆdB(PB3 bf(%cZCn 8-J#h*EB TeM  H#)fmGG2yT{["qT,͐1)hd+ȣ;%{~<>36X625øOHt⠥I{Q  8-9t%wxh ^KzHdX]@ZX-wг^P4΍hGGG#*'·w3~J7pz1Zg!ϕ֨&(rj2#s :\"$%CBPdשёr 01D#Ƣ'Cū碅ٲh7=0@ ݡ!؜3tJ-e\ 9hhk mQIo@| 68Ac@ATPP`-&_s#ٶÜh%N`VT&!nk m}ظ{ .Xv44L* 3|SGDjFH#A92,X.qT> zGqsQ7 ]%"J dD2N [ y0ğT4z `>eć k430Ԍ 6iF!v…v1EUlh-f-A6͘U 0>AB.Q9#xsz]x r|M?liec9VLVJD~>sAl6vlLLv-O/MRX@Nzsꃂ'~3焱Ltť*X"F"N EץI9]r.z1g  UjMلd-ZoP{1{nK,Fـ-C>A 1/A&7nPxxBGRz'$l[h}GZ#DBԩHRsb8%57ΐ#n чyN'T=3Ww}U榬cdFH dúXB^Σhtktm,=U 10 Go4QȵӚI S\Jm\FhPT~Q{{7XWdTzEŒ=ZZ׾_o1!U~H+_G=T5IqeddN ! lϸ>w{ρ 2C[Ⱥ$!#?cL=ę7NvhUhVJ՞`?"]ON; >p%|j•}Skְ )oʳv3rՙGn9'MuF.XȳOIԲ!鎙 XIZ+ٔ H@§Ιc\ g ";#Sje\!{DU4ɶ _ RӒΌ%>o"+ԾxN E2fl;ΙRIaas  y8cpJ=i41ږ1 i9jd?y:a9B_H۔hz}9;^('ӹ`<ޣHAIcưaߞ:?'{|>7v 5 1vt椮g8acl+D1Ez \Gl^4B+Dg0+ B۩)*$.v11H8>qsQB8Z7>N βM5uԁUp]HFg@нwsFkR eQ)O\80HúK0VȚb=؎6&;b=%-2r1Zz;T& !< iG]0f9qhPVKg6 ,|?W@ i|\W(Kw` YJ_y ˇ F [dl3Z ;nGܐہlh= sHyC])ul:4e<FuRJػX:#9,)3`*ϯٔ NJ2Ozeg|ߦt_JAx[r5:'u:}/,ei2rܞy&_x vtY:x»sb/8!jF-qE=r\Ki:,mB q$In(-*Yv .v8hw#]GYo3fXgna 59![ )\ @Z;!djv62vWTofD&L?8ܮ_}='zze(򊙔zuʛ8O/[(p|^beF,lfIEa5jRRꊼ~ݹ#<*<숾 U={͎gF0pgFWe2nWJraHV6&,jb˒kMxfRq~`| p~&%x0q0^NMp]M#(A߇Jy~Uٻ*gp%WlAmSCfEK6G(SJĴ sf !r+ 43ZdiIfl亏*^Y;?,/rMeet.4U@4K$&oR=]5@ԑ Sxo"=+,_}ϝO'^_fxDG >W 𨢻Yfx 5 f͜`sd\tz{E-e'{HGPBFDZ[nY2&Q,?2h/񛹱n)$l~ꈎu UFNsC|D@4=!60rM,/Y&!հ zeF@3IENDB`robocode/robocode/resources/images/explosion/explosion2-31.png0000644000175000017500000002060410205417702023770 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%)m IDATx[]yo:C"R8VlIc9NC$ (w?-h>j"C h6n&X&QùϜ9}]kaCҶm9&ؘÙs^o}0 30 30 30 30 30 30 30 30 30 30 30 30/%|sܟ7SJx^\xkMfY&SC{ee'9_{v\l::+WJh/K'yQ)Z#RO?FҊwg^^|@¦"%%rEyu|gPİ֙F@<GGo*BYMTx$c%Ðq#a~cMFgQ ~vO$y䒦<Ÿi0ID GO$WirA |Q`j r8 C2oc^JvV''ɷD;eɍK1h:޿j:vF ^i4F(`na5Ҹ/ xD:$AlsP\8"bCe+M0'R~aoײ}Vscw,^|ޖܾf v,snb}"u$.p[Wo"dnaMim|M5iB4 ?t+86_ ^0l-KKa/,/  5pxmKx2 JB=l 4 AʷiC뚓9Al Zs̓#c>_OA 6 6Հ1"w !@Yґ,^`U  mb9 K N"y21BYdy b簶`;_@n-0slNbmHSa&BQr ~L3Kt`GQ2!;$ 猵5498`>Z U_!_f\[q^4 1 i1zA iFhzG%^<G)(PNK&o\źΑg9 Or (@y#zHMky-¹)]Z*tweK4?Ay_g\d5 3$ $Z|B8A.FԠQMH5Vp l pLi )E :F3ƙ gù95i|lnbo9iAe%Khy AAg/ͫfZ4ZݏBj+u`ы1q-X[V> ^ |nBˇr , Kq9 Ӏ4s$9dԛPxS\E`Vi&, =KakS%i$-. ﲗBBKsk4<\BBV9h#4**#X-/bM!O qI$@(J:6  7-Õ7B?śXX NΞLYHȽQZ;z+O)H F)xPex +Rh~ud>, CRdxV}6k)kg/"" s n@jk>A[{fxޝd. /襧(u;1ك\B5 ,-Sj7lWBE^]ڃ~ih+@T%V% S4:1x }B:M.cen1A +5h J '+CVZi*B^%ȫ*"dgE$qpuss~d=^ b_a~]s^ Nz\F#y/b^C_GN=};wo#D7'2O*UFӚ51ۄW?&cMAұD_pUc|aD4`#'cAD]ϑ$ n%sJב|,O_k,Ē:*Vds H_3W|X ^Q<~>D2ɇ^݇Ӱw ޹pe`T[!pXs\]8*v?qx򰮎+42KQ^OKj)*, ])NH^EFj=Zk"ȣ{?[Wp|.u5S"4O2!J}$"#&,!lUU44`SWJEpūdWo#S,[kq+x]8X``8cG^&N` ^~VY邮H9I!v~؁|:$w N2N[n\pʱYKkPvpא2"T4HE cr՘꧃&36JLmR"H~<YysUɽA<"Y+N*=q5O 0|hiГIb C1Tܩ@2t ap障3DH@<#w>= 3  @m]bߏ&Jwŕ!`(18`b[)҂pbֺ{j[ I)|%IC%N\ޯRn^Q5rZVHD@DSni@!_4 ;?68|]q9{#H87] VxIE\-wk (ROVh/Wag}3)s)ab v|jA낓2-yHUW+U%%H<>LbytQiwf}Beis*X)N}VH'8HTbkhڐ!B snv4RbhC 7="G|^ 7S_@K8gO"ĸ1jD='M'DP\^O&H*Х-oБ8 W0rz#8~ vQw.v)~mW0IM[$f|P|X lRbSFA0CπhOpy#|/3>>;JbxCz!>Ϫ.)O=B+1FC;Q0rKW˟o(p|[1GӈY#ex@Q'~ )ZRe]9n E$q;l2X3q59֢Pbr 5%07DMq2_ ܮ~TضtU+B$b 9rwŸls+!: S0`"lnл |TF& PZY@&#8K^9v))k(Ƈf;7Drco[v&pfN0FJaH vjrf$i#%U(I'L-98LAȷB6P7;v}AuNzB(+h%Vj\jCkr\+m6${.s5_#MNAݧ9Ⱦl2TVWҋ I*ݠS+@5f ]e-*g1_كjp0GCMk['?x^]J:W9^Շ L )Q51,G[\ PȼSwQSuuO0%g{ba$#>a?~ 14yX>݆ј`JZE)>7p!$% 3KG i 02 Mdv:h)֓2FV>wQ?^=jiţZO47 Oyq5.Oܮ]H~p0e!w4yTU'zF#@AęӜ/\n0LaP+:]?qIGϣwko"θⓝCG<.AԨL'K~L!JݢpA}ڧ'*7?.#^tPpC5_ eZA9t^ ,n)C7zV][2+ILѮݯLD8G7Xl$wwQ.vo OrniWl$$>hZQ Ne}NEO%'~x|\;wFEN~l`*xy@ꕝé?Π7AbbBo = {}" =peg=\n:v8% ƚ!$ [izQI^(/]ˣ<$6HK˰q~ XmCwCp4971sTZ!΁ 3]<NnĉM|CZHa6V%O)׭8<}rcp9Qh鄥o @-i1j#e`4UԪ;_7B.A+@w\Ċ.5t+2{Hlqዌ/ySZBn@h '5 ڻ1XPbvfui FsCp!Gs= 'Zt#'C$KNWsw>THM+ ޤ(:S! tz9MaE<  .?1N\~k4}.X58`C[HK!Nun@aZ528\{:(x 5lZax*MH\?YP(a6BF]!I!>Vnxz"oTq~DK- N@ $c8@Z@~35g}o"!  1ܡ[&a1مw8t׮AAYAz(w\/ yiX'2a%H(_ylIԞEznF3{H1> * 2CNjC稙!2u6mا(vP1ZBˋԳ EFTO$=1nR <&~No` 7gV,r\=%Lr!<,>H$wD" DXsEw&:{s8?Šs%b<]sHe,J;B;hW5Ʀ}]_f.̥#1]aXp#a 36 ~g>@W3A BJ<0^s#au=D1Ң0XrK!58{JDإf),ہiIc ȴL&irI$l;âM01=.{dRQ bN%n naX}UZJ8bƩyps\\ܮkFwq!ί#M TDVDh Ǻ]F"1*i He@5(&$iVG/e^}aTȞb=!)BAZrMGW7-oi{ftWUEe'Aa@J2dH 1*)qBS2㴗>p.;G{Z]0Hs.rt_ _!1:jQ\ q5p6ܨ;5xRӠSOG$X_\.0/ SCe|t{Xy 2 ]j3) ޿ ;[$sF <Ӥ>r;V?/ɛykMbb[)^O'c ,tYN%Ό?g\8 \W\|//?IDATZy(\J^k4^,!U:'9i[?Y9?xL_Ųݕ,]jx쓪{=)CsN)OrrvUE*/:@s }Al<?g-Xuz] Up~FcUɥNG3XO/ߝafafafafafafafafafafafaf8(T 2IENDB`robocode/robocode/resources/images/explosion/explosion1-12.png0000644000175000017500000006173710205417702024002 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME$1ġ IDATx˲dǑ{ZVU lv:T[nj00ivx~5+p@hluP3sĪByi񘲬lge\+/ oS>={&_yӧ9'|'_[?sk7HWfJ6f1ۿ7ΰ;b#VgX/]Ѧ\\X^/|,9j$ǒLϏm'coMI۷#K:5?+ѾϞ ;#ƶ8 Gi+\P;@]$ֆyLӏ /,x>V|<{iŘru#\r_qդjI7Xc=A2G<{뻞7 )n?7va:TpX u+j/`ZR 0"J:A,e]yq(w[N_^ׇ wyeVV[fْl||+?O^c]فW3tO/Ɨk???~/~8~p7 ͩaBCB/Bx!h S*^c80ۂ64ֹ>w>Q^xvg<>`\_&tVGs_mpy NVUol/y6'?$.]b'{JY%y^~}]`;ValC/4rGϠ7P,ys#Tmv6Ql̨a@)'I#Qta^3wΝgߟ}wF;QJ2=R|-XC\f`T5Z0{MDg>llK6ȗ:HEtG/CK(Ԃ|ҹ;n$&R=g&kt[YnS<!'HQ@ ?w+˘x]L~5JW‘G"I$CIKǀU36*a#`bx:R*J Xv\F )rf ΋kgĵTҍNDd]z$&LiBLmK KrYT8!T&X9T((Nfۂ:"әx]c56rC߯'&Y;\(7v#f:5btldcXuh!HVs (N팾llŸqcS#p-0#bj_\_N |*eU:lNܹ"T:2+=g![BƸM:ʙ(+7.?\N 32_Ip~BNPRx) W6vn0}D]JjFKCP$*D+JmB;\zdVO}qv=$+Z7B*̗,ꓕWC*2)ǩ!"T2Λ]P]'zOI JY;ukEJi3䁜(jRhfhtT-Lp6E ;ùG/a0}' a|k{ˁxBiהÑG̐35i3H#^);B#1 c (wa L5`bD#6H%D ^(W*E FGDԘ3^hJ4倰 tCŐVp9 1BF㡃6SK VKdRyk>{|B_d G֨v)5a8-t9:ysKp`2"It4@X8n,Vjy`[iIVBp $wU@"}y WC$@ LɺsЄflR0QR`?MPb`5AS2*D* z@ˌPМwt 4,r IɊGm&2,sIJѦSMA0C~oG߸@? +m =P^nnGq9\c~C;\ݧN,t-` H:"~EVBvh{'H@rd0DԎ+J]TP!]&TsR+o?4"*Yb(ŎZnj`Q4HXF):+B*q=QJiҔikO*+hy`r7Dށ>! :a1@DݛYȒC1FBg6`~Fh"k$A$]GֆKPˊ &(KTQm)TdOEP#C* 5H%e,IxP26Flb*x/m@ {+}3۔fc\3Gzyrz oP*d1<ȡ AظLB*XTz>#D"1 |o%F4 ,:z(sC|"&,h^ZLސ9YM2ńҕ0Evn@mŤRbԒh7Ү@*ai "(g"I'\;xP੄nؤaݔC!?7ߝbͩPTr#ԏ|rDŽƎ]Io:={!uCyv!PTDIQC"DĞnAlԻ!JIE2tFr䍋NW0V RvL" b4Hѡ+hTB!4 &5٫U)yi}` Q8Fͽy-"vP3!=@wB뭬BNn8h*f PH{M {XhY66P5p/<}eJ]+z\?RJѯoVd(4vd+4<ҥZ!&vp$!ct7Pg=iAvj.dvz&mGW3j SăJE$$`#lHZ6HN߉@|PQ| .!{DQJPlH bAer!3EC#h6">i> xƨJP< (%Xw0hª'ÏB}ܼP`=||M x4b1S5lM4VR An rk'sN::=μ^dJD+g*'> =pB=w{VWfWN2p'7EU9»mLF,C @S=!lf%JvaGFCd7R>,!:JWG1Z_7Lht$/ ҡa"QPF~Gũ[# T\6u̜0:&O=Ʃ8mmrJtύI~T/:u<HMoCkH$lţk֙t!zchZ"j+or)#~ | A>*J úŸ4 к %X>Z ;𚗱`ph #<ȴGXH`z3g ! + HFScŲcѵsFEMlޙelHGɥCvhՆ,YXVn_8irq:\Ι3 /xA/gOL }(4Z%7$$,>&}uG|Sf&pp|Wh:PU+t/hB tB0tld]i\#!X)xfD7׊.I1imd4u;BB @\3R в&Cro!|ѽ}Z*S4z$ku-9L7҃%*bѵsp\a@q-,%YZza`YBXFG/) > ޭίE88Zs}h}dDAH:%:Uփ)ФVQ(Meq I>ɧlSpB?%8:VF!)1=2:C&5t5bcB5o}pO~shuבZb8D ƽ'UލTRI $[ɪmIƬvhE(!duR>>ƼT:Sl/Srv%q(/vڽ6unJjmfFВh@! ٓC6#B$J \"Bw 7_=Ym )%!G>81VQQ! WަӮtFze{&W(+x.HC4:4-d !*hb-:48wg˨K O.SE *wKU!3XsgzuAY_< )"&aA;\M `LeLU 5fIاol(u8㫤$3 nT:4 ׅ"g"OXYi' v6ݘFaTITQ %Mz)0q!xZQ.HkB8 jK, h䟏Dg] _hkaNX W!,87$ϾtIuӡBe߇2ÄTL7x,d(%l+ԅ\@.HYBpO < + ^6:v&1ƹVԄEn+K67l9! %5F-4؆$LN&"-@&-BQSm&T1:WORIbFc3a$WޠgtRbHBm%J$m6ƾR5(r[Y))bj T"*.ɘhj^6uubI:P_79vCMI5,:+'a3k\qMpKrCV"Ha^k2DŽ\aD-WaRi_k ]$(<[2iړ7bڰmb86 r̻ VʡHid Ō膻h ͅԅZCpJbxcSDgtXI/opz[0hL{ ;'aL₋]I&:w2:h28n`]xLx_2"UܘMؖ:νVD9aB!|ڇp/]AlM*BKzbφaob9|GE=h9mp}hDv4?PtL@e,.lT\†Z#Sڮ˼m-c+nNr-S8$ ذ(ٹhp'CPbcP\߇:,Bfڏ `-NEpu"X#1yb1-g.YNLΤ't9 ,@ }YXZ83&)Jxf k d9ƻIY*K=(hPFcJ$tka,Ju~o}J?QV(q{69OEGi2ѣQs#z/5nLvn @IYwf7>ׇrgܙ]&[{:99컦bi*+{$WieTTAV.%wTsժVQi U5c50+DE^uA<0}AkY[L"JfIv$8UHq5^Ya9 ˣ2o+_x3I- zCLZ iJjqItLu|1;_8.7.9&]#1+ ]l!,U+da7PMrmҦJgA0/HKlicoL-Fn`qc(QMX05:ʈc}P$oҔϴɇD6J ̐:-BmJ)Bs zK;(Y{5>0rCά7IؕKB G OL5ju=:-1'yU_8r_pʫ].5[仰dwF ȧ4Bpɂj] {xD^ tcƨޏY [X"k;%sX@ Ry Zy{_$j'*Cܲ',jN@]ra` w>`RBq[DM[s& k 4϶-SZ+a,$o0L0$9dU;s o5󍾒M1)}їF ]=K;Sɲ,Spf=ntT&vOzIaΊVOSx1 }P߅(;,jlBLM(٘,0WzS PVWJ &]6TYar@wLڏv]Y*v$eՔXЋKzˈ>*u*ӄQx\ mo'4XʊFBgYYRl<'qJ.h[0?Qce2Oke$Ifϔ9۬8RcATy,r##!Jr]?x9vY?2{ 9!vkK.VWs Çx?Ko>8oB9O%A0\RPkG`ڳ@ҝ;a]\4nD T$ cv> Cɢ+!ٹ$gHR^@ѐ\'s@nbd?{oo~?(|?Q̗)ʒwa*4sZ "EjxTDR.(*(-ǥD0GZrr6ZL(yqYK e )w/DYmBSʚ@5m-ōEKwͣ#=l(T*Tz/4M#$PNhubGvDa k2 FXh;!7u.0;o&/+C 񽏃O> l|~]'~*p,ckM{M В '|ABި-%Q[/++'[cf?5XжVRybSP?b)TF_ '1fwBn#h5`˄au0W#6C vY= i3 ]V 9؀[WeM*"A֜F1g_a?{m/9(Qჟ)syDg#4$Vp_SaRF+ K:zաTFH,)M26FUrTp^τ%z)<"])Չy f+YfG7XNLGmB(b&Ɯu)hnjNnUBl/OJoj)';TNX)h5̐r(sˆta↕/pf/'>_΋txiG~υK_MO?r>;_;aƋ{ްBl0(j2Ei&X](cK9 :4 5RQVT%>):(hT\6MY(*:鉉F+ L$؉)9`3Gձ p > 5FmjCQN'N> g+:r$P4. rh?N\7?P߸-Yljt >]߸~Yy'ʻHs;I 9i)@L̄&"6-MZp '܎6{H;K$p$hHw]r_5$Y궧XPK`^(ˑ%Y^R޵ c9' *-^k"p:DV1p sft$6tvL'Jx\:O8$~.7>&|]_;;>a}!lwCLnW2`ceUGEdʗǚ+9R2gKfJ\%޸8{RhSټē8ZRQ*9RqJR8-MtĠॲTa5mtpVgb(l-X^v-Ye(*p])6lOLpN٥㧝 O3N7Ԍnxf/_(_wa'ÿYqOT!jCgš` nQjt\đyQ_ Zc?ӝO;:6iR6uƜM<{-(*E8t^p)hy+& O:9_֟OdZ_ ߆N~~|6"PlήZw5XFaҬPRR8'sr=蹪Q7-O ',HQ|BFЊĒ{ {=q|p-,_f-h(g:"GĻD&NT/VXeʳNjjKLFI'K;vL;f[ +o}|&{I`U@P閄H}C|fdxNT)L? w^O&+0OJf OPý/4$׵U xDb^-&yfHye-7ow=$0mA_ ܠb۠=NZ﬏vP37t3 AL~-Y_:8?~Ϫ3lpDZ"$s= pL[f8!~f{B0Yq9Q3{8x[34F*`4޴GQ8G&t<}{V &Փ<,Rfj݀p wKei ʓ5i>)6۾.&IDyN>ɵgF&&%8:w|m7|οzi_r S!X@թrY~&zLyW,칋&JbDҎikY-%JͿEs Jv!z9u8NIdX֭iJ/AЪBB+U VXڰv F*9̩uϢ0oJ" ; -HdCDчC >2Ӎ4A,6z7=ixbtOtrX0' ,12n"C P;`Va ^:| .g~2 pf~k¦ .38/iQ0iY9{ܜy) ]~!4.K|);[8N K7Ph Zi%_e9l5r@EIσuO&v-0~Mo#\⪼;Iy=4)VkitUGK r F)e!4}>'ڡܐC}D1T0h1 X7Ljqw,{z%]Ђ&(&⚘v%%19Yp>WYNr]' tfng`l KruxxcGX{Kj,1? >{ x#~`ghDk#2Z +jb;Ȓ:.,?\ypP}Bug 5&)і0'_C}+inD ;ƜFahqbxbqgz(ThRI˂"ҋ҈ vMµ7)eHԩaGz`LA+h Eж`V4;{_t┣%,yDigc \:4otC2uqa&Efܨ /dCꄲCx8$/8=~=<x^ëiu=lo_~p=U&;>RqJ) "T+>1A)WgT[[ҹW(5Ǿ:ڂAKwpn(uf}fW@m;?YPZFnH˭2%w&h_Jay>[@5əJ.#8905 uT+Qx<"@9 | '48݂ݜy-I5$D2.`](JʤfRlN'cVLq [&j-tP!-Xx ,_Hd"BNH&HS0Ta\'%Ԃʌ%Qy-F>:E}=7nP0ڗyS0ԝ ]̖r>?9.FOr_% zd;ܑ6PG&siUF3,eXRR78spDI 0nmIa%wM{Ԯ``Ta/UAc Q3CٸN])Pƚ7Kʷ$JO<Iȿ[3lÌ18z*#6|d8mv=kc |~ D A.8N:ٜ|Hc"v 6+_w.7R!c~BGLv pb MjF mjM pR U3e1gA!SG7c u҉ʶ\ћQ,4akc%P! ʩTd4&I%5PL脦4q]R9mA - ԃ=-37'w G<xH7hԏzCNygؙvqfrs١*JeȄd~mr m RX%sfNpc1/cG3:.pD> XV 54F Z"!j Lӣx;o~pjh$[n'$i5'eV;5f, 70CtO lɑd*U Nt9m o&eRRw}N FPy9ᾂ!DDDkxEF4@.e2.yizŘ>s2&I>{Awc; ^JD{ˑ3@R@] ݔ&'*J{=X yĊIr]) Ƀ^V MВXv"zPI]AكzeO%XǞ[I)BeژFH]dWE8je5Ý[Hy yDιp^>N|Rc=qTjqDpqNax)Mt٘, C'>GY@xHMj"\F=L&e0LV ]x,[n?Ew5ObpbIͦڄ7.@~,NέNʘTߘi ]i1Ӌ$NTrĬjq9FQu_@kϑ o!zrF8rf;FR VyB vsJDHO#Pzp$R&6bIJ]\'tlI ౷\[J`;Ec1NxL!3Έ>Pʻ)hrR;dorxP1bWJ,EiqeHov e(V "qC(I1b!YRdr\4f(O߷Mz~wzE|z?xRLXoAZvN Wqq`Ft͉Dɜ *ͱ8'ZKz7%eP} g!uJIsh-:oLP!C慐$7&1h $#&$+%#ᇏ,V 5 bdysHl6CӎnY[qI;ɧ?=/>+.AKr|`'TDK7&䘦0мe؃K%SO3;Ve |ӆJwT}N 圓B#vof̒fX&i괐SxVơZ1u/@%3 \_/AB .rCFȆxJgeϗ'`iCU #O\X_*ߕh+|\<],7wzYNPULBF5܃IYPd IJAA,Mtj "01L&tLqAH@_ ?z" J?%|k(iz: Ӡ\Ӽh6qycL.} ѹDua/wϿo/>(iY?(?{V*«t_4"GӹiAb>]<rLbflaLM)0[PYZV:eKlDR.ND%隤H<"bZ(v$tHGQ"[sm9.Qsdܻʤ`.vB6lvB9;MMkmz59ɷ>s쿩"b+L>w ~.ʝ4^Kaˀ1ێ a;lʬ@4jՌa+ɔNS@^!%cWBND\H\I`1?b`$]|L]z:Gz8̈Y&{z+dNQ9v"z_5NKs NGf!pŖmDq+?wx1y엉;_o 7~w~]{ q-<(Q< W ks7Hɖ6n\0 { ;g^"~# Wr8lX2)iµ (p^ ٓ^-˄9fav19[\[2%G "W7 OD,7z 6z9ѹYv، ?Km\߬]ӤM;?NZQP ݔu ]9`d+Xf eb3?lΙif41Aʚv֡uU4 ؟;GDp@Qlao!*Ap~n)p# ,3bt&L19B$E+"rqd-gL&;m7i# W;Et.tO?|𡽽5W#Ya"rm\ڞ~:XIKz }(Yb0*r|2h._)*cYxٍs=7X|1_}1%jŝ2¶*mW[횻AIy-#gŒ0^ +mf K%Q`ses5=(vZa!67F:| ,㥳 k .DFNGvyb՗<:2,Y>9<*I ќx _ u( ;:W#;9X9dQ?&o|Ӌ'w\`/W"ʇ)-8Cb!X'a(e:z34|nɾZfJO c9:8FI+S2Ǻ8#]EVo'u%1ݟ9v-J^q5 H*SRjO1(i& ݹؿs^o|%,ġ/X ?鏄 eIK0D>df7kݍY:Qg)Zz\@ĺ"Sg HC"؆Pm̂=** rM{yxKDW% >C3,%*s  g\ɢ;!;s[ :0G|}?d޿ ^܄L@Bf{OڠHo3͌BК_]ODLZ꩒"w6=r~NUݺ}cj(Y` ,";/KX;_Ȃ+^^[b`(L܏8Y(G$eCYܾU:Nu^ƞ@nWE00 hC1&` FLQ jW6EܮiPw!RF8dHD `MYqd Ғ|2$*)bbnq1miĦ4-ޭ/q[h驌եiP{ PقHao.0!ɀd#H.ɤR~R*sHIOi"5Yjz*^ѪжZF'7kL^Қ k.dtӱJg .L-i 9LK }HʽZ3av)Tp@?@3 ,?V{ݿڛ"pZ{a @ YȬfΰƌρfX;PAUrۄ .` ZV; &,.:zLr2Snš5cL$iۢ}eCtKt݊`!d>XNTYp]UN&$<"'ȸ|D 1h#. Q#:OTFn0w}Uvp(]F`[w G$8 #kwhgɍ{CT&[UzΓc+)# e_zb8Ԡ#3f-+)aLBؓMǐ~ؖfj6p~~-ل34Rt~4ɱd)pKl]LM4B5J,[NWyA]`6SOSԪ쨘YI}svG3&2U+,^rIz)BPZj$caKA&=䢞 [WK ;p*brfKzV =VԺ LVH΂a!Bef#];C&74{X+D-AI)Sj)ŜJ0M=Ze#i37ܻ|c_'p| )ov~d`Nw>E8-G.YdE+g9X ͜W0 s(BȆ SB|t&JudpN`U!yi&D$r!510PwgTNsd`m%G0!C(&Ge1ܒy$$̀"HYHչ2Gݷ,{&V9`]2L !/k򅷙W>r"Fj녾ǵ`u| [ps%pm#3GfCUOͪƘS9|Vr/)>9وƞ{ -׸^1yXH4m&?WsMLG> O]aR~ O +ki 9,%l$\!ܧi@aEf1V~ְj_ }cj$6@HFJd1s۱ʁgHK؞{uPqVz .33XW f l lIĆr1fdeS6pf> \$Yy g3p? hXW1lJx6,s0$I$IyY_f_{~*bd.Z4 @-ob#J/Z'% yV'UœG|S]kOAܷpaBgi53:fiZ> qu"Ydn dlpE⬎4iM&—ۙF1!ni_5KZ=$t7p-S'4Q>+ #k=+?7/E+qk6Aѝ|έau`yzTᗎ=,nۏFc%5++U\xps|WkpeR hcގ \HIDAT\ Tl[,Y׉UX_$ğ-r_o#sp)-oq89疍wB^XLt}q;ƾPw+rde&!iw1 /AP E6WV 6|iEI l?r܉hs=Cc]Yc0Edb/2L;9rFEÃ̝{]oey[?APe00hag-w*uEN9㶽`﻽ Lo]Wb[ZdžT;-ppre>g{o6s{+ k?,sى62L)$3:Wgf7 O5! /*|Y9%,}hϓĝ{ߠjcy;!yWX(tIx#3j_)m?`#NOOK TOp8R;eR)K|E'1^Z:1rYV qxe?C_/Oܶ֩h)lcXD>\CJS~wY_'(:k_έѷg @]dǟb} ~fK"Үݏ؁Eb {-|/"pj׎+mAu[oҿ ױ{c[l]ֺC2[$IENDB`robocode/robocode/resources/images/explosion/explosion2-50.png0000644000175000017500000005224010205417702023772 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME&+5 IDATxIeu[{5VIf*ɐY e%QF  SF~O hjר\*%QmLE1R&2iv7Η]$pmιZ.f7ol~fGn>oD|L7JX>B7oo_Wo 2?HBs3P~p^e 6?HD7{K L*p4Y𭛊kF``,4DXTڏ*tptx>q0.W<7nnʯs?^6Vs;b)JpA XO][ڱr_(.y^z ?ފt0d늢*! ГD0&11ڌ;&\M4NGhҢh}֧vXP8[tǨ😛3WnRLKE}:CYϩM`t`yzT+@8UJ) 4ε nEegwc-w ! Q#a: a^D |ԳR=c *9#&UELZa ~m0BH5!O -A9FS:R˒n)&GK/'z yW URC;T4ۻƇ .PL)<Ž4K~),أFLjq2=gg35[D_Иe/JܦC|%TGO@7|\\~,5 zL_Pzwfw.CB"aPjXXXkzoQa'haR E9ZϡUT3B1Q4KRHpGr S*дXx@׿ϠXq_!/}1W7l֚k 7fԍ 0r L1~LjbdaJm 5\×w]q"b&&h=)^-Q3JWm HSNJz7hZ!VxcpQx p2blcBK<#W D֡R4)ݼsGxF ن(c_WPrDCe^Gc`i ).pVcB=]*Pńq3\BKY(J E%i:1Fe@} H CJW(ڦb`J*((W NCJ!xܠG΀A (}{(O, uCSu#1M`ib/c4ܹЛyYvXL `6*q! bZ.DϔfpL0*bRx* *hˬmJP˂&,KK)x)QzUPE V+B=A +LՐM6%- ִ!#mpCǁ{9p =!cb, 1yZUS5U#Ի9=u|8 j1bvi3Q'p҃s`5F д` z'P,6hP|" ho0U 'pPw_FSlXk~t`9 T&&mGwG_R\h؊pt[9}I(swgk *_ª?d(cڀq fvp `H{B  @F>M4KBؠC=uX\p( x+ hW VIIxWx(, Kbf7XsrS,;9*<og?[go{{C/⿎W(.yBޔu^ h=TC UE` P`J'oL®%`:u 0.hqv@C{ķذ$РT!`# 7#ZGu@Q`@αW0TR5SY ;|e$ P`Z@GVP. +uDREì ˜0]SC*qRywwp`M GlǠ}0Ppm_zɇa\¦;@װ  h#!@_peK<e/ f<0 ֖z?D]<+PǞz8qpRKp5&"tjaZuh?((# d04AKpHƸ.P L%nZ@W_C5)˳ʝba+/`ݻ84|en7X1!+3S-A ^}nblVjxi'q>Z`-iKs @ {tUT&PLiLTqtqܧxp>D5l:4iPbe:OǶT>>. +=* U0?aoz~ղ7ۿ7TM%}1p7xq|I ,zp`}.{q#kcou&VIo5.%PGъQIqtz ұcN+iPzxB/pd`ف^YEE?n w#xGQ1ge^hn+ ߅_xҷ߽G<*8-CACċ?]W1>Xx{0w27Ielnn%lRͤtvg9Mt\^w!ds9}7Dg0g#p4%^8szxE/6bua3@a(fKbnk7os`&Id> &gl0vޓ,,i2z^̕q+T(hBu\p:hzв"XYY re=o垵'0?'^{G0fblvjvE_Q LOll@8`PQ6VJ;xMB:tu6 MJ3& }f_'>ӱt&\Xatx۔; 2fU3NoOQW2 ]EQ{BN6~c7߲o @xa5Rb חE1&0,S^`h=pd"2GKx, m' 'ɕ$@L d6[r)ˎݷ%0u0B9H;8[GE躤lOgs3цKcjWk f<j}p| ş=St.ֆv =TCfaB?}M!q'vSll4Q; [II:dAe!`YWOPcn>SivWDEX65K(dF_dWZP_+Q4bvG-T-]CU|^$?$IưIoF X_~z)%J{JhG_ƝoJ/7«NXut!Nጧf !ZƏUbUO˒3;SK;\du*=&YAGe'2[ 2E/@,lS\!g"N B0st).f;qq;;;ox8PܸM )B{+0AyA{QX)kE9 Pc*(6 3xe/Zu離yɗT9J$ Z"Mf[/fI) '>+eDi˩4@0 ]b̀C}A(RSp)™fŝ|AQ}xIx=JQan-w^7!~Az0!URMzb`. <+kmju布*\ W1Jчj;Wcz3Dkؔ%/:ûop 橅(_V%VLiʍh쪤 ^"@0Feb]7k`ӷz^Q*B%&K&V ܕp|V0=Kg"W)73%KB8B jcx˅ɆwpcKht!ggY>7?;;\+7 +xH͠/,XOcT)ƄP!LhEi"$]$an&~@KeuU Iaf]&ɰbB&_fG#+bxݦSC(Ȕ42 E10Al/L6| ?uSL_g¿hTkFȦbH]ce ~"|) *S3FE싗&RPɥ/bl;.DROݭ'8tYe݄ .YYW>SºB5W()TZ :-6ЩX`kq%8xWxo" }074d9*1bk3"c\\+Q%)8 F_i5+Yuz4ImTI:b 4Md0J`7B[ͳ *@W7(EmVt_T0`UzX7YqS+hЌE#I|`|#76 ZTw˯kX3[ňFPhAa!ТkRWXtb]I^ìթ38,@qWPUY >G-wmg]dB.a% GFh֏A/2i O@q=6d%nLPvAXR`zt?YZk">YVŚ8I(dt}ҋ%oa,gōd!6r:DPrؾ J(NJuEѳ[lC)5jq(q.=@n+j0QU 1ʏ" %5'8q;2F-*¿I\R'RO>e/,`k1&Yf-4 ^Wt-b⚆R:C {Ȗby;o fD5г;`fhY,Bh7) pCe VQP}A[(hWi[JHMgkF-ݥ:!fFYO#=eoGz~hØR5ؒ3S25-+$X8zIx k0j/PEBF{BW9Q\ cvF%UqiDŸt\@e kaVՄj\&22eeM- 6/lI*-5) Jx{+R 'c1*PQl O;7.`[aGBco P&0@JE#"W//uOJ\6 K}&0znp򤟯j8.-zGo.CrrK۵ [/4<\bqp&tie*p%3lVBG-:h,x'[^ݻ RBM5/cG~1BpJ,)bi!vovoY@"miyeeuV-,[229M2A,`]Do4Ã&0vhBc )Ѧ`m *ZYS N^zI#8/AӉBAڮ xw˹ۖVYv˨UY|.ȠBdo[Bx b@cvJ5OhW#mŧ6E()6fSA FizWbAeaa>M2]Xy^eatpVbWU+*zQ*BwsE(vY?uAi̅*+nK[0HyI6뒷r2):wM:o`ƥ򽏥6,h||QhP(-46MG=u3I>0.XbF4* Qw$ jL*v71h'Kl7 g (gdض"P Fsd]M֦.i'eOл !Aspq!*ibI*<" KN' `|TAxW1 ?A)8UŜ6şn'>@ )u}g >mSy6n[x8 Ӫ `&rX^N!E"qR*U&@bj5}(b۪Z)ҬpfVY* 'lkSXIER"7L,aUg!bⲺ>K -AkJt &&xiw߈N| O<Ut9У֗1P2ʘh&:>BJ̶֞bO0H ,az YS;:ZC_88\[~8=](z$thi;Jq8j=t>pxxy {èb!V>vft&X_e"\dmƜ\R$-@l41Dft='^ae(UvuN/bl T[P4N$6.ZMJvhP0k:;q;C8}w?;ǐ^^9ޙYa`, ,6t4oTtt Mqދcy,eOC\7 >|ٷɼAe$.s̪YagE\EUF]&iYgO^Yy;] 6kxF*B M MkyXp)c:$5,,cO923nws6uє-×k4"Ң:A83g͙8_]{ݥNJn$AUי_g[%%]Se DX/#*`N0ReMV؂:xvHx}E(& 쒥w6=lr:N}lXһ:URIMAw=]KL˖Ci 5Z-)ﰾGr}\Q,'Zm"͔)@ۺZ\f.w7)Bb $7μK}v{aGpd#jG5.zƟ?<ҥ(-o @A &<],Z'-w6_?Iԅp>Iwᕙ y+K' }2j +:Bot(<&;\XBIKe2fnw,o'ļ [d YKgGYbצIU4Pe>SU 庀NsVT"sdCڭ24@ )/%ҵg`乾c98_XwO/C0@Ẍ́BIZ#%j zԈN ͗0O0k5t\5dM7x?enx#㶥K7 |ʪyeV.Oi\Hl=}Hca{wACw9קXb5~˵<\xg#4 Cnpm/&?ke0Va"&X18?IJ)~obR=cjӪ&}#-;Ed>ܛѴX8}!8>:HkBNRIUپ6PTU5(|G 6U;M?D=P aD㇣o,{~ E?<:PpcrVfƵF|Ik9D a_g-qGO\sM6Pe]lٲ[r(+aB?fBPO>k fjZwYu>oE 0㒷etѹ `u8{Dž{80݂a/6AП7 fe!e?m6ӹ -uf) Qe#Ȝ*u-(hcBӮco[3,b &搫ؘ 蝧) C1ۢ*SrZǔGsW( 7Yyn8Oh|֥8_F?ò$O @Uߠ0^Q\?Tj1 c#a}v׬-y[OuvmLdy\&_`OHJd_ R'UV*'sPl"V ZCZ]qixfA^R%_I){Zmy]O3!s@Po_A*JQ CsXJxҭ!^+dUld ˈ >AM֘YgPg=-;gUɄf?ݻWdxΧy%r)KZ5y.w5=]mP;5Eˋmz槎^<-W v3U9^XS&⮠raBs ?aiSf1'sAJ,t"tßB!Si|ȪwJe`QS-c8mk|@3> lXejv=>}/ ;jP`w!cHOZ#grgO㧬Ap{p/ЙTKT8avPb0+aƙݶg(Aށ΄]]> Y/,Q8ˌ \dͣuj7ah4vȀe!bE#t^nՌmM`sbOP'C:yH:*z4P~麗p?sKī>S<HYTu,TSe8r}䞃 A)ܖIl'9R)^b]5B,d5L KXKnf]I#v,e'[<q;W_s[T4Ŝ9> RX-= S Rb!!?0pqޏױ++"N0% SW0Ċ:AF?!̊{g -99e͔ f5/7@s#(?…[Y&p,(<[6)d o)g ⌦[]^ۍ-]LEdT I,.Å:~>+^/0slqౙIlW@u( e?7?| 'j5樛0.jT+y_ =yf?­ް1< <8T#F̳jZE*17F| k uڂmґQ4٫.tMLarX^~q2^Qlϯp0Ebsx3j=Ź v5ٛ+3[?ߠ[xoL~9ý7ԫb(M۔ZVw=:j72 _謳ξmV 4lt6lˊ(bMx38%eэV߫{~~wapz0e4g{!` )r\VIq05{+WktXz袲 ݻ s8<v䋢y/5l1}^;Er K1$:O;їQД%əL*ѯT,Z>"rC'{O5j &uQb"wPWd:ŀn|'!zO+\y=Dж<V$bл &+W=yҶAV:NSmdQ2`f8e'dΡeպb1I3,I7B~8neV >X^1M:O; .x^[mB>/z[eo}ޛȸ"9x"u3BpM2ڜ.lNm2^{~-xўp鱧*kuL&AP$qG9mFaS pq?/Z<}p f"UƽC>::<ʼnM1-"OOzл^WOvyomm̳9@ӝ:1Es=t=  n!f# W" k%-N5qVҴ F5Ah5&0$< ?Wyuܽoii 1CQp(p}^jvBؽ8>c @Rˀ(FQb!pa˽U)?0{rO~gɠ}N?H[W¶FxYz'X_^^/`;^{dZA^U3"M0R1!_'i/8O[)Y=^P%Rk5148;kļ Z(I (mfo{[TȢ4O|o<)|^wF^v?߻ QCJ]yOװr &DI$f U=/x; "Û&P0aXCj|R;7(rV$TN$WnxsŽR EAf D&=Evz/52M%)yxX&ҝvI42%{Xv3b!L]`ˤJ%.F@-ңSNDCS6,%OMH'p+FUUe0\D6\:it8ڀwǴs fFW8j6 qF.1}25a 11JWEsIDATjD4hukc(K@'wGp\LSgEI&]'}&\W|8OU:3.a#6_Mp dp/*Xib9>^Yw tV~J}9Jgj:70[l>CrGmN@N4@^ a+hȗV{5X3\T]::Qɤ=DeH^҂ޙ'E1HNbyg+vO6IwEsTGSɦַIΜ?;kDg`͐2?x[x,.#>$YVNMLX_ޝ5LZlg{_uLj!2q$W.Ac1YX y מR#\~%%~_e`\cT5QSm_L7NRsN2籛<A6Nj4:z)HLNPI^Qh I;9\VEp>Z!H ?Zd?z.Հ 1OOก):0|>vMiYN3zmBF-}Dl\:< 0#9D!zTQkAl ZbG1rV `(2]]!f@͛Sxbr o=^&#za\FCFC-m: hCn'[4#8̉z6BF O !"'Bg|&_e? RY.~2w18X] . Kf4IunRȲJ"PMHAf/k>{3"'SPE M ڐz5+{v~BV) R˷锭Qu'%LpBhbST )t;p1D&`VPzF`V ڀK 0ǚL/ȚLX.+3U9@pܿͬO 9Q~4{-eBV8! g6_Dy)XtX--Q'fsj 3`i6F2n"ʥ#-tL*P/P )ȍ``ڀX2o<QpaOp\C4g]#G!JQĂ?4*]*;6Nã;!f.$ESTM*%.Qzէiѱ -TVk 4Cui,[! B#M:ZY!JB,f"jp 䛼Y6h͔נ\B3H7{GFk\ C3BeIGꄨ*u"`IPfsk&6,@ (FMɖ]ދ|t7ffIPc 83QzAShoe4 Ot@T0@uwy &c w5ALVlv*D5(O Wo@`~555#sv~\Uc6D0ap*P? FQ˸;M,uGCvP!>B/b\!N :OYر -soس5n&#o,Q(hP^xZc[J@#ZyeoQ 'oG;*+%<"r*W$u|%Tr6a˒P77\ c6dZp+Ų(Xب3y/rQMPfڳ3r<,õ'*u4WU@~Ca)p/z߻  Jgo -uF `#B 1vJO&/!GL@B+ ɂNf)F>G8B30G4hlAۮ)k5֜Zs\eKcV Wr$a{37ȩbjP0-D)1>jY[QveQ xʓe-TYӐQaiX5A9aږ81;&EE_| 'h{rh2q>ٚ b76(c&T8鈎e[blfv5Vո!~Xѱ7ӆMֲZ{V ZDa߷ nFۆ7֊PNH{CI g(Ajvׂ&+ 8ל.2BQDaeRT93s<*D4 bח|F|a+IOҀyOgGXX3]e䃌U,`y5KIN׈E%hrTB[1Rt mMj6a08mZ2]s,t8EW'Cؿ' ロRv- XUFsad;xQc.~TAղm`(L4VQYâBsP*sƍn2)#H٭"ev.idv$\;|Rv_Y1-g\K-A9BKrˑA&âMH/&(%f &8Ұ -qsf6 \{¹|ɍ~~滚wחGU9|Ѭv B%c(rDZQftԏ-|CMiFG+)ZSgi1Itp@鳼tC Y=453e9<Q66 `|T`*0Tu9^A\/;)>J[9>.|ghlO['K_]:"r_z|!zZj`&8RGڠh@tb-V+edQFy/Z Se\&rOb_Y|!z/_a5|\l+RSn(X҃OUM|S߇ϭ^/++nRONGKk`NݺzsJa:Juijw_$ptnW<:]ν+~pแ@ (~/Qz_z& оIENDB`robocode/robocode/resources/images/explosion/explosion2-13.png0000644000175000017500000000524410205417702023773 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%0m 1IDATxo}9s Br%JXRjɖnҨ #y(ZykEh4VQ"Y]t mE{sNFM8, 39B!B!B!B!B!B!B!B!B!B!B!Qup$_C_x⥦b <0,t\hyǗ~ѫ[o&ꏮd2\54ufliiDvBӷVOFv)-4Cڷ?Oş﯒yn)ϲ3 SHdljrET (q`Ni6plw^2qA u :ڦ$aІAzrQLQy%|EQ3_F21^Kn~|Zw<#۫ wla7Нj)a۬SJA'zugFL~6$Gq j p@yiZ£g BE?$Qns'qCOS -z&fRW:Ens<y3&n1 & ܆ o/Ay=l/;P;t0=Ơ}b$ ~ 1}3; }N@p`&K(bkL|QyeN;itdEjeʕc  >݁(Z,@ 6a+.}?Y^3Aˆu4e0"us}]NGwGUPb[s5x4>\b+WrNr s ԟd_ 鏱רv!j?ML'_wrzA";WFE3Lמe5wwLڠEH.z^qM 9H ʱuآte33X$f؛v6< 2Re b&Ґi 尦q@Q 雤?"]G SC%Un#`3$|Y4I3Gc9Q2 iFbUDgϓF  &=[$]wVnįmhrN P pYui}WƯ6(yLwE8UY'E뤾&r@y,>脪)䰏poЅ,?ǹ;$o3y򸮖`p֚# 4^ m/o3 lۘGm|;>k󸮚PZzD,a8ރu`cwTv׷0]z8dxrwjjGl1*(Jڣ>`tU˥f.gKOX(6qI{X㶀w5jӎvk@ɸ(X*,/ Ckk }mx /P>ƽ>?8hRN]qzBV&z׹e+]^\Z a44!d4n V?ئ~HgԿzw7 p}౏A \n>CV]b?gTiG ΡBZ(ϑ$gQ\0?Tgw'V.,@wovO_3Z` .;Jͧ xe@BܸV_y!x R@3(s/\Puow ,67`"\%]R]TwmMw3yˠb!~cqC/7Zkk0Yfw{ %yHVm%4" f!).-&,$#T@V^#Ύ2ȞAE-9P87ҏ[3X>^VelE'&xXc0/ҍwkp*]Z )mI^F95u͍e)/Iy ޢݠ *f4NIE/uG><əJ53l<҂[N>}9q1`!JI ~H^| Gh*/?)syD~> \H`UrsW:Mjn[B; MlQ\lZ؁b iĭ >[C9r&B!B!B!B!B!B!B!B!B!B!B!'WM!dIENDB`robocode/robocode/resources/images/explosion/explosion2-19.png0000644000175000017500000001021210205417702023770 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%ZIDATxo\}̜޹J,ɴ#Y]_4n´NQi>@>D0 n<ȭIJqD[WRŋ%g\f 4<-pvog888888888888888888<\g+x+< ,^~p`xdZDK6'7>o$四,R0G_TVh /Ihu壚佄.L>+A ڷRҀ#T@Qᵏf=#jLM`ydZ+8w_S]r<.%0Ecl5%&%ߨthƌ݊  ),d.~olM)(ё%Ly!Kl*XgdUL¯(f\a-`mPb @,(g$06Bk֒K QK.+!jyJRJc2̩0>HQJ6>:{+[7ƚN څ"C/Hny jqF| 1"@:K6haAP m𝋚vzESI`cwjIlǂ,a!WXAWL@g XBkd_{?ACI3NAu_G+AȼAԊ +%w.o i}* Kt3>=oC"}ǒcJ z:E^*nk,|( (i]gNZ#y^Ei DHՠSP"`E=|JԶԴaPOG!bmcUPvZGu6k(QFR|ioZ>TMM~mmӎ3twyb?ӅNF9|K{[7l3~skԻ{o0Ajک4HzNM؍J)bwav1 + 7$'2d؏~bo,(X.f )ENʩ@Cp]pfC0BT'O4yZk>.ݩMs"U8}<>?IN7];ɇ$#Fib6)4gx4[!jRM ]~<}M@DOpAa0R)픷?QhObE :v7Y}1Ji"EyJF, K"BF*QJ^nՃ )[G$e<2 Eú {g\9lzNI<ӟџm_?t.zk0cmo2hNo7T' _BԍLҋX^ݻUǃi+4suf1YL&Y{\>TV BH^Y|RU3E'DDpkT 4Y"_>pA 5"%44 apr/ Je=XCf4؍"fS|tA<>#lST|h@3,t t'@fjg>Fw@\XCQTI$2V`z3ӀDC9jdU GoA)ş#Xޅ(xO]&+(@2= EZ`-½t?6 qp1R2Tuw,0&Fڄ{ezWayo]g~O3~tbh70A;AmQW*nROPTe"_0pj$+VjX9~ ~DLO"!71gPq(R'oxfaiIc9d/h+x >0ߢ5c͔Fy ==83 G 1 r-6HE8Bj]$B[WtlW3VXzQ&6!iX)wH1ucw|.DsD)"*$m/yka0NǷ_='z!i\'{ʀxb$g-z/(FΗ,"K4s0D!9 %$Jɤ@TX Ktn)r+f`p^Ij|[$̕uTL"% >{xױH| q6am]AQnV 4r v&_AsV֘?aAp%+Ģ ȍz$@!qN =A5l)t"+XWbEG)} _SOf1aDInz{)aɌ=_x쿂=x'Yͦ T!GFCv(aZfC739ɓ%]ۥe%+[Kv+ kڶ`&)O f,7;=Z 1C۫CG&@WQ=~7L>yſ/h}@O}sAD8#QMɣEp~>;0 a<dN88888888888888888888%U ѲIENDB`robocode/robocode/resources/images/explosion/explosion2-55.png0000644000175000017500000006414510205417702024006 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME&[3 IDATxۯeusuۗs;I$Qrlwh /OA^@$@%W1 h4:jm-x)Vթ:uξۜsa]Xd[u{ךo1 ~_W?ӟro+=S(l?eBߋۘ䵿o_H|v OMkhwBYzZx%=ȟNNU}wPX_ަuS\}S)_q࿍B} ϿIOy#Q|~aR(koFӵfe[.eEO,c/3kaxd6<\r3A02!l#_;\sS`(NY?/sg6# )A6Zm +x}La?fccsuv0 p^Z p*꙰\Ci!Q4BY `> c\%VQx^L^+^~Mx0st', ?WE|`G|".lFx prQ:Sˬ*~X T}I3XhfCu:i]#h`"_~)O(f{lygA0Z:!=_b-ja<z5+ RU &xn"=#m`GHX@^ϼ/>{WN  K/K]K7ؾTJȼXy2sW%h+ s ph G/JVN|d4 .X)naU=úT>nia62ZXncfx9qt7rĕ)V) plb]]kr A5tR R\(.mF _]sTWƞް;,7 hpׄgLU_5-Whx 06g!uGu4ue3ra(%`=Ff[Қ@jZ]"6|gzŸ1w>me LJ kqK#gg . hYh :N7,EU af 96TϬ۲#x5o NjR…k?s Z 27 5p1& Jsy+GY3ڑ<]ӕp¦dJaڊ8grHQ-!U;,W}k<쿉2AÚR3޵Բw~)uTTƱZUj%p$FK$ 8 m4ѱE0`JngiL [Дq7l=߃[TX/X)¼T pf*C0J+XU Ԩi١~CE 2Fz)0RcE\1~9B WX0+qr qР(+xj*@9 &PYepylaUaGYaPJ1oa zFoQ/cxo ^"Owx{"P ʶT9/?Ay*aqgPl`b5-j}P xL4GpB(.1UCRbPm a0`w!\{(Di(G :.BK8)X1gfC,J:h\K 1 ˁbԅ`Q6TaT؂-s"bqѢFd'4"o"zF =cluN-czSP .#N=\>R~0rMy%Kee+c?T!)"2` zc()Vv`"юʲU8CCAQ#&1V`->FM[=Y j5tF` KS{LQUyeaA2Ba Kl-iQ_: Lx*~ AߗTs;\، ;p| #W_+_|s3:Uyw p96qk)aD8(1ruw"rE0b{s_fh+6?pᔠq\#`uqXB7 bՊ1)% 4'#crhv !P!JL4cb# / vbpFWU-kk"8o0QiˎR:{sx4Z#~VzW75 |DY3$P*ò*%no, `jn1xVT9370r5#Tb 낭,(-[(u9`GDYa9ᤁŽkѡHM wїo !!8g;yX6q\Q uRXtc"Jq.0è,4bŽl]1Å;(L@%fJȯ\zflsu#fp`Y,~^m kwN-!#=ND9d^]c8: :ࢅ^ۈX(4!0%TNJ8)N5%Vpej@,A,9jA :BTU‚qe}NLJDQW07hW  x4 >Z'_v@#b8 .M# #}k^QwGn/Wqr\Aqj@ :^X@Q&kL^UZpUܲZs?rP VpHnᮅ T%4%DeH{ l@):-IQjWu~Jký|x5ڨD#cX*4(5brZmV-l8 k^`-8Cy~֮~aR}dx;}Rr},Yɜn"WpN*8*pj Mm[":^Aj8a'xto!p%0s0(&q:|ҥ* cv# Q_e!?*gmE8#L Utc+CNk7RcA`_yx{Uem:J߸rl֤(@fP*p} /$]|Ì$Mne/J4E:Gi^*zX7"ՎWDB=>~w O862y`^8oG/Uܲk~n+p/7*}gYw.$64haQcUܤfᴁۧqb[,:?0 )pZ"g86i2y& f&Y~h]5WCaaR3B cFLD ;2s[ C]%zsxL!x~Fg:˽u |㑳Mվ"lKT X,-ZE%,78ZT|"fV- ._`ljVO“ɯ63!K U]6 wM~TIR7+fEɊd-#Ȉ!∡* . .Jp(rOgFr'g ԁ{^4] [ǥw̫-V,ZcMQqCRzul<lqb%ȸ@r1751_se><[wu{@I dHq*@NV%Ba7< "g#IFpCaJ-x1#eqWhW7?>Qyow^x =1r˱`C5ø@̌J`REw F!hBp}_&jS@K~m!w9Q/⭗!/_5⟳Y. GK\3!s rjump?p wKU7ܤmYF,ȦxX. 7>]A}[\>;0tt>ї"֞" bb8F:$2yX >ޥ$ؔ*$I#rmKAvMzKZ^RZ}0sX쿯y'.YA -N) SIأ.rJjSXD ]0=FYX29CQ{E3> pw-uKiK1%>am2g` " &l9YT)ի\oFM2)ƒ#> ȿ; X@2Sr9.&8C'xc̊%>{50`i 3-Djp)m=MRm^ )p2lKO5Go 'F&0+Gp`Y'3wܬS 8oN1GqI_p<y#/Vm =jlJ@~9Ѐ@0'˾HlLLԱpHL<âJD4U^ky1/e!<|Xդ &Ktf {6QjL|r9xr/('hw=D& DTjMn&a% =$֕J1ni g# >e>~D/Y?C_b/8 ?|mMa6T]Zp`_4f5TB3W cK2YD3`玂cE_ ۻD&9Ƕ0d$}5db'`'<S,)`J`&^c&c-pB=!iH4 n]D(ct: hɥVZf\lOgJ& `(=nEqrvτY^raCBP'<4o` ]F͌%P*x _kg¿ZZ9²n-W J!<ƓLsM%bRS1˜@v{sx^o_6vH .:\Eb&\j⼱)xE'L‰ILr̈́DMb/nr~;8}T\_-|J>P@QXM+On{S o3({\ -[sǏ7%+0c1nP7I$ө@.*'V.rcz5{Mf"\\Xc W"\5x` xj9];α{?x&fr=?"Ozj-[Ñ㥝csXPo T%GFE(Q5%ֆԱs\'Kfqhv.BL$P̙FSb BpIBOLL\Xc1{:q$4Y3.<#h}43d).}?9qvUGc/|}ȫ7)yƧ5Ms9ڄLzu3Oz2k c&˜ZTQI:9 p%ĉ)I"3`Ƞp쥳 PbnZ߰YAUq G^5џ_ w΄?r; ^XR_)C F])焸@L1 G9sxMupw m';.vt1r0z(KH G!1xSG?s0yكiοMc>lEVᩧz>;'8x HU=sKbqqھqnl{Ӱӫ#pUo}g, IDAT  _kX0v2/iP sb\P91qD!"3z^#!d#lC"|7XwK8`'[ Qe4 9n^p P2qYv xgBTeLIe?0 -h? veh65cblgi%LFn*Eq|U~`i8eAԊqF\qK %ָ`"ɓzIÏc4W1BO cLdNtKJwƌWµtV),4I잦x xw:3DK˚֫Si뭇7yC)Ͳjp.WtxFwה;g1?쥡] X2[X_R%}2GDŠXp6jɎ 5 0/t. Tځyu pm )st[x]w/AK(ȄNA乀'>/&^Xx~ ,KJ /ZŤ&EfNgp~-b==^"$"edlȻ}`v ^Ax\ /@]9Z@ !:Lt(<-nc5x#FZ"BK\Dt|ąC8*B<vǠ4rE6>>S>YپM+d `3TBo3w`'BJt8qILߧ{z&#اв y<-dPIô%0ǫ;t!F1xfҎhì ܿ3I;zp0.5}LIYtZ/DB8$O(^SMuFa :Pšy#XFhKQ> ^c^.#] 7ۇp\pHjᑇZqz:z<&at0$%7r`_Nbo/Y>e 4LpB5.x5yR$elP^@vcc3U 8.2_XBkh) FKl>*1DĄc 9BCG08=DV "a5|b4v$M(viu:ͽx^ b5& a4d *4fdv-@SIwO,;RĤB\CE橸0vho76x&O{G=00Z!Rb1˱ߐ'֯F!b1Q:hRQ!1fF '}@P * ID5籥,"k`Ř|@] f' }@Ӻy^{cЦa~2'w߲b˽3 W~8֝aaK`419SD%R= b󘵯 2 U1KyIf],Ngb@(bB& MZO&>}.U6@hQZKgGXN%M-6sWij&.jMx0Lp·gQyF`rebH`pRJx\u@źDJZS 8Cu!>%tTMZU%5ZdÖi;ѧj${K#!ܘ%6j֛%.;`=K;x<$+P*Z=&3lMB'VEƄդLi+B~׎?q6W-I%;$WIjh)m2Hۇ^GO-(]t} v-U,UеBqd ~x5g:bLؤIZa-"bǘD$ౌ?JBØ<3h6>K^( fIf' ?Wf3$ta&*n$$#иpA#AR' "ι4 `bbFOis Ø1846441YpM@4Uk%a 0ViF`^c kI'}:GI͔UAaKirzY+R2pœIDUlOwL".^!*"i:Fҷ퍦kD8;2c# EGCj7v\9rȝAMo4i(ʙu?*7yKDAz4ĒX?GXӎ5Ň\Ĥd>8x<N]lRi~d߄=M eaIGĞƶDQzJHq*D Ki GnTVeBo M Rjp8@I#؞^1&q[ˌ'o-јL~LUB@aˆkUj1߻ΦKq2b`%i($2_HcK~:lȵܸr7O,X^Mf"v>{#.#Mfbb@e# Q)cH0F 10iDhT'Q<~HӐ!VXYXaZa B! X}0GpzVCdV7)E W\Q3$>ʾ:@&F<&*3a[g!z>Mnu:׬NF.}?Ml'tK-p>wC}Wmt&]7L D "H@hvcbGp#%DS >)#&R]t5PFO4#ʀhӼUPLb|ZHrXi؋ j..ҸXe& oZ}$}B§tdW&@W/irP6͙@ZlnԐ\v,arXX|r]R_?дd0R)ŲVԠQej䡀9qd(Àa`Yv* fV좿םn7˃{O\f* Fw޳Y{w""g t(нCx7IvtH,0:  ]5He*. &h[t g/]]=KO坬TLيn^,aUjmYIr1"o3)o3rl<5 u|}v?N=/yod1]'֩U}^2نtXtE 19B6 JQ{t|2=xC@)"E)MF\"E5V$dVyj49N\ V.-ym6;F'aV 8<fiiU1ݻä7}M`Tv I&ۻMȵ3$L$ٶm:O;;D5h$lr@(qh j@)@Z3l~g# ɐV2c[>v!az'(š5F.{#b9>q)K6)YIΛ3ﲑWŜ yt-a3$áC ehY#cޯѳ5b-M3S |> [W[NjÛ灓VpKO J&mZm Y/ۨibUiCIq1Ip%FF%a{#&`Lﻏ 0<޸9>%w 0,C4 kğS39gˊY! E!u/G?Ց@ 'c8>p$U**F<&z7 (rf.F1LSJi4Z]v' <6b<-h믨mQ*G>=fݯ2яϛEN +#"EҖW\JUéZ%{U@}Hfݣ i#eIJ5֬v+mPf{q7bɁgu<ޓ|{2*M/ +(Ӭ4}1hF1˂*L -OX,,>KU WyKvPգi3:j$4#ͿyWD(kt!>+a$Ӿ6#ݳHTbFi>p3/ksuL*zocCu=UGV:& `'G}{ޫ {£wQ`U)iMI+ ߲oSx] ޴\YhlJ8Ds xr'h ~WSqEsVo' ?CћϨkR5f>pD#+c'8 6r_'upe;)F1 CrB$,zf@ ;뫫ADo[p'Jh7}ڣ'yoX&7"JzOE Y4<9aPsS8΃C w:ӏLףգG~W([cbˋJ=%D&NG9H 2"=HʾJd$Kǻs^wj`:D.x_w_*֚/O L{ s f1[da!=Vh1PIE<YaxN<$z;ۍ46v#uθ蚍ݚQc]tu4vr܄/CTêq]P+.4搭A3ݫh l;;VԳ_|xȇɯJ.^@fヂّ%%(\PTNn2hՌoC1*= ~r #PX$+8;!Mr>M 7 erF_k͍\c 95 9X>rnh(pwi<ɮzg2Z ĸ$(]Md33Y:/#KCA17&O/D]BAi҂rpGsNOx&ܶ gEJ7 ȏ,.zf<ǨGh? s#υ뽠MAQ %p&ƬuwJb*T kh? V4}9ېiTy$z[Jd!9uW߽jT8wg\\+7~(2BsĝbThQxQa9p Vm@ulEe ^ۯ$n|{0{ C/s?a^g_OmCxBp%ֱ0XJ{j=מ* ϏEú[Xuy nØ$ј>%sTrP{EʒϚM%,"iB/هڥ{g޽)!0}Ǩ^ՈL*245E{#B \_L۴?W3j)9*֮o(ΞjB!+?Dljx10oѳ'7?Da\~1!L/4~W_0z؀"29d:M4MwĔ 8Mf2vHNl "F;Z,F=6 1w&*&ŀڨzߎ@(_Ab0)Vt16-F4:W טhGef4a%g8zyw x>q>q\{x ]9x ].:6>CY J"5bC<㥡ؼTyor@ltJꊟ-*E&f4bW\HG6j@vc\ +1;lv=͞Sgjx7c О!Wow@e=0(x?28zC\W<cEP5i/93rDa ;yB٤9&?actuC'>O$TYPLZQ؏*]ZΝ$;"DڝQj38fFF36ܹUU^ޞeY![34o+䃿_%Mb4(h(g!p7)pf ^ x#l?870CN|sEJExe+gBLdyԌ ,7!~ٿO@1s&bW/.xFC>emk&M]V+W7z!pNM;o9u2^5G9~SÏvkobvD@Q2!ꊙ:p8n4E[ot[6|n h uegB~I*砝Q!\$a>_!ķEl9mb@5$L!#X_vx4^b"Rw ѿq u:3lRKh5aP޲VɹExℯybVP<][B((k Iѹs.0!sejyλBU~X:&tH4lr1If&Q2}4J˺䴽c9fT$./Sxc1#p%K*/q^IJ^m:![!*EEIؿG\,VkESrp`k,jE#M,NVN=~ wM"ѱN SY/*:?YKUqN2P`HZLO\!d Tr\5Fv5<6!^a qgR+Dܞ^aN65gMֹ-fjj]/~R-ڊm]QVx)RKM0)4;S plT=Jjʐ@qn\P͐Ĕ Cfjf&.2RȦ.Nm:dn4wETHma4ʝ?'Wh`ˮpk$YȜ7 64:2BR UAӷo9C{ni,fPafSh LyM<^U*9Nzd5#|7^/|d TjCo $$[աSξ6Y;pdv#"v9B|w9-QȨ{Q\=x ϺL>@dĞ#m@ S ӝ֎X㡈TkBDi&k|&Nj0C>1 0T B4_/ro~}ѥowKVo{&9~wO̫:z#ǰiް钡dߥkgKYx'bktet pyif#&x;HjPeqd7'+x˄g-^>Dş`^\8:օpn~y YC_6((UMh=;@Q =A#ӴyD*Б 3q0n-1YL;uoaM5C*:KvqKBf5|y65!^gU#@g/ i] C;Za yNYJEy9\ǿ_x/4@05%] jdHk"3EP̜5 7@Ո/0:/QRz1;|AiIL:>^=@+;R|j#J=QL &AR (] A~}/961Tɥ|eaPgB뛾;‹%1`^%nٯ״c/L^ȳ므jy 1\.xWcQ3C Jn`wV7|.SywJqNS7Yjmlzq}%=K6c <&BlZfŠ97f 3c)LcLW&ٻ<ަQP ms1)N2q/҃OYώOѫ7 Ym?! O9FAy/Wd`Xi§ cap᧊f9k zb銂E)3!>D{Ua&*H_LVy3ytۄt҃uC&KnHo&iGN idd6.k(gXkK&Kp8VYռɿI]8I?+mji6=l-L ")\g8\@saDm/PN/)c?[_ԑB䭛£"t|+P+ #B⛘B),]RC&|C6t`JK}NMb>`'a h;&KqǦ!VgHap r;>^~?m$$:㤁ĄbТP⥟}#*eC&>}eJWg[&Rh4hz%/91Qgt1VjPUϋ2r;&FܭHvjpA#c8u6tD)(MT -$dt2Z+N#~Rѥʔ^m&wmڼOx ڭCޚZ9DzFbϰ:oaCe3DQU+(Tmf8YcXRvLO_cxD(qb1B6=k 餢s& mަ d\c6C^#;)bΈssJ)'(}0PoZ6㨸aǚ 4ݵ6uoGJ7%ppr;ljST P-$@wydk}ESMRa4kvbz54h}N6 !YA,A&su:6# 1[ x˙ebo`# [Z}J!.R .,0q?y3D`C< FLXti28GvejCTK_QezKݲ֑{hJ{ i?,^_>s[账TjTorkjҝq٣?'SnV1_ K'&Gp qSlBGV0qHVCDұtԶn`s)w1 0'T~{L]BJU`ʒ[Tb0k}Rle: I0}%uF3_d6lAhd\4eI=gk~U8޹ W]BO6 B7PL7 a RM"e6>^npyTKEӤh<#x>ń\T)z*V3*JWVQ'o^а Sx(eU` %J {[R7G&#[95&B9P7P"lqly6A}.?ZOׂ?Qf ĩcV $%-;Yce ZZҖa~ s2M~~}{'z\ GD1M(:J2ME=Lw׈9E!"AD13B 3|T{EʊzqlQ( wQ :M;J^PtLK԰n ^*Ftgظa/J[m$Kl[ö/(4_1+^Ї|yփ 4D,#xU+p%N(͊AZZGf*7'(s)"͚M`iһƴpT"o׆gAǺhYbccF5 QY:|4B\<IKCp D}Z=x&~ob 2@( tLlq)x]BQ:lXơ̈́^; e=F*=B ^ep=>-} Q+_M -V1aEP[z8BXڈ> P;L F'ن lw7֥pkCV;J }Š+Z}Ę}#Q') ] {9 .ly&r%1MpLjYb`hpAÆ>@EK^3į1蟰' JIAJ6nï%l~cKqۈx-EQ*ei(ܖS*_l[b* .t787ӗPj FH7&[ƴ )zkO.F@~s ?0~ շu61+)x7-<.UUӄm^bjJS 5ZjDO( 2GStH&IVhc(6Z8Gqf gx(N(eI=-.IDATo ='q-  J8Eg0WShb|TTfc5׳i6To/ / NYZZӋ1S6%chhG# 1L{yEay2-އ>L@ [*>2ŲwRWCSdZdA=03 5 Qfh&hJBbe e,"&-KP*6D6{+^!Dšo~ٲ=?m=[yC9X\>ʨf7UIAa:c"&GhS69=G(S *4mk9𚥲DgX19 *DL& >bC'YhY">"n ~^};/#7ÇF4{NFq^kjAP8%"K"#<"QOtZQ $qFJ?5]!zEkZԆ"n0Yy2"pS9p08rm pͧiBV.9ٔVlPm-P؁}ƾ^Ts@zԆ #W)BoUTl Bkx-՝)#\E/LȤKIo}EGRf D~<1XWw84ٛEXjan*M7tD `:B(bKa[آ# -ӆu(ݡ_ps= О?\x}p_x֪D^;=knkk/Kmk1S1Uc??(7[ŲWf~M8EՅ ͗0:Ҕ `^ ᬒ?p?x |Ϳ^+~0( &*.lI1heBJtJ"FҖ&T\4IOL(ȵ2!vDR({bߡgq9o=|y 7yMg[/RL>|'q [Aq/N-k25b1jI|y駁!wLub*W^)U ?ߊՃo7]&X-כ 3%]. FU4ƠU"(,BPj*e( I JpegzGS8жڳ(#Ў"{ӆxiPU mCoi+ud <Axp.F:}{Я?R=ptt\7-I5bCTӏnؠ&Cu !?Wah+<]ϣQ{g Ioe*A'h|o94V/.|,Q#֎6=R:ۥ/tʲ4NzM5jz{Qᵰ#V v\mqHwIZpaz{DP/Wk>/}#!+IENDB`robocode/robocode/resources/images/explosion/explosion2-60.png0000644000175000017500000007443410205417702024004 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME& 2 IDATxYeWr5tǼ9LfqDDYBeHua_ ~ 'P"`N HE n,V3sysϰ5LR%̪r}{ϼn)ȣo>zVʻ&ie6=Fx[p /y|:ޤ!wY*Kx|#w1~#(7¿~U6Q[pӪ|DBu;?BY X 7oG:^Cmmrrpg(~9Ly7qּB៽5,w>$_"{MWk3<<|#B?6x4(6mm nU9mG?_(GG#YAurSǃ2i-UL}]$p|K3_[3[5ᣥKB߿vOz┭S^?\2L3w&wӬOjᬕoD(N9qW;[$>?0_XB. c U4srHַ\}Qܭ80S@M&+J7>s?va8F7o w[d `&f.j(M:tF4Ihe$n_ܺSE0i~bYӗ (m΀u&e?;\m2lzLX~ ye? n`tWkoLum@ϲyx>>WP!|rDy{$_Okn <0 P\[n 2dND XzK Bbm3Y|Ixl+81__;0VC2,ӆ/TiG[eU0*<gx'8ntO:kWɆEPА$)W#D!A+ ?(o=!ig1/_Nǁ8,)0iJ2'jxX#Gٻ ) R鱺&'N:rʼnZ/uhZJoPcP_e.H +^ni~b GޙWsl+ܑ z!cV|@:Agm$W>3Y+._ԕe-JE51XQ  I`'t)S s53jNX`?f^rdz[S7 ,W_w-ZCX&Zŝ;̞z2tᬥφ 26L1_ixh[ܱ~e a섃.:<`_@Վ| |`.a3Q~τ}ᗟ8?$73rfý-mPT~U{Lx9L:Nc5SjC?9@J::]a b"3 FWw$)$ gYؙ }@fd3zxTRjH^ZʋQ)/$>o-ˁ+6V%|σT -3?"5cX$ӑ͊ʵ~LW+n` #F?7(`xk2<0?0lrY,"i $]C LjNҥ:ͧhbt´u)&ѓ>oM΅. ! }!/|Pl19cӔ$QS o;:,U`fc6q 6 g1_n-Nyx`x*ǦuthEU,rVnB7P#˨AO0QHZæ8v'햣8fN)ʭfS}xؐ_7Աq"p> Xz.FҖ Z0!\G3 M2^n gmtW3Go9TGg,9Nv,F^dLH!P2p |Fzr`,l6pu!<-g9sXxG:4|rQXͅϣ! ˂4¹|o0gK*mvq ͱqk({ \Mpiحa/ ,wzN5S8Y#9}w+YL7?l̿ns lŅ Cu/\zE6ld!Y:3U&Nnbxl>7,#v<ܷYPgjƪA߀?}W tH>CܢPS#*fqXwL,aB`7\O$pNk&]\XhZ˻QvǦi? 5s52.6DkQiih &62f`{vUfs9m>Ƿ32/Td8CAm ?_PM#1T1A6Hᇨy2X.j`7x3 #J=pciptd}w5Y0~đ.NiC,̚I5ۈKTeD6r&uf+wL9 Y&r8ǗCEĉT4 >Y`lB9',2Y "xT K᳉CdVB&L%2/bDS50Nn=C,&#: GU&2X!5#  Rs^oP@HPX"/;0L2sI` bpa=6#y@nr"J[DN2^xvX'IFeP>b.n%FX=g5ld<%SDs$iXgpOu&Ma{!'9 F38GIۆ!@U)Y -9mH}j`QuYĶγ My0̀Jq]B<[(sj-ܭkvtNO%)#X 2uaTt`3澣^\*_lVROx$OȺf/yj8a|OZɰ$HB j@ 匐ceE= *WkwpL)`M`P &ofpʬ6RAB_%RWnB<޴XeVws)t> r ȧT "sܚ2uW0>Чrr0p'w}-xxEar2;,ҦL kN0`Υɂ36Yp#yCāNvsD]S uB-!g= v!X T%P* G5$PI`k==E<s_q[0a揙ߑ4ڌN7F6lĜqj\ W)1DS]Ag-t_f.4Iw$__bÝޱ3|JWi^p][lѼ-}1v3Oi1F2F&c}]a4tq% ar220q\!9bš 8BIy5qTT%8A7IwHO<\'JOxbkx!T=CEC"-NɹE0 _#Y-[qa`Y,/>% ?o ?m95}0i'WS$~N`1U> ER`db^ "P-# 5>sΩB`P%5swIu 69bg8gy p&,_+Te@AayV `0$s l! P ߩs00l"r=sv&RuJ75ؘI {sIeՔ@!$ V=9jO?J‚߲<1-ÿY R8Mć oh=0 ! \?䠁ЧR\~g b (-`,T!)a*ثa3 ~Պ!Gspv0%Ø:/O F  X^w$QBS:ikDT.T2^g 3>7 EI1"m\Bdx6QoWĖA]a557®Ms'UǨ05o`̳HC'[D!8پ5B9^fc m.uHMRY5 66" |9h T nΡxS``v].ۡ|O` d"\ p s#9 J qp)qؚp@I 8B0(P1nOj3l+O2'N)~O WnW IhK%(J]mb'"o`5|cd@tXQ28@3m-b@z*=HTp8K`XH*4:ܕt/pz: TIca7! Do +s0 9˜}CcDsDX8[IC(`2='{ScM{\or#|S}G񟤀#c/[i%]*fJSo)>~xsg ĽON0<$1sHKN -rCgM}a9N! 6 Be*ߓ TF?BTÄin&ĀPPi[,b "I䨘9u\º79[-/*ypqmIA5-d 9a;^qc G uڳ_#2OY>qtUr`[ZboH`~'lyn2C l'x4\x?Ǧ_{B*qsTy(0pPC#5dT Ť*Eh-xhJW+ةa)((6:>B/3t68* 2'.E xu_-|ª٬ؑlO$>&Ul#¤+{gLfa4z~O䢺[;O.\y Ib˴zcAbQ[Vqt [s3 Xxx}g>ąLo"_6zB}(Q=L j$qCM%¢0{D}a2{la?*I܇nF8ݴ8v"p $Zr"yzvׅLlq0dQcq/yMn"'<3+y 2>S \&e|>A2oޕJTJv4 y@3sQpR>s1fIx8(=C- \]* ڔ ho6F&pI%1p޺/{:PNO>xdi3Kͤ@/AAđ8"IuˉZ,90ʟ!+?c#MLzY^OCT2c˓RYW Mp{^WI7| 'Oޔ~v3 bT-<njZ Go`a!Ti>-Dv 5]8› }@uMH`+ 8&SAB ϰ 4 gXs.oG "So0%1h8E $p*ѩ"Mӑ=`cm˦?:KC\(Z 7&RDrI#QKn7ەδ8椢h]$]WgP cݕsl\)M.kA>. 46JpSUP(yW3g[hѾr){i]zMf:BPUa:0 6Mɯ^ W3"k|HLN;J5z fY;lDprO#[lTPc˓esrPty$sW?TC[* c:_`Ky.iGA+Qe]Au,Jg(tU4vBhY5.f]_fX ( IDAT7>;R0ir.[.&JuNf1}rgf01`԰r\]vBr.FtGFGD~fL~(#ZY;cOH<Í$%ۯ§w!%[rPTXݳ1o;_@h6c²{vKT0T2J%;E$*ya.ObV;<\Ƈx&$`hJtC& 4(oIe`9&h0c b gTy4yT-}HmÞg<(\DOv!z? 3[# )wRo#4۲Ӷ|q-oKwՈA>CYӻ, sK,qa[|"V8wX4{60Sv(Ϙq˹ u|/;x6+Cl> ٢cZB{a+lCTy3&Oi$2B2:L&^8^ ]IiHQSZvR[7F)TL.Noܣ+| >4Z H H70LHZ2qܴ*::8{UA ?~loq.J8jkX0X GM[9K&ZhFl$#>!dG{"txfud=`8Uu bИW%zˆ4ws)r.8F$:@Q61POGCNAF9SXP]lTP ӑ摷ѡ )TWlE}_j!۔A/+ÙQet#Q;GJ,>jۮBf RNд[-FZԜ%1 9GDNP{l0%ؖLq씔s_ѧCLM4nj7=^쯰)NWYǫR͚'}z \?QJhJɗs1$? {xOOƤȽR G7N2Mla'(t ?ʦh֌dMتRn+&e ?Ù kNIs 곺4)0i3{۪pehͳQdL6gz5n7C]uFW@,Tw7?ti%XCvG.{*c  9KY Wm4th* L*H5dE"T]Db4N,^}70\W#^M3tI70P%K*k%%5yxfp g\^zD-LqʕTQ2HŞtS`@ #'{ޣv&LLl\ƞ+թqD:o`KHOW)9^L\B5@luL4>0$Dʊ:$+U8u7h9)ہvGȚlDO1.!DCi7@xjT>:Σlw\?ӎ9+ vZw#'5'cj5e9}>7077c_)UHf))^܂Ns7>`RwyIG?zB bGzŢlRQCo!Za!|Ѿ^&Hdbd2;~JM|;C9bwݢjX*WďjXQ()M|1cCGhcQpql4bQ(Na֕W%K.W W;ة`^)cDZqWu™E਒ЮƔS[NŨY,H)OfRK;8zLm{QzSDk)ipxK,ts$SrI4?GoNIv>"s~lNi}v#Bl`K{׏d-'hrQZ_֔?ޔݏQgj_~L8=vǎr4u.W<,m hn sڴ <bdXĎf2XiO3R<*ao9$Z$[lگTJ^[d ]8uXgHX#XLVKٻZv]g~yYkY$ERe[(n A`!oy `yg'hIC "4Աl%JXSok9ys>%]PP=o|7 $R1pDHC9sBHlphGMn|kYVo+{74N69tGKba_ X٨klaXK/0*h?٧S: ƾ&\*DȨAM Mbp=V;8b GvLWX>zy$x_ ݾORt(vGM@rKI 4s8<#MH Y}be!D| U^ up Brk^\V4g!] hkXoyvU1`u/Zo UZ-u2يȳ{RISը6Q ҡPx !g5us"7$ ' Fw}M4Ժ ޙ4ʦuig{5U0ᬒ*05*+"vC:+hqj݂̼);1iW#8(GJub8@$tJDipChs!gSx0T<7ޠO / Rvch7a'8ll!QxYC⥐} cccvMhdMȷoȥ#2j<8ӯgUB:TbuN>/mi\l2!_2~߾H_iYW;(_LA' vW`52|Rx\ Yv5봅VծO9OP6h;Slp!.r  .O~Mg՗ض&vg-P$ A91{*E1\22BPĵ$V;d; n.4E?dAˆ#,.k?jgINf^U2w 4_R3uӉ=on )ZYDӚxquNs&.c23M$$)U{lo4iO=R<1E K߿+ok_~:;{,o=\@mkD{? .Ih !Op;vsK&Ʀp?)+Bpwf,j*3hwRV_PE w 4s1LQ]lp Qk&y#k隑TйbT>66ӠzI4!Ucy7&y+39\- l\WV* c;oŤ^(/D$Z5z[T0Re̚сd&· &cu?B#;@Pר&U}8;#Y4| 4^^#'Q@q1Cc!0}&a "Pt> >zð -[ -ޏ3dW MP! Q qŪr2ee X֗:CBk;*ja58ەC;ʔ3:ŧ pàܘYO q~ f2G˝ZV6ǯSWy%%hchy|iDͮH34Wm12'ѣ2EOzsF^vVb.ӄ,QfHssF5L6Feb/7U:W"h-"u:fAQ=DJ67xLwaBoEҕ@#c. ez1q(ĊD*$z94 OnMҙS,cGvx 99'\Hd:'zO%s3r'ƹ^deX\DC͌{˽[0*XmR}sbAH(In Bk"B'2q(j4Ni͆!첥`.A5>A4PZvC>B>mj-y;3ڎ:atH"Jh&?<|RL3K L!4u(ȫÉw=HG"2#R yB #c2yLRфKmcglt@d-=p/R!FQi&|ܼ (3T''9Ż#󠅳qzrm˕'YK U~2$F8:Gq&rBі{lS{njnzWO}=d^@W439]"aÌA=W! ?'/A/hUHZB.|aQz*kLDBQ\ R"8sԽb 7['Pn– Eh%ܔH 0E>҄o ۦx*j*cuV>]}Ypb-ۺ+a hOk`Uޚ# \%|tV̭\.Zvg`wk\fšmɐDע)?󜬷P^92LB3.soӕpʕVAB:ѓ{f|4Ri4tP$bd+gAbv|kl|Үwي@ZVN}nf5J.ޘ[XUN,<SS:3q 0sp;4f&@8@Y:$ڴtkd%] Ötāf֚^ft.|y)O)7 C2lM=MȍMJQ&8zȥ-N, 2Gmɟ!EtsyƂY4~dasW TĸU�km6{M tvLql&}.SSֱf]Z`+[)߹!R@{"eXջl5' IDATx'0+Pv lp2CNq&sbE#h+²dvAy(]}S{o`w,n \8$WO (JJ F̀O,`oC&'7taG/8>9XA'h1'3ً ȳ 6LTN& \6Z9q]}|5j~GXyl~~b@%ZroRG&u0qK2 ǰH.{F@\"Mi1xYMׁR^6L!ail?|jvw(Vm_} 0|gӸuo/S2T/_ѿi5OWN v6(aT,=lm 8VTzykk@,Sr8k?8OKLx|l_?>g{߿<VǍc9vIChYݛ~iX6I7Rqqp3 2Mmsם|>LI8bHw,E+?<"?ATA=TxvSDzۊlZ1`߫KgcjR}V?hc-dXF%XtZ#Aи9Ǩ1)M;0Q=q.Lӱ4p~jٯ>`{F}8v4cL'E.LVaY)% -@s P^3k2ʤLy vף%'?L:RS|d!Tޛ aDRK~-{~~TIo6{5oR|ֳH3H EcP2/7Y3dg4mK/4Ab1c)|1ᑏ?=7g6umݩsZ !\!D~ΦrM|*vgE6~Ea3}idg\sxNAGUOpR #J j>Hku:"봎Zj `7֜W~![7 A2muJU+M-gW?Yڠ]obVlhY_9-P"DReJ) pUG >l|xvGX:^ w_pk3 LB{R#wos.P}%OͧY 3ct-!ސcT+̷`ԫ`tz6Vh;3xxT_o1Rlb'@Aˢ2 5w<s0?IT 0Z$KɢNV_ %.Z:v/P]H!sδK>'y.G/=Ox7ܟ@JrC a[6X=ݱJOQidʷ%mX1WtnB))nVk:!UenlA#l^no6?zn᪵]Ca~ N*X[p,L'Kv+m4's_n&$Wts[(D&Ib2͔a LAX~G/_#.Aw=7/#3i)_عk+ i3θ鎩>#+#r.sRor, S&<mvFiJiFJ$Jhݲ-++rS#c Rɀzfl^,jmWilgX=L͕#F;7ZR|H3֨l`xn݈^@}Ul_XƱ71n¦@$**GhTg |c2VNYeV8;> ~cɎvh0>Pd '*7>>/Oh3rO?W /;B`l^Be`vM!d*PpF8)mڌ8G %^MU#m@18j-ɫ(VBs ;]Bhhg.8|V dv5L%P:;ܽG;RҤq1& OW#oJcq=VOqފ8t5Q DcE 9\ o9DWݎlˎ)$r=uWe ܠ8]-[J)#ooYbP3<_B g?si柵77nx{hxVWG8; VQ߱)i-\v{w  1ޠ2Sz! cV>ߔZuvNsژq{X+{[-ܶ6zmD" ]`Ju `);[Xͣ~gh5\I1*i7.QWx 7{4liɯ'WB#dwҶTzfgβpDyۉճƍvF0F]_2?^H3A℔'7Isojh2 t d-78.]qS }G`G| \KœŤ5}\~P:T]e;F [$y1Զac_#:{yWwN_QuЮ G.x/>o<_^SeeQ nW~sy>z oғT"Ah l1GDx9¹c$"`jϮQnmĕD #42E EmB!+-y}x I}uqh}zIuswﴎczW |ZV'"M#jo3SD!.rZ&g e-#p-[8CV° \.=)7,Zn #5_%dѴ _ ڇCnYkvihG *n!HGG~UyZo8gͭxm|ǠiK9DOqrSAlQUXL&j-uUM똬f`]Ҵ١ qzJtNSn˜[$xCo~c섳/Q>,?r=lCv>%*[ :ZҼcQ;{_B-kntM􎝻ϋC.b'kBG/)Gԁ4fkFyU-ŝц;im|w(T!?8jlwثHpIĬ.5b*&N tKϯ*a2I {h>fF&kyMnn(D +80Azj9Qq4-Ǭٶ|?hEN]G/8n_Bkhv [ 8|8 DP2CѰCP!mG'k60ϖcj<ܩn֪p?D <~{3l5]Z[65ŦL$; gv3]]xB,Ѵut[u osgHjzT稛l 'ȬsD[ ìnƣ27DLvo -^>&0S6D :"d$G2oo3dʆ?lnϓ[PߚUO&޸â.uiyl{b/a8roPY$#^ '9Z3.Ix>ǻ礴m+^ٍ]-L6km 6>>O:;m>|m__WZ;:#p/ CjHwfs% 6.в5` $|h.Pe //;U?cp3|)r<(/8Q%/ :CG)gsM6:U%Fs#8#Z?͂pbkYcۙOQS3G}Mf5ޮr~xourږ۾ܻ myR&R0%U6ּfz+m_ԽZËZܦ(T/K27ڳ;r8MK^@XXx'?_m9[F5t~ehզJ58v9#Q,\y570).1|Qrh(d4'LrXqNmh#2F+ܡe{kvo@Y%fV丱qm;d•RЩt6j!XOeH|56rCuERf\7 \u1Pzm??Xg1'oÎ]bR"lH~JćDΑ^ ٸx&8Ev)yTp:Y}C١nDGi$-g`Mh'VSe!S1vP﷑wfSGwIUԃUC"Bâ _Uoɩ]XvXieXo!qFH3o;';׎JuLj'ʿ6o;>|gGp)+ b/hi|x! L/RBSaˡ¤u!T2xҀaz*q5WWZHWd`ϬjU6N*Y`wy @O2HؔWL\'4 /ᆀkC61,*x/4R\Se;6! v翈t2k W ^霒ޚzvlEN*5Bm{ڪ Yu rR9HLoYΫ^8E*#j `, bYN) d'\4Ki+|w=[:a^" 3<' 4H>e&/xWЪ kOPpT7J-cX${cbu~9Gxe'4g-8P^RN~wU /8chG(^ъmBԺTERRdj~bWp5l)~`'DhvJT7 G\ׇ^]%^>&96g<ҥp|[KͿç>i1*M$z :.BmL4н Sn| !ƒ/>QCyqAOS?lG߫۩n-vN\}in`:+g/"F}p[wlZV^BdwY+RF}Rjg#vf)DŽs141ȼSG+~(;qyë㋭єH.K#q|DU"1镺zўFMΩT{А(IoE"rhb(./w|eM{ܫ^faG4E8A7ѤxO9܃>gIDATDbS94jMrQbMo)bg3Zw M&7A9S77{ѽXU#8<@pypq|/U{P$CBrPPPWjM 2Vh t1khԦdGEq\1K7nnJFOѲHD-tE cU.Y'i`ByN%fKlQD\ };vmځI2l+~BH.蒢- %6a>E]/|ix. ? yV/7lX;=Ƀ~5 ;kYlJFțX8$1) !6.R1 BE1)I-C"*ۉ>8♢j/#\w]-{*z|NDĸaS,njEYQQeyv-h揻)?sj;%4O>' wRRC'O  {TTK_y #9. ~FH{NX+g$G ~ @|-,wq`8|HxBF% p8%"a/(eKZS.)%.+J~sFݧCꮊ(*GEϯQGE&9Gn<fz6jJ1%%w[;u {xD/1A; 411(A#t6G|ZV$٧=#"0E2AF2="[LZBq<9槄8S )lar9&[S#ag/~}įpg=7IxtEM 5ÒAn!rD+SGHe qN%h"ET]GhqyŭAĦ<߯܇2DF-j(/'oPLH^)F3]M&$^Mqvmcx՟ўStP[G'j8,Ѱ@u [R{; XY`t #HX 5]0 *9' 6tݖj9 JO3 x񗰰 崫 a-vŒ] ț5{Qh#.p1 A$-7i#I~FeG 1G$Q>p[Q nMsH!!  Rlz*>Dm˖J@=N; K:fZ>Sr&o8~%3ioRq OpQI, UP2`49m\0Y:c3d6řʑ uZ9o,DNG!fJzT2kG7  vX1Yk@˧P-:)1NhQI;?͛"H\:"n`'jZpWaH:Ywb!u#dr c]8=E~H"ֆtWx U~ISn[14R$-ukx+f~ZHxs!a%#r(0:ͅ,9=nm)gbfXTjR30  _L5ǯw[O{[& p6BD:]7{EBpcFKT)S4رUM "`S]f10_;6FeiIs|w9d%= @r9̘ocÀ믘h{aVl [V>vA̟ 1RKL֬Ɪc:b D !ω.|ƪ)tݒF2=Jps:!Ƞ oO:ypKTV-z0r^dA6dGf=8yér| jFu.+Q "DSD^` 9}yD~ ( bq:ĝv- :7[r09L.1ܧ09 F*K 5-c/ ԉnt9Ml_0s|5 gSb m8'Q=1dAp1tdp{D}rg1)|4r 5WT=4s; cjVyE-b]B= c5{օ1[O"Nhg ,,Qt9}J_"2;s2G݁Nn˱^TӸIoh SV/h {bW[ p}y#\FJy{xq#`f99ˣ]u%%QɜLC`F%5d8-NUWYȐBZi1PZ =1oAz=eӏY·#G̣Kc[<]zנ31 _??JMUN$T͚]1䖴%q?#/: v{:*܁ &}w3wʹ^ɼ.o@'jx(<]~/. |vS9Y)*^ Tc0k[0RA4 D*+*#`Gz> 2" RFBEƎM;İGcm7+Wkp W2+Bn{@]( B~ A,!7P:%r/4ny>Y ϺiA'pB1!#J=>F!o w0RF櫊z4$!qFda vpQP,Ft,PF$v$B)y#qYJ~3`y97꼸 ^NNQ& rCQ,ȹ?D\#6no _ȗ]&q]7AyMxq%p Gpbp+;/+8,N1fLؓh40#a \XfC1S(=؈@&,RBȧM O c~5W¯OoLlVa5S'( li GO^u3y _[ˇ?7F _P9>"AJ9z$77Hk5b6Y**&#DL f͚FJՖ aHd31$ni[_a|#||m{,9TQDHjp} ?C5L?'xL-Kڼw'g&w u6|IENDB`robocode/robocode/resources/images/explosion/explosion2-14.png0000644000175000017500000000557310205417702024001 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%0m IDATxo\y9 9R(iɖZ,qbXN R]ȋ.?C#dU]u'@*`.n"bKeRDJ|ə};' 6HCXw>; B!B!B!B!B!B!B!B!B!B!BgI}.ֹ_^WtԯA3SӊU7vUuwqv-y֫R5+_S\]0Tic  k:l1q@qQ0*{hBwsojhg|R0Nj}#-d^BsV7ɲ{>1 R0i4oj8zP;%oL~-Ѧ -ilmNflaCq>gտk(|(Gbb6m.0V p6IurAbN'YzL Ng|o⪳蚫' >Ga8-rpE(Qn$ƞyiP|C| ^(q{]2!+xNnSS2x֍ =B?0{ Hl܍q\e?tC{*nal7h Í]E'PǤ\kYvT;_qgek/a4ADLc2~Ǚ)yCe,nOdO+]`_" |AW5;h|C)!E|՝DxXf̍eRQXskk=<:ךF e틷;Ҝ!sx<9;{ yKVw&]r374+J%糣=O+9`}ƲVX2'tma NpzMjEYY =-Fkv6K?{gDzH%Lrf1DgI&bwAg Z'}{P$|<5NuL~RFx#\\/L~H\"Ҏ u%҈vpT{|ZyAJ:5 xI 6%I]'rGm !%Jk$8QB6i1!NXKA OyiY0͋y/vᵚQz(dF6G}4diCj1Oe0ph o4(= _ c!9j#ӊU  ϑ|([`O=cŽ9X^[=82wUJ_ _kAfPmiAax>hM?;. 9ؽ]n]>SO+z!B!B!B!B!B!B!B!B!B!B!B_LIENDB`robocode/robocode/resources/images/explosion/explosion2-43.png0000644000175000017500000003665610205417702024011 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%7VP IDATxٯ_yy5=s%J`[t82ꠉi -8 @M/|S轥zzuP4RDnP4c'e[)Ro^;]{ /7\k=< /wBpXp `{#+=\{A|Y͝G k9xsxZP >o? .I 6W3}IV{6Q1=s{B,W}ڔ@|ώB%6Q[4sEbýUuYĎaxt-k}{W_5;{,LQ*Y ފb\D3Jc6Th'0N@ϡ03O+)5im9mxZ6ox^I ~_}Y( h%ǚlĹ2haPHa\Db#'( zQF%1%˺FeM$k=Ջ >Y 6]߻O+PA$f+-o]|5/ģS_(.*:*Fe ȘO6JRlO9P #%yhE]טhAV˂n$S*z F/g{~k/Ṍu;7/Il&}xU4VzáE+Q)o">/rrR +2"[rM:aHTsY3jɊXQ6%VܼP=핸 4_5F 8.'gqM3ϋWZ]IN${(b|A#<HwBUƖSoW{-$#5(jA #HuPvs#Hu #r [*$U(@Zb-k=D<}&w^lb :,09#x!QT IR䬓3IFV@b49:ǹί#Y@a.B`NRr$gcv5$Js˻7֗\=2n\!aoK@6Dbzj`kz֏ G*7.)~RF$®$3!`eEYnLSLsBbo bXGN 2!br_uEW7ܛvf)j/8rs U`#A"Eaj5DR"̅gs'=uKc (xob0{jE515glk)HYAQ i,N4þĚ^!z)) _`UĦY!q|6w1]xےVS2$_Z =GjmdzQF@B@nYE_aFC}H"{eB Hb[T d%GXP;Qz KE3ҨgOPgfKG8 O|) kp/5MRX'qJ")~W7Aʑ#*!0C|60n_P9ʭ!&BmKIA+X9X: RɲzT(bJ0JYz#GRh'P( -V bu4[$)!L %Bj叐fRaH??>x$y AUA̒r _ǻg?P8ﰜBzxﱵF0Dh(j5D&i2 V0sPP{#fIœP i{7gs,{HJDD%JkDZFg%q{XQ0+‸~Kx(;Ec+oϭ 'd[jtTY3Z A%/a1jDpeyf]ǀLF `#UPC-NA"a}KXOO!! vx =By b/^REDDY p,OR!ѻLm 8a8m_u|R\+|+2h/!EE:zˤ1^C#:0ڦ 0a!a V <(@ aQ40rg(3T"kK5X * !/bXG#!rN`;4邠4"x Қ-9gb+&~f1;z4 5ӱ`Xs|H@Qxéf6 }#8ޞ8CSJC0 =P$H7P Y:(`jJQ PWPS+ObIPB-t. @ykD-CGf=óC=Ocs/|l܄ATΈ8Ù>|)KĵAkA!|^zRA!V d1$ā;K<\B9* ) q;`f&%`Y * lK N0=l­%|0}XD }!ܑ?MFGO3c^ckϵܥ}LpޔDXKӜ5 y (ƚU F@a5xVi1HAI픀iRx n9dUsJj8X1pPcEf _܀3k5:lO@/^aw@7)|'-Oi3G|ࣰ+O$E%Ƿ/_`q!&M%f'+ t䓅4G4jFAFQyM7Fy* B aU@UA? &QPG6|(&)?thA&~Gdvn7 C!xqDd>PPK4GHbX  AFynM*^PYs繆3y dҪ"i>bZq>AHQJ3jnj ʉKڣ Mvۯhc蘥N>B*=RM66, K!AVpFx[MpٱYۻ6?XUc{LrW2 go܀%`'!i$(f.R!:Nod1>+8Ȍ|؉ ~œ?/ܚ)~&?J9쥬)#q2v[h"#*Hz 5)!|x=WR4ނBz2U,N!U!ˆF $"T*p8;+VQUt{̙ >ED럣(W. ߾ތꈼΘ37 uɟܚfa= q{)XŪkJO]w:;?k,'Yb)`X%hX"DK:O-y]a""| Cn P;l5WGX#*'9|5GDxN}V`cѨ"|n֝f':kgDO!|k4&}ri#Yzv k")L_fmeJ_zAYZ._\k'c^?98Bu}#!^OF"wVק1=tJJkP"'AΛ[n %(r7 4mP3>n{Fw#:GML3%ޛ$=tI<*^l{WׁJ)(n =gw YM(Q=M_$$}caؿ ;4Ⱦ;9ox=iu%`pW슥X/5z?"ʊyydߺ `A>0UzUp:,VPIVsѠ 'f A5}ϰ^A<[p3-{` ~ 8߄zO7~<$:r ]`\vcpv!9()*goi)bx8=\$|Y6^Q<> TFYQ`u/7ωVH'ph k\9%B#M{s HO݁Qz!*>Q /%EN(5l%nb/9ǡT)|@\}i :pܣ?~J}`vpO? g[B5;l,?&6m viH׾ڤsܡ/ LA1?e<Chq__q~ބ*8q ҂p"GXN&KS&r_4.aOg-;\@@u_6~\,zK6JR=pjƿQw@^_,9tmrl2ӈ#)MWp_nǂ/$dj"kb3"rpn #$944ϒ D5 n#h՘V\ܷj0Bۯx|VKҥ*C:YgbE-FhA=.1Ⱦ-so7x+*]zYpJT21gPk)8rVQC܋1̉89JhʵbrBiG!h0߯;xe h !*xg:!/1*؜H* +3sz|}`EL @*rB  E!G5 (AJ/idkWכᓐCҝ e+`8hpNrܘ?H(leCVjc9ǟ~z+ o_ STc2c*'{8;B!m*x#IVDL1SBG"NJ" =qa*Q|H\s)D bXEL_ޝW)`/@I QLSeJ]QbC*GH*C9dw/Kt8}cGEH+pe:T{Kh+)83n>hZH6D/,Mc5Kx1 A:d) Jp|{(2(!1 bt#MܟPlh}lm6fI!pJD5BRMFq}z vr!5~X3cSdrHRWTˈ٬f7h'DRGD;<ǘES9J.mHYvAR8ՇQȣ*ۺ4.0n1 \GeuSݔP`3 ׏N!&Va^#MsRqmMS+o:Sl]l]NS iD4NfH(]JsFf7sh9[s GM'ma&'喂[N~?ˉ8]iVA64mK!C#9qSX3)I.Rwdxx5OVT&'#j#l'}")7oFik|]VT3j+&Y6`qJ Ls-qIq4X"TIyUzc4sQft. qMqOmBI"Leb4Dj n|֝F@4ߋuH;֢m;QCi>u,VQc`Y24hM"ǛCB& ElGnWV@-D:H1ByB1+oSkPt|Swג— XtLl(5TM`QڀP"BaQĵ"_ vWu)NBG [7I8 u 'H!\t C/Q%{ =*9)vUIOH(ƼcMrG,qAQ2 73b0!-%m4gKN3ab .Fpy\С'ot7]#T :P[`UE"vҊn^tp~ \9 }t-{A` " ) zf|@h'3Qҁ2q(B*$ITh߸'Vo;oz؃r8D"ӆ}sD=6`stB& #X#? A+i`|FHWtfkoLQ|w5 7qPaHe s "ߘc(鯬A(7C9JXUu> tw|wʑN-0Hc,v X GUzFO8)V[!F9C7^hRNQH5_ V[>zcaaA=ś=,'Wh^RqaY3.g6-\T hŋo娓øW8W`ML+(ݜkS8Q恙 !n?O;`wٶ n3zYTSGl_OjȣA/IDATP%er.L1>`_-<DjB)MjKx5˞ Yb))vҧX>nMWذ T]4HZt==oa~cuZ2Xi|@:P98w ?@;8qHUϑYR񅽊Taf!}xq}=k R̳%N@>[,0O5ևd'@HmݸI=\RӺ-+<:DRQEJ@{(ijxJcxF^pǖ ^3<ͧ*y_OMMHxПbt4sbZR]yH |Եn"BbR@ ,2L<"H,La/o=$P;h9Ō俐qr6l'yF翻$-͙ CU5Tcdvw/zwHn*׼vԼ>xL@vtrJFFQڇքbAm K}H}\䌅^18kޮ{+(yIgoKرf-r=v5.!ʏmJ7v\[Йuۃ6_ݣY_@k(7n$MJB$gqrBΈ9+[ZkyP{)l|9⩃l"B>G,4/C:Ce,J83NzFN);{g"nOuU^p8&I?$RdjN-KʬdpƎ߰qOuX KIOA&(~ *'07IOK,ט ɗ,fƍpR#Xs58:ՏV CPfAa e+yooU`͡hŊ#rKPu\Fh[\{\;sh}8Xa Ct',9i\xwk|x DQ-ù/_ @!=Hu;xy\Bj웂\z"mRQMa0F>aNpf蒹Yd>MFhؼ"_?niL`SHIx"߼!8Q s7kN AI졝H $8 #9Dۚ3 3G>ŝAMl݃O< k?jI&eIP*ŘkJ7u`eo=8澣ws- VRN)%WzH &WKVC.ÙjRty[4 Sȇ18raDFZ+L#\v>A+j͏J~w{56*kTaɳ A*j/ ix6y[ZbeIUM|.k -0d?9{ú}̢la ]!Nu&B$[4c&9@E^9 *ys_rjcM`ӽ0plaS@֘4 1QmtBѶٸnEFP>}&:4rֱeP8.O#nHANB]$AͥKo٘R%4_ $siރ`Ϋ H}b"|W+:=ػ6AWa0TnLJ!;)DV0B"-*b$cJcP!Z+qcwaaLJtۇآkymaƈg3-4kv`{*wfymE(-t6 ?ށ?%_r|bHIN_bVeBq~nuk(!x?-*EQTNjp۵`z n{1m;X[w~֠Y2G(GZrF]XGp}:ھ?Ce fRǎ=Ğ|27&aFX!o NB2I ֌X`PՁH۶_ZJ $vqi" ;|<-QrmcDւ{_ױ\8Zo!60\gH+\|W[`^$򯲓gvdB7̹lTi8YCflځ3VUPZuwF>tDsx8?-e` mo`/4;>}O'}ST=2ESNӵ f8›J' 9`o Owp"F wPðayC C5#E"t/ 8.WfcUcdGl*=0 &_=dMɶqa$$\No-lwJ'+4VH*ENr.RÛ n !0SjJ}5G웊-)WTKbԬϞE3*Tٴ İ`oN/CHL57#.28)Hsva9t#7tW, NP OXY B !ŖD*flU%E([`9pBc 3" ~w՜~)}+WLm߅x#Gf} )a^ P\JsV 6W~H5A)))q1^ω}jeIADB 2g$ch,%xEbuXV2./HX?5A!J:#@$#mJ(RP)9@]m㝥WsfUǨ|>ޢ]Pqv k rcTM, ok( ,̊rqK< :Ba+qbdug ~[8wLxd|첟Zg% oO.^ts{!;E xS Y$Jwp)>zA]̼ub)yuc ` c^#|}~4b+ųsbj5dQo!gk ~qϰ4(GK5F9=f%v ڢ#ShiH=/p )=]g0l˒?| !vx_uX#' 8CkLj)UH]#.A{N E" a^ HT8cxM\3%Wx~-cxr1@H wϨ. ƍ̌# #D"-~ry,^[H0:s8'=S}ͳhBA)`3 /qbT}X~ 'QMJ/pdL0"93g1c3-EN0V$xϯL',h[6#&3TMd@0# JaE˷94D&U{V}MPmT3FLqٔ{[PPϣz0 H}?q3Tz+JCPFM0.)lI1ladJT4'5xƓ/JŎmYphTLℑK7rہ?l?1Vz&Z4>`iO)+ ک33h 8J  *'JEIgvw]ܣhVqRF V,IjJWr{K IQG a YLp2zH=y`Jur]C[yT[5y!5ړYsѓ>9+oK W'x1pJTs1lVƹK&0y`gCրdBRHp]L*NED Z-5F.1^\1SRf5H gsǙc[ܓBs {ؼf:e iBlEϊ٭4QF7QMA&!Zw)@Zrj D e[쮴و4[yNp+Q}6g~7 44,d/:"ᠥ\Z&!V6# J;D+U5#)&1j 2Cf4a"亡5/皸oIrg}gIZ0bRSYo+`6Қ)Cyb/9NڌY&#d,vm(t k"Uhq)2GFe@#󳑵k%w-DQWګ}M1i)4+ M&SV5".Y%E#ZR F뒠Dܜ!ī9k{Rͨnbr})_ay(gAk!@E?d ~~  LĿ:̛Lti(A( (m"y "':bė$FKǒ޿yoKaunȲrLGQhTeI D;tk JB)!SW,1(W%JP m]a}g<sKw5ek5L3akf8ÙeJ&t&%˽sw+br~qZ']U*I;§ˉ偰v-RWxpc c#s147j)sNtAS8JŪ tOb'4%jR1id\:0)̪fԁxa9皼gңV`~K>nxՖ|<V;T`[L +EbuA\rA ֦]?=X\Hp IG Qu̱X麍( %@I?V>PEPl\0}67RTᥳuh;/] wӏA?LO(FGuo5&goI/j` ݃csFza&zV%ҤȚP@Ƀ8K4o|\?!>^/ı=2{ 6/u]Gpfypa kбMD/є$ND*׭:޿#G $f!A~T?rSc}fA]Wln~7nkΎbP@l9Gg>$=TKH"s`'خ+/(xv)r_$y`ٽtPæ@<-8(1 X`X`X`X`,IENDB`robocode/robocode/resources/images/explosion/explosion1-15.png0000644000175000017500000003756210205417702024004 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME$40. IDATx[ǒKUwe]H6Ḿ`~ lj7k`Ƀc8m3H$uKu]2U]ݫ{]x.VwWWeDFFFw8; c63NxY&Vύq]~-댫z }eI-)kTqaIT"l(Ήpts&[,LΊTՎAHg)kT}#J ]EX)Z6+XU8q=]Ꝅ:RԊ~u)JHu308? -YVw._!‘Vex,5h;"պ%]TZ<*XIgA(^!ʨ:bV;>< 7ar8MEJp:Wˎ5x53>0cYw4>p|y;.?[?y9ZhZqҭB9~5&A)`3v?y޷)+EY?_j4Ye ˄kOX@SU8q ) ye}Mj\ >U.hB(Zgx}xp8(Ҟxi4G+pu *{|;H;_B=k6JPgOJǟx)jclta~7?l~B4'鍰iY׶  q+_'uv xjnפ.xw=ŷ_ L0q;޷ &s.So2}*pCEzwv}Rac2oY%j+k~05e2 U^n 'up;~-ǞS$3ŋzZKmnjItdvx2nj7reAR^vbw+Y3{]#S?M_0]EХcE׎w_~B%8B_Wf{S$~mI0/Ŷt`vX.m{pZ\vfZ)R..GׂݙӐkZm|]9,^ȏdυDZOb,Zք_W -Mh葿b4sB*}pn[!aI>|ZXD/v(AϮQ#39g"6_ԗ P3B^ S#ZnMxtYo:JD[)7e>]VO m(u`yy2?Ʒ3++`:؍,(<vAALʸ嗀ǕSFx\<~ +YG TK yqRÊjkN)¹_'0 chēˁ^Ǫv-;`y~YƲA5 \O g<~x6f^ F kN Wty-/ip9Q@7{&, ~Z]rF˚bkٟ&Қ lU-@ L G]פe0WQWx=6ךQ6J|T@gP#+zǯ0{|w1xE{aZ(G2ǰp;gy ~7X}m_٫45Ґ& M?mCQ2 z)m~xL<>wwF哣q.2hAݼA=l_ <"5>ycZl遦:P-,y fhj>yF4DkϤMNk)5׊ :mQB Ma {sQ3IWfO!b~xOcA*Cs4;({PL O(&gVTۀ9ēWJ`"i5oKeMGV4WK/|b4暟Le^xup0+ґG-eJֲjg44[͂. -93^1;ctYD+caR6aAS6\ ziL?`xuU9ZV loܩb?I ~8o= ҩ l v v{o"mnwVEHp((DZM] n޶B5ca8B37ҰtR `z·Z062cёsk>쿒58PCslUx@JBbV²VoFKm_Vh^ԕuo+`8ư.yE4E.Yq9+z0csBf!=ΥAA}*6~މV 0՚ӹT ˿P oѤh'F3ܐ$%ԅgV[[eMz;FHT U+ ~N9*%ߨ{wҰK׽n8n_;/S{Mjypѩ[3k|QB`q_{\XzY*j83LuRn+g%x`ə0;\HM^ L⪳:/Pȧ:k*ټNwYX:EySQP찬5CQSAU$Ea}[ؤI3G/Qn X| k;?\AΛn.ɰr]|Svmpx;:`vLٿv,4$Hyճ}>l].ЖJe3ێ i`gimd.uZhD%vXI(, p\]6(fFֿ| A B Oov Wx.c1B7F=7 y'{D92{j=~?\gji%JrmqKPJ?|cԪXyBUW[nZ7KU.==)R=h9RWw5_ [sR.3 &GRCL+p81+k 5fx^j>@J0BCMXAy7;(7q&?y| .5^7M񦞟N5< AH}湳bQ_~G1BEY)|ouUۚV9)EYhʖPDcKZ*S?vi-شe.D~46?g\3W8`xŷ=BQl ~id^Qٛt]%xx=Cߕܫ6'](CЅAY˼-+*}}ڨ_?繂nn>_ISg낙z\ Xl9y!hI'N~%eߵ}Զ/"<^~ЇpiR8CaK{h0՞ uSu.!#rn^p#4:_~W?Ʋ*pgWhf: $*5BmXV BW[ktEq^'5v;V`[f.tܐ׊?t/ ΤVe)Bc >[Yl4(!35yۧ}M\bݺ33|OaTפ^Q2k 5noI?o#g@Q+.괳}.USL^O-8 ku@RQK֐9 _;~N>R8"L6΋sӇH7U{8le:UNԊӹnaG#Tu*9*,{SE5H3.t3Bh~;:m/W~iL| Oj5j֧^a :A4>O%@9kjPZP3s(kkmq 03BRkvW{M Dj5B`xEUkްwj֩^2=_ϧf$$v+lAszD| xj9|``( س賟{>fQ ^rl:ס~~65BجO'01'h qFi󺏳7,2%R(؀,Ek & žWT S6&.Fס^r0; F_+;g̣ TĬPvu]Oumŏ@ yQʣRd. 8o+f]_R͔:y KM-;ӍT6IAW(oVx)抱,ju[5br]2(Pbi0C+iB2^ ZGTxΖpG!gcBA; ʧV% gѝ4t nOoxCj坢kKԯKP7e߶4<\G+_ 1 C>. gm3}^W%bKbR GHcYT~ȴ^(]b{ ºSJӏ4=#N Qo*fʶ]^ p{K*+H&Nߏ+lNn)S26P ɺXMf=idu+, XQq'Д;-$8CpbgǞ,W+-~b~(݇`Y-$u2Ԛ5h~6w-MۏCG9#`!MVHJ)s 8},v,v7ã]C [ @~~,8o:@5~0 H_\@e X5ıЂ~Q3TYυ" |װl_ \kp !QVeru)4ŖSkQ˖mFe=Zhl %_i63 H/Lj]ױJi˺lU:Q;,T0ҫ,<~pƿx5fCK߶>CHNWŖf͊%Jem ޻XYV?2p&)*NQJܫ0q+b e!任вizFpe'lzQaZ¡ H~qX7bziac yI`ywhAZzEx@13~zTwCob;jS ީ߶ N5<'NQ$6O|k@nuO~m [N>@n 9x֦zcr5i>ו`mGrAzL&NVwpm宜KT%'ǖY\s4mB(TvZt#0Kis~CP=t̅z4(`[t&`Jko/6jj:v܊ka=-cayneB] G;C9@ۡu|Cޡ]W-moDQ,R1-a_AT,` !]&Q^RaQ 8Pü`z\88\*Can"Z3tk_/X-/ 9 A!}pF0 0(bxx}9Dw=@x9y8O˿di5f RX&G?0wcУZ:W(?skzULQzWmeT4ӠF&m]F(F/ \Dہk |,n./Zkg4ӄb铱w&, I}VQ!E`Tej,: ݄BMaQ0qV;el-Dj3 k}N1 dα\sYn ͢ҘYlwZfd亜 $ב2&:ӘۘV fGGG1 .sH'X;RBVxrνEx4ZFQohzT^ivH͊F+NkӕsQ9żXi|k]Q@NYsYhth F-O=9zQΟd*Y`dQ o@$j"NT/U]còR "8b}@MX5O^(Y6*ֽz qxsmV: s j&_'/`y:qeH`S>0ґ.+9mI(4i$:j "x^1=6+̪{5|t\uA+%#<g? uIDAT{6_&7JB a (TB"l8jG%DeZ%H^Wqhf#Х۾]su<-lDž_e1Bc}Ya:çazgWm*jb[AʭA 2ڨ'9V a vhkN;A Mzͫ "F\osP:{WcOz8pqvÌOz"GX;8C`҅ ^vM`- fc-t4qCn^þ0m̷npa P_䥮9Yߓj0j5=4jFա;ߪQ K¡| ~J"] 22oWNGgu.-bX{N{,_ 5KϵٶvVd^1$,G(o:tD'B8m1I "r4 zEWk112EZbDs-KS.d`j>Mx,>u~Wy:W +Nn:n@*e]F-:Y]3" %F^1f6i4V},/qh4@-=׻0Vd|%XWOk2/$t"y RY;"N墬UpfU5;? 4WL1.I9-]ol;t⍝Fi`M{W%HKuXxiCc`YTf&9^3EM bUU4)F4[1>7?V`f0.vɀҀvZ@}ۘ7+eG`h%'`#bvocj m*LeD Y-`hҁ:U_X=%D3O@ i&n(jͤ!Vo;mm7gK ӷ}ƚd"2BƝ)^W!]V!L`cDwV+0Z#˵e.6-Rÿmwe CY*$<4 -9]'~gY%OՁ8/Ci3x$GkbdZm*pla8Af\iZu1< P ,%qVw| (pz?`c v;"Gog 9ϋ@VHx1To]ifY zV*O9FÀW84~c^/ئrY -fmdZ&WhB|n.疲Iu lXV=gUBDaGŒ98fJFg5Wst /Wp5L FHXH ecsA;M1 upZaKE?v5FH҂M`FkL3 ލYazE=Z5"`fi:Sϭ4t M%k wיөj.Z~_t}{% 6(=+N8fHC$^T (=ôB1j/,k~Ib"B(dM48鄞EF+BJ!3`_1+=K+̾dBUS}shB 38Y߭_D+;|wȚa4pj8;KI"*L@ W*"WrMiL+Ţ槁Jѵ~(1ҩ:PLag▨U‹oz3G_`sA_})KlxMAfwfhޫ?U|m՜O'0q*@hL' $ץ0Ť(fPyt 7;$*c텎v?ePifQϳ?kҼ{!^.f>(+ +h&!55'QJdElXl^ <mT6xW6zUba0c#ԴGZ?a㏉mc;(JH+MY"k*Ɗuat8) 9 TVS8Gfr)\wT~K%F{7W&ZU $Ki-(s)aH$TZ<k Rck#]Uh@욻UrVɱ ¯]VEYT=Z<*тDS"cս4 `/4]ժ BVyW364Z ݢ!Y//{$~KBfPJ@7ހd\tUӊԄڃphs~69Ǥw="u%e*`h|;FeXFLt Vz"Nτ'>GȨJlm)nᏱs:YfX3{z؅QW>;}+^ǝKͿ"| ʯ֌%MBC{ ~LTiWܪ?*gqcH3/5eD5KQZYOeℚ>tx W@׳Oy0+4Sq⊭Bo,W`;DPʐ3ab}~>9q}܏)8}y1f=5=Sz^B3J5*0e1F=Gy'cT*֡L!]A3Q{&SUxCt\(NCQ`'%IBXTK+ׂD0)o((UbfX+n;槿UU c"h^a hC,TD4T3hj#LT.tO7UG9O!ܙrETAWϳ"SG(P}H|{Sʘn&ST@8SPhQDz+J8w t9jYC yǵ,税=3='U0JeR* 2k-, ٙu)&Zk۹1B>>n]i~3>M%zƯʱZ?Q;Ѳ&o \ժUmec*D jSJӋB8Po%=8aGmϞ 3J2}~mvџ<$o;\G}[T=o,${$ƓCk:LØwZM(.k*oZk%ѱSJzM,U&*)s37 {Zq#\Ŕuftcz>-r^TKlfFr HYTp冹V;"E)ؽ NZ\@WC*՘8 yQV,%BS[!*W :QjBURGH: "c<$4$2(QA0^ a:VT֢i6f]S?KHc*ErM#]Y淤[ȚÕ±f4ؘ8r8| %IZJWеZP5!禑V}ɕ__BS$5JM7+gM'B2}P\+vW1ZȝJ&g> i w_8(]"@ xyf'CQ Ot^*rvE\_ѯ,O/ 4:RRP@T:EҬ`s,XݺDH:L܃Oj ^x̅P9f( uMPz3%gpQXj-Fhzx~y)1ösӰj`3 W?b)*xF f5(`+Bj/bV8Q^(zi}O%<}EZ:VqG!C\BrU 8:f`Y66ݜzm5Ct,`CF[yutPug=IˠH͊!$C?,ޣNP^YzVB z e_\Db(Uk]:?#ר(J?6Oe3+9ŊW8WwwiglgS!P.$}JԞc%`B!JjVpwxJ%A:t=wx~'RPg `$֟G.2ʑU!4/z^vP *Hq-iBτd.mmurfhMhHU ~R3S{4 [Rdžו֑kOʣ W9HribFY(V}0cGJ i-u nGʵ19`B/=_V$jTO_u­7e3:KM'L'5I`K88K_lTJgVFj5gq7k% %gJыߕǙgAig~2Ձ,q,!eЫBѳ3VeZxJ zqBU5Ipc(9;LScV+fa[_8oVxNu&,9Kk1~ͩJe&JklmMptԺU}bH_9Zz*fO= m aϱ RGiSא8j]'w̍`WnPjv n{|(57V a$p6(cm}Q*(s(+[L_Owfm ,gcܼ`nԊf!+ fB w`&Z ,=zң8&u/| '˕̝<ҙ\u.iQ)h_[h_Kxc3-VZ n<⮢8ƕtY{zCG-Dn0~C@e!&{tX9˄aχe?ˬ[]>ɻZ?{DNh̛2!Y& # |/,?eڽr1 U5 oW?̗5K]g7V+ަhg}csت5?6ʰytP-w(Qd&7V6w_#fsœF+It޴rWsnm]!xNXx3_V\M,~ ns/ڪ#d,LrFD<swp[l/YJ[w{A#yaV oV,t^ Nk:÷1qW%eẑP<\]fꣅ^\~]]dgc)+)|X*AS#K6?d/Cq/*!bGr]絔Bn][?-(7r%Hc%mZY߷v>sIENDB`robocode/robocode/resources/images/explosion/explosion2-16.png0000644000175000017500000000647410205417702024004 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%> IDATxo\ym ÝDdY5MڱJ" `W]b4'CW흁(ܘ*)F/]ˤdj1ej1!9˙9b-v|Wpy9 B!B!B!B!B!B!B!B!B!B!“|>߹Pߐ{ oy/:= apz}D3 ӣ ,J Xma29ЊEhXN~j$:+4uo6UavTsHL˧دi,^PN,#hvfP1-\o)`-jfR o]W5/:ct4$iq~)a).4&x# QGĻ~jYJ`_u8W`s@ra{>4 d65L(ža,͎GǻNQ0q_֗!zfdn*G y .S/qz½g{ժ)_'6P* ph55cF!MBS8e}W (t9I&7a4:ZTd).lVTr\PiW-$8&설 &&i`c4>8p U CP9dZd-boG~_u1$#ar mp?ݏ+g &`x 9jm~ĠdU?d[[ƒ!1t`:jPRd`8 oxW=NPJ!(Tpk}.OvfPŪfU\5puJ4J='z%n!Ⱦjx!Kd\ Zr30ܒ%L {+(UĘ Z}Xw)/<p%G8 u|evTsR/E:6Úĉ*dL{&ĉpP*)Q|q ,TUUf3!;$ 6 i:n9+bx2q {.O?80ŌHpsLK^C & ")s o¬;SE4iL CݗB:\`;͂kʱ,*G'i7:Ex?m {Pn)1\blw/!_rRqѶMx׉p7X7`;];0ac-6 Qx"kMwXp0oM-yG1(Mwȉ8+@Y fgQF&daPF4hu^g2ydVWi4q2bb UM{0TÝHױUtNo3z׃:| zj} \B"$zG=cd{4dqIRh45TY1~2wc{y?%hƅzv)Q7xqᦏ` L|뼂Evh 2Ah b+$W9Lˍ 7*VJY I4PtL:!o!G2l}e 'Edv6>uқ[!#]s'"U>A-b>S%br+V2b뿋z([T"0~͖&j0caI.X6sL~K0?5pVb(5&UjE8[ ֖[I^m=K7:`ƽp 8kT<[!B!B!B!B!B!B!B!B!B!BwhWOnIENDB`robocode/robocode/resources/images/explosion/explosion2-59.png0000644000175000017500000007306210205417702024010 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME& R IDATxۏgוYk}]})R̖dM`lp0yAD=!_~`:$آ'Djvw;>nΌlJ1` (T~skZŗ\.`lF7V.880GwZo 5nzk_F Dǿ|h1Fx-q1_#<`;|77[/*pROܟ/;w"<#ȯ|o2j P9Xk9!?N{r{\z!,ob__k‡"rӃgjzifbx'}/}o-ßg|aӯM_po*7p(z*'ƍwA6w>||3zDy2K/AP,6x(;Q̣Ӆ-oMhg' Oy {(>R~g[eח{KᏍO.[Řl٩2A'GG¸g 0פx>AowL,>.m9߉_t?3>JBuI·O=i븒rEIHTVW5"S}O+$"{{L'|Q~|-wTxYL|B&rk>10޺k6U?Lѩv:NōXL0BI斬=4o([ ILXP9Ψ[f,UGwQ~;Ÿ-gS?P1Snhl$/TI"^kp km;bR t)&QE?W~f Qx0e,|D'Do iB#@d^=ڒH̑_xezَq03nfwƲ ?|CW9TYUg@l+d;AeW]AIc9t#QqSl޳^=4V̇b5>~v)xTuTwcNl ũwO5}W5vHk62 &+ @O!!ζ~|qx6USQWC-4$4q mhPEi>AtvYL-c6P]lƃcG\~5ؾ F'Z9>\\qjfȟ y6sƿ}G8Ơ{۩_W`&V$C\%qWX:J"Ҁ5(3C%9R36k6 MR7\,x]etoEd2/[we1MR691̥㭰95y>&~~|`SLf'u<˯7oCVKoBKAυ \BV˳Ľ([e`|B}z]h_sVY/\w8C>n CB嗠=DҧvN3t4uTܨJ:=nc\_kؓ&=&πƒۜ] -)|4i@8*Gjӡ#tV+J\<<x"j+GlמTOX ;F-qx}"XGy6섰la69pcaz\-F8ƽXwGq~7}ؿ.KrYl*HU$ϱ IB߀UTj0Qڐ'8:O a8ѤL=1.2 = $S&'X)O "D~$c<rCxp•⨟mM'MW a͐Z:q!1A-W=ӤO9Oq6.Gx1M6f؞&V.7-íKj-vlՓ¨ث*l@9 u| ߦ 'rX\-)0L8]::cd~z\Ǣ / oǭ.XO<@!Ǹ1f)~B!̓a[6 s"j´!u aܼwBPmc' 9+)X:#&8qTc#MD9yfC`)qzٱz1.{;=W.)Oj%nrHN)N98f`B v+0z5GK|jtgd;V{fu,3yُwM_, <LjL8: W'I:f;N|FhXRrмϠGx}V#'[wn0I녩LzFnd0]Z'D$ˈ[CL8‹1X NӊOJ%Kc#*/-ە161"qfz]ܘu%RȽaƼ:,ؤcl=˭cN#ajsOH=_B+x'+"_A0N5G0Bd%$$Ify, ⚋\z!]{>9!ٞA kU=Ϥ% 'qK^yj L d ˼KU$]5ȰyӄukQQS H~f%9D'/ .ڸLh(`V0$0d@'[1zd6=D7hZHݲ54e>cs=gqJr|5bnPyy >`PHC D2^#5,E|L,\q@R2~3ZD-IK4_0C/+ i!N>D# 1g;d UQ")jI±O^5T_f="F%Dz{I` w{[tҢfZP$Xތ$Lmf9)lbr=4Mno9-;W{N;ON7Q:Wz2?tM#thgկz%M*Tn"G(J=^JK@9BOlw.å)~&`;2v!E0e'`_Cb/1s qdǤ2'(L><$a8FzN ,=>Nܿ&eQ\3# {KeqXYEҁ`KrpykSװWv<|'{Lϊ*1eJ/%b"59S Sjj WQLJ6^<fZQT Ҡ865Ք{8=wLőҀG4nʵT]s9Fo'=BDM 8_~cBܖ1Yמ'8e9?!',T e@iϊˑ K&\VĻ{8WѩԻ(wH~H̲v0y W1tndeJ4i ~Ķ/p_W0$*iLL+F8*G`A@p?Jzj} >z]\UցfPiY#j2S9[8/2;`jǜ™T1Grl^ '8KdF+hA-K_K"CvR:> yQ~w)G(;(G \גx d$ ʽՋE]<ܜAd"b.;/R<@=C60j pI@+Pg*@3[dJw4& :sIÚ*m' !K7Vwy]lJo}~k-L=q-p-@Ӕtx}"&a +###FzewOGϔIإD>LZ7aN}}BŒgҹmڡ P l y+@Ж\(TOl(Np|a`' +(4ʷ}{`*1eȹ86<,y*?,q4=tPՎ$5[B#2/pe_]7/ü>d {T B?Jٻ÷9\DG e[(gzbkEse~89>">5А2lnBrx ;"aqLjWC OR*Uhr%Jֳ/wce;~qlA &r ~#t3;Lt$X*TkRՐ f1{b2* =SjI`NsO~{ܰW͓r|W:~҂K3:wvP&0GsWR!7#Q0vQcu쌬$@:!g{$H l uJv^`7:|?$9Ә׵8Ԏ0&-pf ́ 9W ھ8 " DT[&ƻ 1Â\0sW|_GB "sT+6yfO[t NԶ&7ɋ-%+ik-f;N=Qbǿq\Ga@xxAؐ|&] R|Ʋ[bᘔ:p-N8L9ֆu 9:4plI?_E vDa™Dn8MBv$4DLp%r3hUMH2 *1I$slz8 G-@ޖ]iAD!qʆzW(y$HΆ d)s038c4cXL`mἜ[|r2ixy_?Q84dH-1 8F6W[Cdx7H]Rkhw@9ۅ_ }r<NirMv{Dy ͯv@V0;w$sd;mF}G YUH\ waaSvMnUú.2z?X (z8]Fw`x&;{p<kahH~c8ؙ{`σ`a)eIK&Lhoҫ fϩ刜.Ӧ_дi'G)p Uaw A6o!R/=>"sJĜ$ǴÚaF5 f1/tK.Bוm3@1*3_ʤ;SxaQhVfR, xyQ#4%D_P +i0 %UUcY$ s_s'|(Ѷ86Hp ,.Sg;M] >gӎ;^_ 5v",Ij6#} vXR*dِs8`tSë%kd&Dlͦ8?kG$t8Xt.3q+th6D2Yt2$wJL f{R|MtE"dI^\z}A=:AR&29Ӟ o ^PGOFb|bN@b94R6Pim|^(|:e1iWt˱+WoD7κ5{D:VS~?w5}~7+SVt}MW}Tf'd [0#Ǜ9h#NaߊgzTo"2lprȍi!~d(RcDCqh%w.c1zuqOc?BF0bĒp(cSɍU=L(@=VxW* W1,X<)NG2[{XzPR.ͳ` OoSDDz>腷{n?@77*㝹%aaXgY?'31& *\ۼP;.OV^zXl9OIGSή Н(J*YLBGF0Xڞz)&9۶㉫|+piV 7twg #̟p7$;%r=M `n>_b9IZoe=cO˦U'ƴ ZʭUM1@Ǎg~h[+T$ޏ%Q)DѻKlNdUd(?ŅSVb4IYn+gpn {& 1ݭ:7UtO EQdlXBbxm+ XIK|d,3\p 6q|+ #\#E=/;l:g5nXԞ*pZ4դtB I&)jw p=g=IᶰbmIly"M+zJIOE4D4|Y(z犭p[rj["l d+hB貁YTPdo9:@H*įqPե@i%>KX^wcyco1ui6S|rhvʎy~R}b}$>8D d&w<5>ոP5HM12Z" 2dE}Dyv,0>]Qע';" ʆ! D$XC PӳN$Sv\]5R QGB8ĕԽ*JAaK 6 h#3qJq_NuT}CY{R|~qEɪ8>LpBv-Gy>}c9JDġyR#B"S\PS7QtJM0O|2Y[ ʹa}u[5T/0"E*icqI,Ny( Eqg5Nuc3jGit(kH*?Y pf?N㇑I.S=e0?Z"Դ!jϞX;|tC$uYM^ mݒ NB"=9OpÅ` O@2%׆{ߠS B:Lbܱ \Txv&XupnT 0rʐJa@[atLs,׏BӚ7lL e!\#<{n@*:`4D!3׳se05N:>(h|ܳwUyyW3 BW ibiHN gs-*K2#"%+ Ɛʳ&!3t̤mqFo<:>r=iP.i.SDy%OCpAQrt L\ͭOFjcsZi G!6[V Qo9rRU ZđT"(:<<Sr,\1g86 "Z"@2afHBÀ5˴`&WH 9:!h1/J] 8A5%6=kM~>q#;-DOG X~ Wg0bG㽍/ɗ?7MIPGhyHg=y'.\RG +7:r =kTLXT˜w71fXa\bͧ@ |I޾H}Tđ@G0!S9'w\ƇLTC@8/VapDIDƞ#RX2v<Ñ{ZֵiK#e6BFFo bRo5<^+(reh .U 8 a$hg.$j{t=M!1A>AR>iϯrixY{~q8>S9S_ײJ9vx1N%Ld#4\ #%P#O "5%iYU2+EI%"){9g7˃oG,@n{ַ[,'h ]Eѻ|,. 5KW5鮁!Zxg)jρ$0 Y58Ju (׸$iWGJ-T-^jrU3m=!1 u]]zẼ640iid t5&X O~c!{Ue;@Navh#v@suw;- h;XN.{85cTX,`NW.;жbGh*VZMҶ"^-PQW$81)@KQw=ί !lʠ3m0NVlc;~]I!J [9{8]ۿ@; v-8-瘄Zk :%kqO8mV*-OyO<稅U.fs.Ƿ9d.8̝' n|31s&.uTA$#"gd琲!8% %C5J9"(^pl{u-Myb_Α-aCt<6 =՛(pܛi^,z1+W=T&[xN*ֱ? )0ݕoΒN(ŷ0 W-VWÎcmU]jX\+/qǯp!"c|A2Xؕ>!%k!^E_R_%jW9PD-#Q^)orojay⠚-O,ٺXitb DJԒ# C3qϜ5~f;5e`bR}%U ZIo* + \F0KS4C DkN[}.F;y.ߘ-+pm_/{ lJqSSJ`6(7#|qd}w$3pl:C) nqB./*B!D0'aǂWVxsòp<3%ac ̰GLspDLCârvpn-j3;&DSoggMΕW@5Ȉ Z~6px;Ʃn&~li2j+fc963pͨ rR4䊠H3*](,;4҈u˯ D=Ie81߿9p 4?(+7:lܛK;~|[!gU4O?tmˢ9+:eӪb0P`S9Ȟ&!;"S-*@4a$SS@ [1C쇛5y]hYU/V8b ni9ERReD"1 MI!e&yCkJe,ig)3i ?~Wyl~'j}+Xu?k L,%HYBF2 Xc^nrmIARu:sD,vRPihYNVP`~D{}@KBp_3X0QXYEzLp_uVvN)Ź}A.e2*D1 I'9 JVts̗Y=´ kH4qYgyT:ϫfS5]ZѸ WCr&pY(,]'/T|9##oo lǚ=( ZVA&CQj|r.7L+ZLdsan~@3 0K$Ag'"@B%^tCgBg#eQ]mj+wW{:"15,{2ɒ"vs=5v/k.7C%O%DI͵M+p2O)w)AaLوmL(i 9r7x8y5/zM+zo~POqI# kӷжI~ڥeX.̦VI,yrL`? =XK Wac-&Kbbخm&}87 pEH7l҈Gcn圬/%*[< D#dƒ9%`7wgGd 1KĹT zr;#G8Z[Θ6BRKEpwiCfWic նz[XA\TmZoŜsf&m-n*{QK#Ul\u# 1<>tfT?2T)lIgF^mƒ%a5I6anKbyN?B ܸ%6+Z±ŷU. Br"f\Τ0KJ*?W}% peeFgxT0zn$brK -d]yM@@L "d&Ն GD<9ܝZYUufj} l+v5\ÿ: 鹲~쫅K{T˹CFU Kc樳Qf:P&Uspaɪ*$c)"䔙Ȋ& O!g+ŠP ~$ȚB&rɴ%:397TN9+/k{̣Yd*ՑiplGtA-tzwMGLIA?<~-ə5 L#Eef0FGq#L@//KIv!9L/-As2Cgw5~0/lepVuשaUf7G~0n]9}{8؋J7vCToZ>AOj=j]hm"c'l=ֻbZA3wgg7hvr NXeW_ӊl řqUs6B Q IDATYRg"Lx]%]Ll1Hv;BνuTc #+ l|dPFI ̅iɤ-7mfX"W<Vã_ژYτ\՛Pզa:tdI4DJ;(4Ɲs5 Æ_ŷ*<ũk-IҼn➎jTn]+6>~g?k.֝3oVx' UOs}kkv}BM>GhVp}f  ;ި&ZR9n0̢̚\¸<>o0SٝTX8p o`6^.t+u;q<%5G Œ(LJ<ŕSz! \HN#7qB3nV5^yx䬻zK9Ζϖ5SiXEk!փm>6,WhUKe; F^hfrWUVkg1Mv>>3ĝuD{̪W.;!aT 뭰EIazӔy(B?>(ܿ?_q Ǟ;\N4ʴJJ!5HRYsb~~[;w6Ѽ׻3\#DF BaHw2`9;]quwt\86:(;3Jf`ᶞEg~|,NFilQ)j8Q NlUª94c ikW[NꢟԨ{={PJ*zcenȐEpS`Q"xkMyvO\Sy-#G~2/~"sGYՖtNvS$bz=2-h_hZےӊwG9}v .p%1 ICiP]Cm\ﱮdɶ`h._ڲd!ԏ][^Og'}RU f:I>eFkcj?jkQu-mMVty4M&7`:(L\7@o oضb!3 f. ߅A<z?ZO6νF 1O)2/V=yB?.<Dž 矃 ǒZZm[P=B6C\S’KUK?i, }3Njq]ګ&vzӯ~~_I4),ԦO;(ŢF:cm GA"[tW PS{Xg#ܬ:*Ĵ~f齚W=xz!\A6+bb՘v/(4k%\nEx1:/$rAk6kVKx:E!s\_ҚvX– ih9teѢqL$frT6ocZo`PiܒhY'_Dr_V*ww"uicF uDƉD'G[;w>deMSlzZB}} v&fƲkFΏgܿR&p_Y:2f;;Ȃ"kV2G͵r:)~-Y64G*<)9|DtS3qtJʟr5< ڭM5nr2ץ-jT;A3ۂ6;׎]I66Ś6}jUH-۪kH$c7m?(]"FN꨸Vz]6TPbZg \o^#9;Yҹ  k ?&_:>~+TQۂ"~rp _Ri.O|뇉.5Nܒoo9zD}V Siha[txBKRZ;3u|'WuƧ}fOMpV4eGlq0<+7MRU=U\nIĚ9?a;@u o*X6۵(z P%kUpwy7OI'md? 4zEܬIwoq(mC$ }.ŽNW"6c|2R99=fѾEl'}ߘ_j1$5. xǙ)+$U Nm]cuagau7SPzӘ!=ܽ/HKo-lw+/'F`Imh+&ؤP9E9.I8nhteI໋gt@7E^74sYYwPD8H, =(\ R'AIqQ tnw3rKλvmꤚ#T6P-H+ɔGhD)eʪt1MJƢڱ<4F g2v2$VeҲ`5{4<'pZ~cj6Yto4qQma`R)_фkRײ-'ӁO.=F7C BR-|3FI &(>, ߁9hx|#ICf:Eӧ4 +hx|癦 Iq.ŝYTO'vT>Gp#G#X#^ yȚHd9E7&SS_V"ޚ0߇ jӲ[_)`5_)<1TXGL*vǬy pW-B^TN1g4qÐz63[GIվk@&O V  _?Ǟts& wh:!]s;#] IZ:|Cyſs 7Pu%S1Ӫ0(Wf @JJk9M+V{E=[lФ?ch9_OߠRgrJ* *pmtwxl}Ujc(Kً;XiLR)!2853Hf.a`wL yS_V?w$ ~u)4rQ'G^Hd`s L+xM*_: Qb!rk$MYꬱ#7eo4z_ pƫa𥎙uuJJW-o M.uuܮ]ViEu {$tuS*-2 ,WH?B +?w bS@.ϙ+N{y 9\%$3mOsh¾4Pq~W?pS=*_j!^r9V2O7eԏ;kϠ4`cZm[pU_Pc6a5(x^W Ѯ>ک^`}:U)1yx 1]:-;rȔ IiQ(z^/^dpZ >ŻAcC|5Gc(ۉO'=zܼIdw o2CBel5&c𹲿ݹη4I Q.id hk}\Jw^wkKwW+P[Ƿ[CS5*e?]E*5o]]J覎spEfV2O~Bx}?/_r? SV)m7!-+o$ H)(k.cUe;DwMսçޚLuYFx~c9CVzV152NM ,nH^fجo]U4M(xkô+8,ի`mh'_{w6MU!Iz;L!*4ݩ]kI<$S }->o-r/'RdO8q+V*Sw*][jk6qXy8]s~#E+ݚ^P̝o<ٸG6hzj[a7:VwPm]|Ī\L>8h:l E?u?A/|o6V*LD,#^#b-])l)-V r=hl`Jݩ dr:yᒅe|/WuK+v\a05Au+b}Xܘȴͻb1Me؇AinV=>Բo8<1>E#ЏK1^[Ҵryg;N*AߺxXnqk4ptߓƎs|aw9iAO2QO[\udC8fl@;Z45z:~w*X(gr RK.G!9Ż)7xRϗ0ؖZ`|p1{JyN7 y!鎉LCnCt>.Xfq5\kJOvkΝ3> u^%yE'IQ~OOW6W~q1z\mY]9h0GR kKqS;¥KGྠ ܂%"aS)N&O)#hO'͂ $85򿓈VW JDOVӘ~g ݆V[ aB+7Lxz_ş|wd{S0HK=ҰS\ S1):ǥ FTx]ʊ\"W  Wv\tܭް!]w?v GNtQ=D]ב!mI!:?Nf C`NYd(eB.SR!eD$&ZD*jb&SWv I^E1Y`_͑V󌶙.Mzoy8;/p$?Siw:gMk ̔m[8HƦ qsTf8@ܜTx:[ j h)"C…DNPkV +x46O P_U6IV';Q199oPM<2=kC(?ŕ5Cjq6;ݕJCj~cgc^ BB(E/R0RpR(9ܒVfadzmc"FnSY3jO9ߞ0w|.W 2b{i(阆dݮi '"tgHiHe<&CsH.xnz]Vw6vy~֪9{I^~%juld$@ _4@Ā1< F tDu%"y?޻`)ew ɽ ]V}K;چaa;|1٦R*tBo*"_~s>@J_aO}"k:> D9F2NRB%c:P"7={umWP)N2VsCĈa xL8tH^Y m9+k1!M?~6?=4>YOJW2[TJhmE7T,%3a%`%ĎBO0oz5;;ju5p$0 K+]KǕҳc-<&qDz6BP׍֗__:+BD8)G, zei$23cĖdx uɪ/lb9uQ]b0Qn)ר讆`^0 6J@ǪAdNǤ!yd@h7 z~"xxӮP \`!Q^r8|@! b cV>Bm:>+}$'jxL('H]VrGaRK@6X3Ip)-On;~6>Co%T~AW2)c0LD!F>i\P .9*szcP}ظm)H4N**$ZR`OzZlP,"icfȹ!GOcN匪[cҘ4`~Xa#JNfF)/TNl1TB,(bJS2^B$ q~]R74-˽%,Bݹ{$-/+Cix mp=3D")S,=%'pB5U(* HFjc1QY|q0`xqO` / acqd6 "X N뇤?#hjDŽuiURO)"dN^:T*۲a6z&rv<; 8fF֤)itD2T cI \`-i sԖl&<^WN5ހ^n1"EY^ֿpu3 Y:V!ZJ=ARuNbFcGtk"!@q4"=xBG-xz/O-ni1{qdGq'mҌ?Bg$ZV*2',dX{ sZRYS[I/s Jc,E0y~45VߧG rLߟnƖ*a;;|t˴~h%GK$mR{lsw0Q/\zB8G9D@1VY8)2bKaiܛ7y[ңb&iY,ّBN2H ͘ Az*2|)Pqߐdy}UsC"dWD=\͝ZQ|D.G#͌VM{ݠB$pңɤ2PLKCPj5>=GHGd]Fb]y!WxPx@|Oz6=?Zyiiτ%)ܧ}(O,Lqگ)Np}oϝɫMHٜbcf9%jE(3AʦΔz0MNc'QhU[M,-^TuTTTF,PGk3\*)۸az76PGj}j 9?ElXxS& gR%DϨlkJ1e4-yƄF,0 C/+cuXxq|\?x"z>0e[kY#Qﱴb1 |471޼i[BX V.|LS^(r\Fj$p +my*MߐRg2:A< (Aw"#PT L0m/ PuCp=f 2̦ <?(ctYBHσG/V:u0^CH a78s* H *ǹrVҴ[csKƷ&a3ؿz/;y/\o9<9cgȤ U胳_ n|;3nSko |8ۈNFFqM$.͕,4pH#>>=3 f 1(&cg5]X9bJAuG2Z(W WfGvW%ken-]FjnFkDֈKŢ0ʤ-ݖI奕1,o(?gI H4 #)F{Rg lVo̧ޯŹRz(׻}mѹ4畻3[Ğ/ S}Ws[ym)_5I/wz| +T3بal'Pg @@f3D[=DҸPd4r⨎@Њ0LUxF˸Q:rݠAkG;fq퀷*y3fk_Ù=UNxFў`\QT'Fl+G+# ߹4Kv a2*Cw/@68ZcuPO+V`C7R d=<%Rtlvfo?K(x>oGY&_t<p&0 JDcô4TiG:#=r^d)S '8-!Tx|Vc1 E'ږ!mEdK?lirŀ-+ܷ.9CR=B%B:vCϣb#clIb\~9t7[q$1+ScU/rn7 9+?/kAς.­ƒ]  a Kp0,M+ۆ!6|4, IfX2}В4Rj>V ad\1l2ʆj݈3X5{e LLَXA[ W;C& 1eP9s }U.hLGpaNiwɗ G_oE8΃qbPg`'WMϓo|؏vǩgʫ+GkݫGmd2 C?)NPl vGű\Sp :c(W=iؒ4z?Lq+a6wTabt|MV @Mstx sY8fC3ppVq{Rx[8ƳԹpn߱go;UTs p4_laFYb--Sb3mCocTO&4`1%KϪJJn+=Q%{=u)g5/t(NwaPz@_`rGiۄ]Œ`oST6Lɰ-}]ed}i܁;hZ_!FJ()?;ooW޼V5`O{Iu.fcS60bҠC I#PeL Qh26Lz]֞fy1?ܺs? ![峦Č<%KhZ"XHCr5,^^PIv o ) z) LZdΖe4Q:ɰ0>6ޟ:p=yld?=CAׄah!:d"?@q9򔫋 Ju2ߪ_%]|;Z/W?y=p~vk$.rj6rm`"Oh BTcVʼt>ZVkAytUhr%[\0M蘽9 _9Eh堉ٯ(eÕoaW z~_}IENDB`robocode/robocode/resources/images/explosion/explosion2-4.png0000644000175000017500000000231110205417702023703 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME% VIDATxkef7Mm6e-[[^=ԣH= @ZA }d?$Y{~jv}ìEYOS<ax {p,7W⹟ыltwStGuSN~3q')>#YeNS+ШRpt JӿK">ơix5%uR bS"7qSoah3؅!m.3m9R.U7N !fa+ix |&zn 2!C۳at`U.z hlVFgB[JOx&r9\y@Wp*&YG]`RuюpMX~M}[p/H[itFFcЅϕ I,=s=Ɓ_@ X% cȮQR):$Kh}]% =H4ȦB]Hp1=˲0uɴ6-N>сjX er$vvN*ڏLiMmø,xcl뮝R2 o̫㬙"bJ;C}"Oܬh&Z3x[[wa \ϯwf_u睭_Fȿ7`IENDB`robocode/robocode/resources/images/explosion/explosion2-22.png0000644000175000017500000001201010205417702023760 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME% 2IDATxKl\ys}̓oR,۪d;vI2b@ +"ͶnڅewEhQ Ц'qTQlY4EqHΐb!8}>Bh0s x<x<x<x<x<x<x<x<Rg&o{o [ΝΝ<{^!8> >ॗOåL`;0o;`8hzثw- =/@nظ" $QћonJf9-hjK4Qe,.ϊ5*(㊉t 4Q`pQR9#.COJ0{OiħKk5Bڝ[+1ҬT bR5DYɟ"ur*q26-{sM˩S]s$j䦤ޱpF޲b ~ ɩEE!zxJ&H5H3p5r#8I@T(NowIu*Y5UێK 3ᥗ'#IŐi´KxnQ,ྰ 9F'2R3%21J$4ڇcHU!eec53Xm 8! i)dDvC.w,'x}'#?ݩS;Hp7٪9^q{[^njWa8ELU5B`~$S87uu$!8BWO1cӽ Q @hvGPQj27twRlseGZGˇAv*u{i_F\ >.v KG1b U}d8 ,Ύ`1vǘI(@>IREPc’$%;NMf> l"\-c`-lSoXJ51}>tՒ 6II$acz 8ͼRe8T|v6 rd -LDÌVYf֩X?@VgB./D*π&&bqGrma G!_>1Õ&2 觰Ր:Ic2D'fbfAg~z2lk.[i4NYXR:w\FC"'CST SG)X)&d. ABށ@1-.dmG"$0 ^ONCxי?\eGɪ9oV K1&l.}^z:}Jh <7ʹ6P <Ɓ)@]?D?_:̎;@\msֹ5x2,.KE]Ч{ /%ٍV~3N`z0 8dUf!r -n=ȁ*y.P&uK&Acqʏsssȑ6յxn 3gQ':k"鸟QsbB` isFGB %>7c9˯ӭ&\l W[>qKxy-d捀XLSbbs:uff-0ZwX)bur ~%J=G>F,-0roZ/#D~+4ha,&zp8 v<(#0Ya03a#L棈 <~F3 ҀP]p+di:2z*MsfqyP~PerıqɹE0nPRU Od;Dj8>[H%"P@ k 1`Ks p6N xT.ICTJI$UEj< OIpg,^Ÿ*u0Xʠ jbQ'\zx9PU!pνJЮ Bup1T#D'}]TA]azƻ!y~*d{puO5O0.@EKN\T;rVVkB70Y1YD 7%G U,0 q/(&+(;pt(ޘ"J@5] .lH㊍Xr>K(;QUsD񓃊Da46!.Ag A!IDLCRE-Xma{4H[EFp_>|0A 70A$!V "Q#~ld"BEQgit Vbm1@ DH"!FJsEnΦ"baCr5XDQHb4;"% A X,Nkzh{ Z<B-bŜNC9E>.PLϠ( `He"E)ј088[P*m $}ȤBwbPo3ׁFh3+]r"eIǎP|c$ܬ}4cМYn;QX 49VA:MLjr ΡUc `[`U#/vzŏ>,`Ao@I bRjlQvG+40:.U<0 IzÛiuqArv(q>R($p lM))볖Э Z?BIvNЕc(8ݹ}eH-lt.o7$'fF5K%;lG%KoHۚn(<9ek[@r#u\v CH4Iˆl{jâ>:YDžt,ަ ŚC \:4uQg7.+ITa&1A5Q]H_bb+:5XְYLt(B"ns &.:ͩW!^+l#@8N>e`p2T j62Ù<:5WQEo< 3GT 4]*J7Z~2?pn{8!"۹E=ܠbK)HnPg-.Zh?;cr)HM_(SX9h `Dh )U1o?Cϥ8}&KWQѿ ^[A%TChaQp$XCQV"jȩSD(yF)skySws`ކl0FDSHc wt@n#6.NQBh3_sмWIQI"dGjrEU j5C`#\XaZ鳿wv*q,a[{x瘘+6#zZRI4*JB!p Nmk ~X J͑F]SrwPd*'0(USBRJظB"CXs]]k"ˤZKu)Ӎ/v ^:!*5*"*&%52]v2 ; # _D.(g,=L+>DrN J UL)rJR0rJKm!$8K s5|NuXi 3.Yr!V:b 2,-eޣߦBMIuAz)'4h]J6gd̄.Fu2Zoi^p!G=qb;,ZX\t V;T7c;룓8PRDiZ ]imL ն}ᙰnY.8@ aS V՚[} -XܳOٳ (&8^23-|PQ Vm-[ ^8p&@^NqfiART#b6т Ek;:?%ڳ s,sY._6Z? i{ zzn4| Ο(13=U .u {G|\1qwW[mx<x<x<x<x<x<x<x<x<u݅5 IENDB`robocode/robocode/resources/images/explosion/explosion2-53.png0000644000175000017500000006037610205417702024006 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME&R IDATxɯeu[9m^E$CKbI*(; ؀a@&GxQP` Ed⵷9n<;2E&+S*.}9ܽo}kW_~uW_~uW ?"C Js pg7?ï7"=4M7_*§~m#ܕ_>Fwq}R?@xn/+o ]̪[6N.#߇;o6_^~QNJ ~};1OD^EB.Na,APŠ` ֥H#v)td -GeΞȧEz ȽQx8^xolE?ʊV͑7mtWwEOz@~/bn4bT6S Y* mଋh4}88rjOlD{no3a:*G:?H߻sO>{g?Do ⯜ ­<|Iaץ_Ĉ+p]τf_<6pkx,T C ҄ J\[:Dvdq8fEEx\Ց̱|4p=:߹-<['oȻo EOy@pPs>P;K!ґtݧ8~XGnJ _.쾯8 {? x,n/w CWjFző-UtUɬ78Ue !'h-CR- +۞G ~XqW&YFx|Dqk?_/ AqsPȱ̻@{N8ΞJwIo gͯ+\{-x <|v@Zf(RuFfJZ\4PT_*Qx bԺū -ƵeGaZ&;6!ﶩkZ(,=V7 :E1Z0 ڲK`U'()qz tDy#+Z:jMt\n4ja-QP Iz fM`C-*r[¹W0Ds_"GibX o"$~|-( G[9F*$,xӅ-*IB!) 8a(nuh*kX eQ( P2$(F"BA4G-nwQ9?ƨe 4_v3_K`_q& U">&?!Cc0Oe}B(/v7Fa~!`i?\oK~JSM~af`v ldp~ߤsc)QTavXG[OK 1UPE *XFS9aRAp8^ C/PtPD\5ޭ/%>nc!F^O`0Z]*WNhDu;y a;ĨYYT % ~KV'e=nWxgfF03J3C9oo#zNP/?n)v.^!" Ph'4͊.8o(b;"T ]gЄPP3(AFBB'G7/3\a»ʀ4kcr{pV8"szu T5z cT tXL%(.DS4ղ UBkh(VST!R( : FA5p `8))QWp)װ,˞;tX΀a*N` ( @ <PνyDuHk&#D$f?F JϙLPhlEp8Ćum{nzߊ_57_Q1StQc&x5's,tn(lE ëgֆAHˏ'xǴu a3tA5j~ wðH_)PTHz= -<->. hS*402|DH4hK2%H-K ( :q;EǤu6=[x+GJ=inZT(C`L9_Od(%0 >+?䠄,lM%vӬ6ʷ Rt*28Iԃiu7)||p_qc - (? 6X/.Q }ZAᡌrC NCebCN%h,i+^e Pp0 Mah(T U:Dx@5BTA yMrḅ% *y>>= 5A *}PK M7]kg`0L-M Nbt:-Rzjk>&~H.v  QI1slutI%PN$TYF6 njYf|;qS8\%!` ^Գ x:*Bﲗ+I!>XP& 4B14BV_J_Y'n |]ڒj|T(w>Ycct !AI{>Bd1y7c.m^Yo>QknUc<{6RxpOd2} QX'Ļ0-w)MUeyn-Z$_C/R+쾯xBa2+y[Kj+5Sڠˈ}*G.窃'KX3f,tYH.?w '\u ndH$0ϻ| ]~*aC)KYp>VD@*)V)Lw; xJ='tfKܑ[ֳ5hݢסKY pW;ө ZՈ)緱&xlez\Lb}z^f\0- d ᨑ`Ȣ賒]x#AKVQ _Y_ge.=qZ@5I s^ f7:>e`l:tpg-?iwKb< XK,ܠV/Rᚻ??xJ^w^VM >z"-"4=&p`azu%v 9# l̳H2R}.6?NY6ѹ\>ϟvIm]z> V5tE W@pك(Mqm2Їꖭp^Ԕ[D3w5H"nTغ&\4L a o#yx`!-! OW U{) >RM"\,03#nܰYzYʋkTrg'N` 8CF/SQK~;OSkx:dA?b E J5VP<]GeD}a B=x Jr ~ MG*p7U,p:$L5D0\4QbrB#aTl]h JF D20[H{0,^b u7Bu~%OKxa_ט[N`SVQgtk;4i3-jZb]<ܤ0jTDV|bR\jhz ڦśZxq{SXt)g^D9}ΖH~1]e3Q6+LNi$,Ѝū,|e(xm9G$8k,A^empMIϧCU V#l52Q)BAGM-V a/<6sN,N6Čj{bea,Gy ЍF1B:[r7 y(=Gq >k5,s`G)w>6:l-ƭpco)(JW/R4wxF ʬpN Ԁ*!&I 2GBӤv&* y,U'9Ȋqad P $R#>]"LCg|-%p1ttreiVؐsߩB9w\ЮiF{G@="_@C/ }$<(n%TNq#ʬ(GHS#tq@(j^͙2F~g/a&R^N`%fIەHcaQ<#npNVq#>u3n!1w.Fi&boCE|"k(౼}q0#oSԘˆs97^v߇hXP" Y ~&6N,ZinMᰂfʿTm"&1D #.9X Q߰~~$p8}aGMQ߲aJxn78Ǝd&'s}|cU`tRP}x Ͻ';wo(_Z J-ǚf붠z ˨ϗ"z5e U(&uĤ|wZz@L2Rpx d>[} 2F99`#bHhm.K;R0Rb͹Qy iGb&hV%Pہ]XO*?~17Z ua~^(jh|ɤtm 5b-A $N (Th>.zQHeL;iFp 3h?V,j!n ~z7[*\+mWkL,/+;C b C%DM%J%K0=Lu)y JaCh &n]0I@JmY\) QG&#A/DQŽ<&5k7 44M],@qn4&L/x|Kx|n>i*c[37t ME_L02S CDD]Sd֤"p25'yR`^ U&\X­$0rxuc/?8Gg}LQQr=`j0-TUi1傢iPE&iO ;@ρ?8\3ţ#vI]RJlUՔq Fm7!@(#pmH<<̭T,i7aCt020aR(e>Z,#M]]~3}9\EKdD9RĜYlXըTGuOr `:mYP"Eq8+^ޟ S$%zl\@SxtdqQ!Ɗ6~JdJ&X蕠]+| OVEc ݐ@JjŊJ4alagx,fǕMVp—JIZ] -3qTYNē MwDDlz/鹏 R;( /:8S=R <9[09a]&6ag7CňuK(yfr6ҌN#R}bD;n4RQ%˦4Z+9.=\ߋ<!5Q>LO+Bx5ϭ5(EW!aÜ).(J|Q`舨 Rk.ء͖KULnK4>֙JJ?[ʋf7t?aX@qf..WβQMɏ2i|RJF`F$I=4E\C]'@Ã( ўe`mSzj\q(Ms]i2|W[=^1Rê@SL} F* [-*&j:)U֩ԩ,/p) n3N.P*\-, i*iR9IJI^fjr߸G%0#Y ̨`:k2M1RGR.Img։Zѩ v}~hp6!~BoOeKp[cyӘoY{.y ?]| 2U  K)S}(H92Lm|=P N8t@IֺEv.o`lZOmHm> [8`-}KS:)Y <X^0`R3g  sL[Rr`R_21اj~mp^ó5* г t8VLkO4g@+rHl3ZieRADE0)EN$@<'J؝Eja&{$⇤ bIc`*pr7s!I>2?`!Wr3q:_*ɮEwLz!=DcYjer$M'DvyaYLTy& f7R1Di# :(;كx%]܀وa4E|n?MNsx&y>Grҥ O^Zӭ53-Zq<c˳QF>M\*#t1Ke|0 `'ĘKv?33ntK;Цt67uMdIFupIƐI>)y66[,^h")>MeKZ)֘ZØOb4Yj[iVǴ(B"Ö.c`Se^ | \Shy 91Đw0%41 ) `~Tü=UNrC[TU e6$UϞ׳˅^FzTH Mʸ^;g=w5ۤ~evHiեY%ob #{> (}s="6E~S/ivbZ:r>~Et]D@(BbL6EѧstCb8"Hת@e*K.xJ9{?شH$$fO[U>uVwKK\*KހS䪢z5ٌT志r YY6V~1I0UDtUz2G'F#⩔w1,sAht: tYF$RJR&bH PeF \@E~NRWIJ:Q[u=Juy2g왌2 ܣYoCʝcٔOF.8|Jb,-=f@j8vht;/4nP&JbS2^I7 ^z"=]b! p 4!>.睰]~lOSLWpxw8 p:G\*-1(W#11VxVn#>yZ^>-^Cls"Ieb32g' JwRq!B$Yp\̑K^]n Ca.Gͣk,+kӋqϞawN<\'Ğ*V @Q1Ѓ$9I:bi j)G6d!_do/xhiJZ|}eM \䐖C@%-"1j.![iib=Q*c$` 8i("iH:O={P'FOԉV.Z _j$[*Va2hIp;$=&GZƗ&Qxm:ԝΛ2LgFdFb7O.<0WûQ6\]A gHNq?:ΧMu.$|Gdk| E*"x*-(v @IĞ(*.Mٯy*aᢃ&Y%y@@˫:#EFMňw"KQeL~e4FDN?ڱq eqqPNs3*~%';'k Cލ}HBhAֈC=Q9."EL + rsZ~7pvي o(uʮhz.h~Bak[VZ˴+$jFA+؞$7]ʚy:hl=y "ǝB#/};"i WZ&6Џ73\%kEvyz>]CwLiCL'Q!!a DbDiq 5}Rp>SO]Dn֑$y|w4xQ^ZL䂢'H`xUrݴp]'mMkp;oW+sI^8Z07Sxʖ+eWug_ix0ѵlvF+4\zU[@ߧȵeޅKуKC/)~H8|gKXXՊN5hʣM1`Sٵ 𛑻 5ܹ];"uϿ\ l{V&V9vE7)PĊVXZ\th=лLڻ N@V nir3~ۏF͕q݈7|vݑKXrr'YM;mxQoGJ4n7)-j&9 8s1nJ>'e.#4(t+vx$.Q\G jkֶƎ}=w;/^! ƟGPV1p- kX'K8iRn"i"o%pR˅Хp'~wG.}dFjԟmF|:"qgW~QVPWB댨YNS\C~>@HP a!>yJXSl8Gɂu$\-[ǁ?|)|መLmq' Lt™3yTgt5Zmѻmw:~vuWWѢ, (=\ *$\MDW\90-yb2-"dwi>uxs]u)6)*@]z{|!OI{4Vpn`S'.^a݃tַ/2OA}lAV:O&zWieWLc SRh %Y- 9ܺbL!%X+DDωasD!)=G^ \U1fZ̞eAt3:^ŏ;/Io }A- 4[ c R'pmKչqGgj'vî&I^ƬMϲu 4xƢR2N:IلM &[e\Nݔr,&xs2ugHyF7X*ơ]ʠO"'7??> < 8Џp0R1Zh Q,B)CrļͼyM;I4Yl}ٲ^,ˮLv];0Lm{yBN8|w3ݮuOg{߻L>HвIvdEAv%ƊpVKXY[-o 6gw#gk[a byB9KSS|#nz6]o7ߡon_KX4]Gz]bT۸0'=,߶W^^y~չMσ4=o֟7ŽjdhIò?ubdkUذY7}Ía??AU#=Ç+t&lꖭ)`d+/34yC[}KXҦ^}ҩ}^{^G /{=;.ʺ5vA-'՘M-<\?Iv!e6RV)%;Pǝ%.ܺwӳ@|zAܣW[n^63=`:+?˥vJy^>\'^"kx|W>KLqHk؆HUr ku yৃj <*͏,Zi[ BwA*&!ȋeMߛLJe蕏m/_(+t1wHyCma=7L/=*a+cz89œdRmZn>q|^rrI >~y"#oaClnN6@+TFc4b m<̟40oO'h]Bl^yO/'.e?w>*# > S0GH1U(v=`8><'%T~I>LFmSSti-,D'/1 'Gz!zޝȮtW8ؾ3$v$0^.k \[фum& W{>ۿUͷo/; zaXdMo} L|8ȹ\1պ#JOu2Ӡ(9rnU"ĨLJ8|ɭH9zyuԯ@ԋN(kk= QoV ݷ^ Ӳ64"9e=s{lהeIOa 'h +4GM7 : `'IkozY*vkyW/nx};].W+nM2Erw{I؍/ ` `YL E#߹f-?[N)~8V[oyUq1М+nhd%6 Ȝjt!IׇpcU HսLb'b4!-^TUY}{׺^^(W|2v qn,R({u$Bt8aR=s cGjHeKdQYMy/4cCVZwSN; PQ[]$&E IDATmd"D]RdI0CH]wuywuRV$P:yH ,'ƐLՕ^77`z7vmE2Sµ"]uO c0}[J~%ge-*GO "6\?V.&&Y:oM^b ntǢ$ڥ-^ ?]6&t@hmϽ҅g&sxs 4d}}[^v6g%QvŘK/hUɞް:}zM[_d'(}GGos= l7sr.O6wxiܗ^>v,DoŽn [[IF]CD5y)q2,{w[wz+@Y0+s;zwb5l4݃>^S'#xp֜|f %7xe7PTiSw;nO%h^Gl**d1-h>:mQw@~GΐAQמL ]uWAʄȈtRo ۭ|Q2hgX ^1М[ %8*`8Wƍ~G]nznWw7覎Je_7-,{8 z#P;VD4ۦ+ ;F@"*>%•N@ҽqUz~> G/A^@mR*XMZJ9: = PTL8 )- Sb|̶NdQu:1wi{L. M ٜپÉ^ z,{ًCU3Wo&WF~Yi_{LK{ +C9DY\TyJz`9}5wO4!ϰ̈́VaF7Fw0Y],*m]u/[mFubݬ@۴=0\otMحt_@{y .K-A/V.Mޭ ^7`V(o1Y&_6 Nd~%CEo[n,sL,pid1CYs kpkH  4PWdf(|X.,KEI릠]4a1Nj+TUƥfhao!Ln0dM''3GG,mf8J#1q{@Y"aȺ!mC[ێdw'm}U;nt|>UUEC.UNw]ht Uڧ8W/jUuJYP nҷE`21mPd?0fBTJ/OĤ@CoT;M:ˋJ-)Ȼ<6tk긇w0߀0]h<X~Š_!;/BdPAK8YV!w~Ae'c=7&>oo>(c:cKYPdz~S졥$UMÈۍ/D|XwYB0t]8# I>m,tu2yz= 8ڦEYXS7lazvyH$C-{bhxZP`Lg[>59<'1O)m#@=t {0r? *Ք75N99-@4h>=.Re#&#" tmufl*Tnф؊VT1-M X>ŃMG5{޲df/)[ 3z qR%xLI](+IݻA;mmS_ZigΪ+ ,ھ~Ӧ\y1.=ZgQ܄S: [J"KKQUkhQw8yE䮿Nu4^o޸@{\:*1;Gzɉmw5G&r3k;HnTNwč.)k3O0kS|Z .RYWYb0hbO?A [#7qEw k.{՛Tpa^xr<, 9$[ј~t输۶rkȧ?!d3z[2cHIoF|pry+%N2&b|X=g7y ËD( SN%&1kZ?O-]q@.ԮR$\]'8mB". >XrFѨCj hNjD}_iwD3i#z'ogK5qa϶ 첨[?Ucs[Ƒ=[&.奣_ `@=&X h0#/2Ȓje&{Nߺ􀛐 Du̢n^jZG*@mwP[~V[Z'bE'1Q>~H4P~EASXsA}yMZЫ:VLAr u_Hb9[S*:,'ϡ&Aݾn +h)5BYSP!If3QLɷ"Ke St!YVa?I;˒e?\njD?WN&t3 "=Y7 ꇮb K &XΈ+Q!ט&Ȝp"c5E8g FkW708u O6n>@@ Q ieX_c`:.otmۼ0WǺQuS-3:34gH69E\\-s-ZC$:x>R> Bb͈ 0| an:S:8hc2s|JWI$x/$dm2A+xdEɚDYlXb7MLtwz Nv0jRb VU6D$.ȱ$U^:N JJg^"*:5h a dnE+npA70Ȧ$5;cM{GqrRWl?ŤBVB#h1*'&vɿ_ugkDj3/!Ѹ* pd;JMcj|zxr͆\-AW(_EjB3&&]bd*.ݒ@a+Z_abGTqX}Nsj$  25B2ib– de;#7G&EDTPuj#ņȂn) 5^QPۖL/7Y/B>rB֭;((s8zw@IMk ZvǴ>p)WCFw:( Hj%_F F X,ax (c.hԿ]!gX[B 5'"1K2;-F="s^` emMT KK(:%YS2S#b5,]B\P<9O6!F O6xBߦųEs 4H XFĢ(.U5]ubJK 9E aV A! oLFe~2D`F4[~p hƴf6ˑ(t3R z0B˚mJPOA68GEp("@&I2X`c(dDd$~B AyK*PP% *ZJϬ ob'( >%κ*I *a8B[$ƵuPL=!^/Aozǰ@9u[?|7ϓ+¿\p7<b\C[Ta Z^!j%hj=HTEFh@V)O"R];%{?*r21VPab2 > Zn[_~uMQ?Ǵ&s^PFLĪca/ C6 pQUU?É'f/1]cS038DZ<sF?2' ٪T Jۢ]B<0)Ayᠦ:  oWb-3M<,B}d,1 V u"!MCqtՎ/9n+h]O 8$gx9B1CDU%RJﱨ 4I2":w6Z$j{E^֊vL〮#j\2ɘK *|L (YX%giQ&[@&5yhF-n[$""#Q8b2(88>_Oc"ba&q:pL1grZkZK#75H3_+1%1fN1Xо3 69ZLPaIT 2*D~kliPȶe'aͲmpZc܈<(3C dM+\h:*4Õʉk|, 1vN3J!Վ(ZnjKK 3 GLM&bPmA@yΆB 3EgzDk Gk4 ]cֆF9l!o F4( G0&HBCFS[\ N@b(;gi`*~(sT.0khjGX{ zq Gh#qf#8M ;5O|>0rCyÇP(Dã-=|lJm  aSBڒł(d(bnIIjNCqV%QT剟lglVx5#5e Y5xgQܪ?\T91G6̲@#F"qLa*`i+Ђr8T̀Kd19Z+\0H$@<uXlt&lȲ ^mBٖqC6mh&-;NC䝇8S0#_SԚW 63D6j L$0_A#:29U7[BZ-Mn G̛o%3H1A=͟?ך>CM,Uܨ,>hj :CDQDe1%Z :q(0JƱ"SȆǭw'wHǯ"Y{.95 Cؽ~5RdixIwXD6"o!¿FıI.Ţ[xGtE}2E8>c;OBc@00s1TX`"DE% FB&0|= F|4NjoVNģ?4W*lFȻ`!&u. &)}38Q屆s?k 궦Tpjuk*ԔɆaa4Ȥ\i:O".Zսu=τNb㐞gӿaۛ73Nq_<NNRU<kyxUhT\V!Io2XDPif_G"zXxgIDAT/mxp"_|ySR|xSsQlo[㍦:B wƑ_|y!!lIK_/ fT-#IENDB`robocode/robocode/resources/images/explosion/explosion2-56.png0000644000175000017500000006606610205417702024013 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME&˪.+ IDATxIeu[9m^/lH&TI5DY,@<ቒs<РJeDRQ*U1SLf&359<;"d$i[U w=^Z;?Os " ^sU /ؾʿ%^~t%ϟow'Gׯ> "ۏ/O;xiQYoeXRB~Q''n#SYܑBl[ 7瑟ub&qV6_~OxkCH">{p |XwM\&x?H_F 7"_c\b}z./ ֜?>34 Y A'.VЯ*rcx<\E.6|“;uW&[ŗy45柾)<¹ϟ=y[ٳœ\%"I_F "C}\޹::ፕ*M0p"Ϊ's*qӉE=I.Ϗ?N Nğz~W[;n9~xx+n_u.NJQȷ?܏~5rVī}> _/>m/ ;wO?V-ፅb{m5KC4nc! U9$\D.fs@"Bլ+f㒵 N{/:5~@_w( MqG㥥꾢 <4M+XP7vxY ~|iV M^K4YW%f}5s?ҰTtFd-ܰbT sg@+$($$] !qId"U:1H&6Sc[G~Nvx>xo%\&>xE{ŵwIjjSM;XER 8n8ajxyi.½j˧Og\_ h(TOVyt7qF$xNMY#'\w%}AǷ{-U, YA YDш7hҁ>Fzi@CW=8.Fw#IA%M ϰ#p<4^1Vj Ws;l~Kׯ2x>^w2V^߻/, M9Uc YDN+&y 1"׼g=t:~XHy?|>Mi'̷ͥI4'f 4@KECLmP%09dDëj$`VGzm[*mRu |e:|Yݺ\ju}av &{i(A8fym9W3zIn5b:@q!}T2s~ױxȟ~U/e׭3~iC-Dߤ{B08i!R4tFs喂+犟W[oZ+h6<` *1dF˜/ ccTu os=PF`*QSf&\˜'BZރ4phF{?Zc.47ךf~amE_YePRYk+W7(e ~lYkmT=oe-[|aad6Ft 1D?V|(rP'n5QU!V{i s6vN5qC P|s:Dza[bj cp㈖DUa\LӡbL\mػ/pv]PI(SM=jNX+xhjϐ3QiQ~Dhf5t[t KGئ=í❗KQw6G@S-Œ^zrDu{^Hg/jI \`#\;JXY=6+fihCE0r@D 3C$~뜴0HZSi j`IR#Uh9c">Z. fsA}%R*bN1TBfbhtdchz=:h"xƹg1$UB@ OX#q0FΫ 0g/_<.wYN3c"J=YܷquFf13I3#11$q)T:Q[s* #fFEKpŕ n` dzdžH ZTnE/ߠU s9s0"l6Bnyp]`1$A0@Z(t-F AQ+vcDc47t ,}.=+$|J+l`4c?Fz7@;'͛B V7ģUwQoq6ч_YFKRW  J3".DzQH8ph*ҹP/ia J- 4*H 1+(ڧ!VT8D6 [3} 8̲Z^N7̀NỄ!(D+bl [*7A.oU$8l.7r9yY" )GpQW m{Zz3Oت@+׈kcƦ:<ᔍ5`,:6Tk!a|BwIRc3xX%ѩ&2CIɂjF87"@mؤJt@ӧkE %aB"I&.QqA2 ΐGdC `5]E HpD30왭w̢<8_Eg?oFG`{v%V{"F1fad q^!*E ϵypo wHkTW$OD&6 "*Pk3p_xǍ@/c:"R ( vQ7#̳Ցl O j_5/$_>iTՌ~ q?BI!M,!`N!sP5ܜ;d;`>>D9~!&`}KW{阋zZ戹= 5-s· e &rHxHĀHuc)cp,Ы .PqKf)#A )}iQj&jE l{cÚ '#l5y:Tbq?WVπWiއZs*$&1@P9߿QO/z)`}vժjǰJ$`(JVg!5MCWZ8ab>S R K *_#EPaiA+wD Rxc$T`eXoFk{paOξN 1~CS!*rG{ q3j=gh?yf,آ}2 fM }<<3,t=xJ`5\/F̔#fk\p}JGP 4%7"z{ψ=D)BvǍV}z<|8U|zB{3L 0GRC\@qWc ?GR{H+~C9܈W?\$ޗkN ,#ſ<3c_t ǪBk6 H{>í>Y>?B4,4.tq GUj[ϳ-UWϯs ~ RV ܏%߯T+@#;$2GFgADP*ǚgMH)3BXaԖ$F^#0uuCҲgo'IG^m"1^0l VA eK W#pc+XWsDz۱l~)m͏j;%Y]1RSUmC:7ǥW~tNӂϡfP\}S|A( 2tvN(0pa 7B0#R)-הN!uAQzV G*:* iN lq>qb5#؛gOx8fXsdD%߁w^F*sA)825*6}PW7Z c@#[fp&>]b~XpB#eǖrH`[A3N]y LJx0;c6w{zqEmlWQ~=!@,ILjЕŧ"(G,V0 \`XG\M|8h#Jj <@8l_7hl+hfXK{Hhm 茾%ঠ b{%-|^v[,0,-]NhʏΟ $SY10T:]HQKL 5ᢂe=!+-)K8Y vʧp`6TMJ5B/xGSXTߢjY8; ;w 0hfZqn,UjC*2 }ZԲ  L59lNag#ؔ+ &pznUWgyG 1dS|*]ٔݟ|S<)i'8,ӌ h)i$Tpɳ DJGi@,LBL >sIglwx OYƢ.wMc\G]7W6g2c,5Ws4sTk38V>+Ny%[Fcss:GJ=^ߥٞc3LJ? )p+/4Q3ci#7 ۨ9'Ih9 k C!'UN Wos6C![-]]r,Qx,qr+<.`V/L2ٙ˞i9}}݃6[h WprA >鄷AnJiHDE+w 9'ڏdYxa`!s{brv.z-ΊbŢՇ Ze*(YCpQދU^{;/gzP=DQl.o8+ ՙ31lpSLuV F{ՌZm7<`~Qw88H皶Itx}N:زE^A`|w2T'Cr;Y)v f]~J1ejR嗝2tE` ;j2"fT<ij̋%[B.;~,gD~7h,J$~mb]WA}pZkFFv p̜>\JA &6(mAX̤]39VCv]=ixe_Yen1ͥ'a\R$JIK/Ţiabz '׫i$8r pe <<(A9|Z5 zrS_N.K䮁9FxBT#]:p M(E9UH\03\\n2({3BIBNW"=bK.Vu]NtJx,{ T 2"/_[~b0Nn4 n pKt>c:{}jo9ݾE7FaauFpĝRzi9[>Es <͞Ao,j؀TԹ1 @E-fNf]2G#<<].WRĩUh0ys^gz*bTLԠ&`j~"0}QJVؽSnDa 2}s]nn9n< $טG@i[a^y^[F ?+ŽF]C~٪tygYyc7 :VDU Ԣ쌘HhIcMZ8W6 &>KsM6dow/hSVsO>[VkpB >% +,#{j%՜ y:ir/å]^GBPƘ-^$)$.hMv8 xt@}x[xv{˄+,bu5{"E IDAT.~${h U-F*" *iU.TƔ-v CE}) Bʝ!Utm*hZdW Մ'(]^ 6ݥ{,ڑHI'!I?~8<>9_BԥL-63M a=5*ܯ87%~'?#9H <ۮViORƬ<բc9 q& !F"@AKfL w+8s ?2xȝ2.OQ[&Tl)&i=LQeHUxm'1>N\yt<>Ffw&rmȰO?x} p̏4)T8[]J IxL0&B$'kh9>.TxyzS\4ͦlhG?n@CB6Y-<*ͣM6{3]KMJ@=qӓ7vM(m/(Ҷ/][w=Uhɽa{N]Jj o <:U8ݐb+fڠAj|&2G]⤠*M5Fr$_ s!Jxeݴ2ym|.];Ά'-%qA}XdKF^?{چʮ<+eVҶ`>jl\Z=O;LҽЫI(/(~҄:VR:[Cx /AʄϠwƙ!)TDS!u77 M5Es{Go\I0hRR(I ( ۛ&u(u ̐p*#eUt9υ V.}N0R0I{O ;^))YbKPe*C$q]fqc.yyS2i?)icÐcי_VIVJtˊv9L<:BzCf7u0>-BZ`fBS bi..~j-/pQl("J}NFe,C.n)|R<eKV DDR&,_E,ґ!) tO7,UeRk-zxK1o5klSSl]BҤTEH.SID &fbvTg H>mnsOc3eːf0i&$R(@zxډ2wwdpse? v^06czࡗ mNE1.$HySI&jV5,眺l|Ekar+\ǿ:֖cZ-#P6)DKC꡴Y)5d~n]:_>WU]_A]^NFGԓ~, NaBMv A*kPA? )  >ѠB$^Q01Gysf?Cs蛾ta%We;_ҨidKL.[E2 to&ce N9y+D/pB&UuQsdg+F`*Yʀk>s&ԈNJyB,%#JE#VB0h4]YzQD0C HJbQcV5ը9GlV)1a1eZUIy {38+oo=tS=0/M"vr &?ɠҙUR' /RYࠨ61s.L4]}Se6g" p{\}H$"QDDRD+2#IFj3@06q)ԗ{ox uUR}#mS-(G'Œ0)#%R1-e~_q1mVY-TRk @l0Ȧ *tT4`QXTPBCVWY1, IUX|3f,wkǔvìTgۜF3{v EdR>А j8jM;fnaYL$maۼ2UJ>~M`=֌Dz*ՌA'CŘl>D4ݘ+\a$9nq^^¯ˋ zC)޶q%%stN_pM@s@\=\U{͞(SMyX~Lq&:9t̻l5GsorzZ~!`'5lGɈV! J҈* 0j {6!`HG@"(7o7dW88[Vv]h;)vâ4.}eUn:*H.2s GpZVH MMh's`&sD9Wlf3ueQqʒ:%D@TQcնqVh6oǑEY=O6M}Z O\o1oe8<) F2flBSƋlx!*T既 cJ)u$ʃfc篰i2uS.u:ʛ]&;gF{76 L `TbPBr׆"H>XeQ&ner'TDHh(}ZlfRWA5u#p>| $j>^Um)p+*nsST"X 0AE")A-{u.\) F:6<4 u\t^.Vm*8c)gUZ=ʨgB,rosP;[v*w`;,jҧ3Qc]<| ;.T{P7Nyɕώs6 4*)$I6 U@f@d.Y5j2lggX/?16x'~k.<#a\):bv3[(BTQ4pC.&^|Sc2iA=qFchyn]SmD힑2NY zĕCOpS`gd .)ѭ)^-L_9 'pP)dPlsӑ dBLSv}]Ҡ!9NHݢ(,(s55&lIzK'=9 Àl "?&Xc¡I`y^1̅Y:/R舱B /379!*xy;D= 􄃗^%6JQfL~m=enB-wt% )$Oa[^9Xg k;F5F)=fW5gV>xLZK %fҘ t<囿;pjl'Hᇚ|᣻pFI<+A|V4D=C Vt}v覀2JgX6 tBg6CƉ7/}5!cozρڙ?N z4Nt}&l=uі SY4$z8 ԭ2&?_n:Cw O6DSL]EÞR#w0x8 0&>ʻ@DՇ^-J^3Bׂ rxinjG; #2wPaoI1S>נ9\B׉.9܎p'j-K/mf fWyM;d`3QYL]r1Yp0zj}>EP./e^ 1 IDATS?fc9hƊ1D^Dܭ~?ppC>ĭ:B e5xrvf-Q36{ FEuqmAo 2tJo3w9;\td %<\8BH Yu?aLJg|bo&,*|S ȾuzrZ ittQ sYo.ᕢvs0qߠdMW`@6wz_=]yFQvb,>w6 A˹nG1r fKǰekzjI,Xmʃְ!!ʝ@He Щllpr6i\\PeoI?uJ~t Ț.HyD:m;_MlW鳓^S7|\gʸ}<&R8}Z?a3 I5ue@+?>̇\W4ͅ= eZfihy? Uk^``y}>L54-6J~#b  IGN6d9>^è =Ѯ%ΰ|RXmi0R3 -Q*Bhs(8o3Fmrd `Xh)35ݼWVDSduGsY`=&f2knFppL?;$*oiB7X,}w#'3X4Q[=Ŀj#?~gMo2R.c N9*h/͖q!ךT13:{U&zfR[Je!//8 XD0)E*DI9B] f1I;s~d2'3 #x1 Vtj=9~s@^!KAh7c~5$^z+Y:xf)" |ܠS6<^)iY5";3#_0j K/}69#{#D{d*^VwIO,aApX÷|{uVV%%c0ﹷb]F,ㆦ1#(?>շ0L`vXCtA/|S7Q8Q E&vvB'w%VEa.G;xL GX}Jt5ˑڃ DO ů:',UyC3\vj˒\2P@ gA$HKDBc>hnH#~qH-{f/"P?-M)΋Hf? vAOJ7QX* &דD'&6䰧DĦ". VW)<dLs0^eج-$}?˿ik/+|@c|o6+ᱠZ ޺2W3,±+'r<oVЕXL`WhjBj_(nJMFjni*5)PwA,vP6`4k`{`83'3*jT4qk>fW+~0gEn@|?={v,!`{$qn~3 ݿ̑e<*b3nmiMnNha 9wT&FIʩv[c!.~9e90sceiM?b2&NW96fNĴ!6b;`x:2͡_;RT0~H7?g3`7皧^q8XtSљI }ň/eӞQ- m7&>OSy#${^n^r鲑$VR^(H, m^_\;KqlR=v+]\;>(?Bx;vK'vK'WiW!J1cQ$9#OU_?ҿῃw4o(VcgKnm1NvAdEk .%=y;b+NXH{3E2ݸ ;`Vl\WmfnT[UsX' |RL 8_9nBҝK&!d~EݛkUbX,hI1^(/bO)޿׏, o?76e5CdUG1` _ \}ܚaޠ96ptpRiuJVXƉ毿a>=I)MBvm7=0= 5]^$R+^x mdfG6IwY*u__C+VOMnJ _l|]eY`yT’ 3 etmU1I jX+wEG(8Q+b/*VTW q'8}CSn2yC?D:^DSU\B%F,o xeh3L;?WfnEVJY~c6K}V.L!Nd'NM;ߑ^==8C=l=m_G IO4F_2L~RWu51ͩtvL*cI~s?nN[5[+%B'Kp黾6gGQ:OmB򭟛,v\,r/[4{ 3m;'5D` z_j17+l / 57_;dc-l}=ڀ!!ɯG: WwއʼnfxnsKh+lt$U*̉jN&&{A=DVk vsESTUձEK|7F乻(KW0w򇤊b-B6`4.bMWTd>MF8tJ>ʻO=KOWŔa0q\ڇŦ^ACҹ^/2q'c2N6ymQ=֬HHdwE-/K%?2;43Uɱqii\}\CQiPBR@G#c2Iuˣ;.[Zxm/Ls:?,M:{v .?-DXjy;?ܝ8.r\߭-e{I?Ye x%n7`|)fC1-<^gw+hcRC #'Z@t{++5u.Y#úw$WqWy6Tf,qw Lt JcX`V'5xJ3eg(9*`5]3N{rol)+"uvSa49yc6)u KBH',P+I9k3 kHO[kɸ׆Liu46\ۜنgWgn9z~݅g}$̜ǿl^ը3޳ PuGͪzuݶBnr_o.++m$#Ȣoa:ew%t|FKLx(T mzs`].]Ꮠ5yx٨5*c9M[ƮF9$'=3ljHACx6 *V}{aKiԣu.JE|Z>WO*靷^k-zPXs96Tt,-@,B0Yuq]Qr\ʁ 7.?;9;gRQ )c>zXks+᪅vLX$EqN 3f N64B9\B 5N˔6tFKcL**A`ݍHT5X-ҵnb՗(b #Np+|ʣH:,d2Ї$hŠb {Bo,dN0 ë0J/yՎ}FВR|q3:ngY4z;f(A0}AX$fD㜟\AH/#sfM{MK`pfz1C]z89=']=qbIs3gR2]b+ f|=~H9%ST:pJ4'_pq0jھDJA( "Q"|38$ivS"FMp9w=F]aBC҈qHHj 木:,+\mgp#tC c()[\ۤ1o釈 KӁ16o1Ünٲ=獥h$h $"$,J;P@KZ| huGJ-V!iDfα5m%ĞT <K"r;?XuuZTZ}6͂Wwe~.[AD DTh3S&Fc}<ӕ<2VWVnѲEc$3F *&LQ["2 z1Ko~6'$_qV[/, ;\Z#*RQuŐb~u?#Sق)A86xS`͈ D]2Uuz06-i:N4ub0-ٰ^ wp^R|d|`RJ>^W8&@'E ‘bu,*do=vuYrU(s*X:Vh}E*KI*&t:)Wk&i5U<)I{XL"OՒüD+lx1,{֢ɡ4Ղ!~ ' ƶaK+yj7 P=EVgs<"aHI1TO0sVW̫+iDZ+Vjh"հ!K}y wP&($'W$qH NY"ZkDR"\/eӻaԃ<::vH$Bbm:35K :9Zv$oLQHR[lg}MKp,ȸEd1%:b&]a]$t>$TE_H I4:T= jpz;iF\hNaj#ԯ^% ~}kJ' 8 yocoQֈlQڣh=GaP2@2xRpxsm>3%@1{x":-iܯqodDOH!$r9`%ZSoϩ *M%FP:>A=Dl@(}6=\ zё^' XL*Y2YZ+Wj90"g+4UI"e@nꏨaNxz |x*goY403<ct*ʚ("#=Vhm T[IU$% |Svi8nz!fD\{ ^SceE ?#0ǧv-p5k$HsVDv MV4")JcZ]cԏPAǹ'iƓ}D}Qya h'ɀ*(1J.h5*v4'2C9J)-_ ¢_oa%\@Ǒ?{OsI\^Fޜ{>3p;hqr@KjS(5J+80#\驨 I-VZF{s%EҎ/e*B8lO{bi+DhD:DRy6#RIysu;r>J`x9 (\,nI1J?!S_NEMG(4UbZ.zƃ5J?SlfUb: IDATӗg-]`pI!uȡx?^@e3 TE1 #"Qr9):Ӏф1/4d#*e1)+1qDUdiWTՆas?2 瘸AA4ZxA2ϱ8(nj\C$YRJiǸKjNzߣ''z@EU+lMm`{%T> GPEu^CBDm<:ޡ?R<n:PV7 |] O 4Ͽ'{dhJg6PTdR 15"/ f'd25ä$YR96ĀV[l@mi!' flQih|6] H:UgڳZ6hwƾp'))=Bt>q=J /%6k/fa,%Gc4')*CDQDM616bE-c/ȘHC#$,׉'@_QFO`q[ X";͢>;7|A{xHHcFX:aBBNi=}xA 6;P[P)SBB7->fU&(բ+0W(F5H$+D%u-x.`{XT$6uҏy\NhEB }m ɒ3q$>#}D݊[K=ΌШB^P@4>43O;T`&Rq]@H:\-CK^NcNoG?!y=,}cǏƊjFۆHRY>I*f]/TFd'mNKѩF)!ݸ1xPEE+kB؀n(-H7̪˳D}6q !)Tb"4˘mDf1WubO Rkjyk|RMT3hgl7B^GZ'ĬgB8LU M|SE =D'Nmx}m2AtA54t~24ĪA=SaCI Ҡm*cʡĠEL^TmHP{[w(e:Lh1vè;\ߓW !ޗ^1#Y8.7}V C3̃@?Dsw5+9n.jۊаT]ӌ*BRE&\ojDR% e}X1v6;mQm@ BU,B.XKTR%A/.*P$8`{.M: Ed.;gΜf/<ם^N4"x.X 6G TU K pKi$hВaUBJ )%Hi|T @U$Lb+t1[FCJ68x8 <3a@MHj;1`} rU-E?EG`V q(ASJ7βxImv)/l.~s%5 !j $7Q3Vh$ N@i!FEtTjI昌B=8(,FYν1N,[ʒ#6<;;v&bJpK {bx5jPE\#|@#-9PξcH¾zݞ7u^'EbO Laۚqih ^i0',`5!dNb-TM{#h񾞩Z{Zmy]zNѩshv< _%wg(؂Y/d!\i#M%vI88=nZiWwg./g~/C.JWD0K / m)(F)p ^`M=݋'1D)"8SW*z\ XFze#z4W#5085'l8- Ϝ85?*40:<ݹp6ގkCMoM#|U ]C{MR  FM`!](H[E X]O*k IabKGD pHYs  tIME&Uλ IDATxļY]ו[k3!AR$%YeY)YYPDF G/g1)CU@HUlJ[%QE2g{~8d;%ٙq{95k[/"Acmm@z92-*pxcfwOƈ?FDtj5}pcw{p \'; TN[&p2?5:Wpkzo"W/"}^̍K KJԠ W_Y:%9 ҹ87\ߥe|݄:ecIB:/ߔ{)_bu $y~7X׷lAJd\aОQW\k:?<&z+y*U^Γ Ҩ.26~\m&,;mkbZ<K9?D9?/cFx/ۿ-P9$%ay Ktϳ'̦p}7Jo?UⷎC卝/6ON\(M85_8eJ|~W[1?D)~ ?*WWݙ+7 { @IQ3BTN>c[;o ?L)r? GK "2p5es)ػbp~yʤ7 ~ ?IX;ϷK/M`*4C͐qdf>;67,!7׏>^fƫ S'욿q|?F| '×9Mʛq n~kr,a bW,9ʵW_aB轢d&o){B4:mIy~2'3syo;7#| @>LBw0>uƈ\9jlo}93?ΰ\Qv`]ab9qи¿%Q"??WB 20*E'P  < )djѐiWżb),3;e#$v^`F+?>$tAAKbQS űt@"I/|J~<Ȥ*7P̰Ine~|[qPl7"F >_QϏQIQudyMhDΉp8r07Nկ)V~IJ;8c+#cGƁTx28 yJ~#z'bGeGCH .Дʐ FbJE@gLrQFgDCtIz(pu,M*`:"4ҰC,&ؒ"~FeMהMuM_ˏ/moNq+R)6J. ehl@KT Ֆg׎lg(_b2' iO3_l1|-H|A9ŕ"F#gCYw T`GP9쌮l"$SR#oVs~7so R/ n?C9$s !(}ː4c32TЌIF#ƥF,?ǹq4o"gr9\ rJ$̈igA&0-6N.8}C/?n«+cp1qKn tn)P ׳kYg(JXV(+\0-Pc3F~5w.ƍ¹b9=&.!3$ls^{>Ex2!:'έuAyd$u8 p*{d%%#%UI &r:_x,o2Y#\g$] bh=i˶82H&(68pFe+H( }2 `.(@p $p18{#gNF~'ܻ(!gzAYr@JH%`d<1T4!a ڕ|b\VMF <X<,6.PZX_(iTB6zq`y$M \ΊP!3rS`<٫hg+Ŝ1_"G.g,{~ܢL?yh 9{S2SJϜUg4-' b#t[ *-&œ瘏%Ag\!ypFa# !Q:,rCrf!!@Id5M~Tg4+K.K:j8Yfc%`Ty$FA䜧@! ypCM1& VfƜYVj8aZ~ pW#WG/p !uX2f`5N1,8dxK;߹8+u3h*p"EҌ$ ƳLdC1,i > V@hKb:df l@N;3l:GU5(JWVYX%,9yEV6]ڔe =Qo )WǛE?= Bu5 }Z e4>M>JBOp&@dxp5 uhX0^qpwK3L)9'YΑdyJ_'۫8%]F>e HptiSʂYLRj\* lX⹠ #itU9X ̥_F.$sk"G ҹ10B$pSH`{\pb1V=EpX%L..;a+h^^ C_paA~@%ANl#ȿCl8BпG#Ozb8T8+٩p/ CK+AD}S)ԯaGhMQ?" =)5DΖPnԳ / rV3P#FJ{.LDGXl CH{AZH!|"m 5 s.:JXxR$IdjH>AK38ln.q`'F,p_/Kk} :]Ñq܇UY9d A=~F=䱠G r4_+lm:U*G(2>u8K%26XS`@eR|֠ɣ5+DY^އ>G;`QQ {;r֍pa4.R5  Sf$ʂ3J!CɚvJo 7w}~Ige&r + XQ0!ex?$#pLmp#p {QQ8fXL@+ ,DbئWL/I2GU8%eX AIp:)I`P8"U) + a'65-mf 1-GNM*%w`+eTHg+>,9n'WG jPR񀶎lYૄlY)i8#qoˉ uKS}A!2_"'11Ib:#}i3\}. 08(#3CJEB#RY,!ŻG %-N1h :f5GCo Al"1@w!7ЌBXǖ`12b|YxP\Hޢaˆl Q);PHl2l!yx-:|8Q{?mjb\Gƶ",PBeN@!-62(, uaFZblQ͸.4ƕöF JOx .)˒X~*`s?%0-NP #.F4OYOջ9AMJZMQ7VH!Ē0^B`: p0~hS0[:Cb(GVtTOH(]c>_(7994֑=a?.t8 :g5(D2H13c2iO|H"L}5-dQ`.8,u8B#ߛ,3D32N8P^ ?9\Nu#/!@JWErqzd'oL T>^0%"@dJVDZI9_)\&Md)SlH0`.:~H Q7=5ζXȖ^uSs_}o^7\#eX ŒlsqvL cL F9*sDx '~M,ӆ m g!&D4grd\e9%H/zpp5MDˊ._Ȉ@SLp0d402HM'QA#"HHAL2BU@f:A̦uoLP`P99&5ƈZ}`L=.(@?L+:y ;JuTJ( {Ie   @&w ɵ/h1AhD&_ۇ% AT8 ]̟zza&7`=Юx*܎# ƚՖ.o9T;WQ(yQ):Rez< i1*|NGP&o(-R댾~:\b=-QWrR0SC?Y gx@!0-P zNoyI `dĘ9!6eO@XD!DE9bBF2)tWChuOSIx ΠYp@{dyHE-xuo O:G<]g~||b\F.ZD ydUH;óq.EK&KnHQDQk I}~pq` H:VcG88c9;܏☕` IDATN0 NrG `&O^`'%Xi9 R( ח5̋X-p]lRTWfb .$wy*µ-NÎ4wэGJ; .R܅+Pr~awkq3 kõN^vN%7tMq A Yr z{+R(Dzۆƾ|Oq3"ЛK |aBj['J6|A%.G ;MQ_H(!lz~"l(Ų -¨TDėHB5# O"ǧd)0韡@WAq3<]qrxѫ"ve"M.ۘrKɎGݔ½2$aЦ"ZtNGd0!]~h&ŷm%TAjJ; q~y^ITpʴK춆#u=cf BO.Ω T%MR:+X#2W-4U|miT،<$9b=&wi`\.8j 9*<$D203<ud0|P$\ǩNQ(X)&l̪uN!Om)M֪%agWAC֩`JMø"L q&R~ROq@ NjB?N> pa >}Ӳ(,LίOs4;ڔPuT2G\O@{v>RҙDG;"ac"p ۂ-3r+K:bRV{ƒ`)Ff(7h,ؾK`_-H$ce;,\^²T`VH?g)5SuS Oy3J3)h>}m-ӒqL@Ka!ʄn /| pA&/dA;wGxcpB(WalEbq6 qir秸<ݰ-#zu"`ogXMb?6+@[ݠ?n8&ǒBgT:{j3eõf^ p6.9"![@qGH,O9@j*\fY U5 ͓z< vɡ*L ؓ|c)gӱ1OmXLnU])\'CUUoRX='}DS%x)OΎF#O7-jvL놄 "'8Wdug-_ҧ l)ʞb5p%j9/7Gb~z^zH%#̸qk) j5]L섘?D س(/!%XRO1TwYLivX2L+s\-]<*ZL9+b^:f;"7N=дR3Yv+\I'~ɻw:V-J%\+zV52廬+?;_3(ALgEwo:e:"CqU˕P39wq:N3LNrIgN =q_S^<.ʆTis)6)s+sR vc·gl]!6&e6cCP2uWnʾ]r nf SXhTs(v8i5Y?.ܓ'[/%"lhs&zyfvp3Ո~b~({=B΄,[Z-P2Xb h$|䁏5p-z³HIAsXlS&N>R˴e\e90P7Yɒ8KP"@H+.}>;|;e~} d>]FZ*jSPab' ԨZAf~t"HopiL<$q^Kol=_rQn3u&Zdl`:[X rHD2!$gtjhB5cx AˉPlhǎ& PsJ |x0^Ba#aǺQ=K /_ޤ$;{֊ݜ޼yX I"eU=@"=EG0L@x"XӦ!ӒbeVDZľRYEL69gG|y>!/R7J?pTpO;$@8r@ڃ(=elCRA赋Qt5K̎p1R  _;eʹ|+wsFwᒿ_쯅}WgceΘ {-D,Fcoe%Iᕏ?xkHhHnb儶YVAKt 9o)g&$#.;ԯ ^| =Qr6sF-%]|^"z`"ZŠP托EtF`;8Gt;]?!u m~ +X1 cl6O`l@nYyGYhY}{HVRODSLj3E#Aw8HU~ ]"ra+RaT۽qԱjkk#<\{B~s8죶vCd^!WdHpKcV!|h d-_ i3d`F,fgwEֹ=g+]):w)|ϔ?~9kgIS`;(R*T Ʈ56[7+g#\-^{̋c,v~Jwɱ YNY # S.%%N o'˴#;N0[t{HVSm߭joT>tz8;6WCȡCvpԧQ cô]hhv+N$u1ؗXS_f'(9KHHģ>/{w΋9{pTy<d0% c0. ´WLϖt+x5]үGl@Y6'eڒٙi)rBkŁ`щR F^0)FFl98Ӆ:d2 _4NkoӽU[ikwPS6׋?\n8 ڐqvHa>c V[do {Mx-#4¼7:ㇿZ pG(: C`a9\E6" !RX t w`*e;Y#6P1];dg{ĕ'`BU}%5hس ܈%%TR-eGz]Ie87\+E\î_<}. 0:8em7!-!mK`(Ōu+21^2 Tfڐb W9|~{OaW8:.7BB4>pj\Th̸V' Lw_!#`첰seep 3C";t\!2Q<2‚:&.М):ڣ>%%9@Oa1!Z<U9?_9EW ˿ g3p(CJ-*ҡ=4+<#$y%E q<#}mc<=9r2i%,p: G} ^xDEoo(S5-}˰z VTXz~FgnKA~. y7Bi5? c]v6j8%؍ :jj[K!ɀ%%L+JS%V<%K)JN;zK^}xƾ2/FvK)f:c-=b:xP&#0utQ9τ(!˘p-HQ޲G) 3\aؐq6#"kaF~&4;vYn+< <6xb#wFc1XLHz䯳lliiP7~o [C맹P N"-|s C( [혁0 TepyiPmAnqyA[xpgjAvuDS>G}5pw|`qΈɍfC5<1ezlMc%n4"Y'c逆&/]" V┡ȑy hv6[\v̸;~Jk{?s{9 jՖP*NsliRrI1-OHsG̀ٗ>br qb7;}03 }Ƒ~g\RIxՄȑuxLѻx !`ڰ}3} .̶{ƼGG>- q|ovX lGaV" }dPsk[ gbr$ qJ$[ܶ W_fenFGdJPtA?IߤadqkM@Q jr]Z0+yI< {,"Fc~LKf^I;mlstkI#;]:lʧՉ7B{7pcgp/}XQ f>>AtA35,B`tᱰB|"|GB ҬVdnp M$%e 0Ֆ1F0t Dd }1@)Pha$jb@L5B\c$ LZ;U8 nٛ*5 l2(rbt|I 'ʎ9{FA3lyF*ʞ)tsrkܿ=o_dPAazΧmh ]n1O(?aLEhk!LI'Yy^SͮAN5PmNK\ nHE$XlRwR}0ρN َ e P|^(CvPRPt/D. Ts&%%?؞&Sf`w7H̥%N#8Ĥ.IQąNֈ wQQ0 1>"4a4/R=,GxEprӁ}(wz !"r9f` >}d{:ɔaI J~ |Ⱦ'vxmGWFt1s2 %}^(qļW./f/ fb8*B2E4_b:s$>~g1DbB5-ڞhuU7 / \";@.xl !%ABa!3?BYKK`Eir"UxqFL>:{Xԙ~! Fi1MUh1O))R:X e$Y-fti*dЙm=ooe>ŬtȦUN[I,SN!:˰EI]vh_APIRo|04F6D(i0.[z;"H ߄2_c-A1SVGd)TukL%6&Zb#;eg"E$NJ ɠLKl2\G'2 W__ ̰/Q$-<9 ͟r.9?'hiґ0+^9Ox0J)H>Ι˛B^?sA?k2XytU-\/IY&e&Qic$dq"kh MSƘWI¹ E4G8%%,*H+ Q (6q&,ȤąSFL(aYж~Kd2g2 BБd .F1?"OGDYb`y*d023 1|qBuO1+b0sFgic93BigMtZ) GseZxw1 ?OL|5Wo8jkڈĴ8ej8J@3).U D)$fVl#pA 'f ,7X6IcHIU%w4CleL%yf_ccmm:[@Z/ D =]n2AʌLv#3I8~P]pJWu)xva,nQrB S$=# mcXXb*(0 ˓y1?X7>{?(1@(a9XΜgpo]`aM#f_|>+:Fuj}# +1ј/ ^ll4v2Hbu-+M4шc }G ; IDATk:.=: ah5i/cdqI!Jfkrag\3%QD0ƆZ*J$jM'A-d{PN( F #gO0)dONe]9xN=ml3msF%0΁0 Q.\uHS4n͙Eyuny=P]/_h HJ$b`?y.̪w0!Ek ~"H;s f+Wo_ / aY9S-MPZ44ݓ7[<'#*Xl@J=MA[#eCӧr؁zuėIr9YeEmm( JBBL`tk ]*\!>I;)::H%\ǘ?4!^c+vX[4OedYh}b<[zb|_ٯwQsS$eQT|&KCl( $ͤ'ix M54J@-Kz\RQf)4R A&TΔ K LY a&QiV@IP-栶!::x臨@žL.aK5oq%W"s" I!HAmO^ᴯm"- *+̈́=7B2$[nq$캙=pEvKl>&lNe°G5v:.KXaNy kq&*VVxIlQ1fAiʜ[!׹|BϷx8ܡ 7U09:Rg X0Y iMmf5"cDeCh3# Қ3@ί)ݿfZ KTzZ=Bu-l a&K\#,Dh g\S0A:HYh= < q"̐'Љ2R qara=Gq*\KWO?|[{_)ׁE8]c r| wT vB1S:$0 uv~W9?$l~&D&e˶16%RE( ufA/Q*eL[<>GDp+g& e0,\Q 9g:mG/dwNL ƽ+ }_Ր(%}GGs;!D8R ,,I)I̱.&e8j 1Mףnq/z_zw޺l#wj1m_]N_e՞/WTjpPD8̞QL#م.:xhfcZF`G,=p8ꄤaI+q|eLeL̮tk@i;QLkS<&}sâL;pK$\A&[h&9])xΓဋ;JOAQmA,jOOJeF'["osN*Zh-TB+)t!#&xR@M)1ĮԙiTWR+IHFf8J9l'3Oc_<W2·88j )Y*`*be&kZ,1\oAx@Wi)+Q;Q_~ `Cd)t֐ CN>qnɱ0gnsr|4'02 NЦBɊΛ NTRU #٫;vDC[2%OD'$[l0 %m,(7]-&XXǃ/o6Zלo{',~LEMCh"^Q$/8!H',ںr *"`Qe?y]m eGq$[zݓ+faM0>)AUV!*ntzy ϳTXMD\8Kޣ͌()ѫy#"dM{˙leA{nbW@k߽?󃏅~sP߯VT?mgLL{n+s Ia4MaNUrf1|#hf])b !84r` a,s@<2daA KKc]5dqvh%Z/寀] A(Xq%n{^]PڹRBAŠDTp^n74zM);gBٓ% Fm@"{ Cj6,Xw~[߂'Oy!|߾N6#?5ϵڳ5H)lpٻ*fЃTl{k4_$1RE'"Q;AeY:]!ޣ0{ S3g*}L, j2Z41PH@3%DlbY sԽTmcvt%>^g 03`T#6:e ii89Hģ2a_1X$.THͬs"].7 }^҈pn~;~0|$_`ʝ%zj_{Gtc?#Fw< >mlOʗX؉hD4'["̾B%!=A{"mx ႆhxbu>#'c`>| Km"N \uGX )FD#=TB1Jvr11H) J9=F5z 2gcbDK$HlJld[VAiD |3 SMw?YkƧgcIh |BO#RqmyH@6LX[3, +#l0oX9Þ!KsA)H1sM9}V*tqF-^yE.osH|J#1xOk͸ <]EeNVaBx whS]:0)Tʻ֘%DqӺ$4uaANe~łj$x`*K܏iB@6!ee# L{89{ο#q_ |Xx85%|9Fhk/meUk&q <>!.#-Mg* ܌6$iڌg궱q6rh"{5UBW2;ȡUV:NATo("Mc AMCgϰ!a3@hČ,wtO0D'JPRVUȺbC.Z rJc&ETbБTSc7S kl%$]%+̟a`drYx[N@ObLj 5&+PCu\luM:Ÿ]CWozRq|qz6,5ܣ#T'&`˵dNyw\C&&&F#-}wc lCɗؘFm6ȼ\n9@X5Pu_'Ȋ_cvj!xD3v&F$y!BO) " #8 u<αxVtGM]K16uce ]Q"uT%t.`='Tgf+¼/,Y[8t8r |5 W_L{M)T_^ 戍̱sAۺ;!SS6$u }CU~ƞ-ф%kcS_Tpj8 iطf)MǑ,)ZFy9c]2Ob7-@8>!kB<ɯeWv[ksm^ELj$3I&$j*eِQ,`@ 3Ol@J==?A6ʓ2LðlTL2fC&h_` R$OD7gZK7b>1Rȵׯ$\b=wXxW ^,5/`ܪ߲f ^; X8%;L '$G :dBxɼsP9BXx D^5pE&u0|N4VFŽUs&|N-X0GNW<!f#j M,1)9.X̸ Rj@-]u ́{En`7&5ԁe.:0 R&8==QLvܤ4QGXVav|x\7BˌN=t.:??~aK` '>b삲ĝbDY!"# hȘv>吳u ٠.,\8ZΓr3XXb 6sJs?"|:w8Nrk VjkN'}#~F,$xLHdK5B9DTnN  ~{7F9# ¥FR}kf ~- =Lc-bϰmIc'N:~ NC?EpId[n,akB= 1n货BYkm!*ثhs5)_a !3`~ +GZ|J ,"s؁D!lA)6,ZEL†xD^>ojMp&zCl1 ( VZ4BGe$ >/E^qb*-][f{ʵ [3:A%Kz|x/-k<]Mi+|JJ60a,ĄH6·cc 5AwPB8VnR@CKǸA~oU˒\JR^xsoE;;bi ~E,YFZ$!Bdω-q,B2hJ"81)k#\o&nplg;8`\]v&1>a:'HW<}JGZ$QԄ0Y>0xf|Z_^^wV8kZ??A{d\2-Μyn8joX%>VS`JKtC^^G_w?a+m(5PyFOH !@&<4MbD! ttj&0Gbfyh!4XhͶlTŹCE{%.dqhFt~T~e(kD - :g~f$j8%|BF\PpF39β5<.+2Y! lyt;. 1Ne{֦|䄹_ev`:kh"+Y] bWOw!`${+hIyBǑd{J IDATb*FSt%r%[GjTӢj0,}\t*M]A^ &8-f ;$ĮAr*ik|r7Iq8> a <d|H emu#1o0S;{%9*%B5u32NʂHL T[•fX=0kOp:R,4c&sTF v@DID(i(tA?cc/aqD)ƼCb (ZjLI;&SY=sRD%&HNa Ws"yQ0_b9b)Ў<>XJd[g\kuLpH zzJ/wQ5vƷD4R)U/FȂbX>Ґ&G5Ze )&=IB{0XC u[<ЌK,P$  :& [@) Q/|!_#r)_)VD!:YH!hE˗(s Ti؛|?G:eL1؂dDmijJSiL1$|wCh &Kb{)I/X991SuZbq cIvcTn_tD/b  dڷ9ZV5 ¿@۽Ȅ`D *veJ6B-Uw`e_JD$(x!\PfqĭqbaO_ۙA |'7a<<2R9YB2F.qa-):ru~kzA#nXۡ&y!j@ʠk NbhܐYE#rK# :vlC)DIJ\pRtP^ӒYlJc֚ 6mbʭCȳEGg"q\%U^otR)ȡJy7'?4 ނψ}pq]Tp|NN Mpn>fgK,OS,ޠ0\MV(T{Zf w6L~T*v5/ibO蕾!!ʭ4=AkjBFxiS#~ wT@]=o7=|^sL2e <R ^V~n3z2Xv;jڻpY T wd̬Tw9?wϸmC4.D#ڎ$+ +CHqCcfD$k9GJ֖h q]`m9]~~zFe_;_ ̟}bLڼ9 BpEUѢL,ZqjigZ#Lw^%!RȮ9bn)Q[JE)6`F3,e'хºI-4Zg,n+q-E=`ܝA/=C @[pJмh49ȏ(cAdO^-O&HD5"|}To9a2!2':UlJ(ۋRMqHCd3?&ܦ2鿠/v\ѐs:d yaCG ]@Dt^2- +< 2k|ٵz !y^TVAz O(M^CxEu>b#r/1M4$OQ6oj_E "Zr)$APp2Z $[r^1dxn8Z2Xiq ss1u".He^9vCg11" 7Xs<>B=FfaO]?4kؗC.MAAxxC`y=:wL u,q>+ 7 V8yqq:B%!T>GD0@.eSŕg#=!5gh('SWо*0Tpi`f8-pNɾ@"!l\M ztÀY]ŏhPp230ڼET ۄX{<\ ]nKLk2CX@(t=w֠aSC#ftpxKL.W%k@'#Ķ *#C֬g|[;7U >!״]&cbf 4QX`|u:3z+xd;\Ӵ}Ȃr!Q9'43rE+H,PԣUks/c:FȅWp+\"~Ƥ7Db)[ri8ȍOo px"C٩RR#iIl^仈iKO(sJR,D"!,`YYB\ ,YO(Sj!e QlFzQO+ٳ`nr!SIMŽzF-Wn4'cL[:Қ'ۿDܤ>=F TXK |ǘ+w>g?Ggx H A@҆)Ea(= EݫQ. ba_lJ& 7#BOࠩ _%>\ڽY9G8#sB)-gleqNcN+ԑʚXu){TȾ_T jVniqAzH2ږ7bK[GeH||3N-~{v~vhݲOKdv VŕbJ! |L#{b&)@i- !ܝ"Bȑ Rf$$gVqBqbuR+N +L;'s-qMNbf̡~Y9G}BxdZ$D'V2(¼@p_lIS ^ #F6ڀ W G˖\z ㈥ MF*Ou|By-E'aʴ w^p9BrLS=4eS#N0u2lJ*GA B£uvjƋTVW\.((A&h곗 yX&>HN4KgCeyBvm(]O2Kx<R8XA\!rE4őm[5~TװLP͔<'/;\h馑<%M1w;7[:]Y A>YhӃ^6D)=MR Ĕ8˺״L *@, xij􇸿ʿX*g*5')VDձ953@q9dwژ`2whLI4pn'! IZ(omDᩱhV6J:ĵۚTbPe47d29%9V{[`u$v-tCFNtO5Z>#NK]dODSA[ط#x;~ʮ{Z[kM~@ou\C51k";x5\暛#_\s ~u˸D/ 9 SDAӽ%@ބN&JTURUf=3#IPYL7Z- dvbJe't3N`]NxZa~7=⟡'&(Nrhh"j@8c~2lڳOJp__H7t-|fi?,Z$eZ_#&9ϑI "[{rsl#1”bxD7ӣG yYOw_\ &mRG3X6 xZtML䆶2# o#YOX6+q)}钃)r᠙H}mxbEщ[2l:^*pb-9AʒD Lc]]v3hzĞoes^@c XFGiGtܲ ;#)㻙(OL8́!&kH:f 3-{gaQjnеB6!HqEp(#%lpk|(1#VəXAi\ZvPK %s  k{a`3=^cdna$h"@KKqI@~(1i`2B .G $ ˃QftL\<ƹ3\=,V@r{&{A=.n!aIb*=mTZ \" &< #=IMqx29GtmE|9ѹ Z k PiqOi9n(a{&fJ6 0r#V+w*愦 ""WX^ %4tAȴhYέZ#Oqѹf ˯_C@K"=}Op3gq`Z;&) K[ϙ'Hzƒq7~3\уB"98;Mm{ +@^!34\ʎ$gn&-DC[FF'b#6lφFT5M@|.ahI!0Nz)uIºeKsEp'7FV3[Ÿ ֣,Hрc)8 FIBHP9Έu }֌;h.5lNcN҈6HJM/&O~r6L6؈mGo&ZqKHQ W27>p41a{ƠiC"gCZqBˎ2mc\E1*;177xF1{z(G7γ{ eX.GΣs1pSFKHsM҈'rGq`S F^MuZu.,rR|L.i%7L,*CUv+5ECevip78{qgBY {K%Srv}>qezDΛ|s--+Y|O X q'3/[JV XjE2-f~8C*Ҷ!2!K,oPy kԟw,pw*ozvZ8|yEx wϮ'.0x^{L6850~zWFi,W:w߭?WۿѺEcVNa* V糣 5³qw$g( 9߆s]G}0jhW#`ێWtґrڢ X +0[ KøZ9Rfd30bHˑϜ$+P_gqh}KhrhGmm*\ඣebŸshgO{YXDSxzqjWn"!#᪥ՎF:JۑlI-%-j[@DsRzeGNɐ&2FNLdڜȢK\> +#Li@FZb\0֔})0rR3Q1Jo.Ṃ?/QʓA91S7Og)i谲/^@. ݻ?r2?9:}Yy<vtpss!*SpX <4Hn o*jXW[-0%_*NHb ։2&DH?d,{`qxj\&) i]V{8IQ -]p0E8ՎȺLŇw?_+,:abKGD pHYs  tIME&  IDATxۯ$Wv[y;׺H7V,%yf<(@O`l@O~ooO_0iiZM6Ydv\/;N-lj`:@ʌko}[kG??G~1%M@s,tK hN[^~ ?@p9 ?o69jPF]*wk#ծQ?kW>xs5S]>Nu,&o [ÿS6U:/|ao*7£mptnUMR}g m?=7p#9QF^7|8`` :21=5e`zF7tiI+9}N]:| W jp֧. da,Y.e0H0gjl9jJHϨ2YIՖ BI_$ݗ"d ϼ9ь]q䜱9#]d=9LGGbh3se\eƿVՃ;}|tp66Glcd,FDis6C{dlGu>gRCMOjL[: ckȑ|ʕH{ 象~pt[υّ͹ZvM8 h5:T,l #V*ԫ1jow1."SQYK623 #=Z+( =jG۟FK8?9:}d?\b4J:ʓ̟W})녯9đBōXq&a$5m#4 kxO>Iaiqҍ;2[b%j;>]Odba\>lVQKxR2ƒ#4l±fXFTi+6\2YbM349 Li+%ނ[d{ I&U5ɽLJfia~G@Nh<ܮO?QUt$LZYTez:b,#|Ӆ TjRur'XK 3sXcqH^|ufgdJ̍2t+O,(j /̈́'<[Žv-o8V3,y?A>*茈ҙ9U:jIyI Ȑs؝) ฿DM[)b Ы0JL0F+`MBX %}?%$0=xg>1똩rd#!+l33!ja)FhK5]j)Oo>F򇠆LvsWXc0]D=%Eb #Q,vkdV3v׷rHɎ+k P_A5z|QYڵEW=U6w,R9~Fyea71JYzFZadZWS po^"_c5Co> ъ,ç9!Y;)3SG(U/M yg≮+%M,X0B1A_X9?#:_!6Q31TB_15$Hj')N-)FD-B )HVH\+#yMuL]aX{VmFe%.exW t :YҔy1‡]fOy+<2/dRu 2my%deR~.+UFh-0~ oX$&$0 |fpEwb16GĿi;%Ec>'i ]{P*byu*)9;F (^6& !2'R z\^#ՒO͂W5JkKJo? W_7FA }WWZR*ڈu35FLH~X=\j/nQ]i}q!M mC gS fFon!qRϞ t0̕'0a)XA Zj L\1Bl@f2Lq P- 'kdD l EDbQ*I6GX`Xy_뒎S4,SDIbYU]Mlb1^`,tϏ)X9s*,M&<'jd=naY-@__7g~Mzc)bOjp*^;W=:ܚs _XPBApzɀuJ2U΀AeJUv+T峫y0p4зE` R.JjrVW1XHrNHJVp ci 87S` oݟagOyI=d{/%[.?Mlx"߸9~VۿX ],ߜ  ߹jxtP+ӳGgw+݊wᨇ~-x$YHG=|UVe6b*+pm uydM_Cc1+[}RNe*1J‚XP2i 8=(Tpıgh,*6ωّ]C`3 +^u9A>E',ެp):`:g|ri"o='$/¯:hoPO7y,Sy# !A|ymFkC`ߕe6pX㩃ZoKe*8M;<5GktZi8;)BSȮ@Y s^?^ $[ uM6AKs81t~zsl]x"SU[T /AзfW{T)wG>-6s<طymgټ"d_EԠfiW ,>x[VNp} W 8<8/p` 8iq&'_ Vpcǝ;}d*F(}OnXVuN*R̬D yA8 tsy~*EJ,2R* ?bmc2K4pgG`<4 ܨK_&F&ùBuAg"C\8n1s&Go*pi)*5^q5;MI&1\\3' ϝ;@>ףaGsa6|[f:xdcI}C^0ǘ3z=Y]3p Ex%%h(0 F8þ2n-WD4fZP&\Ƙ-)ȱs^8m(3N9W+`aeK2PǛcBn iC™ !>KHJuӶ+$3wXW}lčd\u\F^=O-w`[CݕP ~c0D*6(V"R[o/zh7-x"qUWo#F5K8yt{; 4 \Hz #RpG0ja詃uP8&})V#[0%M:@n( AAv6֥݊OJ۠,2 Kj7Z8Nʹfz0X?\[  pݿ9}6?:zD#Q/5aB]` ˙ UoYEKU RgT#֡HѕL,/?0Ͱ6p:b]+*7Eˮ,` ip7oK*  6T n1J\7c<7.s//tstHCH3e}~]K F'͟N߰*_7>cm+ò<f󥧛9T=-cC}=9r hC17=;h EQ`3fG[٥. IDATz?\x&c  aQଅý\AgΈ}Y!^oYΝwބw4]R-?Rqz4sE P1"3):,u-c DҢeX{ϰ 1̃EFs;MW2t |*] ?`)}~?)R]ڗۦ1[h(? ĥ/G;c DcY8B= Hk-0؊l?{3Ǟ ^M5EEM aL43tD&I*gB kʴA]d>gx'p2_zFK5}Cphe15kJ" ȹGlI+(2쐲-Ã&or tXHDCv+ڐ\:,xNlNx(E+t}\daep: Zsrn3;fv9Ӂ/;ю_Eؠjv,%I\$6񪗼c)Q +ɒs*Zpx!73|GFK;o q6jgr#&q* )̐$kKe+XDntFK:=\SĊȚRTj#,Rӣ~*j"LRi/oC.TeaBP)Js_s` lqg{0f+M4[aϢYi`AU.G擋 S8 ;8QEXי''W:|}юQ 1{L!i! C5J&cd@Òd "IJbļsx/ÝA!/j\dRj1}d]Ӛ a14?ġ_UZC3|*e![[nz/ l_P [48жn CJ#M*:4lI Y>{N hP:w8#$7&>jܳVBa4  Mc,5 $[Dh4KRasM#B"#QdjAHT ?*Gs%RmBA4cdt_pjUu\ ZCKȥ2vHٔa?l} peK݈;gSv[`ܴVn7eݚW8v)tC`&\RN 3뜬IY0J=sb;Vu=sp-s(9hXvJ]\UeQD`&68B8cPU, #=F YCD5kCqbeJTv} -]2ZS1." 2[(u}L}ˌ ![XlG0[$ښYm)e~mE5ITSri8C/NL̜ Y{E>(pn՚mp$xKʎ >9dujeH勋 7p G$=S‰!è`bEHE/`M*:~e[MX1"dU}HΏp`X@S6ٔʳyj凡S_6q2El~2q{OÆQWlr8ﷺz3!U- omvI[ibe ) zʦv0{,7RtUncUR`A^!<7T+˭-àu$*POʖ C@0Ý?܏g 4FՌMSК(5Rl>]fA3֕#K@GMTp^Q. ً]1d/"~ЬrR J\a.bwغ:3[n /-[Π[Bqk0/2v n7eGgl.aޭSNBcKqLO&V7EhoHí"`Ԡ0}ߘGM HFsKc<7rG 6iWpkh.zX4p >wRk&CF&`6Uee߮U8Lit4L"**hU_>ק,0F޴N$ݐ=v@nKPy7ײ/x^Ep:D?!9:fpq~#B&Jİk` >>#e(~(M)ZF >hhAaY7j!>*Ǥ*+cWj ЙES351?+_PBd=T.ɀ[GcvQ:qKaź\gUBnr?~k+yޒ- [De :.O[9 cW9A}: NyL4ϰ.` 0IH%/'Ra^ٟQHlY#&.OTxR sTpSA՗]7}xVT1 Dۖ'.#_d(ۆ)F &-ڲo/J VYؙMN@~vk"GڊBJ\cX5;[C+iѴ@lu%fDWh^ , ~IUHQUb7"8@Nn.wϨN-d yy.h;yɠ86vaG0W [W~ JXSƺ@G=°,Qj0}8;G74U8mpYÌPWdX(vTrr9L /_.z0$laeB ;E횜;TVd@rq_Jp8&͖^י޳9m3@"ILB*rdS%D ę'(lUeDR]Kd}nkHQUH4k}WR( l#@pl !ذJ3bd0 pE~N.zZI.툗."A U1l6 \0 ]ȣF1q.PPH9+X Tft)-̶dUhϵT;uɬBK`Ѹi!4ܔ˭RQ9WF-  ؎ZF*%VI#X׈HJԙ^H_SLYϻMFsCdn8DqX ir縼- xgK7Q~I!αTiĖPx׋rP8 %ΚozMrCNOz}rAF `T Q!^D#b GR=x'ok~߷KJ5RiP9MLWb Ex$HfDҌLp>Isn'9TO!G$%$8X5_N- k9{&fd`**" JǒEXq>.k-N=+QPX5cYju!hN=QXJ|Ս I l^^׎ i4DitLz ]R3=Ika5*J ygF39qzMJc@@&H3Udi[r{HHGꪇ4bM["[2;LvS;B8()g^IXɒ0vE6#W)!>IUNdgTvJ7Ѭn^5)$pZk֩i'nFjE-3({8I.VwN 4u;/E}NUNN֥woJ  hRd[FQz`8zLZ\ E|MwZY/4ZKXL]vQ[ܝ1d_sR)NCZWNo-J;Sͨw0)@Svm4uj_ʍգpS+9xFEѲN0N=jHҁ 1H"U@`L 1.Hf$XSHw"YbAo{Y#ӌ94nd 5&Y5tм2}Io*DQ$*iQxMӧ)!a@H6oQwDV͍i ;eU̜7:i A;fmtFtGea*$A*.#м"4٧yvܕ*f0&Xn`l).b4Ú 4UhĨÂ+Q8m"@;:VkBߓ]ݎLu+gƋ;‹w^ lm#u~@rТE,6хrLD,9p91రY]7c6伦ʁe7 F=#S^r)'kh:m趘I}w]N;_V+=qFh$85/ 󸤛)/],Q\NySe0.#Հ9Mƒq>3D{<nch݈Fy0`̼%~8yUݻ8 әGC]\ԝU(qnFl07dNiҬZ_ۢ0kVHÔ!¶$[~Rط?EuBJͥYX_ ,NS<b aPDv}R 0B5-q j,MRP/i.rg-4LE]`#lSŘ2A=S}i͉Ɉ HX!yq[\@;WЌ B"CՋ̃2(ፁsۉlZ 5*ZUNL$1 I\\2$uG_ckL TPZ[;c,sc+z_z,Xaa! 1dnK=;]*l3}8( -lEPޕ*geM[@ynBAK @K&;9M UDRXw^1pӎHjF*HȑxTf {N%>W.6WB:C I )c& ~? ^X2a)u\$r:[ _r(M5pehW|=bOKukV n^{rw:sŮFStQY;5Wd Vlg8ZkHbLg#TQ]`R\X][6#eNă.+=n e>s N8>.3C%,+U"1D1G\79,- <M [{scT{mSg˾&˱4Q 6_]/߹۳sy ia*U;(~RdOq}:": IDATVPPDB 'Z^w p랓ǺG:8>FGDpl+ _X0T d1<_9nyAF u* 㤢6*D 3ߪ'ϲ#F\᜔2;.P=sG{t\ں8e'-8~EdFɖ{_ 9ŏN9*zo,?1n\-X:oR|` RDkQL} k26 8;o$w WeNS9rqg>'2$?x $0tg8Π}."ؖȥ_*F([[<wj7gʞR鲴c7AYĽ =a;w/E* "F*_R 3$3zmYrZ(d:j۱1# &w0oq6n7*3}5q%> rܟ/7k EfGNZ0B2Tؙӫ8o4:Vr(gA$\Mp+lsNz6i-.LT}y;ϡ0z;{= ·Xoo/9-.GI- 07r-R} 1cbV״n ;VL\P;!o+z[q!WZm b-$}tT r؊jbna5IIzyFۺDj(,xs=qlU_- |Bkw]e徑 ~.f&%嚰͟F[SxNkz1‹M i fM2P7QfSI#nbDu*ЭӜ,ocט@pSF̧̋G. B,7~O2l_ 2U i5>X*\;l7okpKg)qg-;~ˌWb){$*X j~{+=hRMܛ:h *~gPQt`+8^Wa FJ/!1̖w̆th|U?3XVw-k]K¸oṆ|Ά-mb1,-L[%X||HgFܨ_ܜ A8j_Ya= E{3V(}QF-AXӮRT6y9<^IQ9/ *̞RhgY)*a GPq=[iH1ف`e Ҽΰ~CJky=!PՉfO'ЯqpKeNA.%ID÷Z b ߜfͼZXפiEÂ((B_XS)/4 1hҔT6{<|Sƛ]v} I,I6I^!3W{N=.gJbV~^+@ڶ,_8hb:UqMW490g]_ ~ny `,npTE3L 7lsb$Λǖ7Ogv|,jͫ0VXKILfNN2 asMUdfdcQ-d]#P|@aj*XX98W/ʴҠ!,oEXܻ|.=sAhٗv}w]G*{ځe]4*J\0 )MzN7Q7|~6؏l_e>^F~kbu u Xg-"=CYmNopYm;֡eUW/)I ֭1u UjLT>ʉm &]Esa1=CѲgb.Y~~Lϐf6E gG zl ͞y_/Z{uD@6;_ gDߌi][8߾J8dftݜ<07/<ᛑo ?m,_mPLL 2[j^Pw 錃͆a`'$3#'ԴfO*Fܜ`q߃3'D ko=wo)~kJir|]bU]{)nn~\=7[GmX;/YJw{ 8IWz)v=2dc1Uh2]H !QgukBpx;kˋ_ǙFҴΈd7c_W+ǁoĆ4q$0  bt&K'%,޸)<.KLL͢h3(:l' v1l^* `7vm[imN]^!meww8 ;rpaYTi$)њTSVZFZºbZ97e@}|G}X̵E\Z[3}CZ,K2|d`KD~ziK\t &l,^.P"n^[<1X2V4az a(Sa/߇>Ky-6.U+5bjTC{x}n\K"f^ #z-.rpK8zxb 7|In];jXE_X>{Q/J_u5 x4;z޶I䬴SV360NyO8lǖ=xWxa#wvbۍ.2#Xl6"b9EH'z"Mk(͝L2ɷ57zA_&"*4G50gh1ER 4sRfp/oK}\VCa3j{#d/;?&VJ(t^Au0cl"kDBiÌۯ!s&m,Ue$ X_N w:1P)Fa-ZdK/'V D* 7Pa$Yt=6 KdRkƽ?{5 \d&ǽ0j|֘ov4SG37~Rj`l :'P MN?߇? ;0Ჲ$+\swk;*yWn} ev=Kp;-Q|Ï%ߑA%gx͔ק!)>5E~Xíro!ܘVs*pڌ s^In=V7e,2a,I1X'\a/gO/Pe3Kqoȹ@6(+5oƧ~eX]zfWgaU m}8~GרyAJ5rRç+>@RZb2bZ'6(am&S~Bohr&v}PEﵨQ oT{"%6)W{Zk%ⶉP\ _ͿS gͻ36aBC ƷQ|Ƙ]2 cBG-U ɮ,?_yo+5x Jd(<.NOR΋xܞqa->?9gR2 z];ɦCZ4J4NEtZcX%[!J79HMkvIV'X> X)zӝ|`ӰbFNsӫkm?(sf8;'7᪝"ka"Q)fӡc e|[DwՖFTKww-5(t\; pѶ`tgw9h=~i.r3tc -YkJuh_ѡu?yJd&EbN6ge3BHl!^9f>`3>&۟l6>/1FlqeM?,w,?{'sػjdBNXl0f78ɈXI$M$^fkK wX^["im!]$nGj [xclXsrF+)7#k ŏ7гc]g6,vu^dv[@R3\ltjH?!I>0Ȇt5Wc䏶7~ ##K80IhnJ`EƆ$7$QCiPhп 04e3z[)+"ےd ST ⸙Zܒ21TLD81ySĮZrb< tkX*۞UT~̫`dt3Ds$ݴL;I%Q%?ئT: #=E36v4^Sk.GO>D~W&0p}e+3fM䆅X9Q[Li MkL#jq\7+ws49?W`ϝ>N35)nt#}>BƠ[V>EP r@Hk&l#pDm/=MW!> }!yI̗cxU|Ne3 0۲d: TV)w Or㢷`15iho=, &O!8~#!Dpf6Ll=y|x,xsAqbirbv?dcM0K@O3RJT[@Aօē#yJ6L˧$4VT OI1g`ϩ,‚m"݌'PN}*1+pȒZ^%ɞc9' K-,dYw̏idW r<åuh-l:7p6N9p@'էxTX(Zz$ RƓ7ZAAgM 8sM*lՑr0SUF@2[9#sRS&ylHkbqq2UhukT&8=DŽP J [r`jr5ɫך/GfB?қ[Jw+*HŚ5>_"\]]K_e_ o=xR[^]/fC浉}=qC~53eS3,Y4|3B$u;w.Nk]޿7q.LE t`3 uxP˭~Gʩ5QB KHb y61&ndVڮ0aKlv~$5kΞ;! Eha0DdSaÎ=3v1҆~ZQcf-9:oGHbHdҀ+=v`RdresҳF偧2O .NG|&8j/V ZL7%[[ssٕm(cu FF9`1Xlny¦͢fIӓm+ '@LH ! xېzH8#ӭMCȟ-k` 'X &U𓸢 1ֽ0 ^0Tk2(]C0&`p{8ےrC$]c"8?{b){8sU&)IDATf{a?)|<l Vp&ѬH};.ۈVĸdǒE8CÛV L!r/8htI0݂u,$c06Cĸ1#b/,[9^e@TsFo^‘\&tZl3r[l"\ S;'[o{cb4UD0 jD:lgcBA^_'9X[sMVuTGO,O|ˁ sc~Il:d6w,w]E'Z6+ϦHkWxkJʗ tMfܨ|d8!SuAtqS'0)eBYљϩ1lV'.z32$je7rQ&J>bL+;%5"Y2VUŀ_%`8̘縉,6=9bgd.0y5CS©~F6V.DL}fg-&[c y֬ÆzD}r,*nm"R0PofOk;dtHrVѭjXsstlGv+Ռ#A&r!!2ô˨$XטZg/; 4FCqtiʑp6 <=OsͩLg~g=|5A֊> .]e,p1<}LX,XM7e+óXLTw5"WpN6:@ÆWO8÷ MygFj0lxI&p+#-c[3ੜa4L笳0)VEҌl'llЌv HLb%-1vK  YZr>`%

?2?!tRUD{Iww=G"U ll W2ru'̜'O1!HLX8, mF" \'a3d9t'O-\Dևܰxnx̓*/ U:n2g)_]o㜨ڑk,~F;r5UhTi't [GB&XON*ԪT' bGN&HH&`KXsIN=GIZ^paocE#s!^{q#b#' #=U]t&d&Cّ%f H*6Um6l{zDڞnLimq mb."!cf~Wٹ9~[VBW &1^(tRtᝌW.WXֲm*lyxᤩg?kȴL# ?o58be3`@fcT.`MAɁTQ .cG2{lzlqy$FbT'Џ?*.J j&Y~&kٶr99M<A8uK+6eu, md9lk1I w7 dRILgf? ^33`kY8n/,u!s/NGȿy?z?ϾnxzM+X A* 70@iiYcv8qx, .r"sECѾQǤ@3I&P-9j{L[&\G [&h#K], Z$;tM3an ãe+FpȓQO đSC*1,B qXEO2}67&3s;;/ La"|ye|uH:`͝K[n69$GI#&E6Yd' NC@5~Tխ,H @vS׹$>" . {o7wdx}iYEaqZPL,I=#[bIvƍ$L E}N0y f @9 :W^&Ķ ëښ"ڐ͊k]S u[JUNK4NQQis,Y5. (НNi`9:n+Gpa&V ;p3Hg(31P8P Ɖ}ٮ\O2|wzڹraS7=a_WOeEBH* p0YYz&MIGD h($FcBtl+2Lv~9Iшl1RS5+"kPJ %v-c89LHUG&Ct&$C!}Hq6*&W Gk4a84ć*2"wCÍe<޽a@Us3%͕b~(WܜfΞ\/HI<_Bx 72 -'c,em'R={L,[`"iATD) y #0"KchAesBLBrחI>Y`ք܂oH):RۑMG46>H9Pleh+kёx1r;T2yy^]aoeaIU8`l3kwxetY7^}+YfA8Jp ,lLDd>-3>HnKвƚ(%6{4{lrd[ +79ґҠUW4Dm(DCH ).2of8 6܋qye6Y֭XeNkd D8,spVŋ@ʣHNpL S)p=-C4vp2:\( ӞyčTX_hJu6 7JZ dHxm]7H34ԷDZb |UDgt?r3_ᆴ|ۆ k&uvְ]∇mWqp.GVWgމ^=yn 8D Zs?G5 d1&|&ݖV"Nše;~H)y)_ , ;>߷?11-e6-}Pq[R,²K!^RD*Di^"1'*3됨#a⌉t*W_U~M<ŞUop~--yv-G6Ifd0<` t:|)rzz~K!?T~ 37 v-C K8 fjKa-ŖeZZ7$h <4k #͐ \˜h"WBN0-"$Ƨ)[׮gjq<p%^l 6rwY+aq`DN[?&Azޖ+`? x.  aJg; pTV9KY`xIº3'}ktdS܎Lm91z8[)nKZVqT ςק𨽅' vc,'eNW6OʅسHrIENDB`robocode/robocode/resources/images/explosion/explosion2-35.png0000644000175000017500000002435310205417702024001 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%/Eȃ IDATxi\gv{Ş3I&ERJ䚲LոZf0FSƼh`0 }r1h7Dnm`H.eJDqI2-<˼7!w `sa9c9c9c9c9c9c9c9c9c9c=ij{~uNϭЧ"}Ϳs B[~V$[u͋۞KMOws"kxm7oEB] {A[gG1櫊ښTiXsHo$R F9Eϛ?ߚX{͒g7Zϭ/x%la$ Q JJBkP/* (Ԙp'*Qʷ&߅+8A˞ tO+# $ͦOlNϟ 0`0H8qk(F1B BBB) #>pɆ u ;^ALkviTvpfsr!_tw$fdk(Y8f5/%\}zo\|dtQÀd\5L |:h@#ҴFxoE1Y{@pe{2,$x"= nyE#ϝL ^pNIC@j&s1QС wsrV\Y4NIR[:=_'u⬉Ȱ#TwMP~ lq1:cD@$Ϣg+5#ǒ4H I/h+ơ#AXAn1/eQS dvѻ^1.R u4!U$WUzوO1<E!Q3&u⬃ыr o;"AFj΅+ڧ>} n+A;_FG=dD׎@#s#8?VPKA3X6 p@j!7bx8Y}9/PbX :tj ^Y[Oz/SȟC+(C\aO4\~}{7էxdkDq!Nh ~Hj/ZK|4<-B=$Hem9_+t 35FEDwy& XKp:gI4'3ȉ97e+_<}6p@Ҩ9ԁ/J!: k;@lp/6х"AM N5([>!%pj|o:ݬ$&\RX4,%jj `4K;{>耢x=k dnu1_<xvq/ K}jNk4x95۰Bxb *_|~u պ(ZGv[C$g—ڐ,pYD%FZ!i~_A TXI0Q>ͽ/ R߻#1A1bXnCO@.`ƣY/h )[Q <Zu8U$a@ǰ~yIWCSԁai6a%5o:]B Q|SKl"o\ϿPx\]4 66rFB쏡ѯ6R=ЮZViy"¨"~)g3W}[C{\%`zOP-a">DAKHu=3f;1# ;YlkN{:X%W|RJ_[ybtO]\,,"L%pJMTiyo3{`Lv{uIXlb ?0I!y$ q'O3ߋkhLBB&I ¯ᣯl ^\.Wk˕`:ș1Q>yzdZD r .: ژASvrvۛg\C;/j[!w r.jI7A]Wh/3v0v]L٤\^%a|?ɯqrQ%"2k9D ~XrCc_ w9䵯Ջ?zD}l58D[̓1AC~ K(7yq  |CK*LصN֨zae *(lTi#~;LZRPU[wړ\ WXq"8+D#YbSwP{5YmLCtת1-U{&(_z-.V|,p`BCN[zU%o^"?s 2;B֑/6P' )Z kktj[UrW.A$R# LiӞaKSƜS}T ٵqHp=h1G 9AgK [.uՙ98ٟk)z|$Q r%8wq@: +c5s41hك/Կ6*Ӡ)ӿ k' ެ;VX+("Dِ<,8nxH4 Iw% )袨-JjiM.d­5+mMf?|R  n UucI%M=/i"B([(airԑX}lpLى5"Z¨(VbNZxtCy8V8:> /j4s8'+{gU{H{`I1w e n(@s X %D"L\@S,B Vf1mXi~NUN3{Z\X僣L7YGGhɁѰ悅O,9Dл~CX4󀡭>lcU &2pgU|͘`I41-TLO ʚ7PA8De*gny92>GSh tܷ]!@櫭ԇN@3?5 ӔuY6K2gmͭL! 5QHFO OXF#J!yBx[CZ6a-WU#gOUBEcU$7L=8t$* C=BGO_> .%"( p&Ȫh@ kU+JNX[ B_($*Rcrt6s@9+J*hk,c(2`"BP̱sX߇AM-v)S Jo!ٲ P;A[O@z)x#x" "jSwL7X|[^WIpjLs;p£xy,( *nXR.2s:VjNLxґd&NQ6 JwgXUʒNJtO^ =QV9qYvHi RO- UfU-VTj fQSXbca1 -܁}ʓ "\A3<#c{Z\Z2VoO`?pz<);$8JO@P!Ч#t>12%8=9>F(O",.ERQbD.2#ӄIz*::ҢMJ{㞁)w7ƃ)m฀">Z Ęv16vye\,7`YԐVnCi* \MXݪ꓈ڌ ,&y <;lF}ш3q 7ێp8FHCd3lMO8LiI;<ņڟ\W]:<.Y(_z!?ĊM >p M3/?c ^#0$#k̖iRjtVG<ɽJePj3dCK5Di<=?skm8)aaR_b|U_=$B1A 1)Aqی2R\-਍{z.9:Y;`ZxR`lA ]t<ݥgC\/5o=R}Eq MŸ*Y,AaR'GOO[ǚvTpLGPl_}{C~#ƬCƬoOgrwL)g5ʻW3=d2at:0bZ̀,OIԐQjOsL|xZQnr2V&l[wn[s豸!ܺnfiDjȰ7"Sd#bl2+OW9ͤODg@G#,.KCӶ~qxÏ4P\{7 W{9B(YAdNХ{02YeNE}\tR y\ؔ" 8`YxWwxox_cm8Xw{I `Z0jP4Ъp.|E<xPpEDhB,/׹rj:T% fFN:%Q[ .?OB8a%Qz NFPNȔʼn {XVil_9!@'ehE_'ߠD(byY[p y|7-4zQIH;'~̶5hʧNߤ:y=3YA]'ŭPSp*?ϾK?qx,ah&%hc&J vSV\ F|gptMNeII^_gLոzϴ2U=;b~MVJw߃Y1I? FCz㜇Gkó6( 8tP#OXB3HyOaUNZAU@Mۮ݌%3?S =C*|=t飹[}^ZWVpttƪy4]߇a*>1A>p}F6er\p3V[//)T!eRJǯ2yV?n:8'gfF0q3&Zr4IdXa_-T!GGվqMbnnYE|SnFp0=l! tO Usy\tsDk"F% lq<*} gʪ˗ΘgQ3Yj8Jp{n]x8^Zԭ4zNҟ$l0zY{0.Eʻx#` w()a=瓇=p<7#sk|QGs)XY)*A : #8׭ށptЭH>ېpg߳ C rp<RPBWZr7@AMA8ѣC\d9ݳ%ǘi8j'A)`;CSYPB.1(ZPW{ʲk@ے*-`6g[`ɐ?J96u lT~̾ˮ$W³]DSd$Y* ɝgk!9 0vQHpħO@2NOu N[\up>xXlz‘c 0'DlIDATK%6Ƌl9#ǸrLHD]q޸l-A=آw>,]~V }2}>}|<CMFByF`?;IEhZ<Øb\E|c?`䞰,4 N Ow2@T)Fj-\9_ ZD 9x,JtfXbw5Ev/_;HB?~o-o8C1~£FU)GByWm}b6quC :ƦPcbYPG_˳duF)1Tx k=76O;2]DI0vS-x)PBTq^[saPX<c6av-^]DC7&P,BA#wR/br1" CD8]\"˛ա!Bl!+[ CX2)CO8+r*L kOe^^`# B8(Q#@aFF2cl)F Gf#c .VL!\cF>XAڗHG䓏q5?_ZGo$(zQD[$䪅`>E ?]s@g cӚpv tv2 kr9v.맼N#j IˆXƺUA:JX!a )9 -@- !O7~Cb$ }P %}-Fg_{:5oYqeǟo{0ܺok,תʓhDZyN+{~xQ}YDhv%+di󣶣]-/.͘_ g?S"L5o|dz`tW<ׁt9(Iϝ۷&;s1s1s1s1s1s1s1s1s1s;?IENDB`robocode/robocode/resources/images/explosion/explosion2-39.png0000644000175000017500000003104510205417702024001 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%3Q IDATxYeuÙ7ʬ"(6&-u 7ddmz1FLCdER"H֐7;aO~8f*lJ)b{NNNNNNNNNNNNNNNNA0a<{bCp3u`m5?[@= ;}#ݱ`݆ݬf_ p 3R_1h] ߑ\J2E{{pW3>V=[?f WUG]`M@)\"Ʌb4 Dy`RX$-8~0o\G ! x䝾3)ŇVD. R "P@;Вu 8Ґ,? VU<~)Nc^+ijxnE(fFdӘV1 AvFIB&%Ai"F@ xC% ]M()y`*Tc? >`~.] 3~VཫKnlK./z>_\ 4Y)b\?i"maӘj^ rJMm1VӒ׫)J;__|x9Z`J'q3J7hf=˂W$=(83 ޶{@k w. BBN hBH cJM"Ғhcѐ[S .U;/Ǝd8=y)C8?GܸYN%Өہ< K&-}1*.KHuA_ۨ!qJHA.*pm-dHB g BX);d>dPN[m )`N`TͰ$y`V%/_6֤"A0%&*3w* B@pdϭKn<$/&s˂#BHD :tQ~zxA6J&A ^L@῅?‹m92,Ʉlv \kJB #6MɀyptcixV'JUݺ ]"S|2$DT|6\fŝAd51)AH~7-[ֳ/"MFW2H"V) "t@,t4-M)^[3X; ,-^Ċ!D>]|oEvq^pV2Hgn(q@Zl܏ *K97̐#ϨDes";+x X>+(SVT]QO#tA Qtd?SĕF)*)e:";+HQH.Èip9d,)@*OvH2,  ےx (Dd6Md=kH;AF"YQ"T>b g~Ɨʞ*/GtGDwY&^ / bQ7ڡY"*QN>C.9HG!T$J9݅WW pg SS ,*hk:(b /{QG9iP$*@rAJD:9 d^R?=Ğd%5hˠw',FM*EG2\ĵ>o^.qgE#1D6}<HK=.`TWh Y2Z,ŐJXH`P=>Z50l6 yaXcAhRd@ 8ׅ;d0։J{Q5%y\qzP1~?W+74KM!Yzlϱ96'$|/²7`~"[XOюk $Zi,(!@`xBA3 &Ki`\-RHp z "#uy!6O2U@>\rAІӮQ;ց_$R\7uƂ7$B: ~ e~{& 贠OP" ҬAWB;T Gvx ADJW_xLlFAa5ז *!Tf v%Bt́yXveB x Q`A[ͣ _PMuU/c6+cYZ p5πSP1!<,4sS؎ag 9LKxSxuǢցsuak=_B>-z۷7.l Se~@eEXNbh2,a PX6n+ Ћ݅x 8\=+ S`a܀%k,5_k]mYljHBVkP+i^W+ 2bR/ةsX"I?JS(_Uq"' [LWY հU~YVm7s8S31͂gƍtFCE#pq׸ hEگ} oamal#4ߗSH:`GmںK2w]?[F ř=HI"O+LAU0p@j8`N: _h?~Q6 ˍ"0Wj y\s@L**K\3󼱮z_]t*ׯ:vT1X۔B!2"`r{"F5ܩ iù?Hk ~ޣIØPK>zIh^[61۴~BeajkLD7b -oe1.&i:Jr\~?w?0OHwf̿$kSv.YhS!Y dx«`#R̩Fu)1*=|_V2 緛 ZXY;qWW7!qb-Y-_Ŋ ^qx;GCp)E!ט 誅踋w*2uw]=g[%Tqί~n^n^fN՗* !k2sw@<1(_! x22~Hr-ϝU]? ޹x{M Gu2eBrzHupZQBZgBzHVvi1~ PعYhBU-s#ƻ]R~~DXK_+(ApQ`q/Z82a=AX*Q̅%X`1ՅRc'sfp|H0t6BW_o޹ľ4}}R]Nϲbv&9* ۆi>JM .Nǁv ,X$ޥ]G]B[TPhq v+80`yi|Hڤ cٽf=_:H+8UVn/%qo .PG#W T+Û@BlX&ERDSW|}q_c(++7%6+%ł" |u B E ,&Ђ,I&BQy u\hkTmz M67 K۴F[ }!X)SR̈́IH_\\@rJSDmĭ+űUiZ;ћ46jUEr ǍfO-MjӶؤ^*\֏'U &%c]1[:rպ~xRZ@>q*R&)Db^J质[hCSWGdNK ϶_uQ.qゕncB-贖5|2x702tqJ$b'( H#%1o!].J=2Ά94_ƥ8w57dᖎ!J#*k~ur/.¯+K}pqjw s\|w)cd{o}MrzS2%"L|]TŇ.!AIKMi^SnT~}Y!JC`#iwS7@B Շ+m$޻*x$Wسh& j!Dmd6ܬ@C|Vr5m`%9n7Ϥgxe 70b{X%.[$b#W3I>[NgofeΎd鼂XF*6"d R*=bYTϲ|+ĜYH+b>]q74l M8[y`zxXI\"aGO,y& ~%SI+SZĔ>CIc}:d ,6^ni qs4D1RI\ CÁULauNQ\T8X n3qi`lKDPXeJ"bcLxbD|T7gpxvgFOF lg0ud(%%2A:~bdp/9(:(*"(hRoxx~~.6~,e:s#)ziL];0&MWRib v턓 Db\:Ʃ~$R 2LQ$Q˸O$&/hg%DVVWw._yם^B01G#&Uj!ńQ4AhHE+f6s03ggª0V"YN0i4jX1u T;W ,RxepD* "ph'9X |=(#OCᐪ„)QDu7o;V<'圣W6 9/U/i5'O)Zs_es+=7 Y=8߀8!8_a+:3$<>t)a:Q !A ANLPZI`%mC3]7L,\p<.e P1 spf FcT<‹*H\Id Ypzž!,7 A8p%hɺeP/6œ#W5@5iߵ4舓>{ *|6`{fudj  #bk-|~q xj=1SϾop )J(/*e1&R]9%ؿp 5F PX(H 0D}9 )FSCGZ^_zzɸ| ߟ}XZ&%?1?SXs>bq~jiT˹E8A{X(+mIZ ۅ!8@T/%ZYoBHd'j.] > MǓ=+tY`)ՁpPx^3[yZzʘ&" uߘMћZt](}S֌zNAm2pOp&_79<8@@ݫzsrOxDasSF%<QbnTqXxHyˍI[ՆN1St2DŽ'`&%V P۞kIu =L $۞{Q`5]Or<ĩM&% p3c~5q%k6R VZiBMz6;LNy(KbW[^䞔 E G`Tz :jX3oVE3#> j7ZpHYzD-Pamz;H#h™α1r\tu4mdvPA'[^R46@Un2{m& L!EX"6a'qяy` /~'_|#8.]M(!,/cFPE*LjOeM,e 8&"p8?ؘ6MTPr%xa X x*R'gsgZ?L~ܫAwE%[+Ʃ2>\di E#/5;v8pXqɬga:ɤ}K60,nM \rrETQ̊" l %V b(XlvtN}@l6Ӎ sL*0a/rtի 7KȧȡaUrVWwʊYs Jp)TY p߬ Ɗc#0a 1v1$$V#yySÎ">o} ^ċ98Q^RLb! 86tg QcgpwOY9-t=~g/ѺM ]їˆpH!tE \eŗC[}8y2rZN&@A@᳢90>Gʹ8,}XAE,oQedʅL~G>pt~|J _.x3 ܇Wz2ʢgTzҶPzSM>=8J a +hmۘE%E Qb鍋`˰&2pw"zmD|2^Z7 a5?\3q LIDATPS,ڮ]*ɶi覣7h]#֕}C30u@n%amHM)5 J\ רYil+aB!On5U\,}E7 Ē蓅?>_u͠Mثk;{ ̇tm"^U*Ņ~E2՜s{&=IVqP#0}vu.FzF9<}&2+ Hfͤ1a+9s`s)so8+`Y72&=*s+I[E+M{GC k+),6;D&R^^a )`q h[qK| px@ ˧Onô۴Ό7<j8J7߅uMd^_%VyQ-$C}shFr #$bEƌȰȺEJA9k: mRT;LIB9Uk9&w7s}ӼMh9OsUsIY{sSokmTlní=r-[I& vq$'Z \^z\ŪhN~rүBG0!R [W2K2ct2'1 >GVeO GߺG7WyhJKVr)^ UOPhbZ3B7*zư a 4mNcyF#{ Ĺjaf*[Գj%arnff ><!>O-"q6AB=rxqq;X >xI1 ":Y-ZĺMHVKB'j p:LZ n4s!=Tl:'e3)^阩CpFX8k7LU"=lC4lC O0ZlO6'ḇLH3 AQ7.>q#I%>Ӥ*_sKmNw`PIWuVZwcg6&vNg5sܸ{cӕnsЃ/JFsNkm[{&U/C(p>FU{B//(=g|CDQdgEV`90NWt^DÙ<ؖ0xq|m8ݯݻПe;bu%M p0G52UkwaT}zTn#x[r0L^ȿ#f}G.G#8ѡF nݢnF*96$dqP3̀_B3M2)p {"~HTvJ#{щ2xqӝjG7?هU (z :-Fn\L7t 6ݥwN*ZEחdsbx0$)xaѡ@L CHJ5եwD`Vd6&fAuhjJy;9!NQ4n}v#u;-ﰖVeC8GY}V?q0 >غvP>O#"Qj@HUHiFDy kϣx:}O++GHhrw<q-j}( Xe^TKwKת9/k-`gTL L`bJAW Cׂ`m0Gv}TF}b#R";]^I͂ю}j6F?A؀!DaHFDzmq C#~KK/p "|s <$dLIǍ-?`CVm^T'8A pc&adࠪ+Z1"'xKV g3v%d6 \|hnjMA' qMD-8ۂS'v&r0(֑ERtb?L"+~(d@%w[BGonL~"6` C<"(Hh]b!H$٧drc^ Ua,?ƊѲ7E˨)y aV*c.k]CA1JŘ& "q*O@!"e"ԇm}l2j@jW U^B0!R)P&۲t+ĥ%r!"6*,P!RYEW]"JDh5}LS.VہCU*c<޽ o_ oyt%z=鄜%_T@BJ%c@ @0 -K7 T9Bj#SA$C(w )AZĘPS|Jpʣ[jd6fjZD*A T.A>BpD1E8_#*5$Ӓ,m~&?*9u,xMK߄ǹ=äSSc +V#Gj%Jd"B9J#G␪$ A'aĵgrSD|0A;=AexWXI+S)xJ\5kVi',k"vx,RLbtTkC`#jp0sC-{׎7Ѕˊ h#bRBզ%:G :HǺ p]}ز󨨬wZ)^rw#"ZS/hˊ{ᆢ&YLҔwS vH[X2HRJJecZM0iE{E[eLe#YFZ_'V)]YE-X,=yQ7eϻWzʛb"珮K/8PKHP (1"BE,8C !4B)+JEz &c q`:n,S (vy? \'&Ӟ8FiEC S``IzDף*!ab^I`$Jz>BN%Vc"uĖҲWxyӞ׾?|ڟZ m 6DmFiDh%$.aThu2*DF2 2Ҡ1*7ahaA'J29(K"8Jm*b*8^[%m 8$ɨ.'ZJ=Q)$vIV2Dx)" _{슂7PV5El"Zp'ic-ƽ<ɡ4Xh.D:Sn̨ʈQHuklk<8Ja18RU DIFYPгQiC÷G{5:uqwG[;KNI?IY*cv2"@; Q[ݺlvv)`"䂅Jpa6MtHUÌۼ@ >H~SR~MwKQD"z(&6aP.^Di%D@!QH*Ke,ѤBK#miO TXq]1,5 Pcm+eD4 LrC5x[Rp|yo6 KIǀ?S_ͺ_@+)ȖB;rE* i=(1#KmV:l:\Wy{ ͕K~y++scZܶ:es+.Q3if8k$-v*1gj'u׶5*,=#Y;Ҟgsy#w/b+\֚R\@ͯc۫+gA0[y Hڕͽԋ ہݭ5F=ASE?@x_OwYެ$NU34)ÍQvWq'x` ONNNNNNNNNNNNN~OܤIENDB`robocode/robocode/resources/images/explosion/explosion1-8.png0000644000175000017500000003364210205417702023721 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME$- IDATxۏdWv[k}NDddf]XK_cdr<3g4h(C/#ۏlX^?ٯ<@ŀi`؀ƴ"=j]&ü8Z~؇4I23"*NZ<[ֳl=[ֳl=[ֳl=[ֳl=[ֳl=[ֳl=[ֳl=[ֳl=[ֳYe!BD ׯ|o |w5;D}9|a 6n+3W;_s[^3xw/N7/#/#QƟ)w'A9myn n]ko#8וׁcΡ>8~epum 2ŀz8.oeضd~ͻ[_G.!Y/s [6Ϋp~ /?=B^x\!4Fw O۫?> |EI,-um$YBG,LP$*Eg2|_ϽXw\7&,J§o2su5d#oo:n~}ۍz$=(G;?_Q"p;O^pqq`Cɹ_ڭȁur;H#'V#!v"0Q:IlP<JBcU DeFTN/Bi`ڸ_+`y$pst6y3G6_`p[+G_ῃˁo_O !)Fcp<<GMh@mh2Ȏ$d.xhځ:^nN'*i.Nm046Duqp=ܘp6\C+ǻƶ4Ʒoiؗ@5FNco$sK2!7F J8e &  $W M3Gb^S 㝉/ Lp ؄)8$H0]ؚRCF8˴ TS&"Vqhpbf؜fƹ>޿\>~[;|^GB<_pCQ6;o1Z@H# - '%"I Xp(*.T1=1N3זэ3tPzq$ib%U2åPZ`K+ϴP2†#vh2N%p[;5x>(y;ˑߌ?۟=&;;(4FhJY`g,*QVqꆨP QPOpMm X$UZuAEiTIJ58 *1( o qՂ Yv,3zT&.l_-! |#`ہ|5' #Qm 4Jf M4k(&FBPVquZ5bj4[QOnhC x$1\@ "c Yś`* 5R D 4@DG',kc,8};+Csp-(?ew_-z{X=' `nA9'XDdeDQ4?‰R Jᥡ9*FHk8AXMal b#IG\vHH6tUzHEMB1DT=A!+]G^vA\lN30Hs3Lw -rK-)m$]@.p99=;T6 MC nW*؄ JhBp 0x:z &&e$.-#mDMh"NKMImJAjaR gNp1*c} 2o w| =HeisD/"^$ v#\ ֝@ Н#Dwq"4<^ $F-a==`48#4ӊ+PF[DfGjvQY>*i+~|0B 'l(H8.7p`7t#ՠA0؅~$Az  N00zE"D +Ym#R 4 I"JD|%ps7 4x@$luЌɆF"YV3+z _##&puibn;#ssxϴXxt 6BWp&pLP ,L eZP 6lQ35d".II*47DYF#ݑ:& h# ɆHcU1P7"ߺi2h6k@cې9;?c撍d .lw n0^zXƱG~T4,E-3&LF@Qa Y #a*x[ *U қWH$4(h`1p$@i$D909qx7n*"6pm2ʖ[ʰ#--7[jm xi :Cn !B&@Ơ)BHT4MU"Ehb+Z;*YJ#.;JnJX6hJ}n &|-\<=ţp_I9-Y8Ȝv mGdO]m!> Ŭ@CZdi@G{!3#8xM0<"Q&jI BNꎨԁ(t`>_(F RbS%@("9O/%ԧ ;rA$MuH҄zCp1~qmaaa`H=2si5cY7ΠHF羵O0\lSG:a`" 刧BG^haVqk9LRQWaҨdg2Mi7_^yM1KuDŽD*E8H` {_ d71t8ЍӵZZw `qu ZXr@!'R&Ma=#2hҝcKݓhƤ ,T4ɠ@E@h[zfTr6Ź#FV[0hIxx[.N)>0ڀ1-a w9֣a 7$# ҋBZI@N賂 ="^&WpJ`FS%1@X$ꞠDY ,33q{jL(E(&BcRYFbC3z#lhb^G ?5a!*&$D (k_Ѽ~nk!?qݯtwk uhu}Cxd!6%؆({()Aɤf8HBBS#H<N<E0!Wf\4dX %FnPY>9 qq;]sP XLxwsPV$jpYP]._h7z pZsT,P;#m1pn0&FȂg$7!R) m'4Qc/E#DmT-4B W( "7;% ½&<8:pwpy| n: . 4n@.PBO催N VGX?JЍ~zV R BfIP!@" ?t@0akD6ѢE @U_\ЀK" C<,2a7pX3e+-{k/X_luݞF 4W^Zw.=@R7km@ K j'KU`'XÌrF9RY/=g4Lov wʹX9BGӪ_ABqm`w r=b`DkZT0 N`3p`XaSak o/Nh[Fk\9ߝLl"Dzlա޾ݵY3a\e-Nn8c]å-?"A ܋Q D-ߔ A8 C'H"t,"6REO3 W*50q:RuG-$eD@GR?x/ѫ!}J˰O*ⱐ )yFm&j!B$˽HS~#〙v058RPفL'<*/am#Ku \‡`u*zKf咻w~ǘKiWH -"Dh^nBcG Ԕ$qDJldRv7ʇe~FXo8 xa}ynaF I,7x bpg׏Sf̑  bYh$'6)%AXHs$q@C:CzȔv3&ΈITk%aD$8B}B5 ֋B0 g\RYVv_ ./ơe> mKlװyB,yB=P:ϡ)=}V =ɽs$w̆1}4Ưs;)K|>62٦l:" bEZXD ٵL0u`_KF[pl-Fp }ʙH4! U8ZbG Yg7o@ѫpJ2cEt %Qi̟ԫeQYgZ2K:$ L o4Wn{(%=BJb}>@t"zBI/:r>( }0ID4:/ siPt> gJ*q}9od̅:.0ՉQ>Q̴0ԙ) kyqߥЉ#omC^#$M4;5< NEDn2"!s}7 / ѵGvb}rw4B0;H]D-ȶXB,ۺ:MX%wGk!ԅg6#(ZpǬ[veu@VP7YyJk/H %0ԕV`”sQ k$u>$ФRȵ3l,܄Ll3b'>e98[Yz[ֻ.oan'bpqF!]8g+}^`3R2$Z{Bc)ܐpQm!oÛ篑mLf*O#-D~L0nQOjm8`n!2Xxr2.0k6  4m'Vข ;cnP4KDT!xy ]J5k=Be3uh^>%3)nW1&[ΩC?iaF\i  >a*hubh4 Xa^Pqq7"'*ɯQHij̟gA g T~#+8/dJ|#lb QY%ѐ-RV v_ &0WsJc3%OT"K$ Jfm HM@[u)s|иTnM͇ۿ|[D) !toi<2㼐Ύd z&Ѹp#:uw:CJ>_v+Hjg.%9ltn\Kj|ԳRP+lkD*s`iͩ^1N~s-gN8'`&щ!f̴s /uw/*18j0&)i@53I\nҾOmQ{;j'xgEB#Ofxbp9|Xt$ɇGܟ#ҹ#ʂ1xXCB%x%(OPNLWu¶-ccqo ~z O+{pC9!w - U[@g + PO"i#Tm}éH<>_Lͦ0+PO `1plRH-gXء4V8 TyC^g;0xD&LZ剴f&y2o{*O[SW`Qg?+RU ʖA9#sqEMn3[$q ODd >,p,Lk(T'zQQ*;s5b]XA044o$:YIz kbx2h3ok5t4p#IDAT.oF+ >*ꉲL R/4*I; 3~k8nrnYxNol*B .5H.'*FbPsMT7g9)T46BoZ"X1]h7W W 7uf,5}8?w>70ysϜya~^}>pLLkZ,E{í}YaԁJuX$;z/©Ё!!z-{'WG |?  f.Vjh0 ~ pp 3ON|fIm[4E">_8 ;7X`acLr_q%S>='`+ӿi)aV;h첯s\$zIz:'k||G螨/֘숆 !ƑD"a.hK79]!L+ο_l#ցi76$îq LՅغE+çQ|Z3oJ^$t{c܄NS[+̭W m}??u&S-T}Lr$BGTہ-H[uRHCsRѼ`mν?i=M|Z+o_7jr K<#yF7%Flc=;t?ѩl֬|tH=uTOƓKȱa]vYHΨ:NC⌙4OiFcUe ˠ~ pWfHD/V9B扲vk/lWAFS/]'zu/TͶ0F&ٮ cfQCD4Z ]5DH bVqaЙJ LH'τJy G~~(+1NXYPeC By|j?؞Eػl1BxYEu wj'腥ցxZ06KڝT~CjeTpOm^_coyng\f @ 0!0>Tz+=+oxlpuXXDKݣyM!W*W3]݆c >Z]Ѕ%` ;.K4T*BfN0t?=)o_ ^A?V6|\` TbEBAҁm Ԑunp軙uD8iÒP& Q~4:YVQYs>c/)۰ސ"`qՉ:b5YWura VJl44ϙ&b!}8*<6$ed@[H%c1ڌꆪ-r,t\YF ƺvrvӹ{z`.Ph'Ug=ܳzhF6t6u DO0>Jf16c6:|vέ رaȐ1l{\OPvD}|yϣ:s.~:RWkg \t\Lڮ24f},צQdܼ RL"Sc ⊆Hkf#M.f[ɴb4H*4vƽ|q|n_~[#%¬LF6CjF⩋0HL$BD)<1Ů8P<.ZHVa7RwV?nқJCC( Q$Ãb" T7 &T++]bk >|~G+㹐q'@0lQKh1P0,w&'"Ka^;Npzp¶ S}CF0]gWКW t ykB3[f! QƋ7o~91)sP|v>ާjDaq%P?PYрB# 9,HynUV6J@֏i-kXDCh'`> J"̈͠PG&3AD<)/Oo; \rb!*2 64T8 J9BbC LI5b1jfǀčl9*UzeU '#i+0W~\&脰6mfkvĵM2iy!Qzg73~sx|v}? 㹒w}s:WcT$?qg|ȀsP)Bj:h@@i[J^mݰyU|wm%_pZq=d? ZJ0_~@p[} Ga!L>yi*!TW~nO0D^{E*J84`ycDR)B'3ug鞙sbi!"Eʡ*&p BGv * HL"H{L'6`}[N9& BQ3jq`Tnjjn6Lys0oȦZ'nJqCPяG0$z0Ie0P>"#f3{+,?eyLF;3:72;l`> nIwM_^5UǿSϤ̑bpce.>3)☫bK3Z=ArFMePS%JVL)`Emvƴ!j7ۼ-]9df v$+k2U@"b > 't6S|rIꙻS3B^3+klMOGO>q~H=W3@~|P+Fᗷ Eb۽^x*$B6E g+` dX” ٰmgB@@t'\YPsX@rluLI$\jjAN/2a#L|U:qbbLߜeoք__z $B8imFG.RU+a2su2 8vNhi=-Kü4Am_Y@:!X&$n#Fʴ"!>RLؗ`(PIVupoSJ:){#z'/Wa OWIӵ Nl^d@p: NZ IB0:MS Vs`K=.i+'0CdP3P(\ ) dcO.{78\M: IF0r԰M,dEYYvF4DNLK}W_=O :R%Tz8{h-cxq3nh[#{V=45,QAXh,t,|)1j`QJ-V5-ehP V\IH! l?q#Rث6Ž 7GGbD#Zsaٻ8961kFl)^֛;F ,&4pX̕44 6́:f 9OCtA; i 3BɓDq)~4vvB ]&F2wbrA>G;IGSऩNZF,Ћc櫰3!;!gWc y!/(^L^MfPew_@:zdh1a(J/>f72 B"H6}qBt(jx',eD iw+s8OS^6@/?h]!wX ёx?Ԉ. p'ό/ݹqxKc~{xxEtOqk.pR*`ϡ}~ xװ :sĩ2M٩1 ;fb_#9orwp,OEg%#J&W;47e\*O*H&9)|\`nSs(ޣl$V[z^| 3aq<m`QBRL <DG:݂>:A¿ٸs'h09Gh8:|#IW0µeQ\;+jW .?RϥSmvCѮ3;gj!WQ4AݽD:,sTK/Ϋ-Wwx3KBΕ*aWGF^.;Ûm?0|O #Wk;ʣUյ*?n[7}6l/#~<~w J'd6ky?|ݳK^swmceb-b-b-b-b-b-b-b-b-b-xYoDO%IENDB`robocode/robocode/resources/images/explosion/explosion2-15.png0000644000175000017500000000612710205417702023776 0ustar lambylambyPNG  IHDR>abKGD pHYs  tIME%7] IDATxo]}y7ߒ(RUYF-E6Q hj&nA]5E#i uS;X&(E>=..cH*Z9;9B!B!B!B!B!B!B!B!B!B!B!2ܨzq{pحqJqlVޯ/9ኅ C-JƩ3ص`A15`Z39stY5GCwcYa*u69V,oKwJ.P-MWLHGm%UQ v=BK @v)SSyq]qERWd<)6N`IZcxe;GѼM?t;J8T(ZV+otR=%]m֚PJr;C$z/;J ?C ,ѲIj頳*[7`'2Vg->k5l czxtw[aJ1}N<;IJч$~fb=G%GI2rUg3|O@p8U5@g};V@)ނ!*^@dRLZ$ C-q6bw/ƪߠNY |a2#*D"ejJC 3)5JxZ&g]:zwO b K鄃`NUaL[?`%oЎa9a|(Yi{+epc37 LDYFTx.:@{H$ ݗ)ߤ? /P, Zh @M8.lu*A"^?)DΟK$1\٢\f^&PCa`}xA@k;#G!-f^m`Ow,SzAOt/Qk].y0L#7݁Q`:PZu`s; WWnomP%¿o#Z[XM^*Q/85̑A pd%Zπ[<u x!l~nU?Y~0뛠>B?[h.A72N%.ywh@g4697+SSUC639'N֔fe/?"cQƞޫ:z!B!B!B!B!B!B!B!B!B!B!B3|IENDB`robocode/robocode/resources/images/ground/0000755000175000017500000000000011061320762020213 5ustar lambylambyrobocode/robocode/resources/images/ground/blue_metal/0000755000175000017500000000000011061320762022324 5ustar lambylambyrobocode/robocode/resources/images/ground/blue_metal/blue_metal_3.png0000644000175000017500000000614510440666242025401 0ustar lambylambyPNG  IHDR@@% bKGD pHYs  tIME #tEXtCommentCreated with The GIMPd%n IDATxZٖ\ 3ڥX^oWq;iY.Qy˻t~t P(ȿw.;'~v5>>:%-ܥ_x|}Y\lu٣'N {w?@~><^'77ׯϗNCف^ܻZ? )GOMwӋ_۟CTtsYzœϷR&a(1{Uw*7ן>~W k/ז?>~矮.XW%w%7KW~J)qif̍9򢜟=zՇ I he|=`y0KcK]*ZD->}*mhl"L2%m вDH oսf'IV(lȚ3FKQw9| LD4 ggq?*H^"wNd:pu<^fsr5`=12Ir̒Y23= yWצּI" }{m,r~#֑yp #G7qسjr+{GP+}Cr$'_;liXME'%[.w20CY7Jj揥v?rVHb40-V\zjj4ii(z@iQmy|y6L*eU5v|f r-r)ҜhP־/ \f{)^YRJ96}a&4M kpsYJ9~{2 ɷUX3k 6O{urT2@{8 c4{T|.{}(TiEA11=g2YpwT޹jK)9f)!vcRj} AFgJlx%E-l3@VpHD20O/s}kZM <h$Pk}{Q1\bc(Zww/rgs;4 pg)SffHsKVǒ()xANB@D9 Kf)C*N*KJx1iEe*fI}e\JDE|8YP{&v>^3.EtJ@Kܝ ",0FFixHa-s{5C 5RVYyն=jf@zV>ߊҮ;(TTՑF!;^f$*%p{<.^+e3sފDMm|N 1HyqþdXeT%V(,nV*W""Yۅ?H.L ]Z06.\yW}0x$dcor߫DJ)3HhBDʤu u ZNֳ`/]"=RG;;|$fMRL>h챙7 W.4^1+4Kd]j"ia}Mf$M]=v5@Z^@k1j@r+s*A{d`: i2Wt8aВ3Ls K"/eȡlueV(:GȻ\ qq)դ3sWPb/ETc4aWipH+s{k:^5laTCXac!/RchJ(H,I5"2o{_? x>"wWLZܚSDǧ:BU)X> fz\!e]"k1 + - {b.j Wvz̶"c9@2qX ہoӏ\V9m놵RFbWDiC7#3ڮ[͟?~9=z,o.߿Djs``z*EH`uִAm,?zg/_N./~W%_JޜnZzCf;A̅b)Jn#vn tM7ϟyeÀy %൥\u$C}W]1^YZ ՛oxd;77Ϟ?ywn߿mJj͙@.VKq Jj$Y -\?eog?u ȼ~^z[[$ ɉa\i2l{{s v*,΋'_}o@F;O{իo>2(QB+E ֶ&5#+\. A&R6 u>?{7|xof_nEL'ҕGZy)3+3&izަm7(:#"폄lZrq^LY,1v4iP._mI' & e+) 7nH亁ham}q`:&F@$6] N(:I1"3 \'%efjf`eJ*HWRfL2mZkf i3RHJ @&thƩ:l'9%SB1cln~`+2 Vn2ۤh2"36Xi1$02&KPkxǙgFY rf{AmgF i>zE!'et'`7x`ܒ PHE9k⣔Mp5+tfDw(dTg#y,[*k\# z(Hθy`g\"J,tP'hz<`y71q/,^H^W̜^7)'`)de=ZJ}rP6&NZniՏ;6$tQʐTdU9*жlNGsRw@X~mhL\87NyIm H`:VqSYS7nq,;uds-ˠ$BkQCtX/M#cyV=|rwKW%ǦjIKnfmSqGQ_g{EU9x2GDD9\m?.OOW㕙 :7wn&9mtUm+is'CUPi9)j|ݫ_?yB7Έm7gfA-u&;u&݊G݂ɼA!oЗI Uϡgc&][Lx:Z-ǦB:eVUb"}ձ/UzQX>m1_;-zF@Ϟrw6 g~h:j;:# t:rJ*"O_~~\5_dk^rvh\)bZȈ_Kĥp?cpڋ^߾ۧ_>~"m9OQᾫiHzSv8Q%G`_޾'_{of统~ٷ}"n&=8CgUcZТKVLi/?}ƭ32 /+oq48ؖx/ytjcu[#62So$mT9+Yg?Gxz~nıqUXGv՘<u2PǏ˯<ϝGgNz?7|_?՛.daIENDB`robocode/robocode/resources/images/ground/blue_metal/blue_metal_4.png0000644000175000017500000001067410440666242025404 0ustar lambylambyPNG  IHDR@@% bKGD pHYs  tIME 41tEXtCommentCreated with The GIMPd%n IDATxڭZɎ]Wrn|^RCMo[>tc&rWJ~IMؾv$$I4fݚfd_v9Et;4nxQ]vp9Z(LDdf+'%?oκD/h{I|w1~`^2S օ433PC9ZIJl"lsK2e{;}ohF݈E&|w}ŋg!@33w%ŵs$fF읡VR iH*{23?{z~q[KI8Od{U4w6="2zfauوLedFFFd{dޖ尴ُOq͗>ɻޯ@Ό|䛿|Rh7J5nnf2%0֚H5'ͪI@4w-gFfDg]=iE]3ŵDj#zDd6g*"^P2bI /L*H GI D tMrEV٨#-j"ǺFF+HDJ*e+>Ш$-Ka,Fް d m eV]L󌌤dZ`O#aV@-webKͅDGF(#i2BD4ݨ{5}} EhۓJX$2 p[33ې2wEtbω}9JL(1VU/NR d> *s+Orơ^$3+0bۿd S*F綤 43Wߠ9ǝXeƪ z[;eGDkDj^a *z*#âroޓ) YvR a"GۈQ@*P=7*p,˲,Ë#z9I:-ȏ$%TY8,RJ`7s` ps&eOhho%TeNdPbIqnm&IT $EĤtWH)߇P{*E `^Q+(Hv<;<[%I3V)9%֟1նXeB fKkm$DTENDD}%#:)3Esޏiͽ/TG1Yey[dy5U5 w Bf]z_#u}y/z|yٺ^͛Cn]tU*AAۂܩ RM#돃܏ƍҌ c]ϖWϟ])jmv\`Y_rEu7̄0U53M*Iѱ23wbG B{Fp<珿Z;`I%`E0뜤XfK[X>'6$7`#XU&Yf-ۢ A x}ⷿ_>?Ox~q'(`FI mge @ppo2"b-n]m5 Qnt] ({kmim7./_৭r |O/JXK> 3\B! +ILTbVdL#.ӫo...}넸ϞGRZ t;[%m6`0Tjf(#4xQJ|]/[[rJAҥKb $A;cB$9/FVSe %){Uخ|YE L|rpRS7&Ц!ͣT#A"V"" UuLef_vz / k|>x3wś)oڑbW_P㻫'woݷ[[s_E[lkB:Ҹm@nYD%ff* ޏf;0A..zö7Eッ}-[%w(I{]>ZswdZfBckmY=L>Fѱ,̼&AQvo$B:ȚX{EehȄz_!M*U!)e*"22e9,A3_C[H1U$[kEp ԆK7ӈѿƝܦ`>#lB[3Z;_\>yr}7̣G_;x[~#4! 'C mWD[=V6#;٬Gʼ|J ຮv<  ز, m*) &(a&tr^u}˺3g=d Vud]9ƝA6yT/(,89Smے)mʰ OƝ,}]O*`8*=z/CHw<0sfncr"V ]l撪ᭇ9M"mSJ*w>g%@ bE7r?s3o h[}X'mk-©Qe{m7#NJ=DD#<:QS%)%AqFbTSY:7z?q[^?oԽQAjt8g08 QmNm[{6bRe{!yӟiVO 2Z7{sR=L-7-E0wZtKST9uH%wѱ-x^u=A Q:9Rڋ_.c[o-;oG?ywNs~ܗecNrtA~<~}-C{٢D\L2\ {iG}s`v IÓ_>ŝ{uLxo?!٧jmi m74R)Үx 2Zi[L&Z&"w3_~L7 e7Kܺ5yt z[YD<3쐪bVKrl@z+kfen6X5~=WԃD_<?>ȏixA1̝nuFf&8`ѯ@6` h@*8 xV%U0F̨@|Dd$K *d{5,#ۧ@5O!3i*Fǀ$l hHhֆ,̶7/} B "y|t"S&jeasm(0!zs=0бT~F7{1( FN{v5_Qw%S(!_t>PͅIv8HoByr‘4D+(ւfDp8G;Bw_ -yQ8LdLFd8rx"3,0P< 2\3Zz˧g7Us: &M@!@4b yt/m>Ze"\U !XVZtn‡qT!iԳs `Dn,K. w d04Maңm vŒ|Qq\;c Fu+`bim4*Ạ̀ϽLDNZoz}M=_p電ܓG~tV`Ul`ΨEIrvE_Tb'`/kz "B߅]cA@,g= +ؾzSKu( G3FGfh Ȉuvo/v:A<1`O+qZqݦ) jj=㱪IK_Vl P'< ctBTU9-)Irr/''e"`P;w3kn{_I+YƢ~uڼ1M7HfJ' t zDj,:?@ ܨ,M50IO[>Hp@$.u5F][N34* 1"Z:#K}&U[h/yO%(SHл 7*9V[5I1/IENDB`robocode/robocode/resources/images/ground/blue_metal/blue_metal_2.png0000644000175000017500000000667110440666242025404 0ustar lambylambyPNG  IHDR@@% bKGD pHYs  tIME "/# tEXtCommentCreated with The GIMPd%n IDATxZْIn<jf7^+Uͫ2""L[VF]Y˿|z?T 7ῖu"෮ZPSFmg@0W52ZG~ӋW0E(! '|G89Qo?~yrN77~WB ?AzeCeKٯQT$.Ьx](_+X;BzWU{o6W,=vz7}rIFtL??޼}'5@:?܇߫~yo~K!V"}.O\g '7л[9ͻ/nInNBx=}YD(1KN>a TmWDl YW{|.ݟ!*ZBR`@ J"d\"Z'XUIhPО͓Vrgn3ޅD9$0CG-c[PFx2UJ Z`DITmc5+EȀWt59^rnMd ( :G0]U!-Ry\5"(A2Ev#OlLyn+~@W [茀Y<T"^#s/ZjG@t,V+9,N#!B5U+$<@f{L|P̲j.j(/Yz*H8~ہZ0\pUe^t8Wv0.b4)D^b#[UEJԴZ}^*"Q"̺x5b_.\hpk 5RٙoŌrr{<,͋R<.wuDMʪ]\ QՈhլ$̓R e"sBա"g@R3e;_h{G8v;4bJ]5(kJ4z4=76bF硋i6MVjTwe"k5R̊׹zՍ`3!P.ܛxf4"U¹z5#ϯ%dU`xBGң2hb 351vQ-tkdM.ːۍB =7RIQqK3tYAzDsytBh[7-hvH3@œD&KĠsz!=UUߗ njλkU4@pv-I)NQӌ>4:逳X؂r˾SITˌ|(+<±t^t;=C/EHcvnFX`B4rkT3I" >f""Nu$`\ZD&x]9CfE8=dԌ(W*G6Aj`[;A2R{O6Pcji-L "v #]=EZylnm(f:-uw`o4(QSB2jAe#LJ u#zHfkj.ٍoVSұJDUSZmnQYXw-Ц…k]S I]1*sK7v1֜|ϵW|YPx,{gCQVR<䤪)WL}\+Ï#c{} ` We=MlƁX6U<w ?><`:?嗟΃q[sΛ̌BNFTKA[ݶ?׫rz;Ï×/w gMgKЧƥ m(jPлp,W 1-7/^?_] 5/Hu~xڗ>\7boz M0Ѝev hʷo_޾R܏nX~!NN[II9HGc5\3tN7V k3,~^2x?ӯ|wѽO |g>NnKggdGa\lka9(PX)%;X\C6?C|\n"/fq. ʤyP^L ^H~P\Z hIԍe~|-2mEhEUv80J~\YkWL6Yn?u%-U?Q޼{_o_>~;?A7ͯIENDB`robocode/robocode/resources/images/ground/explode_debris.png0000644000175000017500000000672610440666242023732 0ustar lambylambyPNG  IHDR@@iqbKGD pHYs  tIME:"tEXtCommentCreated with The GIMPd%n :IDATxَWǿZzg,qGWW\ !.I!c{llwm?CMOx [*Lթs}f'}Wlk^: 5% YQ 2M3[BD.J0BDžU^ǒ^f֕3TĘ+¸Ђ2"@#H 覞7,c\"0* r}M=넔]" % hbxĥXff6[@k35gf}ٔFp3Ԇ0iͮ*I/ѾKc>c=Ә3S\{[W=y]Xtײ '-챙-fvw2T U7{R CvlK뛙3U.J"x=z!l&xSښLc4flfS*em3}lf-_=O(%]PP#\jfD`-tWY$r1C@l[fCݗ=W%} =H-Bk=v@# >NM NJ;33}"f]ȥ'BK| M$~SO5džElż gf+iٛfռf bsB i ?2NN|:6Oq]ĄReWq+Y@0-4-={dff~0{(jΤf> *nbb)lj= cf?BpdfK] GA9y67CVP 5G N*sfCk1&fvlf3aWju)o =_D_H/c #ͳg65ߖO{ Ktg x̾8^.06w*XwQ Dr˚G:m͟aZD֖< &u?@4{ )aZ!aS q1D4׆FONvrIM߇c3aGE`XoP/VHmt'} )biXuw$X'kܙzTuobZ@Ĝ3%?~,mOU^%5A^~[zfRAh88gTlH{`fC/l s8@ٯ|'-bnT z<7L9_A V?T[]f-lJ(zc- #' @7 SX LqvhGۚ ~b٬!,QG86DN`&z3F1m{S8YbJus X=E|>sg@k9'` ZE n-HߞnTYƞX2D X9"H `CR|߼,v06u)V#tbFLՋ4;]k$b5s={' zj#194'\D]Nm3Ww[ bHD WWӞ=ub@u0dV;3 1ew8 WPH FjMjBEwd[\wpuj(7 W;'W R/*9:G~>Qk)sE] ~IENDB`robocode/robocode/resources/images/ground/.cvsignore0000644000175000017500000000001310470715222022207 0ustar lambylambyThumbs.db robocode/robocode/resources/images/.cvsignore0000644000175000017500000000001310470715222020711 0ustar lambylambyThumbs.db robocode/robocode/resources/images/body.png0000644000175000017500000000324610205417702020365 0ustar lambylambyPNG  IHDR$&9gAMA|Q cHRMz%u0`:o1IDATxbd@ʁزe #.@ ǣGb0dO:ps RRpb8|$ó  H .&PWΠ#`ffU@tЭ[ddl[gōx #c) # p @`)**bH|2 @8CHPPf+ !ARMpϟI|iꕂ@i`q9 XΜ9߿(LLL eؼ*c3gdbbg`ccC- !/^ >}_ lG (Je/_d>0-VVA䠿@?2<|Eb @!g }A\ܕ{@GQߟCfp///Awׯ1[| )~eVz6 <@e` ư0 &&qϞ tȌ`߿"())q p}À?2pq,@=6 @`IJJbHG {V;A Ɛ{.ûw B%`lv@$##!OČ頿` *޼y/||| &hapJ=l(33- zP|222('P !aYYY4  p1prrb84`C O>e R\`3 ^zerVTule` @r|I? c9AQ2.6.80e;xU eAF'0qSIfc  ffq zV@ P ߔ8߿_AfcoloEj9T\Tu?v@ǿ6lV"""999B\t 9D%Ob~ZnnH xX(j~u\%/$2[EEE-@`*:vv]XXEaA*$AM_ &TأFRl Jrc@E< F])#3`M:h/Z ;@*/vvF#QDl, VB Kt 8?~aA!'-lllv@ŵ 322|L df'N!ãq L?3dʼLLHe`@8 1>|PX@Wk?bu)f* 4[g+}]TAPa?b;R18Ɂh/!-IENDB`robocode/robocode/robocode/0000755000175000017500000000000011125256066015240 5ustar lambylambyrobocode/robocode/robocode/BulletHitEvent.java0000644000175000017500000000661411130241114020770 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Updated Javadocs *******************************************************************************/ package robocode; import robocode.peer.RobotStatics; import robocode.robotinterfaces.IBasicEvents; import robocode.robotinterfaces.IBasicRobot; import java.awt.*; import java.util.Hashtable; /** * This event is sent to {@link Robot#onBulletHit(BulletHitEvent) onBulletHit} * when one of your bullets has hit another robot. * * @author Mathew A. Nelson (original) */ public final class BulletHitEvent extends Event { private static final long serialVersionUID = 1L; private final static int DEFAULT_PRIORITY = 50; private final String name; private final double energy; private Bullet bullet; /** * Called by the game to create a new {@code BulletHitEvent}. * * @param name the name of the robot your bullet hit * @param energy the remaining energy of the robot that your bullet has hit * @param bullet the bullet that hit the robot */ public BulletHitEvent(String name, double energy, Bullet bullet) { super(); this.name = name; this.energy = energy; this.bullet = bullet; } /** * Returns the bullet of yours that hit the robot. * * @return the bullet that hit the robot */ public Bullet getBullet() { return bullet; } /** * Returns the remaining energy of the robot your bullet has hit (after the * damage done by your bullet). * * @return energy the remaining energy of the robot that your bullet has hit */ public double getEnergy() { return energy; } /** * @return energy the remaining energy of the robot that your bullet has hit * @deprecated Use {@link #getEnergy()} instead. */ @Deprecated public double getLife() { return energy; } /** * Returns the name of the robot your bullet hit. * * @return the name of the robot your bullet hit. */ public String getName() { return name; } /** * @return energy the remaining energy of the robot that your bullet has hit * @deprecated Use {@link #getEnergy()} instead. */ @Deprecated public double getRobotLife() { return energy; } /** * @return the name of the robot your bullet hit. * @deprecated Use {@link #getName()} instead. */ @Deprecated public String getRobotName() { return name; } /** * {@inheritDoc} */ @Override final int getDefaultPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override final void dispatch(IBasicRobot robot, RobotStatics statics, Graphics2D graphics) { IBasicEvents listener = robot.getBasicEventListener(); if (listener != null) { listener.onBulletHit(this); } } /** * {@inheritDoc} */ @Override final void updateBullets(Hashtable bullets) { // we need to pass same instance bullet = bullets.get(bullet.getBulletId()); } } robocode/robocode/robocode/KeyTypedEvent.java0000644000175000017500000000367111130241112020630 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode; import robocode.peer.RobotStatics; import robocode.robotinterfaces.IBasicRobot; import robocode.robotinterfaces.IInteractiveEvents; import robocode.robotinterfaces.IInteractiveRobot; import java.awt.*; /** * A KeyTypedEvent is sent to {@link Robot#onKeyTyped(java.awt.event.KeyEvent) * onKeyTyped()} when a key has been typed (pressed and released) on the keyboard. * * @author Pavel Savara (original) * @see KeyPressedEvent * @see KeyReleasedEvent * @since 1.6.1 */ public final class KeyTypedEvent extends KeyEvent { private static final long serialVersionUID = 1L; private final static int DEFAULT_PRIORITY = 98; /** * Called by the game to create a new KeyTypedEvent. * * @param source the source key event originating from the AWT. */ public KeyTypedEvent(java.awt.event.KeyEvent source) { super(source); } /** * {@inheritDoc} */ @Override final int getDefaultPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override final void dispatch(IBasicRobot robot, RobotStatics statics, Graphics2D graphics) { if (statics.isInteractiveRobot()) { IInteractiveEvents listener = ((IInteractiveRobot) robot).getInteractiveEventListener(); if (listener != null) { listener.onKeyTyped(getSourceEvent()); } } } } robocode/robocode/robocode/battlefield/0000755000175000017500000000000011124142536017512 5ustar lambylambyrobocode/robocode/robocode/battlefield/BattleField.java0000644000175000017500000000174211130241114022525 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Replaced BoundingRectangle with Rectangle2D *******************************************************************************/ package robocode.battlefield; import java.io.Serializable; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ public interface BattleField extends Serializable { public java.awt.geom.Rectangle2D getBoundingBox(); public int getHeight(); public int getWidth(); } robocode/robocode/robocode/battlefield/DefaultBattleField.java0000644000175000017500000000270311130241114024030 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew Nelson * - Initial API and implementation * Flemming N. Larsen * - Rewritten *******************************************************************************/ package robocode.battlefield; import robocode.common.BoundingRectangle; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ public class DefaultBattleField implements BattleField { private static final long serialVersionUID = 1L; private final BoundingRectangle boundingBox; public DefaultBattleField(int width, int height) { super(); this.boundingBox = new BoundingRectangle(0, 0, width, height); } public BoundingRectangle getBoundingBox() { return boundingBox; } public int getWidth() { return (int) boundingBox.width; } public void setWidth(int newWidth) { boundingBox.width = newWidth; } public int getHeight() { return (int) boundingBox.height; } public void setHeight(int newHeight) { boundingBox.height = newHeight; } } robocode/robocode/robocode/JuniorRobot.java0000644000175000017500000006243111130241112020343 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Nutch Poovarawan from Cubic Creative * - The design and ideas for the JuniorRobot class * Flemming N. Larsen * - Implementor of the JuniorRobot * Pavel Savara * - Re-work of robot interfaces *******************************************************************************/ package robocode; import robocode.robotinterfaces.IBasicEvents; import robocode.robotinterfaces.IJuniorRobot; import robocode.robotinterfaces.peer.IJuniorRobotPeer; import robocode.util.Utils; import static robocode.util.Utils.normalRelativeAngle; import java.awt.*; import static java.lang.Math.toDegrees; import static java.lang.Math.toRadians; /** * This is the simplest robot type, which is simpler than the {@link Robot} and * {@link AdvancedRobot} classes. The JuniorRobot has a simplified model, in * purpose of teaching programming skills to inexperienced in programming * students. The simplified robot model will keep player from overwhelming of * Robocode's rules, programming syntax and programming concept. *

* Instead of using getters and setters, public fields are provided for * receiving information like the last scanned robot, the coordinate of the * robot etc. *

* All methods on this class are blocking calls, i.e. they do not return before * their action has been completed and will at least take one turn to execute. * However, setting colors is executed immediately and does not cost a turn to * perform. * * @author Nutch Poovarawan from Cubic Creative (designer) * @author Flemming N. Larsen (implementor) * @author Pavel Savara (contributor) * @see Robot * @see AdvancedRobot * @see TeamRobot * @see Droid * @since 1.4 */ public class JuniorRobot extends _RobotBase implements IJuniorRobot { /* * The JuniorRobot event handler, which implements the basic robot events, * JuniorRobot event, and Runnable. */ private final class InnerEventHandler implements IBasicEvents, Runnable { private double juniorFirePower; public void onBulletHit(BulletHitEvent event) {} public void onBulletHitBullet(BulletHitBulletEvent event) {} public void onBulletMissed(BulletMissedEvent event) {} public void onDeath(DeathEvent event) {} public void onHitByBullet(HitByBulletEvent event) { double angle = peer.getBodyHeading() + event.getBearingRadians(); hitByBulletAngle = (int) (Math.toDegrees(Utils.normalAbsoluteAngle(angle)) + 0.5); hitByBulletBearing = (int) (event.getBearing() + 0.5); JuniorRobot.this.onHitByBullet(); } public void onHitRobot(HitRobotEvent event) { double angle = peer.getBodyHeading() + event.getBearingRadians(); hitRobotAngle = (int) (Math.toDegrees(Utils.normalAbsoluteAngle(angle)) + 0.5); hitRobotBearing = (int) (event.getBearing() + 0.5); JuniorRobot.this.onHitRobot(); } public void onHitWall(HitWallEvent event) { double angle = peer.getBodyHeading() + event.getBearingRadians(); hitWallAngle = (int) (Math.toDegrees(Utils.normalAbsoluteAngle(angle)) + 0.5); hitWallBearing = (int) (event.getBearing() + 0.5); JuniorRobot.this.onHitWall(); } public void onRobotDeath(RobotDeathEvent event) { others = peer.getOthers(); } public void onScannedRobot(ScannedRobotEvent event) { scannedDistance = (int) (event.getDistance() + 0.5); scannedEnergy = Math.max(1, (int) (event.getEnergy() + 0.5)); scannedAngle = (int) (Math.toDegrees( Utils.normalAbsoluteAngle(peer.getBodyHeading() + event.getBearingRadians())) + 0.5); scannedBearing = (int) (event.getBearing() + 0.5); scannedHeading = (int) (event.getHeading() + 0.5); scannedVelocity = (int) (event.getVelocity() + 0.5); JuniorRobot.this.onScannedRobot(); } public void onStatus(StatusEvent e) { final RobotStatus s = e.getStatus(); others = peer.getOthers(); energy = Math.max(1, (int) (s.getEnergy() + 0.5)); robotX = (int) (s.getX() + 0.5); robotY = (int) (s.getY() + 0.5); heading = (int) (toDegrees(s.getHeading()) + 0.5); gunHeading = (int) (toDegrees(s.getGunHeading()) + 0.5); gunBearing = (int) (toDegrees(normalRelativeAngle(s.getGunHeading() - s.getHeading())) + 0.5); gunReady = (s.getGunHeat() <= 0); // Auto fire if (juniorFirePower > 0 && gunReady && (peer.getGunTurnRemaining() == 0)) { if (peer.setFire(juniorFirePower) != null) { gunReady = false; juniorFirePower = 0; } } } public void onWin(WinEvent event) {} public void run() { fieldWidth = (int) (peer.getBattleFieldWidth() + 0.5); fieldHeight = (int) (peer.getBattleFieldHeight() + 0.5); // noinspection InfiniteLoopStatement while (true) { JuniorRobot.this.run(); } } } /** * The color black (0x000000) */ public final static int black = 0x000000; /** * The color white (0xFFFFFF) */ public final static int white = 0xFFFFFF; /** * The color red (0xFF0000) */ public final static int red = 0xFF0000; /** * The color orange (0xFFA500) */ public final static int orange = 0xFFA500; /** * The color yellow (0xFFFF00) */ public final static int yellow = 0xFFFF00; /** * The color green (0x008000) */ public final static int green = 0x008000; /** * The color blue (0x0000FF) */ public final static int blue = 0x0000FF; /** * The color purple (0x800080) */ public final static int purple = 0x800080; /** * The color brown (0x8B4513) */ public final static int brown = 0x8B4513; /** * The color gray (0x808080) */ public final static int gray = 0x808080; /** * Contains the width of the battlefield. * * @see #fieldWidth */ public int fieldWidth; /** * Contains the height of the battlefield. * * @see #fieldWidth */ public int fieldHeight; /** * Current number of other robots on the battle field. */ public int others; /** * Current energy of this robot, where 100 means full energy and 0 means no energy (dead). */ public int energy; /** * Current horizontal location of this robot (in pixels). * * @see #robotY */ public int robotX; /** * Current vertical location of this robot (in pixels). * * @see #robotX */ public int robotY; /** * Current heading angle of this robot (in degrees). * * @see #turnLeft(int) * @see #turnRight(int) * @see #turnTo(int) * @see #turnAheadLeft(int, int) * @see #turnAheadRight(int, int) * @see #turnBackLeft(int, int) * @see #turnBackRight(int, int) */ public int heading; /** * Current gun heading angle of this robot (in degrees). * * @see #gunBearing * @see #turnGunLeft(int) * @see #turnGunRight(int) * @see #turnGunTo(int) * @see #bearGunTo(int) */ public int gunHeading; /** * Current gun heading angle of this robot compared to its body (in degrees). * * @see #gunHeading * @see #turnGunLeft(int) * @see #turnGunRight(int) * @see #turnGunTo(int) * @see #bearGunTo(int) */ public int gunBearing; /** * Flag specifying if the gun is ready to fire, i.e. gun heat <= 0. * {@code true} means that the gun is able to fire; {@code false} * means that the gun cannot fire yet as it still needs to cool down. * * @see #fire() * @see #fire(double) */ public boolean gunReady; /** * Current distance to the scanned nearest other robot (in pixels). * If there is no robot in the radar's sight, this field will be less than 0, i.e -1. * This field will not be updated while {@link #onScannedRobot()} event is active. * * @see #onScannedRobot() * @see #scannedAngle * @see #scannedBearing * @see #scannedEnergy * @see #scannedVelocity * @see #scannedHeading */ public int scannedDistance = -1; /** * Current angle to the scanned nearest other robot (in degrees). * If there is no robot in the radar's sight, this field will be less than 0, i.e -1. * This field will not be updated while {@link #onScannedRobot()} event is active. * * @see #onScannedRobot() * @see #scannedDistance * @see #scannedBearing * @see #scannedEnergy * @see #scannedVelocity * @see #scannedHeading */ public int scannedAngle = -1; /** * Current angle to the scanned nearest other robot (in degrees) compared to * the body of this robot. * If there is no robot in the radar's sight, this field will be less than 0, i.e -1. * This field will not be updated while {@link #onScannedRobot()} event is active. * * @see #onScannedRobot() * @see #scannedDistance * @see #scannedAngle * @see #scannedEnergy * @see #scannedVelocity * @see #scannedHeading */ public int scannedBearing = -1; /** * Current velocity of the scanned nearest other robot. * If there is no robot in the radar's sight, this field will be -99. * Note that a positive value means that the robot moves forward, a negative * value means that the robot moved backward, and 0 means that the robot is * not moving at all. * This field will not be updated while {@link #onScannedRobot()} event is active. * * @see #onScannedRobot() * @see #scannedDistance * @see #scannedAngle * @see #scannedBearing * @see #scannedEnergy * @see #scannedHeading */ public int scannedVelocity = -99; /** * Current heading of the scanned nearest other robot (in degrees). * If there is no robot in the radar's sight, this field will be less than 0, i.e -1. * This field will not be updated while {@link #onScannedRobot()} event is active. * * @see #onScannedRobot() * @see #scannedDistance * @see #scannedAngle * @see #scannedBearing * @see #scannedEnergy * @see #scannedVelocity */ public int scannedHeading = -1; /** * Current energy of scanned nearest other robot. * If there is no robot in the radar's sight, this field will be less than 0, i.e -1. * This field will not be updated while {@link #onScannedRobot()} event is active. * * @see #onScannedRobot() * @see #scannedDistance * @see #scannedAngle * @see #scannedBearing * @see #scannedVelocity */ public int scannedEnergy = -1; /** * Latest angle from where this robot was hit by a bullet (in degrees). * If the robot has never been hit, this field will be less than 0, i.e. -1. * This field will not be updated while {@link #onHitByBullet()} event is active. * * @see #onHitByBullet() * @see #hitByBulletBearing */ public int hitByBulletAngle = -1; /** * Latest angle from where this robot was hit by a bullet (in degrees) * compared to the body of this robot. * If the robot has never been hit, this field will be less than 0, i.e. -1. * This field will not be updated while {@link #onHitByBullet()} event is active. * * @see #onHitByBullet() * @see #hitByBulletAngle */ public int hitByBulletBearing = -1; /** * Latest angle where this robot has hit another robot (in degrees). * If this robot has never hit another robot, this field will be less than 0, i.e. -1. * This field will not be updated while {@link #onHitRobot()} event is active. * * @see #onHitRobot() * @see #hitRobotBearing */ public int hitRobotAngle = -1; /** * Latest angle where this robot has hit another robot (in degrees) * compared to the body of this robot. * If this robot has never hit another robot, this field will be less than 0, i.e. -1. * This field will not be updated while {@link #onHitRobot()} event is active. * * @see #onHitRobot() * @see #hitRobotAngle */ public int hitRobotBearing = -1; /** * Latest angle where this robot has hit a wall (in degrees). * If this robot has never hit a wall, this field will be less than 0, i.e. -1. * This field will not be updated while {@link #onHitWall()} event is active. * * @see #onHitWall() * @see #hitWallBearing */ public int hitWallAngle = -1; /** * Latest angle where this robot has hit a wall (in degrees) * compared to the body of this robot. * If this robot has never hit a wall, this field will be less than 0, i.e. -1. * This field will not be updated while {@link #onHitWall()} event is active. * * @see #onHitWall() * @see #hitWallAngle */ public int hitWallBearing = -1; /** * The robot event handler for this robot. */ private InnerEventHandler innerEventHandler; /** * Moves this robot forward by pixels. * * @param distance the amount of pixels to move forward * @see #back(int) * @see #robotX * @see #robotY */ public void ahead(int distance) { if (peer != null) { peer.move(distance); } else { uninitializedException(); } } /** * Moves this robot backward by pixels. * * @param distance the amount of pixels to move backward * @see #ahead(int) * @see #robotX * @see #robotY */ public void back(int distance) { ahead(-distance); } /** * Turns the gun to the specified angle (in degrees) relative to body of this robot. * The gun will turn to the side with the shortest delta angle to the specified angle. * * @param angle the angle to turn the gun to relative to the body of this robot * @see #gunHeading * @see #gunBearing * @see #turnGunLeft(int) * @see #turnGunRight(int) * @see #turnGunTo(int) */ public void bearGunTo(int angle) { if (peer != null) { peer.turnGun(normalRelativeAngle(peer.getBodyHeading() + toRadians(angle) - peer.getGunHeading())); } else { uninitializedException(); } } /** * Skips a turn. * * @see #doNothing(int) */ public void doNothing() { if (peer != null) { peer.execute(); } else { uninitializedException(); } } /** * Skips the specified number of turns. * * @param turns the number of turns to skip * @see #doNothing() */ public void doNothing(int turns) { if (turns <= 0) { return; } if (peer != null) { for (int i = 0; i < turns; i++) { peer.execute(); } } else { uninitializedException(); } } /** * Fires a bullet with the default power of 1. * If the gun heat is more than 0 and hence cannot fire, this method will * suspend until the gun is ready to fire, and then fire a bullet. * * @see #gunReady */ public void fire() { fire(1); } /** * Fires a bullet with the specified bullet power, which is between 0.1 and 3 * where 3 is the maximum bullet power. * If the gun heat is more than 0 and hence cannot fire, this method will * suspend until the gun is ready to fire, and then fire a bullet. * * @param power between 0.1 and 3 * @see #gunReady */ public void fire(double power) { if (peer != null) { getEventHandler().juniorFirePower = power; peer.execute(); } else { uninitializedException(); } } /** * Do not call this method! *

* {@inheritDoc} */ public final IBasicEvents getBasicEventListener() { return getEventHandler(); } /** * Do not call this method! *

* {@inheritDoc} */ public final Runnable getRobotRunnable() { return getEventHandler(); } /** * This event methods is called from the game when this robot has been hit * by another robot's bullet. When this event occurs the * {@link #hitByBulletAngle} and {@link #hitByBulletBearing} fields values * are automatically updated. * * @see #hitByBulletAngle * @see #hitByBulletBearing */ public void onHitByBullet() {} /** * This event methods is called from the game when a bullet from this robot * has hit another robot. When this event occurs the {@link #hitRobotAngle} * and {@link #hitRobotBearing} fields values are automatically updated. * * @see #hitRobotAngle * @see #hitRobotBearing */ public void onHitRobot() {} /** * This event methods is called from the game when this robot has hit a wall. * When this event occurs the {@link #hitWallAngle} and {@link #hitWallBearing} * fields values are automatically updated. * * @see #hitWallAngle * @see #hitWallBearing */ public void onHitWall() {} /** * This event method is called from the game when the radar detects another * robot. When this event occurs the {@link #scannedDistance}, * {@link #scannedAngle}, {@link #scannedBearing}, and {@link #scannedEnergy} * field values are automatically updated. * * @see #scannedDistance * @see #scannedAngle * @see #scannedBearing * @see #scannedEnergy */ public void onScannedRobot() {} /** * The main method in every robot. You must override this to set up your * robot's basic behavior. *

* Example: *

	 *   // A basic robot that moves around in a square
	 *   public void run() {
	 *       ahead(100);
	 *       turnRight(90);
	 *   }
	 * 
* This method is automatically re-called when it has returned. */ public void run() {} /** * Sets the colors of the robot. The color values are RGB values. * You can use the colors that are already defined for this class. * * @param bodyColor the RGB color value for the body * @param gunColor the RGB color value for the gun * @param radarColor the RGB color value for the radar * @see #setColors(int, int, int, int, int) */ public void setColors(int bodyColor, int gunColor, int radarColor) { if (peer != null) { peer.setBodyColor(new Color(bodyColor)); peer.setGunColor(new Color(gunColor)); peer.setRadarColor(new Color(radarColor)); } else { uninitializedException(); } } /** * Sets the colors of the robot. The color values are RGB values. * You can use the colors that are already defined for this class. * * @param bodyColor the RGB color value for the body * @param gunColor the RGB color value for the gun * @param radarColor the RGB color value for the radar * @param bulletColor the RGB color value for the bullets * @param scanArcColor the RGB color value for the scan arc * @see #setColors(int, int, int) */ public void setColors(int bodyColor, int gunColor, int radarColor, int bulletColor, int scanArcColor) { if (peer != null) { peer.setBodyColor(new Color(bodyColor)); peer.setGunColor(new Color(gunColor)); peer.setRadarColor(new Color(radarColor)); peer.setBulletColor(new Color(bulletColor)); peer.setScanColor(new Color(scanArcColor)); } else { uninitializedException(); } } /** * Moves this robot forward by pixels and turns this robot left by degrees * at the same time. The robot will move in a curve that follows a perfect * circle, and the moving and turning will end at the same time. *

* Note that the max. velocity and max. turn rate is automatically adjusted, * which means that the robot will move slower the sharper the turn is * compared to the distance. * * @param distance the amount of pixels to move forward * @param degrees the amount of degrees to turn to the left * @see #heading * @see #robotX * @see #robotY * @see #turnLeft(int) * @see #turnRight(int) * @see #turnTo(int) * @see #turnAheadRight(int, int) * @see #turnBackLeft(int, int) * @see #turnBackRight(int, int) */ public void turnAheadLeft(int distance, int degrees) { turnAheadRight(distance, -degrees); } /** * Moves this robot forward by pixels and turns this robot right by degrees * at the same time. The robot will move in a curve that follows a perfect * circle, and the moving and turning will end at the same time. *

* Note that the max. velocity and max. turn rate is automatically adjusted, * which means that the robot will move slower the sharper the turn is * compared to the distance. * * @param distance the amount of pixels to move forward * @param degrees the amount of degrees to turn to the right * @see #heading * @see #robotX * @see #robotY * @see #turnLeft(int) * @see #turnRight(int) * @see #turnTo(int) * @see #turnAheadLeft(int, int) * @see #turnBackLeft(int, int) * @see #turnBackRight(int, int) */ public void turnAheadRight(int distance, int degrees) { if (peer != null) { ((IJuniorRobotPeer) peer).turnAndMove(distance, toRadians(degrees)); } else { uninitializedException(); } } /** * Moves this robot backward by pixels and turns this robot left by degrees * at the same time. The robot will move in a curve that follows a perfect * circle, and the moving and turning will end at the same time. *

* Note that the max. velocity and max. turn rate is automatically adjusted, * which means that the robot will move slower the sharper the turn is * compared to the distance. * * @param distance the amount of pixels to move backward * @param degrees the amount of degrees to turn to the left * @see #heading * @see #robotX * @see #robotY * @see #turnLeft(int) * @see #turnRight(int) * @see #turnTo(int) * @see #turnAheadLeft(int, int) * @see #turnAheadRight(int, int) * @see #turnBackRight(int, int) */ public void turnBackLeft(int distance, int degrees) { turnAheadRight(-distance, degrees); } /** * Moves this robot backward by pixels and turns this robot right by degrees * at the same time. The robot will move in a curve that follows a perfect * circle, and the moving and turning will end at the same time. *

* Note that the max. velocity and max. turn rate is automatically adjusted, * which means that the robot will move slower the sharper the turn is * compared to the distance. * * @param distance the amount of pixels to move backward * @param degrees the amount of degrees to turn to the right * @see #heading * @see #robotX * @see #robotY * @see #turnLeft(int) * @see #turnRight(int) * @see #turnTo(int) * @see #turnAheadLeft(int, int) * @see #turnAheadRight(int, int) * @see #turnBackLeft(int, int) */ public void turnBackRight(int distance, int degrees) { turnAheadRight(-distance, -degrees); } /** * Turns the gun left by degrees. * * @param degrees the amount of degrees to turn the gun to the left * @see #gunHeading * @see #gunBearing * @see #turnGunRight(int) * @see #turnGunTo(int) * @see #bearGunTo(int) */ public void turnGunLeft(int degrees) { turnGunRight(-degrees); } /** * Turns the gun right by degrees. * * @param degrees the amount of degrees to turn the gun to the right * @see #gunHeading * @see #gunBearing * @see #turnGunLeft(int) * @see #turnGunTo(int) * @see #bearGunTo(int) */ public void turnGunRight(int degrees) { if (peer != null) { peer.turnGun(toRadians(degrees)); } else { uninitializedException(); } } /** * Turns the gun to the specified angle (in degrees). * The gun will turn to the side with the shortest delta angle to the * specified angle. * * @param angle the angle to turn the gun to * @see #gunHeading * @see #gunBearing * @see #turnGunLeft(int) * @see #turnGunRight(int) * @see #bearGunTo(int) */ public void turnGunTo(int angle) { if (peer != null) { peer.turnGun(normalRelativeAngle(toRadians(angle) - peer.getGunHeading())); } else { uninitializedException(); } } /** * Turns this robot left by degrees. * * @param degrees the amount of degrees to turn to the left * @see #heading * @see #turnRight(int) * @see #turnTo(int) * @see #turnAheadLeft(int, int) * @see #turnAheadRight(int, int) * @see #turnBackLeft(int, int) * @see #turnBackRight(int, int) */ public void turnLeft(int degrees) { turnRight(-degrees); } /** * Turns this robot right by degrees. * * @param degrees the amount of degrees to turn to the right * @see #heading * @see #turnLeft(int) * @see #turnTo(int) * @see #turnAheadLeft(int, int) * @see #turnAheadRight(int, int) * @see #turnBackLeft(int, int) * @see #turnBackRight(int, int) */ public void turnRight(int degrees) { if (peer != null) { peer.turnBody(toRadians(degrees)); } else { uninitializedException(); } } /** * Turns this robot to the specified angle (in degrees). * The robot will turn to the side with the shortest delta angle to the * specified angle. * * @param angle the angle to turn this robot to * @see #heading * @see #turnLeft(int) * @see #turnRight(int) * @see #turnAheadLeft(int, int) * @see #turnAheadRight(int, int) * @see #turnBackLeft(int, int) * @see #turnBackRight(int, int) */ public void turnTo(int angle) { if (peer != null) { peer.turnBody(normalRelativeAngle(toRadians(angle) - peer.getBodyHeading())); } else { uninitializedException(); } } /* * Returns the event handler of this robot. */ private InnerEventHandler getEventHandler() { if (innerEventHandler == null) { innerEventHandler = new InnerEventHandler(); } return innerEventHandler; } } robocode/robocode/robocode/_RobotBase.java0000644000175000017500000000520011130241112020075 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen * - Initial implementation * Pavel Savara * - Re-work of robot interfaces, added setOut() *******************************************************************************/ package robocode; import robocode.exception.RobotException; import robocode.robotinterfaces.IBasicRobot; import robocode.robotinterfaces.peer.IBasicRobotPeer; /** * This is the base class of all robots used by the system. You should not base * your robots on this class. *

* You should create a robot that is derived from the {@link Robot} or * {@link JuniorRobot} class instead. *

* There is no guarantee that this class will exist in future versions of Robocode. * * @author Flemming N. Larsen (original) * @author Pavel Savara (contributor) * @see Robot * @see JuniorRobot * @see AdvancedRobot * @see TeamRobot * @since 1.4 */ public abstract class _RobotBase implements IBasicRobot, Runnable { // Internal for this package _RobotBase() {} IBasicRobotPeer peer; /** * The output stream your robot should use to print. *

* You can view the print-outs by clicking the button for your robot in the * right side of the battle window. *

* Example: *

	 *   // Print out a line each time my robot hits another robot
	 *   public void onHitRobot(HitRobotEvent e) {
	 *       out.println("I hit a robot!  My energy: " + getEnergy() + " his energy: " + e.getEnergy());
	 *   }
	 * 
*/ public java.io.PrintStream out; /** * {@inheritDoc} */ public final void setOut(java.io.PrintStream out) { this.out = out; } /** * {@inheritDoc} */ public final void setPeer(IBasicRobotPeer peer) { this.peer = peer; } /** * Throws a RobotException. This method should be called when the robot's peer * is uninitialized. */ static void uninitializedException() { StackTraceElement[] trace = Thread.currentThread().getStackTrace(); String methodName = trace[2].getMethodName(); throw new RobotException( "You cannot call the " + methodName + "() method before your run() method is called, or you are using a Robot object that the game doesn't know about."); } } robocode/robocode/robocode/manager/0000755000175000017500000000000011127773706016661 5ustar lambylambyrobocode/robocode/robocode/manager/IRepositoryManager.java0000644000175000017500000000251611130241112023262 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.manager; import robocode.repository.Repository; import java.io.File; import java.util.jar.JarInputStream; /** * @author Pavel Savara (original) */ public interface IRepositoryManager { File getRobotCache(); Repository getRobotRepository(); File getRobotsDirectory(); void clearRobotList(); int extractJar(File f, File dest, String statusPrefix, boolean extractJars, boolean close, boolean alwaysReplace); int extractJar(JarInputStream jarIS, File dest, String statusPrefix, boolean extractJars, boolean close, boolean alwaysReplace); boolean cleanupOldSampleRobots(boolean delete); // TODO: Needs to be updated? boolean verifyRobotName(String robotName, String shortName); RobocodeManager getManager(); } robocode/robocode/robocode/manager/IImageManager.java0000644000175000017500000000211011130241112022113 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.manager; import robocode.gfx.RenderImage; import java.awt.*; /** * @author Pavel Savara (original) */ public interface IImageManager { void initialize(); Image getGroundTileImage(int index); RenderImage getExplosionRenderImage(int which, int frame); RenderImage getExplosionDebriseRenderImage(); RenderImage getColoredBodyRenderImage(Integer color); RenderImage getColoredGunRenderImage(Integer color); RenderImage getColoredRadarRenderImage(Integer color); } robocode/robocode/robocode/manager/VersionManager.java0000644000175000017500000002401711130241112022417 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup * - Changed to give notification only if the available version number is * greater than the version retrieved from the robocode.jar file, and only * give warning if the user rejects downloading a new version, if the new * version is a final version * - Changed the checkdate time interval from 10 days to 5 days * - Updated to use methods from WindowUtil, FileUtil, Logger, which replaces * methods that have been (re)moved from the Utils and Constants class * - Added a connect timeout of 5 seconds when checking for a new version * - Added missing close() on input stream readers * - Added the Version class for comparing versions with compareTo() *******************************************************************************/ package robocode.manager; import robocode.dialog.WindowUtil; import robocode.io.FileUtil; import static robocode.io.Logger.logError; import static robocode.io.Logger.logMessage; import javax.swing.*; import java.io.*; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.util.Calendar; import java.util.Date; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ public final class VersionManager implements IVersionManager { private final static String INSTALL_URL = "http://robocode.sourceforge.net/installer"; private static String version; private final RobocodeManager manager; public VersionManager(RobocodeManager manager) { this.manager = manager; } public void checkUpdateCheck() { Date lastCheckedDate = manager.getProperties().getVersionChecked(); Date today = new Date(); if (lastCheckedDate == null) { lastCheckedDate = today; manager.getProperties().setVersionChecked(lastCheckedDate); manager.saveProperties(); } Calendar checkDate = Calendar.getInstance(); checkDate.setTime(lastCheckedDate); checkDate.add(Calendar.DATE, 5); if (checkDate.getTime().before(today) && checkForNewVersion(false)) { manager.getProperties().setVersionChecked(today); manager.saveProperties(); } } public boolean checkForNewVersion(boolean notifyNoUpdate) { URL url; try { url = new URL("http://robocode.sourceforge.net/version/version.html"); } catch (MalformedURLException e) { logError("Unable to check for new version: ", e); if (notifyNoUpdate) { WindowUtil.messageError("Unable to check for new version: " + e); } return false; } InputStream inputStream = null; InputStreamReader inputStreamReader = null; BufferedReader reader = null; try { URLConnection urlConnection = url.openConnection(); urlConnection.setConnectTimeout(5000); if (urlConnection instanceof HttpURLConnection) { logMessage("Update checking with http."); HttpURLConnection h = (HttpURLConnection) urlConnection; if (h.usingProxy()) { logMessage("http using proxy."); } } inputStream = urlConnection.getInputStream(); inputStreamReader = new InputStreamReader(inputStream); reader = new BufferedReader(inputStreamReader); String newVersLine = reader.readLine(); String curVersLine = getVersion(); boolean newVersionAvailable = false; if (newVersLine != null && curVersLine != null) { Version newVersion = new Version(newVersLine); if (newVersion.compareTo(curVersLine) > 0) { newVersionAvailable = true; if (JOptionPane.showConfirmDialog(manager.getWindowManager().getRobocodeFrame(), "Version " + newVersion + " of Robocode is now available. Would you like to download it?", "Version " + newVersion + " available", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) { try { BrowserManager.openURL(INSTALL_URL); } catch (IOException e) { JOptionPane.showMessageDialog(manager.getWindowManager().getRobocodeFrame(), e.getMessage(), "Unable to open browser!", JOptionPane.INFORMATION_MESSAGE); } } else if (newVersion.isFinal()) { JOptionPane.showMessageDialog(manager.getWindowManager().getRobocodeFrame(), "It is highly recommended that you always download the latest version. You may get it at " + INSTALL_URL, "Update when you can!", JOptionPane.INFORMATION_MESSAGE); } } } if (!newVersionAvailable && notifyNoUpdate) { JOptionPane.showMessageDialog(manager.getWindowManager().getRobocodeFrame(), "You have version " + version + ". This is the latest version of Robocode.", "No update available", JOptionPane.INFORMATION_MESSAGE); } } catch (IOException e) { logError("Unable to check for new version: " + e); if (notifyNoUpdate) { WindowUtil.messageError("Unable to check for new version: " + e); } return false; } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException ignored) {} } if (inputStreamReader != null) { try { inputStreamReader.close(); } catch (IOException ignored) {} } if (reader != null) { try { reader.close(); } catch (IOException ignored) {} } } return true; } public String getVersion() { return getVersionStatic(); } public static String getVersionStatic() { if (version == null) { version = getVersionFromJar(); } return version; } private static String getVersionFromJar() { String versionString = null; BufferedReader in = null; try { URL versionsUrl = VersionManager.class.getResource("/resources/versions.txt"); if (versionsUrl == null) { logError("no url"); versionString = "unknown"; } else { in = new BufferedReader(new InputStreamReader(versionsUrl.openStream())); versionString = in.readLine(); while (versionString != null && !versionString.substring(0, 8).equalsIgnoreCase("Version ")) { versionString = in.readLine(); } } } catch (FileNotFoundException e) { logError("No versions.txt file in robocode.jar."); versionString = "unknown"; } catch (IOException e) { logError("IO Exception reading versions.txt from robocode.jar" + e); versionString = "unknown"; } finally { if (in != null) { try { in.close(); } catch (IOException ignored) {} } } String version = "unknown"; if (versionString != null) { try { version = versionString.substring(8); } catch (Exception e) { version = "unknown"; } } if (version.equals("unknown")) { logError("Warning: Getting version from file."); return getVersionFromFile(); } return version; } private static String getVersionFromFile() { String versionString = null; FileReader fileReader = null; BufferedReader in = null; try { fileReader = new FileReader(new File(FileUtil.getCwd(), "versions.txt")); in = new BufferedReader(fileReader); versionString = in.readLine(); while (versionString != null && !versionString.substring(0, 8).equalsIgnoreCase("Version ")) { versionString = in.readLine(); } } catch (FileNotFoundException e) { logError("No versions.txt file."); versionString = "unknown"; } catch (IOException e) { logError("IO Exception reading versions.txt" + e); versionString = "unknown"; } finally { if (fileReader != null) { try { fileReader.close(); } catch (IOException ignored) {} } if (in != null) { try { in.close(); } catch (IOException ignored) {} } } String version = "unknown"; if (versionString != null) { try { version = versionString.substring(8); } catch (Exception e) { version = "unknown"; } } return version; } public static int compare(String a, String b) { return new Version(a).compareTo(new Version(b)); } } class Version implements Comparable { private final String version; public Version(String version) { this.version = version.replaceAll("Alpha", ".A.").replaceAll("Beta", ".B.").replaceAll("\\s++", ".").replaceAll( "\\.++", "\\."); } public boolean isAlpha() { return (version.matches(".*(A|a).*")); } public boolean isBeta() { return (version.matches(".*(B|b).*")); } public boolean isFinal() { return !(isAlpha() || isBeta()); } public int compareTo(Object o) { if (o == null) { throw new IllegalArgumentException(); } if (o instanceof String) { return compareTo(new Version((String) o)); } else if (o instanceof Version) { Version v = (Version) o; if (version.equalsIgnoreCase(v.version)) { return 0; } String[] left = version.split("[. \t]"); String[] right = v.version.split("[. \t]"); return compare(left, right); } else { throw new IllegalArgumentException("The input object must be a String or Version object"); } } private int compare(String[] left, String[] right) { int i = 0; for (i = 0; i < left.length && i < right.length; i++) { int res = left[i].compareToIgnoreCase(right[i]); if (res != 0) { return res; } } if (left.length > right.length) { if (left[i].equals("B") || left[i].equals("A")) { return -1; } return 1; } if (left.length < right.length) { if (right[i].equals("B") || right[i].equals("A")) { return 1; } return -1; } return 0; } @Override public String toString() { return version; } } robocode/robocode/robocode/manager/BrowserManager.java0000644000175000017500000000335111130241112022413 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Rewritten *******************************************************************************/ package robocode.manager; import robocode.io.FileUtil; import java.io.IOException; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ public class BrowserManager { private static final String browserCommand; static { if (System.getProperty("os.name").toLowerCase().startsWith("windows")) { browserCommand = "rundll32 url.dll, FileProtocolHandler"; } else { browserCommand = "browser.sh"; } } public static void openURL(String url) throws IOException { url = FileUtil.quoteFileName(url); final String command = browserCommand + ' ' + url; ProcessBuilder pb = new ProcessBuilder(command.split(" ")); pb.directory(FileUtil.getCwd()); Process p = pb.start(); try { p.waitFor(); } catch (InterruptedException e) { // Immediately reasserts the exception by interrupting the caller thread itself Thread.currentThread().interrupt(); } if (p.exitValue() < 0) { throw new IOException( "Unable to launch " + browserCommand + ". Please check it, or launch " + url + " in your browser."); } } } robocode/robocode/robocode/manager/LookAndFeelManager.java0000644000175000017500000000324211130241112023112 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen * - Initial API and implementation *******************************************************************************/ package robocode.manager; import javax.swing.*; import java.util.Locale; /** * Manager for setting the Look and Feel of the Robocode GUI. * * @author Flemming N. Larsen (original) */ public class LookAndFeelManager { /** * Sets the Look and Feel (LAF). This method first try to set the LAF to the * system's LAF. If this fails, it try to use the cross platform LAF. * If this also fails, the LAF will not be changed. */ public static void setLookAndFeel() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Throwable t) { // Work-around for problems with setting Look and Feel described here: // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6468089 Locale.setDefault(Locale.US); try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Throwable t2) { // For some reason Ubuntu 7 can cause a NullPointerException when trying to getting the LAF System.err.println("Could not set the Look and Feel (LAF). The default LAF is used instead"); } } } } robocode/robocode/robocode/manager/RobocodeProperties.java0000644000175000017500000010401311130241112023303 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Added option for visible ground, visible explosions, visible explosion * debris, antialiasing, text antialiasing, rendering method, and method * for getting the combined rendering hints * - Changed the FPS methods into TPS methods, but added the "Display FPS in * titlebar" option * - Added sound options * - Added common options for showing battle result and append when saving * results * - Added PropertyListener allowing listeners to retrieve events when a * property is changed * - Removed "Allow color changes" option as this is always possible with * the current rendering engine * - Added common option for enabling replay recording * - Updated to use methods from the Logger, which replaces logger methods * that have been (re)moved from the robocode.util.Utils class * - Added file paths to theme, background, and end-of-battle music + * file path for sound effects like gunshot, robot death etc. * - Added SortedProperties class in order to sort the keys/fields of the * Robocode properties file * - Added "Buffer images" Render Option * Nathaniel Troutman * - Added missing removePropertyListener() method *******************************************************************************/ package robocode.manager; import robocode.io.Logger; import java.awt.*; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.*; import java.util.List; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Nathaniel Troutman (contributor) */ public class RobocodeProperties { // Default SFX files private final static String DEFAULT_FILE_GUNSHOT_SFX = "/resources/sounds/zap.wav", DEFAULT_FILE_ROBOT_COLLISION_SFX = "/resources/sounds/13831_adcbicycle_22.wav", DEFAULT_FILE_WALL_COLLISION_SFX = DEFAULT_FILE_ROBOT_COLLISION_SFX, DEFAULT_FILE_ROBOT_DEATH_SFX = "/resources/sounds/explode.wav", DEFAULT_FILE_BULLET_HITS_ROBOT_SFX = "/resources/sounds/shellhit.wav", DEFAULT_FILE_BULLET_HITS_BULLET_SFX = DEFAULT_FILE_BULLET_HITS_ROBOT_SFX; // View Options (Arena) private boolean optionsViewRobotEnergy = true, optionsViewRobotNames = true, optionsViewScanArcs = false, optionsViewExplosions = true, optionsViewGround = true, optionsViewExplosionDebris = true; // View Options (Turns Per Second) private boolean optionsViewTPS = true, optionsViewFPS = true; // Rendering Options private int optionsRenderingAntialiasing = 0, // 0 = default, 1 = on, 2 = off optionsRenderingTextAntialiasing = 0, // 0 = default, 1 = on, 2 = off optionsRenderingMethod = 0, // 0 = default, 1 = speed, 2 = quality optionsRenderingNoBuffers = 2, // 1 = single buffering, 2 = double buffering, 3 = tripple buffering optionsBattleDesiredTPS = 30; private boolean optionsRenderingBufferImages = true, optionsRenderingForceBulletColor = false; // Sound Options (Sound Effects) private boolean optionsSoundEnableSound = false, optionsSoundEnableGunshot = true, optionsSoundEnableBulletHit = true, optionsSoundEnableRobotDeath = true, optionsSoundEnableWallCollision = true, optionsSoundEnableRobotCollision = true; // Sound Options (Mixer) private String optionsSoundMixer = "DirectAudioDevice"; private boolean optionsSoundEnableMixerVolume = true, optionsSoundEnableMixerPan = true; // Development Options private String optionsDevelopmentPath = ""; // Common Options private boolean optionsCommonShowResults = true, optionsCommonAppendWhenSavingResults = true, optionsCommonEnableReplayRecording = false; // Team Options private boolean optionsTeamShowTeamRobots = false; // Music files private String fileThemeMusic = "", fileBackgroundMusic = "", fileEndOfBattleMusic = ""; // SFX files private String fileGunshotSfx = DEFAULT_FILE_GUNSHOT_SFX, fileRobotCollisionSfx = DEFAULT_FILE_ROBOT_COLLISION_SFX, fileWallCollisionSfx = DEFAULT_FILE_WALL_COLLISION_SFX, fileRobotDeathSfx = DEFAULT_FILE_ROBOT_DEATH_SFX, fileBulletHitsRobotSfx = DEFAULT_FILE_BULLET_HITS_ROBOT_SFX, fileBulletHitsBulletSfx = DEFAULT_FILE_BULLET_HITS_BULLET_SFX; // Robocode internals private String lastRunVersion = ""; private Date versionChecked; private long robotFilesystemQuota = 200000; private long consoleQuota = 8192; private long cpuConstant = -1; // Number of Rounds private int numberOfRounds = 10; private final Properties props = new SortedProperties(); private final SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy H:mm:ss"); private final static String OPTIONS_VIEW_ROBOTNAMES = "robocode.options.view.robotNames", OPTIONS_VIEW_SCANARCS = "robocode.options.view.scanArcs", OPTIONS_VIEW_ROBOTENERGY = "robocode.options.view.robotEnergy", OPTIONS_VIEW_GROUND = "robocode.options.view.ground", OPTIONS_VIEW_TPS = "robocode.options.view.TPS", OPTIONS_VIEW_FPS = "robocode.options.view.FPS", OPTIONS_VIEW_EXPLOSIONS = "robocode.options.view.explosions", OPTIONS_VIEW_EXPLOSION_DEBRIS = "robocode.options.view.explosionDebris", OPTIONS_BATTLE_DESIREDTPS = "robocode.options.battle.desiredTPS", OPTIONS_RENDERING_ANTIALIASING = "robocode.options.rendering.antialiasing", OPTIONS_RENDERING_TEXT_ANTIALIASING = "robocode.options.rendering.text.antialiasing", OPTIONS_RENDERING_METHOD = "robocode.options.rendering.method", OPTIONS_RENDERING_NO_BUFFERS = "robocode.options.rendering.noBuffers", OPTIONS_RENDERING_BUFFER_IMAGES = "robocode.options.rendering.bufferImages", OPTIONS_RENDERING_FORCE_BULLET_COLOR = "robocode.options.rendering.forceBulletColor", OPTIONS_SOUND_ENABLESOUND = "robocode.options.sound.enableSound", OPTIONS_SOUND_ENABLEGUNSHOT = "robocode.options.sound.enableGunshot", OPTIONS_SOUND_ENABLEBULLETHIT = "robocode.options.sound.enableBulletHit", OPTIONS_SOUND_ENABLEROBOTDEATH = "robocode.options.sound.enableRobotDeath", OPTIONS_SOUND_ENABLEWALLCOLLISION = "robocode.options.sound.enableWallCollision", OPTIONS_SOUND_ENABLEROBOTCOLLISION = "robocode.options.sound.enableRobotCollision", OPTIONS_SOUND_MIXER = "robocode.options.sound.mixer", OPTIONS_SOUND_ENABLEMIXERVOLUME = "robocode.options.sound.enableMixerVolume", OPTIONS_SOUND_ENABLEMIXERPAN = "robocode.options.sound.enableMixerPan", OPTIONS_COMMON_SHOW_RESULTS = "robocode.options.common.showResults", OPTIONS_COMMON_APPEND_WHEN_SAVING_RESULTS = "robocode.options.common.appendWhenSavingResults", OPTIONS_COMMON_ENABLE_REPLAY_RECORDING = "robocode.options.common.enableReplayRecording", OPTIONS_TEAM_SHOWTEAMROBOTS = "robocode.options.team.showTeamRobots", FILE_THEME_MUSIC = "robocode.file.music.theme", FILE_BACKGROUND_MUSIC = "robocode.file.music.background", FILE_END_OF_BATTLE_MUSIC = "robocode.file.music.endOfBattle", FILE_GUNSHOT_SFX = "robocode.file.sfx.gunshot", FILE_ROBOT_COLLISION_SFX = "robocode.file.sfx.robotCollision", FILE_WALL_COLLISION_SFX = "robocode.file.sfx.wallCollision", FILE_ROBOT_DEATH_SFX = "robocode.file.sfx.robotDeath", FILE_BULLET_HITS_ROBOT_SFX = "robocode.file.sfx.bulletHitsRobot", FILE_BULLET_HITS_BULLET_SFX = "robocode.file.sfx.bulletHitsBullet", OPTIONS_DEVELOPMENT_PATH = "robocode.options.development.path", VERSIONCHECKED = "robocode.versionchecked", ROBOT_FILESYSTEM_QUOTA = "robocode.robot.filesystem.quota", CONSOLE_QUOTA = "robocode.console.quota", CPU_CONSTANT = "robocode.cpu.constant", LAST_RUN_VERSION = "robocode.version.lastrun", NUMBER_OF_ROUNDS = "robocode.numberOfBattles"; private final RobocodeManager manager; private final RenderingHints renderingHints = new RenderingHints(new HashMap()); private final List listeners = new ArrayList(); public RobocodeProperties(RobocodeManager manager) { this.manager = manager; } /** * Gets the optionsViewRobotNames. * * @return Returns a boolean */ public boolean getOptionsViewRobotNames() { return optionsViewRobotNames; } /** * Sets the optionsViewRobotNames. * * @param optionsViewRobotNames The optionsViewRobotNames to set */ public void setOptionsViewRobotNames(boolean optionsViewRobotNames) { this.optionsViewRobotNames = optionsViewRobotNames; props.setProperty(OPTIONS_VIEW_ROBOTNAMES, "" + optionsViewRobotNames); } /** * Gets the optionsViewScanArcs. * * @return Returns a boolean */ public boolean getOptionsViewScanArcs() { return optionsViewScanArcs; } /** * Sets the optionsViewScanArcs. * * @param optionsViewScanArcs The optionsViewScanArcs to set */ public void setOptionsViewScanArcs(boolean optionsViewScanArcs) { this.optionsViewScanArcs = optionsViewScanArcs; props.setProperty(OPTIONS_VIEW_SCANARCS, "" + optionsViewScanArcs); } /** * Gets the optionsViewRobotEnergy. * * @return Returns a boolean */ public boolean getOptionsViewRobotEnergy() { return optionsViewRobotEnergy; } /** * Sets the optionsViewRobotEnergy. * * @param optionsViewRobotEnergy The optionsViewRobotEnergy to set */ public void setOptionsViewRobotEnergy(boolean optionsViewRobotEnergy) { this.optionsViewRobotEnergy = optionsViewRobotEnergy; props.setProperty(OPTIONS_VIEW_ROBOTENERGY, "" + optionsViewRobotEnergy); } /** * Gets the optionsViewGround. * * @return Returns a boolean */ public boolean getOptionsViewGround() { return optionsViewGround; } /** * Sets the optionsViewGround. * * @param optionsViewGround The optionsViewGround to set */ public void setOptionsViewGround(boolean optionsViewGround) { this.optionsViewGround = optionsViewGround; props.setProperty(OPTIONS_VIEW_GROUND, "" + optionsViewGround); } /** * Gets the optionsViewTPS. * * @return Returns a boolean */ public boolean getOptionsViewTPS() { return optionsViewTPS; } /** * Sets the optionsViewTPS. * * @param optionsViewTPS The optionsViewTPS to set */ public void setOptionsViewTPS(boolean optionsViewTPS) { this.optionsViewTPS = optionsViewTPS; props.setProperty(OPTIONS_VIEW_TPS, "" + optionsViewTPS); } /** * Gets the optionsViewFPS. * * @return Returns a boolean */ public boolean getOptionsViewFPS() { return optionsViewFPS; } /** * Sets the optionsViewFPS. * * @param optionsViewFPS The optionsViewFPS to set */ public void setOptionsViewFPS(boolean optionsViewFPS) { this.optionsViewFPS = optionsViewFPS; props.setProperty(OPTIONS_VIEW_FPS, "" + optionsViewFPS); } /** * Gets the optionsViewExplosions. * * @return Returns a boolean */ public boolean getOptionsViewExplosions() { return optionsViewExplosions; } /** * Sets the optionsViewExplosions. * * @param optionsViewExplosions The optionsViewExplosions to set */ public void setOptionsViewExplosions(boolean optionsViewExplosions) { this.optionsViewExplosions = optionsViewExplosions; props.setProperty(OPTIONS_VIEW_EXPLOSIONS, "" + optionsViewExplosions); } /** * Gets the optionsViewExplosionDebris. * * @return Returns a boolean */ public boolean getOptionsViewExplosionDebris() { return optionsViewExplosionDebris; } /** * Sets the optionsViewExplosionDebris. * * @param optionsViewExplosionDebris The optionsViewExplosionDebris to set */ public void setOptionsViewExplosionDebris(boolean optionsViewExplosionDebris) { this.optionsViewExplosionDebris = optionsViewExplosionDebris; props.setProperty(OPTIONS_VIEW_EXPLOSION_DEBRIS, "" + optionsViewExplosionDebris); } /** * Gets the optionsRenderingAntialiasing. * * @return Returns an int */ public int getOptionsRenderingAntialiasing() { return optionsRenderingAntialiasing; } /** * Sets the optionsRenderingAntialiasing. * * @param optionsRenderingAntialiasing The optionsRenderingAntialiasing to set */ public void setOptionsRenderingAntialiasing(int optionsRenderingAntialiasing) { this.optionsRenderingAntialiasing = optionsRenderingAntialiasing; props.setProperty(OPTIONS_RENDERING_ANTIALIASING, "" + optionsRenderingAntialiasing); Object value; switch (optionsRenderingAntialiasing) { case 1: value = RenderingHints.VALUE_ANTIALIAS_ON; break; case 2: value = RenderingHints.VALUE_ANTIALIAS_OFF; break; case 0: default: value = RenderingHints.VALUE_ANTIALIAS_DEFAULT; } renderingHints.put(RenderingHints.KEY_ANTIALIASING, value); } /** * Gets the optionsRenderingTextAntialiasing. * * @return Returns an int */ public int getOptionsRenderingTextAntialiasing() { return optionsRenderingTextAntialiasing; } /** * Sets the optionsRenderingTextAntialiasing. * * @param optionsRenderingTextAntialiasing * The optionsRenderingTextAntialiasing to set */ public void setOptionsRenderingTextAntialiasing(int optionsRenderingTextAntialiasing) { this.optionsRenderingTextAntialiasing = optionsRenderingTextAntialiasing; props.setProperty(OPTIONS_RENDERING_TEXT_ANTIALIASING, "" + optionsRenderingTextAntialiasing); Object value; switch (optionsRenderingTextAntialiasing) { case 1: value = RenderingHints.VALUE_TEXT_ANTIALIAS_ON; break; case 2: value = RenderingHints.VALUE_TEXT_ANTIALIAS_OFF; break; case 0: default: value = RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT; } renderingHints.put(RenderingHints.KEY_TEXT_ANTIALIASING, value); } /** * Gets the optionsRenderingMethod. * * @return Returns an int */ public int getOptionsRenderingMethod() { return optionsRenderingMethod; } /** * Sets the optionsRenderingMethod. * * @param optionsRenderingMethod The optionsRenderingMethod to set */ public void setOptionsRenderingMethod(int optionsRenderingMethod) { this.optionsRenderingMethod = optionsRenderingMethod; props.setProperty(OPTIONS_RENDERING_METHOD, "" + optionsRenderingMethod); Object value; switch (optionsRenderingMethod) { case 1: value = RenderingHints.VALUE_RENDER_QUALITY; break; case 2: value = RenderingHints.VALUE_RENDER_SPEED; break; case 0: default: value = RenderingHints.VALUE_RENDER_DEFAULT; } renderingHints.put(RenderingHints.KEY_RENDERING, value); } /** * Gets the combined rendering options as RenderingHints. * * @return Returns an RenderingHints value */ public RenderingHints getRenderingHints() { return renderingHints; } /** * Gets the optionsRenderingNoBuffers * * @return Returns an int */ public int getOptionsRenderingNoBuffers() { return optionsRenderingNoBuffers; } /** * Sets the optionsRenderingNoBuffers. * * @param optionsRenderingNoBuffers The optionsRenderingNoBuffers to set */ public void setOptionsRenderingNoBuffers(int optionsRenderingNoBuffers) { this.optionsRenderingNoBuffers = optionsRenderingNoBuffers; props.setProperty(OPTIONS_RENDERING_NO_BUFFERS, "" + optionsRenderingNoBuffers); } /** * Gets the optionsRenderingBufferImages * * @return Returns a boolean */ public boolean getOptionsRenderingBufferImages() { return optionsRenderingBufferImages; } /** * Sets the optionsRenderingBufferImages. * * @param optionsRenderingBufferImages The optionsRenderingBufferImages to set */ public void setOptionsRenderingBufferImages(boolean optionsRenderingBufferImages) { this.optionsRenderingBufferImages = optionsRenderingBufferImages; props.setProperty(OPTIONS_RENDERING_BUFFER_IMAGES, "" + optionsRenderingBufferImages); } /** * Gets the optionsRenderingForceBulletColor * * @return Returns a boolean */ public boolean getOptionsRenderingForceBulletColor() { return optionsRenderingForceBulletColor; } /** * Sets the optionsRenderingForceBulletColor. * * @param optionsRenderingForceBulletColor * The optionsRenderingForceBulletColor to set */ public void setOptionsRenderingForceBulletColor(boolean optionsRenderingForceBulletColor) { this.optionsRenderingForceBulletColor = optionsRenderingForceBulletColor; props.setProperty(OPTIONS_RENDERING_FORCE_BULLET_COLOR, "" + optionsRenderingForceBulletColor); } /** * Gets the optionsBattleDesiredTPS. * * @return Returns a int */ public int getOptionsBattleDesiredTPS() { return optionsBattleDesiredTPS; } /** * Sets the optionsBattleDesiredTPS. * * @param optionsBattleDesiredTPS The optionsBattleDesiredTPS to set */ public void setOptionsBattleDesiredTPS(int optionsBattleDesiredTPS) { this.optionsBattleDesiredTPS = optionsBattleDesiredTPS; props.setProperty(OPTIONS_BATTLE_DESIREDTPS, "" + optionsBattleDesiredTPS); notifyDesiredTpsChanged(); } /** * Gets the optionsSoundEnableSound * * @return Returns a boolean */ public boolean getOptionsSoundEnableSound() { return optionsSoundEnableSound; } /** * Sets the optionsSoundEnableSound. * * @param optionsSoundEnableSound The optionsSoundEnableSound to set */ public void setOptionsSoundEnableSound(boolean optionsSoundEnableSound) { this.optionsSoundEnableSound = optionsSoundEnableSound; props.setProperty(OPTIONS_SOUND_ENABLESOUND, "" + optionsSoundEnableSound); } /** * Gets the optionsSoundEnableGunshot * * @return Returns a boolean */ public boolean getOptionsSoundEnableGunshot() { return optionsSoundEnableGunshot; } /** * Sets the optionsSoundEnableGunshot. * * @param optionsSoundEnableGunshot The optionsSoundEnableGunshot to set */ public void setOptionsSoundEnableGunshot(boolean optionsSoundEnableGunshot) { this.optionsSoundEnableGunshot = optionsSoundEnableGunshot; props.setProperty(OPTIONS_SOUND_ENABLEGUNSHOT, "" + optionsSoundEnableGunshot); } /** * Gets the optionsSoundEnableBulletHit * * @return Returns a boolean */ public boolean getOptionsSoundEnableBulletHit() { return optionsSoundEnableBulletHit; } /** * Sets the optionsSoundEnableBulletHit. * * @param optionsSoundEnableBulletHit The optionsSoundEnableBulletHit to set */ public void setOptionsSoundEnableBulletHit(boolean optionsSoundEnableBulletHit) { this.optionsSoundEnableBulletHit = optionsSoundEnableBulletHit; props.setProperty(OPTIONS_SOUND_ENABLEBULLETHIT, "" + optionsSoundEnableBulletHit); } /** * Gets the optionsSoundEnableRobotDeath * * @return Returns a boolean */ public boolean getOptionsSoundEnableRobotDeath() { return optionsSoundEnableRobotDeath; } /** * Sets the optionsSoundEnableRobotDeath. * * @param optionsSoundEnableRobotDeath The optionsSoundEnableRobotDeath to set */ public void setOptionsSoundEnableRobotDeath(boolean optionsSoundEnableRobotDeath) { this.optionsSoundEnableRobotDeath = optionsSoundEnableRobotDeath; props.setProperty(OPTIONS_SOUND_ENABLEROBOTDEATH, "" + optionsSoundEnableRobotDeath); } /** * Gets the optionsSoundEnableWallCollision * * @return Returns a boolean */ public boolean getOptionsSoundEnableWallCollision() { return optionsSoundEnableWallCollision; } /** * Sets the optionsSoundEnableWallCollision. * * @param optionsSoundEnableWallCollision * The optionsSoundEnableWallCollision to set */ public void setOptionsSoundEnableWallCollision(boolean optionsSoundEnableWallCollision) { this.optionsSoundEnableWallCollision = optionsSoundEnableWallCollision; props.setProperty(OPTIONS_SOUND_ENABLEWALLCOLLISION, "" + optionsSoundEnableWallCollision); } /** * Gets the optionsSoundEnableRobotCollision * * @return Returns a boolean */ public boolean getOptionsSoundEnableRobotCollision() { return optionsSoundEnableRobotCollision; } /** * Sets the optionsSoundEnableRobotCollision. * * @param optionsSoundEnableRobotCollision * The optionsSoundEnableRobotCollision to set */ public void setOptionsSoundEnableRobotCollision(boolean optionsSoundEnableRobotCollision) { this.optionsSoundEnableRobotCollision = optionsSoundEnableRobotCollision; props.setProperty(OPTIONS_SOUND_ENABLEROBOTCOLLISION, "" + optionsSoundEnableRobotCollision); } /** * Gets the optionsSoundEnableMixerVolume * * @return Returns a boolean */ public boolean getOptionsSoundEnableMixerVolume() { return optionsSoundEnableMixerVolume; } /** * Sets the optionsSoundMixer * * @param optionsSoundMixer The optionsSoundMixer to set */ public void setOptionsSoundMixer(String optionsSoundMixer) { this.optionsSoundMixer = optionsSoundMixer; props.setProperty(OPTIONS_SOUND_MIXER, optionsSoundMixer); } /** * Gets the optionsSoundMixer * * @return Returns a String */ public String getOptionsSoundMixer() { return optionsSoundMixer; } /** * Sets the optionsSoundEnableMixerVolume. * * @param optionsSoundEnableMixerVolume The optionsSoundEnableMixerVolume to set */ public void setOptionsSoundEnableMixerVolume(boolean optionsSoundEnableMixerVolume) { this.optionsSoundEnableMixerVolume = optionsSoundEnableMixerVolume; props.setProperty(OPTIONS_SOUND_ENABLEMIXERVOLUME, "" + optionsSoundEnableMixerVolume); } /** * Gets the optionsSoundEnableMixerPan * * @return Returns a boolean */ public boolean getOptionsSoundEnableMixerPan() { return optionsSoundEnableMixerPan; } /** * Sets the optionsSoundEnableMixerPan. * * @param optionsSoundEnableMixerPan The optionsSoundEnableMixerPan to set */ public void setOptionsSoundEnableMixerPan(boolean optionsSoundEnableMixerPan) { this.optionsSoundEnableMixerPan = optionsSoundEnableMixerPan; props.setProperty(OPTIONS_SOUND_ENABLEMIXERPAN, "" + optionsSoundEnableMixerPan); } public boolean getOptionsTeamShowTeamRobots() { return optionsTeamShowTeamRobots; } public void setOptionsTeamShowTeamRobots(boolean optionsTeamShowTeamRobots) { this.optionsTeamShowTeamRobots = optionsTeamShowTeamRobots; props.setProperty(OPTIONS_TEAM_SHOWTEAMROBOTS, "" + optionsTeamShowTeamRobots); } public String getFileThemeMusic() { return fileThemeMusic; } public String getFileBackgroundMusic() { return fileBackgroundMusic; } public String getFileEndOfBattleMusic() { return fileEndOfBattleMusic; } public String getFileGunshotSfx() { return fileGunshotSfx; } public String getBulletHitsRobotSfx() { return fileBulletHitsRobotSfx; } public String getBulletHitsBulletSfx() { return fileBulletHitsBulletSfx; } public String getRobotDeathSfx() { return fileRobotDeathSfx; } public String getRobotCollisionSfx() { return fileRobotCollisionSfx; } public String getWallCollisionSfx() { return fileWallCollisionSfx; } /** * Gets the versionChecked. * * @return Returns a String */ public Date getVersionChecked() { return (versionChecked != null) ? (Date) versionChecked.clone() : null; } /** * Sets the versionChecked. * * @param versionChecked The versionChecked to set */ public void setVersionChecked(Date versionChecked) { this.versionChecked = (versionChecked != null) ? (Date) versionChecked.clone() : null; props.setProperty(VERSIONCHECKED, dateFormat.format(new Date())); } /** * Gets the robotFilesystemQuota. * * @return Returns a long */ public long getRobotFilesystemQuota() { return robotFilesystemQuota; } /** * Sets the robotFilesystemQuota. * * @param robotFilesystemQuota The robotFilesystemQuota to set */ public void setRobotFilesystemQuota(long robotFilesystemQuota) { this.robotFilesystemQuota = robotFilesystemQuota; props.setProperty(ROBOT_FILESYSTEM_QUOTA, "" + robotFilesystemQuota); } /** * Gets the consoleQuota. * * @return Returns a long */ public long getConsoleQuota() { return consoleQuota; } /** * Sets the consoleQuota. * * @param consoleQuota The consoleQuota to set */ public void setConsoleQuota(long consoleQuota) { this.consoleQuota = consoleQuota; props.setProperty(CONSOLE_QUOTA, "" + consoleQuota); } /** * Gets the cpuConstant. * * @return Returns a long */ public long getCpuConstant() { return cpuConstant; } /** * Sets the cpuConstant. * * @param cpuConstant The cpuConstant to set */ public void setCpuConstant(long cpuConstant) { this.cpuConstant = cpuConstant; props.setProperty(CPU_CONSTANT, "" + cpuConstant); } /** * Gets the optionsDevelopmentPath * * @return Returns a String */ public String getOptionsDevelopmentPath() { return optionsDevelopmentPath; } /** * Sets the optionsDevelopmentPath. * * @param optionsDevelopmentPath The optionsDevelopmentPath to set */ public void setOptionsDevelopmentPath(String optionsDevelopmentPath) { if (!optionsDevelopmentPath.equals(this.optionsDevelopmentPath)) { manager.getRobotRepositoryManager().clearRobotList(); } this.optionsDevelopmentPath = optionsDevelopmentPath; props.setProperty(OPTIONS_DEVELOPMENT_PATH, optionsDevelopmentPath); } /** * Gets the optionsCommonShowResults * * @return Returns a boolean */ public boolean getOptionsCommonShowResults() { return optionsCommonShowResults; } /** * Sets the optionsCommonAppendWhenSavingResults. * * @param enable The optionsCommonAppendWhenSavingResults to set */ public void setOptionsCommonAppendWhenSavingResults(boolean enable) { this.optionsCommonAppendWhenSavingResults = enable; props.setProperty(OPTIONS_COMMON_APPEND_WHEN_SAVING_RESULTS, "" + enable); } /** * Gets the optionsCommonAppendWhenSavingResults * * @return Returns a boolean */ public boolean getOptionsCommonAppendWhenSavingResults() { return optionsCommonAppendWhenSavingResults; } /** * Sets the optionsCommonShowResults. * * @param enable The optionsCommonShowResults to set */ public void setOptionsCommonShowResults(boolean enable) { this.optionsCommonShowResults = enable; props.setProperty(OPTIONS_COMMON_SHOW_RESULTS, "" + enable); } /** * Gets the optionsCommonEnableReplayRecording * * @return Returns a boolean */ public boolean getOptionsCommonEnableReplayRecording() { return optionsCommonEnableReplayRecording; } /** * Sets the optionsCommonEnableReplayRecording. * * @param enable The optionsCommonEnableReplayRecording to set */ public void setOptionsCommonEnableReplayRecording(boolean enable) { this.optionsCommonEnableReplayRecording = enable; props.setProperty(OPTIONS_COMMON_ENABLE_REPLAY_RECORDING, "" + enable); notifyReplayRecordingChanged(); } public int getNumberOfRounds() { return numberOfRounds; } public void setNumberOfRounds(int numberOfRounds) { this.numberOfRounds = Math.max(1, numberOfRounds); props.setProperty(NUMBER_OF_ROUNDS, "" + this.numberOfRounds); } public void store(FileOutputStream out, String desc) throws IOException { props.store(out, desc); } public void load(FileInputStream in) throws IOException { props.load(in); optionsViewRobotNames = Boolean.valueOf(props.getProperty(OPTIONS_VIEW_ROBOTNAMES, "true")); optionsViewScanArcs = Boolean.valueOf(props.getProperty(OPTIONS_VIEW_SCANARCS, "false")); optionsViewRobotEnergy = Boolean.valueOf(props.getProperty(OPTIONS_VIEW_ROBOTENERGY, "true")); optionsViewGround = Boolean.valueOf(props.getProperty(OPTIONS_VIEW_GROUND, "true")); optionsViewTPS = Boolean.valueOf(props.getProperty(OPTIONS_VIEW_TPS, "true")); optionsViewFPS = Boolean.valueOf(props.getProperty(OPTIONS_VIEW_FPS, "true")); optionsViewExplosions = Boolean.valueOf(props.getProperty(OPTIONS_VIEW_EXPLOSIONS, "true")); optionsViewExplosionDebris = Boolean.valueOf(props.getProperty(OPTIONS_VIEW_EXPLOSION_DEBRIS, "true")); optionsBattleDesiredTPS = Integer.parseInt(props.getProperty(OPTIONS_BATTLE_DESIREDTPS, "30")); // set methods are used here in order to set the rendering hints, which must be rebuild setOptionsRenderingAntialiasing(Integer.parseInt(props.getProperty(OPTIONS_RENDERING_ANTIALIASING, "0"))); setOptionsRenderingTextAntialiasing( Integer.parseInt(props.getProperty(OPTIONS_RENDERING_TEXT_ANTIALIASING, "0"))); setOptionsRenderingMethod(Integer.parseInt(props.getProperty(OPTIONS_RENDERING_METHOD, "0"))); optionsRenderingNoBuffers = Integer.parseInt(props.getProperty(OPTIONS_RENDERING_NO_BUFFERS, "2")); optionsRenderingBufferImages = Boolean.valueOf(props.getProperty(OPTIONS_RENDERING_BUFFER_IMAGES, "true")); optionsRenderingForceBulletColor = Boolean.valueOf( props.getProperty(OPTIONS_RENDERING_FORCE_BULLET_COLOR, "false")); optionsSoundEnableSound = Boolean.valueOf(props.getProperty(OPTIONS_SOUND_ENABLESOUND, "false")); optionsSoundEnableGunshot = Boolean.valueOf(props.getProperty(OPTIONS_SOUND_ENABLEGUNSHOT, "true")); optionsSoundEnableBulletHit = Boolean.valueOf(props.getProperty(OPTIONS_SOUND_ENABLEBULLETHIT, "true")); optionsSoundEnableRobotDeath = Boolean.valueOf(props.getProperty(OPTIONS_SOUND_ENABLEROBOTDEATH, "true")); optionsSoundEnableRobotCollision = Boolean.valueOf(props.getProperty(OPTIONS_SOUND_ENABLEROBOTCOLLISION, "true")); optionsSoundEnableWallCollision = Boolean.valueOf(props.getProperty(OPTIONS_SOUND_ENABLEWALLCOLLISION, "true")); optionsSoundMixer = props.getProperty(OPTIONS_SOUND_MIXER, "DirectAudioDevice"); optionsSoundEnableMixerVolume = Boolean.valueOf(props.getProperty(OPTIONS_SOUND_ENABLEMIXERVOLUME, "true")); optionsSoundEnableMixerPan = Boolean.valueOf(props.getProperty(OPTIONS_SOUND_ENABLEMIXERPAN, "true")); optionsDevelopmentPath = props.getProperty(OPTIONS_DEVELOPMENT_PATH, ""); optionsCommonShowResults = Boolean.valueOf(props.getProperty(OPTIONS_COMMON_SHOW_RESULTS, "true")); optionsCommonAppendWhenSavingResults = Boolean.valueOf( props.getProperty(OPTIONS_COMMON_APPEND_WHEN_SAVING_RESULTS, "true")); optionsCommonEnableReplayRecording = Boolean.valueOf( props.getProperty(OPTIONS_COMMON_ENABLE_REPLAY_RECORDING, "false")); optionsTeamShowTeamRobots = Boolean.valueOf(props.getProperty(OPTIONS_TEAM_SHOWTEAMROBOTS, "false")); fileThemeMusic = props.getProperty(FILE_THEME_MUSIC); fileBackgroundMusic = props.getProperty(FILE_BACKGROUND_MUSIC); fileEndOfBattleMusic = props.getProperty(FILE_END_OF_BATTLE_MUSIC); fileGunshotSfx = props.getProperty(FILE_GUNSHOT_SFX, DEFAULT_FILE_GUNSHOT_SFX); fileRobotCollisionSfx = props.getProperty(FILE_ROBOT_COLLISION_SFX, DEFAULT_FILE_ROBOT_COLLISION_SFX); fileWallCollisionSfx = props.getProperty(FILE_WALL_COLLISION_SFX, DEFAULT_FILE_WALL_COLLISION_SFX); fileRobotDeathSfx = props.getProperty(FILE_ROBOT_DEATH_SFX, DEFAULT_FILE_ROBOT_DEATH_SFX); fileBulletHitsRobotSfx = props.getProperty(FILE_BULLET_HITS_ROBOT_SFX, DEFAULT_FILE_BULLET_HITS_ROBOT_SFX); fileBulletHitsBulletSfx = props.getProperty(FILE_BULLET_HITS_BULLET_SFX, DEFAULT_FILE_BULLET_HITS_BULLET_SFX); lastRunVersion = props.getProperty(LAST_RUN_VERSION, ""); props.remove("robocode.cpu.constant.1000"); try { versionChecked = dateFormat.parse(props.getProperty(VERSIONCHECKED)); } catch (Exception e) { Logger.logMessage("Initializing version check date."); setVersionChecked(new Date()); } robotFilesystemQuota = Long.parseLong(props.getProperty(ROBOT_FILESYSTEM_QUOTA, "" + 200000)); consoleQuota = Long.parseLong(props.getProperty(CONSOLE_QUOTA, "8192")); cpuConstant = Long.parseLong(props.getProperty(CPU_CONSTANT, "-1")); numberOfRounds = Integer.parseInt(props.getProperty(NUMBER_OF_ROUNDS, "10")); } public String getLastRunVersion() { return lastRunVersion; } /** * Sets the lastRunVersion. * * @param lastRunVersion The lastRunVersion to set */ public void setLastRunVersion(String lastRunVersion) { this.lastRunVersion = lastRunVersion; props.setProperty(LAST_RUN_VERSION, "" + lastRunVersion); } public void addPropertyListener(PropertyListener listener) { listeners.add(listener); } public void removePropertyListener(PropertyListener propertyListener) { listeners.remove(propertyListener); } private void notifyDesiredTpsChanged() { for (PropertyListener listener : listeners) { listener.desiredTpsChanged(optionsBattleDesiredTPS); } } private void notifyReplayRecordingChanged() { for (PropertyListener listener : listeners) { listener.enableReplayRecordingChanged(optionsCommonEnableReplayRecording); } } /** * Sorted properties used for sorting the keys for the properties file. * * @author Flemming N. Larsen */ private static class SortedProperties extends Properties { private static final long serialVersionUID = 1L; @SuppressWarnings("unchecked") @Override public Enumeration keys() { Enumeration keysEnum = super.keys(); Vector keyList = new Vector(); while (keysEnum.hasMoreElements()) { keyList.add((String) keysEnum.nextElement()); } Collections.sort(keyList); // noinspection RedundantCast return (Enumeration) keyList.elements(); } } /** * Property listener. * * @author Flemming N. Larsen */ public class PropertyListener { public void desiredTpsChanged(int tps) {} public void enableReplayRecordingChanged(boolean enabled) {} } } robocode/robocode/robocode/manager/RobocodeManager.java0000644000175000017500000002015711130241112022527 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup * - Added setEnableGUI() and isGUIEnabled() * - Updated to use methods from FileUtil and Logger, which replaces methods * that have been (re)moved from the robocode.util.Utils class * - Added access for the SoundManager * - Changed to use FileUtil.getRobocodeConfigFile() * - Added missing close() on FileInputStream and FileOutputStream * - Bugfix: When the intro battle has completed or is aborted the battle * properties are now reset to the default battle properties. This fixes * the issue were the initial robot positions are fixed in new battles * Nathaniel Troutman * - Bugfix: Added cleanup() to prevent memory leaks by removing circular * references * Pavel Savara * - uses interfaces of components *******************************************************************************/ package robocode.manager; import robocode.RobocodeFileOutputStream; import robocode.io.FileUtil; import robocode.io.Logger; import static robocode.io.Logger.logError; import robocode.recording.IRecordManager; import robocode.recording.RecordManager; import robocode.security.RobocodeSecurityManager; import robocode.security.RobocodeSecurityPolicy; import robocode.security.SecureInputStream; import robocode.security.SecurePrintStream; import robocode.sound.ISoundManager; import robocode.sound.SoundManager; import java.io.*; import java.security.Policy; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Nathaniel Troutman (contributor) */ public class RobocodeManager { private IBattleManager battleManager; private ICpuManager cpuManager; private IImageManager imageManager; private IRobotDialogManager robotDialogManager; private IRepositoryManager repositoryManager; private IThreadManager threadManager; private IWindowManager windowManager; private IVersionManager versionManager; private ISoundManager soundManager; private IRecordManager recordManager; private IHostManager hostManager; private final boolean slave; private RobocodeProperties properties; private boolean isGUIEnabled = true; private boolean isSoundEnabled = true; static { RobocodeManager.initStreams(); } public RobocodeManager(boolean slave) { this.slave = slave; } /** * Gets the battleManager. * * @return Returns a BattleManager */ public IBattleManager getBattleManager() { if (battleManager == null) { battleManager = new BattleManager(this); } return battleManager; } public IHostManager getHostManager() { if (hostManager == null) { hostManager = new HostManager(this); } return hostManager; } /** * Gets the robotManager. * * @return Returns a RobotListManager */ public IRepositoryManager getRobotRepositoryManager() { if (repositoryManager == null) { repositoryManager = new RobotRepositoryManager(this); } return repositoryManager; } /** * Gets the windowManager. * * @return Returns a WindowManager */ public IWindowManager getWindowManager() { if (windowManager == null) { windowManager = new WindowManager(this); } return windowManager; } /** * Gets the threadManager. * * @return Returns a ThreadManager */ public IThreadManager getThreadManager() { if (threadManager == null) { threadManager = new ThreadManager(); } return threadManager; } /** * Gets the robotDialogManager. * * @return Returns a RobotDialogManager */ public IRobotDialogManager getRobotDialogManager() { if (robotDialogManager == null) { robotDialogManager = new RobotDialogManager(this); } return robotDialogManager; } public RobocodeProperties getProperties() { if (properties == null) { properties = new RobocodeProperties(this); FileInputStream in = null; try { in = new FileInputStream(FileUtil.getRobocodeConfigFile()); properties.load(in); } catch (FileNotFoundException e) { logError("No " + FileUtil.getRobocodeConfigFile().getName() + ", using defaults."); } catch (IOException e) { logError("IO Exception reading " + FileUtil.getRobocodeConfigFile().getName() + ": " + e); } finally { if (in != null) { // noinspection EmptyCatchBlock try { in.close(); } catch (IOException e) {} } } } return properties; } public void saveProperties() { if (properties == null) { logError("Cannot save null robocode properties"); return; } FileOutputStream out = null; try { out = new FileOutputStream(FileUtil.getRobocodeConfigFile()); properties.store(out, "Robocode Properties"); } catch (IOException e) { Logger.logError(e); } finally { if (out != null) { // noinspection EmptyCatchBlock try { out.close(); } catch (IOException e) {} } } } /** * Gets the imageManager. * * @return Returns a ImageManager */ public IImageManager getImageManager() { if (imageManager == null) { imageManager = new ImageManager(this); } return imageManager; } /** * Gets the versionManager. * * @return Returns a VersionManager */ public IVersionManager getVersionManager() { if (versionManager == null) { versionManager = new VersionManager(this); } return versionManager; } /** * Gets the cpuManager. * * @return Returns a CpuManager */ public ICpuManager getCpuManager() { if (cpuManager == null) { cpuManager = new CpuManager(this); } return cpuManager; } /** * Gets the Sound Manager. * * @return Returns a SoundManager */ public ISoundManager getSoundManager() { if (soundManager == null) { soundManager = new SoundManager(this); } return soundManager; } /** * Gets the Battle Recoder. * * @return Returns a BattleRecoder */ public IRecordManager getRecordManager() { if (recordManager == null) { recordManager = new RecordManager(this); } return recordManager; } /** * Gets the slave. * * @return Returns a boolean */ public boolean isSlave() { return slave; } private static void initStreams() { PrintStream sysout = new SecurePrintStream(System.out, true); PrintStream syserr = new SecurePrintStream(System.err, true); InputStream sysin = new SecureInputStream(System.in); System.setOut(sysout); if (!System.getProperty("debug", "false").equals("true")) { System.setErr(syserr); } System.setIn(sysin); } public void initSecurity(boolean securityOn, boolean experimentalOn) { Thread.currentThread().setName("Application Thread"); RobocodeSecurityPolicy securityPolicy = new RobocodeSecurityPolicy(Policy.getPolicy()); Policy.setPolicy(securityPolicy); RobocodeSecurityManager securityManager = new RobocodeSecurityManager(Thread.currentThread(), getThreadManager(), securityOn, experimentalOn); System.setSecurityManager(securityManager); RobocodeFileOutputStream.setThreadManager(getThreadManager()); } public boolean isGUIEnabled() { return isGUIEnabled; } public void setEnableGUI(boolean enable) { isGUIEnabled = enable; } public boolean isSoundEnabled() { return isSoundEnabled && getProperties().getOptionsSoundEnableSound(); } public void setEnableSound(boolean enable) { isSoundEnabled = enable; } public void cleanup() { if (battleManager != null) { battleManager.cleanup(); battleManager = null; } if (hostManager != null) { hostManager.cleanup(); hostManager = null; } } } robocode/robocode/robocode/manager/HostManager.java0000644000175000017500000000204111130241112021700 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.manager; /** * @author Pavel Savara (original) */ public class HostManager implements IHostManager { private final RobocodeManager manager; HostManager(RobocodeManager manager) { this.manager = manager; } public long getRobotFilesystemQuota() { return manager.getProperties().getRobotFilesystemQuota(); } public IThreadManager getThreadManager() { return manager.getThreadManager(); } public void cleanup() {// TODO } } robocode/robocode/robocode/manager/RobotRepositoryManager.java0000644000175000017500000006544211130241112024166 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Replaced FileSpecificationVector with plain Vector * - Updated to use methods from WindowUtil, FileTypeFilter, FileUtil, Logger, * which replaces methods that have been (re)moved from the Utils class * - Changed to use FileUtil.getRobotsDir() * - Replaced multiple catch'es with a single catch in * getSpecificationsInDirectory() * - Minor optimizations * - Added missing close() on FileInputStream * - Changed updateRobotDatabase() to take the new JuniorRobot class into * account * - Bugfix: Ignore robots that reside in the .robotcache dir when the * robot.database is updated by updateRobotDatabase() * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap * - Changed so that the robot repository only adds .jar files from the root * of the robots folder and not from sub folders of the robots folder * Pavel Savara * - Re-work of robot interfaces * - detection of type of robot by overriden methods *******************************************************************************/ package robocode.manager; import robocode.Droid; import robocode.Robot; import robocode.dialog.WindowUtil; import robocode.io.FileTypeFilter; import robocode.io.FileUtil; import static robocode.io.Logger.logError; import static robocode.io.Logger.logMessage; import robocode.peer.robot.RobotClassManager; import robocode.repository.*; import robocode.robotinterfaces.*; import javax.swing.*; import java.awt.*; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseWheelEvent; import java.io.*; import java.lang.reflect.Method; import java.security.AccessControlException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.StringTokenizer; import java.util.jar.JarEntry; import java.util.jar.JarInputStream; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Robert D. Maupin (contributor) * @author Pavel Savara (contributor) */ public class RobotRepositoryManager implements IRepositoryManager { private FileSpecificationDatabase robotDatabase; private File robotsDirectory; private File robotCache; private Repository repository; private final RobocodeManager manager; private final List updatedJarList = Collections.synchronizedList( new ArrayList()); private boolean write; public RobotRepositoryManager(RobocodeManager manager) { this.manager = manager; } public File getRobotCache() { if (robotCache == null) { File oldRobotCache = new File(getRobotsDirectory(), "robotcache"); File newRobotCache = new File(getRobotsDirectory(), ".robotcache"); if (oldRobotCache.exists()) { oldRobotCache.renameTo(newRobotCache); } robotCache = newRobotCache; } return robotCache; } private FileSpecificationDatabase getRobotDatabase() { if (robotDatabase == null) { WindowUtil.setStatus("Reading robot database"); robotDatabase = new FileSpecificationDatabase(); try { robotDatabase.load(new File(getRobotsDirectory(), "robot.database")); } catch (FileNotFoundException e) { logMessage("Building robot database."); } catch (IOException e) { logMessage("Rebuilding robot database."); } catch (ClassNotFoundException e) { logMessage("Rebuilding robot database."); } } return robotDatabase; } public Repository getRobotRepository() { // Don't reload the repository // If we want to do that, set repository to null by calling clearRobotList(). if (repository != null) { return repository; } WindowUtil.setStatus("Refreshing robot database"); updatedJarList.clear(); // jarUpdated = false; boolean cacheWarning = false; // boolean changed = false; this.write = false; // Future... // Remove any deleted jars from robotcache repository = new Repository(); // Clean up cache -- delete nonexistent jar directories cleanupCache(); WindowUtil.setStatus("Cleaning up robot database"); cleanupDatabase(); String externalRobotsPath = manager.getProperties().getOptionsDevelopmentPath(); { StringTokenizer tokenizer = new StringTokenizer(externalRobotsPath, File.pathSeparator); while (tokenizer.hasMoreTokens()) { String tok = tokenizer.nextToken(); File f = new File(tok); if (!f.equals(getRobotsDirectory()) && !f.equals(getRobotCache()) && !f.equals(getRobotsDirectory().getParentFile())) { getSpecificationsInDirectory(f, f, "", true); } } } updatedJarList.clear(); File f = getRobotsDirectory(); WindowUtil.setStatus("Reading: " + f.getName()); if (f.exists() && f.isDirectory()) { // it better be! getSpecificationsInDirectory(f, f, "", true); } // This loop should not be changed to an for-each loop as the updated jar list // gets updated (jars are added) by the methods called in this loop, which can // cause a ConcurrentModificationException! // noinspection ForLoopReplaceableByForEach for (int i = 0; i < updatedJarList.size(); i++) { JarSpecification updatedJar = (JarSpecification) updatedJarList.get(i); processJar(updatedJar); updateRobotDatabase(updatedJar); write = true; } updatedJarList.clear(); f = getRobotCache(); WindowUtil.setStatus("Reading: " + getRobotCache()); if (f.exists() && f.isDirectory()) { // it better be! getSpecificationsInDirectory(f, f, "", false); } List fileSpecificationList = getRobotDatabase().getFileSpecifications(); if (write) { WindowUtil.setStatus("Saving robot database"); saveRobotDatabase(); } WindowUtil.setStatus("Adding robots to repository"); for (FileSpecification fs : fileSpecificationList) { if (fs instanceof TeamSpecification) { repository.add(fs); } else if (fs instanceof RobotFileSpecification) { if (verifyRobotName(fs.getName(), fs.getShortClassName())) { repository.add(fs); } } } if (cacheWarning) { JOptionPane.showMessageDialog(null, "Warning: Robocode has detected that the robotcache directory has been updated.\n" + "Robocode may delete or overwrite these files with no warning.\n" + "If you wish to update a robot in the robotcache directory,\n" + "You should copy it to your robots directory first.", "Unexpected robotcache update", JOptionPane.OK_OPTION); } WindowUtil.setStatus("Sorting repository"); repository.sortRobotSpecifications(); WindowUtil.setStatus(""); return repository; } private void cleanupCache() { File dir = getRobotCache(); File files[] = dir.listFiles(); if (files != null) { for (File file : files) { if (file.isDirectory() && file.getName().lastIndexOf(".jar_") == file.getName().length() - 5 || file.isDirectory() && file.getName().lastIndexOf(".zip_") == file.getName().length() - 5 || file.isDirectory() && file.getName().lastIndexOf(".jar") == file.getName().length() - 4) { File f = new File(getRobotsDirectory(), file.getName().substring(0, file.getName().length() - 1)); // startsWith robocode added in 0.99.5 to fix bug with people // downloading robocode-setup.jar to the robots dir if (f.exists() && !f.getName().startsWith("robocode")) { continue; } WindowUtil.setStatus("Cleaning up cache: Removing " + file); FileUtil.deleteDir(file); } } } } private void cleanupDatabase() { List externalDirectories = new ArrayList(); String externalPath = manager.getProperties().getOptionsDevelopmentPath(); StringTokenizer tokenizer = new StringTokenizer(externalPath, File.pathSeparator); while (tokenizer.hasMoreTokens()) { File f = new File(tokenizer.nextToken()); externalDirectories.add(f); } List fileSpecificationList = getRobotDatabase().getFileSpecifications(); for (FileSpecification fs : fileSpecificationList) { if (fs.exists()) { File rootDir = fs.getRootDir(); if (rootDir == null) { logError("Warning, null root directory: " + fs.getFilePath()); continue; } if (!fs.isDevelopmentVersion()) { continue; } if (rootDir.equals(getRobotsDirectory())) { continue; } if (externalDirectories.contains(rootDir)) { continue; } // This one is from the developmentPath; make sure that path still exists. getRobotDatabase().remove(fs.getFilePath()); write = true; } else { getRobotDatabase().remove(fs.getFilePath()); write = true; } } } public File getRobotsDirectory() { if (robotsDirectory == null) { robotsDirectory = FileUtil.getRobotsDir(); } return robotsDirectory; } public void clearRobotList() { repository = null; } private List getSpecificationsInDirectory(File rootDir, File dir, String prefix, boolean isDevelopmentDirectory) { List robotList = Collections.synchronizedList(new ArrayList()); // Order is important? String fileTypes[] = { ".class", ".jar", ".team", ".jar.zip" }; File files[] = dir.listFiles(new FileTypeFilter(fileTypes)); if (files == null) { logError("Warning: Unable to read directory " + dir); return robotList; } for (File file : files) { String fileName = file.getName(); if (file.isDirectory()) { if (prefix.length() == 0) { int jidx = fileName.lastIndexOf(".jar_"); if (jidx > 0 && jidx == fileName.length() - 5) { robotList.addAll(getSpecificationsInDirectory(file, file, "", isDevelopmentDirectory)); } else { jidx = fileName.lastIndexOf(".zip_"); if (jidx > 0 && jidx == fileName.length() - 5) { robotList.addAll(getSpecificationsInDirectory(file, file, "", isDevelopmentDirectory)); } else { robotList.addAll( getSpecificationsInDirectory(rootDir, file, prefix + fileName + ".", isDevelopmentDirectory)); } } } else { int odidx = fileName.indexOf("data."); if (odidx == 0) { renameOldDataDir(dir, file); continue; } int didx = fileName.lastIndexOf(".data"); if (didx > 0 && didx == fileName.length() - 5) { continue; } // Don't process .data dirs robotList.addAll( getSpecificationsInDirectory(rootDir, file, prefix + fileName + ".", isDevelopmentDirectory)); } } else if (fileName.indexOf("$") < 0 && fileName.indexOf("robocode") != 0) { FileSpecification cachedSpecification = getRobotDatabase().get(file.getPath()); FileSpecification fileSpecification; // if cachedSpecification is null, then this is a new file if (cachedSpecification != null && cachedSpecification.isSameFile(file.getPath(), file.length(), file.lastModified())) { // this file is unchanged fileSpecification = cachedSpecification; } else { fileSpecification = FileSpecification.createSpecification(this, file, rootDir, prefix, isDevelopmentDirectory); updateRobotDatabase(fileSpecification); write = true; if (fileSpecification instanceof JarSpecification) { String path = fileSpecification.getFilePath(); path = path.substring(0, path.lastIndexOf(File.separatorChar)); path = path.substring(path.lastIndexOf(File.separatorChar) + 1); if (path.equalsIgnoreCase("robots")) { // this file is changed updatedJarList.add(fileSpecification); } } } if (fileSpecification.isValid()) { robotList.add(fileSpecification); } } } return robotList; } private void saveRobotDatabase() { if (robotDatabase == null) { logError("Cannot save a null robot database."); return; } try { robotDatabase.store(new File(getRobotsDirectory(), "robot.database")); } catch (IOException e) { logError("IO Exception writing robot database: ", e); } } private void updateRobotDatabase(FileSpecification fileSpecification) { // Ignore files located in the robot cache String name = fileSpecification.getName(); if (name == null || name.startsWith(".robotcache.")) { return; } String key = fileSpecification.getFilePath(); if (fileSpecification instanceof RobotFileSpecification) { RobotFileSpecification robotFileSpecification = (RobotFileSpecification) fileSpecification; try { RobotClassManager robotClassManager = new RobotClassManager(robotFileSpecification); Class robotClass = robotClassManager.getRobotClassLoader().loadRobotClass( robotClassManager.getFullClassName(), true); robotFileSpecification.setUid(robotClassManager.getUid()); if (robotFileSpecification.isValid()) { if (!java.lang.reflect.Modifier.isAbstract(robotClass.getModifiers())) { if (Droid.class.isAssignableFrom(robotClass)) { robotFileSpecification.setDroid(true); } if (ITeamRobot.class.isAssignableFrom(robotClass)) { robotFileSpecification.setTeamRobot(true); } if (IAdvancedRobot.class.isAssignableFrom(robotClass)) { robotFileSpecification.setAdvancedRobot(true); } if (IInteractiveRobot.class.isAssignableFrom(robotClass)) { // in this case we make sure that robot don't waste time if (checkMethodOverride(robotClass, Robot.class, "getInteractiveEventListener") || checkMethodOverride(robotClass, Robot.class, "onKeyPressed", KeyEvent.class) || checkMethodOverride(robotClass, Robot.class, "onKeyReleased", KeyEvent.class) || checkMethodOverride(robotClass, Robot.class, "onKeyTyped", KeyEvent.class) || checkMethodOverride(robotClass, Robot.class, "onMouseClicked", MouseEvent.class) || checkMethodOverride(robotClass, Robot.class, "onMouseEntered", MouseEvent.class) || checkMethodOverride(robotClass, Robot.class, "onMouseExited", MouseEvent.class) || checkMethodOverride(robotClass, Robot.class, "onMousePressed", MouseEvent.class) || checkMethodOverride(robotClass, Robot.class, "onMouseReleased", MouseEvent.class) || checkMethodOverride(robotClass, Robot.class, "onMouseMoved", MouseEvent.class) || checkMethodOverride(robotClass, Robot.class, "onMouseDragged", MouseEvent.class) || checkMethodOverride(robotClass, Robot.class, "onMouseWheelMoved", MouseWheelEvent.class) ) { robotFileSpecification.setInteractiveRobot(true); } } if (IPaintRobot.class.isAssignableFrom(robotClass)) { if (checkMethodOverride(robotClass, Robot.class, "getPaintEventListener") || checkMethodOverride(robotClass, Robot.class, "onPaint", Graphics2D.class) ) { robotFileSpecification.setPaintRobot(true); } } if (Robot.class.isAssignableFrom(robotClass) && !robotFileSpecification.isAdvancedRobot()) { robotFileSpecification.setStandardRobot(true); } if (IJuniorRobot.class.isAssignableFrom(robotClass)) { robotFileSpecification.setJuniorRobot(true); if (robotFileSpecification.isAdvancedRobot()) { throw new AccessControlException( robotFileSpecification.getName() + ": Junior robot should not implement IAdvancedRobot interface."); } } if (IBasicRobot.class.isAssignableFrom(robotClass)) { if (!robotFileSpecification.isAdvancedRobot() && !robotFileSpecification.isJuniorRobot()) { robotFileSpecification.setStandardRobot(true); } updateNoDuplicates(robotFileSpecification); return; } } } getRobotDatabase().put(key, new ClassSpecification(robotFileSpecification)); } catch (Throwable t) { robotFileSpecification.setValid(false); getRobotDatabase().put(key, robotFileSpecification); logError(robotFileSpecification.getName() + ": Got an error with this class: " + t.toString()); // just message here } } else if (fileSpecification instanceof JarSpecification) { getRobotDatabase().put(key, fileSpecification); } else if (fileSpecification instanceof TeamSpecification) { updateNoDuplicates(fileSpecification); } else if (fileSpecification instanceof ClassSpecification) { getRobotDatabase().put(key, fileSpecification); } else { System.out.println("Update robot database not possible for type " + fileSpecification.getFileType()); } } private boolean checkMethodOverride(Class robotClass, Class knownBase, String name, Class... parameterTypes) { if (knownBase.isAssignableFrom(robotClass)) { final Method getInteractiveEventListener; try { getInteractiveEventListener = robotClass.getMethod(name, parameterTypes); } catch (NoSuchMethodException e) { return false; } if (getInteractiveEventListener.getDeclaringClass().equals(knownBase)) { return false; } } return true; } private void updateNoDuplicates(FileSpecification spec) { String key = spec.getFilePath(); WindowUtil.setStatus("Updating database: " + spec.getName()); if (!spec.isDevelopmentVersion() && getRobotDatabase().contains(spec.getFullClassName(), spec.getVersion(), false)) { FileSpecification existingSpec = getRobotDatabase().get(spec.getFullClassName(), spec.getVersion(), false); if (existingSpec == null) { getRobotDatabase().put(key, spec); } else if (!existingSpec.getUid().equals(spec.getUid())) { if (existingSpec.getFilePath().equals(spec.getFilePath())) { getRobotDatabase().put(key, spec); } else // if (duplicatePrompt) { File existingSource = existingSpec.getJarFile(); // getRobotsDirectory(),getRobotCache()); File newSource = spec.getJarFile(); // getRobotsDirectory(),getRobotCache()); if (existingSource != null && newSource != null) { long t1 = existingSource.lastModified(); long t2 = newSource.lastModified(); if (t1 > t2) { existingSource.renameTo(new File(existingSource.getPath() + ".invalid")); getRobotDatabase().remove(existingSpec.getFilePath()); getRobotDatabase().put(key, spec); conflictLog( "Renaming " + existingSource + " to invalid, as it contains a robot " + spec.getName() + " which conflicts with the same robot in " + newSource); } else { newSource.renameTo(new File(newSource.getPath() + ".invalid")); conflictLog( "Renaming " + newSource + " to invalid, as it contains a robot " + spec.getName() + " which conflicts with the same robot in " + existingSource); } } } } else { spec.setDuplicate(true); getRobotDatabase().put(key, spec); } } else { getRobotDatabase().put(key, spec); } } private void conflictLog(String s) { logError(s); File f = new File(FileUtil.getCwd(), "conflict.logError"); FileWriter writer = null; BufferedWriter out = null; try { writer = new FileWriter(f.getPath(), true); out = new BufferedWriter(writer); out.write(s + "\n"); } catch (IOException e) { logError("Warning: Could not write to conflict.logError"); } finally { if (out != null) { try { out.close(); } catch (IOException ignored) {} } if (writer != null) { try { writer.close(); } catch (IOException ignored) {} } } } private void processJar(JarSpecification jarSpecification) { String key = jarSpecification.getFilePath(); File cache = getRobotCache(); if (!cache.exists()) { cache.mkdirs(); File readme = new File(cache, "README"); try { PrintStream out = new PrintStream(new FileOutputStream(readme)); out.println("WARNING!"); out.println("Do not edit files in this directory."); out.println("Any changes you make here may be lost."); out.println("If you want to make changes to these robots,"); out.println("then copy the files into your robots directory"); out.println("and make the changes there."); out.close(); } catch (IOException ignored) {} } WindowUtil.setStatus("Extracting .jar: " + jarSpecification.getFileName()); File dest; if (jarSpecification.getRootDir().equals(getRobotsDirectory())) { dest = new File(getRobotCache(), jarSpecification.getFileName() + "_"); } else { dest = new File(jarSpecification.getRootDir(), jarSpecification.getFileName() + "_"); } if (dest.exists()) { FileUtil.deleteDir(dest); } dest.mkdirs(); File f = new File(jarSpecification.getFilePath()); extractJar(f, dest, "Extracting .jar: " + jarSpecification.getFileName(), true, true, true); getRobotDatabase().put(key, jarSpecification); } public int extractJar(File f, File dest, String statusPrefix, boolean extractJars, boolean close, boolean alwaysReplace) { FileInputStream fis = null; try { fis = new FileInputStream(f); JarInputStream jarIS = new JarInputStream(fis); return extractJar(jarIS, dest, statusPrefix, extractJars, close, alwaysReplace); } catch (IOException e) { logError("Exception reading " + f + ": " + e); } finally { if (fis != null) { try { fis.close(); } catch (IOException ignored) {} } } return 16; } public int extractJar(JarInputStream jarIS, File dest, String statusPrefix, boolean extractJars, boolean close, boolean alwaysReplace) { int rc = 0; boolean always = alwaysReplace; byte buf[] = new byte[2048]; try { JarEntry entry = jarIS.getNextJarEntry(); while (entry != null) { WindowUtil.setStatus(statusPrefix + " (" + entry.getName() + ")"); if (entry.isDirectory()) { File dir = new File(dest, entry.getName()); dir.mkdirs(); } else { File out = new File(dest, entry.getName()); if (out.exists() && !always) { Object[] options = { "Yes to All", "Yes", "No", "Cancel" }; int r = JOptionPane.showOptionDialog(null, entry.getName() + " exists. Replace?", "Warning", JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, options, options[0]); if (r == 0) { always = true; } else if (r == 2) { WindowUtil.setStatus(entry.getName() + " skipped."); entry = jarIS.getNextJarEntry(); continue; } else if (r == 3) { entry = null; rc = -1; continue; } } File parentDirectory = new File(out.getParent()).getCanonicalFile(); parentDirectory.mkdirs(); FileOutputStream fos = null; try { fos = new FileOutputStream(out); int num; while ((num = jarIS.read(buf, 0, 2048)) != -1) { fos.write(buf, 0, num); } FileDescriptor fd = fos.getFD(); fd.sync(); } finally { if (fos != null) { fos.close(); } } if (entry.getTime() >= 0) { out.setLastModified(entry.getTime()); } if (entry.getName().indexOf("/") < 0 && FileUtil.getFileType(entry.getName()).equals(".jar")) { FileSpecification fileSpecification = FileSpecification.createSpecification(this, out, parentDirectory, "", false); updatedJarList.add(fileSpecification); } } entry = jarIS.getNextJarEntry(); } if (close) { jarIS.close(); } } catch (IOException e) { logError("IOException " + statusPrefix + ": ", e); } return rc; } public boolean cleanupOldSampleRobots(boolean delete) { // TODO: Needs to be updated? String oldSampleList[] = { "Corners.java", "Crazy.java", "Fire.java", "MyFirstRobot.java", "RamFire.java", "SittingDuck.java", "SpinBot.java", "Target.java", "Tracker.java", "TrackFire.java", "Walls.java", "Corners.class", "Crazy.class", "Fire.class", "MyFirstRobot.class", "RamFire.class", "SittingDuck.class", "SpinBot.class", "Target.class", "Target$1.class", "Tracker.class", "TrackFire.class", "Walls.class" }; File robotDir = getRobotsDirectory(); if (robotDir.isDirectory()) { for (File sampleBot : robotDir.listFiles()) { if (!sampleBot.isDirectory()) { for (String oldSampleBot : oldSampleList) { if (sampleBot.getName().equals(oldSampleBot)) { logMessage("Deleting old sample file: " + sampleBot.getName()); if (delete) { sampleBot.delete(); } else { return true; } } } } } } return false; } private void renameOldDataDir(File dir, File f) { String name = f.getName(); String botName = name.substring(name.indexOf(".") + 1); File newFile = new File(dir, botName + ".data"); if (!newFile.exists()) { File oldFile = new File(dir, name); logError("Renaming " + oldFile.getName() + " to " + newFile.getName()); oldFile.renameTo(newFile); } } // Allowed maximum length for a robot's full package name private final static int MAX_FULL_PACKAGE_NAME_LENGTH = 32; // Allowed maximum length for a robot's short class name private final static int MAX_SHORT_CLASS_NAME_LENGTH = 32; public boolean verifyRobotName(String robotName, String shortClassName) { int lIndex = robotName.indexOf("."); String rootPackage = robotName; if (lIndex > 0) { rootPackage = robotName.substring(0, lIndex); if (rootPackage.equalsIgnoreCase("robocode")) { logError("Robot " + robotName + " ignored. You cannot use package " + rootPackage); return false; } if (rootPackage.length() > MAX_FULL_PACKAGE_NAME_LENGTH) { final String message = "Robot " + robotName + " has package name too long. " + MAX_FULL_PACKAGE_NAME_LENGTH + " characters maximum please."; logError(message); return false; } } else {// TODO every robot should be in package, right. Kick thim out. } if (shortClassName != null && shortClassName.length() > MAX_SHORT_CLASS_NAME_LENGTH) { final String message = "Robot " + robotName + " has classname too long. " + MAX_SHORT_CLASS_NAME_LENGTH + " characters maximum please."; logError(message); return false; } return true; } /** * Gets the manager. * * @return Returns a RobocodeManager */ public RobocodeManager getManager() { return manager; } } robocode/robocode/robocode/manager/WindowManager.java0000644000175000017500000003346711130241112022252 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Added showInBrowser() for displaying content from an URL * - Added showRoboWiki(), showYahooGroupRobocode(), showRobocodeRepository() * - Removed the Thread.sleep(diff) from showSplashScreen() * - Updated to use methods from the FileUtil, which replaces file operations * that have been (re)moved from the robocode.util.Utils class * - Changed showRobocodeFrame() to take a visible parameter * - Added packCenterShow() for windows where the window position and * dimension should not be read or saved to window.properties * Luis Crespo & Flemming N. Larsen * - Added showRankingDialog() *******************************************************************************/ package robocode.manager; import robocode.control.events.BattleCompletedEvent; import robocode.control.events.IBattleListener; import robocode.control.snapshot.ITurnSnapshot; import robocode.dialog.*; import robocode.editor.RobocodeEditor; import robocode.io.FileUtil; import robocode.packager.RobotPackager; import robocode.ui.AwtBattleAdaptor; import robocode.ui.BattleResultsTableModel; import robocode.battle.BattleProperties; import javax.swing.*; import javax.swing.filechooser.FileFilter; import java.awt.*; import java.io.File; import java.io.IOException; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Luis Crespo (contributor) */ public class WindowManager implements IWindowManager { private final static int TIMER_TICKS_PER_SECOND = 50; private final AwtBattleAdaptor awtAdaptor; private RobocodeEditor robocodeEditor; private RobotPackager robotPackager; private RobotExtractor robotExtractor; private RobocodeFrame robocodeFrame; private final RobocodeManager manager; private RankingDialog rankingDialog; public WindowManager(RobocodeManager manager) { this.manager = manager; awtAdaptor = new AwtBattleAdaptor(manager.getBattleManager(), TIMER_TICKS_PER_SECOND, true); // we will set UI better priority than robots and battle have EventQueue.invokeLater(new Runnable() { public void run() { try { Thread.currentThread().setPriority(Thread.NORM_PRIORITY + 2); } catch (SecurityException ex) {// that's a pity } } }); } public synchronized void addBattleListener(IBattleListener listener) { awtAdaptor.addListener(listener); } public synchronized void removeBattleListener(IBattleListener listener) { awtAdaptor.removeListener(listener); } public ITurnSnapshot getLastSnapshot() { return awtAdaptor.getLastSnapshot(); } public int getFPS() { return awtAdaptor.getFPS(); } public RobocodeFrame getRobocodeFrame() { if (robocodeFrame == null) { robocodeFrame = new RobocodeFrame(manager); } return robocodeFrame; } public void showRobocodeFrame(boolean visible) { RobocodeFrame frame = getRobocodeFrame(); if (visible) { // Pack frame to size all components WindowUtil.packCenterShow(frame); WindowUtil.setStatusLabel(frame.getStatusLabel()); } else { frame.setVisible(false); } } public void showAboutBox() { packCenterShow(new AboutBox(getRobocodeFrame(), manager), true); } public String showBattleOpenDialog(final String defExt, final String name) { JFileChooser chooser = new JFileChooser(manager.getBattleManager().getBattlePath()); chooser.setFileFilter( new FileFilter() { @Override public boolean accept(File pathname) { return pathname.isDirectory() || pathname.getName().toLowerCase().lastIndexOf(defExt.toLowerCase()) == pathname.getName().length() - defExt.length(); } @Override public String getDescription() { return name; } }); if (chooser.showOpenDialog(getRobocodeFrame()) == JFileChooser.APPROVE_OPTION) { return chooser.getSelectedFile().getPath(); } return null; } public String saveBattleDialog(String path, final String defExt, final String name) { File f = new File(path); JFileChooser chooser; chooser = new JFileChooser(f); javax.swing.filechooser.FileFilter filter = new javax.swing.filechooser.FileFilter() { @Override public boolean accept(File pathname) { return pathname.isDirectory() || pathname.getName().toLowerCase().lastIndexOf(defExt.toLowerCase()) == pathname.getName().length() - defExt.length(); } @Override public String getDescription() { return name; } }; chooser.setFileFilter(filter); int rv = chooser.showSaveDialog(manager.getWindowManager().getRobocodeFrame()); String result = null; if (rv == JFileChooser.APPROVE_OPTION) { result = chooser.getSelectedFile().getPath(); int idx = result.lastIndexOf('.'); String extension = ""; if (idx > 0) { extension = result.substring(idx); } if (!(extension.equalsIgnoreCase(defExt))) { result += defExt; } } return result; } public void showVersionsTxt() { showInBrowser( "file://" + new File(FileUtil.getCwd(), "").getAbsoluteFile() + System.getProperty("file.separator") + "versions.txt"); } public void showHelpApi() { showInBrowser( "file://" + new File(FileUtil.getCwd(), "").getAbsoluteFile() + System.getProperty("file.separator") + "javadoc" + System.getProperty("file.separator") + "index.html"); } public void showFaq() { showInBrowser("http://robocode.sourceforge.net/help/robocode.faq.txt"); } public void showOnlineHelp() { showInBrowser("http://robocode.sourceforge.net/help"); } public void showJavaDocumentation() { showInBrowser("http://java.sun.com/j2se/1.5.0/docs"); } public void showRobocodeHome() { showInBrowser("http://robocode.sourceforge.net"); } public void showRoboWiki() { showInBrowser("http://robowiki.net"); } public void showYahooGroupRobocode() { showInBrowser("http://groups.yahoo.com/group/robocode"); } public void showRobocodeRepository() { showInBrowser("http://robocoderepository.com"); } public void showOptionsPreferences() { try { manager.getBattleManager().pauseBattle(); WindowUtil.packCenterShow(getRobocodeFrame(), new PreferencesDialog(manager)); } finally { manager.getBattleManager().resumeIfPausedBattle(); // THIS is just dirty hack-fix of more complex problem with desiredTPS and pausing. resumeBattle() belongs here. } } public void showResultsDialog(BattleCompletedEvent event) { packCenterShow(new ResultsDialog(manager, event.getSortedResults(), event.getBattleRules().getNumRounds()), true); } public void showRankingDialog(boolean visible) { if (rankingDialog == null) { rankingDialog = new RankingDialog(manager); if (visible) { packCenterShow(rankingDialog, true); } else { rankingDialog.dispose(); } } else { if (visible) { packCenterShow(rankingDialog, false); } else { rankingDialog.dispose(); } } } public void showRobocodeEditor() { if (robocodeEditor == null) { robocodeEditor = new robocode.editor.RobocodeEditor(manager); WindowUtil.packCenterShow(robocodeEditor); } else { robocodeEditor.setVisible(true); } } public void showRobotPackager() { if (robotPackager != null) { robotPackager.dispose(); robotPackager = null; } robotPackager = new robocode.packager.RobotPackager(manager.getRobotRepositoryManager()); WindowUtil.packCenterShow(robotPackager); } public void showRobotExtractor(JFrame owner) { if (robotExtractor != null) { robotExtractor.dispose(); robotExtractor = null; } robotExtractor = new robocode.dialog.RobotExtractor(owner, manager.getRobotRepositoryManager()); WindowUtil.packCenterShow(robotExtractor); } public void showSplashScreen() { RcSplashScreen splashScreen = new RcSplashScreen(manager); packCenterShow(splashScreen, true); WindowUtil.setStatusLabel(splashScreen.getSplashLabel()); manager.getRobotRepositoryManager().getRobotRepository(); WindowUtil.setStatusLabel(splashScreen.getSplashLabel()); manager.getImageManager(); manager.getCpuManager().getCpuConstant(); WindowUtil.setStatus(""); WindowUtil.setStatusLabel(null); splashScreen.dispose(); } public void showNewBattleDialog(BattleProperties battleProperties) { try { manager.getBattleManager().pauseBattle(); WindowUtil.packCenterShow(getRobocodeFrame(), new NewBattleDialog(manager, battleProperties)); } finally { manager.getBattleManager().resumeBattle(); } } public boolean closeRobocodeEditor() { return robocodeEditor == null || !robocodeEditor.isVisible() || robocodeEditor.close(); } /** * Gets the manager. * * @return Returns a RobocodeManager */ public RobocodeManager getManager() { return manager; } public void showCreateTeamDialog() { TeamCreator teamCreator = new TeamCreator(manager.getRobotRepositoryManager()); WindowUtil.packCenterShow(teamCreator); } public void showImportRobotDialog() { JFileChooser chooser = new JFileChooser(); chooser.setFileFilter(new FileFilter() { @Override public boolean accept(File pathname) { if (pathname.isHidden()) { return false; } if (pathname.isDirectory()) { return true; } String filename = pathname.getName(); if (filename.equals("robocode.jar")) { return false; } int idx = filename.lastIndexOf('.'); String extension = ""; if (idx >= 0) { extension = filename.substring(idx); } return extension.equalsIgnoreCase(".jar") || extension.equalsIgnoreCase(".zip"); } @Override public String getDescription() { return "Jar Files"; } }); chooser.setDialogTitle( "Select the robot .jar file to copy to " + manager.getRobotRepositoryManager().getRobotsDirectory()); if (chooser.showDialog(getRobocodeFrame(), "Import") == JFileChooser.APPROVE_OPTION) { File inputFile = chooser.getSelectedFile(); String fileName = chooser.getSelectedFile().getName(); int idx = fileName.lastIndexOf('.'); String extension = ""; if (idx >= 0) { extension = fileName.substring(idx); } if (!extension.equalsIgnoreCase(".jar")) { fileName += ".jar"; } File outputFile = new File(manager.getRobotRepositoryManager().getRobotsDirectory(), fileName); if (inputFile.equals(outputFile)) { JOptionPane.showMessageDialog(getRobocodeFrame(), outputFile.getName() + " is already in the robots directory!"); return; } if (outputFile.exists()) { if (JOptionPane.showConfirmDialog(getRobocodeFrame(), outputFile + " already exists. Overwrite?", "Warning", JOptionPane.YES_NO_OPTION) == JOptionPane.NO_OPTION) { return; } } if (JOptionPane.showConfirmDialog(getRobocodeFrame(), "Robocode will now copy " + inputFile.getName() + " to " + outputFile.getParent(), "Import robot", JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION) { try { FileUtil.copy(inputFile, outputFile); manager.getRobotRepositoryManager().clearRobotList(); JOptionPane.showMessageDialog(getRobocodeFrame(), "Robot imported successfully."); } catch (IOException e) { JOptionPane.showMessageDialog(getRobocodeFrame(), "Import failed: " + e); } } } } /** * Shows a web page using the browser manager. * * @param url The URL of the web page */ private void showInBrowser(String url) { try { BrowserManager.openURL(url); } catch (IOException e) { JOptionPane.showMessageDialog(getRobocodeFrame(), e.getMessage(), "Unable to open browser!", JOptionPane.ERROR_MESSAGE); } } public void showSaveResultsDialog(BattleResultsTableModel tableModel) { JFileChooser chooser = new JFileChooser(); chooser.setFileFilter(new FileFilter() { @Override public boolean accept(File pathname) { if (pathname.isHidden()) { return false; } if (pathname.isDirectory()) { return true; } String filename = pathname.getName(); int idx = filename.lastIndexOf('.'); String extension = ""; if (idx >= 0) { extension = filename.substring(idx); } return extension.equalsIgnoreCase(".csv"); } @Override public String getDescription() { return "Comma Separated Value (CSV) File Format"; } }); chooser.setDialogTitle("Save battle results"); if (chooser.showSaveDialog(getRobocodeFrame()) == JFileChooser.APPROVE_OPTION) { String filename = chooser.getSelectedFile().getPath(); if (!filename.endsWith(".csv")) { filename += ".csv"; } boolean append = manager.getProperties().getOptionsCommonAppendWhenSavingResults(); tableModel.saveToFile(filename, append); } } /** * Packs, centers, and shows the specified window on the screen. * @param window the window to pack, center, and show * @param center {@code true} if the window must be centered; {@code false} otherwise */ private void packCenterShow(Window window, boolean center) { Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); window.pack(); if (center) { window.setLocation((screenSize.width - window.getWidth()) / 2, (screenSize.height - window.getHeight()) / 2); } window.setVisible(true); } } robocode/robocode/robocode/manager/IVersionManager.java0000644000175000017500000000143511130241112022527 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.manager; /** * @author Pavel Savara (original) */ public interface IVersionManager { void checkUpdateCheck(); boolean checkForNewVersion(boolean notifyNoUpdate); String getVersion(); } robocode/robocode/robocode/manager/IWindowManager.java0000644000175000017500000000415711130241112022355 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.manager; import robocode.control.events.BattleCompletedEvent; import robocode.control.events.IBattleListener; import robocode.control.snapshot.ITurnSnapshot; import robocode.dialog.RobocodeFrame; import robocode.ui.BattleResultsTableModel; import robocode.battle.BattleProperties; import javax.swing.*; /** * @author Pavel Savara (original) */ public interface IWindowManager { RobocodeFrame getRobocodeFrame(); void showRobocodeFrame(boolean visible); void showAboutBox(); String showBattleOpenDialog(String defExt, String name); String saveBattleDialog(String path, String defExt, String name); void showVersionsTxt(); void showHelpApi(); void showFaq(); void showOnlineHelp(); void showJavaDocumentation(); void showRobocodeHome(); void showRoboWiki(); void showYahooGroupRobocode(); void showRobocodeRepository(); void showOptionsPreferences(); void showResultsDialog(BattleCompletedEvent event); void showRankingDialog(boolean visible); void showRobocodeEditor(); void showRobotPackager(); void showRobotExtractor(JFrame owner); void showSplashScreen(); void showNewBattleDialog(BattleProperties battleProperties); boolean closeRobocodeEditor(); void showCreateTeamDialog(); void showImportRobotDialog(); void showSaveResultsDialog(BattleResultsTableModel tableModel); void addBattleListener(IBattleListener listener); void removeBattleListener(IBattleListener listener); int getFPS(); ITurnSnapshot getLastSnapshot(); } robocode/robocode/robocode/manager/CpuManager.java0000644000175000017500000000620311130241112021516 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Updated to use methods from WindowUtil and Logger, which replaces * methods that have been (re)moved from the robocode.util.Utils class * - Added calculateCpuConstant() used for (re)calculating the CPU constant * - Added setCpuConstant() for calculating and setting the CPU constant * - Limited the CPU constant to be >= millis granularity in order to prevent * robots from skipping turns as the granularity might be coarse * - Changed CPU constant to be measured in nanoseconds instead of * milliseconds * Robert D. Maupin * - The "heavy math" algorithm for calculation the CPU constant * Pavel Savara * - Cheating the optimizer with the setCpuConstant() so the optimizer does * not throw the rational computation away *******************************************************************************/ package robocode.manager; import robocode.dialog.WindowUtil; import robocode.io.Logger; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Robert Maupin (contributor) * @author Pavel Savara (contributor) */ public class CpuManager implements ICpuManager { private final static int APPROXIMATE_CYCLES_ALLOWED = 6250; private final static int TEST_PERIOD_MILLIS = 5000; private long cpuConstant = -1; private final RobocodeManager manager; public CpuManager(RobocodeManager manager) { this.manager = manager; } public long getCpuConstant() { if (cpuConstant == -1) { cpuConstant = manager.getProperties().getCpuConstant(); if (cpuConstant == -1) { calculateCpuConstant(); } } return cpuConstant; } public void calculateCpuConstant() { WindowUtil.setStatus("Estimating CPU speed, please wait..."); setCpuConstant(); Logger.logMessage( "Each robot will be allowed a maximum of " + cpuConstant + " nanoseconds per turn on this system."); manager.getProperties().setCpuConstant(cpuConstant); manager.saveProperties(); WindowUtil.setStatus(""); } private void setCpuConstant() { long count = 0; double d = 0; long start = System.currentTimeMillis(); while (System.currentTimeMillis() - start < TEST_PERIOD_MILLIS) { d += Math.hypot(Math.sqrt(Math.abs(Math.log(Math.atan(Math.random())))), Math.cbrt(Math.abs(Math.random() * 10))) / Math.exp(Math.random()); count++; } // to cheat optimizer, almost never happen if (d == 0.0) { Logger.logMessage("bingo!"); } cpuConstant = Math.max(1, (long) (1000000.0 * APPROXIMATE_CYCLES_ALLOWED * TEST_PERIOD_MILLIS / count)); } } robocode/robocode/robocode/manager/ImageManager.java0000644000175000017500000001642411130241112022017 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Rewritten to support new rendering engine and to use dynamic coloring * instead of static color index * Titus Chen * - Added and integrated RenderCache which removes the eldest image from the * cache of rendered robot images when max. capacity (MAX_NUM_COLORS) of * images has been reached *******************************************************************************/ package robocode.manager; import robocode.gfx.ImageUtil; import robocode.gfx.RenderImage; import java.awt.*; import java.util.*; import java.util.List; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Titus Chen (contributor) */ public class ImageManager implements IImageManager { private final RobocodeManager manager; private Image[] groundImages; private RenderImage[][] explosionRenderImages; private RenderImage debriseRenderImage; private Image bodyImage; private Image gunImage; private Image radarImage; private static final int MAX_NUM_COLORS = 256; private HashMap robotBodyImageCache; private HashMap robotGunImageCache; private HashMap robotRadarImageCache; public ImageManager(RobocodeManager manager) { this.manager = manager; initialize(); } public void initialize() { // Note that initialize could be called in order to reset all images (image buffering) // Reset image cache groundImages = new Image[5]; explosionRenderImages = null; debriseRenderImage = null; bodyImage = null; gunImage = null; radarImage = null; robotBodyImageCache = new RenderCache(); robotGunImageCache = new RenderCache(); robotRadarImageCache = new RenderCache(); // Read images into the cache getBodyImage(); getGunImage(); getRadarImage(); getExplosionRenderImage(0, 0); } public Image getGroundTileImage(int index) { if (groundImages[index] == null) { groundImages[index] = getImage("/resources/images/ground/blue_metal/blue_metal_" + index + ".png"); } return groundImages[index]; } public RenderImage getExplosionRenderImage(int which, int frame) { if (explosionRenderImages == null) { int numExplosion, numFrame; String filename; List> explosions = new ArrayList>(); boolean done = false; for (numExplosion = 1; !done; numExplosion++) { List frames = new ArrayList(); for (numFrame = 1;; numFrame++) { filename = "/resources/images/explosion/explosion" + numExplosion + '-' + numFrame + ".png"; if (ClassLoader.class.getResource(filename) == null) { if (numFrame == 1) { done = true; } else { explosions.add(frames); } break; } frames.add(new RenderImage(getImage(filename))); } } numExplosion = explosions.size(); explosionRenderImages = new RenderImage[numExplosion][]; for (int i = numExplosion - 1; i >= 0; i--) { explosionRenderImages[i] = explosions.get(i).toArray(new RenderImage[explosions.size()]); } } return explosionRenderImages[which][frame]; } public RenderImage getExplosionDebriseRenderImage() { if (debriseRenderImage == null) { debriseRenderImage = new RenderImage(getImage("/resources/images/ground/explode_debris.png")); } return debriseRenderImage; } private Image getImage(String filename) { Image image = ImageUtil.getImage(filename); if (manager.getProperties().getOptionsRenderingBufferImages()) { image = ImageUtil.getBufferedImage(image); } return image; } /** * Gets the body image * Loads from disk if necessary. * * @return the body image */ private Image getBodyImage() { if (bodyImage == null) { bodyImage = getImage("/resources/images/body.png"); } return bodyImage; } /** * Gets the gun image * Loads from disk if necessary. * * @return the gun image */ private Image getGunImage() { if (gunImage == null) { gunImage = getImage("/resources/images/turret.png"); } return gunImage; } /** * Gets the radar image * Loads from disk if necessary. * * @return the radar image */ private Image getRadarImage() { if (radarImage == null) { radarImage = getImage("/resources/images/radar.png"); } return radarImage; } public RenderImage getColoredBodyRenderImage(Integer color) { RenderImage img = robotBodyImageCache.get(color); if (img == null) { img = new RenderImage(ImageUtil.createColouredRobotImage(getBodyImage(), new Color(color, true))); robotBodyImageCache.put(color, img); } return img; } public RenderImage getColoredGunRenderImage(Integer color) { RenderImage img = robotGunImageCache.get(color); if (img == null) { img = new RenderImage(ImageUtil.createColouredRobotImage(getGunImage(), new Color(color, true))); robotGunImageCache.put(color, img); } return img; } public RenderImage getColoredRadarRenderImage(Integer color) { RenderImage img = robotRadarImageCache.get(color); if (img == null) { img = new RenderImage(ImageUtil.createColouredRobotImage(getRadarImage(), new Color(color, true))); robotRadarImageCache.put(color, img); } return img; } /** * Class used for caching rendered robot parts in various colors. * * @author Titus Chen */ @SuppressWarnings("serial") private static class RenderCache extends LinkedHashMap { /* Note about initial capacity: * To avoid rehashing (inefficient though probably unavoidable), initial * capacity must be at least 1 greater than the maximum capacity. * However, initial capacities are set to the smallest power of 2 greater * than or equal to the passed argument, resulting in 512 with this code. * I was not aware of this before, but notice: the current implementation * behaves similarly. The simple solution would be to set maximum capacity * to 255, but the problem with doing so is that in a battle of 256 robots * of different colors, the net result would end up being real-time * rendering due to the nature of access ordering. However, 256 robot * battles are rarely fought. */ private static final int INITIAL_CAPACITY = MAX_NUM_COLORS + 1; private static final float LOAD_FACTOR = 1; public RenderCache() { /* The "true" parameter needed for access-order: * when cache fills, the least recently accessed entry is removed */ super(INITIAL_CAPACITY, LOAD_FACTOR, true); } @Override protected boolean removeEldestEntry(Map.Entry eldest) { return size() > MAX_NUM_COLORS; } } } robocode/robocode/robocode/manager/IBattleManager.java0000644000175000017500000000566211130241112022323 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen * - Initial implementation *******************************************************************************/ package robocode.manager; import robocode.Event; import robocode.battle.BattleProperties; import robocode.control.BattleSpecification; import robocode.control.events.IBattleListener; /** * Used for controlling a robot from the e.g. the UI or RobocodeEngine. * * @author Flemming N. Larsen * @since 1.6.1 */ public interface IBattleManager { /** * Kills the robot. * * @param robotIndex the index of the robot to kill. */ void killRobot(int robotIndex); /** * Enable or disable the robot paintings. * * @param robotIndex the index of the robot that must have its paintings enabled or disabled. * @param enable {@code true} if paint must be enabled; {@code false} otherwise. */ void setPaintEnabled(int robotIndex, boolean enable); /** * Enable or disable the robot paintings using the RobocodeSG coordinate system * with the y-axis reversed compared to the coordinate system used in Robocode. * * @param robotIndex the index of the robot that must use RobocodeSG paintings. * @param enable {@code true} if RobocodeSG paint coordinate system must be * enabled when painting the robot; {@code false} otherwise. */ void setSGPaintEnabled(int robotIndex, boolean enable); /** * Sends an interactive event for the robot. * * @param event the interactive event that has occurred to the robot. */ void sendInteractiveEvent(Event event); void startNewBattle(BattleProperties battleProperties, boolean waitTillOver); void startNewBattle(BattleSpecification spec, boolean waitTillOver); void waitTillOver(); void nextTurn(); void prevTurn(); void pauseBattle(); void resumeBattle(); void togglePauseResumeBattle(); void resumeIfPausedBattle(); // TODO refactor, remove void pauseIfResumedBattle(); // TODO refactor, remove void restart(); void replay(); void stop(boolean waitTillEnd); void addListener(IBattleListener listener); void removeListener(IBattleListener listener); boolean isManagedTPS(); void setManagedTPS(boolean value); String getBattlePath(); String getBattleFilename(); void setBattleFilename(String newBattleFilename); BattleProperties loadBattleProperties(); void saveBattleProperties(); BattleProperties getBattleProperties(); void setDefaultBattleProperties(); void cleanup(); } robocode/robocode/robocode/manager/RobotDialogManager.java0000644000175000017500000000647011130241112023202 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Renamed 'enum' variables to allow compiling with Java 1.5 * - Replaced RobotPeerVector with plain Vector * - Ported to Java 5.0 * - Fixed possible ConcurrentModificationException issues * - Bugfixed setActiveBattle() and reset() which removed dialogs via * remove(dialog) instead of remove(name) * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap *******************************************************************************/ package robocode.manager; import robocode.control.snapshot.IRobotSnapshot; import robocode.dialog.*; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * @author Mathew A. Nelson (orinal) * @author Flemming N. Larsen (contributor) * @author Robert D. Maupin (contributor) */ public class RobotDialogManager implements IRobotDialogManager { public static final int MAX_PRE_ATTACHED = 25; private final Map robotDialogMap = new ConcurrentHashMap(); private BattleDialog battleDialog = null; private final RobocodeManager manager; public RobotDialogManager(RobocodeManager manager) { super(); this.manager = manager; } public void trim(List robots) { // new ArrayList in order to prevent ConcurrentModificationException for (String name : new ArrayList(robotDialogMap.keySet())) { boolean found = false; for (IRobotSnapshot robot : robots) { if (robot.getName().equals(name)) { found = true; break; } } if (!found) { RobotDialog dialog = robotDialogMap.get(name); robotDialogMap.remove(name); dialog.dispose(); dialog.detach(); } } } public void reset() { for (String name : robotDialogMap.keySet()) { RobotDialog dialog = robotDialogMap.get(name); if (!dialog.isVisible()) { robotDialogMap.remove(name); dialog.detach(); dialog.dispose(); } } } public RobotDialog getRobotDialog(RobotButton robotButton, String name, boolean create) { RobotDialog robotDialog = robotDialogMap.get(name); if (create && robotDialog == null) { if (robotDialogMap.size() > MAX_PRE_ATTACHED) { reset(); } robotDialog = new RobotDialog(manager, robotButton); robotDialog.pack(); WindowUtil.place(robotDialog); robotDialogMap.put(name, robotDialog); } return robotDialog; } public BattleDialog getBattleDialog(BattleButton battleButton, boolean create) { if (create && battleDialog == null) { battleDialog = new BattleDialog(manager, battleButton); battleDialog.pack(); WindowUtil.place(battleDialog); } return battleDialog; } } robocode/robocode/robocode/manager/IThreadManager.java0000644000175000017500000000205511130241112022310 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.manager; import robocode.peer.proxies.IHostedThread; /** * @author Pavel Savara (original) */ public interface IThreadManager { void addThreadGroup(ThreadGroup g, IHostedThread robotProxy); IHostedThread getLoadingRobot(); IHostedThread getLoadingRobotProxy(Thread t); IHostedThread getLoadedOrLoadingRobotProxy(Thread t); IHostedThread getRobotProxy(Thread t); void reset(); void setLoadingRobot(IHostedThread newLoadingRobotProxy); } robocode/robocode/robocode/manager/NameManager.java0000644000175000017500000001332011130241112021645 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup *******************************************************************************/ package robocode.manager; import java.io.Serializable; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ @SuppressWarnings("serial") public class NameManager implements Serializable { private String fullClassName; private String version; private boolean developmentVersion; private String fullClassNameWithVersion; private String uniqueFullClassNameWithVersion; private String fullPackage; private String rootPackage; private String shortClassName; private String veryShortClassName; private String shortClassNameWithVersion; private String veryShortClassNameWithVersion; private String uniqueVeryShortClassNameWithVersion; private String uniqueShortClassNameWithVersion; public NameManager(String className, String version, boolean developmentVersion, boolean isTeam) { if (className == null) { throw new NullPointerException("className cannot be null."); } this.fullClassName = className; if (version != null) { if (version.length() > 10) { version = version.substring(0, 10); } } this.version = version; this.developmentVersion = developmentVersion; } public String getFullClassName() { return fullClassName; } public String getRootPackage() { if (rootPackage == null) { int dotIndex = fullClassName.indexOf("."); rootPackage = (dotIndex > 0) ? fullClassName.substring(0, dotIndex) : null; } return rootPackage; } public String getShortClassName() { if (shortClassName == null) { if (getFullClassName().lastIndexOf(".") > 0) { shortClassName = getFullClassName().substring(getFullClassName().lastIndexOf(".") + 1); } else { shortClassName = getFullClassName(); } } return shortClassName; } public String getShortClassNameWithVersion() { if (shortClassNameWithVersion == null) { if (getVersion().length() == 0) { shortClassNameWithVersion = getShortClassName(); } else { shortClassNameWithVersion = getShortClassName() + " " + getVersion(); } } return shortClassNameWithVersion; } // Example: sample.Walls 1.0* // The * indicates a development version, or not from the cache. public String getUniqueFullClassNameWithVersion() { if (uniqueFullClassNameWithVersion == null) { if (getFullClassNameWithVersion().equals(getFullClassName())) { uniqueFullClassNameWithVersion = getFullClassName(); } else { if (!developmentVersion) { uniqueFullClassNameWithVersion = getFullClassNameWithVersion(); } else { uniqueFullClassNameWithVersion = getFullClassNameWithVersion() + "*"; } } } return uniqueFullClassNameWithVersion; } public String getUniqueShortClassNameWithVersion() { if (uniqueShortClassNameWithVersion == null) { if (getShortClassName().equals(getShortClassNameWithVersion())) { uniqueShortClassNameWithVersion = getShortClassName(); } else { if (!developmentVersion) { uniqueShortClassNameWithVersion = getShortClassNameWithVersion(); } else { uniqueShortClassNameWithVersion = getShortClassNameWithVersion() + "*"; } } } return uniqueShortClassNameWithVersion; } public String getUniqueVeryShortClassNameWithVersion() { if (uniqueVeryShortClassNameWithVersion == null) { if (getVeryShortClassName().equals(getVeryShortClassNameWithVersion())) { uniqueVeryShortClassNameWithVersion = getVeryShortClassName(); } else { if (!developmentVersion) { uniqueVeryShortClassNameWithVersion = getVeryShortClassNameWithVersion(); } else { uniqueVeryShortClassNameWithVersion = getVeryShortClassNameWithVersion() + "*"; } } } return uniqueVeryShortClassNameWithVersion; } public boolean isDevelopmentVersion() { return developmentVersion; } public String getVersion() { if (version == null) { version = ""; } return version; } public String getVeryShortClassName() { if (veryShortClassName == null) { veryShortClassName = getShortClassName(); if (veryShortClassName.length() > 12) { veryShortClassName = veryShortClassName.substring(0, 12) + "..."; } } return veryShortClassName; } public String getVeryShortClassNameWithVersion() { if (veryShortClassNameWithVersion == null) { if (getVersion().length() == 0) { veryShortClassNameWithVersion = getVeryShortClassName(); } else { veryShortClassNameWithVersion = getVeryShortClassName() + " " + getVersion(); } } return veryShortClassNameWithVersion; } public String getFullClassNameWithVersion() { if (fullClassNameWithVersion == null) { if (getVersion().length() == 0) { fullClassNameWithVersion = getFullClassName(); } else { fullClassNameWithVersion = getFullClassName() + " " + getVersion(); } } return fullClassNameWithVersion; } public String getFullPackage() { if (fullPackage == null) { if (fullClassName.lastIndexOf(".") > 0) { fullPackage = fullClassName.substring(0, fullClassName.lastIndexOf(".")); } else { fullPackage = null; } } return fullPackage; } } robocode/robocode/robocode/manager/ThreadManager.java0000644000175000017500000000573311130241112022205 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup * - Fixed potential NullPointerException in getLoadingRobotProxy() * - Added getRobotClasses() and getRobotProxies() for the * RobocodeSecurityManager * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap *******************************************************************************/ package robocode.manager; import robocode.peer.proxies.IHostedThread; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Robert D. Maupin (contributor) */ public class ThreadManager implements IThreadManager { private final List groups = Collections.synchronizedList(new ArrayList()); private Thread robotLoaderThread; private IHostedThread loadingRobot; private final List robots = Collections.synchronizedList(new ArrayList()); public ThreadManager() { super(); } public void addThreadGroup(ThreadGroup g, IHostedThread robotProxy) { if (!groups.contains(g)) { groups.add(g); robots.add(robotProxy); } } public synchronized IHostedThread getLoadingRobot() { return loadingRobot; } public synchronized IHostedThread getLoadingRobotProxy(Thread t) { if (t != null && robotLoaderThread != null && (t.equals(robotLoaderThread) || (t.getThreadGroup() != null && t.getThreadGroup().equals(robotLoaderThread.getThreadGroup())))) { return loadingRobot; } return null; } public synchronized IHostedThread getLoadedOrLoadingRobotProxy(Thread t) { IHostedThread robotProxy = getRobotProxy(t); if (robotProxy == null) { robotProxy = getLoadingRobotProxy(t); } return robotProxy; } public IHostedThread getRobotProxy(Thread t) { ThreadGroup g = t.getThreadGroup(); if (g == null) { return null; } int index = groups.indexOf(g); if (index == -1) { return null; } return robots.get(index); } public void reset() { groups.clear(); robots.clear(); } public synchronized void setLoadingRobot(IHostedThread newLoadingRobotProxy) { if (newLoadingRobotProxy == null) { this.robotLoaderThread = null; loadingRobot = null; } else { this.robotLoaderThread = Thread.currentThread(); loadingRobot = newLoadingRobotProxy; } } } robocode/robocode/robocode/manager/ICpuManager.java0000644000175000017500000000134711130241112021633 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.manager; /** * @author Pavel Savara (original) */ public interface ICpuManager { long getCpuConstant(); void calculateCpuConstant(); } robocode/robocode/robocode/manager/BattleManager.java0000644000175000017500000004072311130241112022207 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup & optimizations * - Removed getBattleView().setDoubleBuffered(false) as BufferStrategy is * used now * - Replaced FileSpecificationVector, RobotPeerVector, and * RobotClassManagerVector with plain Vector * - Added check for if GUI is enabled before using graphical components * - Added restart() method * - Ported to Java 5 * - Added support for the replay feature * - Removed the clearBattleProperties() * - Updated to use methods from FileUtil and Logger, which replaces methods * that have been (re)moved from the robocode.util.Utils class * - Added PauseResumeListener interface, addListener(), removeListener(), * notifyBattlePaused(), notifyBattleResumed() for letting listeners * receive notifications when the game is paused or resumed * - Added missing functionality in to support team battles in * startNewBattle(BattleSpecification spec, boolean replay) * - Added missing close() on FileInputStreams and FileOutputStreams * - isPaused() is now synchronized * - Extended sendResultsToListener() to handle teams as well as robots * - Added setDefaultBattleProperties() for resetting battle properties * - Removed the showResultsDialog parameter from the stop() method * - Added null pointer check to the sendResultsToListener() method * - Enhanced the getBattleFilename() to look into the battle dir and also * add the .battle file extension to the returned file name if this is * missing * - Removed battleRunning field, isBattleRunning(), and setBattle() * - Bugfix: Multiple battle threads could run in the same time when the * battle thread was started in startNewBattle() * Luis Crespo * - Added debug step feature, including the nextTurn(), shouldStep(), * startNewRound() * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap * Nathaniel Troutman * - Bugfix: Added cleanup() to prevent memory leaks by removing circular * references * Pavel Savara * - now driven by BattleObserver and commands to battle * - initial code of battle recorder and player *******************************************************************************/ package robocode.manager; import robocode.Event; import robocode.battle.Battle; import robocode.battle.BattleProperties; import robocode.battle.IBattle; import robocode.battle.events.BattleEventDispatcher; import robocode.control.BattleSpecification; import robocode.control.RandomFactory; import robocode.control.RobotSpecification; import robocode.control.events.BattleFinishedEvent; import robocode.control.events.BattlePausedEvent; import robocode.control.events.BattleResumedEvent; import robocode.control.events.IBattleListener; import robocode.io.FileUtil; import robocode.io.Logger; import static robocode.io.Logger.logError; import static robocode.io.Logger.logMessage; import robocode.peer.robot.RobotClassManager; import robocode.recording.BattlePlayer; import robocode.repository.FileSpecification; import robocode.repository.Repository; import robocode.repository.RobotFileSpecification; import robocode.repository.TeamSpecification; import robocode.security.RobocodeSecurityManager; import java.io.*; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; import java.util.concurrent.atomic.AtomicBoolean; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Luis Crespo (contributor) * @author Robert D. Maupin (contributor) * @author Nathaniel Troutman (contributor) * @author Pavel Savara (contributor) */ public class BattleManager implements IBattleManager { private RobocodeManager manager; private volatile IBattle battle; private BattleProperties battleProperties = new BattleProperties(); private BattleEventDispatcher battleEventDispatcher = new BattleEventDispatcher(); private String battleFilename; private String battlePath; private int pauseCount = 0; private final AtomicBoolean isManagedTPS = new AtomicBoolean(false); public BattleManager(RobocodeManager manager) { this.manager = manager; } public synchronized void cleanup() { if (battle != null) { battle.waitTillOver(); battle.cleanup(); battle = null; } manager = null; battleEventDispatcher = null; } // Called when starting a new battle from GUI public void startNewBattle(BattleProperties battleProperties, boolean waitTillOver) { this.battleProperties = battleProperties; List battlingRobotsList = new ArrayList(); if (battleProperties.getSelectedRobots() != null) { StringTokenizer tokenizer = new StringTokenizer(battleProperties.getSelectedRobots(), ","); int num = 0; while (tokenizer.hasMoreTokens()) { String bot = tokenizer.nextToken(); boolean failed = loadRobot(battlingRobotsList, bot, null, String.format("%4d", num), false); if (failed) { return; } num++; } } startNewBattleImpl(battlingRobotsList, waitTillOver); } // Called from the RobocodeEngine public void startNewBattle(BattleSpecification spec, boolean waitTillOver) { battleProperties = new BattleProperties(); battleProperties.setBattlefieldWidth(spec.getBattlefield().getWidth()); battleProperties.setBattlefieldHeight(spec.getBattlefield().getHeight()); battleProperties.setGunCoolingRate(spec.getGunCoolingRate()); battleProperties.setInactivityTime(spec.getInactivityTime()); battleProperties.setNumRounds(spec.getNumRounds()); battleProperties.setSelectedRobots(spec.getRobots()); List battlingRobotsList = new ArrayList(); int num = 0; for (robocode.control.RobotSpecification battleRobotSpec : spec.getRobots()) { if (battleRobotSpec == null) { break; } String bot = battleRobotSpec.getNameAndVersion(); boolean failed = loadRobot(battlingRobotsList, bot, battleRobotSpec, String.format("%4d", num), false); num++; if (failed) { return; } } startNewBattleImpl(battlingRobotsList, waitTillOver); } private boolean loadRobot(List battlingRobotsList, String bot, RobotSpecification battleRobotSpec, String teamName, boolean inTeam) { boolean found = false; final Repository repository = manager.getRobotRepositoryManager().getRobotRepository(); final FileSpecification fileSpec = repository.get(bot); if (fileSpec != null) { if (fileSpec instanceof RobotFileSpecification) { final String tn = inTeam ? teamName : null; RobotClassManager rcm = new RobotClassManager((RobotFileSpecification) fileSpec, tn); if (battleRobotSpec != null) { rcm.setControlRobotSpecification(battleRobotSpec); } battlingRobotsList.add(rcm); found = true; } else if (fileSpec instanceof TeamSpecification) { TeamSpecification currentTeam = (TeamSpecification) fileSpec; String version = currentTeam.getVersion(); if (version == null) { version = ""; } StringTokenizer teamTokenizer = new StringTokenizer(currentTeam.getMembers(), ","); while (teamTokenizer.hasMoreTokens()) { loadRobot(battlingRobotsList, currentTeam.getRootDir() + teamTokenizer.nextToken(), battleRobotSpec, currentTeam.getName() + version + "[" + teamName + "]", true); } found = true; } } if (!found) { logError("Aborting battle, could not find robot: " + bot); this.battleEventDispatcher.onBattleFinished(new BattleFinishedEvent(true)); return true; } return false; } private void startNewBattleImpl(List battlingRobotsList, boolean waitTillOver) { if (battle != null && battle.isRunning()) { battle.stop(true); } Logger.setLogListener(battleEventDispatcher); logMessage("Preparing battle..."); if (manager.isSoundEnabled()) { manager.getSoundManager().setBattleEventDispatcher(battleEventDispatcher); } final boolean recording = manager.getProperties().getOptionsCommonEnableReplayRecording() && System.getProperty("TESTING", "none").equals("none"); if (recording) { manager.getRecordManager().attachRecorder(battleEventDispatcher); } else { manager.getRecordManager().detachRecorder(); } // resets seed for deterministic behavior of Random final String seed = System.getProperty("RANDOMSEED", "none"); if (!seed.equals("none")) { // init soon as it reads random manager.getCpuManager().getCpuConstant(); RandomFactory.resetDeterministic(Long.valueOf(seed)); } Battle realBattle = new Battle(battlingRobotsList, battleProperties, manager, battleEventDispatcher, isPaused()); if (recording) { realBattle.setAllPaintRecorded(true); } battle = realBattle; Thread battleThread = new Thread(Thread.currentThread().getThreadGroup(), realBattle); battleThread.setPriority(Thread.NORM_PRIORITY); battleThread.setName("Battle Thread"); realBattle.setBattleThread(battleThread); if (!System.getProperty("NOSECURITY", "false").equals("true")) { ((RobocodeSecurityManager) System.getSecurityManager()).addSafeThread(battleThread); ((RobocodeSecurityManager) System.getSecurityManager()).setBattleThread(battleThread); } // Start the realBattle thread battleThread.start(); // Wait until the realBattle is running and ended. // This must be done as a new realBattle could be started immediately after this one causing // multiple realBattle threads to run at the same time, which must be prevented! realBattle.waitTillStarted(); if (waitTillOver) { realBattle.waitTillOver(); } } public void waitTillOver() { if (battle != null) { battle.waitTillOver(); } } private void replayBattle() { logMessage("Preparing replay..."); if (battle != null && battle.isRunning()) { battle.stop(true); } Logger.setLogListener(battleEventDispatcher); if (manager.isSoundEnabled()) { manager.getSoundManager().setBattleEventDispatcher(battleEventDispatcher); } manager.getRecordManager().detachRecorder(); // BattlePlayer battlePlayer battle = manager.getRecordManager().createPlayer(battleEventDispatcher); Thread battleThread = new Thread(Thread.currentThread().getThreadGroup(), battle); battleThread.setPriority(Thread.NORM_PRIORITY); battleThread.setName("BattlePlayer Thread"); // Start the battlePlayer thread battleThread.start(); } public String getBattleFilename() { String filename = battleFilename; if (filename != null) { if (filename.indexOf(File.separatorChar) < 0) { filename = FileUtil.getBattlesDir().getName() + File.separatorChar + filename; } if (!filename.endsWith(".battle")) { filename += ".battle"; } } return filename; } public void setBattleFilename(String newBattleFilename) { battleFilename = newBattleFilename; } public String getBattlePath() { if (battlePath == null) { battlePath = System.getProperty("BATTLEPATH"); if (battlePath == null) { battlePath = "battles"; } battlePath = new File(FileUtil.getCwd(), battlePath).getAbsolutePath(); } return battlePath; } public void saveBattleProperties() { if (battleProperties == null) { logError("Cannot save null battle properties"); return; } if (battleFilename == null) { logError("Cannot save battle to null path, use setBattleFilename()"); return; } FileOutputStream out = null; try { out = new FileOutputStream(battleFilename); battleProperties.store(out, "Battle Properties"); } catch (IOException e) { logError("IO Exception saving battle properties: " + e); } finally { if (out != null) { try { out.close(); } catch (IOException e) { Logger.logError(e); } } } } public BattleProperties loadBattleProperties() { BattleProperties res = new BattleProperties(); FileInputStream in = null; try { in = new FileInputStream(getBattleFilename()); res.load(in); } catch (FileNotFoundException e) { logError("No file " + battleFilename + " found, using defaults."); } catch (IOException e) { logError("IO Exception reading " + getBattleFilename() + ": " + e); } finally { if (in != null) { try { in.close(); } catch (IOException e) { Logger.logError(e); } } } return res; } public BattleProperties getBattleProperties() { if (battleProperties == null) { battleProperties = new BattleProperties(); } return battleProperties; } public void setDefaultBattleProperties() { battleProperties = new BattleProperties(); } public boolean isManagedTPS() { return isManagedTPS.get(); } public void setManagedTPS(boolean value) { isManagedTPS.set(value); } public synchronized void addListener(IBattleListener listener) { battleEventDispatcher.addListener(listener); } public synchronized void removeListener(IBattleListener listener) { battleEventDispatcher.removeListener(listener); } public synchronized void stop(boolean waitTillEnd) { if (battle != null && battle.isRunning()) { battle.stop(waitTillEnd); } } public synchronized void restart() { // Start new battle. The old battle is automatically stopped startNewBattle(battleProperties, false); } public synchronized void replay() { replayBattle(); } private boolean isPaused() { return (pauseCount != 0); } public synchronized void togglePauseResumeBattle() { if (isPaused()) { resumeBattle(); } else { pauseBattle(); } } public synchronized void pauseBattle() { if (++pauseCount == 1) { if (battle != null && battle.isRunning()) { battle.pause(); } else { battleEventDispatcher.onBattlePaused(new BattlePausedEvent()); } } } public synchronized void pauseIfResumedBattle() { if (pauseCount == 0) { pauseCount++; if (battle != null && battle.isRunning()) { battle.pause(); } else { battleEventDispatcher.onBattlePaused(new BattlePausedEvent()); } } } public synchronized void resumeIfPausedBattle() { if (pauseCount == 1) { pauseCount--; if (battle != null && battle.isRunning()) { battle.resume(); } else { battleEventDispatcher.onBattleResumed(new BattleResumedEvent()); } } } public synchronized void resumeBattle() { if (--pauseCount < 0) { pauseCount = 0; logError("SYSTEM: pause game bug!"); } else if (pauseCount == 0) { if (battle != null && battle.isRunning()) { battle.resume(); } else { battleEventDispatcher.onBattleResumed(new BattleResumedEvent()); } } } /** * Steps for a single turn, then goes back to paused */ public synchronized void nextTurn() { if (battle != null && battle.isRunning()) { battle.step(); } } public synchronized void prevTurn() { if (battle != null && battle.isRunning() && battle instanceof BattlePlayer) { ((BattlePlayer) battle).stepBack(); } } public synchronized void killRobot(int robotIndex) { if (battle != null && battle.isRunning() && battle instanceof Battle) { ((Battle) battle).killRobot(robotIndex); } } public synchronized void setPaintEnabled(int robotIndex, boolean enable) { if (battle != null && battle.isRunning()) { battle.setPaintEnabled(robotIndex, enable); } } public synchronized void setSGPaintEnabled(int robotIndex, boolean enable) { if (battle != null && battle.isRunning() && battle instanceof Battle) { ((Battle) battle).setSGPaintEnabled(robotIndex, enable); } } public synchronized void sendInteractiveEvent(Event event) { if (battle != null && battle.isRunning() && !isPaused() && battle instanceof Battle) { ((Battle) battle).sendInteractiveEvent(event); } } } robocode/robocode/robocode/manager/IHostManager.java0000644000175000017500000000141311130241112022013 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.manager; /** * @author Pavel Savara (original) */ public interface IHostManager { long getRobotFilesystemQuota(); IThreadManager getThreadManager(); void cleanup(); } robocode/robocode/robocode/manager/IRobotDialogManager.java0000644000175000017500000000217011130241112023304 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.manager; import robocode.control.snapshot.IRobotSnapshot; import robocode.dialog.BattleButton; import robocode.dialog.BattleDialog; import robocode.dialog.RobotButton; import robocode.dialog.RobotDialog; import java.util.List; /** * @author Pavel Savara (original) */ public interface IRobotDialogManager { void trim(List robots); void reset(); RobotDialog getRobotDialog(RobotButton robotButton, String name, boolean create); BattleDialog getBattleDialog(BattleButton battleButton, boolean create); } robocode/robocode/robocode/battleview/0000755000175000017500000000000011124141762017401 5ustar lambylambyrobocode/robocode/robocode/battleview/BattleView.java0000644000175000017500000004576411130241114022317 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Rewritten * Pavel Savara * - now driven by BattleObserver *******************************************************************************/ package robocode.battleview; import robocode.control.events.BattleAdaptor; import robocode.battle.snapshot.RobotSnapshot; import robocode.battlefield.BattleField; import robocode.battlefield.DefaultBattleField; import robocode.control.events.BattleFinishedEvent; import robocode.control.events.BattleStartedEvent; import robocode.control.events.TurnEndedEvent; import robocode.control.snapshot.IBulletSnapshot; import robocode.control.snapshot.IRobotSnapshot; import robocode.control.snapshot.ITurnSnapshot; import robocode.gfx.GraphicsState; import robocode.gfx.RenderImage; import robocode.gfx.RobocodeLogo; import robocode.manager.IImageManager; import robocode.manager.IWindowManager; import robocode.manager.RobocodeManager; import robocode.manager.RobocodeProperties; import robocode.control.snapshot.BulletState; import robocode.robotpaint.Graphics2DProxy; import java.awt.*; import java.awt.geom.*; import java.awt.image.BufferStrategy; import java.awt.image.BufferedImage; import static java.lang.Math.*; import java.util.Random; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Pavel Savara (contributor) */ @SuppressWarnings("serial") public class BattleView extends Canvas { private final static String ROBOCODE_SLOGAN = "Build the best, destroy the rest"; private final static Color CANVAS_BG_COLOR = SystemColor.controlDkShadow; private final static Area BULLET_AREA = new Area(new Ellipse2D.Double(-0.5, -0.5, 1, 1)); private final static int ROBOT_TEXT_Y_OFFSET = 24; // The battle and battlefield, private BattleField battleField; private boolean initialized; private double scale = 1.0; // Ground private int[][] groundTiles; private final int groundTileWidth = 64; private final int groundTileHeight = 64; private Image groundImage; // Draw option related things private boolean drawRobotName; private boolean drawRobotEnergy; private boolean drawScanArcs; private boolean drawExplosions; private boolean drawGround; private boolean drawExplosionDebris; private int numBuffers = 2; // defaults to double buffering private RenderingHints renderingHints; // Fonts and the like private Font smallFont; private FontMetrics smallFontMetrics; private final IImageManager imageManager; private final RobocodeManager manager; private BufferStrategy bufferStrategy; private Image offscreenImage; private Graphics2D offscreenGfx; private final GeneralPath robocodeTextPath = new RobocodeLogo().getRobocodeText(); private static final MirroredGraphics mirroredGraphics = new MirroredGraphics(); private final GraphicsState graphicsState = new GraphicsState(); private Graphics2DProxy[] robotGraphics; public BattleView(RobocodeManager manager) { super(); this.manager = manager; imageManager = manager.getImageManager(); battleField = new DefaultBattleField(800, 600); new BattleObserver(manager.getWindowManager()); } @Override public void paint(Graphics g) { final ITurnSnapshot lastSnapshot = manager.getWindowManager().getLastSnapshot(); if (lastSnapshot != null) { update(lastSnapshot); } else { paintRobocodeLogo((Graphics2D) g); } } private void update(ITurnSnapshot snapshot) { if (!initialized) { initialize(); } if (manager.getWindowManager().getRobocodeFrame().isIconified() || offscreenImage == null || !isDisplayable() || (getWidth() <= 0) || (getHeight() <= 0)) { return; } offscreenGfx = (Graphics2D) offscreenImage.getGraphics(); if (offscreenGfx != null) { offscreenGfx.setRenderingHints(renderingHints); drawBattle(offscreenGfx, snapshot); if (bufferStrategy != null) { Graphics2D g = null; try { g = (Graphics2D) bufferStrategy.getDrawGraphics(); g.drawImage(offscreenImage, 0, 0, null); bufferStrategy.show(); } catch (NullPointerException e) {// Occurs sometimes for no reason?! } finally { if (g != null) { g.dispose(); } } } } } public void setDisplayOptions() { RobocodeProperties props = manager.getProperties(); drawRobotName = props.getOptionsViewRobotNames(); drawRobotEnergy = props.getOptionsViewRobotEnergy(); drawScanArcs = props.getOptionsViewScanArcs(); drawGround = props.getOptionsViewGround(); drawExplosions = props.getOptionsViewExplosions(); drawExplosionDebris = props.getOptionsViewExplosionDebris(); renderingHints = props.getRenderingHints(); numBuffers = props.getOptionsRenderingNoBuffers(); } private void initialize() { setDisplayOptions(); if (offscreenImage != null) { offscreenImage.flush(); offscreenImage = null; } offscreenImage = getGraphicsConfiguration().createCompatibleImage(getWidth(), getHeight()); offscreenGfx = (Graphics2D) offscreenImage.getGraphics(); if (bufferStrategy == null) { createBufferStrategy(numBuffers); bufferStrategy = getBufferStrategy(); } // If we are scaled... if (getWidth() < battleField.getWidth() || getHeight() < battleField.getHeight()) { // Use the smaller scale. // Actually we don't need this, since // the RobocodeFrame keeps our aspect ratio intact. scale = min((double) getWidth() / battleField.getWidth(), (double) getHeight() / battleField.getHeight()); offscreenGfx.scale(scale, scale); } else { scale = 1; } // Scale font smallFont = new Font("Dialog", Font.PLAIN, (int) (10 / scale)); smallFontMetrics = offscreenGfx.getFontMetrics(smallFont); // Initialize ground image if (drawGround) { createGroundImage(); } else { groundImage = null; } initialized = true; } private void createGroundImage() { // Reinitialize ground tiles Random r = new Random(); // independent final int NUM_HORZ_TILES = battleField.getWidth() / groundTileWidth + 1; final int NUM_VERT_TILES = battleField.getHeight() / groundTileHeight + 1; if ((groundTiles == null) || (groundTiles.length != NUM_VERT_TILES) || (groundTiles[0].length != NUM_HORZ_TILES)) { groundTiles = new int[NUM_VERT_TILES][NUM_HORZ_TILES]; for (int y = NUM_VERT_TILES - 1; y >= 0; y--) { for (int x = NUM_HORZ_TILES - 1; x >= 0; x--) { groundTiles[y][x] = (int) round(r.nextDouble() * 4); } } } // Create new buffered image with the ground pre-rendered int groundWidth = (int) (battleField.getWidth() * scale); int groundHeight = (int) (battleField.getHeight() * scale); groundImage = new BufferedImage(groundWidth, groundHeight, BufferedImage.TYPE_INT_RGB); Graphics2D groundGfx = (Graphics2D) groundImage.getGraphics(); groundGfx.setRenderingHints(renderingHints); groundGfx.setTransform(AffineTransform.getScaleInstance(scale, scale)); for (int y = NUM_VERT_TILES - 1; y >= 0; y--) { for (int x = NUM_HORZ_TILES - 1; x >= 0; x--) { Image img = imageManager.getGroundTileImage(groundTiles[y][x]); if (img != null) { groundGfx.drawImage(img, x * groundTileWidth, y * groundTileHeight, null); } } } } private void drawBattle(Graphics2D g, ITurnSnapshot snapShot) { // Save the graphics state graphicsState.save(g); // Reset transform g.setTransform(new AffineTransform()); // Reset clip g.setClip(null); // Clear canvas g.setColor(CANVAS_BG_COLOR); g.fillRect(0, 0, getWidth(), getHeight()); // Calculate border space double dx = (getWidth() - scale * battleField.getWidth()) / 2; double dy = (getHeight() - scale * battleField.getHeight()) / 2; // Scale and translate the graphics AffineTransform at = AffineTransform.getTranslateInstance(dx, dy); at.concatenate(AffineTransform.getScaleInstance(scale, scale)); g.setTransform(at); // Set the clip rectangle g.setClip(0, 0, battleField.getWidth(), battleField.getHeight()); // Draw ground drawGround(g); if (snapShot != null) { // Draw scan arcs drawScanArcs(g, snapShot); // Draw robots drawRobots(g, snapShot); } // Draw the border of the battlefield drawBorder(g); if (snapShot != null) { // Draw all bullets drawBullets(g, snapShot); // Draw all text drawText(g, snapShot); } // Restore the graphics state graphicsState.restore(g); } private void drawGround(Graphics2D g) { if (!drawGround) { // Ground should not be drawn g.setColor(Color.BLACK); g.fillRect(0, 0, battleField.getWidth(), battleField.getHeight()); } else { // Create pre-rendered ground image if it is not available if (groundImage == null) { createGroundImage(); } // Draw the pre-rendered ground if it is available if (groundImage != null) { int groundWidth = (int) (battleField.getWidth() * scale) + 1; int groundHeight = (int) (battleField.getHeight() * scale) + 1; int dx = (getWidth() - groundWidth) / 2; int dy = (getHeight() - groundHeight) / 2; AffineTransform savedTx = g.getTransform(); g.setTransform(new AffineTransform()); g.drawImage(groundImage, dx, dy, groundWidth, groundHeight, null); g.setTransform(savedTx); } } } private void drawBorder(Graphics2D g) { final Shape savedClip = g.getClip(); g.setClip(null); g.setColor(Color.RED); g.drawRect(-1, -1, battleField.getWidth() + 2, battleField.getHeight() + 2); g.setClip(savedClip); } private void drawScanArcs(Graphics2D g, ITurnSnapshot snapShot) { if (drawScanArcs) { for (IRobotSnapshot robotSnapshot : snapShot.getRobots()) { if (robotSnapshot.getState().isAlive()) { drawScanArc(g, robotSnapshot); } } } } private void drawRobots(Graphics2D g, ITurnSnapshot snapShot) { double x, y; AffineTransform at; int battleFieldHeight = battleField.getHeight(); if (drawGround && drawExplosionDebris) { RenderImage explodeDebrise = imageManager.getExplosionDebriseRenderImage(); for (IRobotSnapshot robotSnapshot : snapShot.getRobots()) { if (robotSnapshot.getState().isDead()) { x = robotSnapshot.getX(); y = battleFieldHeight - robotSnapshot.getY(); at = AffineTransform.getTranslateInstance(x, y); explodeDebrise.setTransform(at); explodeDebrise.paint(g); } } } for (IRobotSnapshot robotSnapshot : snapShot.getRobots()) { if (robotSnapshot.getState().isAlive()) { x = robotSnapshot.getX(); y = battleFieldHeight - robotSnapshot.getY(); at = AffineTransform.getTranslateInstance(x, y); at.rotate(robotSnapshot.getBodyHeading()); RenderImage robotRenderImage = imageManager.getColoredBodyRenderImage(robotSnapshot.getBodyColor()); robotRenderImage.setTransform(at); robotRenderImage.paint(g); at = AffineTransform.getTranslateInstance(x, y); at.rotate(robotSnapshot.getGunHeading()); RenderImage gunRenderImage = imageManager.getColoredGunRenderImage(robotSnapshot.getGunColor()); gunRenderImage.setTransform(at); gunRenderImage.paint(g); if (!robotSnapshot.isDroid()) { at = AffineTransform.getTranslateInstance(x, y); at.rotate(robotSnapshot.getRadarHeading()); RenderImage radarRenderImage = imageManager.getColoredRadarRenderImage(robotSnapshot.getRadarColor()); radarRenderImage.setTransform(at); radarRenderImage.paint(g); } } } } private void drawText(Graphics2D g, ITurnSnapshot snapShot) { Shape savedClip = g.getClip(); g.setClip(null); int i = -1; for (IRobotSnapshot robotSnapshot : snapShot.getRobots()) { i++; if (robotSnapshot.getState().isDead()) { continue; } int x = (int) robotSnapshot.getX(); int y = battleField.getHeight() - (int) robotSnapshot.getY(); if (drawRobotEnergy) { g.setColor(Color.white); int ll = (int) robotSnapshot.getEnergy(); int rl = (int) ((robotSnapshot.getEnergy() - ll + .001) * 10.0); if (rl == 10) { rl = 9; } String energyString = ll + "." + rl; if (robotSnapshot.getEnergy() == 0 && robotSnapshot.getState().isAlive()) { energyString = "Disabled"; } centerString(g, energyString, x, y - ROBOT_TEXT_Y_OFFSET - smallFontMetrics.getHeight() / 2, smallFont, smallFontMetrics); } if (drawRobotName) { g.setColor(Color.white); centerString(g, robotSnapshot.getVeryShortName(), x, y + ROBOT_TEXT_Y_OFFSET + smallFontMetrics.getHeight() / 2, smallFont, smallFontMetrics); } drawRobotPaint(g, robotSnapshot, i); } g.setClip(savedClip); } private void drawRobotPaint(Graphics2D g, IRobotSnapshot robotSnapshot, int robotIndex) { final java.util.List graphicsCalls = ((RobotSnapshot) robotSnapshot).getGraphicsCalls(); if (graphicsCalls == null || !robotSnapshot.isPaintEnabled()) { return; } // Save the graphics state GraphicsState gfxState = new GraphicsState(); gfxState.save(g); g.setClip(0, 0, battleField.getWidth(), battleField.getHeight()); Graphics2DProxy gfxProxy = getRobotGraphics(robotIndex); gfxProxy.clearQueue(); gfxProxy.appendCalls(graphicsCalls); if (robotSnapshot.isSGPaintEnabled()) { gfxProxy.processTo(g); } else { mirroredGraphics.bind(g, battleField.getHeight()); gfxProxy.processTo(mirroredGraphics); mirroredGraphics.release(); } // Restore the graphics state gfxState.restore(g); } private Graphics2DProxy getRobotGraphics(int robotIndex) { if (robotGraphics[robotIndex] == null) { robotGraphics[robotIndex] = new Graphics2DProxy(); robotGraphics[robotIndex].setPaintingEnabled(true); } return robotGraphics[robotIndex]; } private void drawBullets(Graphics2D g, ITurnSnapshot snapShot) { Shape savedClip = g.getClip(); g.setClip(null); double x, y; for (IBulletSnapshot IBulletSnapshot : snapShot.getBullets()) { x = IBulletSnapshot.getPaintX(); y = battleField.getHeight() - IBulletSnapshot.getPaintY(); AffineTransform at = AffineTransform.getTranslateInstance(x, y); if (IBulletSnapshot.getState().getValue() <= BulletState.MOVING.getValue()) { // radius = sqrt(x^2 / 0.1 * power), where x is the width of 1 pixel for a minimum 0.1 bullet double scale = max(2 * sqrt(2.5 * IBulletSnapshot.getPower()), 2 / this.scale); at.scale(scale, scale); Area bulletArea = BULLET_AREA.createTransformedArea(at); Color bulletColor; if (manager.getProperties().getOptionsRenderingForceBulletColor()) { bulletColor = Color.WHITE; } else { bulletColor = new Color(IBulletSnapshot.getColor()); } g.setColor(bulletColor); g.fill(bulletArea); } else if (drawExplosions) { if (!IBulletSnapshot.isExplosion()) { double scale = sqrt(1000 * IBulletSnapshot.getPower()) / 128; at.scale(scale, scale); } RenderImage explosionRenderImage = imageManager.getExplosionRenderImage( IBulletSnapshot.getExplosionImageIndex(), IBulletSnapshot.getFrame()); explosionRenderImage.setTransform(at); explosionRenderImage.paint(g); } } g.setClip(savedClip); } private void centerString(Graphics2D g, String s, int x, int y, Font font, FontMetrics fm) { g.setFont(font); int width = fm.stringWidth(s); int height = fm.getHeight(); int descent = fm.getDescent(); double left = x - width / 2; double top = y - height / 2; double scaledViewWidth = getWidth() / scale; double scaledViewHeight = getHeight() / scale; double borderWidth = (scaledViewWidth - battleField.getWidth()) / 2; double borderHeight = (scaledViewHeight - battleField.getHeight()) / 2; if (left + width > scaledViewWidth) { left = scaledViewWidth - width; } if (top + height > scaledViewHeight) { top = scaledViewHeight - height; } if (left < -borderWidth) { left = -borderWidth; } if (top < -borderHeight) { top = -borderHeight; } g.drawString(s, (int) (left + 0.5), (int) (top + height - descent + 0.5)); } private void drawScanArc(Graphics2D g, IRobotSnapshot robotSnapshot) { Arc2D.Double scanArc = (Arc2D.Double) ((RobotSnapshot) robotSnapshot).getScanArc(); if (scanArc == null) { return; } g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, (float) .2)); scanArc.setAngleStart((360 - scanArc.getAngleStart() - scanArc.getAngleExtent()) % 360); scanArc.y = battleField.getHeight() - robotSnapshot.getY() - robocode.Rules.RADAR_SCAN_RADIUS; int scanColor = robotSnapshot.getScanColor(); g.setColor(new Color(scanColor, true)); if (abs(scanArc.getAngleExtent()) >= .5) { g.fill(scanArc); } else { g.draw(scanArc); } g.setComposite(AlphaComposite.SrcOver); } private void paintRobocodeLogo(Graphics2D g) { setBackground(Color.BLACK); g.clearRect(0, 0, getWidth(), getHeight()); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.transform(AffineTransform.getTranslateInstance((getWidth() - 320) / 2.0, (getHeight() - 46) / 2.0)); g.setColor(new Color(0, 0x40, 0)); g.fill(robocodeTextPath); Font font = new Font("Dialog", Font.BOLD, 14); int width = g.getFontMetrics(font).stringWidth(ROBOCODE_SLOGAN); g.setTransform(new AffineTransform()); g.setFont(font); g.setColor(new Color(0, 0x50, 0)); g.drawString(ROBOCODE_SLOGAN, (float) ((getWidth() - width) / 2.0), (float) (getHeight() / 2.0 + 50)); } public void setInitialized(boolean initialized) { this.initialized = initialized; } private class BattleObserver extends BattleAdaptor { public BattleObserver(IWindowManager windowManager) { windowManager.addBattleListener(this); } @Override public void onBattleStarted(BattleStartedEvent event) { battleField = new DefaultBattleField(event.getBattleRules().getBattlefieldWidth(), event.getBattleRules().getBattlefieldHeight()); setVisible(true); setInitialized(false); super.onBattleStarted(event); robotGraphics = new Graphics2DProxy[event.getRobotsCount()]; } @Override public void onBattleFinished(BattleFinishedEvent event) { super.onBattleFinished(event); robotGraphics = null; } public void onTurnEnded(final TurnEndedEvent event) { if (event.getTurnSnapshot() == null) { repaint(); } else { update(event.getTurnSnapshot()); } } } } robocode/robocode/robocode/battleview/MirroredGraphics.java0000644000175000017500000003470511130241114023506 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen * - Initial implementation *******************************************************************************/ package robocode.battleview; import robocode.gfx.GraphicsState; import java.awt.*; import java.awt.RenderingHints.Key; import java.awt.font.FontRenderContext; import java.awt.font.GlyphVector; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.awt.image.BufferedImageOp; import java.awt.image.ImageObserver; import java.awt.image.RenderedImage; import java.awt.image.renderable.RenderableImage; import java.text.AttributedCharacterIterator; import java.util.Map; /** * This class is a Graphics2D wrapper class used for mirroring graphics on * the Y-axis. This class ensures that strings that are painted using the * drawBytes(), drawChars(), and drawString() methods are painted on the * right location but that the text itself is not mirrored when painted. * * @author Flemming N. Larsen (original) */ public class MirroredGraphics extends Graphics2D { // The wrapped Graphics object private Graphics2D g; // Save/restore of Graphics object private final GraphicsState graphicsState = new GraphicsState(); // The original transform mirrored private final AffineTransform origTxMirrored = new AffineTransform(); // A transform used for temporary transform operations (is reused) private final AffineTransform tmpTx = new AffineTransform(); /** * Binds a Graphics2D object to this wrapper object. * When painting using this wrapper has finished the * {@link #release() } method must be called. * * @param g the Graphics2D object to wrap * @param height the height of the battlefield to mirror * @see #release() */ public void bind(Graphics2D g, int height) { this.g = g; graphicsState.save(g); origTxMirrored.setTransform(g.getTransform()); origTxMirrored.translate(0, height); origTxMirrored.scale(1, -1); g.setTransform(origTxMirrored); } /** * Releases the bounded Graphics2D object from this wrapper. * * @see #bind(Graphics2D, int) */ public void release() { graphicsState.restore(g); } // -------------------------------------------------------------------------- // Overriding all methods from the extended Graphics class // -------------------------------------------------------------------------- // Methods that should not be overridden or implemented: // - finalize() // - toString() @Override public Graphics create() { return g.create(); } @Override public Graphics create(int x, int y, int width, int height) { return g.create(x, y, width, height); } @Override public void translate(int x, int y) { g.translate(x, y); } @Override public Color getColor() { return g.getColor(); } @Override public void setColor(Color c) { g.setColor(c); } @Override public void setPaintMode() { g.setPaintMode(); } @Override public void setXORMode(Color c1) { g.setXORMode(c1); } @Override public Font getFont() { return g.getFont(); } @Override public void setFont(Font font) { g.setFont(font); } @Override public FontMetrics getFontMetrics(Font f) { return g.getFontMetrics(f); } @Override public Rectangle getClipBounds() { return g.getClipBounds(); } @Override public void clipRect(int x, int y, int width, int height) { g.clipRect(x, y, width, height); } @Override public void setClip(int x, int y, int width, int height) { g.setClip(x, y, width, height); } @Override public Shape getClip() { return g.getClip(); } @Override public void setClip(Shape clip) { g.setClip(clip); } @Override public void copyArea(int x, int y, int width, int height, int dx, int dy) { g.copyArea(x, y, width, height, dx, dy); } @Override public void drawLine(int x1, int y1, int x2, int y2) { g.drawLine(x1, y1, x2, y2); } @Override public void fillRect(int x, int y, int width, int height) { g.fillRect(x, y, width, height); } @Override public void drawRect(int x, int y, int width, int height) { g.drawRect(x, y, width, height); } @Override public void clearRect(int x, int y, int width, int height) { g.clearRect(x, y, width, height); } @Override public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { g.drawRoundRect(x, y, width, height, arcWidth, arcHeight); } @Override public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { g.fillRoundRect(x, y, width, height, arcWidth, arcHeight); } @Override public void draw3DRect(int x, int y, int width, int height, boolean raised) { g.draw3DRect(x, y, width, height, raised); } @Override public void fill3DRect(int x, int y, int width, int height, boolean raised) { g.fill3DRect(x, y, width, height, raised); } @Override public void drawOval(int x, int y, int width, int height) { g.drawOval(x, y, width, height); } @Override public void fillOval(int x, int y, int width, int height) { g.fillOval(x, y, width, height); } @Override public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) { g.drawArc(x, y, width, height, startAngle - 90, arcAngle); // Translated into the Robocode coordinate system } @Override public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) { g.fillArc(x, y, width, height, startAngle - 90, arcAngle); // Translated into the Robocode coordinate system } @Override public void drawPolyline(int[] xPoints, int[] yPoints, int npoints) { g.drawPolyline(xPoints, yPoints, npoints); } @Override public void drawPolygon(int[] xPoints, int[] yPoints, int npoints) { g.drawPolyline(xPoints, yPoints, npoints); } @Override public void drawPolygon(Polygon p) { g.drawPolygon(p); } @Override public void fillPolygon(int[] xPoints, int[] yPoints, int npoints) { g.fillPolygon(xPoints, yPoints, npoints); } @Override public void fillPolygon(Polygon p) { g.fillPolygon(p); } // Modified so that the y-axis is mirrored @Override public void drawString(String str, int x, int y) { // Change the transform to use the mirrored transform and save the current one AffineTransform saveTx = setToMirroredTransform(); g.drawString(str, x, -y); // Restore the transform g.setTransform(saveTx); } // Modified so that the y-axis is mirrored @Override public void drawString(AttributedCharacterIterator iterator, int x, int y) { // Change the transform to use the mirrored transform and save the current one AffineTransform saveTx = setToMirroredTransform(); g.drawString(iterator, x, -y); // Restore the transform g.setTransform(saveTx); } // Modified so that the y-axis is mirrored @Override public void drawChars(char[] data, int offset, int length, int x, int y) { // Change the transform to use the mirrored transform and save the current one AffineTransform saveTx = setToMirroredTransform(); g.drawChars(data, offset, length, x, -y); // Restore the transform g.setTransform(saveTx); } // Modified so that the y-axis is mirrored @Override public void drawBytes(byte[] data, int offset, int length, int x, int y) { // Change the transform to use the mirrored transform and save the current one AffineTransform saveTx = setToMirroredTransform(); g.drawBytes(data, offset, length, x, -y); // Restore the transform g.setTransform(saveTx); } @Override public boolean drawImage(Image img, int x, int y, ImageObserver observer) { return g.drawImage(img, x, y, observer); } @Override public boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer) { return g.drawImage(img, x, y, width, height, observer); } @Override public boolean drawImage(Image img, int x, int y, Color bgcolor, ImageObserver observer) { return g.drawImage(img, x, y, bgcolor, observer); } @Override public boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor, ImageObserver observer) { return g.drawImage(img, x, y, width, height, bgcolor, observer); } @Override public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer) { return g.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, observer); } @Override public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, Color bgcolor, ImageObserver observer) { return g.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, bgcolor, observer); } @Override public void dispose() { g.dispose(); } @Override @Deprecated public Rectangle getClipRect() { return g.getClipBounds(); // Must use getClipBounds() instead of the deprecated getClipRect() method } @Override public boolean hitClip(int x, int y, int width, int height) { return g.hitClip(x, y, width, height); } @Override public Rectangle getClipBounds(Rectangle r) { return g.getClipBounds(r); } // -------------------------------------------------------------------------- // Overriding all methods from the extended Graphics2D class // -------------------------------------------------------------------------- @Override public void draw(Shape s) { g.draw(s); } @Override public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) { return g.drawImage(img, xform, obs); } @Override public void drawImage(BufferedImage img, BufferedImageOp op, int x, int y) { g.drawImage(img, op, x, y); } @Override public void drawRenderedImage(RenderedImage img, AffineTransform xform) { g.drawRenderedImage(img, xform); } @Override public void drawRenderableImage(RenderableImage img, AffineTransform xform) { g.drawRenderableImage(img, xform); } // Modified so that the y-axis is mirrored @Override public void drawString(String str, float x, float y) { // Change the transform to use the mirrored transform and save the current one AffineTransform saveTx = setToMirroredTransform(); g.drawString(str, x, -y); // Restore the transform g.setTransform(saveTx); } // Modified so that the y-axis is mirrored @Override public void drawString(AttributedCharacterIterator iterator, float x, float y) { // Change the transform to use the mirrored transform and save the current one AffineTransform saveTx = setToMirroredTransform(); g.drawString(iterator, x, -y); // Restore the transform g.setTransform(saveTx); } @Override public void drawGlyphVector(GlyphVector gv, float x, float y) { g.drawGlyphVector(gv, x, y); } @Override public void fill(Shape s) { g.fill(s); } @Override public boolean hit(Rectangle rect, Shape s, boolean onStroke) { return g.hit(rect, s, onStroke); } @Override public GraphicsConfiguration getDeviceConfiguration() { return g.getDeviceConfiguration(); } @Override public void setComposite(Composite comp) { g.setComposite(comp); } @Override public void setPaint(Paint paint) { g.setPaint(paint); } @Override public void setStroke(Stroke s) { g.setStroke(s); } @Override public void setRenderingHint(Key hintKey, Object hintValue) { g.setRenderingHint(hintKey, hintValue); } @Override public Object getRenderingHint(Key hintKey) { return g.getRenderingHint(hintKey); } @Override public void setRenderingHints(Map hints) { g.setRenderingHints(hints); } @Override public void addRenderingHints(Map hints) { g.addRenderingHints(hints); } @Override public RenderingHints getRenderingHints() { return g.getRenderingHints(); } @Override public void translate(double tx, double ty) { g.translate(tx, ty); } @Override public void rotate(double theta) { g.rotate(theta); } @Override public void rotate(double theta, double x, double y) { g.rotate(theta, x, y); } @Override public void scale(double sx, double sy) { g.scale(sx, sy); } @Override public void shear(double shx, double shy) { g.shear(shx, shy); } @Override public void transform(AffineTransform Tx) { g.transform(Tx); } // Transforming is handled on the y-axis mirrored transform @Override public void setTransform(AffineTransform Tx) { // Set the current transform to by the original mirrored transform // concatenated with the input transform. This way the new transform // will automatically be mirrored around the y-axis tmpTx.setTransform(origTxMirrored); tmpTx.concatenate(Tx); g.setTransform(tmpTx); } @Override public AffineTransform getTransform() { return g.getTransform(); } @Override public Paint getPaint() { return g.getPaint(); } @Override public Composite getComposite() { return g.getComposite(); } @Override public void setBackground(Color color) { g.setBackground(color); } @Override public Color getBackground() { return g.getBackground(); } @Override public Stroke getStroke() { return g.getStroke(); } @Override public void clip(Shape s) { g.clip(s); } @Override public FontRenderContext getFontRenderContext() { return g.getFontRenderContext(); } // -------------------------------------------------------------------------- // Private worker methods // -------------------------------------------------------------------------- /** * This methods translates the current transform on the internal Graphics2D * object into a transform that is mirrored around the y-axis. * * @return the AffineTransform before calling this method, which must be * used for restoring the AffineTransform later. */ private AffineTransform setToMirroredTransform() { AffineTransform saveTx = g.getTransform(); tmpTx.setTransform(saveTx); tmpTx.scale(1, -1); g.setTransform(tmpTx); return saveTx; } } robocode/robocode/robocode/battleview/SafeComponent.java0000644000175000017500000000205211130241114022771 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.battleview; import java.awt.*; /** * @author Pavel Savara (original) */ @SuppressWarnings("serial") public class SafeComponent extends Component { // Dummy component used to preventing robots in accessing the real source component private static Component safeEventComponent; public static Component getSafeEventComponent() { if (safeEventComponent == null) { safeEventComponent = new SafeComponent(); } return safeEventComponent; } } robocode/robocode/robocode/battleview/InteractiveHandler.java0000644000175000017500000001276511130241114024017 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Redesigned to use IRobotControls instead of accessing the Battle's * RobotPeers directly. *******************************************************************************/ package robocode.battleview; import robocode.*; import robocode.battle.BattleProperties; import robocode.manager.RobocodeManager; import java.awt.*; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.awt.event.*; import static java.lang.Math.min; /** * This handler is used for observing keyboard and mouse events from the battle view, * which must be process to the all robots interactive event handlers. * The mouse events y coordinates are mirrored to comply to the coordinate system * used in Robocode. * * @author Pavel Savara (original) * @author Flemming N. Larsen (contributor) */ public final class InteractiveHandler implements KeyEventDispatcher, MouseListener, MouseMotionListener, MouseWheelListener { private final RobocodeManager manager; public InteractiveHandler(RobocodeManager manager) { this.manager = manager; } public boolean dispatchKeyEvent(java.awt.event.KeyEvent e) { switch (e.getID()) { case KeyEvent.KEY_TYPED: handleInteractiveEvent(new KeyTypedEvent(cloneKeyEvent(e))); break; case KeyEvent.KEY_PRESSED: handleInteractiveEvent(new KeyPressedEvent(cloneKeyEvent(e))); break; case KeyEvent.KEY_RELEASED: handleInteractiveEvent(new KeyReleasedEvent(cloneKeyEvent(e))); break; } // Allow KeyboardFocusManager to take further action with regard to the KeyEvent. // This way the InteractiveHandler does not steal the event, but is only a keyboard observer. return false; } public void mouseClicked(MouseEvent e) { handleInteractiveEvent(new MouseClickedEvent(mirroredMouseEvent(e))); } public void mouseEntered(MouseEvent e) { handleInteractiveEvent(new MouseEnteredEvent(mirroredMouseEvent(e))); } public void mouseExited(MouseEvent e) { handleInteractiveEvent(new MouseExitedEvent(mirroredMouseEvent(e))); } public void mousePressed(MouseEvent e) { handleInteractiveEvent(new MousePressedEvent(mirroredMouseEvent(e))); } public void mouseReleased(MouseEvent e) { handleInteractiveEvent(new MouseReleasedEvent(mirroredMouseEvent(e))); } public void mouseMoved(MouseEvent e) { handleInteractiveEvent(new MouseMovedEvent(mirroredMouseEvent(e))); } public void mouseDragged(MouseEvent e) { handleInteractiveEvent(new MouseDraggedEvent(mirroredMouseEvent(e))); } public void mouseWheelMoved(MouseWheelEvent e) { handleInteractiveEvent(new MouseWheelMovedEvent(mirroredMouseWheelEvent(e))); } public static KeyEvent cloneKeyEvent(final KeyEvent e) { return new KeyEvent(SafeComponent.getSafeEventComponent(), e.getID(), e.getWhen(), e.getModifiersEx(), e.getKeyCode(), e.getKeyChar(), e.getKeyLocation()); } private void handleInteractiveEvent(robocode.Event event) { manager.getBattleManager().sendInteractiveEvent(event); } private MouseEvent mirroredMouseEvent(final MouseEvent e) { double scale; BattleProperties battleProps = manager.getBattleManager().getBattleProperties(); BattleView battleView = manager.getWindowManager().getRobocodeFrame().getBattleView(); int vWidth = battleView.getWidth(); int vHeight = battleView.getHeight(); int fWidth = battleProps.getBattlefieldWidth(); int fHeight = battleProps.getBattlefieldHeight(); if (vWidth < fWidth || vHeight < fHeight) { scale = min((double) vWidth / fWidth, (double) fHeight / fHeight); } else { scale = 1; } double dx = (vWidth - scale * fWidth) / 2; double dy = (vHeight - scale * fHeight) / 2; int x = (int) ((e.getX() - dx) / scale + 0.5); int y = (int) (fHeight - (e.getY() - dy) / scale + 0.5); return new MouseEvent(SafeComponent.getSafeEventComponent(), e.getID(), e.getWhen(), e.getModifiersEx(), x, y, e.getClickCount(), e.isPopupTrigger(), e.getButton()); } private MouseWheelEvent mirroredMouseWheelEvent(final MouseWheelEvent e) { double scale; BattleProperties battleProps = manager.getBattleManager().getBattleProperties(); BattleView battleView = manager.getWindowManager().getRobocodeFrame().getBattleView(); int vWidth = battleView.getWidth(); int vHeight = battleView.getHeight(); int fWidth = battleProps.getBattlefieldWidth(); int fHeight = battleProps.getBattlefieldHeight(); if (vWidth < fWidth || vHeight < fHeight) { scale = min((double) vWidth / fWidth, (double) fHeight / fHeight); } else { scale = 1; } double dx = (vWidth - scale * fWidth) / 2; double dy = (vHeight - scale * fHeight) / 2; int x = (int) ((e.getX() - dx) / scale + 0.5); int y = (int) (fHeight - (e.getY() - dy) / scale + 0.5); return new MouseWheelEvent(SafeComponent.getSafeEventComponent(), e.getID(), e.getWhen(), e.getModifiersEx(), x, y, e.getClickCount(), e.isPopupTrigger(), e.getScrollType(), e.getScrollAmount(), e.getWheelRotation()); } } robocode/robocode/robocode/security/0000755000175000017500000000000011130001316017065 5ustar lambylambyrobocode/robocode/robocode/security/SecurePrintStream.java0000644000175000017500000001300611130241112023347 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup *******************************************************************************/ package robocode.security; import java.io.OutputStream; import java.io.PrintStream; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ public class SecurePrintStream extends PrintStream { public static final PrintStream realOut = System.out; public static final PrintStream realErr = System.err; public SecurePrintStream(OutputStream out, boolean autoFlush) { super(out, autoFlush); } @Override public final boolean checkError() { PrintStream out = checkAccess(); return (out == this) ? super.checkError() : out.checkError(); } @Override public final void close() { PrintStream out = checkAccess(); if (out == this) { super.close(); } else { out.close(); } } @Override public final void flush() { PrintStream out = checkAccess(); if (out == this) { super.flush(); } else { out.flush(); } } @Override public final void print(char[] s) { PrintStream out = checkAccess(); if (out == this) { super.print(s); } else { out.print(s); } } @Override public final void print(char c) { PrintStream out = checkAccess(); if (out == this) { super.print(c); } else { out.print(c); } } @Override public final void print(double d) { PrintStream out = checkAccess(); if (out == this) { super.print(d); } else { out.print(d); } } @Override public final void print(float f) { PrintStream out = checkAccess(); if (out == this) { super.print(f); } else { out.print(f); } } @Override public final void print(int i) { PrintStream out = checkAccess(); if (out == this) { super.print(i); } else { out.print(i); } } @Override public final void print(long l) { PrintStream out = checkAccess(); if (out == this) { super.print(l); } else { out.print(l); } } @Override public final void print(Object obj) { PrintStream out = checkAccess(); if (out == this) { super.print(obj); } else { out.print(obj); } } @Override public final void print(String s) { PrintStream out = checkAccess(); if (out == this) { super.print(s); } else { out.print(s); } } @Override public final void print(boolean b) { PrintStream out = checkAccess(); if (out == this) { super.print(b); } else { out.print(b); } } @Override public final void println() { PrintStream out = checkAccess(); if (out == this) { super.println(); } else { out.println(); } } @Override public final void println(char[] x) { PrintStream out = checkAccess(); if (out == this) { super.println(x); } else { out.println(x); } } @Override public final void println(char x) { PrintStream out = checkAccess(); if (out == this) { super.println(x); } else { out.println(x); } } @Override public final void println(double x) { PrintStream out = checkAccess(); if (out == this) { super.println(x); } else { out.println(x); } } @Override public final void println(float x) { PrintStream out = checkAccess(); if (out == this) { super.println(x); } else { out.println(x); } } @Override public final void println(int x) { PrintStream out = checkAccess(); if (out == this) { super.println(x); } else { out.println(x); } } @Override public final void println(long x) { PrintStream out = checkAccess(); if (out == this) { super.println(x); } else { out.println(x); } } @Override public final void println(Object x) { PrintStream out = checkAccess(); if (out == this) { super.println(x); } else { out.println(x); } } @Override public final void println(String x) { PrintStream out = checkAccess(); if (out == this) { super.println(x); } else { out.println(x); } } @Override public final void println(boolean x) { PrintStream out = checkAccess(); if (out == this) { super.println(x); } else { out.println(x); } } @Override public final void write(byte[] buf, int off, int len) { PrintStream out = checkAccess(); if (out == this) { super.write(buf, off, len); } else { out.write(buf, off, len); } } @Override public final void write(int b) { PrintStream out = checkAccess(); if (out == this) { super.write(b); } else { out.write(b); } } private PrintStream checkAccess() { SecurityManager securityManager = System.getSecurityManager(); if (securityManager != null && securityManager instanceof RobocodeSecurityManager) { RobocodeSecurityManager rsm = (RobocodeSecurityManager) securityManager; PrintStream out = rsm.getRobotOutputStream(); return (out == null) ? this : out; } return this; } } robocode/robocode/robocode/security/RobocodeSecurityManager.java0000644000175000017500000005355511130241112024524 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup * - Added checkPackageAccess() to limit access to the robocode.util Robocode * package only * - Ported to Java 5.0 * - Removed unnecessary method synchronization * - Fixed potential NullPointerException in getFileOutputStream() * - Added setStatus() * - Fixed synchronization issue with accessing battleThread * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap * Pavel Savara * - Re-work of robot interfaces * - we create safe AWT queue for robot's thread group *******************************************************************************/ package robocode.security; import robocode.RobocodeFileOutputStream; import robocode.common.ObjectCloner; import robocode.exception.RobotException; import robocode.io.RobocodeObjectInputStream; import robocode.manager.IThreadManager; import robocode.peer.BulletCommand; import robocode.control.snapshot.BulletState; import robocode.peer.DebugProperty; import robocode.peer.ExecResults; import robocode.peer.proxies.IHostedThread; import robocode.peer.robot.RobotFileSystemManager; import robocode.peer.robot.TeamMessage; import java.awt.*; import java.io.*; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.security.AccessControlException; import java.security.Permission; import java.util.*; import java.util.List; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Robert D. Maupin (contributor) * @author Pavel Savara (contributor) */ public class RobocodeSecurityManager extends SecurityManager { private final PrintStream syserr = System.err; private final IThreadManager threadManager; private final Object safeSecurityContext; private final boolean enabled; private final boolean experimental; private final Map outputStreamThreads = Collections.synchronizedMap( new HashMap()); private final List safeThreads = Collections.synchronizedList(new ArrayList()); private final List safeThreadGroups = Collections.synchronizedList(new ArrayList()); private final Set alowedPackages = new HashSet(); private Thread battleThread; public RobocodeSecurityManager(Thread safeThread, IThreadManager threadManager, boolean enabled, boolean experimental) { super(); this.threadManager = threadManager; this.enabled = enabled; this.experimental = experimental; safeSecurityContext = getSecurityContext(); // Loading of classes to prevent security issues on untrusted threads try { final ClassLoader scl = ClassLoader.getSystemClassLoader(); scl.loadClass(BulletState.class.getName()); scl.loadClass(BulletCommand.class.getName()); scl.loadClass(ExecResults.class.getName()); scl.loadClass(TeamMessage.class.getName()); scl.loadClass(DebugProperty.class.getName()); scl.loadClass(RobotException.class.getName()); scl.loadClass(RobocodeObjectInputStream.class.getName()); scl.loadClass(ObjectCloner.class.getName()); Toolkit.getDefaultToolkit(); } catch (ClassNotFoundException e) { throw new Error("We can't load important classes", e); } alowedPackages.add("util"); alowedPackages.add("robotinterfaces"); alowedPackages.add("robotpaint"); // alowedPackages.add("robocodeGL"); if (experimental) { alowedPackages.add("robotinterfaces.peer"); } ThreadGroup tg = Thread.currentThread().getThreadGroup(); while (tg != null) { addSafeThreadGroup(tg); tg = tg.getParent(); } // we need to excersize it, to load all used classes on this thread. isSafeThread(); isSafeContext(); } private synchronized void addRobocodeOutputStream(RobocodeFileOutputStream o) { outputStreamThreads.put(Thread.currentThread(), o); } public void addSafeThread(Thread safeThread) { checkPermission(new RobocodePermission("addSafeThread")); safeThreads.add(safeThread); } public void addSafeThreadGroup(ThreadGroup safeThreadGroup) { checkPermission(new RobocodePermission("addSafeThreadGroup")); safeThreadGroups.add(safeThreadGroup); } @Override public void checkAccess(Thread t) { if (!enabled) { return; } Thread c = Thread.currentThread(); if (isSafeThread(c)) { return; } if (isSafeContext()) { return; } super.checkAccess(t); IHostedThread robotProxy = threadManager.getRobotProxy(c); if (robotProxy == null) { robotProxy = threadManager.getLoadingRobotProxy(c); if (robotProxy != null) { throw new AccessControlException( "Preventing " + robotProxy.getStatics().getName() + " from access to thread: " + t.getName()); } checkPermission(new RuntimePermission("modifyThread")); return; } ThreadGroup cg = c.getThreadGroup(); ThreadGroup tg = t.getThreadGroup(); if (cg == null || tg == null) { throw new AccessControlException( "Preventing " + Thread.currentThread().getName() + " from access to a thread, because threadgroup is null."); } if (cg != tg) { throw new AccessControlException( "Preventing " + Thread.currentThread().getName() + " from access to a thread, because threadgroup is different."); } if (cg.equals(tg)) { return; } throw new AccessControlException( "Preventing " + Thread.currentThread().getName() + " from access to threadgroup: " + tg.getName() + ". You must use your own ThreadGroup."); } @Override public void checkAccess(ThreadGroup g) { if (!enabled) { return; } Thread c = Thread.currentThread(); if (isSafeThread(c)) { return; } if (isSafeContext()) { return; } super.checkAccess(g); ThreadGroup cg = c.getThreadGroup(); if (cg == null) { // What the heck is going on here? JDK 1.3 is sending me a dead thread. // This crashes the entire jvm if I don't return here. return; } IHostedThread robotProxy = threadManager.getRobotProxy(c); if (robotProxy == null) { robotProxy = threadManager.getLoadingRobotProxy(c); if (robotProxy != null) { throw new AccessControlException( "Preventing " + robotProxy.getStatics().getName() + " from access to threadgroup: " + g.getName()); } checkPermission(new RuntimePermission("modifyThreadGroup")); return; } if (g == null) { throw new NullPointerException("Thread group can't be null"); } if (cg.equals(g)) { if (g.activeCount() > 5) { throw new AccessControlException( "Preventing " + Thread.currentThread().getName() + " from access to threadgroup: " + g.getName() + ". You may only create 5 threads."); } return; } robotProxy.drainEnergy(); throw new AccessControlException( "Preventing " + Thread.currentThread().getName() + " from access to threadgroup: " + g.getName() + " -- you must use your own ThreadGroup."); } /** * Robocode's main security: checkPermission * If the calling thread is in our list of safe threads, allow permission. * Else deny, with a few exceptions. */ @Override public void checkPermission(Permission perm, Object context) { if (!enabled) { return; } syserr.println("Checking permission " + perm + " for context " + context); checkPermission(perm); } @Override public void checkPermission(Permission perm) { // For John Burkey at Apple if (!enabled) { return; } // Check if the current running thread is a safe thread if (isSafeThread()) { return; } // First, if we're running in Robocode's security context, // AND the thread is a safe thread, permission granted. // Essentially this optimizes the security manager for Robocode. if (isSafeContext()) { return; } // Ok, could be system, could be robot // We'll check the system policy (RobocodeSecurityPolicy) // This allows doPrivileged blocks to work. try { super.checkPermission(perm); } catch (SecurityException e) { // ok wa have a problem handleSecurityProblem(perm); } } private void handleSecurityProblem(Permission perm) { // For development purposes, allow read any file if override is set. if (perm instanceof FilePermission) { FilePermission fp = (FilePermission) perm; if (fp.getActions().equals("read")) { if (System.getProperty("OVERRIDEFILEREADSECURITY", "false").equals("true")) { return; } } } // Allow reading of properties. if (perm instanceof PropertyPermission) { if (perm.getActions().equals("read")) { return; } } if (perm instanceof RuntimePermission) { if (perm.getName() != null && perm.getName().length() >= 24) { if (perm.getName().substring(0, 24).equals("accessClassInPackage.sun")) { return; } } } // Ok, we need to figure out who our robot is. Thread c = Thread.currentThread(); IHostedThread robotProxy = threadManager.getLoadedOrLoadingRobotProxy(c); // We don't know who this is, so deny permission. if (robotProxy == null) { if (perm instanceof RobocodePermission) { if (perm.getName().equals("System.out") || perm.getName().equals("System.err") || perm.getName().equals("System.in")) { return; } } // Show warning on console. syserr.println("Preventing unknown thread " + Thread.currentThread().getName() + " from access: " + perm); syserr.flush(); // Attempt to stop the window from displaying // This is a hack. if (perm instanceof java.awt.AWTPermission) { if (perm.getName().equals("showWindowWithoutWarningBanner")) { throw new ThreadDeath(); } } // Throw the exception throw new AccessControlException( "Preventing unknown thread " + Thread.currentThread().getName() + " from access: " + perm); } // At this point, we have robotProxy set to the RobotProxy object requesting permission. // FilePermission access request. if (perm instanceof FilePermission) { FilePermission fp = (FilePermission) perm; // Robot wants access to read something if (fp.getActions().equals("read")) { // Get the fileSystemManager RobotFileSystemManager fileSystemManager = robotProxy.getRobotFileSystemManager(); // If there is no readable directory, deny access. if (fileSystemManager.getReadableDirectory() == null) { robotProxy.drainEnergy(); throw new AccessControlException( "Preventing " + robotProxy.getStatics().getName() + " from access: " + perm + ": Robots that are not in a package may not read any files."); } // If this is a readable file, return. if (fileSystemManager.isReadable(fp.getName())) { return; } // Else disable robot robotProxy.drainEnergy(); throw new AccessControlException( "Preventing " + robotProxy.getStatics().getName() + " from access: " + perm + ": You may only read files in your own root package directory. "); } // Robot wants access to write something else if (fp.getActions().equals("write")) { // Get the RobocodeOutputStream the robot is trying to use. RobocodeFileOutputStream o = getRobocodeOutputStream(); // There isn't one. Deny access. if (o == null) { robotProxy.drainEnergy(); throw new AccessControlException( "Preventing " + robotProxy.getStatics().getName() + " from access: " + perm + ": You must use a RobocodeOutputStream."); } // Remove the RobocodeOutputStream so future access checks will fail. removeRobocodeOutputStream(); // Get the fileSystemManager RobotFileSystemManager fileSystemManager = robotProxy.getRobotFileSystemManager(); // If there is no writable directory, deny access if (fileSystemManager.getWritableDirectory() == null) { robotProxy.drainEnergy(); throw new AccessControlException( "Preventing " + robotProxy.getStatics().getName() + " from access: " + perm + ": Robots that are not in a package may not write any files."); } // If this is a writable file, permit access if (fileSystemManager.isWritable(fp.getName())) { return; } // else it's not writable, deny access. // We are creating the directory. if (fileSystemManager.getWritableDirectory().toString().equals(fp.getName())) { return; } // Not a writable directory. robotProxy.drainEnergy(); // robotProxy.getOut().println("I would allow access to: " + fileSystemManager.getWritableDirectory()); robotProxy.getOut().println( "Preventing " + robotProxy.getStatics().getName() + " from access: " + perm + ": You may only write files in your own data directory. "); throw new AccessControlException( "Preventing " + robotProxy.getStatics().getName() + " from access: " + perm + ": You may only write files in your own data directory. "); } // Robot wants access to write something else if (fp.getActions().equals("delete")) { // Get the fileSystemManager RobotFileSystemManager fileSystemManager = robotProxy.getRobotFileSystemManager(); // If there is no writable directory, deny access if (fileSystemManager.getWritableDirectory() == null) { robotProxy.drainEnergy(); throw new AccessControlException( "Preventing " + robotProxy.getStatics().getName() + " from access: " + perm + ": Robots that are not in a package may not delete any files."); } // If this is a writable file, permit access if (fileSystemManager.isWritable(fp.getName())) { return; } // else it's not writable, deny access. // We are deleting our data directory. if (fileSystemManager.getWritableDirectory().toString().equals(fp.getName())) { // robotProxy.out.println("SYSTEM: Please let me know if you see this string. Thanks. -Mat"); return; } // Not a writable directory. robotProxy.drainEnergy(); throw new AccessControlException( "Preventing " + robotProxy.getStatics().getName() + " from access: " + perm + ": You may only delete files in your own data directory. "); } } if (perm instanceof RobocodePermission) { if (perm.getName().equals("System.out") || perm.getName().equals("System.err")) { robotProxy.println("SYSTEM: You cannot write to System.out or System.err."); robotProxy.println("SYSTEM: Please use out.println instead of System.out.println"); throw new AccessControlException( "Preventing " + robotProxy.getStatics().getName() + " from access: " + perm); } else if (perm.getName().equals("System.in")) { robotProxy.println("SYSTEM: You cannot read from System.in."); throw new AccessControlException( "Preventing " + robotProxy.getStatics().getName() + " from access: " + perm); } } // Permission denied. syserr.println("Preventing " + robotProxy.getStatics().getName() + " from access: " + perm); robotProxy.drainEnergy(); if (perm instanceof java.awt.AWTPermission) { if (perm.getName().equals("showWindowWithoutWarningBanner")) { throw new ThreadDeath(); } } throw new AccessControlException("Preventing " + Thread.currentThread().getName() + " from access: " + perm); } public void getFileOutputStream(RobocodeFileOutputStream o, boolean append) throws FileNotFoundException { if (o == null) { throw new NullPointerException("Null RobocodeFileOutputStream"); } addRobocodeOutputStream(o); FileOutputStream fos; try { fos = new FileOutputStream(o.getName(), append); } catch (FileNotFoundException e) { IHostedThread robotProxy = threadManager.getRobotProxy(Thread.currentThread()); if (robotProxy == null) { syserr.println("RobotProxy is null"); return; } File dir = robotProxy.getRobotFileSystemManager().getWritableDirectory(); addRobocodeOutputStream(o); // it's gone already... robotProxy.println("SYSTEM: Creating a data directory for you."); // noinspection ResultOfMethodCallIgnored dir.mkdir(); // result direcotry was already there ? addRobocodeOutputStream(o); // one more time... fos = new FileOutputStream(o.getName(), append); } o.setFileOutputStream(fos); } private synchronized RobocodeFileOutputStream getRobocodeOutputStream() { return outputStreamThreads.get(Thread.currentThread()); } public static boolean isSafeThreadSt() { RobocodeSecurityManager rsm = (RobocodeSecurityManager) System.getSecurityManager(); return rsm.isSafeThread(); } private boolean isSafeThread() { return isSafeThread(Thread.currentThread()); } private boolean isSafeThread(Thread c) { try { if (c == battleThread) { return true; } if (safeThreads.contains(c)) { return true; } for (ThreadGroup tg : safeThreadGroups) { if (c.getThreadGroup() == tg) { safeThreads.add(c); return true; } } return false; } catch (Exception e) { syserr.println("Exception checking safe thread: "); e.printStackTrace(syserr); return false; } } private boolean isSafeContext() { try { return getSecurityContext().equals(safeSecurityContext); } catch (Exception e) { syserr.println("Exception checking safe thread: "); e.printStackTrace(syserr); return false; } } private synchronized void removeRobocodeOutputStream() { outputStreamThreads.remove(Thread.currentThread()); } public void removeSafeThread(Thread safeThread) { checkPermission(new RobocodePermission("removeSafeThread")); safeThreads.remove(safeThread); } public synchronized void setBattleThread(Thread newBattleThread) { checkPermission(new RobocodePermission("setBattleThread")); battleThread = newBattleThread; } public static void printlnToRobot(String s) { SecurityManager m = System.getSecurityManager(); if (m instanceof RobocodeSecurityManager) { RobocodeSecurityManager rsm = (RobocodeSecurityManager) m; final PrintStream stream = rsm.getRobotOutputStream(); if (stream != null) { stream.println(s); } } } public PrintStream getRobotOutputStream() { Thread c = Thread.currentThread(); if (isSafeThread(c)) { return null; } if (threadManager == null) { syserr.println("Null thread manager."); return null; } IHostedThread robotProxy = threadManager.getLoadedOrLoadingRobotProxy(c); return (robotProxy != null) ? robotProxy.getOut() : null; } @Override public void checkPackageAccess(String pkg) { if (!enabled) { return; } if (pkg.equals("java.lang")) { return; } if (isSafeThread()) { return; } if (isSafeContext()) { return; } super.checkPackageAccess(pkg); // Access to robocode sub package? if (pkg.startsWith("robocode.")) { String subPkg = pkg.substring(9); if (!alowedPackages.contains(subPkg)) { Thread c = Thread.currentThread(); IHostedThread robotProxy = threadManager.getLoadedOrLoadingRobotProxy(c); if (robotProxy != null) { robotProxy.drainEnergy(); if (!experimental && subPkg.equals("robotinterfaces.peer")) { robotProxy.println( "SYSTEM: " + robotProxy.getStatics().getName() + " is not allowed to access the internal Robocode package: " + pkg + "\n" + "SYSTEM: Perhaps you did not set the -DEXPERIMENTAL=true option in the robocode.bat or robocode.sh file?\n" + "SYSTEM: ----"); } } throw new AccessControlException( "Preventing " + Thread.currentThread().getName() + " from access to the internal Robocode pakage: " + pkg); } } } public static Object createNewAppContext() { // same as SunToolkit.createNewAppContext(); // we can't assume that we are always on Suns JVM, so we can't reference it directly // why we call that ? Because SunToolkit is caching AWTQueue instance form main thread group and use it on robots threads // and he is not asking us for checkAwtEventQueueAccess above try { final Class sunToolkit = ClassLoader.getSystemClassLoader().loadClass("sun.awt.SunToolkit"); final Method createNewAppContext = sunToolkit.getDeclaredMethod("createNewAppContext"); return createNewAppContext.invoke(null); } catch (ClassNotFoundException e) { // we are not on sun JVM return -1; } catch (NoSuchMethodException e) { throw new Error("Looks like SunVM but unable to assure secured AWTQueue, sorry", e); } catch (InvocationTargetException e) { throw new Error("Looks like SunVM but unable to assure secured AWTQueue, sorry", e); } catch (IllegalAccessException e) { throw new Error("Looks like SunVM but unable to assure secured AWTQueue, sorry", e); } // end: same as SunToolkit.createNewAppContext(); } public static boolean disposeAppContext(Object appContext) { // same as AppContext.dispose(); try { final Class sunToolkit = ClassLoader.getSystemClassLoader().loadClass("sun.awt.AppContext"); final Method dispose = sunToolkit.getDeclaredMethod("dispose"); dispose.invoke(appContext); return true; } catch (ClassNotFoundException ignore) {} catch (NoSuchMethodException ignore) {} catch (InvocationTargetException ignore) {} catch (IllegalAccessException ignore) {} return false; // end: same as AppContext.dispose(); } } robocode/robocode/robocode/security/LoggingThreadGroup.java0000644000175000017500000000165111130241112023466 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.security; import robocode.io.Logger; /** * @author Pavel Savara (original) */ public class LoggingThreadGroup extends ThreadGroup { public LoggingThreadGroup(String name) { super(name); } public void uncaughtException(Thread t, Throwable e) { Logger.logError("UncaughtException on thread " + t.getClass(), e); } } robocode/robocode/robocode/security/RobocodeClassLoader.java0000644000175000017500000002070211130241112023602 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup * - Ported to Java 5.0 * - Updated to use methods from the Logger, which replaces logger methods * that have been (re)moved from the robocode.util.Utils class * - Fixed method synchronization issues with several member fields * Matthew Reeder * - Fixed compiler problem with protectionDomain * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap * Nathaniel Troutman * - Added cleanup() method for cleaning up references to internal classes * to prevent circular references causing memory leaks * - Added cleanup of hidden ClassLoader.class.classes *******************************************************************************/ package robocode.security; import static robocode.io.Logger.logError; import static robocode.io.Logger.logMessage; import robocode.packager.ClassAnalyzer; import robocode.peer.robot.RobotClassManager; import robocode.repository.RobotFileSpecification; import java.io.*; import java.lang.reflect.Field; import java.net.MalformedURLException; import java.security.CodeSource; import java.security.Permissions; import java.security.ProtectionDomain; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Matthew Reeder (contributor) * @author Robert D. Maupin (contributor) * @author Nathaniel Troutman (contributor) */ public class RobocodeClassLoader extends ClassLoader { private final Map> cachedClasses = new HashMap>(); private RobotFileSpecification robotFileSpecification; private RobotClassManager robotClassManager; private String rootPackageDirectory; private String rootDirectory; private String classDirectory; private ProtectionDomain protectionDomain; private long uid1; private long uid2; // The hidden ClassLoader.class.classes field private Field classesField = null; public RobocodeClassLoader(ClassLoader parent, RobotClassManager robotClassManager) { super(parent); this.robotClassManager = robotClassManager; this.robotFileSpecification = robotClassManager.getRobotSpecification(); // Deep within the class loader is a vector of classes, and is VM // implementation specific, so its not in every VM. However, if a VM // does have it then we have to make sure we clear it during cleanup(). Field[] fields = ClassLoader.class.getDeclaredFields(); for (Field field : fields) { if (field.getName().equals("classes")) { classesField = field; break; } } if (classesField == null) { logError("RobocodeClassLoader: Failed to find classes field in: " + this); } } public synchronized String getClassDirectory() { return classDirectory; } @Override public InputStream getResourceAsStream(String resource) { logMessage("RobocodeClassLoader: getResourceAsStream: " + resource); return super.getResourceAsStream(resource); } public synchronized String getRootDirectory() { return rootDirectory; } public synchronized String getRootPackageDirectory() { return rootPackageDirectory; } @Override public synchronized Class loadClass(String className, boolean resolve) throws ClassNotFoundException { if (className.indexOf(getRobotClassManager().getRootPackage() + ".") == 0) { return loadRobotClass(className, false); } try { return super.loadClass(className, resolve); } catch (ClassNotFoundException e) { return loadRobotClass(className, false); } } public synchronized Class loadRobotClass(String name, boolean toplevel) throws ClassNotFoundException { if (cachedClasses.containsKey(name)) { return cachedClasses.get(name); } Class c; File f; if (toplevel) { uid1 = 0; uid2 = 0; } if (!name.equals(robotClassManager.getFullClassName())) { if (robotClassManager.getRootPackage() == null) { logError( robotClassManager.getFullClassName() + " is not in a package, but is trying to reference class " + name); logError("To do this in Robocode, you must put your robot into a package."); throw new ClassNotFoundException( robotClassManager.getFullClassName() + "is not in a package, but is trying to reference class " + name); } } String filename = name.replace('.', File.separatorChar) + ".class"; String classPath = robotFileSpecification.getRobotClassPath(); if (classPath.indexOf(File.pathSeparator) >= 0) { throw new ClassNotFoundException( "A robot cannot have multiple directories or jars in it's classpath: " + name); } f = new File(classPath + File.separator + filename); if (protectionDomain == null) { try { // Java 1.4 only: // If we want to use a Policy object to control access, we could do this: // protectionDomain = new ProtectionDomain(new CodeSource(f.toURL(),null),new Permissions(),this,null); // We *cannot* do this anymore, as the robots directory is now allowed to be in the classpath // But it's easier to use the statically-linked version, to simply say // that this class is not allowed to do anything. // Note that we only create one protection domain for this classloader, so the // "code source" is simply the robot itself. Permissions p = new Permissions(); protectionDomain = new ProtectionDomain( new CodeSource(f.toURI().toURL(), (java.security.cert.Certificate[]) null), p); } catch (MalformedURLException e) { throw new ClassNotFoundException("Unable to build protection domain", e); } } int size = (int) (f.length()); uid1 += size; byte buff[] = new byte[size]; FileInputStream fis = null; DataInputStream dis = null; try { fis = new FileInputStream(f); dis = new DataInputStream(fis); dis.readFully(buff); dis.close(); List v = ClassAnalyzer.getReferencedClasses(buff); robotClassManager.addReferencedClasses(v); uid1 += v.size(); for (byte element : buff) { uid2 += element; } c = defineClass(name, buff, 0, buff.length, protectionDomain); robotClassManager.addResolvedClass(name); if (name.equals(robotClassManager.getFullClassName())) { if (robotClassManager.getRootPackage() == null) { rootPackageDirectory = null; classDirectory = null; } else { rootPackageDirectory = new File(classPath + File.separator + robotClassManager.getRootPackage() + File.separator).getCanonicalPath(); classDirectory = new File(classPath + File.separator + robotClassManager.getClassNameManager().getFullPackage().replace('.', File.separatorChar) + File.separator).getCanonicalPath(); } rootDirectory = new File(classPath).getCanonicalPath(); } if (toplevel) { robotClassManager.loadUnresolvedClasses(); robotClassManager.setUid(uid1 + "" + uid2); } cachedClasses.put(name, c); return c; } catch (IOException e) { throw new ClassNotFoundException("Could not find: " + name, e); } finally { if (fis != null) { try { fis.close(); } catch (IOException ignored) {} } if (dis != null) { try { dis.close(); } catch (IOException ignored) {} } } } private synchronized RobotClassManager getRobotClassManager() { return robotClassManager; } public void cleanup() { if (cachedClasses != null) { cachedClasses.clear(); } // Set ClassLoader.class.classes to null to prevent memory leaks if (classesField != null) { try { // don't do that Internal Error (44494354494F4E4152590E4350500100) // classesField.setAccessible(true); classesField.set(this, null); } catch (IllegalArgumentException e) {// logError(e); } catch (IllegalAccessException e) {// logError(e); } } robotClassManager = null; robotFileSpecification = null; } } robocode/robocode/robocode/security/RobocodeSecurityPolicy.java0000644000175000017500000000550511130241112024401 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Ported for Java 5.0 * - Code cleanup * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap *******************************************************************************/ package robocode.security; import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.security.*; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Robert D. Maupin (contributor) */ public class RobocodeSecurityPolicy extends Policy { private final Policy parentPolicy; private final PermissionCollection permissionCollection; private final List trustedCodeUrls; public RobocodeSecurityPolicy(Policy parentPolicy) { this.parentPolicy = parentPolicy; this.permissionCollection = new Permissions(); this.permissionCollection.add(new AllPermission()); trustedCodeUrls = new ArrayList(); CodeSource codeSrc = getClass().getProtectionDomain().getCodeSource(); if (codeSrc != null) { trustedCodeUrls.add(codeSrc.getLocation()); } String classPath = System.getProperty("java.class.path"); StringTokenizer tokenizer = new StringTokenizer(classPath, File.pathSeparator); // TODO skip robots path if is there while (tokenizer.hasMoreTokens()) { try { URL u = new File(tokenizer.nextToken()).toURI().toURL(); if (!trustedCodeUrls.contains(u)) { trustedCodeUrls.add(u); } } catch (MalformedURLException ignored) {} } } @Override public PermissionCollection getPermissions(ProtectionDomain domain) { return getPermissions(domain.getCodeSource()); } @Override public PermissionCollection getPermissions(CodeSource codeSource) { // Trust everyone on the classpath return (trustedCodeUrls.contains(codeSource.getLocation())) ? permissionCollection : parentPolicy.getPermissions(codeSource); } @Override public boolean implies(ProtectionDomain domain, Permission permission) { // Trust everyone on the classpath return (trustedCodeUrls.contains(domain.getCodeSource().getLocation())); } @Override public void refresh() { parentPolicy.refresh(); } } robocode/robocode/robocode/security/RobocodePermission.java0000644000175000017500000000667211130241112023550 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation *******************************************************************************/ package robocode.security; /** * @author Mathew A. Nelson (original) */ @SuppressWarnings("serial") public class RobocodePermission extends java.security.Permission { public RobocodePermission(String name) { super(name); } /** * Checks two Permission objects for equality. *

* Do not use the {@code equals} method for making access control * decisions; use the {@code implies} method. * * @param obj the object we are testing for equality with this object. * @return true if both Permission objects are equivalent. */ @Override public boolean equals(Object obj) { return false; } /** * Returns the actions as a String. This is abstract * so subclasses can defer creating a String representation until * one is needed. Subclasses should always return actions in what they * consider to be their * canonical form. For example, two FilePermission objects created via * the following: *

*

	 *   perm1 = new FilePermission(p1,"read,write");
	 *   perm2 = new FilePermission(p2,"write,read");
	 * 
*

* both return * "read,write" when the {code getActions()} method is invoked. * * @return the actions of this Permission. */ @Override public String getActions() { return null; } /** * Returns the hash code value for this Permission object. *

* The required {@code hashCode} behavior for Permission Objects is * the following:

*

    *
  • Whenever it is invoked on the same Permission object more than * once during an execution of a Java application, the * {@code hashCode} method * must consistently return the same integer. This integer need not * remain consistent from one execution of an application to another * execution of the same application.

    *

  • If two Permission objects are equal according to the {@code equals} * method, then calling the {@code hashCode} method on each of the * two Permission objects must produce the same integer result. *
* * @return a hash code value for this object. */ @Override public int hashCode() { return 0; } /** * Checks if the specified permission's actions are "implied by" * this object's actions. *

* This must be implemented by subclasses of Permission, as they are the * only ones that can impose semantics on a Permission object. *

*

The {@code implies} method is used by the AccessController to determine * whether or not a requested permission is implied by another permission that * is known to be valid in the current execution context. * * @param permission the permission to check against. * @return true if the specified permission is implied by this object, * false if not. */ @Override public boolean implies(java.security.Permission permission) { return false; } } robocode/robocode/robocode/security/SecureInputStream.java0000644000175000017500000000553411130241112023361 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation *******************************************************************************/ package robocode.security; import java.io.IOException; import java.io.InputStream; /** * @author Mathew A. Nelson (original) */ public class SecureInputStream extends java.io.InputStream { private RobocodePermission inputPermission = null; private InputStream in = null; /** * SecureInputStream constructor comment. * * @param in original */ public SecureInputStream(InputStream in) { super(); this.in = in; this.inputPermission = new RobocodePermission("System.in"); } @Override public final int available() throws IOException { checkAccess(); return in.available(); } private void checkAccess() { SecurityManager securityManager = System.getSecurityManager(); if (securityManager != null) { securityManager.checkPermission(inputPermission); } } @Override public final void close() throws IOException { checkAccess(); in.close(); } @Override public final synchronized void mark(int readlimit) { checkAccess(); in.mark(readlimit); } @Override public final boolean markSupported() { checkAccess(); return in.markSupported(); } /** * Reads the next byte of data from the input stream. The value byte is * returned as an {@code int} in the range 0 to 255. If no byte is available * because the end of the stream has been reached, the value -1 is returned. * This method blocks until input data is available, the end of the stream * is detected, or an exception is thrown. *

*

A subclass must provide an implementation of this method. * * @return the next byte of data, or -1 if the end of the stream is reached. * @throws IOException if an I/O error occurs. */ @Override public final int read() throws java.io.IOException { checkAccess(); return in.read(); } @Override public final int read(byte[] b) throws IOException { checkAccess(); return in.read(b); } @Override public final int read(byte[] b, int off, int len) throws IOException { checkAccess(); return in.read(b, off, len); } @Override public final synchronized void reset() throws IOException { checkAccess(); in.reset(); } @Override public final long skip(long n) throws IOException { checkAccess(); return in.skip(n); } } robocode/robocode/robocode/MouseClickedEvent.java0000644000175000017500000000413011130241112021430 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode; import robocode.peer.RobotStatics; import robocode.robotinterfaces.IBasicRobot; import robocode.robotinterfaces.IInteractiveEvents; import robocode.robotinterfaces.IInteractiveRobot; import java.awt.*; /** * A MouseClickedEvent is sent to {@link Robot#onMouseClicked(java.awt.event.MouseEvent) * onMouseClicked()} when the mouse is clicked inside the battle view. * * @author Pavel Savara (original) * @see MousePressedEvent * @see MouseReleasedEvent * @see MouseEnteredEvent * @see MouseExitedEvent * @see MouseMovedEvent * @see MouseDraggedEvent * @see MouseWheelMovedEvent * @since 1.6.1 */ public final class MouseClickedEvent extends MouseEvent { private static final long serialVersionUID = 1L; private final static int DEFAULT_PRIORITY = 98; /** * Called by the game to create a new MouseClickedEvent. * * @param source the source mouse event originating from the AWT. */ public MouseClickedEvent(java.awt.event.MouseEvent source) { super(source); } /** * {@inheritDoc} */ @Override final int getDefaultPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override final void dispatch(IBasicRobot robot, RobotStatics statics, Graphics2D graphics) { if (statics.isInteractiveRobot()) { IInteractiveEvents listener = ((IInteractiveRobot) robot).getInteractiveEventListener(); if (listener != null) { listener.onMouseClicked(getSourceEvent()); } } } } robocode/robocode/robocode/Event.java0000644000175000017500000001563311130241112017152 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Optimized for Java 5 * - Updated Javadocs * - Removed try-catch(ClassCastException) from compareTo() * - Changed compareTo() to first and foremost compare the events based on * their event times, and secondly to compare the priorities if the event * times are equals. Previously, the priorities were compared first, and * secondly the event times if the priorities were equal. * This change was made to sort the event queues of the robots in * chronological so that the older events are listed before newer events *******************************************************************************/ package robocode; import robocode.peer.RobotStatics; import robocode.peer.robot.IHiddenEventHelper; import robocode.robotinterfaces.IBasicRobot; import java.awt.*; import java.io.Serializable; import java.util.Hashtable; /** * The superclass of all Robocode events. * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ public abstract class Event implements Comparable, Serializable { private static final long serialVersionUID = 1L; private long time; private int priority; /** * Called by the game to create a new Event. */ public Event() { super(); } /** * Compares this event to another event regarding precedence. * The event precedence is first and foremost determined by the event time, * secondly the event priority, and lastly specific event information. *

* This method will first compare the time of each event. If the event time * is the same for both events, then this method compared the priority of * each event. If the event priorities are equals, then this method will * compare the two event based on specific event information. *

* This method is called by the game in order to sort the event queue of a * robot to make sure the events are listed in chronological order. *

* * @param event the event to compare to this event. * @return a negative value if this event has higher precedence, i.e. must * be listed before the specified event. A positive value if this event * has a lower precedence, i.e. must be listed after the specified event. * 0 means that the precedence of the two events are equal. */ public int compareTo(Event event) { // Compare the time difference which has precedence over priority. int timeDiff = (int) (time - event.time); if (timeDiff != 0) { return timeDiff; // Time differ } // Same time -> Compare the difference in priority int priorityDiff = event.getPriority() - getPriority(); if (priorityDiff != 0) { return priorityDiff; // Priority differ } // Same time and priority -> Compare specific event types // look at overrides in ScannedRobotEvent and HitRobotEvent // No difference found return 0; } /** * Returns the priority of this event. * An event priority is a value from 0 - 99. The higher value, the higher * priority. The default priority is 80. * * @return the priority of this event */ public int getPriority() { return priority; } /** * Returns the time this event occurred. * * @return the time this event occurred. */ public final long getTime() { return time; } /** * Sets the priority of this event, which must be between 0 and 99. * * @param newPriority the new priority of this event. */ // this method is invisible on RobotAPI final void setPriority(int newPriority) { if (newPriority < 0) { System.out.println("SYSTEM: Priority must be between 0 and 99"); System.out.println("SYSTEM: Priority for " + this.getClass().getName() + " will be 0"); newPriority = 0; } else if (newPriority > 99) { System.out.println("SYSTEM: Priority must be between 0 and 99"); System.out.println("SYSTEM: Priority for " + this.getClass().getName() + " will be 99"); newPriority = 99; } priority = newPriority; } /** * Sets the time when this event occurred. * * @param time the time when this event occurred. */ // this method is invisible on RobotAPI private void setTime(long time) { this.time = time; } /** * Dispatch this event for a robot, it's statistics, and graphics context. * * @param robot the robot to dispatch to. * @param statics the statistics to dispatch to. * @param graphics the graphics to dispatch to. */ // this method is invisible on RobotAPI abstract void dispatch(IBasicRobot robot, RobotStatics statics, Graphics2D graphics); /** * Returns the default priority of this event class. * * @return the default priority of this event class. */ // this method is invisible on RobotAPI abstract int getDefaultPriority(); /** * Checks if this event must be delivered event after timeout. * * @return {@code true} when this event must be delivered even after timeout; {@code false} otherwise. */ // this method is invisible on RobotAPI boolean isCriticalEvent() { return false; } /** * This method is replacing bullet on event with bullet instance which was passed to robot as result of fire command * @param bullets collection containing all moving bullets known to robot */ // this method is invisible on RobotAPI void updateBullets(Hashtable bullets) {} /** * Creates a hidden event helper for accessing hidden methods on this object. * * @return a hidden event helper. */ // this method is invisible on RobotAPI static IHiddenEventHelper createHiddenHelper() { return new HiddenEventHelper(); } // this class is invisible on RobotAPI private static class HiddenEventHelper implements IHiddenEventHelper { public void setTime(Event event, long newTime) { event.setTime(newTime); } public void setDefaultPriority(Event event) { event.setPriority(event.getDefaultPriority()); } public void setPriority(Event event, int newPriority) { event.setPriority(newPriority); } public boolean isCriticalEvent(Event event) { return event.isCriticalEvent(); } public void dispatch(Event event, IBasicRobot robot, RobotStatics statics, Graphics2D graphics) { event.dispatch(robot, statics, graphics); } public void updateBullets(Event event, Hashtable bullets) { event.updateBullets(bullets); } } } robocode/robocode/robocode/Robocode.java0000644000175000017500000002777711130241112017641 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup * - Removed check for the system property "SINGLEBUFFER", as it is not used * anymore * - Replaced the noDisplay with manager.setEnableGUI() and isGUIEnabled() * - Replaced the -fps option with the -tps option * - Added -nosound option and disables sound i the -nogui is specified * - Updated to use methods from WindowUtil, FileUtil, Logger, which replaces * methods that has been (re)moved from the robocode.util.Utils class * - Moved the printRunningThreads() from robocode.util.Utils into this class * and added javadoc for it * - Added playing theme music at the startup, if music is provided * - Changed to use FileUtil.getRobotsDir() * - Setting the results file is now independent of setting the battle file * - Robocode now returns with an error message if a specified battle file * could not be found * - Extended the usage / syntax for using Robocode from a console *******************************************************************************/ package robocode; import robocode.control.events.BattleAdaptor; import robocode.control.events.BattleCompletedEvent; import robocode.control.events.BattleErrorEvent; import robocode.control.events.BattleMessageEvent; import robocode.control.events.BattleStartedEvent; import robocode.dialog.WindowUtil; import robocode.io.FileUtil; import robocode.io.Logger; import robocode.manager.IBattleManager; import robocode.manager.RobocodeManager; import robocode.recording.BattleRecordFormat; import robocode.security.LoggingThreadGroup; import robocode.security.SecurePrintStream; import robocode.ui.BattleResultsTableModel; import java.awt.*; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; /** * Robocode - A programming game involving battling AI tanks.
* Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Pavel Savara (contributor) * @see robocode.sourceforge.net */ public class Robocode { /** * Use the command-line to start Robocode. * The command is: *

	 *    java -Xmx512M -Dsun.io.useCanonCaches=false -jar libs/robocode.jar
	 * 
* * @param args an array of command-line arguments */ public static void main(final String[] args) { ThreadGroup group = new LoggingThreadGroup("Robocode thread group"); new Thread(group, "Robocode main thread") { public void run() { Robocode robocode = new Robocode(); robocode.loadSetup(args); robocode.run(); } }.start(); } private final RobocodeManager manager; private final Setup setup; private final BattleObserver battleObserver = new BattleObserver(); private class Setup { boolean securityOn = true; boolean experimentalOn; boolean minimize; boolean exitOnComplete; String battleFilename; String replayFilename; String resultsFilename; int tps; } private Robocode() { manager = new RobocodeManager(false); setup = new Setup(); } private void run() { try { manager.initSecurity(setup.securityOn, setup.experimentalOn); // Set the Look and Feel (LAF) if (manager.isGUIEnabled()) { robocode.manager.LookAndFeelManager.setLookAndFeel(); } manager.getProperties().setOptionsBattleDesiredTPS(setup.tps); manager.getBattleManager().addListener(battleObserver); if (manager.isGUIEnabled()) { if (!setup.minimize && setup.battleFilename == null) { if (manager.isSoundEnabled()) { manager.getSoundManager().playThemeMusic(); } manager.getWindowManager().showSplashScreen(); } manager.getWindowManager().showRobocodeFrame(true); if (!setup.minimize) { manager.getVersionManager().checkUpdateCheck(); } if (setup.minimize) { manager.getWindowManager().getRobocodeFrame().setState(Frame.ICONIFIED); } // Play the intro battle if a battle file is not specified and this is the first time Robocode is being run if (setup.battleFilename == null && !manager.getProperties().getLastRunVersion().equals(manager.getVersionManager().getVersion())) { manager.getProperties().setLastRunVersion(manager.getVersionManager().getVersion()); manager.saveProperties(); manager.getWindowManager().getRobocodeFrame().runIntroBattle(); } } // Note: At this point the GUI should be opened (if enabled) before starting the battle from a battle file if (setup.battleFilename != null) { if (setup.replayFilename != null) { System.err.println("You cannot run both a battle and replay a battle record in the same time."); System.exit(8); } setup.exitOnComplete = true; IBattleManager battleManager = manager.getBattleManager(); battleManager.setBattleFilename(setup.battleFilename); if (new File(setup.battleFilename).exists()) { battleManager.startNewBattle(battleManager.loadBattleProperties(), false); } else { System.err.println("The specified battle file '" + setup.battleFilename + "' was not be found"); System.exit(8); } } else if (setup.replayFilename != null) { setup.exitOnComplete = true; manager.getRecordManager().loadRecord(setup.replayFilename, BattleRecordFormat.BINARY_ZIP); if (new File(setup.replayFilename).exists()) { manager.getBattleManager().replay(); } else { System.err.println( "The specified battle record file '" + setup.replayFilename + "' was not be found"); System.exit(8); } } } catch (Throwable e) { Logger.logError(e); } } private void loadSetup(String args[]) { final String robocodeDir = System.getProperty("WORKINGDIRECTORY"); if (robocodeDir != null) { changeDirectory(robocodeDir); } if (System.getProperty("NOSECURITY", "false").equals("true")) { WindowUtil.messageWarning( "Robocode is running without a security manager.\n" + "Robots have full access to your system.\n" + "You should only run robots which you trust!"); setup.securityOn = false; } if (System.getProperty("EXPERIMENTAL", "false").equals("true")) { WindowUtil.messageWarning( "Robocode is running in experimental mode.\n" + "Robots have access to their IRobotPeer interfaces.\n" + "You should only run robots which you trust!"); setup.experimentalOn = true; } setup.tps = manager.getProperties().getOptionsBattleDesiredTPS(); for (int i = 0; i < args.length; i++) { if (args[i].equals("-cwd") && (i < args.length + 1)) { changeDirectory(args[i + 1]); i++; } else if (args[i].equals("-battle") && (i < args.length + 1)) { setup.battleFilename = args[i + 1]; i++; } else if (args[i].equals("-replay") && (i < args.length + 1)) { setup.replayFilename = args[i + 1]; i++; } else if (args[i].equals("-results") && (i < args.length + 1)) { setup.resultsFilename = args[i + 1]; i++; } else if (args[i].equals("-tps") && (i < args.length + 1)) { setup.tps = Integer.parseInt(args[i + 1]); if (setup.tps < 1) { System.out.println("tps must be > 0"); System.exit(8); } i++; } else if (args[i].equals("-minimize")) { setup.minimize = true; } else if (args[i].equals("-nodisplay")) { manager.setEnableGUI(false); manager.setEnableSound(false); setup.tps = 10000; // set TPS to maximum } else if (args[i].equals("-nosound")) { manager.setEnableSound(false); } else if (args[i].equals("-?") || args[i].equals("-help")) { printUsage(); System.exit(0); } else { System.out.println("Not understood: " + args[i]); printUsage(); System.exit(8); } } File robotsDir = FileUtil.getRobotsDir(); if (robotsDir == null) { System.err.println("No valid robot directory is specified"); System.exit(8); } else if (!(robotsDir.exists() && robotsDir.isDirectory())) { System.err.println('\'' + robotsDir.getAbsolutePath() + "' is not a valid robot directory"); System.exit(8); } } private void changeDirectory(String robocodeDir) { try { FileUtil.setCwd(new File(robocodeDir)); } catch (IOException e) { System.err.println(robocodeDir + " is not a valid directory to start Robocode in."); System.exit(8); } } private void printUsage() { System.out.print( "Usage: robocode [-cwd path] [-battle filename [-results filename] [-tps tps]\n" + " [-minimize] [-nodisplay] [-nosound]]\n" + "\n" + "where options include:\n" + " -cwd Change the current working directory\n" + " -battle Run the battle specified in a battle file\n" + " -replay Replay the specified battle record\n" + " -results Save results to the specified text file\n" + " -tps Set the TPS (Turns Per Second) to use. TPS must be > 0\n" + " -minimize Run minimized when Robocode starts\n" + " -nodisplay Run with the display / GUI disabled\n" + " -nosound Run with sound disabled\n" + "\n" + "properties include:\n" + " -DWORKINGDIRECTORY= Set the working directory\n" + " -DROBOTPATH= Set the robots directory (default is 'robots')\n" + " -DBATTLEPATH= Set the battles directory (default is 'battles')\n" + " -DNOSECURITY=true|false Enable/disable Robocode's security manager\n" + " -Ddebug=true|false Enable/disable debugging (to prevent timeouts)\n" + " -DEXPERIMENTAL=true|false Enable/disable access to peer in robot interfaces\n" + " -DPARALLEL=true|false Enable/disable parallel processing of robots turns\n" + " -DRANDOMSEED= Set seed for deterministic behavior of Random numbers\n"); } private void printResultsData(BattleCompletedEvent event) { // Do not print out if no result file has been specified and the GUI is enabled if ((setup.resultsFilename == null && (!setup.exitOnComplete || manager.isGUIEnabled()))) { return; } PrintStream out = null; FileOutputStream fos = null; if (setup.resultsFilename == null) { out = SecurePrintStream.realOut; } else { File f = new File(setup.resultsFilename); try { fos = new FileOutputStream(f); out = new PrintStream(fos); } catch (IOException e) { Logger.logError(e); } } BattleResultsTableModel resultsTable = new BattleResultsTableModel(event.getSortedResults(), event.getBattleRules().getNumRounds()); if (out != null) { resultsTable.print(out); out.close(); } if (fos != null) { try { fos.close(); } catch (IOException e) {// swallow } } } private class BattleObserver extends BattleAdaptor { boolean isReplay; @Override public void onBattleStarted(BattleStartedEvent event) { isReplay = event.isReplay(); } @Override public void onBattleCompleted(BattleCompletedEvent event) { if (!isReplay) { printResultsData(event); } } @Override public void onBattleMessage(BattleMessageEvent event) { SecurePrintStream.realOut.println(event.getMessage()); } @Override public void onBattleError(BattleErrorEvent event) { SecurePrintStream.realErr.println(event.getError()); } } } robocode/robocode/robocode/HitRobotEvent.java0000644000175000017500000001122211130241112020613 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Updated Javadocs *******************************************************************************/ package robocode; import robocode.peer.RobotStatics; import robocode.robotinterfaces.IBasicEvents; import robocode.robotinterfaces.IBasicRobot; import java.awt.*; /** * A HitRobotEvent is sent to {@link Robot#onHitRobot(HitRobotEvent) onHitRobot()} * when your robot collides with another robot. * You can use the information contained in this event to determine what to do. * * @author Mathew A. Nelson (original) */ public final class HitRobotEvent extends Event { private static final long serialVersionUID = 1L; private final static int DEFAULT_PRIORITY = 40; private final String robotName; private final double bearing; private final double energy; private final boolean atFault; /** * Called by the game to create a new HitRobotEvent. * * @param name the name of the robot you hit * @param bearing the bearing to the robot that your robot hit, in radians * @param energy the amount of energy of the robot you hit * @param atFault {@code true} if your robot was moving toward the other * robot; {@code false} otherwise */ public HitRobotEvent(String name, double bearing, double energy, boolean atFault) { this.robotName = name; this.bearing = bearing; this.energy = energy; this.atFault = atFault; } /** * Returns the bearing to the robot you hit, relative to your robot's * heading, in degrees (-180 <= getBearing() < 180) * * @return the bearing to the robot you hit, in degrees */ public double getBearing() { return bearing * 180.0 / Math.PI; } /** * @return the bearing to the robot you hit, in degrees * @deprecated Use {@link #getBearing()} instead. */ @Deprecated public double getBearingDegrees() { return getBearing(); } /** * Returns the bearing to the robot you hit, relative to your robot's * heading, in radians (-PI <= getBearingRadians() < PI) * * @return the bearing to the robot you hit, in radians */ public double getBearingRadians() { return bearing; } /** * Returns the amount of energy of the robot you hit. * * @return the amount of energy of the robot you hit */ public double getEnergy() { return energy; } /** * Returns the name of the robot you hit. * * @return the name of the robot you hit */ public String getName() { return robotName; } /** * @return the name of the robot you hit * @deprecated Use {@link #getName()} instead. */ @Deprecated public String getRobotName() { return robotName; } /** * Checks if your robot was moving towards the robot that was hit. *

* If isMyFault() returns {@code true} then your robot's movement (including * turning) will have stopped and been marked complete. *

* Note: If two robots are moving toward each other and collide, they will * each receive two HitRobotEvents. The first will be the one if isMyFault() * returns {@code true}. * * @return {@code true} if your robot was moving towards the robot that was * hit; {@code false} otherwise. */ public boolean isMyFault() { return atFault; } /** * {@inheritDoc} */ @Override public final int compareTo(Event event) { final int res = super.compareTo(event); if (res != 0) { return res; } // Compare the isMyFault, if the events are HitRobotEvents // The isMyFault has higher priority when it is set compared to when it is not set if (event instanceof HitRobotEvent) { int compare1 = (this).isMyFault() ? -1 : 0; int compare2 = ((HitRobotEvent) event).isMyFault() ? -1 : 0; return compare1 - compare2; } // No difference found return 0; } /** * {@inheritDoc} */ @Override final int getDefaultPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override final void dispatch(IBasicRobot robot, RobotStatics statics, Graphics2D graphics) { IBasicEvents listener = robot.getBasicEventListener(); if (listener != null) { listener.onHitRobot(this); } } } robocode/robocode/robocode/StatusEvent.java0000644000175000017500000000377011130241112020355 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen * - Initial implementation *******************************************************************************/ package robocode; import robocode.peer.RobotStatics; import robocode.robotinterfaces.IBasicEvents; import robocode.robotinterfaces.IBasicRobot; import java.awt.*; /** * This event is sent to {@link Robot#onStatus(StatusEvent) onStatus()} every * turn in a battle to provide the status of the robot. * * @author Flemming N. Larsen (original) * @since 1.5 */ public final class StatusEvent extends Event { private static final long serialVersionUID = 1L; private final static int DEFAULT_PRIORITY = 99; private final RobotStatus status; /** * This constructor is called internally from the game in order to create * a new {@link RobotStatus}. * * @param status the current states */ public StatusEvent(RobotStatus status) { super(); this.status = status; } /** * Returns the {@link RobotStatus} at the time defined by {@link Robot#getTime()}. * * @return the {@link RobotStatus} at the time defined by {@link Robot#getTime()}. * @see #getTime() */ public RobotStatus getStatus() { return status; } /** * {@inheritDoc} */ @Override final int getDefaultPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override final void dispatch(IBasicRobot robot, RobotStatics statics, Graphics2D graphics) { IBasicEvents listener = robot.getBasicEventListener(); if (listener != null) { listener.onStatus(this); } } } robocode/robocode/robocode/MousePressedEvent.java0000644000175000017500000000413011130241112021477 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode; import robocode.peer.RobotStatics; import robocode.robotinterfaces.IBasicRobot; import robocode.robotinterfaces.IInteractiveEvents; import robocode.robotinterfaces.IInteractiveRobot; import java.awt.*; /** * A MousePressedEvent is sent to {@link Robot#onMousePressed(java.awt.event.MouseEvent) * onMousePressed()} when the mouse is pressed inside the battle view. * * @author Pavel Savara (original) * @see MouseClickedEvent * @see MouseReleasedEvent * @see MouseEnteredEvent * @see MouseExitedEvent * @see MouseMovedEvent * @see MouseDraggedEvent * @see MouseWheelMovedEvent * @since 1.6.1 */ public final class MousePressedEvent extends MouseEvent { private static final long serialVersionUID = 1L; private final static int DEFAULT_PRIORITY = 98; /** * Called by the game to create a new MousePressedEvent. * * @param source the source mouse event originating from the AWT. */ public MousePressedEvent(java.awt.event.MouseEvent source) { super(source); } /** * {@inheritDoc} */ @Override final int getDefaultPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override final void dispatch(IBasicRobot robot, RobotStatics statics, Graphics2D graphics) { if (statics.isInteractiveRobot()) { IInteractiveEvents listener = ((IInteractiveRobot) robot).getInteractiveEventListener(); if (listener != null) { listener.onMousePressed(getSourceEvent()); } } } } robocode/robocode/robocode/exception/0000755000175000017500000000000011107420720017224 5ustar lambylambyrobocode/robocode/robocode/exception/DeathException.java0000644000175000017500000000201611130241112022762 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation *******************************************************************************/ package robocode.exception; /** * @author Mathew A. Nelson (original) */ public class DeathException extends Error { // Must be error! // From viewpoint of the Robot, an Error is a JVM error: // Robot died, their CPU exploded, the JVM for the robot's brain has an error. private static final long serialVersionUID = 1L; public DeathException() { super(); } public DeathException(String message) { super(message); } } robocode/robocode/robocode/exception/RobotException.java0000644000175000017500000000156611130241112023033 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation *******************************************************************************/ package robocode.exception; /** * @author Mathew A. Nelson (original) */ public class RobotException extends Error { // Must be error! private static final long serialVersionUID = 1L; public RobotException() { super(); } public RobotException(String s) { super(s); } } robocode/robocode/robocode/exception/EventInterruptedException.java0000644000175000017500000000171711130241112025253 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation *******************************************************************************/ package robocode.exception; /** * @author Mathew A. Nelson (original) */ public class EventInterruptedException extends Error { // Must be error! private static final long serialVersionUID = 1L; int priority = Integer.MIN_VALUE; public EventInterruptedException(int priority) { this.priority = priority; } public int getPriority() { return priority; } } robocode/robocode/robocode/exception/DisabledException.java0000644000175000017500000000157711130241112023457 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation *******************************************************************************/ package robocode.exception; /** * @author Mathew A. Nelson (original) */ public class DisabledException extends Error { // Must be error! private static final long serialVersionUID = 1L; public DisabledException() { super(); } public DisabledException(String s) { super(s); } } robocode/robocode/robocode/exception/WinException.java0000644000175000017500000000156011130241112022475 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation *******************************************************************************/ package robocode.exception; /** * @author Mathew A. Nelson (original) */ public class WinException extends Error { // Must be error! private static final long serialVersionUID = 1L; public WinException() { super(); } public WinException(String s) { super(s); } } robocode/robocode/robocode/exception/AbortedException.java0000644000175000017500000000202511130241112023315 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.exception; /** * @author Pavel Savara (original) * @since 1.6.1 */ public class AbortedException extends Error { // Must be error! // From viewpoint of the Robot, an Error is a JVM error: // Robot died, their CPU exploded, the JVM for the robot's brain has an error. private static final long serialVersionUID = 1L; public AbortedException() { super(); } public AbortedException(String message) { super(message); } } robocode/robocode/robocode/Condition.java0000644000175000017500000001174311130241114020017 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup * - Updated Javadocs * Nathaniel Troutman * - Added cleanup() method for cleaning up references to internal classes * to prevent circular references causing memory leaks *******************************************************************************/ package robocode; import robocode.security.RobocodeSecurityManager; /** * Condition is used to define custom {@link AdvancedRobot#waitFor(Condition) * waitFor(Condition)} and custom events for an {@link AdvancedRobot}. The code * below is taken from the sample robot named {@code sample.Target}. See the * {@code sample/Target.java} for details. *

 *   addCustomEvent(
 *       new Condition("triggerhit") {
 *           public boolean test() {
 *               return (getEnergy() <= trigger);
 *           };
 *       }
 *   );
 * 
* You should note that by extending Condition this way, you are actually * creating an inner class -- so if you distribute your robot, there will be * multiple class files. (i.e. {@code Target$1.class}) * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Nathaniel Troutman (contributor) * @see AdvancedRobot#waitFor(Condition) * @see AdvancedRobot#addCustomEvent(Condition) * @see AdvancedRobot#removeCustomEvent(Condition) * @see AdvancedRobot#onCustomEvent(CustomEvent) */ public abstract class Condition { /** * The priority of this condition. Defaults to 80. */ public int priority = 80; /** * The name of this condition. */ public String name; /** * Creates a new, unnamed Condition with the default priority, which is 80. */ public Condition() {} /** * Creates a new Condition with the specified name, and default priority, * which is 80. * * @param name the name for the new Condition */ public Condition(String name) { this.name = name; } /** * Creates a new Condition with the specified name and priority. * A condition priority is a value from 0 - 99. The higher value, the * higher priority. The default priority is 80. * * @param name the name for the new condition * @param priority the priority of the new condition */ public Condition(String name, int priority) { this.name = name; if (priority < 0) { RobocodeSecurityManager.printlnToRobot("SYSTEM: Priority must be between 0 and 99."); RobocodeSecurityManager.printlnToRobot("SYSTEM: Priority for condition " + name + " will be 0."); priority = 0; } else if (priority > 99) { RobocodeSecurityManager.printlnToRobot("SYSTEM: Priority must be between 0 and 99."); RobocodeSecurityManager.printlnToRobot("SYSTEM: Priority for condition " + name + " will be 99."); priority = 99; } this.priority = priority; } /** * Returns the name of this condition. * * @return the name of this condition */ public String getName() { return (name != null) ? name : getClass().getName(); } /** * Returns the priority of this condition. * A condition priority is a value from 0 - 99. The higher value, the * higher priority. The default priority is 80. * * @return the priority of this condition */ public final int getPriority() { return priority; } /** * Sets the name of this condition. * * @param newName the new name of this condition */ public void setName(String newName) { name = newName; } /** * Sets the priority of this condition. * A condition priority is a value from 0 - 99. The higher value, the * higher priority. The default priority is 80. * * @param newPriority the new priority of this condition. */ public void setPriority(int newPriority) { priority = newPriority; } /** * Overriding the test() method is the point of a Condition. * The game will call your test() function, and take action if it returns * {@code true}. This is valid for both {@link AdvancedRobot#waitFor} and * {@link AdvancedRobot#addCustomEvent}. *

* You may not take any actions inside of test(). * * @return {@code true} if the condition has been met, {@code false} * otherwise. */ public abstract boolean test(); /** * Called by the system in order to clean up references to internal objects. * * @since 1.4.3 */ public void cleanup() {/* Do nothing: Should be overridden by sub-classes to perform needed clean up to ensure that there are NO circular references */} } robocode/robocode/robocode/BulletMissedEvent.java0000644000175000017500000000422711130241114021466 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Updated Javadocs *******************************************************************************/ package robocode; import robocode.peer.RobotStatics; import robocode.robotinterfaces.IBasicEvents; import robocode.robotinterfaces.IBasicRobot; import java.awt.*; import java.util.Hashtable; /** * This event is sent to {@link Robot#onBulletMissed(BulletMissedEvent) * onBulletMissed} when one of your bullets has missed, i.e. when the bullet has * reached the border of the battlefield. * * @author Mathew A. Nelson (original) */ public final class BulletMissedEvent extends Event { private static final long serialVersionUID = 1L; private final static int DEFAULT_PRIORITY = 60; private Bullet bullet; /** * Called by the game to create a new {@code BulletMissedEvent}. * * @param bullet the bullet that missed */ public BulletMissedEvent(Bullet bullet) { this.bullet = bullet; } /** * Returns the bullet that missed. * * @return the bullet that missed */ public Bullet getBullet() { return bullet; } /** * {@inheritDoc} */ @Override final int getDefaultPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override final void dispatch(IBasicRobot robot, RobotStatics statics, Graphics2D graphics) { IBasicEvents listener = robot.getBasicEventListener(); if (listener != null) { listener.onBulletMissed(this); } } /** * {@inheritDoc} */ @Override final void updateBullets(Hashtable bullets) { // we need to pass same instance bullet = bullets.get(bullet.getBulletId()); } } robocode/robocode/robocode/editor/0000755000175000017500000000000011124143430016513 5ustar lambylambyrobocode/robocode/robocode/editor/CompilerPreferencesDialog.java0000644000175000017500000001405211130241112024425 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Matthew Reeder * - Added keyboard mnemonics to buttons * Flemming N. Larsen * - Code cleanup * - Updated to use methods from FileUtil and Logger, which replaces methods * that have been (re)moved from the Utils and Constants class * - Changed to use FileUtil.getWindowConfigFile() * - Added missing close() on FileOutputStream *******************************************************************************/ package robocode.editor; import robocode.io.FileUtil; import robocode.io.Logger; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.FileOutputStream; import java.io.IOException; /** * @author Mathew A. Nelson (original) * @author Matthew Reeder (contributor) * @author Flemming N. Larsen (contributor) */ @SuppressWarnings("serial") public class CompilerPreferencesDialog extends JDialog { private JButton cancelButton; private JTextField compilerBinaryField; private JTextField compilerClasspathField; private JTextField compilerOptionsField; private JPanel compilerPreferencesContentPane; private CompilerProperties compilerProperties; private JButton okButton; private final EventHandler eventHandler = new EventHandler(); private class EventHandler implements ActionListener { public void actionPerformed(ActionEvent e) { if (e.getSource().equals(getOkButton())) { if (compilerProperties == null) { compilerProperties = new CompilerProperties(); } compilerProperties.setCompilerBinary(getCompilerBinaryField().getText()); compilerProperties.setCompilerOptions(getCompilerOptionsField().getText()); compilerProperties.setCompilerClasspath(getCompilerClasspathField().getText()); saveCompilerProperties(); dispose(); } if (e.getSource().equals(getCancelButton())) { dispose(); } } } public CompilerPreferencesDialog(JFrame owner) { super(owner, true); this.compilerProperties = RobocodeCompilerFactory.getCompilerProperties(); initialize(); } private void initialize() { setTitle("Compiler Preferences"); setContentPane(getCompilerPreferencesContentPane()); } public JButton getCancelButton() { if (cancelButton == null) { cancelButton = new JButton("Cancel"); cancelButton.setMnemonic('C'); cancelButton.addActionListener(eventHandler); } return cancelButton; } public JTextField getCompilerBinaryField() { if (compilerBinaryField == null) { compilerBinaryField = new JTextField(40); compilerBinaryField.setText(compilerProperties.getCompilerBinary()); } return compilerBinaryField; } public JTextField getCompilerClasspathField() { if (compilerClasspathField == null) { compilerClasspathField = new JTextField(40); compilerClasspathField.setText(compilerProperties.getCompilerClasspath()); } return compilerClasspathField; } public JTextField getCompilerOptionsField() { if (compilerOptionsField == null) { compilerOptionsField = new JTextField(40); compilerOptionsField.setText(compilerProperties.getCompilerOptions()); } return compilerOptionsField; } private JPanel getCompilerPreferencesContentPane() { if (compilerPreferencesContentPane == null) { compilerPreferencesContentPane = new JPanel(); compilerPreferencesContentPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); compilerPreferencesContentPane.setLayout(new BoxLayout(compilerPreferencesContentPane, BoxLayout.Y_AXIS)); JLabel label = new JLabel("Compiler Binary:"); label.setAlignmentX(Component.LEFT_ALIGNMENT); compilerPreferencesContentPane.add(label); getCompilerBinaryField().setAlignmentX(Component.LEFT_ALIGNMENT); compilerPreferencesContentPane.add(getCompilerBinaryField()); label = new JLabel(" "); label.setAlignmentX(Component.LEFT_ALIGNMENT); compilerPreferencesContentPane.add(label); label = new JLabel("Compiler Options:"); label.setAlignmentX(Component.LEFT_ALIGNMENT); compilerPreferencesContentPane.add(label); getCompilerOptionsField().setAlignmentX(Component.LEFT_ALIGNMENT); compilerPreferencesContentPane.add(getCompilerOptionsField()); label = new JLabel(" "); label.setAlignmentX(Component.LEFT_ALIGNMENT); compilerPreferencesContentPane.add(label); label = new JLabel("Compiler Classpath:"); label.setAlignmentX(Component.LEFT_ALIGNMENT); compilerPreferencesContentPane.add(label); getCompilerClasspathField().setAlignmentX(Component.LEFT_ALIGNMENT); compilerPreferencesContentPane.add(getCompilerClasspathField()); JPanel panel = new JPanel(); panel.setAlignmentX(Component.LEFT_ALIGNMENT); panel.add(getOkButton()); panel.add(getCancelButton()); compilerPreferencesContentPane.add(panel); } return compilerPreferencesContentPane; } public JButton getOkButton() { if (okButton == null) { okButton = new JButton("OK"); okButton.setMnemonic('O'); okButton.addActionListener(eventHandler); } return okButton; } public void saveCompilerProperties() { if (compilerProperties == null) { Logger.logError("Cannot save null compiler properties"); return; } FileOutputStream out = null; try { out = new FileOutputStream(FileUtil.getCompilerConfigFile()); compilerProperties.store(out, "Robocode Compiler Properties"); } catch (IOException e) { Logger.logError(e); } finally { if (out != null) { try { out.close(); } catch (IOException ignored) {} } } } } robocode/robocode/robocode/editor/RobocodeCompilerFactory.java0000644000175000017500000004105211130241112024130 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup * - Updated Jikes compiler to version 1.22 * - Changed deprecated method calls * - File names are being quoted * - Updated to use methods from FileUtil and Logger, which replaces methods * that have been (re)moved from the robocode.util.Utils and Constants * - Changed to use FileUtil.getCompilerConfigFile() * - Added missing close() on FileInputStreams, FileOutputStreams, and * JarInputStream *******************************************************************************/ package robocode.editor; import robocode.dialog.ConsoleDialog; import robocode.dialog.WindowUtil; import robocode.io.FileUtil; import robocode.io.Logger; import static robocode.io.Logger.logError; import static robocode.io.Logger.logMessage; import javax.swing.*; import java.awt.*; import java.io.*; import java.util.jar.JarEntry; import java.util.jar.JarInputStream; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ public class RobocodeCompilerFactory { private final static String COMPILER_CLASSPATH = "-classpath " + getJavaLib() + File.pathSeparator + "libs/robocode.jar" + File.pathSeparator + FileUtil.getRobotsDir(); private static CompilerProperties compilerProperties; private static boolean compilerInstalling; private static final char SPINNER[] = { '-', '\\', '|', '/' }; public RobocodeCompilerFactory() { super(); } public static RobocodeCompiler createCompiler(RobocodeEditor editor) { compilerProperties = null; if (getCompilerProperties().getCompilerBinary() == null || getCompilerProperties().getCompilerBinary().length() == 0) { if (installCompiler(editor)) { return new RobocodeCompiler(editor, getCompilerProperties().getCompilerBinary(), getCompilerProperties().getCompilerOptions(), getCompilerProperties().getCompilerClasspath()); } logError("Unable to create compiler."); return null; } return new RobocodeCompiler(editor, getCompilerProperties().getCompilerBinary(), getCompilerProperties().getCompilerOptions(), getCompilerProperties().getCompilerClasspath()); } public static boolean extract(File src, File dest) { JDialog statusDialog = new JDialog(); Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); int height = 50; if (File.separatorChar == '/') { height = 100; } statusDialog.setTitle("Installing"); statusDialog.setLocation((screenSize.width - 500) / 2, (screenSize.height - height) / 2); statusDialog.setSize(500, height); JLabel status = new JLabel(); statusDialog.getContentPane().setLayout(new BorderLayout()); statusDialog.getContentPane().add(status, BorderLayout.CENTER); statusDialog.setVisible(true); FileInputStream fis = null; FileOutputStream fos = null; JarInputStream jarIS = null; String entryName; byte buf[] = new byte[2048]; try { fis = new FileInputStream(src); jarIS = new JarInputStream(fis); JarEntry entry = jarIS.getNextJarEntry(); while (entry != null) { int spin = 0; entryName = entry.getName(); if (entry.isDirectory()) { File dir = new File(dest, entry.getName()); dir.mkdirs(); } else { status.setText(entryName + " " + SPINNER[spin++]); File out = new File(dest, entry.getName()); File parentDirectory = new File(out.getParent()); parentDirectory.mkdirs(); int index = 0; try { fos = new FileOutputStream(out); int num; int count = 0; while ((num = jarIS.read(buf, 0, 2048)) != -1) { fos.write(buf, 0, num); index += num; count++; if (count > 80) { status.setText(entryName + " " + SPINNER[spin++] + " (" + index + " bytes)"); if (spin > 3) { spin = 0; } count = 0; } } } finally { if (fos != null) { fos.close(); } } status.setText(entryName + " " + SPINNER[spin++] + " (" + index + " bytes)"); } entry = jarIS.getNextJarEntry(); } statusDialog.dispose(); return true; } catch (IOException e) { statusDialog.dispose(); WindowUtil.error(null, e.toString()); return false; } finally { if (fis != null) { try { fis.close(); } catch (IOException ignored) {} } if (jarIS != null) { try { jarIS.close(); } catch (IOException ignored) {} } } } public static CompilerProperties getCompilerProperties() { if (compilerProperties == null) { compilerProperties = new CompilerProperties(); FileInputStream in = null; File file = null; try { file = FileUtil.getCompilerConfigFile(); in = new FileInputStream(file); compilerProperties.load(in); if (compilerProperties.getRobocodeVersion() == null) { logMessage("Setting up new compiler"); compilerProperties.setCompilerBinary(""); } } catch (FileNotFoundException e) { logMessage("Compiler configuration file was not found. A new one will be created."); } catch (IOException e) { logError("IO Exception reading " + file, e); } finally { if (in != null) { try { in.close(); } catch (IOException ignored) {} } } } return compilerProperties; } private static String getJavaLib() { String javahome = System.getProperty("java.home"); String javalib; if (System.getProperty("os.name").indexOf("Mac") == 0) { javalib = new File(javahome).getParentFile().getPath() + "/Classes/classes.jar"; } else { javalib = javahome + "/lib/rt.jar"; } return FileUtil.quoteFileName(javalib); } public static boolean installCompiler(RobocodeEditor editor) { if (compilerInstalling) { JOptionPane.showMessageDialog(editor, "Sorry, the compiler is still installing.\nPlease wait until it is complete.", "Error", JOptionPane.ERROR_MESSAGE); return false; } compilerInstalling = true; String compilerBinary; String compilerOptions; String osName = System.getProperty("os.name"); ConsoleDialog console = new ConsoleDialog(editor, "Setting up compiler", false); console.setSize(500, 400); console.getOkButton().setEnabled(false); console.setText("Please wait while Robocode sets up a compiler for you...\n\n"); WindowUtil.centerShow(editor, console); console.append("Setting up compiler for " + osName + "\n"); console.append("Java home is " + System.getProperty("java.home") + "\n\n"); boolean javacOk = testJavac(console); boolean jikesOk = false; boolean rv = true; boolean mustBuildJikes = false; String jikesJar; String jikesBinary; boolean noExtract = false; compilerProperties.setRobocodeVersion(editor.getManager().getVersionManager().getVersion()); if (osName.indexOf("Windows") == 0) { jikesJar = "compilers/jikes-1.22.win.jar"; jikesBinary = "./jikes-1.22/bin/jikes.exe"; mustBuildJikes = false; } else if (osName.indexOf("Linux") == 0) { jikesJar = "compilers/jikes-1.22.src.jar"; jikesBinary = "./jikes-1.22/bin/jikes"; mustBuildJikes = true; } else if (osName.indexOf("Mac") == 0) { jikesJar = "compilers/jikes-1.22.src.jar"; jikesBinary = "/usr/bin/jikes"; jikesOk = testJikes(console, jikesBinary + " -classpath " + getJavaLib()); if (!jikesOk) { mustBuildJikes = true; jikesBinary = "./jikes-1.22/bin/jikes"; } } else { jikesJar = "compilers/jikes-1.22.src.jar"; mustBuildJikes = true; jikesBinary = "./jikes-1.22/bin/jikes"; } if (javacOk) { String noString = "(If you click No, Robocode will install and use Jikes)"; if (jikesOk) { noString = "(If you click No, Robocode will use Jikes)"; } int rc = JOptionPane.showConfirmDialog(editor, "Robocode has found a working javac on this system.\nWould you like to use it?\n" + noString, "Confirm javac", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); if (rc == JOptionPane.NO_OPTION) { javacOk = false; } } if (javacOk) { compilerBinary = "javac"; compilerOptions = "-deprecation -g"; getCompilerProperties().setCompilerBinary(compilerBinary); getCompilerProperties().setCompilerOptions(compilerOptions); getCompilerProperties().setCompilerClasspath(COMPILER_CLASSPATH); saveCompilerProperties(); console.append("\nCongratulations! Compiler set up successfully.\n"); console.append("Click OK to continue.\n"); console.scrollToBottom(); rv = true; } else if (jikesOk) { compilerBinary = jikesBinary; compilerOptions = "-deprecation -g -Xstdout +T4"; getCompilerProperties().setCompilerBinary(compilerBinary); getCompilerProperties().setCompilerOptions(compilerOptions); getCompilerProperties().setCompilerClasspath(COMPILER_CLASSPATH); saveCompilerProperties(); console.append("\nCongratulations! Jikes set up successfully.\n"); console.append("Click OK to continue.\n"); console.scrollToBottom(); rv = true; } if (!javacOk && !jikesOk) { console.append("\nExtracting Jikes...\n"); if (noExtract || extract(new File(FileUtil.getCwd(), jikesJar), new File("."))) { if (!noExtract) { console.append("Jikes extracted successfully.\n"); } if (mustBuildJikes) { if (JOptionPane.showConfirmDialog(editor, "Robocode is now going to build Jikes for you.\nThis will take a while... got get a cup of coffee!\n", "Java time", JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION) { if (makeJikes(console, jikesBinary + " -classpath " + getJavaLib())) { compilerBinary = jikesBinary; compilerOptions = "-deprecation -g -Xstdout +T4"; getCompilerProperties().setCompilerBinary(compilerBinary); getCompilerProperties().setCompilerOptions(compilerOptions); getCompilerProperties().setCompilerClasspath(COMPILER_CLASSPATH); saveCompilerProperties(); console.append("\nCongratulations! Jikes is installed successfully.\n"); console.append("Click OK to continue.\n"); console.scrollToBottom(); rv = true; } else { JOptionPane.showMessageDialog(editor, "Robocode was unable to build and test Jikes.\n" + "Please consult the console window for errors.\n" + "For help with this, please post to the discussion at:\n" + "http://robocode.net/forum", "Error", JOptionPane.ERROR_MESSAGE); compilerOptions = "-deprecation -g"; getCompilerProperties().setCompilerOptions(compilerOptions); getCompilerProperties().setCompilerClasspath(COMPILER_CLASSPATH); saveCompilerProperties(); rv = false; } } } else { compilerBinary = jikesBinary; compilerOptions = "-deprecation -g -Xstdout +T4"; getCompilerProperties().setCompilerBinary(compilerBinary); getCompilerProperties().setCompilerOptions(compilerOptions); getCompilerProperties().setCompilerClasspath(COMPILER_CLASSPATH); if (testJikes(console, jikesBinary + " -classpath " + getJavaLib())) { saveCompilerProperties(); console.append("\nCongratulations! Compiler set up successfully.\n"); console.append("Click OK to continue.\n"); console.scrollToBottom(); rv = true; } else { JOptionPane.showMessageDialog(editor, "Robocode was unable to successfully compile with Jikes\n" + "Please consult the console window for errors.\n" + "For help with this, please post to the discussion at:\n" + "http://robocode.sourceforge.net/forum", "Error", JOptionPane.ERROR_MESSAGE); saveCompilerProperties(); rv = false; } } } else { console.append("Unable to extract Jikes.\n"); console.append("Unable to determine compiler for this sytem.\n"); console.scrollToBottom(); JOptionPane.showMessageDialog(editor, "Robocode was unable to extract Jikes." + "Please consult the console window for errors.\n" + "For help with this, please post to the discussion at:\n" + "http://robocode.sourceforge.net/forum", "Error", JOptionPane.ERROR_MESSAGE); compilerOptions = "-deprecation -g"; getCompilerProperties().setCompilerOptions(compilerOptions); getCompilerProperties().setCompilerClasspath(COMPILER_CLASSPATH); saveCompilerProperties(); rv = false; } } compilerInstalling = false; console.getOkButton().setEnabled(true); return rv; } private static boolean makeJikes(ConsoleDialog console, String jikesBinary) { boolean result = false; console.append("\nRobocode building Jikes...\n"); try { String command = "./compilers/buildJikes.sh"; logMessage(command); ProcessBuilder pb = new ProcessBuilder(command); pb.directory(FileUtil.getCwd()); pb.redirectErrorStream(true); Process p = pb.start(); // The waitFor() must done after reading the input and error stream of the process console.processStream(p.getInputStream()); p.waitFor(); if (p.exitValue() == 0) { console.append("Finished building Jikes\n"); result = testJikes(console, jikesBinary); } else { console.append("Jikes compile Failed (" + p.exitValue() + ")\n"); } } catch (IOException e) { console.append("\n" + e.toString() + "\n"); console.setTitle("Jikes compile failed.\n"); } catch (InterruptedException e) { // Immediately reasserts the exception by interrupting the caller thread itself Thread.currentThread().interrupt(); console.append("\n" + e.toString() + "\n"); console.setTitle("Jikes compile failed.\n"); } finally { console.scrollToBottom(); } return result; } public static void saveCompilerProperties() { if (compilerProperties == null) { logError("Cannot save null compiler properties"); return; } FileOutputStream out = null; try { out = new FileOutputStream(FileUtil.getCompilerConfigFile()); compilerProperties.store(out, "Robocode Compiler Properties"); } catch (IOException e) { Logger.logError(e); } finally { if (out != null) { try { out.close(); } catch (IOException ignored) {} } } } private static boolean testJavac(ConsoleDialog console) { console.append("Testing compile with javac...\n"); boolean javacOk = false; try { ProcessBuilder pb = new ProcessBuilder("javac", "compilers/CompilerTest.java"); pb.directory(FileUtil.getCwd()); pb.redirectErrorStream(true); Process p = pb.start(); // The waitFor() must done after reading the input and error stream of the process console.processStream(p.getInputStream()); p.waitFor(); javacOk = (p.exitValue() == 0); } catch (IOException e) { logError(e); } catch (InterruptedException e) { // Immediately reasserts the exception by interrupting the caller thread itself Thread.currentThread().interrupt(); } if (javacOk) { console.append("javac ok.\n"); } else { console.append("javac does not exist.\n"); } return javacOk; } private static boolean testJikes(ConsoleDialog console, String jikesBinary) { console.append("\nTesting compile with Jikes...\n"); boolean jikesOk = false; final String command = jikesBinary + " compilers/CompilerTest.java"; try { ProcessBuilder pb = new ProcessBuilder(command.split(" ")); pb.directory(FileUtil.getCwd()); pb.redirectErrorStream(true); Process p = pb.start(); // The waitFor() must done after reading the input and error stream of the process console.processStream(p.getInputStream()); p.waitFor(); jikesOk = (p.exitValue() == 0); } catch (IOException e) { logError(e); } catch (InterruptedException e) { // Immediately reasserts the exception by interrupting the caller thread itself Thread.currentThread().interrupt(); } if (jikesOk) { console.append("Jikes ok.\n"); } else { console.append("Unable to compile with Jikes!\n"); } return jikesOk; } } robocode/robocode/robocode/editor/EditWindow.java0000644000175000017500000003201611130241112021426 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Matthew Reeder * - Changes to facilitate Undo/Redo * - Support for line numbers * - Window menu * - Launching the Replace dialog using ctrl+H * Flemming N. Larsen * - Code cleanup * - Updated to use methods from the Logger, which replaces logger methods * that have been (re)moved from the robocode.util.Utils class *******************************************************************************/ package robocode.editor; import robocode.io.Logger; import javax.swing.*; import javax.swing.event.CaretEvent; import javax.swing.event.CaretListener; import javax.swing.event.InternalFrameAdapter; import javax.swing.event.InternalFrameEvent; import javax.swing.filechooser.FileFilter; import java.awt.*; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.StringTokenizer; /** * @author Mathew A. Nelson (original) * @author Matthew Reeder (contributor) * @author Flemming N. Larsen (contributor) */ @SuppressWarnings("serial") public class EditWindow extends JInternalFrame implements CaretListener { private String fileName; private String robotName; public boolean modified; private final RobocodeEditor editor; private JEditorPane editorPane; private JPanel editWindowContentPane; private final File robotsDirectory; private JScrollPane scrollPane; private LineNumbers lineNumbers; public EditWindow(RobocodeEditor editor, File robotsDirectory) { super(); this.editor = editor; this.robotsDirectory = robotsDirectory; initialize(); } public JEditorPane getEditorPane() { if (editorPane == null) { editorPane = new JEditorPane(); editorPane.setFont(new Font("monospaced", 0, 12)); RobocodeEditorKit editorKit = new RobocodeEditorKit(); editorPane.setEditorKitForContentType("text/java", editorKit); editorPane.setContentType("text/java"); editorKit.setEditWindow(this); editorPane.addCaretListener(this); ((JavaDocument) editorPane.getDocument()).setEditWindow(this); InputMap im = editorPane.getInputMap(); // read: hack. im.put(KeyStroke.getKeyStroke("ctrl H"), editor.getReplaceAction()); // FIXME: Replace hack with better solution? } return editorPane; } public String getFileName() { return fileName; } public String getRobotName() { return robotName; } private void initialize() { try { this.addInternalFrameListener(new InternalFrameAdapter() { @Override public void internalFrameClosing(InternalFrameEvent e) { if (!modified || fileSave(true)) { editor.setLineStatus(-1); dispose(); } editor.removeFromWindowMenu(EditWindow.this); } @Override public void internalFrameDeactivated(InternalFrameEvent e) { editor.setLineStatus(-1); } @Override public void internalFrameIconified(InternalFrameEvent e) { editor.setLineStatus(-1); } }); setResizable(true); setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); setIconifiable(true); setClosable(true); setMaximum(false); setFrameIcon(new ImageIcon(ClassLoader.class.getResource("/resources/icons/robocode-icon.png"))); setSize(553, 441); setMaximizable(true); setTitle("Edit Window"); setContentPane(getEditWindowContentPane()); editor.addToWindowMenu(this); } catch (Throwable e) { Logger.logError(e); } } public void setFileName(String newFileName) { fileName = newFileName; } public void setModified(boolean modified) { if (modified && !this.modified) { this.modified = true; if (fileName != null) { setTitle("Editing - " + fileName + " *"); } else if (robotName != null) { setTitle("Editing - " + robotName + " *"); } else { setTitle("Editing - *"); } } else if (!modified) { this.modified = false; if (fileName != null) { setTitle("Editing - " + fileName); } else if (robotName != null) { setTitle("Editing - " + robotName); } else { setTitle("Editing"); } } editor.setSaveFileMenuItemsEnabled(modified); } public void setRobotName(String newRobotName) { robotName = newRobotName; } public void caretUpdate(CaretEvent e) { int lineend = getEditorPane().getDocument().getDefaultRootElement().getElementIndex(e.getDot()); editor.setLineStatus(lineend); } public void compile() { if (!fileSave(true, true)) { error("You must save before compiling."); return; } RobocodeCompiler compiler = editor.getCompiler(); if (compiler != null) { compiler.compile(fileName); // The following is a bugfix (#2449081): // Make sure that the robot list in the robot repository is cleared to prevent // problems with old robot file specifications that are inconsistent compared to // the compiled classes. editor.getManager().getRobotRepositoryManager().clearRobotList(); } else { JOptionPane.showMessageDialog(editor, "No compiler installed.", "Error", JOptionPane.ERROR_MESSAGE); } } private void error(String msg) { Object[] options = { "OK" }; JOptionPane.showOptionDialog(this, msg, "Error", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE, null, options, options[0]); } public boolean fileSave(boolean confirm) { return fileSave(confirm, false); } private boolean fileSave(boolean confirm, boolean mustSave) { if (confirm) { if (!modified) { return true; } String s = fileName; if (s == null) { s = robotName; } if (s == null) { s = "This file"; } int ok = JOptionPane.showConfirmDialog(this, s + " has been modified. Do you wish to save it?", "Modified file", JOptionPane.YES_NO_CANCEL_OPTION); if (ok == JOptionPane.NO_OPTION) { return !mustSave; } if (ok == JOptionPane.CANCEL_OPTION) { return false; } } String fileName = getFileName(); if (fileName == null) { return fileSaveAs(); } String reasonableFilename = getReasonableFilename(); if (reasonableFilename != null) { try { String a = new File(reasonableFilename).getCanonicalPath(); String b = new File(fileName).getCanonicalPath(); if (!a.equals(b)) { int ok = JOptionPane.showConfirmDialog(this, fileName + " should be saved in: \n" + reasonableFilename + "\n Would you like to save it there instead?", "Name has changed", JOptionPane.YES_NO_CANCEL_OPTION); if (ok == JOptionPane.CANCEL_OPTION) { return false; } if (ok == JOptionPane.YES_OPTION) { if (editor.getManager() != null) { editor.getManager().getRobotRepositoryManager().clearRobotList(); } return fileSaveAs(); } } } catch (IOException e) { Logger.logError("Unable to check reasonable filename: ", e); } } FileWriter writer = null; try { writer = new FileWriter(new File(fileName)); getEditorPane().write(writer); setModified(false); } catch (IOException e) { error("Cannot write file: " + e); return false; } finally { if (writer != null) { try { writer.close(); } catch (IOException ignored) {} } } return true; } public boolean fileSaveAs() { String javaFileName = null; String packageTree; String fileName = robotsDirectory.getPath() + File.separatorChar; String saveDir = fileName; String text = getEditorPane().getText(); int pIndex = text.indexOf("package "); if (pIndex >= 0) { int pEIndex = text.indexOf(";", pIndex); if (pEIndex > 0) { packageTree = text.substring(pIndex + 8, pEIndex) + File.separatorChar; packageTree = packageTree.replace('.', File.separatorChar); fileName += packageTree; saveDir = fileName; } } pIndex = text.indexOf("public class "); if (pIndex >= 0) { int pEIndex = text.indexOf(" ", pIndex + 13); if (pEIndex > 0) { int pEIndex2 = text.indexOf("\n", pIndex + 13); if (pEIndex2 > 0 && pEIndex2 < pEIndex) { pEIndex = pEIndex2; } javaFileName = text.substring(pIndex + 13, pEIndex).trim() + ".java"; } else { pEIndex = text.indexOf("\n", pIndex + 13); if (pEIndex > 0) { javaFileName = text.substring(pIndex + 13, pEIndex).trim() + ".java"; } } } File f = new File(saveDir); if (!f.exists()) { int ok = JOptionPane.showConfirmDialog(this, "Your robot should be saved in the directory: " + saveDir + "\nThis directory does not exist, would you like to create it?", "Create Directory", JOptionPane.YES_NO_CANCEL_OPTION); if (ok == JOptionPane.YES_OPTION) { f.mkdirs(); f = new File(saveDir); } if (ok == JOptionPane.CANCEL_OPTION) { return false; } } JFileChooser chooser; chooser = new JFileChooser(f); chooser.setCurrentDirectory(f); FileFilter filter = new FileFilter() { @Override public boolean accept(File pathname) { if (pathname.isDirectory()) { return true; } String fn = pathname.getName(); int idx = fn.lastIndexOf('.'); String extension = ""; if (idx >= 0) { extension = fn.substring(idx); } return extension.equalsIgnoreCase(".java"); } @Override public String getDescription() { return "Robots"; } }; chooser.setFileFilter(filter); boolean done = false; while (!done) { done = true; if (javaFileName != null) { chooser.setSelectedFile(new File(f, javaFileName)); } int rv = chooser.showSaveDialog(this); String robotFileName; if (rv == JFileChooser.APPROVE_OPTION) { robotFileName = chooser.getSelectedFile().getPath(); File outFile = new File(robotFileName); if (outFile.exists()) { int ok = JOptionPane.showConfirmDialog(this, robotFileName + " already exists. Are you sure you want to replace it?", "Warning", JOptionPane.YES_NO_CANCEL_OPTION); if (ok == JOptionPane.NO_OPTION) { done = false; continue; } if (ok == JOptionPane.CANCEL_OPTION) { return false; } } setFileName(robotFileName); fileSave(false); } else { return false; } } return true; } private JPanel getEditWindowContentPane() { if (editWindowContentPane == null) { editWindowContentPane = new JPanel(); editWindowContentPane.setLayout(new BorderLayout()); editWindowContentPane.setDoubleBuffered(true); editWindowContentPane.add(getScrollPane(), "Center"); } return editWindowContentPane; } public String getPackage() { String text = getEditorPane().getText(); int pIndex = text.indexOf("package "); if (pIndex >= 0) { int pEIndex = text.indexOf(";", pIndex); if (pEIndex > 0) { return text.substring(pIndex + 8, pEIndex); } } return ""; } private String getReasonableFilename() { String fileName = robotsDirectory.getPath() + File.separatorChar; String javaFileName; String packageTree = null; String text = getEditorPane().getText(); StringTokenizer tokenizer = new StringTokenizer(text, " \t\r\n;"); String token; boolean inComment = false; while (tokenizer.hasMoreTokens()) { token = tokenizer.nextToken(); if (!inComment && (token.equals("/*") || token.equals("/**"))) { inComment = true; } if (inComment && (token.equals("*/") || token.equals("**/"))) { inComment = false; } if (inComment) { continue; } if (packageTree == null && token.equals("package")) { packageTree = tokenizer.nextToken(); if (packageTree == null || packageTree.length() == 0) { return null; } packageTree = packageTree.replace('.', File.separatorChar); packageTree += File.separator; fileName += packageTree; } if (token.equals("class")) { javaFileName = tokenizer.nextToken() + ".java"; fileName += javaFileName; return fileName; } } return null; } private JScrollPane getScrollPane() { if (scrollPane == null) { scrollPane = new JScrollPane(); scrollPane.setViewportView(getEditorPane()); scrollPane.setRowHeaderView(getLineNumbers()); } return scrollPane; } private LineNumbers getLineNumbers() { if (lineNumbers == null) { lineNumbers = new LineNumbers(getEditorPane()); } return lineNumbers; } public void undo() { ((JavaDocument) getEditorPane().getDocument()).undo(); repaint(); } public void redo() { ((JavaDocument) getEditorPane().getDocument()).redo(); repaint(); } } robocode/robocode/robocode/editor/WindowMenuItem.java0000644000175000017500000002217011130241112022264 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Matthew Reeder * - Initial API and implementation *******************************************************************************/ package robocode.editor; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.io.File; /** * Customized JMenuItem where each item is bound to a specific JInternalFrame, * so we can have a dynamic menu of open windows. * * @author Matthew Reeder (original) */ @SuppressWarnings("serial") public class WindowMenuItem extends JCheckBoxMenuItem implements ActionListener { // Maximum number of windows that will be shown on the menu (to get the rest, you'll // have to open the dialog). The number 9 is also the number of most recently used // files that normally show up in other applications. The reason is so that you can // give them dynamic hotkeys from 1 to 9. Otherwise, there's no reason (besides // avoiding taking up way too much space) to limit the size of the menu. public static final int WINDOW_MENU_MAX_SIZE = 9; // Number of static menu items before the dynamic menu (including seperators) public static final int PRECEDING_WINDOW_MENU_ITEMS = 3; // Number of static menu items after the dynamic menu (including seperators // and the More Windows... menu item) public static final int SUBSEQUENT_WINDOW_MENU_ITEMS = 1; // Normal max length of a window name public static final int MAX_WINDOW_NAME_LENGTH = 30; // I make one "special" menu item that isn't tied to a window. Since it has // similar needs for enabling/visibility and labeling, I made it the same class. public static final int REGULAR_WINDOW = 0, SPECIAL_MORE = 2; private EditWindow window; private JMenu parentMenu; private final int type; /** * WindowMenuItem Constructor *

* Initializes the WindowMenuItem and adds it to the parentMenu. */ public WindowMenuItem(EditWindow window, JMenu parentMenu) { super(); this.window = window; this.parentMenu = parentMenu; type = REGULAR_WINDOW; parentMenu.add(this, parentMenu.getMenuComponentCount() - SUBSEQUENT_WINDOW_MENU_ITEMS); addActionListener(this); } /** * WindowMenuItem Constructor for "More Windows..." menu. */ public WindowMenuItem() { type = SPECIAL_MORE; } /** * Event handler for the menu item *

* Brings the window to the front. This should be called for the "More * Windows..." Item, because it doesn't make itself its own ActionListener. *

* Note that e can be null, and this menu item might not be showing (if this * is called from the "More Windows" dialog). */ public void actionPerformed(ActionEvent e) { if (window.isIcon()) { try { window.setIcon(false); } catch (Throwable ignored) {} } if (window.getDesktopPane() != null) { window.getDesktopPane().setSelectedFrame(window); } window.toFront(); window.grabFocus(); try { window.setSelected(true); } catch (Throwable ignored) {} } /** * Returns the label that should be used. If the menu item is supposed to be * hidden, this may not be a real valid label. */ @Override public String getText() { if (type == SPECIAL_MORE) { Container parent = getParent(); if (parent == null) { return ""; } int numWindows = parent.getComponentCount() - PRECEDING_WINDOW_MENU_ITEMS - SUBSEQUENT_WINDOW_MENU_ITEMS; if (numWindows <= 0) { return "No Windows Open"; } return "More Windows..."; } if (window == null || parentMenu == null) { return ""; } String text = (getIndex() + 1) + " " + getFileName(); if (window.modified) { text += " *"; } return text; } /** * Gets the name of the file represented by this item. *

* Creates a unique filler filename if the window is nameless. May shorten * the filename if the name is long. */ protected String getFileName() { if (window.getFileName() == null) { return "Untitled " + (getPrecedingNewFiles() + 1); } String name = window.getFileName(); if (name.length() < MAX_WINDOW_NAME_LENGTH) { return name; } if (name.indexOf(File.separatorChar) < 0) { return name; } // If there are no separators, I can't really intelligently truncate. int startLength = name.indexOf(File.separatorChar, 1) + 1; int endLength = name.length() - name.lastIndexOf(File.separatorChar); if (endLength + startLength + 3 > name.length()) { return name; } // return name anyways, since we're not getting it any shorter. boolean change; do { change = false; int newEndLength = name.length() - name.lastIndexOf(File.separatorChar, name.length() - endLength - 1); if (newEndLength + startLength + 3 <= MAX_WINDOW_NAME_LENGTH) { endLength = newEndLength; change = true; } int newStartLength = name.indexOf(File.separatorChar, startLength + 1) + 1; if (endLength + startLength + 3 <= MAX_WINDOW_NAME_LENGTH) { startLength = newStartLength; change = true; } } while (change); return name.substring(0, startLength) + "..." + name.substring(name.length() - endLength); } /** * Figures out how many nameless windows occur before this one in the parent. */ protected int getPrecedingNewFiles() { int count = 0; for (int i = 0; i < WINDOW_MENU_MAX_SIZE && i < parentMenu.getMenuComponentCount() - PRECEDING_WINDOW_MENU_ITEMS - SUBSEQUENT_WINDOW_MENU_ITEMS && parentMenu.getMenuComponent(i + PRECEDING_WINDOW_MENU_ITEMS) != this; i++) { if (parentMenu.getMenuComponent(i + PRECEDING_WINDOW_MENU_ITEMS) instanceof WindowMenuItem && ((WindowMenuItem) parentMenu.getMenuComponent(i + PRECEDING_WINDOW_MENU_ITEMS)).window.getFileName() == null) { count++; } } return count; } /** * Figures out what index (from 0 to WINDOW_MENU_MAX_SIZE-1) this item is in * the window menu. *

* Returns -1 if this item isn't showing. */ protected int getIndex() { for (int i = 0; i < WINDOW_MENU_MAX_SIZE && i < parentMenu.getMenuComponentCount() - PRECEDING_WINDOW_MENU_ITEMS - SUBSEQUENT_WINDOW_MENU_ITEMS; i++) { if (this == parentMenu.getMenuComponent(i + PRECEDING_WINDOW_MENU_ITEMS)) { return i; } } return -1; } /** * Returns the index of the character in the label that should be underlined */ @Override public int getDisplayedMnemonicIndex() { return (type == SPECIAL_MORE) ? 11 : 0; } /** * Returns the keyboard mnemonic for this item, which is the virtual key * code for its 1-based index. */ @Override public int getMnemonic() { return (type == SPECIAL_MORE) ? KeyEvent.VK_S : KeyEvent.VK_1 + getIndex(); } /** * Returns true if this item should be showing. *

* Returns false if there are more than WINDOW_MENU_MAX_SIZE items before it * in the menu. */ @Override public boolean isVisible() { if (type == SPECIAL_MORE) { Container parent = getParent(); if (parent == null) { return true; } int numWindows = parent.getComponentCount() - PRECEDING_WINDOW_MENU_ITEMS - SUBSEQUENT_WINDOW_MENU_ITEMS; updateSelection(); return (numWindows <= 0) || (numWindows > WINDOW_MENU_MAX_SIZE); } updateSelection(); return getIndex() >= 0; } /** * Returns true if this item should be enabled (selectable). *

* Returns false if it is a More Windows... item and there are no windows. */ @Override public boolean isEnabled() { if (type == SPECIAL_MORE) { Container parent = getParent(); if (parent == null) { return true; } int numWindows = parent.getComponentCount() - PRECEDING_WINDOW_MENU_ITEMS - SUBSEQUENT_WINDOW_MENU_ITEMS; return (numWindows > 0); } return true; } /** * Determines if this menu item should currently show as "selected". *

* The item should be seleced if the window it's tied to has focus. */ @Override public boolean isSelected() { return (type != SPECIAL_MORE) && (window != null && window.getDesktopPane() != null) && window.getDesktopPane().getSelectedFrame() == window; } /** * Makes sure the underlying menu item knows if we're selected. */ public void updateSelection() { setSelected(isSelected()); // Sort of a silly thing to do... setEnabled(isEnabled()); } /** * Gets the EditWindow that this menu item is tied to. */ public EditWindow getEditWindow() { return window; } /** * Creates a string representation of this object. *

* Handy for repurposing the menu items as list items :-) */ @Override public String toString() { return (type == SPECIAL_MORE) ? "" : getFileName(); } } robocode/robocode/robocode/editor/FindReplaceDialog.java0000644000175000017500000003005011130241112022641 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Matthew Reeder * - Initial API and implementation * Flemming N. Larsen * - Minor optimizations *******************************************************************************/ package robocode.editor; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @author Matthew Reeder (original) * @author Flemming N. Larsen (contributor) */ @SuppressWarnings("serial") public class FindReplaceDialog extends JDialog implements ActionListener { private JTextField findField; private JTextField replaceField; private JButton findNextButton; private JButton replaceButton; private JButton replaceAllButton; private JButton toggleReplaceButton; private JButton closeButton; private JCheckBox caseSensitiveCheckBox; private JCheckBox wholeWordCheckBox; private JRadioButton regexButton; private JRadioButton wildCardsButton; private JRadioButton literalButton; private JLabel findLabel; private JLabel replaceLabel; private boolean initLoc; private final RobocodeEditor window; public FindReplaceDialog(RobocodeEditor parentFrame) { super(parentFrame, false); window = parentFrame; JPanel bigPanel = new JPanel(); bigPanel.setLayout(new BoxLayout(bigPanel, BoxLayout.X_AXIS)); JPanel leftPanel = new JPanel(); leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.Y_AXIS)); JPanel findReplacePanel = new JPanel(); findReplacePanel.setLayout(new BoxLayout(findReplacePanel, BoxLayout.X_AXIS)); JPanel labelsPanel = new JPanel(); labelsPanel.setLayout(new BoxLayout(labelsPanel, BoxLayout.Y_AXIS)); labelsPanel.add(getFindLabel()); labelsPanel.add(getReplaceLabel()); findReplacePanel.add(labelsPanel); JPanel fieldsPanel = new JPanel(); fieldsPanel.setLayout(new BoxLayout(fieldsPanel, BoxLayout.Y_AXIS)); fieldsPanel.add(getFindField()); fieldsPanel.add(getReplaceField()); findReplacePanel.add(fieldsPanel); leftPanel.add(findReplacePanel); JPanel optionsPanel = new JPanel(); optionsPanel.setLayout(new BoxLayout(optionsPanel, BoxLayout.X_AXIS)); JPanel checkboxPanel = new JPanel(); checkboxPanel.setLayout(new BoxLayout(checkboxPanel, BoxLayout.Y_AXIS)); checkboxPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Options")); checkboxPanel.add(getCaseSensitiveCheckBox()); checkboxPanel.add(getWholeWordCheckBox()); checkboxPanel.setAlignmentY(TOP_ALIGNMENT); optionsPanel.add(checkboxPanel); JPanel radioPanel = new JPanel(); radioPanel.setLayout(new BoxLayout(radioPanel, BoxLayout.Y_AXIS)); radioPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Use:")); radioPanel.add(getLiteralButton()); radioPanel.add(getWildCardsButton()); radioPanel.add(getRegexButton()); radioPanel.setAlignmentY(TOP_ALIGNMENT); ButtonGroup buttonGroup = new ButtonGroup(); buttonGroup.add(getLiteralButton()); buttonGroup.add(getWildCardsButton()); buttonGroup.add(getRegexButton()); optionsPanel.add(radioPanel); leftPanel.add(optionsPanel); leftPanel.setAlignmentY(TOP_ALIGNMENT); bigPanel.add(leftPanel); JPanel buttonPanel = new JPanel(); buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS)); buttonPanel.add(getFindNextButton()); buttonPanel.add(getToggleReplaceButton()); buttonPanel.add(getReplaceButton()); buttonPanel.add(getReplaceAllButton()); buttonPanel.add(getCloseButton()); buttonPanel.setAlignmentY(TOP_ALIGNMENT); bigPanel.add(buttonPanel); setContentPane(bigPanel); } public void showDialog(boolean showReplace) { getReplaceLabel().setVisible(showReplace); getReplaceField().setVisible(showReplace); getReplaceButton().setVisible(showReplace); getReplaceAllButton().setVisible(showReplace); if (showReplace) { setTitle("Replace"); getRootPane().setDefaultButton(getReplaceButton()); getToggleReplaceButton().setText("Find..."); getToggleReplaceButton().setMnemonic('d'); getToggleReplaceButton().setDisplayedMnemonicIndex(3); } else { setTitle("Find"); getRootPane().setDefaultButton(getFindNextButton()); getToggleReplaceButton().setText("Replace..."); getToggleReplaceButton().setMnemonic('R'); } pack(); if (!initLoc) { Rectangle bounds = window.getBounds(); Dimension size = getSize(); setLocation((int) (bounds.getX() + (bounds.getWidth() - size.getWidth()) / 2), (int) (bounds.getY() + (bounds.getHeight() - size.getHeight()) / 2)); initLoc = true; } setVisible(true); } public JLabel getFindLabel() { if (findLabel == null) { findLabel = new JLabel(); findLabel.setText(" Find:"); findLabel.setDisplayedMnemonicIndex(3); } return findLabel; } public JLabel getReplaceLabel() { if (replaceLabel == null) { replaceLabel = new JLabel(); replaceLabel.setText(" Replace:"); replaceLabel.setDisplayedMnemonicIndex(3); } return replaceLabel; } public JTextField getFindField() { if (findField == null) { findField = new JTextField(); findField.setFocusAccelerator('n'); findField.addActionListener(this); } return findField; } public JTextField getReplaceField() { if (replaceField == null) { replaceField = new JTextField(); replaceField.setFocusAccelerator('p'); replaceField.addActionListener(this); } return replaceField; } public JButton getFindNextButton() { if (findNextButton == null) { findNextButton = new JButton(); findNextButton.setText("Find Next"); findNextButton.setMnemonic('F'); findNextButton.setDefaultCapable(true); findNextButton.addActionListener(this); } return findNextButton; } public JButton getReplaceButton() { if (replaceButton == null) { replaceButton = new JButton(); replaceButton.setText("Replace"); replaceButton.setMnemonic('R'); replaceButton.setDefaultCapable(true); replaceButton.addActionListener(this); } return replaceButton; } public JButton getReplaceAllButton() { if (replaceAllButton == null) { replaceAllButton = new JButton(); replaceAllButton.setText("Replace All"); replaceAllButton.setMnemonic('A'); replaceAllButton.setDisplayedMnemonicIndex(8); replaceAllButton.addActionListener(this); } return replaceAllButton; } public JButton getToggleReplaceButton() { if (toggleReplaceButton == null) { toggleReplaceButton = new JButton(); toggleReplaceButton.addActionListener(this); } return toggleReplaceButton; } public JButton getCloseButton() { if (closeButton == null) { closeButton = new JButton(); closeButton.setText("Close"); closeButton.setMnemonic('e'); closeButton.setDisplayedMnemonicIndex(4); closeButton.addActionListener(this); } return closeButton; } public JCheckBox getCaseSensitiveCheckBox() { if (caseSensitiveCheckBox == null) { caseSensitiveCheckBox = new JCheckBox(); caseSensitiveCheckBox.setText("Case Sensitive"); caseSensitiveCheckBox.setMnemonic('C'); caseSensitiveCheckBox.addActionListener(this); } return caseSensitiveCheckBox; } public JCheckBox getWholeWordCheckBox() { if (wholeWordCheckBox == null) { wholeWordCheckBox = new JCheckBox(); wholeWordCheckBox.setText("Whole Word"); wholeWordCheckBox.setMnemonic('W'); wholeWordCheckBox.addActionListener(this); } return wholeWordCheckBox; } public JRadioButton getLiteralButton() { if (literalButton == null) { literalButton = new JRadioButton(); literalButton.setText("Literal"); literalButton.setMnemonic('L'); literalButton.setSelected(true); literalButton.addActionListener(this); } return literalButton; } public JRadioButton getWildCardsButton() { if (wildCardsButton == null) { wildCardsButton = new JRadioButton(); wildCardsButton.setText("Wild Cards"); wildCardsButton.setMnemonic('i'); wildCardsButton.setDisplayedMnemonicIndex(1); wildCardsButton.addActionListener(this); } return wildCardsButton; } public JRadioButton getRegexButton() { if (regexButton == null) { regexButton = new JRadioButton(); regexButton.setText("Regular Expressions"); regexButton.setMnemonic('x'); regexButton.setDisplayedMnemonicIndex(9); regexButton.addActionListener(this); } return regexButton; } public void actionPerformed(ActionEvent e) { Object source = e.getSource(); if (source == getFindNextButton()) { findNext(); } else if (source == getReplaceButton()) { doReplacement(); findNext(); } else if (source == getReplaceAllButton()) { doReplaceAll(); } else if (source == getCloseButton()) { setVisible(false); } else if (source == getToggleReplaceButton()) { showDialog(!getReplaceButton().isVisible()); } else if (source instanceof JTextField) { getRootPane().getDefaultButton().doClick(); } } private Pattern getCurrentPattern() { String pattern = getFindField().getText(); int flags = Pattern.DOTALL; if (!getRegexButton().isSelected()) { String newpattern = ""; // 'quote' the pattern for (int i = 0; i < pattern.length(); i++) { if ("\\[]^$&|().*+?{}".indexOf(pattern.charAt(i)) >= 0) { newpattern += '\\'; } newpattern += pattern.charAt(i); } // make "*" .* and "?" . if (getWildCardsButton().isSelected()) { newpattern = newpattern.replaceAll("\\\\\\*", ".+?"); newpattern = newpattern.replaceAll("\\\\\\?", "."); } pattern = newpattern; } if (!getCaseSensitiveCheckBox().isSelected()) { flags |= Pattern.CASE_INSENSITIVE; } if (getWholeWordCheckBox().isSelected()) { pattern = "\\b" + pattern + "\\b"; } return Pattern.compile(pattern, flags); } public void findNext() { EditWindow currentWindow = window.getActiveWindow(); if (currentWindow == null || getFindField().getText().length() == 0) { // launch error dialog? return; } Pattern p = getCurrentPattern(); JEditorPane editorPane = currentWindow.getEditorPane(); // for some reason, getText() trims off \r but the indexes in // the editor pane don't. String text = editorPane.getText().replaceAll("\\r", ""); Matcher m = p.matcher(text); int index = editorPane.getSelectionEnd(); if (!m.find(index)) { if (!m.find()) { // No match found return; } } editorPane.setSelectionStart(m.start()); editorPane.setSelectionEnd(m.end()); } public void doReplacement() { EditWindow currentWindow = window.getActiveWindow(); if (currentWindow == null || getFindField().getText().length() == 0) { // launch error dialog? return; } JEditorPane editorPane = currentWindow.getEditorPane(); String text = editorPane.getSelectedText(); if (text == null) { // no selection return; } Matcher m = getCurrentPattern().matcher(text); if (m.matches()) { String replacement = getReplaceField().getText(); if (getRegexButton().isSelected()) { replacement = m.replaceFirst(replacement); } editorPane.replaceSelection(replacement); } } public void doReplaceAll() { EditWindow currentWindow = window.getActiveWindow(); if (currentWindow == null || getFindField().getText().length() == 0) { // launch error dialog? return; } JEditorPane editorPane = currentWindow.getEditorPane(); String text = editorPane.getText(); String replacement = getReplaceField().getText(); editorPane.setText(getCurrentPattern().matcher(text).replaceAll(replacement)); } } robocode/robocode/robocode/editor/CompilerProperties.java0000644000175000017500000000727711130241112023213 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation *******************************************************************************/ package robocode.editor; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Properties; /** * @author Mathew A. Nelson (original) */ public class CompilerProperties { public final static String COMPILER_BINARY = "compiler.binary"; public final static String COMPILER_OPTIONS = "compiler.options"; public final static String COMPILER_CLASSPATH = "compiler.classpath"; public final static String ROBOCODE_VERSION = "robocode.version"; private String compilerBinary = null; private String compilerOptions = null; private String compilerClasspath = null; private String robocodeVersion = null; private final Properties props = new Properties(); public CompilerProperties() { super(); } /** * Returns the compilerBinary. * * @return String */ public String getCompilerBinary() { if (compilerBinary == null) { setCompilerBinary(""); } return compilerBinary; } /** * Returns the compilerClasspath. * * @return String */ public String getCompilerClasspath() { if (compilerClasspath == null) { setCompilerClasspath(""); } return compilerClasspath; } /** * Returns the compilerOptions. * * @return String */ public String getCompilerOptions() { if (compilerOptions == null) { setCompilerOptions(""); } return compilerOptions; } /** * Returns the robocodeVersion. * * @return String */ public String getRobocodeVersion() { return robocodeVersion; } public void resetCompiler() { this.compilerBinary = null; props.remove(COMPILER_BINARY); } /** * Sets the compilerBinary. * * @param compilerBinary The compilerBinary to set */ public void setCompilerBinary(String compilerBinary) { this.compilerBinary = compilerBinary; props.setProperty(COMPILER_BINARY, compilerBinary); } /** * Sets the compilerClasspath. * * @param compilerClasspath The compilerClasspath to set */ public void setCompilerClasspath(String compilerClasspath) { this.compilerClasspath = compilerClasspath; props.setProperty(COMPILER_CLASSPATH, compilerClasspath); } /** * Sets the compilerOptions. * * @param compilerOptions The compilerOptions to set */ public void setCompilerOptions(String compilerOptions) { this.compilerOptions = compilerOptions; props.setProperty(COMPILER_OPTIONS, compilerOptions); } /** * Sets the robocodeVersion. * * @param robocodeVersion The robocodeVersion to set */ public void setRobocodeVersion(String robocodeVersion) { this.robocodeVersion = robocodeVersion; props.setProperty(ROBOCODE_VERSION, robocodeVersion); } public void load(InputStream is) throws IOException { props.load(is); this.compilerBinary = props.getProperty(COMPILER_BINARY); this.compilerOptions = props.getProperty(COMPILER_OPTIONS); this.compilerClasspath = props.getProperty(COMPILER_CLASSPATH); this.robocodeVersion = props.getProperty(ROBOCODE_VERSION); } public void store(OutputStream os, String header) throws IOException { props.store(os, header); } } robocode/robocode/robocode/editor/LineNumbers.java0000644000175000017500000001741611130241112021603 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Matthew Reeder * - Initial API and implementation *******************************************************************************/ package robocode.editor; import javax.swing.*; import javax.swing.event.CaretEvent; import javax.swing.event.CaretListener; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.text.BadLocationException; import java.awt.*; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import static java.lang.Math.max; import static java.lang.Math.min; /** * Custom widget for line numbers, meant to be the row header for a JScrollPane * that scrolls a JEditorPane. * * @author Matthew Reeder (original) */ @SuppressWarnings("serial") public class LineNumbers extends JComponent implements DocumentListener, MouseListener, MouseMotionListener, CaretListener { private final JEditorPane editorPane; private int currentLines, lineWidth, anchor, lastIndex, offset, textWidth; public LineNumbers(JEditorPane editorPane) { this.editorPane = editorPane; editorPane.getDocument().addDocumentListener(this); setForeground(editorPane.getForeground()); setBackground(editorPane.getBackground()); currentLines = 1; lastIndex = -1; anchor = -1; addMouseListener(this); addMouseMotionListener(this); editorPane.addMouseListener(this); setPreferredSize(new Dimension(24, 17)); editorPane.addCaretListener(this); } /** * Listens for changes on the Document in its associated text pane. *

* If the number of lines has changed, it updates its view. */ public void changedUpdate(DocumentEvent e) { anchor = lastIndex = -1; try { checkLines(e.getDocument().getText(0, e.getDocument().getLength())); } catch (BadLocationException ex) { ex.printStackTrace(); } } /** * Listens for changes on the Document in its associated text pane. *

* If the number of lines has changed, it updates its view. */ public void insertUpdate(DocumentEvent e) { anchor = lastIndex = -1; try { checkLines(e.getDocument().getText(0, e.getDocument().getLength())); } catch (BadLocationException ex) { ex.printStackTrace(); } } /** * Listens for changes on the Document in its associated text pane. *

* If the number of lines has changed, it updates its view. */ public void removeUpdate(DocumentEvent e) { anchor = lastIndex = -1; try { checkLines(e.getDocument().getText(0, e.getDocument().getLength())); } catch (BadLocationException ex) { ex.printStackTrace(); } } /** * Called by the DocumentListener methods to check if the number of lines * has changed, and if it has, it updates the display. * * @param text the text to compare to the current text */ protected void checkLines(String text) { int lines = 0; int index = -1; do { lines++; index = text.indexOf('\n', index + 1); } while (index >= 0); if (lines != currentLines) { currentLines = lines; repaint(); } } /** * Draws the line numbers. */ @Override public void paint(Graphics g) { checkLines(editorPane.getText()); g.setFont(editorPane.getFont()); FontMetrics fm = g.getFontMetrics(); // note: using font metrics for the editor font, using a bold font :-) if (lineWidth == 0) { lineWidth = fm.getHeight(); offset = fm.getAscent() - lineWidth; } g.setFont(editorPane.getFont().deriveFont(Font.BOLD)); g.setColor(getBackground()); g.fillRect(0, 0, getWidth(), getHeight()); g.setColor(editorPane.getSelectionColor()); int start = max(1, min(anchor, lastIndex)); int end = min(currentLines, max(anchor, lastIndex)); g.fillRect(0, (start - 1) * lineWidth - offset, textWidth, (end - start + 1) * lineWidth); int maxwidth = max(textWidth, fm.stringWidth("000")); for (int i = 1; i <= currentLines; i++) { String str = Integer.toString(i); maxwidth = max(maxwidth, fm.stringWidth(str)); if (i >= start && i <= end) { g.setColor(editorPane.getSelectedTextColor()); } else { g.setColor(getForeground()); } g.drawString(str, textWidth - fm.stringWidth(str), i * lineWidth + offset); } textWidth = maxwidth; g.setColor(getForeground()); g.drawLine(maxwidth + 2, 0, maxwidth + 2, getHeight()); g.drawLine(maxwidth + 1, 0, maxwidth + 1, getHeight()); Dimension dim = getPreferredSize(); if (dim.height != lineWidth * currentLines || dim.width != maxwidth + 8) { setPreferredSize(new Dimension(maxwidth + 8, lineWidth * currentLines)); setMinimumSize(new Dimension(maxwidth + 8, lineWidth * currentLines)); repaint(); } } /** * Handles selection in the text pane due to gestures on the line numbers. */ protected void doSelection() { int first = min(anchor, lastIndex); int last = max(anchor, lastIndex); try { String text = editorPane.getDocument().getText(0, editorPane.getDocument().getLength()); int index = -1, lines = 1; while (lines < first) { index = text.indexOf('\n', index + 1); lines++; } int firstindex = index + 1; do { index = text.indexOf('\n', index + 1); lines++; } while (lines <= last && index > 0); int lastindex; if (index < 0) { lastindex = editorPane.getDocument().getLength(); } else { lastindex = index + 1; } editorPane.setSelectionStart(firstindex); editorPane.setSelectionEnd(lastindex); } catch (BadLocationException ignored) {} } /** * Selects the number that was clicked on and sets it as an "anchor" for * dragging. */ public void mousePressed(MouseEvent e) { if (e.getSource() == this) { if (e.getX() < textWidth) { anchor = e.getY() / lineWidth + 1; lastIndex = anchor; doSelection(); repaint(); editorPane.requestFocus(); } } else { anchor = lastIndex = -1; repaint(); } } /** * Sets the end anchor and updates the state of the widget to reflect that * the click-and-drag gesture has ended. */ public void mouseReleased(MouseEvent e) { if (e.getSource() == this) { if (e.getX() < textWidth) { if (lastIndex != e.getY() / lineWidth + 1) { lastIndex = e.getY() / lineWidth + 1; doSelection(); repaint(); } editorPane.requestFocus(); } } else { anchor = lastIndex = -1; repaint(); } } /** * Temporarily moves the end anchor of the current selection. */ public void mouseDragged(MouseEvent e) { if (lastIndex != e.getY() / lineWidth + 1) { if (e.getX() < textWidth) { lastIndex = e.getY() / lineWidth + 1; doSelection(); repaint(); } } editorPane.requestFocus(); } /** * Empty - part of the MouseMotionListener interface. */ public void mouseMoved(MouseEvent e) {} /** * Empty - part of the MouseListener interface. */ public void mouseEntered(MouseEvent e) {} /** * Empty - part of the MouseListener interface. */ public void mouseExited(MouseEvent e) {} /** * Empty - part of the MouseListener interface. */ public void mouseClicked(MouseEvent e) {} /** * Listens for changes in caret position on the text pane. *

* Updates the code block display and stuff */ public void caretUpdate(CaretEvent e) { repaint(); } } robocode/robocode/robocode/editor/RobocodeCompiler.java0000644000175000017500000000637011130241112022604 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - File name is being quoted * - Code cleanup * - Updated to use methods from FileUtil and Logger, which replaces methods * that have been (re)moved from the robocode.util.Utils class * - Added missing close() on InputStreams *******************************************************************************/ package robocode.editor; import robocode.dialog.ConsoleDialog; import robocode.dialog.WindowUtil; import robocode.io.FileUtil; import robocode.io.Logger; import java.io.IOException; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ public class RobocodeCompiler { private final String compilerBinary; private final RobocodeEditor editor; private final String compilerOptions; private final String compilerClassPath; protected RobocodeCompiler(RobocodeEditor editor, String binary, String options, String classPath) { super(); this.compilerBinary = binary; this.compilerOptions = options; this.compilerClassPath = classPath; this.editor = editor; } public void compile(String fileName) { fileName = FileUtil.quoteFileName(fileName); ConsoleDialog console; if (editor != null) { console = new ConsoleDialog(editor, "Compiling", false); } else { console = new ConsoleDialog(); } console.setSize(500, 400); console.setText("Compiling...\n"); WindowUtil.centerShow(editor, console); try { StringBuffer command = new StringBuffer(compilerBinary).append(' ').append(compilerOptions).append(' ').append(compilerClassPath).append(' ').append( fileName); Logger.logMessage("Compile command: " + command); ProcessBuilder pb = new ProcessBuilder(command.toString().split(" ")); pb.redirectErrorStream(true); pb.directory(FileUtil.getCwd()); Process p = pb.start(); // The waitFor() must done after reading the input and error stream of the process console.processStream(p.getInputStream()); p.waitFor(); if (p.exitValue() == 0) { console.append("Compiled successfully.\n"); console.setTitle("Compiled successfully."); } else { console.append("Compile Failed (" + p.exitValue() + ")\n"); console.setTitle("Compile failed."); } } catch (IOException e) { console.append("Unable to compile!\n"); console.append("Exception was: " + e.toString() + "\n"); console.append("Does " + compilerBinary + " exist?\n"); console.setTitle("Exception while compiling"); } catch (InterruptedException e) { // Immediately reasserts the exception by interrupting the caller thread itself Thread.currentThread().interrupt(); console.append("Compile interrupted.\n"); console.setTitle("Compile interrupted."); } } } robocode/robocode/robocode/editor/RobocodeEditorKit.java0000644000175000017500000001420011130241112022717 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation *******************************************************************************/ package robocode.editor; import javax.swing.*; import javax.swing.text.BadLocationException; import javax.swing.text.DefaultEditorKit; import javax.swing.text.Document; import javax.swing.text.ViewFactory; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.io.Writer; /** * @author Mathew A. Nelson (original) */ @SuppressWarnings("serial") public class RobocodeEditorKit extends DefaultEditorKit { public EditWindow editWindow; /** * RobocodeEditorKit constructor */ public RobocodeEditorKit() { super(); } /** * Creates a copy of the editor kit. This * allows an implementation to serve as a prototype * for others, so that they can be quickly created. * In a future release this method will be implemented * to use Object.clone * * @return the copy */ @Override public Object clone() { return super.clone(); } /** * Fetches a caret that can navigate through views * produced by the associated ViewFactory. * * @return the caret */ @Override public javax.swing.text.Caret createCaret() { return super.createCaret(); } /** * Creates an uninitialized text storage model * that is appropriate for this type of editor. * * @return the model */ @Override public javax.swing.text.Document createDefaultDocument() { JavaDocument doc = new JavaDocument(); doc.setEditWindow(editWindow); return doc; } /** * Fetches the set of commands that can be used * on a text component that is using a model and * view produced by this kit. * * @return the set of actions */ @Override public Action[] getActions() { return super.getActions(); } /** * Gets the MIME type of the data that this * kit represents support for. * * @return the type */ @Override public String getContentType() { return "text/java"; } /** * Insert the method's description here. * Creation date: (4/18/2001 5:05:58 PM) * * @return robocode.editor.EditWindow */ public EditWindow getEditWindow() { return editWindow; } /** * Fetches a factory that is suitable for producing * views of any models that are produced by this * kit. * * @return the factory */ @Override public ViewFactory getViewFactory() { return new RobocodeViewFactory(); } /** * Inserts content from the given stream which is expected * to be in a format appropriate for this kind of content * handler. * * @param in The stream to read from * @param doc The destination for the insertion. * @param pos The location in the document to place the * content >= 0. * @throws IOException on any I/O error * @throws BadLocationException if pos represents an invalid * location within the document. */ @Override public void read(InputStream in, Document doc, int pos) throws IOException, BadLocationException { super.read(in, doc, pos); } /** * Inserts content from the given stream which is expected * to be in a format appropriate for this kind of content * handler. *

* Since actual text editing is unicode based, this would * generally be the preferred way to read in the data. * Some types of content are stored in an 8-bit form however, * and will favor the InputStream. * * @param in The stream to read from * @param doc The destination for the insertion. * @param pos The location in the document to place the * content >= 0. * @throws IOException on any I/O error * @throws BadLocationException if pos represents an invalid * location within the document. */ @Override public void read(Reader in, Document doc, int pos) throws IOException, BadLocationException { super.read(in, doc, pos); } public void setEditWindow(EditWindow newEditWindow) { editWindow = newEditWindow; } /** * Writes content from a document to the given stream * in a format appropriate for this kind of content handler. * * @param out The stream to write to * @param doc The source for the write. * @param pos The location in the document to fetch the * content from >= 0. * @param len The amount to write out >= 0. * @throws IOException on any I/O error * @throws BadLocationException if pos represents an invalid * location within the document. */ @Override public void write(java.io.OutputStream out, javax.swing.text.Document doc, int pos, int len) throws java.io.IOException, javax.swing.text.BadLocationException { super.write(out, doc, pos, len); } /** * Writes content from a document to the given stream * in a format appropriate for this kind of content handler. *

* Since actual text editing is unicode based, this would * generally be the preferred way to write the data. * Some types of content are stored in an 8-bit form however, * and will favor the OutputStream. * * @param out The stream to write to * @param doc The source for the write. * @param pos The location in the document to fetch the * content >= 0. * @param len The amount to write out >= 0. * @throws IOException on any I/O error * @throws BadLocationException if pos represents an invalid * location within the document. */ @Override public void write(Writer out, Document doc, int pos, int len) throws IOException, BadLocationException { super.write(out, doc, pos, len); } } robocode/robocode/robocode/editor/RobocodeView.java0000644000175000017500000001354611130241112021747 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation *******************************************************************************/ package robocode.editor; import javax.swing.event.DocumentEvent; import javax.swing.text.*; import java.awt.*; /** * @author Mathew A. Nelson (original) */ public class RobocodeView extends PlainView { public final static Color commentColor = new Color(0, 150, 0); public final static Color stringColor = new Color(0, 150, 150); public final static Color keywordColor = new Color(0, 0, 150); public final static Color textColor = Color.black; public final static int TEXT = 0; public final static int KEYWORD = 1; public final static int COMMENT = 2; public final static int STRING = 3; public final static int MULTILINECOMMENT = 4; public RobocodeView(Element elem) { super(elem); } @Override public void changedUpdate(DocumentEvent e, Shape a, ViewFactory f) { super.changedUpdate(e, a, f); JavaDocument d = (JavaDocument) e.getDocument(); if (d.isNeedsRedraw()) { getContainer().repaint(); d.setNeedsRedraw(false); } } @Override protected int drawUnselectedText(java.awt.Graphics g, int x, int y, int p0, int p1) throws BadLocationException { Document doc = getDocument(); Segment segment = new Segment(); Segment token = getLineBuffer(); doc.getText(p0, p1 - p0, segment); int count = p1 - p0; int left = 0; int state = TEXT; int elementIndex = doc.getDefaultRootElement().getElementIndex(p0); AttributeSet lineAttributes = doc.getDefaultRootElement().getElement(elementIndex).getAttributes(); if (lineAttributes.isDefined("inComment")) { state = MULTILINECOMMENT; } for (int i = 0; i < count; i++) { // Starting in default text state. if (state == TEXT) { if (Character.isLetter(segment.array[i + segment.offset]) && Character.isLowerCase(segment.array[i + segment.offset])) { // flush now g.setColor(textColor); doc.getText(p0 + left, i - left, token); x = Utilities.drawTabbedText(token, x, y, g, this, p0 + left); left = i; state = KEYWORD; } // Do nothing else { if (segment.array[i + segment.offset] == '/') { // flush now g.setColor(textColor); doc.getText(p0 + left, i - left, token); x = Utilities.drawTabbedText(token, x, y, g, this, p0 + left); left = i; state = COMMENT; } else if (segment.array[i + segment.offset] == '"') { // flush now g.setColor(textColor); doc.getText(p0 + left, i - left, token); x = Utilities.drawTabbedText(token, x, y, g, this, p0 + left); left = i; state = STRING; } } } else if (state == KEYWORD) { // Still if (Character.isLetter(segment.array[i + segment.offset])) {// && Character.isLowerCase(segment.array[i+segment.offset])) } else { // flush now doc.getText(p0 + left, i - left, token); if (Keywords.isKeyword(token)) { g.setColor(keywordColor); } else { g.setColor(textColor); } x = Utilities.drawTabbedText(token, x, y, g, this, p0 + left); left = i; state = TEXT; if (segment.array[i + segment.offset] == '/') { state = COMMENT; } else if (segment.array[i + segment.offset] == '"') { state = STRING; } } } else if (state == COMMENT) { if (segment.array[i + segment.offset] == '/') { break; } else if (segment.array[i + segment.offset] == '*') { state = MULTILINECOMMENT; } else { state = TEXT; } } else if (state == MULTILINECOMMENT) { if (i > 0 && segment.array[i + segment.offset] == '/' && segment.array[i + segment.offset - 1] == '*') { // flush now doc.getText(p0 + left, i + 1 - left, token); g.setColor(commentColor); x = Utilities.drawTabbedText(token, x, y, g, this, p0 + left); left = i + 1; state = TEXT; } } else if (state == STRING) { if (segment.array[i + segment.offset] == '"') { // flush now doc.getText(p0 + left, i + 1 - left, token); g.setColor(stringColor); x = Utilities.drawTabbedText(token, x, y, g, this, p0 + left); left = i + 1; state = TEXT; } } // Starting not in token } // end loop // Flush last doc.getText(p0 + left, p1 - p0 - left, token); if (state == KEYWORD) { if (Keywords.isKeyword(token)) { g.setColor(keywordColor); } else { g.setColor(textColor); } } else if (state == STRING) { g.setColor(stringColor); } else if (state == COMMENT && ((p1 - p0 - left) > 1)) { g.setColor(commentColor); } else if (state == MULTILINECOMMENT) { g.setColor(commentColor); } else { g.setColor(textColor); } x = Utilities.drawTabbedText(token, x, y, g, this, p0 + left); return x; } @Override protected int getTabSize() { return 4; } @Override public void insertUpdate(DocumentEvent e, Shape a, ViewFactory f) { super.insertUpdate(e, a, f); JavaDocument d = (JavaDocument) e.getDocument(); if (d.isNeedsRedraw()) { getContainer().repaint(); d.setNeedsRedraw(false); } } @Override public void removeUpdate(DocumentEvent e, Shape a, ViewFactory f) { super.removeUpdate(e, a, f); JavaDocument d = (JavaDocument) e.getDocument(); if (d.isNeedsRedraw()) { getContainer().repaint(); d.setNeedsRedraw(false); } } } robocode/robocode/robocode/editor/MoreWindowsDialog.java0000644000175000017500000001057311130241112022752 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Matthew Reeder * - Initial API and implementation * Flemming N. Larsen * - Ported to Java 5 * - Optimizations *******************************************************************************/ package robocode.editor; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.Vector; /** * @author Matthew Reeder (original) * @author Flemming N. Larsen (contributor) */ @SuppressWarnings("serial") public class MoreWindowsDialog extends JDialog implements ActionListener, MouseListener { private JButton activateButton; private JButton cancelButton; private JButton closeButton; private JList windowList; private final Vector windowListItems; public MoreWindowsDialog(RobocodeEditor window) { super(window, "More Windows...", false); windowListItems = new Vector(); JPanel listPanel = new JPanel(new GridLayout(1, 1)); listPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Open Windows")); listPanel.add(new JScrollPane(getWindowList())); JPanel buttonPanel = new JPanel(); buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS)); buttonPanel.add(getActivateButton()); buttonPanel.add(getCancelButton()); buttonPanel.add(getCloseButton()); getContentPane().setLayout(new BorderLayout()); getContentPane().add(buttonPanel, BorderLayout.SOUTH); getContentPane().add(listPanel); setSize(400, 400); } public void addWindowItem(WindowMenuItem item) { windowListItems.add(item); getWindowList().setListData(windowListItems); } public void removeWindowItem(WindowMenuItem item) { windowListItems.remove(item); getWindowList().setListData(windowListItems); } public JButton getActivateButton() { if (activateButton == null) { activateButton = new JButton(); activateButton.setText("Activate"); activateButton.setMnemonic('A'); activateButton.setDefaultCapable(true); activateButton.addActionListener(this); } return activateButton; } public JButton getCancelButton() { if (cancelButton == null) { cancelButton = new JButton(); cancelButton.setText("Cancel"); cancelButton.setMnemonic('C'); cancelButton.addActionListener(this); } return cancelButton; } public JButton getCloseButton() { if (closeButton == null) { closeButton = new JButton(); closeButton.setText("Close"); closeButton.setMnemonic('l'); closeButton.setDisplayedMnemonicIndex(1); closeButton.addActionListener(this); } return closeButton; } public JList getWindowList() { if (windowList == null) { windowList = new JList(); windowList.addMouseListener(this); windowList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); } return windowList; } public void actionPerformed(ActionEvent e) { if (e.getSource() == closeButton) { WindowMenuItem item = (WindowMenuItem) windowList.getSelectedValue(); if (item != null && item.getEditWindow() != null) { item.getEditWindow().doDefaultCloseAction(); } } else { if (e.getSource() == activateButton) { WindowMenuItem item = (WindowMenuItem) windowList.getSelectedValue(); if (item != null) { item.actionPerformed(null); } } setVisible(false); } } public void mouseClicked(MouseEvent e) { if (e.getSource() == getWindowList() && e.getClickCount() == 2) { WindowMenuItem item = windowListItems.get(windowList.locationToIndex(e.getPoint())); item.actionPerformed(null); // Good thing WindowMenuItem doesn't // reference the ActionEvent? setVisible(false); } } public void mousePressed(MouseEvent e) {} public void mouseReleased(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} } robocode/robocode/robocode/editor/RobocodeViewFactory.java0000644000175000017500000000207011130241112023265 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation *******************************************************************************/ package robocode.editor; import javax.swing.text.Element; import javax.swing.text.View; /** * @author Mathew A. Nelson (original) */ public class RobocodeViewFactory implements javax.swing.text.ViewFactory { /** * Creates a view from the given structural element of a * document. * * @param elem the piece of the document to build a view of * @return the view * @see View */ public View create(Element elem) { return new RobocodeView(elem); } } robocode/robocode/robocode/editor/JavaDocument.java0000644000175000017500000002466011130241112021737 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Bugfix: Tabs were sometimes added at the end of the document when * strings are inserted. Bug fixed with the insertString() method, were the * tabCount is now decremented when a '}' is found in the current element * - Updated to use methods from the Logger, which replaces logger methods * that have been (re)moved from the robocode.util.Utils class *******************************************************************************/ package robocode.editor; import robocode.io.Logger; import javax.swing.event.DocumentEvent; import javax.swing.text.*; import javax.swing.undo.UndoManager; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ @SuppressWarnings("serial") public class JavaDocument extends PlainDocument { private UndoHandler undoHandler; private boolean needsRedraw; private EditWindow editWindow; private boolean editing; public JavaDocument() { super(); init(); } public EditWindow getEditWindow() { return editWindow; } private void init() { addUndoableEditListener(getUndoHandler()); } @Override public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { if (!editing) { super.insertString(offs, str, a); return; } if (str.equals("}")) { if (getText(offs - 1, 1).equals("\t")) { super.remove(offs - 1, 1); super.insertString(offs - 1, str, a); } else { super.insertString(offs, str, a); } } else if (str.equals("\n")) { int elementIndex = getDefaultRootElement().getElementIndex(offs); Element element = getDefaultRootElement().getElement(elementIndex); int startOffset = element.getStartOffset(); int endOffset = element.getEndOffset(); String elementText; elementText = getText(startOffset, endOffset - startOffset); int tabCount = 0; while (elementText.charAt(tabCount) == '\t') { tabCount++; } if (elementText.indexOf("{") >= 0) { tabCount++; } if (elementText.indexOf("}") >= 0) { tabCount--; } String tabs = ""; for (int i = 0; i < tabCount; i++) { tabs += "\t"; } super.insertString(offs, str + tabs, a); } else { super.insertString(offs, str, a); } } @Override protected void insertUpdate(DefaultDocumentEvent event, AttributeSet attributeSet) { if (editWindow != null) { editWindow.setModified(true); } int orgChangedIndex = getDefaultRootElement().getElementIndex(event.getOffset()); super.insertUpdate(event, attributeSet); // Get the root element Element rootElement = getDefaultRootElement(); // Determine what changes were made to the document DocumentEvent.ElementChange deltas = event.getChange(rootElement); if (deltas == null) { Element changedElement = getDefaultRootElement().getElement(orgChangedIndex); processMultilineComments(changedElement, false); } else { Element changedElements[] = deltas.getChildrenAdded(); if (changedElements == null || changedElements.length == 0) { Logger.logError("Unknown insert even, 0 children added."); } else { for (Element element : changedElements) { processMultilineComments(element, true); } } } } public boolean isNeedsRedraw() { return needsRedraw; } @Override protected void postRemoveUpdate(DefaultDocumentEvent event) { if (editWindow != null) { editWindow.setModified(true); } super.postRemoveUpdate(event); processMultilineComments(event); } public void processMultilineComments(DefaultDocumentEvent event) { Element rootElement = getDefaultRootElement(); // Determine what changes were made to the document int changedIndex = getDefaultRootElement().getElementIndex(event.getOffset()); Element changedElement = getDefaultRootElement().getElement(changedIndex); processMultilineComments(changedElement, event.getChange(rootElement) != null); } public void processMultilineComments(Element element, boolean isDeltas) { int elementIndex = getDefaultRootElement().getElementIndex(element.getStartOffset()); int startOffset = element.getStartOffset(); int endOffset = element.getEndOffset(); String elementText; try { elementText = getText(startOffset, endOffset - startOffset); } catch (BadLocationException e) { Logger.logError("Error processing updates: ", e); return; } boolean followingLineComment, previousLineComment = false, startsComment = false, endsComment = false; // If we already had a comment flag, then the last line must // have ended "still in a comment" MutableAttributeSet a = (MutableAttributeSet) element.getAttributes(); if (a.isDefined("inComment")) { previousLineComment = true; } // we don't have a comment flag, so check the last line. // note: This should only happen on new lines! else if (isDeltas) { int lastElementIndex = elementIndex - 1; if (lastElementIndex >= 0) { AbstractElement lastElement = (AbstractElement) getDefaultRootElement().getElement(lastElementIndex); if (!lastElement.isDefined("endsComment") && lastElement.isDefined("inComment") || lastElement.isDefined("startsComment")) { a.addAttribute("inComment", "inComment"); previousLineComment = true; } } } followingLineComment = previousLineComment; int cIndex = elementText.indexOf("//"); int eIndex, sIndex; if (cIndex >= 0) { eIndex = elementText.lastIndexOf("*/", cIndex); sIndex = elementText.lastIndexOf("/*", cIndex); } else { eIndex = elementText.lastIndexOf("*/"); sIndex = elementText.lastIndexOf("/*"); } if (eIndex > sIndex) { followingLineComment = false; endsComment = true; startsComment = false; } else if (sIndex > eIndex) { followingLineComment = true; startsComment = true; endsComment = false; } // Following lines should be comments. if (followingLineComment) { // We started the comment if (startsComment) { if (!a.isDefined("startsComment")) { // mark line startsComment a.addAttribute("startsComment", "startsComment"); // make sure next line(s) are marked inComment, until an endComment line setFollowingLinesCommentFlag(startOffset, true); } } else if (a.isDefined("startsComment")) { a.removeAttribute("startsComment"); } // If we used to end the comment but no longer do, fix that... if (a.isDefined("endsComment")) { // unmark line as endsComment a.removeAttribute("endsComment"); // make sure next line(s) are marked inComment, until a endsComment line setFollowingLinesCommentFlag(startOffset, true); } // For cut & paste we need to check anyway. else if (isDeltas) { setFollowingLinesCommentFlag(startOffset, true); } } // Else following lines are NOT comments else { // setFollowingLinesCommentFlag(startOffset,false); // We ended the comment if (endsComment) { if (!a.isDefined("endsComment")) { // mark line endsComment a.addAttribute("endsComment", "endsComment"); // Make sure next line(s) are marked !inComment, until a startComment line setFollowingLinesCommentFlag(startOffset, false); } } else if (a.isDefined("endsComment")) { a.removeAttribute("endsComment"); } // If we used to start a comment, but no longer do, fix that... if (a.isDefined("startsComment")) { // mark line startsComment a.removeAttribute("startsComment"); // make sure next line(s) are marked !inComment, until an endComment line setFollowingLinesCommentFlag(startOffset, false); } // For cut & paste we need to check anyway. else if (isDeltas) { setFollowingLinesCommentFlag(startOffset, false); } } } public void setEditWindow(EditWindow newEditWindow) { editWindow = newEditWindow; } public void setFollowingLinesCommentFlag(int offset, boolean commentFlag) { int elementIndex = getDefaultRootElement().getElementIndex(offset); elementIndex++; boolean done = false; while (!done) { // need to check for last line somehow... Element e = getDefaultRootElement().getElement(elementIndex); if (e == null) { done = true; } else { MutableAttributeSet a = (MutableAttributeSet) e.getAttributes(); if (commentFlag) { if (a.isDefined("inComment")) { done = true; } else { a.addAttribute("inComment", "inComment"); needsRedraw = true; } if (a.isDefined("endsComment")) { done = true; } } else { if (!a.isDefined("inComment")) { done = true; } else { a.removeAttribute("inComment"); needsRedraw = true; } if (a.isDefined("startsComment")) { done = true; } } elementIndex++; } } } public void setNeedsRedraw(boolean newNeedsRedraw) { needsRedraw = newNeedsRedraw; } public boolean getEditing() { return editing; } public void setEditing(boolean editing) { this.editing = editing; } /** * Returns the UndoHandler * * @return the UndoHandler */ private UndoHandler getUndoHandler() { if (undoHandler == null) { undoHandler = new UndoHandler(); } return undoHandler; } /** * Undo */ public void undo() { if (getUndoHandler().canUndo()) { writeLock(); getUndoHandler().undo(); writeUnlock(); needsRedraw = true; } } /** * Redo */ public void redo() { if (getUndoHandler().canRedo()) { writeLock(); getUndoHandler().redo(); writeUnlock(); needsRedraw = true; } } private class UndoHandler extends UndoManager { @Override public synchronized void undo() { super.undo(); processMultilineComments((DefaultDocumentEvent) lastEdit()); } @Override public synchronized void redo() { super.redo(); processMultilineComments((DefaultDocumentEvent) lastEdit()); } } } robocode/robocode/robocode/editor/RobocodeEditor.java0000644000175000017500000005047511130241112022265 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Matthew Reeder * - Changes for Find/Replace commands and Window menu * Flemming N. Larsen * - Code cleanup * - Bugfixed the removeFromWindowMenu() method which did not remove the * correct item, and did not break out of the loop when it was found. * - Updated to use methods from ImageUtil, FileUtil, Logger, which replaces * methods that have been (re)moved from the robocode.util.Utils class * - Changed to use FileUtil.getRobocodeConfigFile() and * FileUtil.getRobotsDir() * - Added missing close() on FileInputStream, FileOutputStream, and * FileReader *******************************************************************************/ package robocode.editor; import robocode.gfx.ImageUtil; import robocode.io.FileUtil; import robocode.io.Logger; import static robocode.io.Logger.logError; import robocode.manager.BrowserManager; import robocode.manager.RobocodeManager; import robocode.manager.RobocodeProperties; import javax.swing.*; import javax.swing.filechooser.FileFilter; import javax.swing.text.Document; import java.awt.*; import java.awt.event.*; import java.io.*; /** * @author Mathew A. Nelson (original) * @author Matthew Reeder (contributor) * @author Flemming N. Larsen (contributor) */ @SuppressWarnings("serial") public class RobocodeEditor extends JFrame implements Runnable { private JPanel robocodeEditorContentPane; private RobocodeEditorMenuBar robocodeEditorMenuBar; private JDesktopPane desktopPane; public boolean isApplication; public final Point origin = new Point(); public final File robotsDirectory; private JToolBar statusBar; private JLabel lineLabel; private RobocodeProperties robocodeProperties; private File editorDirectory; private final RobocodeManager manager; private FindReplaceDialog findReplaceDialog; private ReplaceAction replaceAction; final EventHandler eventHandler = new EventHandler(); class EventHandler implements ComponentListener { public void componentMoved(ComponentEvent e) {} public void componentHidden(ComponentEvent e) {} public void componentShown(ComponentEvent e) { new Thread(RobocodeEditor.this).start(); } public void componentResized(ComponentEvent e) {} } /** * Action that launches the Replace dialog. *

* The reason this is needed (and the menubar isn't sufficient) is that * ctrl+H is bound in JTextComponents at a lower level to backspace and in * order to override this, I need to rebind it to an Action when the * JEditorPane is created. */ class ReplaceAction extends AbstractAction { public void actionPerformed(ActionEvent e) { replaceDialog(); } } public RobocodeEditor(RobocodeManager manager) { super(); this.manager = manager; if (manager != null) { robotsDirectory = manager.getRobotRepositoryManager().getRobotsDirectory(); } else { robotsDirectory = FileUtil.getRobotsDir(); } initialize(); } public void addPlaceShowFocus(JInternalFrame internalFrame) { getDesktopPane().add(internalFrame); // Center a window Dimension screenSize = getDesktopPane().getSize(); Dimension size = internalFrame.getSize(); if (size.height > screenSize.height) { size.height = screenSize.height; } if (size.width > screenSize.width) { size.width = screenSize.width; } if (origin.x + size.width > screenSize.width) { origin.x = 0; } if (origin.y + size.height > screenSize.height) { origin.y = 0; } internalFrame.setLocation(origin); origin.x += 10; origin.y += 10; internalFrame.setVisible(true); getDesktopPane().moveToFront(internalFrame); if (internalFrame instanceof EditWindow) { ((EditWindow) internalFrame).getEditorPane().requestFocus(); } else { internalFrame.requestFocus(); } } public boolean close() { JInternalFrame[] frames = getDesktopPane().getAllFrames(); if (frames != null) { for (JInternalFrame frame : frames) { if (frame != null) { frame.moveToFront(); if ((frame instanceof EditWindow) && !((EditWindow) frame).fileSave(true)) { return false; } } } } if (isApplication) { System.exit(0); } else { dispose(); } return true; } public void createNewJavaFile() { String packageName = null; if (getActiveWindow() != null) { packageName = getActiveWindow().getPackage(); } if (packageName == null) { packageName = "mypackage"; } EditWindow editWindow = new EditWindow(this, robotsDirectory); editWindow.setModified(false); String templateName = "templates" + File.separatorChar + "newjavafile.tpt"; String template = ""; File f = new File(FileUtil.getCwd(), templateName); int size = (int) (f.length()); byte buff[] = new byte[size]; FileInputStream fis = null; DataInputStream dis = null; try { fis = new FileInputStream(f); dis = new DataInputStream(fis); dis.readFully(buff); template = new String(buff); } catch (IOException e) { template = "Unable to read template file: " + FileUtil.getCwd() + File.pathSeparatorChar + templateName; } finally { if (fis != null) { try { fis.close(); } catch (IOException ignored) {} } if (dis != null) { try { dis.close(); } catch (IOException ignored) {} } } String name = "MyClass"; int index = template.indexOf("$"); while (index >= 0) { if (template.substring(index, index + 10).equals("$CLASSNAME")) { template = template.substring(0, index) + name + template.substring(index + 10); index += name.length(); } else if (template.substring(index, index + 8).equals("$PACKAGE")) { template = template.substring(0, index) + packageName + template.substring(index + 8); index += packageName.length(); } else { index++; } index = template.indexOf("$", index); } editWindow.getEditorPane().setText(template); editWindow.getEditorPane().setCaretPosition(0); Document d = editWindow.getEditorPane().getDocument(); if (d instanceof JavaDocument) { ((JavaDocument) d).setEditing(true); } addPlaceShowFocus(editWindow); } public void createNewRobot() { boolean done = false; String message = "Type in the name for your robot.\nExample: MyFirstRobot"; String name = ""; while (!done) { name = (String) JOptionPane.showInputDialog(this, message, "New Robot", JOptionPane.PLAIN_MESSAGE, null, null, name); if (name == null || name.trim().length() == 0) { return; } if (name.length() > 32) { message = "Please choose a shorter name. (32 characters or less)"; continue; } char firstLetter = name.charAt(0); if (!Character.isJavaIdentifierStart(firstLetter)) { message = "Please start your name with a letter (A-Z)"; continue; } done = true; for (int t = 1; done && t < name.length(); t++) { if (!Character.isJavaIdentifierPart(name.charAt(t))) { message = "Your name contains an invalid character.\nPlease use only letters and/or digits."; done = false; break; } } if (!done) { continue; } if (!Character.isUpperCase(firstLetter)) { // popup message = "The first character should be uppercase,\nas should the first letter of all words in the name.\nExample: MyFirstRobot"; name = name.substring(0, 1).toUpperCase() + name.substring(1); done = false; } } message = "Please enter your initials.\n" + "To avoid name conflicts with other robots named " + name + ",\n" + "we need a short string to identify this one as one of yours.\n" + "Your initials will work well here,\n" + "but you may choose any short string that you like.\n" + "You should enter the same thing for all your robots."; String packageName = ""; done = false; while (!done) { packageName = (String) JOptionPane.showInputDialog(this, message, name + " - package name", JOptionPane.PLAIN_MESSAGE, null, null, packageName); if (packageName == null) { return; } if (packageName.length() > 16) { message = "Please choose a shorter name. (16 characters or less)"; continue; } char firstLetter = packageName.charAt(0); if (!Character.isJavaIdentifierStart(firstLetter)) { message = "Please start with a letter (a-z)"; continue; } done = true; for (int t = 1; done && t < packageName.length(); t++) { if (!Character.isJavaIdentifierPart(packageName.charAt(t))) { message = "The string you entered contains an invalid character.\nPlease use only letters and/or digits."; done = false; break; } } if (!done) { continue; } boolean lowercased = false; for (int i = 0; i < packageName.length(); i++) { if (!Character.isLowerCase(packageName.charAt(i)) && !Character.isDigit(packageName.charAt(i))) { lowercased = true; break; } } if (lowercased) { packageName = packageName.toLowerCase(); message = "Please use all lowercase letters here."; done = false; } if (done && manager != null) { done = manager.getRobotRepositoryManager().verifyRobotName(packageName + "." + name, name); if (!done) { message = "This package is reserved. Please select a different package."; } } } EditWindow editWindow = new EditWindow(this, robotsDirectory); editWindow.setRobotName(name); editWindow.setModified(false); String templateName = "templates" + File.separatorChar + "newrobot.tpt"; String template = ""; File f = new File(FileUtil.getCwd(), templateName); int size = (int) (f.length()); byte buff[] = new byte[size]; FileInputStream fis = null; DataInputStream dis = null; try { fis = new FileInputStream(f); dis = new DataInputStream(fis); dis.readFully(buff); dis.close(); template = new String(buff); } catch (IOException e) { template = "Unable to read template file: " + FileUtil.getCwd() + File.pathSeparatorChar + templateName; } finally { if (fis != null) { try { fis.close(); } catch (IOException ignored) {} } if (dis != null) { try { dis.close(); } catch (IOException ignored) {} } } int index = template.indexOf("$"); while (index >= 0) { if (template.substring(index, index + 10).equals("$CLASSNAME")) { template = template.substring(0, index) + name + template.substring(index + 10); index += name.length(); } else if (template.substring(index, index + 8).equals("$PACKAGE")) { template = template.substring(0, index) + packageName + template.substring(index + 8); index += packageName.length(); } else { index++; } index = template.indexOf("$", index); } editWindow.getEditorPane().setText(template); editWindow.getEditorPane().setCaretPosition(0); Document d = editWindow.getEditorPane().getDocument(); if (d instanceof JavaDocument) { ((JavaDocument) d).setEditing(true); } addPlaceShowFocus(editWindow); if (manager != null) { manager.getRobotRepositoryManager().clearRobotList(); } } public void findDialog() { getFindReplaceDialog().showDialog(false); } public void replaceDialog() { getFindReplaceDialog().showDialog(true); } public EditWindow getActiveWindow() { JInternalFrame[] frames = getDesktopPane().getAllFrames(); EditWindow editWindow = null; if (frames != null) { for (JInternalFrame frame : frames) { if (frame.isSelected()) { if (frame instanceof EditWindow) { editWindow = (EditWindow) frame; } break; } } } return editWindow; } public RobocodeCompiler getCompiler() { return RobocodeCompilerFactory.createCompiler(this); } public JDesktopPane getDesktopPane() { if (desktopPane == null) { desktopPane = new JDesktopPane(); desktopPane.setBackground(new Color(128, 128, 128)); desktopPane.setPreferredSize(new Dimension(600, 500)); } return desktopPane; } private JLabel getLineLabel() { if (lineLabel == null) { lineLabel = new JLabel(); } return lineLabel; } private JPanel getRobocodeEditorContentPane() { if (robocodeEditorContentPane == null) { robocodeEditorContentPane = new JPanel(); robocodeEditorContentPane.setLayout(new BorderLayout()); robocodeEditorContentPane.add(getDesktopPane(), "Center"); robocodeEditorContentPane.add(getStatusBar(), "South"); } return robocodeEditorContentPane; } private RobocodeEditorMenuBar getRobocodeEditorMenuBar() { if (robocodeEditorMenuBar == null) { robocodeEditorMenuBar = new RobocodeEditorMenuBar(this); } return robocodeEditorMenuBar; } public RobocodeProperties getRobocodeProperties() { if (robocodeProperties == null) { robocodeProperties = new RobocodeProperties(manager); FileInputStream in = null; try { in = new FileInputStream(FileUtil.getRobocodeConfigFile()); robocodeProperties.load(in); } catch (FileNotFoundException e) { logError("No " + FileUtil.getRobocodeConfigFile().getName() + " file, using defaults."); } catch (IOException e) { logError("IO Exception reading " + FileUtil.getRobocodeConfigFile().getName(), e); } finally { if (in != null) { try { in.close(); } catch (IOException ignored) {} } } } return robocodeProperties; } private JToolBar getStatusBar() { if (statusBar == null) { statusBar = new JToolBar(); statusBar.setLayout(new BorderLayout()); statusBar.add(getLineLabel(), BorderLayout.WEST); } return statusBar; } public FindReplaceDialog getFindReplaceDialog() { if (findReplaceDialog == null) { findReplaceDialog = new FindReplaceDialog(this); } return findReplaceDialog; } public Action getReplaceAction() { if (replaceAction == null) { replaceAction = new ReplaceAction(); } return replaceAction; } public void addToWindowMenu(EditWindow window) { WindowMenuItem item = new WindowMenuItem(window, getRobocodeEditorMenuBar().getWindowMenu()); getRobocodeEditorMenuBar().getMoreWindowsDialog().addWindowItem(item); } public void removeFromWindowMenu(EditWindow window) { for (Component c : getRobocodeEditorMenuBar().getWindowMenu().getMenuComponents()) { if (c instanceof WindowMenuItem) { WindowMenuItem item = (WindowMenuItem) c; if (item.getEditWindow() == window) { getRobocodeEditorMenuBar().getWindowMenu().remove(item); getRobocodeEditorMenuBar().getMoreWindowsDialog().removeWindowItem(item); break; } } } } private void initialize() { addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { close(); } }); setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); setIconImage(ImageUtil.getImage("/resources/icons/robocode-icon.png")); setTitle("Robot Editor"); setJMenuBar(getRobocodeEditorMenuBar()); setContentPane(getRobocodeEditorContentPane()); addComponentListener(eventHandler); } public static void main(String[] args) { try { // Set the Look and Feel (LAF) robocode.manager.LookAndFeelManager.setLookAndFeel(); RobocodeEditor robocodeEditor; robocodeEditor = new RobocodeEditor(null); robocodeEditor.isApplication = true; // used for close robocodeEditor.pack(); // Center robocodeEditor Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); Dimension size = robocodeEditor.getSize(); if (size.height > screenSize.height) { size.height = screenSize.height; } if (size.width > screenSize.width) { size.width = screenSize.width; } robocodeEditor.setLocation((screenSize.width - size.width) / 2, (screenSize.height - size.height) / 2); robocodeEditor.setVisible(true); // 2nd time for bug in some JREs robocodeEditor.setVisible(true); } catch (Throwable e) { Logger.logError("Exception in RoboCodeEditor.main", e); } } public void openRobot() { if (editorDirectory == null) { editorDirectory = robotsDirectory; } JFileChooser chooser; chooser = new JFileChooser(editorDirectory); FileFilter filter = new FileFilter() { @Override public boolean accept(File pathname) { if (pathname.isHidden()) { return false; } if (pathname.isDirectory()) { return true; } String fn = pathname.getName(); int idx = fn.lastIndexOf('.'); String extension = ""; if (idx >= 0) { extension = fn.substring(idx); } return extension.equalsIgnoreCase(".java"); } @Override public String getDescription() { return "Robots"; } }; chooser.setFileFilter(filter); int rv = chooser.showOpenDialog(this); if (rv == JFileChooser.APPROVE_OPTION) { String robotFilename = chooser.getSelectedFile().getPath(); editorDirectory = chooser.getSelectedFile().getParentFile(); FileReader fileReader = null; try { fileReader = new FileReader(robotFilename); EditWindow editWindow = new EditWindow(this, robotsDirectory); editWindow.getEditorPane().read(fileReader, new File(robotFilename)); editWindow.getEditorPane().setCaretPosition(0); editWindow.setFileName(robotFilename); editWindow.setModified(false); Document d = editWindow.getEditorPane().getDocument(); if (d instanceof JavaDocument) { ((JavaDocument) d).setEditing(true); } addPlaceShowFocus(editWindow); } catch (Exception e) { JOptionPane.showMessageDialog(this, e.toString()); Logger.logError(e); } finally { if (fileReader != null) { try { fileReader.close(); } catch (IOException ignored) {} } } } } public void extractRobot() { manager.getWindowManager().showRobotExtractor(this); } public void run() { getCompiler(); } public void saveAsRobot() { EditWindow editWindow = getActiveWindow(); if (editWindow != null) { editWindow.fileSaveAs(); } } public void saveRobocodeProperties() { if (robocodeProperties == null) { logError("Cannot save null robocode properties"); return; } FileOutputStream out = null; try { out = new FileOutputStream(FileUtil.getRobocodeConfigFile()); robocodeProperties.store(out, "Robocode Properties"); } catch (IOException e) { Logger.logError(e); } finally { if (out != null) { try { out.close(); } catch (IOException ignored) {} } } } public void resetCompilerProperties() { CompilerProperties props = RobocodeCompilerFactory.getCompilerProperties(); props.resetCompiler(); RobocodeCompilerFactory.saveCompilerProperties(); getCompiler(); } public void saveRobot() { EditWindow editWindow = getActiveWindow(); if (editWindow != null) { editWindow.fileSave(false); } } public void setLineStatus(int line) { if (line >= 0) { getLineLabel().setText("Line: " + (line + 1)); } else { getLineLabel().setText(""); } } public void showHelpApi() { String helpurl = "file:" + new File(FileUtil.getCwd(), "").getAbsoluteFile() // System.getProperty("user.dir") + System.getProperty("file.separator") + "javadoc" + System.getProperty("file.separator") + "index.html"; try { BrowserManager.openURL(helpurl); } catch (IOException e) { JOptionPane.showMessageDialog(this, e.getMessage(), "Unable to open browser!", JOptionPane.INFORMATION_MESSAGE); } } /** * Gets the manager. * * @return Returns a RobocodeManager */ public RobocodeManager getManager() { return manager; } public void setSaveFileMenuItemsEnabled(boolean enabled) { robocodeEditorMenuBar.getFileSaveAsMenuItem().setEnabled(enabled); robocodeEditorMenuBar.getFileSaveMenuItem().setEnabled(enabled); } } robocode/robocode/robocode/editor/Keywords.java0000644000175000017500000000361011130241112021156 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - This class was made final * - The constructor was removed * - The string constant 'keywords' was renamed into 'KEYWORDS' *******************************************************************************/ package robocode.editor; import javax.swing.text.Segment; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ public final class Keywords { // TODO: Must be updated for Java 5? private final static String KEYWORDS[] = { "abstract", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "default", "do", "double", "else", "extends", "final", "finally", "float", "for", "goto", "if", "implements", "import", "instanceof", "int", "interface", "long", "native", "new", "package", "private", "protected", "public", "return", "short", "static", "strictfp", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "try", "void", "volatile", "while", "true", "false" }; public static boolean isKeyword(Segment seg) { boolean match = false; for (int i = 0; !match && i < KEYWORDS.length; i++) { if (seg.count == KEYWORDS[i].length()) { match = true; for (int j = 0; match && j < seg.count; j++) { if (seg.array[seg.offset + j] != KEYWORDS[i].charAt(j)) { match = false; } } } } return match; } } robocode/robocode/robocode/editor/RobocodeEditorMenuBar.java0000644000175000017500000005571011130241112023534 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Matthew Reeder * - Added Edit and Window menus * - Added keyboard mnemonics to all menus and menu items * Flemming N. Larsen * - Code cleanup * - Updated to use methods from the WindowUtil, which replaces window * methods that have been (re)moved from the robocode.util.Utils class * - Added confirm dialog when trying to reset the compiler preferences * - Did a lot of NullPointerException bugfixes with getActiveWindow() * - Changed menu accelerator keys to use getMenuShortcutKeyMask() instead of * Event.CTRL_MASK in order to comply with other OSes like e.g. Mac OS * - Changed the F6 key press for 'Compile' into 'modifier key' + B, and the * F3 key press for 'Find Next' into 'modifier key' + G to comply with * OSes like e.g. Mac OS, where the function keys are used for other * purposes *******************************************************************************/ package robocode.editor; import robocode.dialog.WindowUtil; import static robocode.ui.ShortcutUtil.MENU_SHORTCUT_KEY_MASK; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; /** * @author Mathew A. Nelson (original) * @author Matthew Reeder (contributor) * @author Flemming N. Larsen (contributor) */ @SuppressWarnings("serial") public class RobocodeEditorMenuBar extends JMenuBar { private JMenu fileMenu; private JMenuItem fileOpenMenuItem; private JMenuItem fileExtractMenuItem; private JMenuItem fileSaveMenuItem; private JMenuItem fileSaveAsMenuItem; private JMenuItem fileExitMenuItem; class EventHandler implements ActionListener { public void actionPerformed(ActionEvent e) { if (e.getSource() == RobocodeEditorMenuBar.this.getFileNewRobotMenuItem()) { fileNewRobotActionPerformed(); } if (e.getSource() == RobocodeEditorMenuBar.this.getFileNewJavaFileMenuItem()) { fileNewJavaFileActionPerformed(); } if (e.getSource() == RobocodeEditorMenuBar.this.getFileOpenMenuItem()) { fileOpenActionPerformed(); } if (e.getSource() == RobocodeEditorMenuBar.this.getFileExtractMenuItem()) { fileExtractActionPerformed(); } if (e.getSource() == RobocodeEditorMenuBar.this.getFileSaveMenuItem()) { fileSaveActionPerformed(); } if (e.getSource() == RobocodeEditorMenuBar.this.getFileSaveAsMenuItem()) { fileSaveAsActionPerformed(); } if (e.getSource() == RobocodeEditorMenuBar.this.getFileExitMenuItem()) { fileExitActionPerformed(); } if (e.getSource() == RobocodeEditorMenuBar.this.getCompilerCompileMenuItem()) { compilerCompileActionPerformed(); } if (e.getSource() == RobocodeEditorMenuBar.this.getCompilerOptionsPreferencesMenuItem()) { compilerOptionsPreferencesActionPerformed(); } if (e.getSource() == RobocodeEditorMenuBar.this.getCompilerOptionsResetCompilerMenuItem()) { compilerOptionsResetCompilerActionPerformed(); } if (e.getSource() == RobocodeEditorMenuBar.this.getHelpRobocodeApiMenuItem()) { helpRobocodeApiActionPerformed(); } if (e.getSource() == RobocodeEditorMenuBar.this.getEditUndoMenuItem()) { editUndoActionPerformed(); } if (e.getSource() == RobocodeEditorMenuBar.this.getEditRedoMenuItem()) { editRedoActionPerformed(); } if (e.getSource() == RobocodeEditorMenuBar.this.getEditCutMenuItem()) { editCutActionPerformed(); } if (e.getSource() == RobocodeEditorMenuBar.this.getEditCopyMenuItem()) { editCopyActionPerformed(); } if (e.getSource() == RobocodeEditorMenuBar.this.getEditPasteMenuItem()) { editPasteActionPerformed(); } if (e.getSource() == RobocodeEditorMenuBar.this.getEditDeleteMenuItem()) { editDeleteActionPerformed(); } if (e.getSource() == RobocodeEditorMenuBar.this.getEditSelectAllMenuItem()) { editSelectAllActionPerformed(); } if (e.getSource() == RobocodeEditorMenuBar.this.getEditFindMenuItem()) { editFindActionPerformed(); } if (e.getSource() == RobocodeEditorMenuBar.this.getEditFindNextMenuItem()) { editFindNextActionPerformed(); } if (e.getSource() == RobocodeEditorMenuBar.this.getEditReplaceMenuItem()) { editReplaceActionPerformed(); } if (e.getSource() == RobocodeEditorMenuBar.this.getWindowCloseMenuItem()) { windowCloseActionPerformed(); } if (e.getSource() == RobocodeEditorMenuBar.this.getWindowCloseAllMenuItem()) { windowCloseAllActionPerformed(); } if (e.getSource() == RobocodeEditorMenuBar.this.getWindowWindowsDialogMenuItem()) { windowMoreWindowsActionPerformed(); } } } private JMenuItem compilerCompileMenuItem; private JMenu compilerMenu; private JMenu compilerOptionsMenu; private JMenuItem compilerOptionsPreferencesMenuItem; private JMenuItem compilerOptionsResetCompilerMenuItem; private final RobocodeEditor editor; private final EventHandler eventHandler = new EventHandler(); private JMenuItem fileNewJavaFileMenuItem; private JMenu fileNewMenu; private JMenuItem fileNewRobotMenuItem; private JMenu helpMenu; private JMenuItem helpRobocodeApiMenuItem; // New Edit menu by Matthew Reeder private JMenu editMenu; private JMenuItem editUndoMenuItem; private JMenuItem editRedoMenuItem; private JMenuItem editCutMenuItem; private JMenuItem editCopyMenuItem; private JMenuItem editPasteMenuItem; private JMenuItem editDeleteMenuItem; private JMenuItem editFindMenuItem; private JMenuItem editFindNextMenuItem; private JMenuItem editReplaceMenuItem; private JMenuItem editSelectAllMenuItem; // New Window menu by Matthew Reeder private JMenu windowMenu; private JMenuItem windowCloseMenuItem; private JMenuItem windowCloseAllMenuItem; private JMenuItem windowWindowsDialogMenuItem; private MoreWindowsDialog moreWindowsDialog; public RobocodeEditorMenuBar(RobocodeEditor editor) { super(); this.editor = editor; initialize(); } private void compilerCompileActionPerformed() { EditWindow editWindow = editor.getActiveWindow(); if (editWindow != null) { editWindow.compile(); } } private void compilerOptionsPreferencesActionPerformed() { CompilerPreferencesDialog d = new CompilerPreferencesDialog(editor); WindowUtil.packCenterShow(editor, d); } private void compilerOptionsResetCompilerActionPerformed() { if (JOptionPane.showConfirmDialog(editor, "You are about to reset the compiler preferences. Do you wish to proceed?", "Reset Compiler Preferences", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.NO_OPTION) { return; } new Thread(new Runnable() { public void run() { editor.resetCompilerProperties(); } }).start(); } private void fileExitActionPerformed() { editor.dispose(); } private void fileNewJavaFileActionPerformed() { editor.createNewJavaFile(); getFileSaveMenuItem().setEnabled(true); getFileSaveAsMenuItem().setEnabled(true); } private void fileNewRobotActionPerformed() { editor.createNewRobot(); getFileSaveMenuItem().setEnabled(true); getFileSaveAsMenuItem().setEnabled(true); } private void fileOpenActionPerformed() { editor.openRobot(); } private void fileExtractActionPerformed() { editor.extractRobot(); } private void fileSaveActionPerformed() { editor.saveRobot(); } private void fileSaveAsActionPerformed() { editor.saveAsRobot(); } private void editUndoActionPerformed() { EditWindow editWindow = editor.getActiveWindow(); if (editWindow != null) { editWindow.undo(); } } private void editRedoActionPerformed() { EditWindow editWindow = editor.getActiveWindow(); if (editWindow != null) { editWindow.redo(); } } private void editCutActionPerformed() { EditWindow editWindow = editor.getActiveWindow(); if (editWindow != null) { editWindow.getEditorPane().cut(); } } private void editCopyActionPerformed() { EditWindow editWindow = editor.getActiveWindow(); if (editWindow != null) { editWindow.getEditorPane().copy(); } } private void editPasteActionPerformed() { EditWindow editWindow = editor.getActiveWindow(); if (editWindow != null) { editWindow.getEditorPane().paste(); } } private void editDeleteActionPerformed() { EditWindow editWindow = editor.getActiveWindow(); if (editWindow != null) { editWindow.getEditorPane().replaceSelection(null); } } private void editSelectAllActionPerformed() { EditWindow editWindow = editor.getActiveWindow(); if (editWindow != null) { editWindow.getEditorPane().selectAll(); } } private void editFindActionPerformed() { editor.findDialog(); } private void editReplaceActionPerformed() { editor.replaceDialog(); } private void editFindNextActionPerformed() { editor.getFindReplaceDialog().findNext(); } private void windowCloseActionPerformed() { EditWindow editWindow = editor.getActiveWindow(); if (editWindow != null) { editWindow.doDefaultCloseAction(); } } private void windowCloseAllActionPerformed() { JInternalFrame[] frames = editor.getDesktopPane().getAllFrames(); if (frames != null) { for (JInternalFrame frame : frames) { frame.doDefaultCloseAction(); } } } private void windowMoreWindowsActionPerformed() { getMoreWindowsDialog().setVisible(true); } private JMenuItem getCompilerCompileMenuItem() { if (compilerCompileMenuItem == null) { compilerCompileMenuItem = new JMenuItem(); compilerCompileMenuItem.setText("Compile"); compilerCompileMenuItem.setMnemonic('m'); compilerCompileMenuItem.setDisplayedMnemonicIndex(2); compilerCompileMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_B, MENU_SHORTCUT_KEY_MASK)); compilerCompileMenuItem.addActionListener(eventHandler); } return compilerCompileMenuItem; } private JMenu getCompilerMenu() { if (compilerMenu == null) { compilerMenu = new JMenu(); compilerMenu.setText("Compiler"); compilerMenu.setMnemonic('C'); compilerMenu.add(getCompilerCompileMenuItem()); compilerMenu.add(getCompilerOptionsMenu()); } return compilerMenu; } private JMenu getCompilerOptionsMenu() { if (compilerOptionsMenu == null) { compilerOptionsMenu = new JMenu(); compilerOptionsMenu.setText("Options"); compilerOptionsMenu.setMnemonic('O'); compilerOptionsMenu.add(getCompilerOptionsPreferencesMenuItem()); compilerOptionsMenu.add(getCompilerOptionsResetCompilerMenuItem()); } return compilerOptionsMenu; } private JMenuItem getCompilerOptionsPreferencesMenuItem() { if (compilerOptionsPreferencesMenuItem == null) { compilerOptionsPreferencesMenuItem = new JMenuItem(); compilerOptionsPreferencesMenuItem.setText("Preferences"); compilerOptionsPreferencesMenuItem.setMnemonic('P'); compilerOptionsPreferencesMenuItem.addActionListener(eventHandler); } return compilerOptionsPreferencesMenuItem; } private JMenuItem getCompilerOptionsResetCompilerMenuItem() { if (compilerOptionsResetCompilerMenuItem == null) { compilerOptionsResetCompilerMenuItem = new JMenuItem(); compilerOptionsResetCompilerMenuItem.setText("Reset Compiler"); compilerOptionsResetCompilerMenuItem.setMnemonic('R'); compilerOptionsResetCompilerMenuItem.addActionListener(eventHandler); } return compilerOptionsResetCompilerMenuItem; } private JMenuItem getFileExitMenuItem() { if (fileExitMenuItem == null) { fileExitMenuItem = new JMenuItem(); fileExitMenuItem.setText("Exit"); fileExitMenuItem.setMnemonic('x'); fileExitMenuItem.setDisplayedMnemonicIndex(1); fileExitMenuItem.addActionListener(eventHandler); } return fileExitMenuItem; } private JMenu getFileMenu() { if (fileMenu == null) { fileMenu = new JMenu(); fileMenu.setText("File"); fileMenu.setMnemonic('F'); fileMenu.add(getFileNewMenu()); fileMenu.add(getFileOpenMenuItem()); fileMenu.add(getFileExtractMenuItem()); fileMenu.add(getFileSaveMenuItem()); fileMenu.add(getFileSaveAsMenuItem()); fileMenu.add(new JSeparator()); fileMenu.add(getFileExitMenuItem()); } return fileMenu; } private JMenuItem getFileNewJavaFileMenuItem() { if (fileNewJavaFileMenuItem == null) { fileNewJavaFileMenuItem = new JMenuItem(); fileNewJavaFileMenuItem.setText("Java File"); fileNewJavaFileMenuItem.setMnemonic('J'); fileNewJavaFileMenuItem.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_N, MENU_SHORTCUT_KEY_MASK | Event.SHIFT_MASK)); fileNewJavaFileMenuItem.addActionListener(eventHandler); } return fileNewJavaFileMenuItem; } private JMenu getFileNewMenu() { if (fileNewMenu == null) { fileNewMenu = new JMenu(); fileNewMenu.setText("New"); fileNewMenu.setMnemonic('N'); fileNewMenu.add(getFileNewRobotMenuItem()); fileNewMenu.add(getFileNewJavaFileMenuItem()); } return fileNewMenu; } private JMenuItem getFileNewRobotMenuItem() { if (fileNewRobotMenuItem == null) { fileNewRobotMenuItem = new JMenuItem(); fileNewRobotMenuItem.setText("Robot"); fileNewRobotMenuItem.setMnemonic('R'); fileNewRobotMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, MENU_SHORTCUT_KEY_MASK)); fileNewRobotMenuItem.addActionListener(eventHandler); } return fileNewRobotMenuItem; } private JMenuItem getFileOpenMenuItem() { if (fileOpenMenuItem == null) { fileOpenMenuItem = new JMenuItem(); fileOpenMenuItem.setText("Open"); fileOpenMenuItem.setMnemonic('O'); fileOpenMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, MENU_SHORTCUT_KEY_MASK)); fileOpenMenuItem.addActionListener(eventHandler); } return fileOpenMenuItem; } private JMenuItem getFileExtractMenuItem() { if (fileExtractMenuItem == null) { fileExtractMenuItem = new JMenuItem(); fileExtractMenuItem.setText("Extract downloaded robot for editing"); fileExtractMenuItem.setMnemonic('t'); fileExtractMenuItem.setDisplayedMnemonicIndex(2); fileExtractMenuItem.addActionListener(eventHandler); } return fileExtractMenuItem; } public JMenuItem getFileSaveAsMenuItem() { if (fileSaveAsMenuItem == null) { fileSaveAsMenuItem = new JMenuItem(); fileSaveAsMenuItem.setText("Save As"); fileSaveAsMenuItem.setMnemonic('A'); fileSaveAsMenuItem.setDisplayedMnemonicIndex(5); fileSaveAsMenuItem.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_S, MENU_SHORTCUT_KEY_MASK | Event.SHIFT_MASK)); fileSaveAsMenuItem.addActionListener(eventHandler); fileSaveAsMenuItem.setEnabled(false); } return fileSaveAsMenuItem; } public JMenuItem getFileSaveMenuItem() { if (fileSaveMenuItem == null) { fileSaveMenuItem = new JMenuItem(); fileSaveMenuItem.setText("Save"); fileSaveMenuItem.setMnemonic('S'); fileSaveMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, MENU_SHORTCUT_KEY_MASK)); fileSaveMenuItem.addActionListener(eventHandler); fileSaveMenuItem.setEnabled(false); } return fileSaveMenuItem; } @Override public JMenu getHelpMenu() { if (helpMenu == null) { helpMenu = new JMenu(); helpMenu.setText("Help"); helpMenu.setMnemonic('H'); helpMenu.add(getHelpRobocodeApiMenuItem()); } return helpMenu; } private JMenuItem getHelpRobocodeApiMenuItem() { if (helpRobocodeApiMenuItem == null) { helpRobocodeApiMenuItem = new JMenuItem(); helpRobocodeApiMenuItem.setText("Robocode API"); helpRobocodeApiMenuItem.setMnemonic('A'); helpRobocodeApiMenuItem.setDisplayedMnemonicIndex(9); helpRobocodeApiMenuItem.addActionListener(eventHandler); } return helpRobocodeApiMenuItem; } private JMenu getEditMenu() { if (editMenu == null) { editMenu = new JMenu(); editMenu.setText("Edit"); editMenu.setMnemonic('E'); editMenu.add(getEditUndoMenuItem()); editMenu.add(getEditRedoMenuItem()); editMenu.addSeparator(); editMenu.add(getEditCutMenuItem()); editMenu.add(getEditCopyMenuItem()); editMenu.add(getEditPasteMenuItem()); editMenu.add(getEditDeleteMenuItem()); editMenu.addSeparator(); editMenu.add(getEditFindMenuItem()); editMenu.add(getEditFindNextMenuItem()); editMenu.add(getEditReplaceMenuItem()); editMenu.addSeparator(); editMenu.add(getEditSelectAllMenuItem()); } return editMenu; } private JMenuItem getEditUndoMenuItem() { if (editUndoMenuItem == null) { editUndoMenuItem = new JMenuItem(); editUndoMenuItem.setText("Undo"); editUndoMenuItem.setMnemonic('U'); editUndoMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, MENU_SHORTCUT_KEY_MASK)); editUndoMenuItem.addActionListener(eventHandler); } return editUndoMenuItem; } private JMenuItem getEditRedoMenuItem() { if (editRedoMenuItem == null) { editRedoMenuItem = new JMenuItem(); editRedoMenuItem.setText("Redo"); editRedoMenuItem.setMnemonic('R'); editRedoMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y, MENU_SHORTCUT_KEY_MASK)); editRedoMenuItem.addActionListener(eventHandler); } return editRedoMenuItem; } private JMenuItem getEditCutMenuItem() { if (editCutMenuItem == null) { editCutMenuItem = new JMenuItem(); editCutMenuItem.setText("Cut"); editCutMenuItem.setMnemonic('t'); editCutMenuItem.setDisplayedMnemonicIndex(2); editCutMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, MENU_SHORTCUT_KEY_MASK)); editCutMenuItem.addActionListener(eventHandler); } return editCutMenuItem; } private JMenuItem getEditCopyMenuItem() { if (editCopyMenuItem == null) { editCopyMenuItem = new JMenuItem(); editCopyMenuItem.setText("Copy"); editCopyMenuItem.setMnemonic('C'); editCopyMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, MENU_SHORTCUT_KEY_MASK)); editCopyMenuItem.addActionListener(eventHandler); } return editCopyMenuItem; } private JMenuItem getEditPasteMenuItem() { if (editPasteMenuItem == null) { editPasteMenuItem = new JMenuItem(); editPasteMenuItem.setText("Paste"); editPasteMenuItem.setMnemonic('P'); editPasteMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, MENU_SHORTCUT_KEY_MASK)); editPasteMenuItem.addActionListener(eventHandler); } return editPasteMenuItem; } private JMenuItem getEditDeleteMenuItem() { if (editDeleteMenuItem == null) { editDeleteMenuItem = new JMenuItem(); editDeleteMenuItem.setText("Delete"); editDeleteMenuItem.setMnemonic('l'); editDeleteMenuItem.setDisplayedMnemonicIndex(2); editDeleteMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0)); editDeleteMenuItem.addActionListener(eventHandler); } return editDeleteMenuItem; } private JMenuItem getEditFindMenuItem() { if (editFindMenuItem == null) { editFindMenuItem = new JMenuItem(); editFindMenuItem.setText("Find..."); editFindMenuItem.setMnemonic('F'); editFindMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F, MENU_SHORTCUT_KEY_MASK)); editFindMenuItem.addActionListener(eventHandler); } return editFindMenuItem; } private JMenuItem getEditFindNextMenuItem() { if (editFindNextMenuItem == null) { editFindNextMenuItem = new JMenuItem(); editFindNextMenuItem.setText("Find Next"); editFindNextMenuItem.setMnemonic('N'); editFindNextMenuItem.setDisplayedMnemonicIndex(5); editFindNextMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_G, MENU_SHORTCUT_KEY_MASK)); editFindNextMenuItem.addActionListener(eventHandler); } return editFindNextMenuItem; } private JMenuItem getEditReplaceMenuItem() { if (editReplaceMenuItem == null) { editReplaceMenuItem = new JMenuItem(); editReplaceMenuItem.setText("Replace..."); editReplaceMenuItem.setMnemonic('R'); editReplaceMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_H, MENU_SHORTCUT_KEY_MASK)); editReplaceMenuItem.addActionListener(eventHandler); } return editReplaceMenuItem; } private JMenuItem getEditSelectAllMenuItem() { if (editSelectAllMenuItem == null) { editSelectAllMenuItem = new JMenuItem(); editSelectAllMenuItem.setText("Select All"); editSelectAllMenuItem.setMnemonic('A'); editSelectAllMenuItem.setDisplayedMnemonicIndex(7); editSelectAllMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, MENU_SHORTCUT_KEY_MASK)); editSelectAllMenuItem.addActionListener(eventHandler); } return editSelectAllMenuItem; } public JMenu getWindowMenu() { if (windowMenu == null) { windowMenu = new JMenu(); windowMenu.setText("Window"); windowMenu.setMnemonic('W'); // If you add more items to this menu, you need to update the // constants in WindowMenuItem, too, or the dynamic part of the // window menu won't operate correctly. windowMenu.add(getWindowCloseMenuItem()); windowMenu.add(getWindowCloseAllMenuItem()); windowMenu.addSeparator(); // stuff will be inserted here... windowMenu.add(getWindowWindowsDialogMenuItem()); } return windowMenu; } private JMenuItem getWindowCloseMenuItem() { if (windowCloseMenuItem == null) { windowCloseMenuItem = new JMenuItem(); windowCloseMenuItem.setText("Close"); windowCloseMenuItem.setMnemonic('C'); windowCloseMenuItem.addActionListener(eventHandler); } return windowCloseMenuItem; } private JMenuItem getWindowCloseAllMenuItem() { if (windowCloseAllMenuItem == null) { windowCloseAllMenuItem = new JMenuItem(); windowCloseAllMenuItem.setText("Close All"); windowCloseAllMenuItem.setMnemonic('A'); windowCloseAllMenuItem.setDisplayedMnemonicIndex(6); windowCloseAllMenuItem.addActionListener(eventHandler); } return windowCloseAllMenuItem; } private JMenuItem getWindowWindowsDialogMenuItem() { if (windowWindowsDialogMenuItem == null) { windowWindowsDialogMenuItem = new WindowMenuItem(); windowWindowsDialogMenuItem.addActionListener(eventHandler); } return windowWindowsDialogMenuItem; } public MoreWindowsDialog getMoreWindowsDialog() { if (moreWindowsDialog == null) { moreWindowsDialog = new MoreWindowsDialog(editor); } return moreWindowsDialog; } private void helpRobocodeApiActionPerformed() { editor.showHelpApi(); } private void initialize() { add(getFileMenu()); add(getEditMenu()); add(getCompilerMenu()); add(getWindowMenu()); add(getHelpMenu()); } } robocode/robocode/robocode/RobocodeFileWriter.java0000644000175000017500000000620411130241112021614 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Updated Javadocs *******************************************************************************/ package robocode; import java.io.File; import java.io.FileDescriptor; import java.io.IOException; /** * RobocodeFileWriter is similar to a {@link java.io.FileWriter} and is used for * writing data out to a file, which you got by calling {@link * AdvancedRobot#getDataFile(String) getDataFile()}. *

* You should read {@link java.io.FileWriter} for documentation of this class. *

* Please notice that the max. size of your data file is set to 200000 * (~195 KB). * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @see AdvancedRobot#getDataFile(String) * @see java.io.FileWriter */ public class RobocodeFileWriter extends java.io.OutputStreamWriter { /** * Constructs a new RobocodeFileWriter. * See {@link java.io.FileWriter#FileWriter(File)} for documentation about * this constructor. * * @param file the file to write to. * @throws java.io.IOException if an I/O exception occurs. * @see java.io.FileWriter#FileWriter(File) */ public RobocodeFileWriter(File file) throws IOException { super(new RobocodeFileOutputStream(file)); } /** * Constructs a new RobocodeFileWriter. * See {@link java.io.FileWriter#FileWriter(FileDescriptor)} for * documentation about this constructor. * * @param fd the file descriptor of the file to write to. * @see java.io.FileWriter#FileWriter(FileDescriptor) */ public RobocodeFileWriter(FileDescriptor fd) { super(new RobocodeFileOutputStream(fd)); } /** * Constructs a new RobocodeFileWriter. * See {@link java.io.FileWriter#FileWriter(String)} for documentation about * this constructor. * * @param fileName the filename of the file to write to. * @throws java.io.IOException if an I/O exception occurs. * @see java.io.FileWriter#FileWriter(String) */ public RobocodeFileWriter(String fileName) throws IOException { super(new RobocodeFileOutputStream(fileName)); } /** * Constructs a new RobocodeFileWriter. * See {@link java.io.FileWriter#FileWriter(String, boolean)} for * documentation about this constructor. * * @param fileName the filename of the file to write to. * @param append set this to true if the output must be appended to the file. * @throws java.io.IOException if an I/O exception occurs. * @see java.io.FileWriter#FileWriter(String, boolean) */ public RobocodeFileWriter(String fileName, boolean append) throws IOException { super(new RobocodeFileOutputStream(fileName, append)); } } robocode/robocode/robocode/HitWallEvent.java0000644000175000017500000000502411130241112020430 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Updated Javadocs *******************************************************************************/ package robocode; import robocode.peer.RobotStatics; import robocode.robotinterfaces.IBasicEvents; import robocode.robotinterfaces.IBasicRobot; import java.awt.*; /** * A HitWallEvent is sent to {@link Robot#onHitWall(HitWallEvent) onHitWall()} * when you collide a wall. * You can use the information contained in this event to determine what to do. * * @author Mathew A. Nelson (original) */ public final class HitWallEvent extends Event { private static final long serialVersionUID = 1L; private final static int DEFAULT_PRIORITY = 30; private final double bearing; /** * Called by the game to create a new HitWallEvent. * * @param bearing the bearing to the wall that your robot hit, in radians */ public HitWallEvent(double bearing) { this.bearing = bearing; } /** * Returns the bearing to the wall you hit, relative to your robot's * heading, in degrees (-180 <= getBearing() < 180) * * @return the bearing to the wall you hit, in degrees */ public double getBearing() { return bearing * 180.0 / Math.PI; } /** * @return the bearing to the wall you hit, in degrees * @deprecated Use {@link #getBearing()} instead. */ @Deprecated public double getBearingDegrees() { return getBearing(); } /** * Returns the bearing to the wall you hit, relative to your robot's * heading, in radians (-PI <= getBearingRadians() < PI) * * @return the bearing to the wall you hit, in radians */ public double getBearingRadians() { return bearing; } /** * {@inheritDoc} */ @Override final int getDefaultPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override final void dispatch(IBasicRobot robot, RobotStatics statics, Graphics2D graphics) { IBasicEvents listener = robot.getBasicEventListener(); if (listener != null) { listener.onHitWall(this); } } } robocode/robocode/robocode/Droid.java0000644000175000017500000000165511130241112017131 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew Nelson * - Initial API and implementation * Flemming N. Larsen * - Updated Javadocs *******************************************************************************/ package robocode; /** * Robots that implement Droid have no scanner, but an extra 20 life/energy. * This class is intended for use in teams. * * @author Mathew A. Nelson (original) * @see JuniorRobot * @see Robot * @see AdvancedRobot * @see TeamRobot */ public interface Droid {} robocode/robocode/robocode/io/0000755000175000017500000000000011124142706015641 5ustar lambylambyrobocode/robocode/robocode/io/Logger.java0000644000175000017500000000577311130241112017723 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Initial implementation based on methods from robocode.util.Utils, which * has been moved to this class *******************************************************************************/ package robocode.io; import robocode.control.events.BattleErrorEvent; import robocode.control.events.BattleMessageEvent; import robocode.control.events.IBattleListener; import robocode.security.RobocodeSecurityManager; import robocode.security.SecurePrintStream; import java.io.ByteArrayOutputStream; import java.io.PrintStream; /** * This is a class used for logging. * * @author Flemming N. Larsen (original) * @author Mathew A. Nelson (original) */ public class Logger { private static IBattleListener logListener; private final static StringBuffer logBuffer = new StringBuffer(); public static void setLogListener(IBattleListener logListener) { Logger.logListener = logListener; } public static void logMessage(String s) { logMessage(s, true); } public static void logMessage(Throwable e) { logMessage(toStackTraceString(e)); } public static void logMessage(String message, Throwable t) { logMessage(message + ":\n" + toStackTraceString(t)); } public static void logError(String message, Throwable t) { logError(message + ":\n" + toStackTraceString(t)); } public static void logError(Throwable t) { logError(toStackTraceString(t)); } public static void logMessage(String s, boolean newline) { if (logListener == null) { if (newline) { SecurePrintStream.realOut.println(s); } else { SecurePrintStream.realOut.print(s); SecurePrintStream.realOut.flush(); } } else { synchronized (logBuffer) { if (!RobocodeSecurityManager.isSafeThreadSt()) { // we just queue it, to not let unsafe thread travel thru system logBuffer.append(s); logBuffer.append("\n"); } else if (newline) { logListener.onBattleMessage(new BattleMessageEvent(logBuffer + s)); logBuffer.setLength(0); } else { logBuffer.append(s); } } } } public static void logError(String s) { if (logListener == null) { SecurePrintStream.realErr.println(s); } else { logListener.onBattleError(new BattleErrorEvent(s)); } } private static String toStackTraceString(Throwable t) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream ps = new PrintStream(baos); t.printStackTrace(ps); ps.close(); return baos.toString(); } } robocode/robocode/robocode/io/TeamMessageSizer.java0000644000175000017500000000244211130241112021702 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - MAX was turned into a constant called MAX_SIZE *******************************************************************************/ package robocode.io; import java.io.IOException; import java.io.OutputStream; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ public class TeamMessageSizer extends OutputStream { private final static long MAX_SIZE = 32768; private long count = 0; @Override public synchronized void write(int b) throws IOException { count++; if (count > MAX_SIZE) { throw new IOException("You have exceeded " + MAX_SIZE + " bytes this turn."); } } public synchronized void resetCount() { count = 0; } public synchronized long getCount() { return count; } } robocode/robocode/robocode/io/BufferedPipedOutputStream.java0000644000175000017500000001062411130241112023574 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup * - Bugfix: Changed the if-statement of "if (readIndex == writeIndex)" in * the read() method to a while-statement in order to correct text-output * bug, where old text or odd characters were printed out * - The setReadIndexToNextLine() has been embedded into the write(int b) * method *******************************************************************************/ package robocode.io; import java.io.IOException; import java.io.OutputStream; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ public class BufferedPipedOutputStream extends OutputStream { private final Object monitor = new Object(); private final byte[] buf; private volatile int readIndex; private volatile int writeIndex; private volatile boolean waiting; private volatile boolean closed; private BufferedPipedInputStream in; private final boolean skipLines; public BufferedPipedOutputStream(int bufferSize, boolean skipLines) { this.buf = new byte[bufferSize]; this.skipLines = skipLines; } /* * @see OutputStream#write(int) */ @Override public void write(int b) throws IOException { synchronized (monitor) { if (closed) { throw new IOException("Stream is closed."); } buf[writeIndex++] = (byte) (b & 0xff); if (writeIndex == buf.length) { writeIndex = 0; } if (writeIndex == readIndex) { // skipping a line! if (skipLines) { boolean writeIndexReached = false; while (buf[readIndex] != '\n') { readIndex++; if (readIndex == buf.length) { readIndex = 0; } if (readIndex == writeIndex) { writeIndexReached = true; } } if (!writeIndexReached) { readIndex++; if (readIndex == buf.length) { readIndex = 0; } } } else { throw new IOException("Buffer is full."); } } if (waiting) { monitor.notifyAll(); } } } protected int read() throws IOException { synchronized (monitor) { while (readIndex == writeIndex) { waiting = true; try { if (!closed) { monitor.wait(10000); } if (closed) { return -1; } } catch (InterruptedException e) { // Immediately reasserts the exception by interrupting the caller thread itself Thread.currentThread().interrupt(); IOException ioException = new IOException("read interrupted"); ioException.initCause(e); throw ioException; } } int result = buf[readIndex++]; if (readIndex == buf.length) { readIndex = 0; } return result; } } public int read(byte b[], int off, int len) throws IOException { if (b == null) { throw new NullPointerException(); } else if (off < 0 || len < 0 || off >= b.length || (off + len) > b.length) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return 0; } int first = read(); if (first == -1) { return -1; } b[off] = (byte) (first & 0xff); int count = 1; synchronized (monitor) { for (int i = 1; readIndex != writeIndex && i < len; i++) { b[off + i] = buf[readIndex++]; count++; if (readIndex == buf.length) { readIndex = 0; } } } return count; } protected int available() { synchronized (monitor) { if (writeIndex == readIndex) { return 0; } else if (writeIndex > readIndex) { return writeIndex - readIndex; } else { return buf.length - readIndex + writeIndex; } } } public BufferedPipedInputStream getInputStream() { synchronized (monitor) { if (in == null) { in = new BufferedPipedInputStream(this); } return in; } } @Override public void close() { synchronized (monitor) { closed = true; if (waiting) { monitor.notifyAll(); } } } } robocode/robocode/robocode/io/FileTypeFilter.java0000644000175000017500000000433111130241112021360 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Moved the original robocode.util.RobocodeFileFilter into this new class * and added javadoc comments * - Changed the constructor to make a deep copy of the file types *******************************************************************************/ package robocode.io; import java.io.File; import java.io.FileFilter; /** * A filter for filtering out files in a file list based on file extensions. * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ public class FileTypeFilter implements FileFilter { // Array of file types private final String[] fileTypes; /** * Creates a new file type filter. * * @param fileTypes an array of file extensions that is accepted for this * file filter, e.g. ".class", ".jar", ".zip" etc. */ public FileTypeFilter(String[] fileTypes) { super(); if (fileTypes == null) { this.fileTypes = null; } else { this.fileTypes = new String[fileTypes.length]; System.arraycopy(fileTypes, 0, this.fileTypes, 0, fileTypes.length); } } /** * Tests if a specified file should be included in a file list. * * @param file the file that must be tested against this file filter. * @return {@code true} if the file is accepted for the file list; * {@code false} otherwise. */ public boolean accept(File file) { if (file.isDirectory()) { return true; } String filename = file.getName(); for (String fileType : fileTypes) { if (filename.length() > fileType.length()) { if (filename.substring(filename.length() - fileType.length()).equals(fileType)) { return true; } } } return false; } } robocode/robocode/robocode/io/RobocodeObjectInputStream.java0000644000175000017500000000265611130241112023560 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Ported to Java 5.0 *******************************************************************************/ package robocode.io; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectStreamClass; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ public class RobocodeObjectInputStream extends ObjectInputStream { private ClassLoader classLoader; public RobocodeObjectInputStream(InputStream in, ClassLoader classLoader) throws IOException { super(in); this.classLoader = classLoader; } @Override protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { String name = desc.getName(); try { return Class.forName(name, false, classLoader); } catch (ClassNotFoundException ex) { return super.resolveClass(desc); } } } robocode/robocode/robocode/io/NoDuplicateJarOutputStream.java0000644000175000017500000000373111130241112023735 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Ported to Java 5.0 * - Moved this class from the robocode.util package into the robocode.io * package * - Removed useless closeEntry() which was only calling the closeEntry() at * the super class * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap *******************************************************************************/ package robocode.io; import java.io.IOException; import java.io.OutputStream; import java.util.HashMap; import java.util.Map; import java.util.jar.JarOutputStream; import java.util.jar.Manifest; import java.util.zip.ZipEntry; import java.util.zip.ZipException; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Robert D. Maupin (contributor) */ public class NoDuplicateJarOutputStream extends JarOutputStream { private final Map entries = new HashMap(); public NoDuplicateJarOutputStream(OutputStream out) throws IOException { super(out); } public NoDuplicateJarOutputStream(OutputStream out, Manifest man) throws IOException { super(out, man); } @Override public void putNextEntry(ZipEntry ze) throws IOException { if (entries.containsKey(ze.getName())) { throw new ZipException("duplicate entry: " + ze.getName()); } entries.put(ze.getName(), ""); super.putNextEntry(ze); } } robocode/robocode/robocode/io/FileUtil.java0000644000175000017500000001625211130241112020213 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Moved the former robocode.util.Constants and all file operations from * robocode.util.Utils into this new class * - Added/updated JavaDoc for all methods * - Added the quoteFileName(), createDir(), getRobotsDir(), getConfigDir(), * getRobocodeConfigFile(), getWindowConfigFile(), getCompilerConfigFile() *******************************************************************************/ package robocode.io; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; /** * This is a class for file utilization. * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ public class FileUtil { // Current working directory private static File cwd; // Initializes the current working directory static { try { FileUtil.setCwd(new File("")); } catch (IOException e) { e.printStackTrace(); } } /** * Returns the current working directory. * * @return a File for the current working directory */ public static File getCwd() { return cwd; } /** * Changes the current working directory. * * @param cwd a File that is the new working directory * @throws IOException if an I/O exception occurs */ public static void setCwd(File cwd) throws IOException { FileUtil.cwd = cwd.getCanonicalFile(); } /** * Returns the file type of a file, i.e. it's extension. * * @param file the file * @return the file type of the file, e.g. ".class", ".jar" or "" if the * file name does not contain an extension. */ public static String getFileType(File file) { return getFileType(file.getName()); } /** * Returns the file type of a file name, i.e. it's extension. * * @param fileName the file name * @return the file type of the file name, e.g. ".class", ".jar" or "" if * the file name does not contain an extension. */ public static String getFileType(String fileName) { int lastdot = fileName.lastIndexOf('.'); return (lastdot < 0) ? "" : fileName.substring(lastdot); } /** * Quotes a file name if it contains white spaces and has not already been * quoted. * * @param filename the file to quote * @return a quoted version of the specified filename */ public static String quoteFileName(String filename) { if (filename.startsWith("\"") || filename.endsWith("\"")) { return filename; } if (System.getProperty("os.name").toLowerCase().startsWith("windows") && filename.startsWith("file://")) { filename = filename.substring(7); } if (filename.matches(".*\\s+?.*")) { return '"' + filename + '"'; } return filename; } /** * Copies a file into another file. * * @param srcFile the input file to copy * @param destFile the output file to copy to * @throws IOException if an I/O exception occurs */ public static void copy(File srcFile, File destFile) throws IOException { if (srcFile.equals(destFile)) { throw new IOException("You cannot copy a file onto itself"); } byte buf[] = new byte[4096]; FileInputStream in = null; FileOutputStream out = null; try { in = new FileInputStream(srcFile); out = new FileOutputStream(destFile); while (in.available() > 0) { out.write(buf, 0, in.read(buf, 0, buf.length)); } } finally { if (in != null) { in.close(); } if (out != null) { out.close(); } } } /** * Deletes a directory. * * @param dir the file for the directory to delete */ public static boolean deleteDir(File dir) { if (dir.isDirectory()) { for (File file : dir.listFiles()) { if (file.isDirectory()) { try { // Test for symlink and ignore. // Robocode won't create one, but just in case a user does... if (file.getCanonicalFile().getParentFile().equals(dir.getCanonicalFile())) { deleteDir(file); file.delete(); } else { System.out.println("Warning: " + file + " may be a symlink. Ignoring."); } } catch (IOException e) { System.out.println("Warning: Cannot determine canonical file for " + file + " - ignoring."); } } else { file.delete(); } } return dir.delete(); } return false; } /** * Creates a directory if it does not exist already * * @param dir the File that represents the new directory to create. * @return the created directory */ public static File createDir(File dir) { if (dir != null && !dir.exists()) { dir.mkdir(); } return dir; } /** * Returns the class name of the specified filename. * * @param fileName the filename to extract the class name from * @return the class name of the specified filename */ public static String getClassName(String fileName) { int lastdot = fileName.lastIndexOf('.'); if (lastdot < 0) { return fileName; } if (fileName.length() - 1 == lastdot) { return fileName.substring(0, fileName.length() - 1); } return fileName.substring(0, lastdot); } /** * Returns the directory containing the robots. * * @return a File that is the directory containing the robots */ public static File getRobotsDir() { File file; String robotPath = System.getProperty("ROBOTPATH"); if (robotPath != null) { file = new File(robotPath); } else { file = new File(cwd, "/robots"); } return createDir(file); } /** * Returns the directory containing the battle files. * * @return a File that is the directory containing the battle files */ public static File getBattlesDir() { return createDir(new File(cwd, "/battles")); } /** * Returns the directory containing the configuration files. * If the directory does not exist, it will be created automatically. * * @return a File that is the directory containing configuration files */ public static File getConfigDir() { return createDir(new File(cwd, "/config")); } /** * Returns the Robocode configuration file. * * @return a File that is the Robocode configuration file. */ public static File getRobocodeConfigFile() { return new File(getConfigDir(), "robocode.properties"); } /** * Returns the window configuration file. * * @return a File that the window configuration file. */ public static File getWindowConfigFile() { return new File(getConfigDir(), "window.properties"); } /** * Returns the compiler configuration file. * * @return a File that the compiler configuration file. */ public static File getCompilerConfigFile() { return new File(getConfigDir(), "compiler.properties"); } } robocode/robocode/robocode/io/BufferedPipedInputStream.java0000644000175000017500000000226211130241112023372 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation *******************************************************************************/ package robocode.io; import java.io.IOException; import java.io.InputStream; /** * @author Mathew A. Nelson (original) */ public class BufferedPipedInputStream extends InputStream { private final BufferedPipedOutputStream out; protected BufferedPipedInputStream(BufferedPipedOutputStream out) { this.out = out; } @Override public int read() throws IOException { return out.read(); } @Override public int read(byte b[], int off, int len) throws IOException { return out.read(b, off, len); } @Override public int available() { return out.available(); } } robocode/robocode/robocode/MouseReleasedEvent.java0000644000175000017500000000413711130241112021625 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode; import robocode.peer.RobotStatics; import robocode.robotinterfaces.IBasicRobot; import robocode.robotinterfaces.IInteractiveEvents; import robocode.robotinterfaces.IInteractiveRobot; import java.awt.*; /** * A MouseReleasedEvent is sent to {@link Robot#onMouseReleased(java.awt.event.MouseEvent) * onMouseReleased()} when the mouse is released inside the battle view. * * @author Pavel Savara (original) * @see MouseClickedEvent * @see MousePressedEvent * @see MouseEnteredEvent * @see MouseExitedEvent * @see MouseMovedEvent * @see MouseDraggedEvent * @see MouseWheelMovedEvent * @since 1.6.1 */ public final class MouseReleasedEvent extends MouseEvent { private static final long serialVersionUID = 1L; private final static int DEFAULT_PRIORITY = 98; /** * Called by the game to create a new MouseReleasedEvent. * * @param source the source mouse event originating from the AWT. */ public MouseReleasedEvent(java.awt.event.MouseEvent source) { super(source); } /** * {@inheritDoc} */ @Override final int getDefaultPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override final void dispatch(IBasicRobot robot, RobotStatics statics, Graphics2D graphics) { if (statics.isInteractiveRobot()) { IInteractiveEvents listener = ((IInteractiveRobot) robot).getInteractiveEventListener(); if (listener != null) { listener.onMouseReleased(getSourceEvent()); } } } } robocode/robocode/robocode/Rules.java0000644000175000017500000001646411130241112017166 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen & Luis Crespo * - Initial API and implementation *******************************************************************************/ package robocode; import static java.lang.Math.abs; import static java.lang.Math.max; /** * Constants and methods that defines the rules of Robocode. * Constants are used for rules that will not change. * Methods are provided for rules that can be changed between battles or which depends * on some other factor. * * @author Luis Crespo (original) * @author Flemming N. Larsen (original) * @since 1.1.4 */ public final class Rules { // Hide the constructor in the Javadocs as it should not be used private Rules() {} /** * The acceleration of a robot, i.e. the increase of velocity when the * robot moves forward, which is 1 pixel/turn. */ public static final double ACCELERATION = 1; /** * The deceleration of a robot, i.e. the decrease of velocity when the * robot moves backwards (or brakes), which is 2 pixels/turn. */ public static final double DECELERATION = 2; /** * The maximum velocity of a robot, which is 8 pixels/turn. */ public static final double MAX_VELOCITY = 8; /** * The radar scan radius, which is 1200 pixels. * Robots which is more than 1200 pixels away cannot be seen on the radar. */ public static final double RADAR_SCAN_RADIUS = 1200; /** * The minimum bullet power, i.e the amount of energy required for firing a * bullet, which is 0.1 energy points. */ public static final double MIN_BULLET_POWER = 0.1; /** * The maximum bullet power, i.e. the maximum amount of energy that can be * transferred to a bullet when it is fired, which is 3 energy points. */ public static final double MAX_BULLET_POWER = 3; /** * The maximum turning rate of the robot, in degrees, which is * 10 degress/turn. * Note, that the turn rate of the robot depends on it's velocity. * * @see #MAX_TURN_RATE_RADIANS * @see #getTurnRate(double) * @see #getTurnRateRadians(double) */ public static final double MAX_TURN_RATE = 10; /** * The maximum turning rate of the robot measured in radians instead of * degrees. * * @see #MAX_TURN_RATE * @see #getTurnRate(double) * @see #getTurnRateRadians(double) */ public static final double MAX_TURN_RATE_RADIANS = Math.toRadians(MAX_TURN_RATE); /** * The turning rate of the gun measured in degrees, which is * 20 degrees/turn. * Note, that if setAdjustGunForRobotTurn(true) has been called, the gun * turn is independent of the robot turn. * In this case the gun moves relatively to the screen. If * setAdjustGunForRobotTurn(false) has been called or * setAdjustGunForRobotTurn() has not been called at all (this is the * default), then the gun turn is dependent on the robot turn, and in this * case the gun moves relatively to the robot body. * * @see #GUN_TURN_RATE_RADIANS * @see Robot#setAdjustGunForRobotTurn(boolean) */ public static final double GUN_TURN_RATE = 20; /** * The turning rate of the gun measured in radians instead of degrees. * * @see #GUN_TURN_RATE */ public static final double GUN_TURN_RATE_RADIANS = Math.toRadians(GUN_TURN_RATE); /** * The turning rate of the radar measured in degrees, which is * 45 degrees/turn. * Note, that if setAdjustRadarForRobotTurn(true) and/or * setAdjustRadarForGunTurn(true) has been called, the radar turn is * independent of the robot and/or gun turn. If both methods has been set to * true, the radar moves relatively to the screen. * If setAdjustRadarForRobotTurn(false) and/or setAdjustRadarForGunTurn(false) * has been called or not called at all (this is the default), then the * radar turn is dependent on the robot and/or gun turn, and in this case * the radar moves relatively to the gun and/or robot body. * * @see #RADAR_TURN_RATE_RADIANS * @see Robot#setAdjustGunForRobotTurn(boolean) * @see Robot#setAdjustRadarForGunTurn(boolean) */ public static final double RADAR_TURN_RATE = 45; /** * The turning rate of the radar measured in radians instead of degrees. * * @see #RADAR_TURN_RATE */ public static final double RADAR_TURN_RATE_RADIANS = Math.toRadians(RADAR_TURN_RATE); /** * The amount of damage taken when a robot hits or is hit by another robot, * which is 0.6 energy points. */ public static final double ROBOT_HIT_DAMAGE = 0.6; /** * The amount of bonus given when a robot moving forward hits an opponent * robot (ramming), which is 1.2 energy points. */ public static final double ROBOT_HIT_BONUS = 1.2; /** * Returns the turn rate of a robot given a specific velocity measured in * degrees/turn. * * @param velocity the velocity of the robot. * @return turn rate in degrees/turn. * @see #getTurnRateRadians(double) */ public static double getTurnRate(double velocity) { return MAX_TURN_RATE - 0.75 * velocity; } /** * Returns the turn rate of a robot given a specific velocity measured in * radians/turn. * * @param velocity the velocity of the robot. * @return turn rate in radians/turn. * @see #getTurnRate(double) */ public static double getTurnRateRadians(double velocity) { return Math.toRadians(getTurnRate(velocity)); } /** * Returns the amount of damage taken when robot hits a wall with a * specific velocity. * * @param velocity the velocity of the robot. * @return wall hit damage in energy points. */ public static double getWallHitDamage(double velocity) { return max(abs(velocity) / 2 - 1, 0); } /** * Returns the amount of damage of a bullet given a specific bullet power. * * @param bulletPower the energy power of the bullet. * @return bullet damage in energy points. */ public static double getBulletDamage(double bulletPower) { double damage = 4 * bulletPower; if (bulletPower > 1) { damage += 2 * (bulletPower - 1); } return damage; } /** * Returns the amount of bonus given when a robot's bullet hits an opponent * robot given a specific bullet power. * * @param bulletPower the energy power of the bullet. * @return bullet hit bonus in energy points. */ public static double getBulletHitBonus(double bulletPower) { return 3 * bulletPower; } /** * Returns the speed of a bullet given a specific bullet power measured in * pixels/turn * * @param bulletPower the energy power of the bullet. * @return bullet speed in pixels/turn */ public static double getBulletSpeed(double bulletPower) { return 20 - 3 * bulletPower; } /** * Returns the heat produced by firing the gun given a specific bullet * power. * * @param bulletPower the energy power of the bullet. * @return gun heat */ public static double getGunHeat(double bulletPower) { return 1 + (bulletPower / 5); } } robocode/robocode/robocode/GunTurnCompleteCondition.java0000644000175000017500000000453511130241112023032 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Updated Javadocs * Nathaniel Troutman * - Added cleanup() method for cleaning up references to internal classes * to prevent circular references causing memory leaks *******************************************************************************/ package robocode; /** * A prebuilt condition you can use that indicates your gun has finished * turning. * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Nathaniel Troutman (contributor) * @see Condition */ public class GunTurnCompleteCondition extends Condition { private AdvancedRobot robot = null; /** * Creates a new GunTurnCompleteCondition with default priority. * The default priority is 80. * * @param robot your robot, which must be a {@link AdvancedRobot} */ public GunTurnCompleteCondition(AdvancedRobot robot) { super(); this.robot = robot; } /** * Creates a new GunTurnCompleteCondition with a specific priority. * A condition priority is a value from 0 - 99. The higher value, the * higher priority. The default priority is 80. * * @param robot your robot, which must be a {@link AdvancedRobot} * @param priority the priority of this condition * @see Condition#setPriority(int) */ public GunTurnCompleteCondition(AdvancedRobot robot, int priority) { super(); this.robot = robot; this.priority = priority; } /** * Tests if the gun has stopped turning. * * @return {@code true} if the gun has stopped turning; {@code false} * otherwise */ @Override public boolean test() { return (robot.getGunTurnRemaining() == 0); } /** * Called by the system in order to clean up references to internal objects. * * @since 1.4.3 */ @Override public final void cleanup() { robot = null; } } robocode/robocode/robocode/ui/0000755000175000017500000000000011124143452015646 5ustar lambylambyrobocode/robocode/robocode/ui/ShortcutUtil.java0000644000175000017500000000345611130241112021157 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen * - Initial implementation *******************************************************************************/ package robocode.ui; import java.awt.*; import java.awt.event.InputEvent; /** * Utility for handling shortcut keys. * * @author Flemming N. Larsen */ public class ShortcutUtil { /** * The menu shortcut key mask. */ public final static int MENU_SHORTCUT_KEY_MASK = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); /** * Returns the text for the shortcut modifier key. * * @return the text for the shortcut modifier key. */ public static String getModifierKeyText() { boolean isMac = (System.getProperty("os.name").startsWith("Mac")); String text = ""; if ((MENU_SHORTCUT_KEY_MASK & InputEvent.SHIFT_MASK) == InputEvent.SHIFT_MASK) { text = "Shift"; } if ((MENU_SHORTCUT_KEY_MASK & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK) { if (text.length() > 0) { text += '+'; } text = "Ctrl"; } if ((MENU_SHORTCUT_KEY_MASK & InputEvent.ALT_MASK) == InputEvent.ALT_MASK) { if (text.length() > 0) { text += '+'; } text = isMac ? "Opt" : "Alt"; } if ((MENU_SHORTCUT_KEY_MASK & InputEvent.META_MASK) == InputEvent.META_MASK) { if (text.length() > 0) { text += '+'; } text = isMac ? "Cmd" : "Meta"; } return text; } } robocode/robocode/robocode/ui/AwtBattleAdaptor.java0000644000175000017500000002036011130241112021701 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.ui; import robocode.battle.events.BattleEventDispatcher; import robocode.battle.snapshot.RobotSnapshot; import robocode.control.events.*; import robocode.control.snapshot.IRobotSnapshot; import robocode.control.snapshot.ITurnSnapshot; import robocode.io.Logger; import robocode.manager.IBattleManager; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; /** * @author Pavel Savara (original) */ public final class AwtBattleAdaptor extends BattleAdaptor { private final IBattleManager battleManager; private final BattleEventDispatcher battleEventDispatcher = new BattleEventDispatcher(); private final BattleObserver observer; private final Timer timerTask; private final AtomicReference snapshot; private final AtomicBoolean isRunning; private final AtomicBoolean isPaused; private StringBuilder[] outCache; public AwtBattleAdaptor(IBattleManager battleManager, int maxFps, boolean skipSameFrames) { this.battleManager = battleManager; snapshot = new AtomicReference(null); this.skipSameFrames = skipSameFrames; timerTask = new Timer(1000 / maxFps, new TimerTask()); isRunning = new AtomicBoolean(false); isPaused = new AtomicBoolean(false); observer = new BattleObserver(); battleManager.addListener(observer); battleEventDispatcher.addListener(this); } protected void finalize() throws Throwable { try { timerTask.stop(); battleManager.removeListener(observer); battleEventDispatcher.removeListener(this); } finally { super.finalize(); } } public synchronized void addListener(IBattleListener listener) { battleEventDispatcher.addListener(listener); } public synchronized void removeListener(IBattleListener listener) { battleEventDispatcher.removeListener(listener); } @Override public void onBattleStarted(BattleStartedEvent event) { repaintTask(true, false); timerTask.start(); } @Override public void onBattleFinished(BattleFinishedEvent event) { timerTask.stop(); repaintTask(true, true); } @Override public void onBattleResumed(BattleResumedEvent event) { if (isRunning.get()) { timerTask.start(); } } @Override public void onBattlePaused(BattlePausedEvent event) { timerTask.stop(); } @Override public void onRoundStarted(RoundStartedEvent event) { repaintTask(true, false); } @Override public void onRoundEnded(RoundEndedEvent event) { repaintTask(true, true); } public ITurnSnapshot getLastSnapshot() { return lastSnapshot; } private ITurnSnapshot lastSnapshot; private void repaintTask(boolean forceRepaint, boolean readoutText) { try { ITurnSnapshot current = snapshot.get(); if (!isRunning.get() || current == null) { lastSnapshot = null; battleEventDispatcher.onTurnEnded(new TurnEndedEvent(null)); } else { if (lastSnapshot != current || !skipSameFrames || forceRepaint) { lastSnapshot = current; if (readoutText) { synchronized (snapshot) { IRobotSnapshot[] robots = lastSnapshot.getRobots(); for (int i = 0; i < robots.length; i++) { RobotSnapshot robot = (RobotSnapshot) robots[i]; robot.updateOutputStreamSnapshot(outCache[i].toString()); outCache[i].setLength(0); } } } battleEventDispatcher.onTurnEnded(new TurnEndedEvent(lastSnapshot)); calculateFPS(); } } } catch (Throwable t) { Logger.logError(t); } } public int getFPS() { return fps; } // FPS (frames per second) calculation private int fps; private long measuredFrameCounter; private long measuredFrameStartTime; private final boolean skipSameFrames; private void calculateFPS() { // Calculate the current frames per second (FPS) if (measuredFrameCounter++ == 0) { measuredFrameStartTime = System.nanoTime(); } long deltaTime = System.nanoTime() - measuredFrameStartTime; if (deltaTime / 1000000000 >= 1) { fps = (int) (measuredFrameCounter * 1000000000L / deltaTime); measuredFrameCounter = 0; } } private class TimerTask implements ActionListener { public void actionPerformed(ActionEvent e) { repaintTask(false, true); } } private class BattleObserver extends BattleAdaptor { @Override public void onTurnEnded(final TurnEndedEvent event) { snapshot.set(event.getTurnSnapshot()); final IRobotSnapshot[] robots = event.getTurnSnapshot().getRobots(); synchronized (snapshot) { for (int i = 0; i < robots.length; i++) { IRobotSnapshot robot = robots[i]; if (robot.getOutputStreamSnapshot() != null && robot.getOutputStreamSnapshot().length() != 0) { outCache[i].append(robot.getOutputStreamSnapshot()); } } } if (isPaused.get()) { EventQueue.invokeLater(new Runnable() { public void run() { battleEventDispatcher.onTurnEnded(event); } }); } } @Override public void onRoundStarted(final RoundStartedEvent event) { snapshot.set(event.getStartSnapshot()); EventQueue.invokeLater(new Runnable() { public void run() { battleEventDispatcher.onRoundStarted(event); } }); } @Override public void onBattleStarted(final BattleStartedEvent event) { isRunning.set(true); isPaused.set(false); snapshot.set(null); synchronized (snapshot) { outCache = new StringBuilder[event.getRobotsCount()]; for (int i = 0; i < event.getRobotsCount(); i++) { outCache[i] = new StringBuilder(1024); } } EventQueue.invokeLater(new Runnable() { public void run() { battleEventDispatcher.onBattleStarted(event); } }); } @Override public void onBattleFinished(final BattleFinishedEvent event) { isRunning.set(false); isPaused.set(false); snapshot.set(null); EventQueue.invokeLater(new Runnable() { public void run() { battleEventDispatcher.onBattleFinished(event); } }); } @Override public void onBattleCompleted(final BattleCompletedEvent event) { EventQueue.invokeLater(new Runnable() { public void run() { battleEventDispatcher.onBattleCompleted(event); } }); } @Override public void onBattlePaused(final BattlePausedEvent event) { isPaused.set(true); EventQueue.invokeLater(new Runnable() { public void run() { battleEventDispatcher.onBattlePaused(event); } }); } @Override public void onBattleResumed(final BattleResumedEvent event) { isPaused.set(false); EventQueue.invokeLater(new Runnable() { public void run() { battleEventDispatcher.onBattleResumed(event); } }); } @Override public void onRoundEnded(final RoundEndedEvent event) { EventQueue.invokeLater(new Runnable() { public void run() { battleEventDispatcher.onRoundEnded(event); } }); } @Override public void onTurnStarted(final TurnStartedEvent event) { EventQueue.invokeLater(new Runnable() { public void run() { battleEventDispatcher.onTurnStarted(event); } }); } @Override public void onBattleMessage(final BattleMessageEvent event) { EventQueue.invokeLater(new Runnable() { public void run() { battleEventDispatcher.onBattleMessage(event); } }); } @Override public void onBattleError(final BattleErrorEvent event) { EventQueue.invokeLater(new Runnable() { public void run() { battleEventDispatcher.onBattleError(event); } }); } } } robocode/robocode/robocode/ui/BattleResultsTableModel.java0000644000175000017500000001364611130241112023236 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Replaced ContestantPeerVector with plain Vector * - Added Rank column * - Ported to Java 5 * - Optimized * - Code cleanup * - Updated to use methods from the Logger and StringUtil, which * replaces methods that have been (re)moved from the robocode.util.Utils * - Changed the column names to be more informative and equal in width * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap * Nathaniel Troutman * - Added sanity check on battle object in getRowCount() * Endre Palatinus, Eniko Nagy, Attila Csizofszki and Laszlo Vigh * - Score with % (percentage) in the table view *******************************************************************************/ package robocode.ui; import robocode.BattleResults; import robocode.io.Logger; import robocode.text.StringUtil; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; import java.text.DateFormat; import java.text.NumberFormat; import java.util.Date; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Robert D. Maupin (contributor) * @author Nathaniel Troutman (contributor) * @author Endre Palatinus, Eniko Nagy, Attila Csizofszki and Laszlo Vigh (contributors) */ @SuppressWarnings("serial") public class BattleResultsTableModel extends javax.swing.table.AbstractTableModel { private String title; private final BattleResults[] results; private final int numRounds; // The sum of the scores gathered by the robots. private final double totalScore; public BattleResultsTableModel(BattleResults[] results, int numRounds) { this.results = results; this.numRounds = numRounds; totalScore = countTotalScore(); } /** * Function for counting the sum of the scores gathered by the robots. * * @return The sum. */ private double countTotalScore() { double totalScore = 0; for (BattleResults result : results) { totalScore += result.getScore(); } return totalScore; } public int getColumnCount() { return 12; } @Override public String getColumnName(int col) { switch (col) { case 0: return "Rank"; case 1: return "Robot Name"; case 2: return " Total Score "; case 3: return "Survival"; case 4: return "Surv Bonus"; case 5: return "Bullet Dmg"; case 6: return "Bullet Bonus"; case 7: return "Ram Dmg * 2"; case 8: return "Ram Bonus"; case 9: return " 1sts "; case 10: return " 2nds "; case 11: return " 3rds "; default: return ""; } } public int getRowCount() { return results.length; } public String getTitle() { if (title == null) { int round = numRounds; title = "Results for " + round + " round"; if (round > 1) { title += 's'; } } return title; } public Object getValueAt(int row, int col) { BattleResults statistics = results[row]; switch (col) { case 0: { int place = row + 1; while (place < getRowCount() && statistics.getScore() == results[place].getScore()) { place++; } return StringUtil.getPlacementString(place); } case 1: return statistics.getTeamLeaderName(); case 2: String percent = ""; if (totalScore != 0) { percent = " (" + NumberFormat.getPercentInstance().format(statistics.getScore() / totalScore) + ")"; } return "" + (int) (statistics.getScore() + 0.5) + percent; case 3: return "" + (int) (statistics.getSurvival() + 0.5); case 4: return "" + (int) (statistics.getLastSurvivorBonus() + 0.5); case 5: return "" + (int) (statistics.getBulletDamage() + 0.5); case 6: return "" + (int) (statistics.getBulletDamageBonus() + 0.5); case 7: return "" + (int) (statistics.getRamDamage() + 0.5); case 8: return "" + (int) (statistics.getRamDamageBonus() + 0.5); case 9: return "" + statistics.getFirsts(); case 10: return "" + statistics.getSeconds(); case 11: return "" + statistics.getThirds(); default: return ""; } } // Used for printing to the console only public void print(PrintStream out) { out.println(getTitle()); for (int col = 1; col < getColumnCount(); col++) { out.print(getColumnName(col) + "\t"); } out.println(); for (int row = 0; row < getRowCount(); row++) { out.print(getValueAt(row, 0) + ": "); for (int col = 1; col < getColumnCount(); col++) { out.print(getValueAt(row, col) + "\t"); } out.println(); } } public void saveToFile(String filename, boolean append) { try { PrintStream out = new PrintStream(new FileOutputStream(filename, append)); out.println(DateFormat.getDateTimeInstance().format(new Date())); out.println(getTitle()); for (int col = 0; col < getColumnCount(); col++) { if (col > 0) { out.print(','); } out.print(getColumnName(col)); } out.println(); for (int row = 0; row < getRowCount(); row++) { for (int col = 0; col < getColumnCount(); col++) { if (col > 0) { out.print(','); } out.print(getValueAt(row, col)); } out.println(); } out.println("$"); out.close(); } catch (IOException e) { Logger.logError(e); } } } robocode/robocode/robocode/ui/BattleRankingTableModel.java0000644000175000017500000001256411130241112023164 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Luis Crespo * - Initial API and implementation * Flemming N. Larsen * - Added independent Rank column * - Various optimizations * - Ported to Java 5 * - Updated to use the getPlacementString() methods from the StringUtil, * which replaces the same method from robocode.util.Utils * - Added additional scores, so that the rankings are similar to the battle * results * - Updated to contain both current and total scores in the columns where it * makes sense * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap * Endre Palatinus, Eniko Nagy, Attila Csizofszki and Laszlo Vigh * - Score with % (percentage) in the table view *******************************************************************************/ package robocode.ui; import robocode.control.snapshot.IScoreSnapshot; import robocode.control.snapshot.ITurnSnapshot; import robocode.text.StringUtil; import javax.swing.table.AbstractTableModel; /** * This table model extracts the robot ranking from the current battle, * in order to be displayed by the RankingDialog. * * @author Luis Crespo (original) * @author Flemming N. Larsen (contributor) * @author Robert D. Maupin (contributor) * @author Endre Palatinus, Eniko Nagy, Attila Csizofszki and Laszlo Vigh (contributors) */ @SuppressWarnings("serial") public class BattleRankingTableModel extends AbstractTableModel { IScoreSnapshot[] scoreSnapshotList; // The sum of the scores gathered by the robots in the actual round private double currentSum; // The sum of the scores gathered by the robots in the previous rounds private double totalSum; /** * Function for counting the sum of the scores gathered by the robots. */ private void countTotalScores() { currentSum = 0; totalSum = 0; for (IScoreSnapshot score : scoreSnapshotList) { currentSum += score.getCurrentScore(); totalSum += score.getTotalScore(); } } public void updateSource(ITurnSnapshot snapshot) { if (snapshot != null) { scoreSnapshotList = snapshot.getSortedTeamScores(); countTotalScores(); } else { scoreSnapshotList = null; } } public int getColumnCount() { return 12; } public int getRowCount() { return scoreSnapshotList == null ? 0 : scoreSnapshotList.length; } @Override public String getColumnName(int col) { switch (col) { case 0: return "Rank"; case 1: return "Robot Name"; case 2: return " Total Score "; case 3: return " Survival "; case 4: return "Surv Bonus"; case 5: return " Bullet Dmg "; case 6: return " Bullet Bonus "; case 7: return "Ram Dmg * 2"; case 8: return "Ram Bonus"; case 9: return " 1sts "; case 10: return " 2nds "; case 11: return " 3rds "; default: return ""; } } public Object getValueAt(int row, int col) { final IScoreSnapshot statistics = scoreSnapshotList[row]; switch (col) { case 0: return StringUtil.getPlacementString(row + 1); case 1: return statistics.getName(); case 2: { final double current = statistics.getCurrentScore(); final double total = statistics.getTotalScore(); return (int) (current + 0.5) + " / " + (int) (total + current + 0.5) + " (" + (int) (current / currentSum * 100) + " / " + (int) ((total + current) / (totalSum + currentSum) * 100) + "%)"; } case 3: { final double current = statistics.getCurrentSurvivalScore(); final double total = statistics.getTotalSurvivalScore(); return (int) (current + 0.5) + " / " + (int) (total + current + 0.5); } case 4: return (int) (statistics.getTotalLastSurvivorBonus() + 0.5); case 5: { final double current = statistics.getCurrentBulletDamageScore(); final double total = statistics.getTotalBulletDamageScore(); return (int) (current + 0.5) + " / " + (int) (total + current + 0.5); } case 6: { final double current = statistics.getCurrentBulletKillBonus(); final double total = statistics.getTotalBulletKillBonus(); return (int) (current + 0.5) + " / " + (int) (total + current + 0.5); } case 7: { final double current = statistics.getCurrentRammingDamageScore(); final double total = statistics.getTotalRammingDamageScore(); return (int) (current + 0.5) + " / " + (int) (total + current + 0.5); } case 8: { final double current = statistics.getCurrentRammingKillBonus(); final double total = statistics.getTotalRammingKillBonus(); return (int) (current + 0.5) + " / " + (int) (total + current + 0.5); } case 9: return "" + statistics.getTotalFirsts(); case 10: return "" + statistics.getTotalSeconds(); case 11: return "" + statistics.getTotalThirds(); default: return ""; } } } robocode/robocode/robocode/Bullet.java0000644000175000017500000001275011130241114017317 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Updated Javadocs *******************************************************************************/ package robocode; import robocode.peer.BulletStatus; import robocode.peer.robot.IHiddenBulletHelper; import java.io.Serializable; /** * Represents a bullet. This is returned from {@link Robot#fireBullet(double)} * and {@link AdvancedRobot#setFireBullet(double)}, and all the bullet-related * events. * * @author Mathew A. Nelson (original) * @see Robot#fireBullet(double) * @see AdvancedRobot#setFireBullet(double) * @see BulletHitEvent * @see BulletMissedEvent * @see BulletHitBulletEvent */ public class Bullet implements Serializable { private static final long serialVersionUID = 1L; private final double headingRadians; private double x; private double y; private final double power; private final String ownerName; private String victimName; private boolean isActive; private int bulletId; /** * Called by the game to create a new {@code Bullet} object * * @param heading the heading of the bullet, in radians. * @param x the starting x position of the bullet. * @param y the starting y position of the bullet. * @param power the power of the bullet. * @param ownerName the name of the owner robot that owns the bullet. * @param victimName the name of the robot hit by bullet * @param isActive still moves * @param bulletId unique id of bullet for owner robot */ public Bullet(double heading, double x, double y, double power, String ownerName, String victimName, boolean isActive, int bulletId) { this.headingRadians = heading; this.bulletId = bulletId; this.x = x; this.y = y; this.power = power; this.ownerName = ownerName; this.victimName = victimName; this.isActive = isActive; } /** * Returns the direction the bullet is/was heading, in degrees * (0 <= getHeading() < 360). This is not relative to the direction you are * facing. * * @return the direction the bullet is/was heading, in degrees */ public double getHeading() { return Math.toDegrees(headingRadians); } /** * Returns the direction the bullet is/was heading, in radians * (0 <= getHeadingRadians() < 2 * Math.PI). This is not relative to the * direction you are facing. * * @return the direction the bullet is/was heading, in radians */ public double getHeadingRadians() { return headingRadians; } /** * Returns the name of the robot that fired this bullet. * * @return the name of the robot that fired this bullet */ public String getName() { return ownerName; } /** * Returns the power of this bullet. *

* The bullet will do (4 * power) damage if it hits another robot. * If power is greater than 1, it will do an additional 2 * (power - 1) * damage. You will get (3 * power) back if you hit the other robot. * * @return the power of the bullet */ public double getPower() { return power; } /** * Returns the velocity of this bullet. The velocity of the bullet is * constant once it has been fired. * * @return the velocity of the bullet */ public double getVelocity() { return Rules.getBulletSpeed(power); } /** * Returns the name of the robot that this bullet hit, or {@code null} if * the bullet has not hit a robot. * * @return the name of the robot that this bullet hit, or {@code null} if * the bullet has not hit a robot. */ public String getVictim() { return victimName; } /** * Returns the X position of the bullet. * * @return the X position of the bullet */ public double getX() { return x; } /** * Returns the Y position of the bullet. * * @return the Y position of the bullet */ public double getY() { return y; } /** * Checks if this bullet is still active on the battlefield. * * @return {@code true} if the bullet is still active on the battlefield; * {@code false} otherwise */ public boolean isActive() { return isActive; } /** * Updates this bullet based on the specified bullet status. * * @param status the new bullet status. */ // this method is invisible on RobotAPI private void update(BulletStatus status) { x = status.x; y = status.y; victimName = status.victimName; isActive = status.isActive; } // this method is invisible on RobotAPI /** * @return unique id of bullet for owner robot */ int getBulletId() { return bulletId; } /** * Creates a hidden event helper for accessing hidden methods on this object. * * @return a hidden event helper. */ // this method is invisible on RobotAPI static IHiddenBulletHelper createHiddenHelper() { return new HiddenBulletHelper(); } // this class is invisible on RobotAPI private static class HiddenBulletHelper implements IHiddenBulletHelper { public void update(Bullet bullet, BulletStatus status) { bullet.update(status); } } } robocode/robocode/robocode/DeathEvent.java0000644000175000017500000000346311130241114020120 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Updated Javadocs *******************************************************************************/ package robocode; import robocode.peer.RobotStatics; import robocode.robotinterfaces.IBasicEvents; import robocode.robotinterfaces.IBasicRobot; import java.awt.*; /** * This event is sent to {@link Robot#onDeath(DeathEvent) onDeath()} when your * robot dies. * * @author Mathew A. Nelson (original) */ public final class DeathEvent extends Event { private static final long serialVersionUID = 1L; private final static int DEFAULT_PRIORITY = -1; // System event -> cannot be changed!; /** * Called by the game to create a new DeathEvent. */ public DeathEvent() { super(); } /** * {@inheritDoc} */ @Override public final int getPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override final int getDefaultPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override final void dispatch(IBasicRobot robot, RobotStatics statics, Graphics2D graphics) { IBasicEvents listener = robot.getBasicEventListener(); if (listener != null) { listener.onDeath(this); } } /** * {@inheritDoc} */ @Override final boolean isCriticalEvent() { return true; } } robocode/robocode/robocode/BattleRules.java0000644000175000017500000000765611130241114020327 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode; import robocode.battle.BattleProperties; /** * Contains the battle rules returned by {@link robocode.control.events.BattleStartedEvent#getBattleRules() * BattleStartedEvent.getBattleRules()} when a battle is started and * {@link robocode.control.events.BattleCompletedEvent#getBattleRules() BattleCompletedEvent.getBattleRules()} * when a battle is completed. * * @see robocode.control.events.BattleStartedEvent BattleStartedEvent * @see robocode.control.events.BattleCompletedEvent BattleCompletedEvent * * @author Pavel Savara (original) * @since 1.6.2 */ public final class BattleRules implements java.io.Serializable { private static final long serialVersionUID = 1L; private final int battlefieldWidth; private final int battlefieldHeight; private final int numRounds; private final double gunCoolingRate; private final long inactivityTime; /** * Do not call this constructor! This constructor is intended for the game alone. *

* Creates a new BattleRules based on a BattleProperties instance. * * @param battleProperties the battle properties that this object will copy from. */ public BattleRules(BattleProperties battleProperties) { this.battlefieldWidth = battleProperties.getBattlefieldWidth(); this.battlefieldHeight = battleProperties.getBattlefieldHeight(); this.numRounds = battleProperties.getNumRounds(); this.gunCoolingRate = battleProperties.getGunCoolingRate(); this.inactivityTime = battleProperties.getInactivityTime(); } /** * Returns the battlefield width. * * @return the battlefield width. */ public int getBattlefieldWidth() { return battlefieldWidth; } /** * Returns the battlefield height. * * @return the battlefield height. */ public int getBattlefieldHeight() { return battlefieldHeight; } /** * Returns the number of rounds. * * @return the number of rounds. */ public int getNumRounds() { return numRounds; } /** * Returns the rate at which the gun will cool down, i.e. the amount of heat the gun heat will drop per turn. *

* The gun cooling rate is default 0.1 per turn, but can be changed by the battle setup. * So don't count on the cooling rate being 0.1! * * @return the gun cooling rate. * @see Robot#getGunHeat() * @see Robot#fire(double) * @see Robot#fireBullet(double) */ public double getGunCoolingRate() { return gunCoolingRate; } /** * Returns the allowed inactivity time, where the robot is not taking any action, before will begin to be zapped. * The inactivity time is measured in turns, and is the allowed time that a robot is allowed to omit taking * action before being punished by the game by zapping. *

* When a robot is zapped by the game, it will loose 0.1 energy points per turn. Eventually the robot will be * killed by zapping until the robot takes action. When the robot takes action, the inactivity time counter is * reset. *

* The allowed inactivity time is per default 450 turns, but can be changed by the battle setup. * So don't count on the inactivity time being 450 turns! * * @return the allowed inactivity time. * @see Robot#doNothing() * @see AdvancedRobot#execute() */ public long getInactivityTime() { return inactivityTime; } } robocode/robocode/robocode/KeyPressedEvent.java0000644000175000017500000000366211130241112021150 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode; import robocode.peer.RobotStatics; import robocode.robotinterfaces.IBasicRobot; import robocode.robotinterfaces.IInteractiveEvents; import robocode.robotinterfaces.IInteractiveRobot; import java.awt.*; /** * A KeyPressedEvent is sent to {@link Robot#onKeyPressed(java.awt.event.KeyEvent) * onKeyPressed()} when a key has been pressed on the keyboard. * * @author Pavel Savara (original) * @see KeyReleasedEvent * @see KeyTypedEvent * @since 1.6.1 */ public final class KeyPressedEvent extends KeyEvent { private static final long serialVersionUID = 1L; private final static int DEFAULT_PRIORITY = 98; /** * Called by the game to create a new KeyPressedEvent. * * @param source the source key event originating from the AWT. */ public KeyPressedEvent(java.awt.event.KeyEvent source) { super(source); } /** * {@inheritDoc} */ @Override final int getDefaultPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override final void dispatch(IBasicRobot robot, RobotStatics statics, Graphics2D graphics) { if (statics.isInteractiveRobot()) { IInteractiveEvents listener = ((IInteractiveRobot) robot).getInteractiveEventListener(); if (listener != null) { listener.onKeyPressed(getSourceEvent()); } } } } robocode/robocode/robocode/TeamRobot.java0000644000175000017500000001275411130241112017766 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Added missing getMessageEvents() * - Updated Javadocs * - The uninitializedException() method does not need a method name as input * parameter anymore * Pavel Savara * - Re-work of robot interfaces *******************************************************************************/ package robocode; import robocode.robotinterfaces.ITeamEvents; import robocode.robotinterfaces.ITeamRobot; import robocode.robotinterfaces.peer.ITeamRobotPeer; import java.io.IOException; import java.io.Serializable; import java.util.Vector; /** * An an advanced type of robot that supports sending messages between team * mates in a robot team. *

* If you have not done already, you should create a {@link Robot} or * {@link AdvancedRobot} first. * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Pavel Savara (contributor) * @see JuniorRobot * @see Robot * @see AdvancedRobot * @see Droid */ public class TeamRobot extends AdvancedRobot implements ITeamRobot, ITeamEvents { /** * Broadcasts a message to all teammates. *

* Example: *

	 *   public void run() {
	 *       broadcastMessage("I'm here!");
	 *   }
	 * 
* * @param message the message to broadcast to all teammates * @throws IOException if the message could not be broadcasted to the * teammates * @see #isTeammate(String) * @see #getTeammates() * @see #sendMessage(String, Serializable) */ public void broadcastMessage(Serializable message) throws IOException { if (peer != null) { ((ITeamRobotPeer) peer).broadcastMessage(message); } else { uninitializedException(); } } /** * Returns a vector containing all MessageEvents currently in the robot's * queue. You might, for example, call this while processing another event. *

* Example: *

	 *   for (MessageEvent e : getMessageEvents()) {
	 *      // do something with e
	 *   }
	 * 
* * @return a vector containing all MessageEvents currently in the robot's * queue * @see #onMessageReceived(MessageEvent) * @see MessageEvent * @since 1.2.6 */ public Vector getMessageEvents() { if (peer != null) { return new Vector(((ITeamRobotPeer) peer).getMessageEvents()); } uninitializedException(); return null; // never called } /** * Do not call this method! *

* {@inheritDoc} */ public final ITeamEvents getTeamEventListener() { return this; // this robot is listening } /** * Returns the names of all teammates, or {@code null} there is no * teammates. *

* Example: *

	 *   public void run() {
	 *       // Prints out all teammates
	 *       String[] teammates = getTeammates();
	 *       if (teammates != null) {
	 *           for (String member : teammates) {
	 *               out.println(member);
	 *           }
	 *       }
	 *   }
	 * 
* * @return a String array containing the names of all your teammates, or * {@code null} if there is no teammates. The length of the String array * is equal to the number of teammates. * @see #isTeammate(String) * @see #broadcastMessage(Serializable) * @see #sendMessage(String, Serializable) */ public String[] getTeammates() { if (peer != null) { return ((ITeamRobotPeer) peer).getTeammates(); } uninitializedException(); return null; } /** * Checks if a given robot name is the name of one of your teammates. *

* Example: *

	 *   public void onScannedRobot(ScannedRobotEvent e) {
	 *       if (isTeammate(e.getName()) {
	 *           return;
	 *       }
	 *       fire(1);
	 *   }
	 * 
* * @param name the robot name to check * @return {@code true} if the specified name belongs to one of your * teammates; {@code false} otherwise. * @see #getTeammates() * @see #broadcastMessage(Serializable) * @see #sendMessage(String, Serializable) */ public boolean isTeammate(String name) { if (peer != null) { return ((ITeamRobotPeer) peer).isTeammate(name); } uninitializedException(); return false; } /** * {@inheritDoc} */ public void onMessageReceived(MessageEvent event) {} /** * Sends a message to one (or more) teammates. *

* Example: *

	 *   public void run() {
	 *       sendMessage("sample.DroidBot", "I'm here!");
	 *   }
	 * 
* * @param name the name of the intended recipient of the message * @param message the message to send * @throws IOException if the message could not be sent * @see #isTeammate(String) * @see #getTeammates() * @see #broadcastMessage(Serializable) */ public void sendMessage(String name, Serializable message) throws IOException { if (peer != null) { ((ITeamRobotPeer) peer).sendMessage(name, message); } else { uninitializedException(); } } } robocode/robocode/robocode/_AdvancedRobot.java0000644000175000017500000002366711130241112020751 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Added a peer.getCall() to getWaitCount() * - Fixed wrong names used in uninitializedException() calls * - Updated Javadocs * - The uninitializedException() method does not need a method name as input * parameter anymore * Pavel Savara * - Re-work of robot interfaces *******************************************************************************/ package robocode; import robocode.robotinterfaces.peer.IAdvancedRobotPeer; /** * This class is used by the system, as well as being a placeholder for all deprecated * (meaning, you should not use them) calls for {@link AdvancedRobot}. *

* You should create a {@link AdvancedRobot} instead. *

* There is no guarantee that this class will exist in future versions of Robocode. * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Pavel Savara (contributor) * @see AdvancedRobot */ public class _AdvancedRobot extends Robot { _AdvancedRobot() {} /** * @param degrees the amount of degrees to turn the robot's gun to the left. * If {@code degrees} > 0 the robot's gun is set to turn left. * If {@code degrees} < 0 the robot's gun is set to turn right. * If {@code degrees} = 0 the robot's gun is set to stop turning. * @deprecated Use {@link AdvancedRobot#setTurnGunLeft(double) * setTurnGunLeft} instead. */ @Deprecated public void setTurnGunLeftDegrees(double degrees) { if (peer != null) { ((IAdvancedRobotPeer) peer).setTurnGun(-Math.toRadians(degrees)); } else { uninitializedException(); } } /** * @param degrees the amount of degrees to turn the robot's gun to the right. * If {@code degrees} > 0 the robot's gun is set to turn right. * If {@code degrees} < 0 the robot's gun is set to turn left. * If {@code degrees} = 0 the robot's gun is set to stop turning. * @deprecated Use {@link AdvancedRobot#setTurnGunRight(double) * setTurnGunRight} instead. */ @Deprecated public void setTurnGunRightDegrees(double degrees) { if (peer != null) { ((IAdvancedRobotPeer) peer).setTurnGun(Math.toRadians(degrees)); } else { uninitializedException(); } } /** * @param degrees the amount of degrees to turn the robot's radar to the right. * If {@code degrees} > 0 the robot's radar will turn right. * If {@code degrees} < 0 the robot's radar will turn left. * If {@code degrees} = 0 the robot's radar will not turn, but execute. * @deprecated Use {@link Robot#turnRadarRight(double) turnRadarRight} * instead. */ @Deprecated public void turnRadarRightDegrees(double degrees) { turnRadarRight(degrees); } /** * @param degrees the amount of degrees to turn the robot's body to the right. * If {@code degrees} > 0 the robot is set to turn right. * If {@code degrees} < 0 the robot is set to turn left. * If {@code degrees} = 0 the robot is set to stop turning. * @deprecated Use {@link AdvancedRobot#setTurnRight(double) * setTurnRight(double)} instead. */ @Deprecated public void setTurnRightDegrees(double degrees) { if (peer != null) { ((IAdvancedRobotPeer) peer).setTurnBody(Math.toRadians(degrees)); } else { uninitializedException(); } } /** * @param degrees the amount of degrees to turn the robot's radar to the left. * If {@code degrees} > 0 the robot's radar is set to turn left. * If {@code degrees} < 0 the robot's radar is set to turn right. * If {@code degrees} = 0 the robot's radar is set to stop turning. * @deprecated Use {@link AdvancedRobot#setTurnRadarLeft(double) * setTurnRadarLeft(double)} instead. */ @Deprecated public void setTurnRadarLeftDegrees(double degrees) { if (peer != null) { ((IAdvancedRobotPeer) peer).setTurnRadar(-Math.toRadians(degrees)); } else { uninitializedException(); } } /** * @param degrees the amount of degrees to turn the robot's body to the left. * If {@code degrees} > 0 the robot is set to turn left. * If {@code degrees} < 0 the robot is set to turn right. * If {@code degrees} = 0 the robot is set to stop turning. * @deprecated Use {@link AdvancedRobot#setTurnLeft(double) * setTurnLeft(double)} instead. */ @Deprecated public void setTurnLeftDegrees(double degrees) { if (peer != null) { ((IAdvancedRobotPeer) peer).setTurnBody(-Math.toRadians(degrees)); } else { uninitializedException(); } } /** * @return the direction that the robot's body is facing, in degrees. * @deprecated Use {@link Robot#getHeading() getHeading()} instead. */ @Deprecated public double getHeadingDegrees() { return getHeading(); } /** * @param degrees the amount of degrees to turn the robot's body to the left. * If {@code degrees} > 0 the robot will turn left. * If {@code degrees} < 0 the robot will turn right. * If {@code degrees} = 0 the robot will not turn, but execute. * @deprecated Use {@link Robot#turnLeft(double) turnLeft(double)} instead. */ @Deprecated public void turnLeftDegrees(double degrees) { turnLeft(degrees); } /** * @param degrees the amount of degrees to turn the robot's body to the right. * If {@code degrees} > 0 the robot will turn right. * If {@code degrees} < 0 the robot will turn left. * If {@code degrees} = 0 the robot will not turn, but execute. * @deprecated Use {@link Robot#turnRight(double) turnRight(double)} instead. */ @Deprecated public void turnRightDegrees(double degrees) { turnRight(degrees); } /** * @deprecated Use {@link AdvancedRobot#execute() execute} instead. */ @Deprecated public void endTurn() { if (peer != null) { peer.execute(); } else { uninitializedException(); } } /** * @return the direction that the robot's gun is facing, in degrees. * @deprecated Use {@link Robot#getGunHeading() getGunHeading()} instead. */ @Deprecated public double getGunHeadingDegrees() { return getGunHeading(); } /** * @return the direction that the robot's radar is facing, in degrees. * @deprecated Use {@link Robot#getRadarHeading() getRadarHeading()} instead. */ @Deprecated public double getRadarHeadingDegrees() { return getRadarHeading(); } /** * @return allways {@code 0} as this method is no longer functional. * @deprecated This method is no longer functional. * Use {@link AdvancedRobot#onSkippedTurn(SkippedTurnEvent)} instead. */ @Deprecated public int getWaitCount() { if (peer != null) { peer.getCall(); } return 0; } /** * @param degrees the amount of degrees to turn the robot's radar to the right. * If {@code degrees} > 0 the robot's radar is set to turn right. * If {@code degrees} < 0 the robot's radar is set to turn left. * If {@code degrees} = 0 the robot's radar is set to stop turning. * @deprecated Use {@link AdvancedRobot#setTurnRadarRight(double) * setTurnRadarRight} instead. */ @Deprecated public void setTurnRadarRightDegrees(double degrees) { if (peer != null) { ((IAdvancedRobotPeer) peer).setTurnRadar(Math.toRadians(degrees)); } else { uninitializedException(); } } /** * @param degrees the amount of degrees to turn the robot's gun to the left. * If {@code degrees} > 0 the robot's gun will turn left. * If {@code degrees} < 0 the robot's gun will turn right. * If {@code degrees} = 0 the robot's gun will not turn, but execute. * @deprecated Use {@link Robot#turnGunLeft(double) turnGunLeft} instead. */ @Deprecated public void turnGunLeftDegrees(double degrees) { turnGunLeft(degrees); } /** * @param degrees the amount of degrees to turn the robot's gun to the right. * If {@code degrees} > 0 the robot's gun will turn right. * If {@code degrees} < 0 the robot's gun will turn left. * If {@code degrees} = 0 the robot's gun will not turn, but execute. * @deprecated Use {@link Robot#turnGunRight(double) turnGunRight} instead. */ @Deprecated public void turnGunRightDegrees(double degrees) { turnGunRight(degrees); } /** * @param degrees the amount of degrees to turn the robot's radar to the left. * If {@code degrees} > 0 the robot's radar will turn left. * If {@code degrees} < 0 the robot's radar will turn right. * If {@code degrees} = 0 the robot's radar will not turn, but execute. * @deprecated Use {@link Robot#turnRadarLeft(double) turnRadarLeft} instead. */ @Deprecated public void turnRadarLeftDegrees(double degrees) { turnRadarLeft(degrees); } /** * @return allways {@code 0} as this method is no longer functional. * @deprecated This method is no longer functional. * Use {@link AdvancedRobot#onSkippedTurn(SkippedTurnEvent)} instead. */ @Deprecated public int getMaxWaitCount() { if (peer != null) { peer.getCall(); } return 0; } } robocode/robocode/robocode/MouseEnteredEvent.java0000644000175000017500000000412211130241112021461 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode; import robocode.peer.RobotStatics; import robocode.robotinterfaces.IBasicRobot; import robocode.robotinterfaces.IInteractiveEvents; import robocode.robotinterfaces.IInteractiveRobot; import java.awt.*; /** * A MouseEnteredEvent is sent to {@link Robot#onMouseEntered(java.awt.event.MouseEvent) * onMouseEntered()} when the mouse has entered the battle view. * * @author Pavel Savara (original) * @see MouseClickedEvent * @see MousePressedEvent * @see MouseReleasedEvent * @see MouseExitedEvent * @see MouseMovedEvent * @see MouseDraggedEvent * @see MouseWheelMovedEvent * @since 1.6.1 */ public final class MouseEnteredEvent extends MouseEvent { private static final long serialVersionUID = 1L; private final static int DEFAULT_PRIORITY = 98; /** * Called by the game to create a new MouseEnteredEvent. * * @param source the source mouse event originating from the AWT. */ public MouseEnteredEvent(java.awt.event.MouseEvent source) { super(source); } /** * {@inheritDoc} */ @Override final int getDefaultPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override final void dispatch(IBasicRobot robot, RobotStatics statics, Graphics2D graphics) { if (statics.isInteractiveRobot()) { IInteractiveEvents listener = ((IInteractiveRobot) robot).getInteractiveEventListener(); if (listener != null) { listener.onMouseEntered(getSourceEvent()); } } } } robocode/robocode/robocode/TurnCompleteCondition.java0000644000175000017500000000450711130241112022357 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Updated Javadoc * Nathaniel Troutman * - Added cleanup() method for cleaning up references to internal classes * to prevent circular references causing memory leaks *******************************************************************************/ package robocode; /** * A prebuilt condition you can use that indicates your robot has finished * turning. * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Nathaniel Troutman (contributor) * @see Condition */ public class TurnCompleteCondition extends Condition { private AdvancedRobot robot; /** * Creates a new TurnCompleteCondition with default priority. * The default priority is 80. * * @param robot your robot, which must be a {@link AdvancedRobot} */ public TurnCompleteCondition(AdvancedRobot robot) { super(); this.robot = robot; } /** * Creates a new TurnCompleteCondition with the specified priority. * A condition priority is a value from 0 - 99. The higher value, the * higher priority. The default priority is 80. * * @param robot your robot, which must be a {@link AdvancedRobot} * @param priority the priority of this condition * @see Condition#setPriority(int) */ public TurnCompleteCondition(AdvancedRobot robot, int priority) { super(); this.robot = robot; this.priority = priority; } /** * Tests if the robot has finished turning. * * @return {@code true} if the robot has stopped turning; {@code false} * otherwise */ @Override public boolean test() { return (robot.getTurnRemaining() == 0); } /** * Called by the system in order to clean up references to internal objects. * * @since 1.4.3 */ @Override public void cleanup() { robot = null; } } robocode/robocode/robocode/BulletHitBulletEvent.java0000644000175000017500000000470011130241114022132 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Updated Javadocs *******************************************************************************/ package robocode; import robocode.peer.RobotStatics; import robocode.robotinterfaces.IBasicEvents; import robocode.robotinterfaces.IBasicRobot; import java.awt.*; import java.util.Hashtable; /** * This event is sent to {@link Robot#onBulletHitBullet(BulletHitBulletEvent) * onBulletHitBullet} when one of your bullets has hit another bullet. * * @author Mathew A. Nelson (original) */ public final class BulletHitBulletEvent extends Event { private static final long serialVersionUID = 1L; private final static int DEFAULT_PRIORITY = 55; private Bullet bullet; private final Bullet hitBullet; /** * Called by the game to create a new {@code BulletHitEvent}. * * @param bullet your bullet that hit another bullet * @param hitBullet the bullet that was hit by your bullet */ public BulletHitBulletEvent(Bullet bullet, Bullet hitBullet) { super(); this.bullet = bullet; this.hitBullet = hitBullet; } /** * Returns your bullet that hit another bullet. * * @return your bullet */ public Bullet getBullet() { return bullet; } /** * Returns the bullet that was hit by your bullet. * * @return the bullet that was hit */ public Bullet getHitBullet() { return hitBullet; } /** * {@inheritDoc} */ @Override final int getDefaultPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override final void dispatch(IBasicRobot robot, RobotStatics statics, Graphics2D graphics) { IBasicEvents listener = robot.getBasicEventListener(); if (listener != null) { listener.onBulletHitBullet(this); } } /** * {@inheritDoc} */ @Override final void updateBullets(Hashtable bullets) { // we need to pass same instance bullet = bullets.get(bullet.getBulletId()); } } robocode/robocode/robocode/MouseMovedEvent.java0000644000175000017500000000411311130241112021145 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode; import robocode.peer.RobotStatics; import robocode.robotinterfaces.IBasicRobot; import robocode.robotinterfaces.IInteractiveEvents; import robocode.robotinterfaces.IInteractiveRobot; import java.awt.*; /** * A MouseMovedEvent is sent to {@link Robot#onMouseMoved(java.awt.event.MouseEvent) * onMouseMoved()} when the mouse has moved inside the battle view. * * @author Pavel Savara (original) * @see MouseClickedEvent * @see MousePressedEvent * @see MouseReleasedEvent * @see MouseEnteredEvent * @see MouseExitedEvent * @see MouseDraggedEvent * @see MouseWheelMovedEvent * @since 1.6.1 */ public final class MouseMovedEvent extends MouseEvent { private static final long serialVersionUID = 1L; private final static int DEFAULT_PRIORITY = 98; /** * Called by the game to create a new MouseMovedEvent. * * @param source the source mouse event originating from the AWT. */ public MouseMovedEvent(java.awt.event.MouseEvent source) { super(source); } /** * {@inheritDoc} */ @Override final int getDefaultPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override final void dispatch(IBasicRobot robot, RobotStatics statics, Graphics2D graphics) { if (statics.isInteractiveRobot()) { IInteractiveEvents listener = ((IInteractiveRobot) robot).getInteractiveEventListener(); if (listener != null) { listener.onMouseMoved(getSourceEvent()); } } } } robocode/robocode/robocode/Robot.java0000644000175000017500000013170511130241112017155 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Added setColors(Color, Color, Color, Color, Color), setAllColors(), * setBodyColor(), setGunColor(), setRadarColor(), setBulletColor(), and * setScanColor() * - Updated Javadocs * - The finalize() is now protected instead of public * - Added onKeyPressed(), onKeyReleased(), onKeyTyped() events * - Added onMouseMoved(), onMouseClicked(), onMouseReleased(), * onMouseEntered(), onMouseExited(), onMouseDragged(), onMouseWheelMoved() * events * - The uninitializedException() method does not need a method name as input * parameter anymore * - The PrintStream 'out' has been moved to the new _RobotBase class * Matthew Reeder * - Fix for HyperThreading hang issue * Stefan Westen (RobocodeGL) & Flemming N. Larsen * - Added onPaint() method for painting the robot * Pavel Savara * - Re-work of robot interfaces * - Added getGraphics() *******************************************************************************/ package robocode; import robocode.robotinterfaces.*; import robocode.robotinterfaces.peer.IStandardRobotPeer; import java.awt.*; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseWheelEvent; /** * The basic robot class that you will extend to create your own robots. *

*

Please note the following standards will be used: *
heading - absolute angle in degrees with 0 facing up the screen, * positive clockwise. 0 <= heading < 360. *
bearing - relative angle to some object from your robot's heading, * positive clockwise. -180 < bearing <= 180 *
All coordinates are expressed as (x,y). *
All coordinates are positive. *
The origin (0,0) is at the bottom left of the screen. *
Positive x is right. *
Positive y is up. * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Matthew Reeder (contributor) * @author Stefan Westen (contributor) * @author Pavel Savara (contributor) * @see * robocode.sourceforge.net * @see * Building your first robot * @see JuniorRobot * @see AdvancedRobot * @see TeamRobot * @see Droid */ public class Robot extends _Robot implements IInteractiveRobot, IPaintRobot, IBasicEvents2, IInteractiveEvents, IPaintEvents { /** * Constructs a new robot. */ public Robot() {} /** * {@inheritDoc}} */ public final Runnable getRobotRunnable() { return this; } /** * {@inheritDoc}} */ public final IBasicEvents getBasicEventListener() { return this; } /** * {@inheritDoc}} */ public final IInteractiveEvents getInteractiveEventListener() { return this; } /** * {@inheritDoc}} */ public final IPaintEvents getPaintEventListener() { return this; } /** * Immediately moves your robot ahead (forward) by distance measured in * pixels. *

* This call executes immediately, and does not return until it is complete, * i.e. when the remaining distance to move is 0. *

* If the robot collides with a wall, the move is complete, meaning that the * robot will not move any further. If the robot collides with another * robot, the move is complete if you are heading toward the other robot. *

* Note that both positive and negative values can be given as input, * where negative values means that the robot is set to move backward * instead of forward. *

* Example: *

	 *   // Move the robot 100 pixels forward
	 *   ahead(100);
	 * 

* // Afterwards, move the robot 50 pixels backward * ahead(-50); *

* * @param distance the distance to move ahead measured in pixels. * If this value is negative, the robot will move back instead of ahead. * @see #back(double) * @see #onHitWall(HitWallEvent) * @see #onHitRobot(HitRobotEvent) */ public void ahead(double distance) { if (peer != null) { peer.move(distance); } else { uninitializedException(); } } /** * Immediately moves your robot backward by distance measured in pixels. *

* This call executes immediately, and does not return until it is complete, * i.e. when the remaining distance to move is 0. *

* If the robot collides with a wall, the move is complete, meaning that the * robot will not move any further. If the robot collides with another * robot, the move is complete if you are heading toward the other robot. *

* Note that both positive and negative values can be given as input, * where negative values means that the robot is set to move forward instead * of backward. *

* Example: *

	 *   // Move the robot 100 pixels backward
	 *   back(100);
	 * 

* // Afterwards, move the robot 50 pixels forward * back(-50); *

* * @param distance the distance to move back measured in pixels. * If this value is negative, the robot will move ahead instead of back. * @see #ahead(double) * @see #onHitWall(HitWallEvent) * @see #onHitRobot(HitRobotEvent) */ public void back(double distance) { if (peer != null) { peer.move(-distance); } else { uninitializedException(); } } /** * Returns the width of the current battlefield measured in pixels. * * @return the width of the current battlefield measured in pixels. */ public double getBattleFieldWidth() { if (peer != null) { return peer.getBattleFieldWidth(); } uninitializedException(); return 0; // never called } /** * Returns the height of the current battlefield measured in pixels. * * @return the height of the current battlefield measured in pixels. */ public double getBattleFieldHeight() { if (peer != null) { return peer.getBattleFieldHeight(); } uninitializedException(); return 0; // never called } /** * Returns the direction that the robot's body is facing, in degrees. * The value returned will be between 0 and 360 (is excluded). *

* Note that the heading in Robocode is like a compass, where 0 means North, * 90 means East, 180 means South, and 270 means West. * * @return the direction that the robot's body is facing, in degrees. * @see #getGunHeading() * @see #getRadarHeading() */ public double getHeading() { if (peer != null) { double rv = 180.0 * peer.getBodyHeading() / Math.PI; while (rv < 0) { rv += 360; } while (rv >= 360) { rv -= 360; } return rv; } uninitializedException(); return 0; // never called } /** * Returns the height of the robot measured in pixels. * * @return the height of the robot measured in pixels. * @see #getWidth() */ public double getHeight() { if (peer == null) { uninitializedException(); } return robocode.peer.RobotPeer.HEIGHT; } /** * Returns the width of the robot measured in pixels. * * @return the width of the robot measured in pixels. * @see #getHeight() */ public double getWidth() { if (peer == null) { uninitializedException(); } return robocode.peer.RobotPeer.WIDTH; } /** * Returns the robot's name. * * @return the robot's name. */ public String getName() { if (peer != null) { return peer.getName(); } uninitializedException(); return null; // never called } /** * Returns the X position of the robot. (0,0) is at the bottom left of the * battlefield. * * @return the X position of the robot. * @see #getY() */ public double getX() { if (peer != null) { return peer.getX(); } uninitializedException(); return 0; // never called } /** * Returns the Y position of the robot. (0,0) is at the bottom left of the * battlefield. * * @return the Y position of the robot. * @see #getX() */ public double getY() { if (peer != null) { return peer.getY(); } uninitializedException(); return 0; // never called } /** * The main method in every robot. You must override this to set up your * robot's basic behavior. *

* Example: *

	 *   // A basic robot that moves around in a square
	 *   public void run() {
	 *       while (true) {
	 *           ahead(100);
	 *           turnRight(90);
	 *       }
	 *   }
	 * 
*/ public void run() {} /** * Immediately turns the robot's body to the left by degrees. *

* This call executes immediately, and does not return until it is complete, * i.e. when the angle remaining in the robot's turn is 0. *

* Note that both positive and negative values can be given as input, * where negative values means that the robot's body is set to turn right * instead of left. *

* Example: *

	 *   // Turn the robot 180 degrees to the left
	 *   turnLeft(180);
	 * 

* // Afterwards, turn the robot 90 degrees to the right * turnLeft(-90); *

* * @param degrees the amount of degrees to turn the robot's body to the left. * If {@code degrees} > 0 the robot will turn left. * If {@code degrees} < 0 the robot will turn right. * If {@code degrees} = 0 the robot will not turn, but execute. * @see #turnRight(double) * @see #turnGunLeft(double) * @see #turnGunRight(double) * @see #turnRadarLeft(double) * @see #turnRadarRight(double) */ public void turnLeft(double degrees) { if (peer != null) { peer.turnBody(-Math.toRadians(degrees)); } else { uninitializedException(); } } /** * Immediately turns the robot's body to the right by degrees. * This call executes immediately, and does not return until it is complete, * i.e. when the angle remaining in the robot's turn is 0. *

* Note that both positive and negative values can be given as input, * where negative values means that the robot's body is set to turn left * instead of right. *

* Example: *

	 *   // Turn the robot 180 degrees to the right
	 *   turnRight(180);
	 * 

* // Afterwards, turn the robot 90 degrees to the left * turnRight(-90); *

* * @param degrees the amount of degrees to turn the robot's body to the right. * If {@code degrees} > 0 the robot will turn right. * If {@code degrees} < 0 the robot will turn left. * If {@code degrees} = 0 the robot will not turn, but execute. * @see #turnLeft(double) * @see #turnGunLeft(double) * @see #turnGunRight(double) * @see #turnRadarLeft(double) * @see #turnRadarRight(double) */ public void turnRight(double degrees) { if (peer != null) { peer.turnBody(Math.toRadians(degrees)); } else { uninitializedException(); } } /** * Do nothing this turn, meaning that the robot will skip it's turn. *

* This call executes immediately, and does not return until the turn is * over. */ public void doNothing() { if (peer != null) { peer.execute(); } else { uninitializedException(); } } /** * Called by the system to 'clean up' after your robot. * You may not override this method. */ @Override protected final void finalize() throws Throwable { // This method must be final! super.finalize(); } /** * Immediately fires a bullet. The bullet will travel in the direction the * gun is pointing. *

* The specified bullet power is an amount of energy that will be taken from * the robot's energy. Hence, the more power you want to spend on the * bullet, the more energy is taken from your robot. *

* The bullet will do (4 * power) damage if it hits another robot. If power * is greater than 1, it will do an additional 2 * (power - 1) damage. * You will get (3 * power) back if you hit the other robot. You can call * {@link Rules#getBulletDamage(double)} for getting the damage that a * bullet with a specific bullet power will do. *

* The specified bullet power should be between * {@link Rules#MIN_BULLET_POWER} and {@link Rules#MAX_BULLET_POWER}. *

* Note that the gun cannot fire if the gun is overheated, meaning that * {@link #getGunHeat()} returns a value > 0. *

* A event is generated when the bullet hits a robot * ({@link BulletHitEvent}), wall ({@link BulletMissedEvent}), or another * bullet ({@link BulletHitBulletEvent}). *

* Example: *

	 *   // Fire a bullet with maximum power if the gun is ready
	 *   if (getGunHeat() == 0) {
	 *       fire(Rules.MAX_BULLET_POWER);
	 *   }
	 * 
* * @param power the amount of energy given to the bullet, and subtracted * from the robot's energy. * @see #fireBullet(double) * @see #getGunHeat() * @see #getGunCoolingRate() * @see #onBulletHit(BulletHitEvent) * @see #onBulletHitBullet(BulletHitBulletEvent) * @see #onBulletMissed(BulletMissedEvent) */ public void fire(double power) { if (peer != null) { peer.setFire(power); peer.execute(); } else { uninitializedException(); } } /** * Immediately fires a bullet. The bullet will travel in the direction the * gun is pointing. *

* The specified bullet power is an amount of energy that will be taken from * the robot's energy. Hence, the more power you want to spend on the * bullet, the more energy is taken from your robot. *

* The bullet will do (4 * power) damage if it hits another robot. If power * is greater than 1, it will do an additional 2 * (power - 1) damage. * You will get (3 * power) back if you hit the other robot. You can call * {@link Rules#getBulletDamage(double)} for getting the damage that a * bullet with a specific bullet power will do. *

* The specified bullet power should be between * {@link Rules#MIN_BULLET_POWER} and {@link Rules#MAX_BULLET_POWER}. *

* Note that the gun cannot fire if the gun is overheated, meaning that * {@link #getGunHeat()} returns a value > 0. *

* A event is generated when the bullet hits a robot * ({@link BulletHitEvent}), wall ({@link BulletMissedEvent}), or another * bullet ({@link BulletHitBulletEvent}). *

* Example: *

	 *   // Fire a bullet with maximum power if the gun is ready
	 *   if (getGunHeat() == 0) {
	 *       Bullet bullet = fireBullet(Rules.MAX_BULLET_POWER);
	 * 

* // Get the velocity of the bullet * if (bullet != null) { * double bulletVelocity = bullet.getVelocity(); * } * } *

* * @param power the amount of energy given to the bullet, and subtracted * from the robot's energy. * @return a {@link Bullet} that contains information about the bullet if it * was actually fired, which can be used for tracking the bullet after it * has been fired. If the bullet was not fired, {@code null} is returned. * @see #fire(double) * @see Bullet * @see #getGunHeat() * @see #getGunCoolingRate() * @see #onBulletHit(BulletHitEvent) * @see #onBulletHitBullet(BulletHitBulletEvent) * @see #onBulletMissed(BulletMissedEvent) */ public Bullet fireBullet(double power) { if (peer != null) { return peer.fire(power); } uninitializedException(); return null; } /** * Returns the rate at which the gun will cool down, i.e. the amount of heat * the gun heat will drop per turn. *

* The gun cooling rate is default 0.1 / turn, but can be changed by the * battle setup. So don't count on the cooling rate being 0.1! * * @return the gun cooling rate * @see #getGunHeat() * @see #fire(double) * @see #fireBullet(double) */ public double getGunCoolingRate() { if (peer != null) { return peer.getGunCoolingRate(); } uninitializedException(); return 0; // never called } /** * Returns the direction that the robot's gun is facing, in degrees. * The value returned will be between 0 and 360 (is excluded). *

* Note that the heading in Robocode is like a compass, where 0 means North, * 90 means East, 180 means South, and 270 means West. * * @return the direction that the robot's gun is facing, in degrees. * @see #getHeading() * @see #getRadarHeading() */ public double getGunHeading() { if (peer != null) { return peer.getGunHeading() * 180.0 / Math.PI; } uninitializedException(); return 0; // never called } /** * Returns the current heat of the gun. The gun cannot fire unless this is * 0. (Calls to fire will succeed, but will not actually fire unless * getGunHeat() == 0). *

* The amount of gun heat generated when the gun is fired is * 1 + (firePower / 5). Each turn the gun heat drops by the amount returned * by {@link #getGunCoolingRate()}, which is a battle setup. *

* Note that all guns are "hot" at the start of each round, where the gun * heat is 3. * * @return the current gun heat * @see #getGunCoolingRate() * @see #fire(double) * @see #fireBullet(double) */ public double getGunHeat() { if (peer != null) { return peer.getGunHeat(); } uninitializedException(); return 0; // never called } /** * Returns the number of rounds in the current battle. * * @return the number of rounds in the current battle * @see #getRoundNum() */ public int getNumRounds() { if (peer != null) { return peer.getNumRounds(); } uninitializedException(); return 0; // never called } /** * Returns how many opponents that are left in the current round. * * @return how many opponents that are left in the current round. */ public int getOthers() { if (peer != null) { return peer.getOthers(); } uninitializedException(); return 0; // never called } /** * Returns the direction that the robot's radar is facing, in degrees. * The value returned will be between 0 and 360 (is excluded). *

* Note that the heading in Robocode is like a compass, where 0 means North, * 90 means East, 180 means South, and 270 means West. * * @return the direction that the robot's radar is facing, in degrees. * @see #getHeading() * @see #getGunHeading() */ public double getRadarHeading() { if (peer != null) { return peer.getRadarHeading() * 180.0 / Math.PI; } uninitializedException(); return 0; // never called } /** * Returns the current round number (0 to {@link #getNumRounds()} - 1) of * the battle. * * @return the current round number of the battle * @see #getNumRounds() */ public int getRoundNum() { if (peer != null) { return peer.getRoundNum(); } uninitializedException(); return 0; // never called } /** * Returns the game time of the current round, where the time is equal to * the current turn in the round. *

* A battle consists of multiple rounds. *

* Time is reset to 0 at the beginning of every round. * * @return the game time/turn of the current round. */ public long getTime() { if (peer != null) { return peer.getTime(); } uninitializedException(); return 0; // never called } /** * Returns the velocity of the robot measured in pixels/turn. *

* The maximum velocity of a robot is defined by {@link Rules#MAX_VELOCITY} * (8 pixels / turn). * * @return the velocity of the robot measured in pixels/turn. * @see Rules#MAX_VELOCITY */ public double getVelocity() { if (peer != null) { return peer.getVelocity(); } uninitializedException(); return 0; // never called } /** * {@inheritDoc} */ public void onBulletHit(BulletHitEvent event) {} /** * {@inheritDoc} */ public void onBulletHitBullet(BulletHitBulletEvent event) {} /** * {@inheritDoc} */ public void onBulletMissed(BulletMissedEvent event) {} /** * {@inheritDoc} */ public void onDeath(DeathEvent event) {} /** * {@inheritDoc} */ public void onHitByBullet(HitByBulletEvent event) {} /** * {@inheritDoc} */ public void onHitRobot(HitRobotEvent event) {} /** * {@inheritDoc} */ public void onHitWall(HitWallEvent event) {} /** * {@inheritDoc} */ public void onRobotDeath(RobotDeathEvent event) {} /** * {@inheritDoc} */ public void onScannedRobot(ScannedRobotEvent event) {} /** * {@inheritDoc} */ public void onWin(WinEvent event) {} /** * {@inheritDoc} */ public void onBattleEnded(BattleEndedEvent event) {} /** * Scans for other robots. This method is called automatically by the game, * as long as the robot is moving, turning its body, turning its gun, or * turning its radar. *

* Scan will cause {@link #onScannedRobot(ScannedRobotEvent) * onScannedRobot(ScannedRobotEvent)} to be called if you see a robot. *

* There are 2 reasons to call {@code scan()} manually: *

    *
  1. You want to scan after you stop moving. *
  2. You want to interrupt the {@code onScannedRobot} event. This is more * likely. If you are in {@code onScannedRobot} and call {@code scan()}, * and you still see a robot, then the system will interrupt your * {@code onScannedRobot} event immediately and start it from the top. *
*

* This call executes immediately. * * @see #onScannedRobot(ScannedRobotEvent) * @see ScannedRobotEvent */ public void scan() { if (peer != null) { ((IStandardRobotPeer) peer).rescan(); } else { uninitializedException(); } } /** * Sets the gun to turn independent from the robot's turn. *

* Ok, so this needs some explanation: The gun is mounted on the robot's * body. So, normally, if the robot turns 90 degrees to the right, then the * gun will turn with it as it is mounted on top of the robot's body. To * compensate for this, you can call {@code setAdjustGunForRobotTurn(true)}. * When this is set, the gun will turn independent from the robot's turn, * i.e. the gun will compensate for the robot's body turn. *

* Example, assuming both the robot and gun start out facing up (0 degrees): *

	 *   // Set gun to turn with the robot's turn
	 *   setAdjustGunForRobotTurn(false); // This is the default
	 *   turnRight(90);
	 *   // At this point, both the robot and gun are facing right (90 degrees)
	 *   turnLeft(90);
	 *   // Both are back to 0 degrees
	 * 

* -- or -- *

* // Set gun to turn independent from the robot's turn * setAdjustGunForRobotTurn(true); * turnRight(90); * // At this point, the robot is facing right (90 degrees), but the gun is still facing up. * turnLeft(90); * // Both are back to 0 degrees. *

*

* Note: The gun compensating this way does count as "turning the gun". * See {@link #setAdjustRadarForGunTurn(boolean)} for details. * * @param independent {@code true} if the gun must turn independent from the * robot's turn; {@code false} if the gun must turn with the robot's turn. * @see #setAdjustRadarForGunTurn(boolean) */ public void setAdjustGunForRobotTurn(boolean independent) { if (peer != null) { ((IStandardRobotPeer) peer).setAdjustGunForBodyTurn(independent); } else { uninitializedException(); } } /** * Sets the radar to turn independent from the robot's turn. *

* Ok, so this needs some explanation: The radar is mounted on the gun, and * the gun is mounted on the robot's body. So, normally, if the robot turns * 90 degrees to the right, the gun turns, as does the radar. Hence, if the * robot turns 90 degrees to the right, then the gun and radar will turn * with it as the radar is mounted on top of the gun. To compensate for * this, you can call {@code setAdjustRadarForRobotTurn(true)}. When this is * set, the radar will turn independent from the robot's turn, i.e. the * radar will compensate for the robot's turn. *

* Example, assuming the robot, gun, and radar all start out facing up (0 * degrees): *

	 *   // Set radar to turn with the robots's turn
	 *   setAdjustRadarForRobotTurn(false); // This is the default
	 *   turnRight(90);
	 *   // At this point, the body, gun, and radar are all facing right (90 degrees);
	 * 

* -- or -- *

* // Set radar to turn independent from the robot's turn * setAdjustRadarForRobotTurn(true); * turnRight(90); * // At this point, the robot and gun are facing right (90 degrees), but the radar is still facing up. *

* * @param independent {@code true} if the radar must turn independent from * the robots's turn; {@code false} if the radar must turn with the robot's * turn. * @see #setAdjustGunForRobotTurn(boolean) * @see #setAdjustRadarForGunTurn(boolean) */ public void setAdjustRadarForRobotTurn(boolean independent) { if (peer != null) { ((IStandardRobotPeer) peer).setAdjustRadarForBodyTurn(independent); } else { uninitializedException(); } } /** * Sets the radar to turn independent from the gun's turn. *

* Ok, so this needs some explanation: The radar is mounted on the robot's * gun. So, normally, if the gun turns 90 degrees to the right, then the * radar will turn with it as it is mounted on top of the gun. To compensate * for this, you can call {@code setAdjustRadarForGunTurn(true)}. When this * is set, the radar will turn independent from the robot's turn, i.e. the * radar will compensate for the gun's turn. *

* Example, assuming both the gun and radar start out facing up (0 degrees): *

	 *   // Set radar to turn with the gun's turn
	 *   setAdjustRadarForGunTurn(false); // This is the default
	 *   turnGunRight(90);
	 *   // At this point, both the radar and gun are facing right (90 degrees);
	 * 

* -- or -- *

* // Set radar to turn independent from the gun's turn * setAdjustRadarForGunTurn(true); * turnGunRight(90); * // At this point, the gun is facing right (90 degrees), but the radar is still facing up. *

* Note: Calling {@code setAdjustRadarForGunTurn(boolean)} will * automatically call {@link #setAdjustRadarForRobotTurn(boolean)} with the * same value, unless you have already called it earlier. This behavior is * primarily for backward compatibility with older Robocode robots. * * @param independent {@code true} if the radar must turn independent from * the gun's turn; {@code false} if the radar must turn with the gun's * turn. * @see #setAdjustRadarForRobotTurn(boolean) * @see #setAdjustGunForRobotTurn(boolean) */ public void setAdjustRadarForGunTurn(boolean independent) { if (peer != null) { ((IStandardRobotPeer) peer).setAdjustRadarForGunTurn(independent); } else { uninitializedException(); } } /** * Sets the color of the robot's body, gun, and radar in the same time. *

* You may only call this method one time per battle. A {@code null} * indicates the default (blue) color. *

* Example: *

	 *   // Don't forget to import java.awt.Color at the top...
	 *   import java.awt.Color;
	 *   ...
	 * 

* public void run() { * setColors(null, Color.RED, new Color(150, 0, 150)); * ... * } *

* * @param bodyColor the new body color * @param gunColor the new gun color * @param radarColor the new radar color * @see #setColors(Color, Color, Color, Color, Color) * @see #setAllColors(Color) * @see #setBodyColor(Color) * @see #setGunColor(Color) * @see #setRadarColor(Color) * @see #setBulletColor(Color) * @see #setScanColor(Color) * @see Color */ public void setColors(Color bodyColor, Color gunColor, Color radarColor) { if (peer != null) { peer.setBodyColor(bodyColor); peer.setGunColor(gunColor); peer.setRadarColor(radarColor); } else { uninitializedException(); } } /** * Sets the color of the robot's body, gun, radar, bullet, and scan arc in * the same time. *

* You may only call this method one time per battle. A {@code null} * indicates the default (blue) color for the body, gun, radar, and scan * arc, but white for the bullet color. *

* Example: *

	 *   // Don't forget to import java.awt.Color at the top...
	 *   import java.awt.Color;
	 *   ...
	 * 

* public void run() { * setColors(null, Color.RED, Color.GREEN, null, new Color(150, 0, 150)); * ... * } *

* * @param bodyColor the new body color * @param gunColor the new gun color * @param radarColor the new radar color * @param bulletColor the new bullet color * @param scanArcColor the new scan arc color * @see #setColors(Color, Color, Color) * @see #setAllColors(Color) * @see #setBodyColor(Color) * @see #setGunColor(Color) * @see #setRadarColor(Color) * @see #setBulletColor(Color) * @see #setScanColor(Color) * @see Color * @since 1.1.3 */ public void setColors(Color bodyColor, Color gunColor, Color radarColor, Color bulletColor, Color scanArcColor) { if (peer != null) { peer.setBodyColor(bodyColor); peer.setGunColor(gunColor); peer.setRadarColor(radarColor); peer.setBulletColor(bulletColor); peer.setScanColor(scanArcColor); } else { uninitializedException(); } } /** * Sets all the robot's color to the same color in the same time, i.e. the * color of the body, gun, radar, bullet, and scan arc. *

* You may only call this method one time per battle. A {@code null} * indicates the default (blue) color for the body, gun, radar, and scan * arc, but white for the bullet color. *

*

	 * Example:
	 *   // Don't forget to import java.awt.Color at the top...
	 *   import java.awt.Color;
	 *   ...
	 * 

* public void run() { * setAllColors(Color.RED); * ... * } *

* * @param color the new color for all the colors of the robot * @see #setColors(Color, Color, Color) * @see #setColors(Color, Color, Color, Color, Color) * @see #setBodyColor(Color) * @see #setGunColor(Color) * @see #setRadarColor(Color) * @see #setBulletColor(Color) * @see #setScanColor(Color) * @see Color * @since 1.1.3 */ public void setAllColors(Color color) { if (peer != null) { peer.setBodyColor(color); peer.setGunColor(color); peer.setRadarColor(color); peer.setBulletColor(color); peer.setScanColor(color); } else { uninitializedException(); } } /** * Sets the color of the robot's body. *

* A {@code null} indicates the default (blue) color. *

*

	 * Example:
	 *   // Don't forget to import java.awt.Color at the top...
	 *   import java.awt.Color;
	 *   ...
	 * 

* public void run() { * setBodyColor(Color.BLACK); * ... * } *

* * @param color the new body color * @see #setColors(Color, Color, Color) * @see #setColors(Color, Color, Color, Color, Color) * @see #setAllColors(Color) * @see #setGunColor(Color) * @see #setRadarColor(Color) * @see #setBulletColor(Color) * @see #setScanColor(Color) * @see Color * @since 1.1.2 */ public void setBodyColor(Color color) { if (peer != null) { peer.setBodyColor(color); } else { uninitializedException(); } } /** * Sets the color of the robot's gun. *

* A {@code null} indicates the default (blue) color. *

*

	 * Example:
	 *   // Don't forget to import java.awt.Color at the top...
	 *   import java.awt.Color;
	 *   ...
	 * 

* public void run() { * setGunColor(Color.RED); * ... * } *

* * @param color the new gun color * @see #setColors(Color, Color, Color) * @see #setColors(Color, Color, Color, Color, Color) * @see #setAllColors(Color) * @see #setBodyColor(Color) * @see #setRadarColor(Color) * @see #setBulletColor(Color) * @see #setScanColor(Color) * @see Color * @since 1.1.2 */ public void setGunColor(Color color) { if (peer != null) { peer.setGunColor(color); } else { uninitializedException(); } } /** * Sets the color of the robot's radar. *

* A {@code null} indicates the default (blue) color. *

*

	 * Example:
	 *   // Don't forget to import java.awt.Color at the top...
	 *   import java.awt.Color;
	 *   ...
	 * 

* public void run() { * setRadarColor(Color.YELLOW); * ... * } *

* * @param color the new radar color * @see #setColors(Color, Color, Color) * @see #setColors(Color, Color, Color, Color, Color) * @see #setAllColors(Color) * @see #setBodyColor(Color) * @see #setGunColor(Color) * @see #setBulletColor(Color) * @see #setScanColor(Color) * @see Color * @since 1.1.2 */ public void setRadarColor(Color color) { if (peer != null) { peer.setRadarColor(color); } else { uninitializedException(); } } /** * Sets the color of the robot's bullets. *

* A {@code null} indicates the default white color. *

*

	 * Example:
	 *   // Don't forget to import java.awt.Color at the top...
	 *   import java.awt.Color;
	 *   ...
	 * 

* public void run() { * setBulletColor(Color.GREEN); * ... * } *

* * @param color the new bullet color * @see #setColors(Color, Color, Color) * @see #setColors(Color, Color, Color, Color, Color) * @see #setAllColors(Color) * @see #setBodyColor(Color) * @see #setGunColor(Color) * @see #setRadarColor(Color) * @see #setScanColor(Color) * @see Color * @since 1.1.2 */ public void setBulletColor(Color color) { if (peer != null) { peer.setBulletColor(color); } else { uninitializedException(); } } /** * Sets the color of the robot's scan arc. *

* A {@code null} indicates the default (blue) color. *

*

	 * Example:
	 *   // Don't forget to import java.awt.Color at the top...
	 *   import java.awt.Color;
	 *   ...
	 * 

* public void run() { * setScanColor(Color.WHITE); * ... * } *

* * @param color the new scan arc color * @see #setColors(Color, Color, Color) * @see #setColors(Color, Color, Color, Color, Color) * @see #setAllColors(Color) * @see #setBodyColor(Color) * @see #setGunColor(Color) * @see #setRadarColor(Color) * @see #setBulletColor(Color) * @see Color * @since 1.1.2 */ public void setScanColor(Color color) { if (peer != null) { peer.setScanColor(color); } else { uninitializedException(); } } /** * Immediately stops all movement, and saves it for a call to * {@link #resume()}. If there is already movement saved from a previous * stop, this will have no effect. *

* This method is equivalent to {@code #stop(false)}. * * @see #resume() * @see #stop(boolean) */ public void stop() { stop(false); } /** * Immediately stops all movement, and saves it for a call to * {@link #resume()}. If there is already movement saved from a previous * stop, you can overwrite it by calling {@code stop(true)}. * * @param overwrite If there is already movement saved from a previous stop, * you can overwrite it by calling {@code stop(true)}. * @see #resume() * @see #stop() */ public void stop(boolean overwrite) { if (peer != null) { ((IStandardRobotPeer) peer).stop(overwrite); } else { uninitializedException(); } } /** * Immediately resumes the movement you stopped by {@link #stop()}, if any. *

* This call executes immediately, and does not return until it is complete. * * @see #stop() * @see #stop(boolean) */ public void resume() { if (peer != null) { ((IStandardRobotPeer) peer).resume(); } else { uninitializedException(); } } /** * Immediately turns the robot's gun to the left by degrees. *

* This call executes immediately, and does not return until it is complete, * i.e. when the angle remaining in the gun's turn is 0. *

* Note that both positive and negative values can be given as input, * where negative values means that the robot's gun is set to turn right * instead of left. *

* Example: *

	 *   // Turn the robot's gun 180 degrees to the left
	 *   turnGunLeft(180);
	 * 

* // Afterwards, turn the robot's gun 90 degrees to the right * turnGunLeft(-90); *

* * @param degrees the amount of degrees to turn the robot's gun to the left. * If {@code degrees} > 0 the robot's gun will turn left. * If {@code degrees} < 0 the robot's gun will turn right. * If {@code degrees} = 0 the robot's gun will not turn, but execute. * @see #turnGunRight(double) * @see #turnLeft(double) * @see #turnRight(double) * @see #turnRadarLeft(double) * @see #turnRadarRight(double) * @see #setAdjustGunForRobotTurn(boolean) */ public void turnGunLeft(double degrees) { if (peer != null) { peer.turnGun(-Math.toRadians(degrees)); } else { uninitializedException(); } } /** * Immediately turns the robot's gun to the right by degrees. * This call executes immediately, and does not return until it is complete, * i.e. when the angle remaining in the gun's turn is 0. *

* Note that both positive and negative values can be given as input, * where negative values means that the robot's gun is set to turn left * instead of right. *

* Example: *

	 *   // Turn the robot's gun 180 degrees to the right
	 *   turnGunRight(180);
	 * 

* // Afterwards, turn the robot's gun 90 degrees to the left * turnGunRight(-90); *

* * @param degrees the amount of degrees to turn the robot's gun to the right. * If {@code degrees} > 0 the robot's gun will turn right. * If {@code degrees} < 0 the robot's gun will turn left. * If {@code degrees} = 0 the robot's gun will not turn, but execute. * @see #turnGunLeft(double) * @see #turnLeft(double) * @see #turnRight(double) * @see #turnRadarLeft(double) * @see #turnRadarRight(double) * @see #setAdjustGunForRobotTurn(boolean) */ public void turnGunRight(double degrees) { if (peer != null) { peer.turnGun(Math.toRadians(degrees)); } else { uninitializedException(); } } /** * Immediately turns the robot's radar to the left by degrees. *

* This call executes immediately, and does not return until it is complete, * i.e. when the angle remaining in the radar's turn is 0. *

* Note that both positive and negative values can be given as input, * where negative values means that the robot's radar is set to turn right * instead of left. *

* Example: *

	 *   // Turn the robot's radar 180 degrees to the left
	 *   turnRadarLeft(180);
	 * 

* // Afterwards, turn the robot's radar 90 degrees to the right * turnRadarLeft(-90); *

* * @param degrees the amount of degrees to turn the robot's radar to the left. * If {@code degrees} > 0 the robot's radar will turn left. * If {@code degrees} < 0 the robot's radar will turn right. * If {@code degrees} = 0 the robot's radar will not turn, but execute. * @see #turnRadarRight(double) * @see #turnLeft(double) * @see #turnRight(double) * @see #turnGunLeft(double) * @see #turnGunRight(double) * @see #setAdjustRadarForRobotTurn(boolean) * @see #setAdjustRadarForGunTurn(boolean) */ public void turnRadarLeft(double degrees) { if (peer != null) { ((IStandardRobotPeer) peer).turnRadar(-Math.toRadians(degrees)); } else { uninitializedException(); } } /** * Immediately turns the robot's radar to the right by degrees. * This call executes immediately, and does not return until it is complete, * i.e. when the angle remaining in the radar's turn is 0. *

* Note that both positive and negative values can be given as input, * where negative values means that the robot's radar is set to turn left * instead of right. *

* Example: *

	 *   // Turn the robot's radar 180 degrees to the right
	 *   turnRadarRight(180);
	 * 

* // Afterwards, turn the robot's radar 90 degrees to the left * turnRadarRight(-90); *

* * @param degrees the amount of degrees to turn the robot's radar to the right. * If {@code degrees} > 0 the robot's radar will turn right. * If {@code degrees} < 0 the robot's radar will turn left. * If {@code degrees} = 0 the robot's radar will not turn, but execute. * @see #turnRadarLeft(double) * @see #turnLeft(double) * @see #turnRight(double) * @see #turnGunLeft(double) * @see #turnGunRight(double) * @see #setAdjustRadarForRobotTurn(boolean) * @see #setAdjustRadarForGunTurn(boolean) */ public void turnRadarRight(double degrees) { if (peer != null) { ((IStandardRobotPeer) peer).turnRadar(Math.toRadians(degrees)); } else { uninitializedException(); } } /** * Returns the robot's current energy. * * @return the robot's current energy. */ public double getEnergy() { if (peer != null) { return peer.getEnergy(); } uninitializedException(); return 0; // never called } /** * Returns a graphics context used for painting graphical items for the robot. *

* This method is very useful for debugging your robot. *

* Note that the robot will only be painted if the "Paint" is enabled on the * robot's console window; otherwise the robot will never get painted (the * reason being that all robots might have graphical items that must be * painted, and then you might not be able to tell what graphical items that * have been painted for your robot). *

* Also note that the coordinate system for the graphical context where you * paint items fits for the Robocode coordinate system where (0, 0) is at * the bottom left corner of the battlefield, where X is towards right and Y * is upwards. * * @return a graphics context used for painting graphical items for the robot. * @see #onPaint(Graphics2D) * @since 1.6.1 */ public Graphics2D getGraphics() { if (peer != null) { return peer.getGraphics(); } uninitializedException(); return null; // never called } /** * Sets the debug property with the specified key to the specified value. *

* This method is very useful when debugging or reviewing your robot as you * will be able to see this property displayed in the robot console for your * robots under the Debug Properties tab page. * * @param key the name/key of the debug property. * @param value the new value of the debug property, where {@code null} or * the empty string is used for removing this debug property. * @since 1.6.2 */ public void setDebugProperty(String key, String value) { if (peer != null) { peer.setDebugProperty(key, value); return; } uninitializedException(); } /** * {@inheritDoc} */ public void onPaint(Graphics2D g) {} /** * {@inheritDoc} */ public void onKeyPressed(KeyEvent e) {} /** * {@inheritDoc} */ public void onKeyReleased(KeyEvent e) {} /** * {@inheritDoc} */ public void onKeyTyped(KeyEvent e) {} /** * {@inheritDoc} */ public void onMouseClicked(MouseEvent e) {} /** * {@inheritDoc} */ public void onMouseEntered(MouseEvent e) {} /** * {@inheritDoc} */ public void onMouseExited(MouseEvent e) {} /** * {@inheritDoc} */ public void onMousePressed(MouseEvent e) {} /** * {@inheritDoc} */ public void onMouseReleased(MouseEvent e) {} /** * {@inheritDoc} */ public void onMouseMoved(MouseEvent e) {} /** * {@inheritDoc} */ public void onMouseDragged(MouseEvent e) {} /** * {@inheritDoc} */ public void onMouseWheelMoved(MouseWheelEvent e) {} /** * {@inheritDoc} */ public void onStatus(StatusEvent e) {} } robocode/robocode/robocode/KeyEvent.java0000644000175000017500000000265311130241112017621 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode; /** * Super class of all events that originates from the keyboard. * * @author Pavel Savara (original) * @since 1.6.1 */ public abstract class KeyEvent extends Event { private static final long serialVersionUID = 1L; private final java.awt.event.KeyEvent source; /** * Called by the game to create a new KeyEvent. * * @param source the source key event originating from the AWT. */ public KeyEvent(java.awt.event.KeyEvent source) { this.source = source; } /** * Do not call this method! *

* This method is used by the game to determine the type of the source key * event that occurred in the AWT. * * @return the source key event that originates from the AWT. */ public java.awt.event.KeyEvent getSourceEvent() { return source; } } robocode/robocode/robocode/BattleEndedEvent.java0000644000175000017500000000550011130241114021240 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode; import robocode.peer.RobotStatics; import robocode.robotinterfaces.IBasicEvents; import robocode.robotinterfaces.IBasicEvents2; import robocode.robotinterfaces.IBasicRobot; import java.awt.*; /** * A BattleEndedEvent is sent to {@link Robot#onBattleEnded(BattleEndedEvent) * onBattleEnded()} when the battle is ended. * You can use the information contained in this event to determine if the * battle was aborted and also get the results of the battle. * * @author Pavel Savara (original) * @see BattleResults * @see Robot#onBattleEnded(BattleEndedEvent) * @since 1.6.1 */ public final class BattleEndedEvent extends Event { private static final long serialVersionUID = 1L; private final static int DEFAULT_PRIORITY = 100; // System event -> cannot be changed!; private final boolean aborted; private final BattleResults results; /** * Called by the game to create a new BattleEndedEvent. * * @param aborted {@code true} if the battle was aborted; {@code false} otherwise. * @param results the battle results */ public BattleEndedEvent(boolean aborted, BattleResults results) { this.aborted = aborted; this.results = results; } /** * Checks if this battle was aborted. * * @return {@code true} if the battle was aborted; {@code false} otherwise. */ public boolean isAborted() { return aborted; } /** * Returns the battle results. * * @return the battle results. */ public BattleResults getResults() { return results; } /** * {@inheritDoc} */ @Override final int getDefaultPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override public final int getPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override final void dispatch(IBasicRobot robot, RobotStatics statics, Graphics2D graphics) { if (robot != null) { IBasicEvents listener = robot.getBasicEventListener(); if (listener != null && IBasicEvents2.class.isAssignableFrom(listener.getClass())) { ((IBasicEvents2) listener).onBattleEnded(this); } } } /** * {@inheritDoc} */ @Override final boolean isCriticalEvent() { return true; } } robocode/robocode/robocode/CustomEvent.java0000644000175000017500000000727311130241114020350 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Updated Javadocs *******************************************************************************/ package robocode; import robocode.peer.RobotStatics; import robocode.robotinterfaces.IAdvancedEvents; import robocode.robotinterfaces.IAdvancedRobot; import robocode.robotinterfaces.IBasicRobot; import java.awt.*; /** * This event is sent to {@link AdvancedRobot#onCustomEvent(CustomEvent) * onCustomEvent()} when a custom condition is met. Be sure to reset or remove * the custom condition to avoid having it recurring repeatedly (see the * example for the {@link #getCondition()} method. * * @author Mathew A. Nelson (original) * @see #getCondition() */ public class CustomEvent extends Event { private static final long serialVersionUID = 1L; private static final int DEFAULT_PRIORITY = 80; private final Condition condition; /** * Called by the game to create a new CustomEvent when a condition is met. * * @param condition the condition that must be met */ public CustomEvent(Condition condition) { this.condition = condition; } /** * Called by the game to create a new CustomEvent when a condition is met. * The event will have the given priority. * An event priority is a value from 0 - 99. The higher value, the higher * priority. The default priority is 80. *

* This is equivalent to calling {@link Condition#setPriority(int)} on the * Condition. * * @param condition the condition that must be met * @param priority the priority of the condition */ public CustomEvent(Condition condition, int priority) { this.condition = condition; setPriority(priority); if (condition != null) { condition.setPriority(getPriority()); } } /** * Returns the condition that fired, causing this event to be generated. * Use this to determine which condition fired, and to remove the custom * event. *

	 *   public void onCustomEvent(CustomEvent event) {
	 *       if (event.getCondition().getName().equals("mycondition")) {
	 *           removeCustomEvent(event.getCondition());
	 *           // do something else
	 *       }
	 *   }
	 * 
* * @return the condition that fired, causing this event to be generated */ public Condition getCondition() { return condition; } /** * {@inheritDoc} */ @Override final int getDefaultPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override final void dispatch(IBasicRobot robot, RobotStatics statics, Graphics2D graphics) { if (statics.isAdvancedRobot()) { IAdvancedEvents listener = ((IAdvancedRobot) robot).getAdvancedEventListener(); if (listener != null) { listener.onCustomEvent(this); } } } /** * {@inheritDoc} */ @Override // final to disable overrides public final int compareTo(Event event) { return super.compareTo(event); } /** * {@inheritDoc} */ @Override // final to disable overrides final boolean isCriticalEvent() { return false; } /** * {@inheritDoc} */ @Override // final to disable overrides public final int getPriority() { return super.getPriority(); } } robocode/robocode/robocode/dialog/0000755000175000017500000000000011124143410016462 5ustar lambylambyrobocode/robocode/robocode/dialog/RobotDescriptionPanel.java0000644000175000017500000001573011130241114023601 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Matthew Reeder * - Added keyboard mnemonics to buttons * Flemming N. Larsen * - Code cleanup *******************************************************************************/ package robocode.dialog; import robocode.manager.BrowserManager; import robocode.repository.FileSpecification; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.net.URL; import java.util.StringTokenizer; /** * @author Mathew A. Nelson (original) * @author Matthew Reeder (contributor) * @author Flemming N. Larsen (contributor) */ @SuppressWarnings("serial") public class RobotDescriptionPanel extends JPanel { private JLabel robotNameLabel; private final JLabel[] descriptionLabel = new JLabel[3]; private JPanel descriptionPanel; private JButton detailsButton; private JLabel robocodeVersionLabel; private JLabel filePathLabel; private FileSpecification currentRobotSpecification; private final static String BLANK_STRING = " "; private final EventHandler eventHandler = new EventHandler(); private class EventHandler implements ActionListener { public void actionPerformed(ActionEvent e) { if (e.getSource() == getDetailsButton()) { if (currentRobotSpecification != null) { URL htmlFile = currentRobotSpecification.getWebpage(); if (htmlFile != null && htmlFile.toString().length() > 0) { try { BrowserManager.openURL(htmlFile.toString()); } catch (IOException ignored) {} } } } } } public RobotDescriptionPanel() { super(); initialize(); } private JLabel getFilePathLabel() { if (filePathLabel == null) { filePathLabel = new JLabel(); filePathLabel.setText(" "); } return filePathLabel; } private JLabel getDescriptionLabel(int index) { if (descriptionLabel[index] == null) { descriptionLabel[index] = new JLabel(); descriptionLabel[index].setFont(new Font("Monospaced", Font.PLAIN, 10)); descriptionLabel[index].setHorizontalAlignment(SwingConstants.LEFT); descriptionLabel[index].setText(BLANK_STRING); } return descriptionLabel[index]; } private JPanel getDescriptionPanel() { if (descriptionPanel == null) { descriptionPanel = new JPanel(); descriptionPanel.setAlignmentY(Component.CENTER_ALIGNMENT); descriptionPanel.setLayout(new BoxLayout(descriptionPanel, BoxLayout.Y_AXIS)); descriptionPanel.setBorder(BorderFactory.createEtchedBorder()); for (int i = 0; i < 3; i++) { descriptionPanel.add(getDescriptionLabel(i)); } } return descriptionPanel; } private JButton getDetailsButton() { if (detailsButton == null) { detailsButton = new JButton("Webpage"); detailsButton.setMnemonic('W'); detailsButton.setVisible(false); detailsButton.setAlignmentY(Component.CENTER_ALIGNMENT); detailsButton.addActionListener(eventHandler); } return detailsButton; } private JLabel getRobocodeVersionLabel() { if (robocodeVersionLabel == null) { robocodeVersionLabel = new JLabel(); } return robocodeVersionLabel; } private JLabel getRobotNameLabel() { if (robotNameLabel == null) { robotNameLabel = new JLabel(); robotNameLabel.setHorizontalAlignment(SwingConstants.CENTER); robotNameLabel.setText(" "); } return robotNameLabel; } private void initialize() { setLayout(new BorderLayout()); JPanel p = new JPanel(); p.setLayout(new BorderLayout()); p.add(getRobotNameLabel(), BorderLayout.CENTER); JPanel q = new JPanel(); q.setLayout(new FlowLayout(FlowLayout.CENTER, 1, 1)); q.add(getRobocodeVersionLabel()); p.add(q, BorderLayout.EAST); q = new JPanel(); q.setLayout(new FlowLayout(FlowLayout.CENTER, 1, 1)); p.add(q, BorderLayout.WEST); add(p, BorderLayout.NORTH); p = new JPanel(); p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); p.add(getDetailsButton()); add(p, BorderLayout.WEST); p = new JPanel(); p.setLayout(new FlowLayout(FlowLayout.CENTER, 1, 1)); p.add(getDescriptionPanel()); // ,BorderLayout.CENTER); add(p, BorderLayout.CENTER); p = new JPanel(); p.setLayout(new FlowLayout(FlowLayout.CENTER, 1, 1)); p.add(getFilePathLabel()); add(p, BorderLayout.SOUTH); p = new JPanel(); p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); // new add(p, BorderLayout.EAST); } public void showDescription(FileSpecification robotSpecification) { this.currentRobotSpecification = robotSpecification; if (robotSpecification == null) { getRobotNameLabel().setText(" "); for (int i = 0; i < 3; i++) { getDescriptionLabel(i).setText(BLANK_STRING); } getDetailsButton().setVisible(false); getRobocodeVersionLabel().setText(" "); getFilePathLabel().setText(" "); } else { String name = robotSpecification.getNameManager().getUniqueFullClassNameWithVersion(); if (name.charAt(name.length() - 1) == '*') { name = name.substring(0, name.length() - 1) + " (development version)"; } String s = robotSpecification.getAuthorName(); if (s != null && s.length() > 0) { name += " by " + s; } getRobotNameLabel().setText(name); if (robotSpecification.getJarFile() != null) { getFilePathLabel().setText(robotSpecification.getJarFile().getPath()); } else { getFilePathLabel().setText(robotSpecification.getFilePath()); } String desc = robotSpecification.getDescription(); int count = 0; if (desc != null) { StringTokenizer tok = new StringTokenizer(desc, "\n"); while (tok.hasMoreTokens() && count < 3) { String line = tok.nextToken(); if (line != null) { if (line.length() > BLANK_STRING.length()) { line = line.substring(0, BLANK_STRING.length()); } for (int i = line.length(); i < BLANK_STRING.length(); i++) { line += " "; } getDescriptionLabel(count).setText(line); } count++; } } for (int i = count; i < 3; i++) { getDescriptionLabel(i).setText(BLANK_STRING); } URL u = robotSpecification.getWebpage(); getDetailsButton().setVisible(u != null && u.toString().length() > 0); String v = robotSpecification.getRobocodeVersion(); getRobocodeVersionLabel().setText(v == null ? "" : "Built for " + v); } getDescriptionPanel().setMaximumSize(getDescriptionPanel().getPreferredSize()); } } robocode/robocode/robocode/dialog/WizardListener.java0000644000175000017500000000143311130241112022267 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation *******************************************************************************/ package robocode.dialog; /** * @author Mathew A. Nelson (original) */ public interface WizardListener { public void cancelButtonActionPerformed(); public void finishButtonActionPerformed(); } robocode/robocode/robocode/dialog/AvailableRobotsPanel.java0000644000175000017500000003113411130241114023355 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup * - Ported to Java 5 * - Replaced FileSpecificationVector with plain Vector * - Replaced synchronizedList on lists for availableRobots, robotList, and * availablePackages with a CopyOnWriteArrayList in order to prevent * ConcurrentModificationExceptions when accessing these list via * Iterators using public methods to this class * - Changed the F5 key press for refreshing the list of available robots * into 'shortcut key' + R to comply with other OSes like e.g. Mac OS * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap *******************************************************************************/ package robocode.dialog; import robocode.repository.FileSpecification; import robocode.repository.TeamSpecification; import robocode.ui.ShortcutUtil; import javax.swing.*; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Robert D. Maupin (contributor) */ @SuppressWarnings("serial") public class AvailableRobotsPanel extends JPanel { private final List availableRobots = new CopyOnWriteArrayList(); private List robotList = new CopyOnWriteArrayList(); private final List availablePackages = new CopyOnWriteArrayList(); private JScrollPane availableRobotsScrollPane; private JList availableRobotsList; private final JButton actionButton; private final JList actionList; private JList availablePackagesList; private JScrollPane availablePackagesScrollPane; private RobotNameCellRenderer robotNamesCellRenderer; private final RobotSelectionPanel robotSelectionPanel; private final String title; private final EventHandler eventHandler = new EventHandler(); public AvailableRobotsPanel(JButton actionButton, String title, JList actionList, RobotSelectionPanel robotSelectionPanel) { super(); this.title = title; this.actionButton = actionButton; this.actionList = actionList; this.robotSelectionPanel = robotSelectionPanel; initialize(); } private void initialize() { setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), title)); setLayout(new BorderLayout()); JPanel top = new JPanel(); top.setLayout(new GridLayout(1, 2)); JPanel a = new JPanel(); a.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), "Packages")); a.setLayout(new BorderLayout()); a.add(getAvailablePackagesScrollPane()); a.setPreferredSize(new Dimension(120, 100)); top.add(a); JPanel b = new JPanel(); b.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), "Robots")); b.setLayout(new BorderLayout()); b.add(getAvailableRobotsScrollPane()); b.setPreferredSize(new Dimension(120, 100)); top.add(b); add(top, BorderLayout.CENTER); JLabel refreshLabel = new JLabel("Press " + ShortcutUtil.getModifierKeyText() + "+R to refresh"); refreshLabel.setHorizontalAlignment(SwingConstants.CENTER); add(refreshLabel, BorderLayout.SOUTH); } public List getAvailableRobots() { return availableRobots; } public List getRobotList() { return robotList; } public List getSelectedRobots() { List selected = new ArrayList(); for (int i : getAvailableRobotsList().getSelectedIndices()) { selected.add(availableRobots.get(i)); } return selected; } /** * Return the availableRobotsList. * * @return JList */ public JList getAvailableRobotsList() { if (availableRobotsList == null) { availableRobotsList = new JList(); availableRobotsList.setModel(new AvailableRobotsModel()); availableRobotsList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); robotNamesCellRenderer = new RobotNameCellRenderer(); availableRobotsList.setCellRenderer(robotNamesCellRenderer); MouseListener mouseListener = new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { // This does not work in Linux under IBM JRE 1.3.0... if (e.getClickCount() >= 2) { if (e.getClickCount() % 2 == 0) { if (actionButton != null) { actionButton.doClick(); } } } } }; availableRobotsList.addMouseListener(mouseListener); availableRobotsList.addListSelectionListener(eventHandler); } return availableRobotsList; } /** * Return the JScrollPane1 property value. * * @return JScrollPane */ private JScrollPane getAvailableRobotsScrollPane() { if (availableRobotsScrollPane == null) { availableRobotsScrollPane = new JScrollPane(); availableRobotsScrollPane.setViewportView(getAvailableRobotsList()); } return availableRobotsScrollPane; } public void setRobotList(List robotListList) { robotList = robotListList; SwingUtilities.invokeLater(new Runnable() { public void run() { availablePackages.clear(); availableRobots.clear(); if (robotList == null) { robotList = new CopyOnWriteArrayList(); availablePackages.add("One moment please..."); ((AvailablePackagesModel) getAvailablePackagesList().getModel()).changed(); getAvailablePackagesList().clearSelection(); ((AvailableRobotsModel) getAvailableRobotsList().getModel()).changed(); } else { availablePackages.add("(All)"); String packageName; for (FileSpecification robotSpec : robotList) { packageName = robotSpec.getFullPackage(); if (packageName == null) { continue; } if (!availablePackages.contains(packageName)) { availablePackages.add(packageName); } } availablePackages.add("(No package)"); for (FileSpecification robotSpec : robotList) { availableRobots.add(robotSpec); } ((AvailablePackagesModel) getAvailablePackagesList().getModel()).changed(); getAvailablePackagesList().setSelectedIndex(0); ((AvailableRobotsModel) getAvailableRobotsList().getModel()).changed(); getAvailablePackagesList().requestFocus(); } } }); } private void availablePackagesListSelectionChanged() { int sel[] = getAvailablePackagesList().getSelectedIndices(); availableRobots.clear(); if (sel.length == 1) { robotNamesCellRenderer.setUseShortNames(true); getAvailablePackagesList().scrollRectToVisible(getAvailablePackagesList().getCellBounds(sel[0], sel[0])); } else { robotNamesCellRenderer.setUseShortNames(false); } for (int element : sel) { String selectedPackage = availablePackages.get(element); if (selectedPackage.equals("(All)")) { robotNamesCellRenderer.setUseShortNames(false); availableRobots.clear(); for (FileSpecification aRobotList : robotList) { availableRobots.add(aRobotList); } break; } // Single package. for (FileSpecification robotSpecification : robotList) { if (robotSpecification.getFullPackage() == null) { if (selectedPackage.equals("(No package)")) { availableRobots.add(robotSpecification); } } else if (robotSpecification.getFullPackage().equals(selectedPackage)) { availableRobots.add(robotSpecification); } } } ((AvailableRobotsModel) getAvailableRobotsList().getModel()).changed(); if (availableRobots.size() > 0) { availableRobotsList.setSelectedIndex(0); availableRobotsListSelectionChanged(); } } private void availableRobotsListSelectionChanged() { int sel[] = getAvailableRobotsList().getSelectedIndices(); if (sel.length == 1) { if (actionList != null) { actionList.clearSelection(); } FileSpecification robotSpecification = (FileSpecification) getAvailableRobotsList().getModel().getElementAt( sel[0]); if (robotSelectionPanel != null) { robotSelectionPanel.showDescription(robotSpecification); } } else { if (robotSelectionPanel != null) { robotSelectionPanel.showDescription(null); } } } public void clearSelection() { getAvailableRobotsList().clearSelection(); ((AvailableRobotsModel) getAvailableRobotsList().getModel()).changed(); } /** * Return the availableRobotsList. * * @return JList */ private JList getAvailablePackagesList() { if (availablePackagesList == null) { availablePackagesList = new JList(); availablePackagesList.setModel(new AvailablePackagesModel()); availablePackagesList.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); availablePackagesList.addListSelectionListener(eventHandler); } return availablePackagesList; } /** * Return the availablePackagesScrollPane * * @return JScrollPane */ private JScrollPane getAvailablePackagesScrollPane() { if (availablePackagesScrollPane == null) { availablePackagesScrollPane = new JScrollPane(); availablePackagesScrollPane.setViewportView(getAvailablePackagesList()); } return availablePackagesScrollPane; } private class EventHandler implements ListSelectionListener { public void valueChanged(ListSelectionEvent e) { if (e.getValueIsAdjusting()) { return; } if (e.getSource() == getAvailableRobotsList()) { availableRobotsListSelectionChanged(); } else if (e.getSource() == getAvailablePackagesList()) { availablePackagesListSelectionChanged(); } } } private class AvailablePackagesModel extends AbstractListModel { public void changed() { fireContentsChanged(this, 0, getSize()); } public int getSize() { return availablePackages.size(); } public String getElementAt(int which) { return availablePackages.get(which); } } private class AvailableRobotsModel extends AbstractListModel { public void changed() { fireContentsChanged(this, 0, getSize()); } public int getSize() { return availableRobots.size(); } public FileSpecification getElementAt(int which) { return availableRobots.get(which); } } private static class RobotNameCellRenderer extends JLabel implements ListCellRenderer { private boolean useShortNames = false; public RobotNameCellRenderer() { setOpaque(true); } public void setUseShortNames(boolean useShortNames) { this.useShortNames = useShortNames; } public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { setComponentOrientation(list.getComponentOrientation()); if (isSelected) { setBackground(list.getSelectionBackground()); setForeground(list.getSelectionForeground()); } else { setBackground(list.getBackground()); setForeground(list.getForeground()); } if (useShortNames && value instanceof FileSpecification) { FileSpecification fileSpecification = (FileSpecification) value; if (fileSpecification instanceof TeamSpecification) { setText("Team: " + fileSpecification.getNameManager().getUniqueShortClassNameWithVersion()); } else { setText(fileSpecification.getNameManager().getUniqueShortClassNameWithVersion()); } } else if (value instanceof FileSpecification) { FileSpecification fileSpecification = (FileSpecification) value; if (fileSpecification instanceof TeamSpecification) { setText("Team: " + fileSpecification.getNameManager().getUniqueFullClassNameWithVersion()); } else { setText(fileSpecification.getNameManager().getUniqueFullClassNameWithVersion()); } } else { setText(value.toString()); } setEnabled(list.isEnabled()); setFont(list.getFont()); return this; } } } robocode/robocode/robocode/dialog/RobocodeMenuBar.java0000644000175000017500000007506011130241114022340 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup * - Added menu items for Robocode API, Robo Wiki, Yahoo Group Robocode, * and Robocode Repository * - Updated to use methods from the WindowUtil, which replaces window methods * that have been (re)moved from the robocode.util.Utils class * - Changed menu shortcut keys to use getMenuShortcutKeyMask() instead of * Event.CTRL_MASK in order to comply with other OSes like e.g. Mac OS * - Added "Recalculate CPU constant" to the Options menu * - Added "Clean Robot Cache" to the Options menu * Matthew Reeder * - Added keyboard mnemonics and a few accelerators to all menus and menu * items * Luis Crespo & Flemming N. Larsen * - Added check box menu item for "Show Rankings" *******************************************************************************/ package robocode.dialog; import robocode.manager.IBattleManager; import robocode.manager.RobocodeManager; import robocode.manager.RobocodeProperties; import robocode.recording.BattleRecordFormat; import static robocode.ui.ShortcutUtil.MENU_SHORTCUT_KEY_MASK; import javax.swing.*; import javax.swing.event.MenuEvent; import javax.swing.event.MenuListener; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; /** * Handles menu display and interaction for Robocode. * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Matthew Reeder (contributor) * @author Luis Crespo (contributor) */ @SuppressWarnings("serial") public class RobocodeMenuBar extends JMenuBar { // Battle menu private JMenu battleMenu; private JMenuItem battleNewMenuItem; private JMenuItem battleOpenMenuItem; private JMenuItem battleSaveMenuItem; private JMenuItem battleSaveAsMenuItem; private JMenuItem battleExitMenuItem; private JMenuItem battleOpenRecordMenuItem; private JMenuItem battleSaveRecordAsMenuItem; private JMenuItem battleExportRecordMenuItem; private JMenuItem battleImportRecordMenuItem; // Robot menu private JMenu robotMenu; private JMenuItem robotEditorMenuItem; private JMenuItem robotImportMenuItem; private JMenuItem robotPackagerMenuItem; private JMenuItem robotCreateTeamMenuItem; // Options menu private JMenu optionsMenu; private JMenuItem optionsPreferencesMenuItem; private JMenuItem optionsFitWindowMenuItem; private JCheckBoxMenuItem optionsShowRankingCheckBoxMenuItem; private JMenuItem optionsRecalculateCpuConstantMenuItem; private JMenuItem optionsCleanRobotCacheMenuItem; // Help Menu private JMenu helpMenu; private JMenuItem helpOnlineHelpMenuItem; private JMenuItem helpCheckForNewVersionMenuItem; private JMenuItem helpVersionsTxtMenuItem; private JMenuItem helpRobocodeApiMenuItem; private JMenuItem helpJavaDocumentationMenuItem; private JMenuItem helpFaqMenuItem; private JMenuItem helpAboutMenuItem; private JMenuItem helpRobocodeMenuItem; private JMenuItem helpRoboWikiMenuItem; private JMenuItem helpYahooGroupRobocodeMenuItem; private JMenuItem helpRobocodeRepositoryMenuItem; private final RobocodeFrame robocodeFrame; private final RobocodeManager manager; private class EventHandler implements ActionListener, MenuListener { public void actionPerformed(ActionEvent e) { Object source = e.getSource(); RobocodeMenuBar mb = RobocodeMenuBar.this; // Battle menu if (source == mb.getBattleNewMenuItem()) { battleNewActionPerformed(); } else if (source == mb.getBattleOpenMenuItem()) { battleOpenActionPerformed(); } else if (source == mb.getBattleSaveMenuItem()) { battleSaveActionPerformed(); } else if (source == mb.getBattleSaveAsMenuItem()) { battleSaveAsActionPerformed(); } else if (source == mb.getBattleOpenRecordMenuItem()) { battleOpenRecordActionPerformed(); } else if (source == mb.getBattleImportRecordMenuItem()) { battleImportRecordActionPerformed(); } else if (source == mb.getBattleSaveRecordAsMenuItem()) { battleSaveRecordAsActionPerformed(); } else if (source == mb.getBattleExportRecordMenuItem()) { battleExportRecordActionPerformed(); } else if (source == mb.getBattleExitMenuItem()) { battleExitActionPerformed(); // Robot Editor menu } else if (source == mb.getRobotEditorMenuItem()) { robotEditorActionPerformed(); } else if (source == mb.getRobotImportMenuItem()) { robotImportActionPerformed(); } else if (source == mb.getRobotPackagerMenuItem()) { robotPackagerActionPerformed(); // Team / Create Team menu } else if (source == mb.getRobotCreateTeamMenuItem()) { teamCreateTeamActionPerformed(); // Options / Preferences menu } else if (source == mb.getOptionsPreferencesMenuItem()) { optionsPreferencesActionPerformed(); } else if (source == mb.getOptionsFitWindowMenuItem()) { optionsFitWindowActionPerformed(); } else if (source == mb.getOptionsShowRankingCheckBoxMenuItem()) { optionsShowRankingActionPerformed(); } else if (source == mb.getOptionsRecalculateCpuConstantMenuItem()) { optionsRecalculateCpuConstantPerformed(); } else if (source == mb.getOptionsCleanRobotCacheMenuItem()) { optionsCleanRobotCachePerformed(); // Help menu } else if (source == mb.getHelpOnlineHelpMenuItem()) { helpOnlineHelpActionPerformed(); } else if (source == mb.getHelpRobocodeApiMenuItem()) { helpRobocodeApiActionPerformed(); } else if (source == mb.getHelpJavaDocumentationMenuItem()) { helpJavaDocumentationActionPerformed(); } else if (source == mb.getHelpFaqMenuItem()) { helpFaqActionPerformed(); } else if (source == mb.getHelpRobocodeMenuItem()) { helpRobocodeHomeMenuItemActionPerformed(); } else if (source == mb.getHelpRoboWikiMenuItem()) { helpRoboWikiMenuItemActionPerformed(); } else if (source == mb.getHelpYahooGroupRobocodeMenuItem()) { helpYahooGroupRobocodeActionPerformed(); } else if (source == mb.getHelpRobocodeRepositoryMenuItem()) { helpRobocodeRepositoryActionPerformed(); } else if (source == mb.getHelpCheckForNewVersionMenuItem()) { helpCheckForNewVersionActionPerformed(); } else if (source == mb.getHelpVersionsTxtMenuItem()) { helpVersionsTxtActionPerformed(); } else if (source == mb.getHelpAboutMenuItem()) { helpAboutActionPerformed(); } } public void menuDeselected(MenuEvent e) { manager.getBattleManager().resumeBattle(); } public void menuSelected(MenuEvent e) { manager.getBattleManager().pauseBattle(); } public void menuCanceled(MenuEvent e) {} } public final RobocodeMenuBar.EventHandler eventHandler = new EventHandler(); public RobocodeMenuBar(RobocodeManager manager, RobocodeFrame robocodeFrame) { super(); this.manager = manager; this.robocodeFrame = robocodeFrame; add(getBattleMenu()); add(getRobotMenu()); add(getOptionsMenu()); add(getHelpMenu()); } private void battleExitActionPerformed() { robocodeFrame.dispose(); } /** * Handle battleNew menu item action */ private void battleNewActionPerformed() { manager.getWindowManager().showNewBattleDialog(manager.getBattleManager().getBattleProperties()); } private void battleOpenActionPerformed() { IBattleManager battleManager = manager.getBattleManager(); try { battleManager.pauseBattle(); String path = manager.getWindowManager().showBattleOpenDialog(".battle", "Battles"); if (path != null) { battleManager.setBattleFilename(path); manager.getWindowManager().showNewBattleDialog(battleManager.loadBattleProperties()); } } finally { battleManager.resumeBattle(); } } private void battleSaveActionPerformed() { IBattleManager battleManager = manager.getBattleManager(); try { battleManager.pauseBattle(); String path = battleManager.getBattleFilename(); if (path == null) { path = manager.getWindowManager().saveBattleDialog(battleManager.getBattlePath(), ".battle", "Battles"); } if (path != null) { battleManager.setBattleFilename(path); battleManager.saveBattleProperties(); } } finally { battleManager.resumeBattle(); } } private void battleSaveAsActionPerformed() { IBattleManager battleManager = manager.getBattleManager(); try { battleManager.pauseBattle(); String path = manager.getWindowManager().saveBattleDialog(battleManager.getBattlePath(), ".battle", "Battles"); if (path != null) { battleManager.setBattleFilename(path); battleManager.saveBattleProperties(); } } finally { battleManager.resumeBattle(); } } private void battleOpenRecordActionPerformed() { IBattleManager battleManager = manager.getBattleManager(); try { battleManager.pauseBattle(); String path = manager.getWindowManager().showBattleOpenDialog(".br", "Records"); if (path != null) { manager.getBattleManager().stop(true); robocodeFrame.getReplayButton().setVisible(true); robocodeFrame.getReplayButton().setEnabled(true); getBattleSaveRecordAsMenuItem().setEnabled(true); getBattleExportRecordMenuItem().setEnabled(true); try { robocodeFrame.setBusyPointer(true); manager.getRecordManager().loadRecord(path, BattleRecordFormat.BINARY_ZIP); } finally { robocodeFrame.setBusyPointer(false); } battleManager.replay(); } } finally { battleManager.resumeBattle(); } } private void battleImportRecordActionPerformed() { IBattleManager battleManager = manager.getBattleManager(); try { battleManager.pauseBattle(); String path = manager.getWindowManager().showBattleOpenDialog(".br.xml", "XML Records"); if (path != null) { manager.getBattleManager().stop(true); robocodeFrame.getReplayButton().setVisible(true); robocodeFrame.getReplayButton().setEnabled(true); getBattleSaveRecordAsMenuItem().setEnabled(true); getBattleExportRecordMenuItem().setEnabled(true); try { robocodeFrame.setBusyPointer(true); manager.getRecordManager().loadRecord(path, BattleRecordFormat.XML); } finally { robocodeFrame.setBusyPointer(false); } battleManager.replay(); } } finally { battleManager.resumeBattle(); } } private void battleSaveRecordAsActionPerformed() { IBattleManager battleManager = manager.getBattleManager(); if (manager.getRecordManager().hasRecord()) { try { battleManager.pauseBattle(); String path = manager.getWindowManager().saveBattleDialog(battleManager.getBattlePath(), ".br", "Records"); if (path != null) { try { robocodeFrame.setBusyPointer(true); manager.getRecordManager().saveRecord(path, BattleRecordFormat.BINARY_ZIP); } finally { robocodeFrame.setBusyPointer(false); } } } finally { battleManager.resumeBattle(); } } } private void battleExportRecordActionPerformed() { IBattleManager battleManager = manager.getBattleManager(); if (manager.getRecordManager().hasRecord()) { try { battleManager.pauseBattle(); String path = manager.getWindowManager().saveBattleDialog(battleManager.getBattlePath(), ".br.xml", "XML Records"); if (path != null) { try { robocodeFrame.setBusyPointer(true); manager.getRecordManager().saveRecord(path, BattleRecordFormat.XML); } finally { robocodeFrame.setBusyPointer(false); } } } finally { battleManager.resumeBattle(); } } } private JMenuItem getBattleExitMenuItem() { if (battleExitMenuItem == null) { battleExitMenuItem = new JMenuItem(); battleExitMenuItem.setText("Exit"); battleExitMenuItem.setMnemonic('x'); battleExitMenuItem.setDisplayedMnemonicIndex(1); battleExitMenuItem.addActionListener(eventHandler); } return battleExitMenuItem; } public JMenu getBattleMenu() { if (battleMenu == null) { battleMenu = new JMenu(); battleMenu.setText("Battle"); battleMenu.setMnemonic('B'); battleMenu.add(getBattleNewMenuItem()); battleMenu.add(getBattleOpenMenuItem()); battleMenu.add(new JSeparator()); battleMenu.add(getBattleSaveMenuItem()); battleMenu.add(getBattleSaveAsMenuItem()); battleMenu.add(new JSeparator()); battleMenu.add(getBattleOpenRecordMenuItem()); battleMenu.add(getBattleSaveRecordAsMenuItem()); battleMenu.add(getBattleImportRecordMenuItem()); battleMenu.add(getBattleExportRecordMenuItem()); battleMenu.add(new JSeparator()); battleMenu.add(getBattleExitMenuItem()); battleMenu.addMenuListener(eventHandler); } return battleMenu; } private JMenuItem getBattleNewMenuItem() { if (battleNewMenuItem == null) { battleNewMenuItem = new JMenuItem(); battleNewMenuItem.setText("New"); battleNewMenuItem.setMnemonic('N'); battleNewMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, MENU_SHORTCUT_KEY_MASK, false)); battleNewMenuItem.addActionListener(eventHandler); } return battleNewMenuItem; } private JMenuItem getBattleOpenMenuItem() { if (battleOpenMenuItem == null) { battleOpenMenuItem = new JMenuItem(); battleOpenMenuItem.setText("Open"); battleOpenMenuItem.setMnemonic('O'); battleOpenMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, MENU_SHORTCUT_KEY_MASK, false)); battleOpenMenuItem.addActionListener(eventHandler); } return battleOpenMenuItem; } public JMenuItem getBattleSaveAsMenuItem() { if (battleSaveAsMenuItem == null) { battleSaveAsMenuItem = new JMenuItem(); battleSaveAsMenuItem.setText("Save As"); battleSaveAsMenuItem.setMnemonic('A'); battleSaveAsMenuItem.setDisplayedMnemonicIndex(5); battleSaveAsMenuItem.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_S, MENU_SHORTCUT_KEY_MASK | InputEvent.SHIFT_MASK, false)); battleSaveAsMenuItem.setEnabled(false); battleSaveAsMenuItem.addActionListener(eventHandler); } return battleSaveAsMenuItem; } public JMenuItem getBattleSaveMenuItem() { if (battleSaveMenuItem == null) { battleSaveMenuItem = new JMenuItem(); battleSaveMenuItem.setText("Save"); battleSaveMenuItem.setMnemonic('S'); battleSaveMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, MENU_SHORTCUT_KEY_MASK, false)); battleSaveMenuItem.setEnabled(false); battleSaveMenuItem.addActionListener(eventHandler); } return battleSaveMenuItem; } private JMenuItem getBattleOpenRecordMenuItem() { if (battleOpenRecordMenuItem == null) { battleOpenRecordMenuItem = new JMenuItem(); battleOpenRecordMenuItem.setText("Open Record"); battleOpenRecordMenuItem.setMnemonic('d'); battleOpenRecordMenuItem.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_O, MENU_SHORTCUT_KEY_MASK | InputEvent.SHIFT_MASK, false)); battleOpenRecordMenuItem.addActionListener(eventHandler); } return battleOpenRecordMenuItem; } private JMenuItem getBattleImportRecordMenuItem() { if (battleImportRecordMenuItem == null) { battleImportRecordMenuItem = new JMenuItem(); battleImportRecordMenuItem.setText("Import XML Record"); battleImportRecordMenuItem.setMnemonic('I'); battleImportRecordMenuItem.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_I, MENU_SHORTCUT_KEY_MASK, false)); battleImportRecordMenuItem.addActionListener(eventHandler); } return battleImportRecordMenuItem; } public JMenuItem getBattleSaveRecordAsMenuItem() { if (battleSaveRecordAsMenuItem == null) { battleSaveRecordAsMenuItem = new JMenuItem(); battleSaveRecordAsMenuItem.setText("Save Record"); battleSaveRecordAsMenuItem.setMnemonic('R'); battleSaveRecordAsMenuItem.setDisplayedMnemonicIndex(5); battleSaveRecordAsMenuItem.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_R, MENU_SHORTCUT_KEY_MASK, false)); battleSaveRecordAsMenuItem.setEnabled(false); battleSaveRecordAsMenuItem.addActionListener(eventHandler); RobocodeProperties props = manager.getProperties(); props.addPropertyListener(props.new PropertyListener() { @Override public void enableReplayRecordingChanged(boolean enabled) { final boolean canReplayRecord = manager.getRecordManager().hasRecord(); final boolean enableSaveRecord = enabled & canReplayRecord; battleSaveRecordAsMenuItem.setEnabled(enableSaveRecord); } }); } return battleSaveRecordAsMenuItem; } public JMenuItem getBattleExportRecordMenuItem() { if (battleExportRecordMenuItem == null) { battleExportRecordMenuItem = new JMenuItem(); battleExportRecordMenuItem.setText("Export XML Record"); battleExportRecordMenuItem.setMnemonic('E'); battleExportRecordMenuItem.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_X, MENU_SHORTCUT_KEY_MASK, false)); battleExportRecordMenuItem.setEnabled(false); battleExportRecordMenuItem.addActionListener(eventHandler); RobocodeProperties props = manager.getProperties(); props.addPropertyListener(props.new PropertyListener() { @Override public void enableReplayRecordingChanged(boolean enabled) { final boolean canReplayRecord = manager.getRecordManager().hasRecord(); final boolean enableSaveRecord = enabled & canReplayRecord; battleExportRecordMenuItem.setEnabled(enableSaveRecord); } }); } return battleExportRecordMenuItem; } private JMenuItem getHelpAboutMenuItem() { if (helpAboutMenuItem == null) { helpAboutMenuItem = new JMenuItem(); helpAboutMenuItem.setText("About"); helpAboutMenuItem.setMnemonic('A'); helpAboutMenuItem.addActionListener(eventHandler); } return helpAboutMenuItem; } private JMenuItem getHelpCheckForNewVersionMenuItem() { if (helpCheckForNewVersionMenuItem == null) { helpCheckForNewVersionMenuItem = new JMenuItem(); helpCheckForNewVersionMenuItem.setText("Check for new version"); helpCheckForNewVersionMenuItem.setMnemonic('C'); helpCheckForNewVersionMenuItem.addActionListener(eventHandler); } return helpCheckForNewVersionMenuItem; } @Override public JMenu getHelpMenu() { if (helpMenu == null) { helpMenu = new JMenu(); helpMenu.setText("Help"); helpMenu.setMnemonic('H'); helpMenu.add(getHelpOnlineHelpMenuItem()); helpMenu.add(getHelpRobocodeApiMenuItem()); helpMenu.add(getHelpRoboWikiMenuItem()); helpMenu.add(getHelpYahooGroupRobocodeMenuItem()); helpMenu.add(getHelpFaqMenuItem()); helpMenu.add(new JSeparator()); helpMenu.add(getHelpRobocodeMenuItem()); helpMenu.add(getHelpRobocodeRepositoryMenuItem()); helpMenu.add(new JSeparator()); helpMenu.add(getHelpJavaDocumentationMenuItem()); helpMenu.add(new JSeparator()); helpMenu.add(getHelpCheckForNewVersionMenuItem()); helpMenu.add(getHelpVersionsTxtMenuItem()); helpMenu.add(new JSeparator()); helpMenu.add(getHelpAboutMenuItem()); helpMenu.addMenuListener(eventHandler); } return helpMenu; } private JMenuItem getHelpFaqMenuItem() { if (helpFaqMenuItem == null) { helpFaqMenuItem = new JMenuItem(); helpFaqMenuItem.setText("Robocode FAQ"); helpFaqMenuItem.setMnemonic('F'); helpFaqMenuItem.setDisplayedMnemonicIndex(9); helpFaqMenuItem.addActionListener(eventHandler); } return helpFaqMenuItem; } private JMenuItem getHelpOnlineHelpMenuItem() { if (helpOnlineHelpMenuItem == null) { helpOnlineHelpMenuItem = new JMenuItem(); helpOnlineHelpMenuItem.setText("Online help"); helpOnlineHelpMenuItem.setMnemonic('O'); helpOnlineHelpMenuItem.addActionListener(eventHandler); } return helpOnlineHelpMenuItem; } private JMenuItem getHelpVersionsTxtMenuItem() { if (helpVersionsTxtMenuItem == null) { helpVersionsTxtMenuItem = new JMenuItem(); helpVersionsTxtMenuItem.setText("Version info"); helpVersionsTxtMenuItem.setMnemonic('V'); helpVersionsTxtMenuItem.addActionListener(eventHandler); } return helpVersionsTxtMenuItem; } private JMenuItem getHelpRobocodeApiMenuItem() { if (helpRobocodeApiMenuItem == null) { helpRobocodeApiMenuItem = new JMenuItem(); helpRobocodeApiMenuItem.setText("Robocode API"); helpRobocodeApiMenuItem.setMnemonic('I'); helpRobocodeApiMenuItem.setDisplayedMnemonicIndex(11); helpRobocodeApiMenuItem.addActionListener(eventHandler); } return helpRobocodeApiMenuItem; } private JMenuItem getHelpRobocodeMenuItem() { if (helpRobocodeMenuItem == null) { helpRobocodeMenuItem = new JMenuItem(); helpRobocodeMenuItem.setText("Robocode home page"); helpRobocodeMenuItem.setMnemonic('H'); helpRobocodeMenuItem.setDisplayedMnemonicIndex(9); helpRobocodeMenuItem.addActionListener(eventHandler); } return helpRobocodeMenuItem; } private JMenuItem getHelpJavaDocumentationMenuItem() { if (helpJavaDocumentationMenuItem == null) { helpJavaDocumentationMenuItem = new JMenuItem(); helpJavaDocumentationMenuItem.setText("Java 5.0 documentation"); helpJavaDocumentationMenuItem.setMnemonic('J'); helpJavaDocumentationMenuItem.addActionListener(eventHandler); } return helpJavaDocumentationMenuItem; } private JMenuItem getHelpRoboWikiMenuItem() { if (helpRoboWikiMenuItem == null) { helpRoboWikiMenuItem = new JMenuItem(); helpRoboWikiMenuItem.setText("RoboWiki site"); helpRoboWikiMenuItem.setMnemonic('W'); helpRoboWikiMenuItem.setDisplayedMnemonicIndex(4); helpRoboWikiMenuItem.addActionListener(eventHandler); } return helpRoboWikiMenuItem; } private JMenuItem getHelpYahooGroupRobocodeMenuItem() { if (helpYahooGroupRobocodeMenuItem == null) { helpYahooGroupRobocodeMenuItem = new JMenuItem(); helpYahooGroupRobocodeMenuItem.setText("Yahoo Group for Robocode"); helpYahooGroupRobocodeMenuItem.setMnemonic('Y'); helpYahooGroupRobocodeMenuItem.addActionListener(eventHandler); } return helpYahooGroupRobocodeMenuItem; } private JMenuItem getHelpRobocodeRepositoryMenuItem() { if (helpRobocodeRepositoryMenuItem == null) { helpRobocodeRepositoryMenuItem = new JMenuItem(); helpRobocodeRepositoryMenuItem.setText("Robocode Repository"); helpRobocodeRepositoryMenuItem.setMnemonic('R'); helpRobocodeRepositoryMenuItem.setDisplayedMnemonicIndex(9); helpRobocodeRepositoryMenuItem.addActionListener(eventHandler); } return helpRobocodeRepositoryMenuItem; } private JMenuItem getOptionsFitWindowMenuItem() { if (optionsFitWindowMenuItem == null) { optionsFitWindowMenuItem = new JMenuItem(); optionsFitWindowMenuItem.setText("Default window size"); optionsFitWindowMenuItem.setMnemonic('D'); optionsFitWindowMenuItem.addActionListener(eventHandler); } return optionsFitWindowMenuItem; } public JCheckBoxMenuItem getOptionsShowRankingCheckBoxMenuItem() { if (optionsShowRankingCheckBoxMenuItem == null) { optionsShowRankingCheckBoxMenuItem = new JCheckBoxMenuItem(); optionsShowRankingCheckBoxMenuItem.setText("Show current rankings"); optionsShowRankingCheckBoxMenuItem.setMnemonic('r'); optionsShowRankingCheckBoxMenuItem.setDisplayedMnemonicIndex(13); optionsShowRankingCheckBoxMenuItem.addActionListener(eventHandler); optionsShowRankingCheckBoxMenuItem.setEnabled(false); } return optionsShowRankingCheckBoxMenuItem; } private JMenuItem getOptionsRecalculateCpuConstantMenuItem() { if (optionsRecalculateCpuConstantMenuItem == null) { optionsRecalculateCpuConstantMenuItem = new JMenuItem(); optionsRecalculateCpuConstantMenuItem.setText("Recalculate CPU constant"); optionsRecalculateCpuConstantMenuItem.setMnemonic('e'); optionsRecalculateCpuConstantMenuItem.setDisplayedMnemonicIndex(1); optionsRecalculateCpuConstantMenuItem.addActionListener(eventHandler); } return optionsRecalculateCpuConstantMenuItem; } private JMenuItem getOptionsCleanRobotCacheMenuItem() { if (optionsCleanRobotCacheMenuItem == null) { optionsCleanRobotCacheMenuItem = new JMenuItem(); optionsCleanRobotCacheMenuItem.setText("Clean robot cache"); optionsCleanRobotCacheMenuItem.setMnemonic('C'); optionsCleanRobotCacheMenuItem.addActionListener(eventHandler); } return optionsCleanRobotCacheMenuItem; } private JMenu getOptionsMenu() { if (optionsMenu == null) { optionsMenu = new JMenu(); optionsMenu.setText("Options"); optionsMenu.setMnemonic('O'); optionsMenu.add(getOptionsPreferencesMenuItem()); optionsMenu.add(getOptionsFitWindowMenuItem()); optionsMenu.add(new JSeparator()); optionsMenu.add(getOptionsShowRankingCheckBoxMenuItem()); optionsMenu.add(new JSeparator()); optionsMenu.add(getOptionsRecalculateCpuConstantMenuItem()); optionsMenu.add(getOptionsCleanRobotCacheMenuItem()); optionsMenu.addMenuListener(eventHandler); } return optionsMenu; } private JMenuItem getOptionsPreferencesMenuItem() { if (optionsPreferencesMenuItem == null) { optionsPreferencesMenuItem = new JMenuItem(); optionsPreferencesMenuItem.setText("Preferences"); optionsPreferencesMenuItem.setMnemonic('P'); optionsPreferencesMenuItem.addActionListener(eventHandler); } return optionsPreferencesMenuItem; } private JMenuItem getRobotEditorMenuItem() { if (robotEditorMenuItem == null) { robotEditorMenuItem = new JMenuItem(); robotEditorMenuItem.setText("Editor"); robotEditorMenuItem.setMnemonic('E'); robotEditorMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E, MENU_SHORTCUT_KEY_MASK, false)); robotEditorMenuItem.addActionListener(eventHandler); } return robotEditorMenuItem; } private JMenuItem getRobotImportMenuItem() { if (robotImportMenuItem == null) { robotImportMenuItem = new JMenuItem(); robotImportMenuItem.setText("Import downloaded robot"); robotImportMenuItem.setMnemonic('I'); robotImportMenuItem.addActionListener(eventHandler); } return robotImportMenuItem; } public JMenu getRobotMenu() { if (robotMenu == null) { robotMenu = new JMenu(); robotMenu.setText("Robot"); robotMenu.setMnemonic('R'); robotMenu.add(getRobotEditorMenuItem()); robotMenu.add(new JSeparator()); robotMenu.add(getRobotImportMenuItem()); robotMenu.add(getRobotPackagerMenuItem()); robotMenu.add(new JSeparator()); robotMenu.add(getRobotCreateTeamMenuItem()); robotMenu.addMenuListener(eventHandler); } return robotMenu; } private JMenuItem getRobotPackagerMenuItem() { if (robotPackagerMenuItem == null) { robotPackagerMenuItem = new JMenuItem(); robotPackagerMenuItem.setText("Package robot for upload"); robotPackagerMenuItem.setMnemonic('P'); robotPackagerMenuItem.addActionListener(eventHandler); } return robotPackagerMenuItem; } private JMenuItem getRobotCreateTeamMenuItem() { if (robotCreateTeamMenuItem == null) { robotCreateTeamMenuItem = new JMenuItem(); robotCreateTeamMenuItem.setText("Create a robot team"); robotCreateTeamMenuItem.setMnemonic('C'); robotCreateTeamMenuItem.addActionListener(eventHandler); } return robotCreateTeamMenuItem; } private void teamCreateTeamActionPerformed() { manager.getWindowManager().showCreateTeamDialog(); } private void helpAboutActionPerformed() { manager.getWindowManager().showAboutBox(); } private void helpCheckForNewVersionActionPerformed() { manager.getVersionManager().checkForNewVersion(true); } private void helpFaqActionPerformed() { manager.getWindowManager().showFaq(); } private void helpOnlineHelpActionPerformed() { manager.getWindowManager().showOnlineHelp(); } private void helpVersionsTxtActionPerformed() { manager.getWindowManager().showVersionsTxt(); } private void helpRobocodeApiActionPerformed() { manager.getWindowManager().showHelpApi(); } private void helpRobocodeHomeMenuItemActionPerformed() { manager.getWindowManager().showRobocodeHome(); } private void helpJavaDocumentationActionPerformed() { manager.getWindowManager().showJavaDocumentation(); } private void helpRoboWikiMenuItemActionPerformed() { manager.getWindowManager().showRoboWiki(); } private void helpYahooGroupRobocodeActionPerformed() { manager.getWindowManager().showYahooGroupRobocode(); } private void helpRobocodeRepositoryActionPerformed() { manager.getWindowManager().showRobocodeRepository(); } private void optionsFitWindowActionPerformed() { WindowUtil.fitWindow(manager.getWindowManager().getRobocodeFrame()); } private void optionsShowRankingActionPerformed() { manager.getWindowManager().showRankingDialog(getOptionsShowRankingCheckBoxMenuItem().getState()); } private void optionsRecalculateCpuConstantPerformed() { int ok = JOptionPane.showConfirmDialog(this, "Do you want to recalculate the CPU constant?", "Recalculate CPU constant", JOptionPane.YES_NO_OPTION); if (ok == JOptionPane.YES_OPTION) { try { robocodeFrame.setBusyPointer(true); manager.getCpuManager().calculateCpuConstant(); } finally { robocodeFrame.setBusyPointer(false); } long cpuConstant = manager.getCpuManager().getCpuConstant(); JOptionPane.showMessageDialog(this, "CPU constant: " + cpuConstant + " nanoseconds per turn", "New CPU constant", JOptionPane.INFORMATION_MESSAGE); } } private void optionsCleanRobotCachePerformed() { int ok = JOptionPane.showConfirmDialog(this, "Do you want to clean the robot cache?", "Clean Robot Cache", JOptionPane.YES_NO_OPTION); if (ok == JOptionPane.YES_OPTION) { try { robocodeFrame.setBusyPointer(true); ar.robocode.cachecleaner.CacheCleaner.clean(); } finally { robocodeFrame.setBusyPointer(false); } } } private void optionsPreferencesActionPerformed() { manager.getWindowManager().showOptionsPreferences(); } private void robotEditorActionPerformed() { manager.getWindowManager().showRobocodeEditor(); } private void robotImportActionPerformed() { manager.getWindowManager().showImportRobotDialog(); } private void robotPackagerActionPerformed() { manager.getWindowManager().showRobotPackager(); } } robocode/robocode/robocode/dialog/ResultsTableCellRenderer.java0000644000175000017500000000357011130241114024227 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Removed from the robocode.dialog.ResultsDialog into a file of it's own * - Cleanup *******************************************************************************/ package robocode.dialog; import javax.swing.*; import javax.swing.border.EtchedBorder; import javax.swing.table.DefaultTableCellRenderer; import java.awt.*; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ @SuppressWarnings("serial") public class ResultsTableCellRenderer extends DefaultTableCellRenderer { private final boolean isBordered; public ResultsTableCellRenderer(boolean isBordered) { super(); this.isBordered = isBordered; setHorizontalAlignment(SwingConstants.CENTER); setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0)); } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { if (isBordered) { setBorder(new EtchedBorder(EtchedBorder.RAISED)); setBackground(SystemColor.menu); setForeground(SystemColor.menuText); } else if (isSelected) { setBackground(SystemColor.textHighlight); setForeground(SystemColor.textHighlightText); } else { setBackground(SystemColor.text); setForeground(SystemColor.textText); } setText(value.toString()); return this; } } robocode/robocode/robocode/dialog/NewBattleBattleFieldTab.java0000644000175000017500000001210111130241114023731 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Totally rewritten *******************************************************************************/ package robocode.dialog; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ @SuppressWarnings("serial") public class NewBattleBattleFieldTab extends JPanel { private final static int MIN_SIZE = 400; private final static int MAX_SIZE = 5000; private final static int STEP_SIZE = 100; private final EventHandler eventHandler = new EventHandler(); private final SizeButton[] sizeButtons = { new SizeButton(400, 400), new SizeButton(600, 400), new SizeButton(600, 600), new SizeButton(800, 600), new SizeButton(800, 800), new SizeButton(1000, 800), new SizeButton(1000, 1000), new SizeButton(1200, 1200), new SizeButton(2000, 2000), new SizeButton(5000, 5000) }; private final JSlider battleFieldWidthSlider = createBattleFieldWidthSlider(); private final JSlider battleFieldHeightSlider = createBattleFieldHeightSlider(); private final JLabel battleFieldSizeLabel = createBattleFieldSizeLabel(); public NewBattleBattleFieldTab() { super(); JPanel sliderPanel = createSliderPanel(); add(sliderPanel); JPanel buttonsPanel = createButtonsPanel(); add(buttonsPanel); } public int getBattleFieldWidth() { return battleFieldWidthSlider.getValue(); } public void setBattleFieldWidth(int width) { battleFieldWidthSlider.setValue(width); battleFieldSliderValuesChanged(); } public int getBattleFieldHeight() { return battleFieldHeightSlider.getValue(); } public void setBattleFieldHeight(int height) { battleFieldHeightSlider.setValue(height); battleFieldSliderValuesChanged(); } private JPanel createButtonsPanel() { JPanel panel = new JPanel(); panel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Default Sizes")); panel.setLayout(new GridLayout(sizeButtons.length, 1)); for (SizeButton button : sizeButtons) { panel.add(button); } return panel; } private JPanel createSliderPanel() { JPanel panel = new JPanel(); panel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Battlefield Size")); // We want the BorderLayout to put the vertical scrollbar // to the right of the horizontal one... so small hack: panel.setLayout(new BorderLayout()); panel.add(battleFieldHeightSlider, BorderLayout.EAST); JPanel subPanel = new JPanel(); subPanel.setLayout(new BorderLayout()); subPanel.add(battleFieldWidthSlider, BorderLayout.SOUTH); subPanel.add(battleFieldSizeLabel, BorderLayout.CENTER); panel.add(subPanel, BorderLayout.CENTER); return panel; } private JSlider createBattleFieldWidthSlider() { JSlider slider = new JSlider(); slider.setMinimum(MIN_SIZE); slider.setMaximum(MAX_SIZE); slider.setMajorTickSpacing(STEP_SIZE); slider.setSnapToTicks(true); slider.addChangeListener(eventHandler); return slider; } private JSlider createBattleFieldHeightSlider() { JSlider slider = createBattleFieldWidthSlider(); slider.setOrientation(SwingConstants.VERTICAL); return slider; } private JLabel createBattleFieldSizeLabel() { JLabel label = new JLabel(); label.setHorizontalAlignment(SwingConstants.CENTER); return label; } private void battleFieldSliderValuesChanged() { int w = battleFieldWidthSlider.getValue(); int h = battleFieldHeightSlider.getValue(); battleFieldSizeLabel.setText(w + " x " + h); } private class SizeButton extends JButton { final int width; final int height; public SizeButton(int width, int height) { super(width + "x" + height); this.width = width; this.height = height; addActionListener(eventHandler); } } private class EventHandler implements ActionListener, ChangeListener { public void actionPerformed(ActionEvent e) { if (e.getSource() instanceof SizeButton) { SizeButton button = (SizeButton) e.getSource(); battleFieldWidthSlider.setValue(button.width); battleFieldHeightSlider.setValue(button.height); battleFieldSliderValuesChanged(); } } public void stateChanged(ChangeEvent e) { if ((e.getSource() == battleFieldWidthSlider) || (e.getSource() == battleFieldHeightSlider)) { battleFieldSliderValuesChanged(); } } } } robocode/robocode/robocode/dialog/NewBattleDialog.java0000644000175000017500000002136711130241114022340 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Matthew Reeder * - Added keyboard mnemonics to buttons and tabs * Flemming N. Larsen * - Code cleanup * - Replaced FileSpecificationVector with plain Vector * - Changed the F5 key press for refreshing the list of available robots * into 'modifier key' + R to comply with other OSes like e.g. Mac OS * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap *******************************************************************************/ package robocode.dialog; import robocode.battle.BattleProperties; import robocode.manager.RobocodeManager; import static robocode.ui.ShortcutUtil.MENU_SHORTCUT_KEY_MASK; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.util.List; /** * @author Mathew A. Nelson (original) * @author Matthew Reeder (contributor) * @author Flemming N. Larsen (contributor) * @author Robert D. Maupin (contributor) */ @SuppressWarnings("serial") public class NewBattleDialog extends JDialog implements WizardListener { private final static int MAX_ROBOTS = 256; // 64; private final static int MIN_ROBOTS = 1; private final EventHandler eventHandler = new EventHandler(); private JPanel newBattleDialogContentPane; private WizardTabbedPane tabbedPane; private NewBattleBattleFieldTab battleFieldTab; private final BattleProperties battleProperties; private NewBattleRulesTab rulesTab; private WizardController wizardController; private RobotSelectionPanel robotSelectionPanel; private final RobocodeManager manager; public NewBattleDialog(RobocodeManager manager, BattleProperties battleProperties) { super(manager.getWindowManager().getRobocodeFrame(), true); this.manager = manager; this.battleProperties = battleProperties; initialize(); } public void cancelButtonActionPerformed() { dispose(); } public void finishButtonActionPerformed() { if (robotSelectionPanel.getSelectedRobotsCount() > 24) { if (JOptionPane.showConfirmDialog(this, "Warning: The battle you are about to start (" + robotSelectionPanel.getSelectedRobotsCount() + " robots) " + " is very large and will consume a lot of CPU and memory. Do you wish to proceed?", "Large Battle Warning", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.NO_OPTION) { return; } } if (robotSelectionPanel.getSelectedRobotsCount() == 1) { if (JOptionPane.showConfirmDialog(this, "You have only selected one robot. For normal battles you should select at least 2.\nDo you wish to proceed anyway?", "Just one robot?", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.NO_OPTION) { return; } } battleProperties.setSelectedRobots(robotSelectionPanel.getSelectedRobotsAsString()); battleProperties.setBattlefieldWidth(getBattleFieldTab().getBattleFieldWidth()); battleProperties.setBattlefieldHeight(getBattleFieldTab().getBattleFieldHeight()); battleProperties.setNumRounds(getRobotSelectionPanel().getNumRounds()); battleProperties.setGunCoolingRate(getRulesTab().getGunCoolingRate()); battleProperties.setInactivityTime(getRulesTab().getInactivityTime()); // Dispose this dialog before starting the battle due to pause/resume battle state dispose(); // Start new battle after the dialog has been disposed and hence has called resumeBattle() manager.getBattleManager().startNewBattle(battleProperties, false); } /** * Return the battleFieldTab * * @return JPanel */ private NewBattleBattleFieldTab getBattleFieldTab() { if (battleFieldTab == null) { battleFieldTab = new NewBattleBattleFieldTab(); } return battleFieldTab; } /** * Return the newBattleDialogContentPane * * @return JPanel */ private JPanel getNewBattleDialogContentPane() { if (newBattleDialogContentPane == null) { newBattleDialogContentPane = new JPanel(); newBattleDialogContentPane.setLayout(new BorderLayout()); newBattleDialogContentPane.add(getWizardController(), BorderLayout.SOUTH); newBattleDialogContentPane.add(getTabbedPane(), BorderLayout.CENTER); newBattleDialogContentPane.registerKeyboardAction(eventHandler, "Refresh", KeyStroke.getKeyStroke(KeyEvent.VK_R, MENU_SHORTCUT_KEY_MASK), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); } return newBattleDialogContentPane; } /** * Return the rulesTab property value. * * @return robocode.dialog.NewBattleRulesTab */ private NewBattleRulesTab getRulesTab() { if (rulesTab == null) { rulesTab = new robocode.dialog.NewBattleRulesTab(); } return rulesTab; } public List getSelectedRobots() { return getRobotSelectionPanel().getSelectedRobots(); } /** * Initialize the class. */ private void initialize() { setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); setTitle("New Battle"); setContentPane(getNewBattleDialogContentPane()); addCancelByEscapeKey(); battleProperties.setNumRounds(manager.getProperties().getNumberOfRounds()); processBattleProperties(); } private void addCancelByEscapeKey() { String CANCEL_ACTION_KEY = "CANCEL_ACTION_KEY"; int noModifiers = 0; KeyStroke escapeKey = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, noModifiers, false); InputMap inputMap = getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); inputMap.put(escapeKey, CANCEL_ACTION_KEY); AbstractAction cancelAction = new AbstractAction() { public void actionPerformed(ActionEvent e) { cancelButtonActionPerformed(); } }; getRootPane().getActionMap().put(CANCEL_ACTION_KEY, cancelAction); } /** * Return the wizardController * * @return JButton */ private WizardController getWizardController() { if (wizardController == null) { wizardController = getTabbedPane().getWizardController(); wizardController.setFinishButtonTextAndMnemonic("Start Battle", 'S', 0); wizardController.setFocusOnEnabled(true); } return wizardController; } /** * Return the Page property value. * * @return JPanel */ private RobotSelectionPanel getRobotSelectionPanel() { if (robotSelectionPanel == null) { String selectedRobots = ""; if (battleProperties != null) { selectedRobots = battleProperties.getSelectedRobots(); } robotSelectionPanel = new RobotSelectionPanel(manager, MIN_ROBOTS, MAX_ROBOTS, true, "Select robots for the battle", false, false, false, false, false, !manager.getProperties().getOptionsTeamShowTeamRobots(), selectedRobots); } return robotSelectionPanel; } /** * Return the tabbedPane. * * @return JTabbedPane */ private WizardTabbedPane getTabbedPane() { if (tabbedPane == null) { tabbedPane = new WizardTabbedPane(this); tabbedPane.insertTab("Robots", null, getRobotSelectionPanel(), null, 0); tabbedPane.setMnemonicAt(0, KeyEvent.VK_R); tabbedPane.setDisplayedMnemonicIndexAt(0, 0); tabbedPane.insertTab("BattleField", null, getBattleFieldTab(), null, 1); tabbedPane.setMnemonicAt(1, KeyEvent.VK_F); tabbedPane.setDisplayedMnemonicIndexAt(1, 6); tabbedPane.insertTab("Rules", null, getRulesTab(), null, 2); tabbedPane.setMnemonicAt(2, KeyEvent.VK_U); tabbedPane.setDisplayedMnemonicIndexAt(2, 1); } return tabbedPane; } private void processBattleProperties() { if (battleProperties == null) { return; } getBattleFieldTab().setBattleFieldWidth(battleProperties.getBattlefieldWidth()); getBattleFieldTab().setBattleFieldHeight(battleProperties.getBattlefieldHeight()); getRobotSelectionPanel().setNumRounds(battleProperties.getNumRounds()); getRulesTab().setGunCoolingRate(battleProperties.getGunCoolingRate()); getRulesTab().setInactivityTime(battleProperties.getInactivityTime()); } private class EventHandler extends WindowAdapter implements ActionListener { public void actionPerformed(ActionEvent e) { if (e.getActionCommand().equals("Refresh")) { getRobotSelectionPanel().refreshRobotList(true); } } } } robocode/robocode/robocode/dialog/WindowUtil.java0000644000175000017500000001401311130241112021424 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Moved window related methods from robocode.util.Utils into this class * - Removed packCenterShow(Window main, Window window, boolean pack) *******************************************************************************/ package robocode.dialog; import javax.swing.*; import java.awt.*; import java.io.PrintWriter; /** * This is a class for window utilization. * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ public class WindowUtil { private static final Point origin = new Point(0, 0); private static final WindowPositionManager windowPositionManager = new WindowPositionManager(); private static JLabel statusLabel; private static PrintWriter statusWriter; private static JLabel defaultStatusLabel; public static void center(Window w) { WindowUtil.center(null, w); } public static void center(Window main, Window w) { WindowUtil.center(main, w, true); } public static void center(Window main, Window w, boolean move) { Point location = null; Dimension size = null; Rectangle windowRect = windowPositionManager.getWindowRect(w); if (windowRect != null) { location = new Point(windowRect.x, windowRect.y); size = new Dimension(windowRect.width, windowRect.height); } if (!move) { size = null; } if (location == null || size == null) { // Center a window Dimension screenSize; if (main != null) { screenSize = main.getSize(); } else { screenSize = Toolkit.getDefaultToolkit().getScreenSize(); } size = w.getSize(); if (size.height > screenSize.height - 20 || size.width > screenSize.width - 20) { // Keep aspect ratio for the robocode frame. if (w.getName().equals("RobocodeFrame")) { int shrink = size.width - screenSize.width + 20; if (size.height - screenSize.height + 20 > shrink) { shrink = size.height - screenSize.height + 20; } size.width -= shrink; size.height -= shrink; } else { if (size.height > screenSize.height - 20) { size.height = screenSize.height - 20; } if (size.width > screenSize.width - 20) { size.width = screenSize.width - 20; } } } if (main != null) { location = main.getLocation(); location.x += (screenSize.width - size.width) / 2; location.y += (screenSize.height - size.height) / 2; } else { location = new Point((screenSize.width - size.width) / 2, (screenSize.height - size.height) / 2); } } w.setSize(size); if (move) { w.setLocation(location); } } public static void centerShow(Window main, Window window) { center(main, window); window.setVisible(true); } public static void setFixedSize(JComponent component, Dimension size) { component.setPreferredSize(size); component.setMinimumSize(size); component.setMaximumSize(size); } public static void error(JFrame frame, String msg) { Object[] options = { "OK"}; JOptionPane.showOptionDialog(frame, msg, "Error", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE, null, options, options[0]); } public static void fitWindow(Window w) { // We don't want to receive the resize event for this pack! // ... yes we do! // w.removeComponentListener(windowPositionManager); w.pack(); center(null, w, false); } public static void packCenterShow(Window window) { // We don't want to receive the resize event for this pack! window.removeComponentListener(windowPositionManager); window.pack(); center(window); window.setVisible(true); } public static void packCenterShow(Window main, Window window) { // We don't want to receive the resize event for this pack! window.removeComponentListener(windowPositionManager); window.pack(); center(main, window); window.setVisible(true); } public static void packPlaceShow(Window window) { window.pack(); WindowUtil.place(window); window.setVisible(true); } public static void place(Window w) { // Center a window Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); Dimension size = w.getSize(); if (size.height > screenSize.height) { size.height = screenSize.height; } if (size.width > screenSize.width) { size.width = screenSize.width; } w.setLocation(origin); origin.y += 150; if (origin.y + size.height > screenSize.height) { origin.y = 0; origin.x += 40; } if (origin.x + size.width > screenSize.width) { origin.x = 0; } } public static void saveWindowPositions() { windowPositionManager.saveWindowPositions(); } public static void message(String s) { JOptionPane.showMessageDialog(null, s, "Message", JOptionPane.INFORMATION_MESSAGE); } public static void messageWarning(String s) { JOptionPane.showMessageDialog(null, s, "Warning", JOptionPane.WARNING_MESSAGE); } public static void messageError(String s) { JOptionPane.showMessageDialog(null, s, "Message", JOptionPane.ERROR_MESSAGE); } public static void setStatus(String s) { if (statusWriter != null) { statusWriter.println(s); } if (statusLabel != null) { statusLabel.setText(s); } else if (defaultStatusLabel != null) { defaultStatusLabel.setText(s); } } public static void setStatusLabel(JLabel label) { statusLabel = label; } public static void setDefaultStatusLabel(JLabel label) { defaultStatusLabel = label; } public static void setStatusWriter(PrintWriter out) { statusWriter = out; } } robocode/robocode/robocode/dialog/NewBattleRulesTab.java0000644000175000017500000000662311130241114022660 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup *******************************************************************************/ package robocode.dialog; import javax.swing.*; import java.awt.*; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ @SuppressWarnings("serial") public class NewBattleRulesTab extends JPanel { private JLabel gunCoolingRateLabel; private JTextField gunCoolingRateField; private JLabel inactivityTimeLabel; private JTextField inactivityTimeField; /** * NewBattleRulesTab constructor */ public NewBattleRulesTab() { super(); initialize(); } public double getGunCoolingRate() { return Double.parseDouble(getGunCoolingRateField().getText()); } /** * Return the gunRechargeRateField * * @return JTextField */ private JTextField getGunCoolingRateField() { if (gunCoolingRateField == null) { gunCoolingRateField = new JTextField(); } return gunCoolingRateField; } /** * Return the gunCoolingRateLabel * * @return JLabel */ private JLabel getGunCoolingRateLabel() { if (gunCoolingRateLabel == null) { gunCoolingRateLabel = new JLabel(); gunCoolingRateLabel.setAlignmentX(Component.RIGHT_ALIGNMENT); gunCoolingRateLabel.setText("Gun Cooling Rate:"); gunCoolingRateLabel.setHorizontalTextPosition(SwingConstants.CENTER); gunCoolingRateLabel.setHorizontalAlignment(SwingConstants.RIGHT); } return gunCoolingRateLabel; } public long getInactivityTime() { return Long.parseLong(getInactivityTimeField().getText()); } /** * Return the inactivityTimeField * * @return JTextField */ private JTextField getInactivityTimeField() { if (inactivityTimeField == null) { inactivityTimeField = new JTextField(); } return inactivityTimeField; } /** * Return the inactivityTimeLabel * * @return JLabel */ private JLabel getInactivityTimeLabel() { if (inactivityTimeLabel == null) { inactivityTimeLabel = new JLabel(); inactivityTimeLabel.setText("Inactivity Time:"); inactivityTimeLabel.setHorizontalAlignment(SwingConstants.RIGHT); } return inactivityTimeLabel; } /** * Initialize the class. */ private void initialize() { JPanel j = new JPanel(); j.setLayout(new GridLayout(4, 2, 5, 5)); j.setBorder(BorderFactory.createEtchedBorder()); j.add(getGunCoolingRateLabel(), getGunCoolingRateLabel().getName()); j.add(getGunCoolingRateField(), getGunCoolingRateField().getName()); j.add(getInactivityTimeLabel(), getInactivityTimeLabel().getName()); j.add(getInactivityTimeField(), getInactivityTimeField().getName()); add(j); } public void setGunCoolingRate(double gunCoolingRate) { getGunCoolingRateField().setText("" + gunCoolingRate); } public void setInactivityTime(long inactivityTime) { getInactivityTimeField().setText("" + inactivityTime); } } robocode/robocode/robocode/dialog/RobocodeFrame.java0000644000175000017500000006460211130241114022041 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup * - Added JPopupMenu.setDefaultLightWeightPopupEnabled(false), i.e. enabling * heavy-weight components in order to prevent battleview to hide menus * - Changed so BattleView handles resizing instead of the RobocodeFrame * - Added TPS slider + label * - Added "Replay" button in order to activate the replay feature * - Updated to use methods from ImageUtil, FileUtil, Logger, which replaces * methods that have been (re)moved from the robocode.util.Utils class * - Added missing close() on FileReader in loadVersionFile() * - Added support for mouse events * Matthew Reeder * - Added keyboard mnemonics to buttons * Luis Crespo * - Added debug step feature by adding a "Next Turn" button, and changing * the "Pause" button into a "Pause/Debug" button * Pavel Savara * - now driven by BattleObserver *******************************************************************************/ package robocode.dialog; import robocode.control.events.BattleAdaptor; import robocode.battleview.BattleView; import robocode.battleview.InteractiveHandler; import robocode.control.events.*; import robocode.control.snapshot.IRobotSnapshot; import robocode.control.snapshot.ITurnSnapshot; import robocode.gfx.ImageUtil; import robocode.io.FileUtil; import robocode.manager.*; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.*; import java.awt.event.*; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * @author Mathew Nelson (original) * @author Flemming N. Larsen (contributor) * @author Matthew Reeder (contributor) * @author Luis Crespo (contributor) * @author Pavel Savara (contributor) */ @SuppressWarnings("serial") public class RobocodeFrame extends JFrame { private final static int MAX_TPS = 10000; private final static int MAX_TPS_SLIDER_VALUE = 61; private final static int UPDATE_TITLE_INTERVAL = 500; // milliseconds private static final Cursor BUSY_CURSOR = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR); private static final Cursor DEFAULT_CURSOR = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR); private final EventHandler eventHandler = new EventHandler(); private BattleObserver battleObserver; private final InteractiveHandler interactiveHandler; private RobocodeMenuBar robocodeMenuBar; private JPanel robocodeContentPane; private JLabel statusLabel; private BattleView battleView; private JScrollPane robotButtonsScrollPane; private JPanel mainPanel; private JPanel battleViewPanel; private JPanel sidePanel; private JPanel robotButtonsPanel; private JToolBar toolBar; private JToggleButton pauseButton; private JButton nextTurnButton; private JButton stopButton; private JButton restartButton; private JButton replayButton; private JSlider tpsSlider; private JLabel tpsLabel; private boolean iconified; private boolean exitOnClose = true; private final RobocodeManager manager; private final IWindowManager windowManager; final List robotButtons = new ArrayList(); public RobocodeFrame(RobocodeManager manager) { super(); interactiveHandler = new InteractiveHandler(manager); this.windowManager = manager.getWindowManager(); this.manager = manager; initialize(); } protected void finalize() throws Throwable { try { manager.getWindowManager().removeBattleListener(battleObserver); } finally { super.finalize(); } } public void setBusyPointer(boolean enabled) { setCursor(enabled ? BUSY_CURSOR : DEFAULT_CURSOR); } public void addRobotButton(JButton b) { if (b instanceof RobotButton) { robotButtons.add((RobotButton) b); } getRobotButtonsPanel().add(b); b.setVisible(true); getRobotButtonsPanel().validate(); } public void runIntroBattle() { IBattleManager battleManager = manager.getBattleManager(); final File intro = new File(FileUtil.getCwd(), "battles/intro.battle"); if (intro.exists()) { battleManager.setBattleFilename(intro.getPath()); battleManager.loadBattleProperties(); boolean origShowResults = manager.getProperties().getOptionsCommonShowResults(); manager.getProperties().setOptionsCommonShowResults(false); battleManager.startNewBattle(battleManager.loadBattleProperties(), true); battleManager.setDefaultBattleProperties(); manager.getProperties().setOptionsCommonShowResults(origShowResults); restartButton.setEnabled(false); getRobotButtonsPanel().removeAll(); getRobotButtonsPanel().repaint(); } } /** * Called when the battle view is resized */ private void battleViewResized() { battleView.validate(); battleView.setInitialized(false); } /** * Rather than use a layout manager for the battleview panel, we just * calculate the proper aspect ratio and set the battleview's size. We could * use a layout manager if someone wants to write one... */ private void battleViewPanelResized() { battleView.setBounds(getBattleViewPanel().getBounds()); } /** * Return the BattleView. * * @return robocode.BattleView */ public BattleView getBattleView() { if (battleView == null) { battleView = new BattleView(manager); battleView.addComponentListener(eventHandler); } return battleView; } /** * Return the MainPanel (which contains the BattleView and the robot * buttons) * * @return JPanel */ private JPanel getMainPanel() { if (mainPanel == null) { mainPanel = new JPanel(); mainPanel.setLayout(new BorderLayout()); mainPanel.add(getSidePanel(), BorderLayout.EAST); mainPanel.add(getBattleViewPanel()); } return mainPanel; } /** * Return the BattleViewMainPanel (which contains the BattleView and a * spacer) * * @return JPanel */ private JPanel getBattleViewPanel() { if (battleViewPanel == null) { battleViewPanel = new JPanel(); battleViewPanel.setPreferredSize(new Dimension(800, 600)); battleViewPanel.setLayout(null); battleViewPanel.add(getBattleView()); battleViewPanel.addComponentListener(eventHandler); } return battleViewPanel; } /** * Return the JFrameContentPane. * * @return JPanel */ private JPanel getRobocodeContentPane() { if (robocodeContentPane == null) { robocodeContentPane = new JPanel(); robocodeContentPane.setLayout(new BorderLayout()); robocodeContentPane.add(getToolBar(), "South"); robocodeContentPane.add(getMainPanel(), "Center"); } return robocodeContentPane; } /** * Return the menu bar. * * @return JMenuBar */ public RobocodeMenuBar getRobocodeMenuBar() { if (robocodeMenuBar == null) { robocodeMenuBar = new RobocodeMenuBar(manager, this); } return robocodeMenuBar; } /** * Return the sidePanel. * * @return JPanel */ private JPanel getSidePanel() { if (sidePanel == null) { sidePanel = new JPanel(); sidePanel.setLayout(new BorderLayout()); sidePanel.add(getRobotButtonsScrollPane(), BorderLayout.CENTER); sidePanel.add(new BattleButton(manager.getRobotDialogManager(), true), BorderLayout.SOUTH); } return sidePanel; } /** * Return the robotButtons panel. * * @return JPanel */ private JPanel getRobotButtonsPanel() { if (robotButtonsPanel == null) { robotButtonsPanel = new JPanel(); robotButtonsPanel.setLayout(new BoxLayout(robotButtonsPanel, BoxLayout.Y_AXIS)); robotButtonsPanel.addContainerListener(eventHandler); } return robotButtonsPanel; } /** * Return the robotButtonsScrollPane * * @return JScrollPane */ private JScrollPane getRobotButtonsScrollPane() { if (robotButtonsScrollPane == null) { robotButtonsScrollPane = new JScrollPane(); robotButtonsScrollPane.setAutoscrolls(false); robotButtonsScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); robotButtonsScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); robotButtonsScrollPane.setAlignmentY(Component.TOP_ALIGNMENT); robotButtonsScrollPane.setMaximumSize(new Dimension(113, 32767)); robotButtonsScrollPane.setPreferredSize(new Dimension(113, 28)); robotButtonsScrollPane.setAlignmentX(Component.CENTER_ALIGNMENT); robotButtonsScrollPane.setMinimumSize(new Dimension(113, 53)); robotButtonsScrollPane.setViewportView(getRobotButtonsPanel()); } return robotButtonsScrollPane; } /** * Return the statusLabel * * @return JLabel */ public JLabel getStatusLabel() { if (statusLabel == null) { statusLabel = new JLabel(); statusLabel.setText(""); } return statusLabel; } /** * Return the pauseButton * * @return JToggleButton */ private JToggleButton getPauseButton() { if (pauseButton == null) { pauseButton = new JToggleButton("Pause/Debug"); pauseButton.setMnemonic('P'); pauseButton.setHorizontalTextPosition(SwingConstants.CENTER); pauseButton.setVerticalTextPosition(SwingConstants.BOTTOM); pauseButton.addActionListener(eventHandler); } return pauseButton; } /** * Return the nextTurnButton * * @return JButton */ private Component getNextTurnButton() { if (nextTurnButton == null) { nextTurnButton = new JButton("Next Turn"); nextTurnButton.setMnemonic('N'); nextTurnButton.setHorizontalTextPosition(SwingConstants.CENTER); nextTurnButton.setVerticalTextPosition(SwingConstants.BOTTOM); nextTurnButton.addActionListener(eventHandler); nextTurnButton.setEnabled(false); } return nextTurnButton; } /** * Return the stopButton * * @return JButton */ private JButton getStopButton() { if (stopButton == null) { stopButton = new JButton("Stop"); stopButton.setMnemonic('S'); stopButton.setHorizontalTextPosition(SwingConstants.CENTER); stopButton.setVerticalTextPosition(SwingConstants.BOTTOM); stopButton.addActionListener(eventHandler); stopButton.setEnabled(false); } return stopButton; } /** * Return the restartButton * * @return JButton */ private JButton getRestartButton() { if (restartButton == null) { restartButton = new JButton("Restart"); restartButton.setMnemonic('t'); restartButton.setDisplayedMnemonicIndex(3); restartButton.setHorizontalTextPosition(SwingConstants.CENTER); restartButton.setVerticalTextPosition(SwingConstants.BOTTOM); restartButton.addActionListener(eventHandler); restartButton.setEnabled(false); } return restartButton; } /** * Return the replayButton * * @return JButton */ public JButton getReplayButton() { if (replayButton == null) { replayButton = new JButton("Replay"); replayButton.setMnemonic('y'); replayButton.setDisplayedMnemonicIndex(5); replayButton.setHorizontalTextPosition(SwingConstants.CENTER); replayButton.setVerticalTextPosition(SwingConstants.BOTTOM); replayButton.addActionListener(eventHandler); RobocodeProperties props = manager.getProperties(); replayButton.setVisible(props.getOptionsCommonEnableReplayRecording()); props.addPropertyListener( props.new PropertyListener() { @Override public void enableReplayRecordingChanged(boolean enabled) { replayButton.setVisible( RobocodeFrame.this.manager.getProperties().getOptionsCommonEnableReplayRecording()); } }); replayButton.setEnabled(false); } return replayButton; } /** * Return the tpsSlider * * @return JSlider */ private JSlider getTpsSlider() { if (tpsSlider == null) { RobocodeProperties props = manager.getProperties(); int tps = Math.max(props.getOptionsBattleDesiredTPS(), 1); tpsSlider = new JSlider(0, MAX_TPS_SLIDER_VALUE, tpsToSliderValue(tps)); tpsSlider.setPaintLabels(true); tpsSlider.setPaintTicks(true); tpsSlider.setMinorTickSpacing(1); tpsSlider.addChangeListener(eventHandler); java.util.Hashtable labels = new java.util.Hashtable(); labels.put(0, new JLabel("0")); labels.put(5, new JLabel("5")); labels.put(10, new JLabel("10")); labels.put(15, new JLabel("15")); labels.put(20, new JLabel("20")); labels.put(25, new JLabel("25")); labels.put(30, new JLabel("30")); labels.put(35, new JLabel("40")); labels.put(40, new JLabel("50")); labels.put(45, new JLabel("65")); labels.put(50, new JLabel("90")); labels.put(55, new JLabel("150")); labels.put(60, new JLabel("1000")); tpsSlider.setMajorTickSpacing(5); tpsSlider.setLabelTable(labels); WindowUtil.setFixedSize(tpsSlider, new Dimension((MAX_TPS_SLIDER_VALUE + 1) * 6, 40)); props.addPropertyListener(props.new PropertyListener() { @Override public void desiredTpsChanged(int tps) { // TODO refactor, causing cycles setTpsOnSlider(tps); } }); } return tpsSlider; } /** * Return the tpsLabel * * @return JLabel */ private JLabel getTpsLabel() { if (tpsLabel == null) { tpsLabel = new JLabel(getTpsFromSliderAsString()); } return tpsLabel; } /** * Return the toolBar. * * @return JToolBar */ private JToolBar getToolBar() { if (toolBar == null) { toolBar = new JToolBar(); toolBar.add(getPauseButton()); toolBar.add(getNextTurnButton()); toolBar.add(getStopButton()); toolBar.add(getRestartButton()); toolBar.add(getReplayButton()); toolBar.addSeparator(); toolBar.add(getTpsSlider()); toolBar.add(getTpsLabel()); toolBar.addSeparator(); toolBar.add(getStatusLabel()); WindowUtil.setDefaultStatusLabel(getStatusLabel()); } return toolBar; } /** * Initialize the class. */ private void initialize() { setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); setTitle("Robocode"); setIconImage(ImageUtil.getImage("/resources/icons/robocode-icon.png")); setResizable(true); setVisible(false); // FNL: Make sure that menus are heavy-weight components so that the menus are not painted // behind the BattleView which is a heavy-weight component. This must be done before // adding any menu to the menubar. JPopupMenu.setDefaultLightWeightPopupEnabled(false); setContentPane(getRobocodeContentPane()); setJMenuBar(getRobocodeMenuBar()); battleObserver = new BattleObserver(manager.getWindowManager()); addWindowListener(eventHandler); getBattleView().addMouseListener(interactiveHandler); getBattleView().addMouseMotionListener(interactiveHandler); getBattleView().addMouseWheelListener(interactiveHandler); getBattleView().setFocusable(true); KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(interactiveHandler); if (manager.isSlave()) { getRobocodeMenuBar().getBattleMenu().setEnabled(false); getRobocodeMenuBar().getRobotMenu().setEnabled(false); getStopButton().setEnabled(false); getPauseButton().setEnabled(false); getNextTurnButton().setEnabled(false); getRestartButton().setEnabled(false); getReplayButton().setEnabled(false); exitOnClose = false; } } private void pauseResumeButtonActionPerformed() { manager.getBattleManager().togglePauseResumeBattle(); } /** * Gets the iconified. * * @return Returns a boolean */ public boolean isIconified() { return iconified; } /** * Sets the iconified. * * @param iconified The iconified to set */ private void setIconified(boolean iconified) { this.iconified = iconified; } private int getTpsFromSlider() { final int value = getTpsSlider().getValue(); if (value <= 30) { return value; } if (value <= 40) { return 2 * value - 30; } if (value <= 45) { return 3 * value - 70; } if (value <= 52) { return 5 * value - 160; } switch (value) { case 53: return 110; case 54: return 130; case 55: return 150; case 56: return 200; case 57: return 300; case 58: return 500; case 59: return 750; case 60: return 1000; } return MAX_TPS; } private void setTpsOnSlider(int tps) { tpsSlider.setValue(tpsToSliderValue(tps)); } private int tpsToSliderValue(int tps) { if (tps <= 30) { return tps; } if (tps <= 50) { return (tps + 30) / 2; } if (tps <= 65) { return (tps + 70) / 3; } if (tps <= 100) { return (tps + 160) / 5; } if (tps <= 110) { return 53; } if (tps <= 130) { return 54; } if (tps <= 150) { return 55; } if (tps <= 200) { return 56; } if (tps <= 300) { return 57; } if (tps <= 500) { return 58; } if (tps <= 750) { return 59; } if (tps <= 1000) { return 60; } return MAX_TPS_SLIDER_VALUE; } private String getTpsFromSliderAsString() { int tps = getTpsFromSlider(); return " " + ((tps == MAX_TPS) ? "max" : "" + tps) + " "; } private class EventHandler implements ComponentListener, ActionListener, ContainerListener, WindowListener, ChangeListener { public void actionPerformed(ActionEvent e) { final Object source = e.getSource(); if (source == getPauseButton()) { pauseResumeButtonActionPerformed(); } else if (source == getStopButton()) { manager.getBattleManager().stop(false); } else if (source == getRestartButton()) { manager.getBattleManager().restart(); } else if (source == getNextTurnButton()) { manager.getBattleManager().nextTurn(); } else if (source == getReplayButton()) { manager.getBattleManager().replay(); } } public void componentResized(ComponentEvent e) { if (e.getSource() == getBattleView()) { battleViewResized(); } if (e.getSource() == getBattleViewPanel()) { battleViewPanelResized(); } } public void componentShown(ComponentEvent e) {} public void componentHidden(ComponentEvent e) {} public void componentRemoved(ContainerEvent e) {} public void componentAdded(ContainerEvent e) {} public void componentMoved(ComponentEvent e) {} public void windowActivated(WindowEvent e) {} public void windowClosed(WindowEvent e) { if (exitOnClose) { System.exit(0); } } public void windowClosing(WindowEvent e) { exitOnClose = true; if (manager.isSlave()) { WindowUtil.message("If you wish to exit Robocode, please exit the program controlling it."); exitOnClose = false; return; } if (windowManager.closeRobocodeEditor()) { WindowUtil.saveWindowPositions(); battleObserver = null; dispose(); } manager.saveProperties(); } public void windowDeactivated(WindowEvent e) {} public void windowDeiconified(WindowEvent e) { setIconified(false); manager.getBattleManager().setManagedTPS(true); } public void windowIconified(WindowEvent e) { setIconified(true); manager.getBattleManager().setManagedTPS(false); } public void windowOpened(WindowEvent e) { manager.getBattleManager().setManagedTPS(true); } public void stateChanged(ChangeEvent e) { if (e.getSource() == getTpsSlider()) { int tps = getTpsFromSlider(); // TODO refactor if (tps == 0) { manager.getBattleManager().pauseIfResumedBattle(); } else { // Only set desired TPS if it is not set to zero manager.getProperties().setOptionsBattleDesiredTPS(tps); manager.getBattleManager().resumeIfPausedBattle(); // TODO causing problems when called from PreferencesViewOptionsTab.storePreferences() } tpsLabel.setText(getTpsFromSliderAsString()); } } } private class BattleObserver extends BattleAdaptor { private final IWindowManager windowManager; private int tps; private int currentRound; private int numberOfRounds; private int currentTurn; private boolean isBattleRunning; private boolean isBattlePaused; private boolean isBattleReplay; private long lastTitleUpdateTime; public BattleObserver(IWindowManager windowManager) { this.windowManager = windowManager; windowManager.addBattleListener(this); } protected void finalize() throws Throwable { try { windowManager.removeBattleListener(this); } finally { super.finalize(); } } @Override public void onBattleStarted(BattleStartedEvent event) { numberOfRounds = event.getBattleRules().getNumRounds(); isBattleRunning = true; isBattleReplay = event.isReplay(); getStopButton().setEnabled(true); getRestartButton().setEnabled(manager.getBattleManager().getBattleProperties().getSelectedRobots() != null); getReplayButton().setEnabled(event.isReplay()); getRobocodeMenuBar().getBattleSaveRecordAsMenuItem().setEnabled(false); getRobocodeMenuBar().getBattleExportRecordMenuItem().setEnabled(false); getRobocodeMenuBar().getBattleSaveAsMenuItem().setEnabled(true); getRobocodeMenuBar().getBattleSaveMenuItem().setEnabled(true); JCheckBoxMenuItem rankingCheckBoxMenuItem = getRobocodeMenuBar().getOptionsShowRankingCheckBoxMenuItem(); rankingCheckBoxMenuItem.setEnabled(!isBattleReplay); if (rankingCheckBoxMenuItem.isSelected()) { manager.getWindowManager().showRankingDialog(!isBattleReplay); } validate(); updateTitle(); } public void onRoundStarted(final RoundStartedEvent event) { if (event.getRound() == 0) { getRobotButtonsPanel().removeAll(); final IRobotDialogManager dialogManager = manager.getRobotDialogManager(); final List robots = Arrays.asList(event.getStartSnapshot().getRobots()); dialogManager.trim(robots); int maxEnergy = 0; for (IRobotSnapshot robot : robots) { if (maxEnergy < robot.getEnergy()) { maxEnergy = (int) robot.getEnergy(); } } if (maxEnergy == 0) { maxEnergy = 1; } for (int index = 0; index < robots.size(); index++) { final IRobotSnapshot robot = robots.get(index); final boolean attach = index < RobotDialogManager.MAX_PRE_ATTACHED; final RobotButton button = new RobotButton(manager, robot.getName(), maxEnergy, index, robot.getContestantIndex(), attach); button.setText(robot.getShortName()); addRobotButton(button); } getRobotButtonsPanel().repaint(); } } @Override public void onBattleFinished(BattleFinishedEvent event) { isBattleRunning = false; for (RobotButton robotButton : robotButtons) { robotButton.detach(); } robotButtons.clear(); final boolean canReplayRecord = (manager.getRecordManager().hasRecord()); final boolean enableSaveRecord = (manager.getProperties().getOptionsCommonEnableReplayRecording() & manager.getRecordManager().hasRecord()); getStopButton().setEnabled(false); getReplayButton().setEnabled(canReplayRecord); getNextTurnButton().setEnabled(false); getRobocodeMenuBar().getBattleSaveRecordAsMenuItem().setEnabled(enableSaveRecord); getRobocodeMenuBar().getBattleExportRecordMenuItem().setEnabled(enableSaveRecord); getRobocodeMenuBar().getOptionsShowRankingCheckBoxMenuItem().setEnabled(false); updateTitle(); } @Override public void onBattlePaused(BattlePausedEvent event) { isBattlePaused = true; getPauseButton().setSelected(true); getNextTurnButton().setEnabled(true); updateTitle(); } @Override public void onBattleResumed(BattleResumedEvent event) { isBattlePaused = false; getPauseButton().setSelected(false); getNextTurnButton().setEnabled(false); // TODO: Refactor? if (getTpsFromSlider() == 0) { setTpsOnSlider(1); } updateTitle(); } public void onTurnEnded(TurnEndedEvent event) { if (event == null) { return; } final ITurnSnapshot turn = event.getTurnSnapshot(); if (turn == null) { return; } tps = event.getTurnSnapshot().getTPS(); currentRound = event.getTurnSnapshot().getRound(); currentTurn = event.getTurnSnapshot().getTurn(); // Only update every half second to spare CPU cycles if ((System.currentTimeMillis() - lastTitleUpdateTime) >= UPDATE_TITLE_INTERVAL) { updateTitle(); } } private void updateTitle() { StringBuffer title = new StringBuffer("Robocode"); if (isBattleRunning) { title.append(": "); if (currentTurn == 0) { title.append("Starting round"); } else { if (isBattleReplay) { title.append("Replaying: "); } title.append("Turn "); title.append(currentTurn); title.append(", Round "); title.append(currentRound + 1).append(" of ").append(numberOfRounds); if (!isBattlePaused) { boolean dispTps = manager.getProperties().getOptionsViewTPS(); boolean dispFps = manager.getProperties().getOptionsViewFPS(); if (dispTps | dispFps) { title.append(", "); if (dispTps) { title.append(tps).append(" TPS"); } if (dispTps & dispFps) { title.append(", "); } if (dispFps) { title.append(manager.getWindowManager().getFPS()).append(" FPS"); } } } } } if (isBattlePaused) { title.append(" (paused)"); } setTitle(title.toString()); lastTitleUpdateTime = System.currentTimeMillis(); } @Override public void onBattleCompleted(BattleCompletedEvent event) { if (manager.getProperties().getOptionsCommonShowResults()) { // show on ATW thread ResultsTask resultTask = new ResultsTask(event); EventQueue.invokeLater(resultTask); } } private class ResultsTask implements Runnable { final BattleCompletedEvent event; ResultsTask(BattleCompletedEvent event) { this.event = event; } public void run() { manager.getWindowManager().showResultsDialog(event); } } } } robocode/robocode/robocode/dialog/WizardTabbedPane.java0000644000175000017500000000574511130241112022501 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation *******************************************************************************/ package robocode.dialog; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.*; import java.awt.event.ContainerEvent; import java.awt.event.ContainerListener; /** * @author Mathew A. Nelson (original) */ @SuppressWarnings("serial") public class WizardTabbedPane extends JTabbedPane implements Wizard { private WizardController wizardController; private int currentIndex = 0; private final WizardListener listener; private final EventHandler eventHandler = new EventHandler(); public class EventHandler implements ContainerListener, ChangeListener { public void componentRemoved(ContainerEvent e) {} public void componentAdded(ContainerEvent e) { if (e.getChild() instanceof WizardPanel) { setWizardControllerOnPanel((WizardPanel) e.getChild()); getWizardController().stateChanged(new ChangeEvent(e.getChild())); } } public void stateChanged(javax.swing.event.ChangeEvent e) { currentIndex = getSelectedIndex(); getWizardController().stateChanged(e); } } public WizardTabbedPane(WizardListener listener) { this.listener = listener; initialize(); } public void back() { setSelectedIndex(currentIndex - 1); } public Component getCurrentPanel() { return getSelectedComponent(); } public WizardController getWizardController() { if (wizardController == null) { wizardController = new WizardController(this); } return wizardController; } public WizardListener getWizardListener() { return listener; } public void initialize() { addChangeListener(eventHandler); addContainerListener(eventHandler); } public boolean isBackAvailable() { return (currentIndex > 0); } public boolean isCurrentPanelReady() { Component c = getCurrentPanel(); return (!(c instanceof WizardPanel)) || ((WizardPanel) c).isReady(); } public boolean isNextAvailable() { return ((currentIndex < getComponentCount() - 1) && isCurrentPanelReady()); } public boolean isReady() { for (Component c : getComponents()) { if (c instanceof WizardPanel) { if (!((WizardPanel) c).isReady()) { return false; } } } return true; } public void next() { setSelectedIndex(currentIndex + 1); } public void setWizardControllerOnPanel(WizardPanel panel) { panel.setWizardController(getWizardController()); } } robocode/robocode/robocode/dialog/BattleButton.java0000644000175000017500000000410411130241114021730 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.dialog; import robocode.manager.IRobotDialogManager; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; /** * @author Pavel Savara (original) */ public class BattleButton extends JButton implements ActionListener { private static final long serialVersionUID = 1L; private final IRobotDialogManager robotDialogManager; private BattleDialog battleDialog; public BattleButton(IRobotDialogManager robotDialogManager, boolean attach) { this.robotDialogManager = robotDialogManager; initialize(); if (attach) { attach(); } } public void actionPerformed(ActionEvent e) { if (battleDialog == null) { attach(); if (!battleDialog.isVisible() || battleDialog.getState() != Frame.NORMAL) { WindowUtil.packPlaceShow(battleDialog); } } else { battleDialog.setVisible(true); } } /** * Initialize the class. */ private void initialize() { addActionListener(this); setPreferredSize(new Dimension(110, 25)); setMinimumSize(new Dimension(110, 25)); setMaximumSize(new Dimension(110, 25)); setHorizontalAlignment(SwingConstants.CENTER); setMargin(new Insets(0, 0, 0, 0)); setText("Main battle log"); setToolTipText("Main battle log"); } public void attach() { if (battleDialog == null) { battleDialog = robotDialogManager.getBattleDialog(this, true); } battleDialog.attach(); } public void detach() { battleDialog = null; } } robocode/robocode/robocode/dialog/RobotButton.java0000644000175000017500000001522511130241114021610 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup * - Added setPaintEnabled() and setSGPaintEnabled() in constructor * - Removed cleanup(), getRobotDialog(), and getRobotPeer() methods, which * did nothing or was not being used * - Updated to use methods from the WindowUtil, which replaces window methods * that have been (re)moved from the robocode.util.Utils class *******************************************************************************/ package robocode.dialog; import robocode.BattleResults; import robocode.control.events.BattleAdaptor; import robocode.control.events.BattleCompletedEvent; import robocode.control.events.BattleFinishedEvent; import robocode.control.events.TurnEndedEvent; import robocode.control.snapshot.IRobotSnapshot; import robocode.control.snapshot.IScoreSnapshot; import robocode.control.snapshot.ITurnSnapshot; import robocode.manager.RobocodeManager; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ @SuppressWarnings("serial") public class RobotButton extends JButton implements ActionListener { private static final int BAR_MARGIN = 2; private static final int BAR_HEIGHT = 3; private final RobocodeManager manager; private final BattleObserver battleObserver = new BattleObserver(); private RobotDialog robotDialog; private final String name; private final int robotIndex; private final int contestIndex; private int maxEnergy = 1; private int maxScore = 1; private int lastEnergy; private int lastScore; private boolean isListening; public RobotButton(RobocodeManager manager, String name, int maxEnergy, int robotIndex, int contestIndex, boolean attach) { this.manager = manager; this.name = name; this.robotIndex = robotIndex; this.contestIndex = contestIndex; this.lastEnergy = maxEnergy; this.maxEnergy = maxEnergy; initialize(); if (attach) { attach(); robotDialog.reset(); manager.getBattleManager().setPaintEnabled(robotIndex, robotDialog.isPaintEnabled()); manager.getBattleManager().setSGPaintEnabled(robotIndex, robotDialog.isSGPaintEnabled()); } } public void actionPerformed(ActionEvent e) { if (robotDialog == null) { attach(); if (!robotDialog.isVisible() || robotDialog.getState() != Frame.NORMAL) { WindowUtil.packPlaceShow(robotDialog); } } else { robotDialog.setVisible(true); } } @Override public void paint(Graphics g) { super.paint(g); Graphics2D g2 = (Graphics2D) g; final int barMaxWidth = getWidth() - (2 * BAR_MARGIN); g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.75f)); if (lastEnergy > 0) { Color color; if (lastEnergy > 50) { color = Color.GREEN; } else if (lastEnergy > 25) { color = Color.YELLOW; } else { color = Color.RED; } g.setColor(color); final int widthLife = Math.max(Math.min(barMaxWidth * lastEnergy / maxEnergy, barMaxWidth), 0); g.fillRect(BAR_MARGIN, getHeight() - (2 * BAR_HEIGHT + BAR_MARGIN), widthLife, BAR_HEIGHT); } if (lastScore > 0) { g.setColor(Color.BLUE); final int widthScore = Math.max(Math.min(barMaxWidth * lastScore / maxScore, barMaxWidth), 0); g.fillRect(BAR_MARGIN, getHeight() - (BAR_HEIGHT + BAR_MARGIN), widthScore, BAR_HEIGHT); } } /** * Initialize the class. */ private void initialize() { addActionListener(this); setPreferredSize(new Dimension(110, 25)); setMinimumSize(new Dimension(110, 25)); setMaximumSize(new Dimension(110, 25)); setHorizontalAlignment(SwingConstants.LEFT); setMargin(new Insets(0, 0, 0, 0)); setToolTipText(name); } public void attach() { if (!isListening) { isListening = true; manager.getWindowManager().addBattleListener(battleObserver); } if (robotDialog == null) { robotDialog = manager.getRobotDialogManager().getRobotDialog(this, name, true); } robotDialog.attach(this); } public void detach() { if (isListening) { manager.getWindowManager().removeBattleListener(battleObserver); isListening = false; } if (robotDialog != null) { final RobotDialog dialog = robotDialog; robotDialog = null; dialog.detach(); } } public int getRobotIndex() { return robotIndex; } public String getRobotName() { return name; } private class BattleObserver extends BattleAdaptor { @Override public void onTurnEnded(TurnEndedEvent event) { final ITurnSnapshot turn = event.getTurnSnapshot(); if (turn == null) { return; } final IRobotSnapshot[] robots = turn.getRobots(); final IScoreSnapshot[] scoreSnapshotList = event.getTurnSnapshot().getIndexedTeamScores(); maxEnergy = 0; for (IRobotSnapshot robot : robots) { if (maxEnergy < robot.getEnergy()) { maxEnergy = (int) robot.getEnergy(); } } if (maxEnergy == 0) { maxEnergy = 1; } maxScore = 0; for (IScoreSnapshot team : scoreSnapshotList) { if (maxScore < team.getCurrentScore()) { maxScore = (int) team.getCurrentScore(); } } if (maxScore == 0) { maxScore = 1; } if (scoreSnapshotList.length > contestIndex) { // Sanity check to prevent bug with ArrayIndexOutOfBoundsException final int newScore = (int) scoreSnapshotList[contestIndex].getCurrentScore(); final int newEnergy = (int) robots[robotIndex].getEnergy(); boolean rep = (lastEnergy != newEnergy || lastScore != newScore); lastEnergy = newEnergy; lastScore = newScore; if (rep) { repaint(); } } } public void onBattleCompleted(final BattleCompletedEvent event) { maxScore = 0; for (BattleResults team : event.getIndexedResults()) { if (maxScore < team.getScore()) { maxScore = team.getScore(); } } if (maxScore == 0) { maxScore = 1; } lastScore = event.getIndexedResults()[contestIndex].getScore(); repaint(); } public void onBattleFinished(final BattleFinishedEvent event) { lastEnergy = 0; repaint(); } } } robocode/robocode/robocode/dialog/RobotDialog.java0000644000175000017500000003246211130241114021536 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Rewritten to compact code * - Added Javadoc comments * - Added Paint button and isPaintEnabled() * - Added Robocode SG check box and isSGPaintEnabled() for enabling Robocode * SG compatibility * - Updated to use methods from the WindowUtil, which replaces window methods * that have been (re)moved from the robocode.util.Utils class * - Added Pause button *******************************************************************************/ package robocode.dialog; import robocode.control.events.BattleAdaptor; import robocode.control.events.*; import robocode.control.snapshot.IRobotSnapshot; import robocode.control.snapshot.ITurnSnapshot; import robocode.control.snapshot.IDebugProperty; import robocode.manager.RobocodeManager; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Hashtable; import java.util.Map; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ @SuppressWarnings("serial") public class RobotDialog extends JFrame { private final Color grayGreen = new Color(0x0080C080); private final RobocodeManager manager; private RobotButton robotButton; private JTabbedPane tabbedPane; private ConsoleScrollPane scrollPane; private ConsoleScrollPane propertiesPane; private JPanel robotDialogContentPane; private JPanel buttonPanel; private JButton okButton; private JButton clearButton; private JButton killButton; private JToggleButton paintButton; private JCheckBox sgCheckBox; private JToggleButton pauseButton; private boolean isListening; private int robotIndex; private IRobotSnapshot lastSnapshot; private boolean paintSnapshot; private boolean grayGreenButton; private final Hashtable debugProperties = new Hashtable(); private final BattleObserver battleObserver = new BattleObserver(); /** * RobotDialog constructor * @param manager game root * @param robotButton related button */ public RobotDialog(RobocodeManager manager, RobotButton robotButton) { super(); this.manager = manager; this.robotButton = robotButton; initialize(); } /** * Initialize the dialog */ private void initialize() { robotIndex = robotButton.getRobotIndex(); setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); setContentPane(getRobotDialogContentPane()); if (manager.isSlave()) { getKillButton().setEnabled(false); } this.setTitle(robotButton.getRobotName()); pack(); } @Override protected void finalize() throws Throwable { try { detach(); } finally { super.finalize(); } } public void detach() { if (isListening) { manager.getWindowManager().removeBattleListener(battleObserver); isListening = false; } robotButton.detach(); } public void attach(RobotButton robotButton) { this.robotButton = robotButton; robotIndex = this.robotButton.getRobotIndex(); if (!isListening) { isListening = true; manager.getWindowManager().addBattleListener(battleObserver); } } public void reset() { getConsoleScrollPane().setText(null); lastSnapshot = null; debugProperties.clear(); } /** * When robotDialog is packed, we want to set a reasonable size. However, * after that, we need a null preferred size so the scrollpane will scroll. * (preferred size should be based on the text inside) */ @Override public void pack() { getConsoleScrollPane().setPreferredSize(new Dimension(426, 200)); super.pack(); getConsoleScrollPane().setPreferredSize(null); } /** * Returns true if Paint is enabled; false otherwise * * @return true if Paint is enabled; false otherwise */ public boolean isPaintEnabled() { return getPaintButton().isSelected(); } /** * Returns true if the Robocode SG paint is enabled; false otherwise * * @return true if the Robocode SG paint enabled; false otherwise */ public boolean isSGPaintEnabled() { return getSGCheckBox().isSelected(); } private final ActionListener eventHandler = new ActionListener() { public void actionPerformed(ActionEvent e) { Object src = e.getSource(); if (src == RobotDialog.this.getOkButton()) { okButtonActionPerformed(); } else if (src == RobotDialog.this.getClearButton()) { clearButtonActionPerformed(); } else if (src == RobotDialog.this.getKillButton()) { killButtonActionPerformed(); } else if (src == RobotDialog.this.getPaintButton()) { paintButtonActionPerformed(); } else if (src == RobotDialog.this.getSGCheckBox()) { sgCheckBoxActionPerformed(); } else if (src == RobotDialog.this.getPauseButton()) { pauseResumeButtonActionPerformed(); } } }; /** * Returns the dialog's content pane * * @return the dialog's content pane */ private JPanel getRobotDialogContentPane() { if (robotDialogContentPane == null) { robotDialogContentPane = new JPanel(); robotDialogContentPane.setLayout(new BorderLayout()); robotDialogContentPane.add(getTabbedPane()); robotDialogContentPane.add(getButtonPanel(), BorderLayout.SOUTH); } return robotDialogContentPane; } private JTabbedPane getTabbedPane() { if (tabbedPane == null) { tabbedPane = new JTabbedPane(); tabbedPane.setLayout(new BorderLayout()); tabbedPane.addTab("Console", getConsoleScrollPane()); tabbedPane.addTab("Properties", getTurnScrollPane()); // tabbedPane.setSelectedIndex(0); tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); tabbedPane.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { paintSnapshot = (tabbedPane.getSelectedIndex() == 1); paintSnapshot(); } }); } return tabbedPane; } private void paintSnapshot() { if (paintSnapshot) { if (lastSnapshot != null) { StringBuilder sb = new StringBuilder(); sb.append("energy: ").append(lastSnapshot.getEnergy()).append('\n'); sb.append("x: ").append(lastSnapshot.getX()).append('\n'); sb.append("y: ").append(lastSnapshot.getY()).append('\n'); sb.append("velocity: ").append(lastSnapshot.getVelocity()).append('\n'); sb.append("heat: ").append(lastSnapshot.getGunHeat()).append('\n'); sb.append("bodyHeading: rad: ").append(lastSnapshot.getBodyHeading()).append(" deg: ").append(Math.toDegrees(lastSnapshot.getBodyHeading())).append( '\n'); sb.append("gunHeading: rad: ").append(lastSnapshot.getGunHeading()).append(" deg: ").append(Math.toDegrees(lastSnapshot.getGunHeading())).append( '\n'); sb.append("radarHeading: rad: ").append(lastSnapshot.getRadarHeading()).append(" deg: ").append(Math.toDegrees(lastSnapshot.getRadarHeading())).append( '\n'); sb.append("state: ").append(lastSnapshot.getState()).append('\n'); sb.append('\n'); IDebugProperty[] debugPropeties = lastSnapshot.getDebugProperties(); if (debugPropeties != null) { for (IDebugProperty prop : debugPropeties) { if (prop.getValue() == null || prop.getValue().length() == 0) { debugProperties.remove(prop.getKey()); } else { debugProperties.put(prop.getKey(), prop.getValue()); } } } for (Map.Entry prop : debugProperties.entrySet()) { sb.append(prop.getKey()).append(": ").append(prop.getValue()).append('\n'); } getTurnScrollPane().setText(sb.toString()); } else { getTurnScrollPane().setText(null); } } } private ConsoleScrollPane getTurnScrollPane() { if (propertiesPane == null) { propertiesPane = new ConsoleScrollPane(); } return propertiesPane; } /** * Returns the console scroll pane * * @return the console scroll pane */ private ConsoleScrollPane getConsoleScrollPane() { if (scrollPane == null) { scrollPane = new ConsoleScrollPane(); JTextArea textPane = scrollPane.getTextPane(); textPane.setBackground(Color.DARK_GRAY); textPane.setForeground(Color.WHITE); } return scrollPane; } /** * Returns the button panel * * @return the button panel */ private JPanel getButtonPanel() { if (buttonPanel == null) { buttonPanel = new JPanel(); buttonPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); buttonPanel.add(getOkButton()); buttonPanel.add(getClearButton()); buttonPanel.add(getKillButton()); buttonPanel.add(getPaintButton()); buttonPanel.add(getSGCheckBox()); buttonPanel.add(getPauseButton()); } return buttonPanel; } /** * Returns the OK button * * @return the OK button */ private JButton getOkButton() { if (okButton == null) { okButton = getNewButton("OK"); } return okButton; } /** * Returns the Clear button * * @return the Clear button */ private JButton getClearButton() { if (clearButton == null) { clearButton = getNewButton("Clear"); } return clearButton; } /** * Returns the Kill button. * * @return the Kill button */ private JButton getKillButton() { if (killButton == null) { killButton = getNewButton("Kill Robot"); } return killButton; } /** * Returns the Paint button. * * @return the Paint button */ private JToggleButton getPaintButton() { if (paintButton == null) { paintButton = new JToggleButton("Paint"); paintButton.addActionListener(eventHandler); } return paintButton; } /** * Returns the SG checkbox. * * @return the SG checkbox */ private JCheckBox getSGCheckBox() { if (sgCheckBox == null) { sgCheckBox = new JCheckBox("Robocode SG"); sgCheckBox.addActionListener(eventHandler); } return sgCheckBox; } /** * Returns the Pause button. * * @return the Pause button */ private JToggleButton getPauseButton() { if (pauseButton == null) { pauseButton = new JToggleButton("Pause/Debug"); pauseButton.addActionListener(eventHandler); } return pauseButton; } /** * Returns a new button with event handler and with the specified text * * @param text The text of the button * @return a new button with event handler and with the specified text */ private JButton getNewButton(String text) { JButton button = new JButton(text); button.addActionListener(eventHandler); return button; } /** * Is called when the OK button has been activated */ private void okButtonActionPerformed() { dispose(); } /** * Is called when the Clear button has been activated */ private void clearButtonActionPerformed() { reset(); } /** * Is called when the Kill button has been activated */ private void killButtonActionPerformed() { manager.getBattleManager().killRobot(robotIndex); } /** * Is called when the Paint button has been activated */ private void paintButtonActionPerformed() { manager.getBattleManager().setPaintEnabled(robotIndex, getPaintButton().isSelected()); } /** * Is called when the SG check box has been activated */ private void sgCheckBoxActionPerformed() { manager.getBattleManager().setSGPaintEnabled(robotIndex, getSGCheckBox().isSelected()); } /** * Is called when the Pause/Resume button has been activated */ private void pauseResumeButtonActionPerformed() { manager.getBattleManager().togglePauseResumeBattle(); } private class BattleObserver extends BattleAdaptor { @Override public void onBattleStarted(BattleStartedEvent event) { getPauseButton().setEnabled(true); getKillButton().setEnabled(true); } @Override public void onBattleFinished(BattleFinishedEvent event) { lastSnapshot = null; paintSnapshot(); getPauseButton().setEnabled(false); getKillButton().setEnabled(false); } @Override public void onBattlePaused(BattlePausedEvent event) { getPauseButton().setSelected(true); } @Override public void onBattleResumed(BattleResumedEvent event) { getPauseButton().setSelected(false); } @Override public void onTurnEnded(TurnEndedEvent event) { final ITurnSnapshot turn = event.getTurnSnapshot(); if (turn == null) { return; } if (turn.getRobots().length > robotIndex) { // Sanity check to prevent bug with ArrayIndexOutOfBoundsException lastSnapshot = turn.getRobots()[robotIndex]; final String text = lastSnapshot.getOutputStreamSnapshot(); if (text != null && text.length() > 0) { getConsoleScrollPane().append(text); getConsoleScrollPane().scrollToBottom(); } if (lastSnapshot.isPaintRobot() && !grayGreenButton) { grayGreenButton = true; getPaintButton().setBackground(grayGreen); } paintSnapshot(); } } } } robocode/robocode/robocode/dialog/WizardCardPanel.java0000644000175000017500000000630111130241112022332 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup *******************************************************************************/ package robocode.dialog; import javax.swing.*; import javax.swing.event.ChangeEvent; import java.awt.*; import java.awt.event.ContainerEvent; import java.awt.event.ContainerListener; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ @SuppressWarnings("serial") public class WizardCardPanel extends JPanel implements Wizard { private WizardController wizardController; private CardLayout cardLayout = null; private int currentIndex = 0; private final WizardListener listener; private final EventHandler eventHandler = new EventHandler(); public class EventHandler implements ContainerListener { public void componentRemoved(ContainerEvent e) {} public void componentAdded(ContainerEvent e) { if (e.getChild() instanceof WizardPanel) { setWizardControllerOnPanel((WizardPanel) e.getChild()); getWizardController().stateChanged(new ChangeEvent(e.getChild())); } } } /** * WizardCardLayout constructor * * @param listener WizardListener */ public WizardCardPanel(WizardListener listener) { this.listener = listener; initialize(); } public void back() { currentIndex--; getWizardController().stateChanged(null); getCardLayout().previous(this); } public CardLayout getCardLayout() { if (cardLayout == null) { cardLayout = new CardLayout(); } return cardLayout; } public Component getCurrentPanel() { return getComponent(currentIndex); } public WizardController getWizardController() { if (wizardController == null) { wizardController = new WizardController(this); } return wizardController; } public WizardListener getWizardListener() { return listener; } public void initialize() { this.setLayout(getCardLayout()); this.addContainerListener(eventHandler); } public boolean isBackAvailable() { return (currentIndex > 0); } public boolean isCurrentPanelReady() { Component c = getCurrentPanel(); return (!(c instanceof WizardPanel)) || ((WizardPanel) c).isReady(); } public boolean isNextAvailable() { return ((currentIndex < getComponentCount() - 1) && isCurrentPanelReady()); } public boolean isReady() { for (Component c : getComponents()) { if (!((WizardPanel) c).isReady()) { return false; } } return true; } public void next() { currentIndex++; getWizardController().stateChanged(null); getCardLayout().next(this); } public void setWizardControllerOnPanel(WizardPanel panel) { panel.setWizardController(getWizardController()); } } robocode/robocode/robocode/dialog/RobotSelectionPanel.java0000644000175000017500000005254611130241114023251 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Matthew Reeder * - Added keyboard mnemonics to buttons * Flemming N. Larsen * - Replaced FileSpecificationVector with plain Vector * - Ported to Java 5 * - Code cleanup * - Updated to use methods from the Logger, which replaces logger methods * that have been (re)moved from the robocode.util.Utils class * - Bugfixed buildRobotList(), which checked if selectedRobots was set * instead of preSelectedRobots. Robots were not selected when loading a * battle * - Replaced synchronizedList on list for selectedRobots with a * CopyOnWriteArrayList in order to prevent ConcurrentModificationException * when accessing this list via Iterators using public methods to this * class * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap *******************************************************************************/ package robocode.dialog; import robocode.io.Logger; import robocode.manager.IRepositoryManager; import robocode.manager.RobocodeManager; import robocode.repository.FileSpecification; import robocode.repository.TeamSpecification; import javax.swing.*; import javax.swing.border.TitledBorder; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import java.awt.*; import java.awt.event.*; import java.util.List; import java.util.StringTokenizer; import java.util.concurrent.CopyOnWriteArrayList; /** * @author Mathew A. Nelson (original) * @author Matthew Reeder (contributor) * @author Flemming N. Larsen (contributor) * @author Robert D. Maupin (contributor) */ @SuppressWarnings("serial") public class RobotSelectionPanel extends WizardPanel { private AvailableRobotsPanel availableRobotsPanel; private JPanel selectedRobotsPanel; private JScrollPane selectedRobotsScrollPane; private JList selectedRobotsList; private JPanel buttonsPanel; private JPanel addButtonsPanel; private JPanel removeButtonsPanel; private JButton addButton; private JButton addAllButton; private JButton removeButton; private JButton removeAllButton; private final EventHandler eventHandler = new EventHandler(); private RobotDescriptionPanel descriptionPanel; private final String instructions; private JLabel instructionsLabel; private JPanel mainPanel; private int maxRobots = 1; private int minRobots = 1; private JPanel numRoundsPanel; private JTextField numRoundsTextField; private final boolean onlyShowSource; private final boolean onlyShowWithPackage; private final boolean onlyShowRobots; private final boolean onlyShowDevelopment; private final boolean onlyShowPackaged; private final boolean ignoreTeamRobots; private String preSelectedRobots; private final List selectedRobots = new CopyOnWriteArrayList(); private final boolean showNumRoundsPanel; private final RobocodeManager manager; private class EventHandler implements ActionListener, ListSelectionListener { public void actionPerformed(ActionEvent e) { if (e.getSource() == getAddAllButton()) { addAllButtonActionPerformed(); } else if (e.getSource() == getAddButton()) { addButtonActionPerformed(); } else if (e.getSource() == getRemoveAllButton()) { removeAllButtonActionPerformed(); } else if (e.getSource() == getRemoveButton()) { removeButtonActionPerformed(); } } public void valueChanged(ListSelectionEvent e) { if (e.getValueIsAdjusting()) { return; } if (e.getSource() == getSelectedRobotsList()) { selectedRobotsListSelectionChanged(); } } } public RobotSelectionPanel(RobocodeManager manager, int minRobots, int maxRobots, boolean showNumRoundsPanel, String instructions, boolean onlyShowSource, boolean onlyShowWithPackage, boolean onlyShowRobots, boolean onlyShowDevelopment, boolean onlyShowPackaged, boolean ignoreTeamRobots, String preSelectedRobots) { super(); this.manager = manager; this.showNumRoundsPanel = showNumRoundsPanel; this.minRobots = minRobots; this.maxRobots = maxRobots; this.instructions = instructions; this.onlyShowSource = onlyShowSource; this.onlyShowWithPackage = onlyShowWithPackage; this.onlyShowRobots = onlyShowRobots; this.onlyShowDevelopment = onlyShowDevelopment; this.onlyShowPackaged = onlyShowPackaged; this.ignoreTeamRobots = ignoreTeamRobots; this.preSelectedRobots = preSelectedRobots; initialize(); } private void addAllButtonActionPerformed() { JList selectedList = getSelectedRobotsList(); SelectedRobotsModel selectedModel = (SelectedRobotsModel) selectedList.getModel(); for (FileSpecification selected : availableRobotsPanel.getAvailableRobots()) { selectedRobots.add(selected); } selectedList.clearSelection(); selectedModel.changed(); fireStateChanged(); if (selectedModel.getSize() >= minRobots && selectedModel.getSize() <= maxRobots) { showInstructions(); } else if (selectedModel.getSize() > maxRobots) { showWrongNumInstructions(); } availableRobotsPanel.getAvailableRobotsList().requestFocus(); } private void addButtonActionPerformed() { SelectedRobotsModel selectedModel = (SelectedRobotsModel) getSelectedRobotsList().getModel(); List moves = availableRobotsPanel.getSelectedRobots(); for (FileSpecification move : moves) { selectedRobots.add(move); } selectedModel.changed(); fireStateChanged(); if (selectedModel.getSize() >= minRobots && selectedModel.getSize() <= maxRobots) { showInstructions(); } else if (selectedModel.getSize() > maxRobots) { showWrongNumInstructions(); } availableRobotsPanel.getAvailableRobotsList().requestFocus(); } private JButton getAddAllButton() { if (addAllButton == null) { addAllButton = new JButton(); addAllButton.setText("Add All ->"); addAllButton.setMnemonic('l'); addAllButton.setDisplayedMnemonicIndex(5); addAllButton.addActionListener(eventHandler); } return addAllButton; } private JButton getAddButton() { if (addButton == null) { addButton = new JButton(); addButton.setText("Add ->"); addButton.setMnemonic('A'); addButton.addActionListener(eventHandler); } return addButton; } private JPanel getAddButtonsPanel() { if (addButtonsPanel == null) { addButtonsPanel = new JPanel(); addButtonsPanel.setLayout(new GridLayout(2, 1)); addButtonsPanel.add(getAddButton()); addButtonsPanel.add(getAddAllButton()); } return addButtonsPanel; } private JPanel getButtonsPanel() { if (buttonsPanel == null) { buttonsPanel = new JPanel(); buttonsPanel.setLayout(new BorderLayout(5, 5)); buttonsPanel.setBorder(BorderFactory.createEmptyBorder(21, 5, 5, 5)); buttonsPanel.add(getAddButtonsPanel(), BorderLayout.NORTH); if (showNumRoundsPanel) { buttonsPanel.add(getNumRoundsPanel(), BorderLayout.CENTER); } buttonsPanel.add(getRemoveButtonsPanel(), BorderLayout.SOUTH); } return buttonsPanel; } private JButton getRemoveAllButton() { if (removeAllButton == null) { removeAllButton = new JButton(); removeAllButton.setText("<- Remove All"); removeAllButton.setMnemonic('v'); removeAllButton.setDisplayedMnemonicIndex(7); removeAllButton.addActionListener(eventHandler); } return removeAllButton; } private JButton getRemoveButton() { if (removeButton == null) { removeButton = new JButton(); removeButton.setText("<- Remove"); removeButton.setMnemonic('m'); removeButton.setDisplayedMnemonicIndex(5); removeButton.addActionListener(eventHandler); } return removeButton; } private JPanel getRemoveButtonsPanel() { if (removeButtonsPanel == null) { removeButtonsPanel = new JPanel(); removeButtonsPanel.setLayout(new GridLayout(2, 1)); removeButtonsPanel.add(getRemoveButton()); removeButtonsPanel.add(getRemoveAllButton()); } return removeButtonsPanel; } public String getSelectedRobotsAsString() { StringBuffer sb = new StringBuffer(); for (int i = 0; i < selectedRobots.size(); i++) { if (i != 0) { sb.append(','); } sb.append(selectedRobots.get(i).getNameManager().getUniqueFullClassNameWithVersion()); } return sb.toString(); } public List getSelectedRobots() { return selectedRobots; } private JList getSelectedRobotsList() { if (selectedRobotsList == null) { selectedRobotsList = new JList(); selectedRobotsList.setModel(new SelectedRobotsModel()); selectedRobotsList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); RobotNameCellRenderer robotNamesCellRenderer = new RobotNameCellRenderer(); selectedRobotsList.setCellRenderer(robotNamesCellRenderer); MouseListener mouseListener = new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) { removeButtonActionPerformed(); } if ((e.getModifiers() & InputEvent.BUTTON3_MASK) != 0) { contextMenuActionPerformed(); } } }; selectedRobotsList.addMouseListener(mouseListener); selectedRobotsList.addListSelectionListener(eventHandler); } return selectedRobotsList; } private JPanel getSelectedRobotsPanel() { if (selectedRobotsPanel == null) { selectedRobotsPanel = new JPanel(); selectedRobotsPanel.setLayout(new BorderLayout()); selectedRobotsPanel.setPreferredSize(new Dimension(120, 100)); selectedRobotsPanel.setBorder( BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Selected Robots")); selectedRobotsPanel.add(getSelectedRobotsScrollPane(), BorderLayout.CENTER); } return selectedRobotsPanel; } private JScrollPane getSelectedRobotsScrollPane() { if (selectedRobotsScrollPane == null) { selectedRobotsScrollPane = new JScrollPane(); selectedRobotsScrollPane.setViewportView(getSelectedRobotsList()); } return selectedRobotsScrollPane; } private void initialize() { setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); setLayout(new BorderLayout()); add(getInstructionsLabel(), BorderLayout.NORTH); add(getMainPanel(), BorderLayout.CENTER); add(getDescriptionPanel(), BorderLayout.SOUTH); setVisible(true); showInstructions(); refreshRobotList(false); } private void removeAllButtonActionPerformed() { JList selectedList = getSelectedRobotsList(); SelectedRobotsModel selectedModel = (SelectedRobotsModel) selectedList.getModel(); selectedRobots.clear(); selectedList.clearSelection(); selectedModel.changed(); fireStateChanged(); showInstructions(); } private void contextMenuActionPerformed() {} private void removeButtonActionPerformed() { JList selectedList = getSelectedRobotsList(); SelectedRobotsModel selectedModel = (SelectedRobotsModel) selectedList.getModel(); int sel[] = selectedList.getSelectedIndices(); for (int i = 0; i < sel.length; i++) { selectedRobots.remove(sel[i] - i); } selectedList.clearSelection(); selectedModel.changed(); fireStateChanged(); if (selectedModel.getSize() < minRobots || selectedModel.getSize() > maxRobots) { showWrongNumInstructions(); } else { showInstructions(); } } private static class RobotNameCellRenderer extends JLabel implements ListCellRenderer { private boolean useShortNames; public RobotNameCellRenderer() { setOpaque(true); } public void setUseShortNames(boolean useShortNames) { this.useShortNames = useShortNames; } public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { setComponentOrientation(list.getComponentOrientation()); if (isSelected) { setBackground(list.getSelectionBackground()); setForeground(list.getSelectionForeground()); } else { setBackground(list.getBackground()); setForeground(list.getForeground()); } if (useShortNames && value instanceof FileSpecification) { FileSpecification robotSpecification = (FileSpecification) value; if (value instanceof TeamSpecification) { setText("Team: " + robotSpecification.getNameManager().getUniqueShortClassNameWithVersion()); } else { setText(robotSpecification.getNameManager().getUniqueShortClassNameWithVersion()); } } else if (value instanceof FileSpecification) { FileSpecification robotSpecification = (FileSpecification) value; if (value instanceof TeamSpecification) { setText("Team: " + robotSpecification.getNameManager().getUniqueFullClassNameWithVersion()); } else { setText(robotSpecification.getNameManager().getUniqueFullClassNameWithVersion()); } } else { setText("??" + value.toString()); } setEnabled(list.isEnabled()); setFont(list.getFont()); return this; } } class SelectedRobotsModel extends AbstractListModel { public void changed() { fireContentsChanged(this, 0, getSize()); } public int getSize() { return selectedRobots.size(); } public Object getElementAt(int which) { return selectedRobots.get(which); } } public AvailableRobotsPanel getAvailableRobotsPanel() { if (availableRobotsPanel == null) { availableRobotsPanel = new AvailableRobotsPanel(getAddButton(), "Available Robots", getSelectedRobotsList(), this); } return availableRobotsPanel; } private RobotDescriptionPanel getDescriptionPanel() { if (descriptionPanel == null) { descriptionPanel = new RobotDescriptionPanel(); descriptionPanel.setBorder(BorderFactory.createEmptyBorder(1, 10, 1, 10)); } return descriptionPanel; } private JLabel getInstructionsLabel() { if (instructionsLabel == null) { instructionsLabel = new JLabel(); if (instructions != null) { instructionsLabel.setText(instructions); } } return instructionsLabel; } private JPanel getMainPanel() { if (mainPanel == null) { mainPanel = new JPanel(); mainPanel.setPreferredSize(new Dimension(550, 300)); GridBagLayout layout = new GridBagLayout(); mainPanel.setLayout(layout); GridBagConstraints constraints = new GridBagConstraints(); constraints.fill = GridBagConstraints.BOTH; constraints.weightx = 2; constraints.weighty = 1; constraints.anchor = GridBagConstraints.NORTHWEST; constraints.gridwidth = 2; layout.setConstraints(getAvailableRobotsPanel(), constraints); mainPanel.add(getAvailableRobotsPanel()); constraints.gridwidth = 1; constraints.weightx = 0; constraints.weighty = 0; constraints.anchor = GridBagConstraints.CENTER; layout.setConstraints(getButtonsPanel(), constraints); mainPanel.add(getButtonsPanel()); constraints.gridwidth = GridBagConstraints.REMAINDER; constraints.weightx = 1; constraints.weighty = 1; constraints.anchor = GridBagConstraints.NORTHWEST; layout.setConstraints(getSelectedRobotsPanel(), constraints); mainPanel.add(getSelectedRobotsPanel()); } return mainPanel; } public int getNumRounds() { try { return Integer.parseInt(getNumRoundsTextField().getText()); } catch (NumberFormatException e) { int numRounds = manager.getProperties().getNumberOfRounds(); getNumRoundsTextField().setText("" + numRounds); return numRounds; } } private JPanel getNumRoundsPanel() { if (numRoundsPanel == null) { numRoundsPanel = new JPanel(); numRoundsPanel.setLayout(new BoxLayout(numRoundsPanel, BoxLayout.Y_AXIS)); numRoundsPanel.setBorder(BorderFactory.createEmptyBorder()); numRoundsPanel.add(new JPanel()); JPanel j = new JPanel(); j.setLayout(new BoxLayout(j, BoxLayout.Y_AXIS)); TitledBorder border = BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Number of Rounds"); j.setBorder(border); j.add(getNumRoundsTextField()); j.setPreferredSize(new Dimension(border.getMinimumSize(j).width, j.getPreferredSize().height)); j.setMinimumSize(j.getPreferredSize()); j.setMaximumSize(j.getPreferredSize()); numRoundsPanel.add(j); numRoundsPanel.add(new JPanel()); } return numRoundsPanel; } private JTextField getNumRoundsTextField() { final robocode.manager.RobocodeProperties props = manager.getProperties(); if (numRoundsTextField == null) { numRoundsTextField = new JTextField(); numRoundsTextField.setAutoscrolls(false); // Center in panel numRoundsTextField.setAlignmentX((float) .5); // Center text in textfield numRoundsTextField.setHorizontalAlignment(SwingConstants.CENTER); // Add document listener numRoundsTextField.getDocument().addDocumentListener(new DocumentListener() { public void changedUpdate(DocumentEvent e) {} public void insertUpdate(DocumentEvent e) { handleChange(); } public void removeUpdate(DocumentEvent e) { handleChange(); } private void handleChange() { try { int numRounds = Integer.parseInt(numRoundsTextField.getText()); manager.getBattleManager().getBattleProperties().setNumRounds(numRounds); if (numRounds != props.getNumberOfRounds()) { props.setNumberOfRounds(numRounds); } } catch (NumberFormatException ignored) {} } }); } return numRoundsTextField; } public int getSelectedRobotsCount() { return selectedRobots.size(); } @Override public boolean isReady() { return (getSelectedRobotsCount() >= minRobots && getSelectedRobotsCount() <= maxRobots); } public void refreshRobotList(final boolean withClear) { final Runnable runnable = new Runnable() { public void run() { try { setBusyPointer(true); final IRepositoryManager repositoryManager = manager.getRobotRepositoryManager(); if (withClear) { repositoryManager.clearRobotList(); } List robotList = repositoryManager.getRobotRepository().getRobotSpecificationsList( onlyShowSource, onlyShowWithPackage, onlyShowRobots, onlyShowDevelopment, onlyShowPackaged, ignoreTeamRobots); getAvailableRobotsPanel().setRobotList(robotList); if (preSelectedRobots != null && preSelectedRobots.length() > 0) { setSelectedRobots(robotList, preSelectedRobots); preSelectedRobots = null; } } finally { setBusyPointer(false); } } }; SwingUtilities.invokeLater(runnable); } private static final Cursor BUSY_CURSOR = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR); private static final Cursor DEFAULT_CURSOR = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR); private void setBusyPointer(boolean enabled) { setCursor(enabled ? BUSY_CURSOR : DEFAULT_CURSOR); } private void selectedRobotsListSelectionChanged() { int sel[] = getSelectedRobotsList().getSelectedIndices(); if (sel.length == 1) { availableRobotsPanel.clearSelection(); FileSpecification robotSpecification = (FileSpecification) getSelectedRobotsList().getModel().getElementAt( sel[0]); showDescription(robotSpecification); } else { showDescription(null); } } public void setNumRounds(int numRounds) { getNumRoundsTextField().setText("" + numRounds); } private void setSelectedRobots(List robotList, String selectedRobotsString) { if (selectedRobotsString != null) { StringTokenizer tokenizer; tokenizer = new StringTokenizer(selectedRobotsString, ","); if (robotList == null) { Logger.logError("Cannot add robots to a null robots list!"); return; } this.selectedRobots.clear(); while (tokenizer.hasMoreTokens()) { String bot = tokenizer.nextToken(); for (FileSpecification selected : robotList) { if (selected.getNameManager().getUniqueFullClassNameWithVersion().equals(bot)) { this.selectedRobots.add(selected); break; } } } } ((SelectedRobotsModel) getSelectedRobotsList().getModel()).changed(); fireStateChanged(); } public void showDescription(FileSpecification robotSpecification) { getDescriptionPanel().showDescription(robotSpecification); } public void showInstructions() { if (instructions != null) { instructionsLabel.setText(instructions); instructionsLabel.setVisible(true); } else { instructionsLabel.setVisible(false); } } public void showWrongNumInstructions() { if (minRobots == maxRobots) { if (minRobots == 1) { instructionsLabel.setText("Please select exactly 1 robot."); } else { instructionsLabel.setText("Please select exactly " + minRobots + " robots."); } } else { instructionsLabel.setText("Please select between " + minRobots + " and " + maxRobots + " robots."); } instructionsLabel.setVisible(true); } } robocode/robocode/robocode/dialog/RobotExtractor.java0000644000175000017500000001414111130241114022304 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Matthew Reeder * - Added keyboard mnemonics to buttons * Flemming N. Larsen * - Replaced FileSpecificationVector with plain Vector * - Ported to Java 5 * - Updated to use methods from the WindowUtil, which replaces window methods * that have been (re)moved from the robocode.util.Utils class * - Changed the F5 key press for refreshing the list of available robots * into 'modifier key' + R to comply with other OSes like e.g. Mac OS * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap *******************************************************************************/ package robocode.dialog; import robocode.manager.IRepositoryManager; import robocode.peer.robot.RobotClassManager; import robocode.repository.FileSpecification; import static robocode.ui.ShortcutUtil.MENU_SHORTCUT_KEY_MASK; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.io.PrintWriter; import java.io.StringWriter; import java.util.List; import java.util.Set; /** * @author Mathew A. Nelson (original) * @author Matthew Reeder (contributor) * @author Flemming N. Larsen (contributor) * @author Robert D. Maupin (contributor) */ @SuppressWarnings("serial") public class RobotExtractor extends JDialog implements WizardListener { String unusedrobotPath; private final int minRobots = 1; private final int maxRobots = 1; // 250; private JPanel robotImporterContentPane; private WizardCardPanel wizardPanel; private WizardController buttonsPanel; private RobotSelectionPanel robotSelectionPanel; public byte buf[] = new byte[4096]; private StringWriter output; private final IRepositoryManager repositoryManager; private final EventHandler eventHandler = new EventHandler(); class EventHandler implements ActionListener { public void actionPerformed(ActionEvent e) { if (e.getActionCommand().equals("Refresh")) { getRobotSelectionPanel().refreshRobotList(false); } } } public RobotExtractor(JFrame owner, IRepositoryManager repositoryManager) { super(owner); this.repositoryManager = repositoryManager; initialize(); } public void cancelButtonActionPerformed() { dispose(); } public void finishButtonActionPerformed() { int rc = extractRobot(); ConsoleDialog d; d = new ConsoleDialog(repositoryManager.getManager().getWindowManager().getRobocodeFrame(), "Extract results", false); d.setText(output.toString()); d.pack(); d.pack(); WindowUtil.packCenterShow(this, d); if (rc < 8) { this.dispose(); } } private WizardController getButtonsPanel() { if (buttonsPanel == null) { buttonsPanel = getWizardPanel().getWizardController(); } return buttonsPanel; } public Set getClasses(RobotClassManager robotClassManager) throws ClassNotFoundException { robotClassManager.getRobotClassLoader().loadRobotClass(robotClassManager.getFullClassName(), true); return robotClassManager.getReferencedClasses(); } private JPanel getRobotImporterContentPane() { if (robotImporterContentPane == null) { robotImporterContentPane = new JPanel(); robotImporterContentPane.setLayout(new BorderLayout()); robotImporterContentPane.add(getButtonsPanel(), BorderLayout.SOUTH); robotImporterContentPane.add(getWizardPanel(), BorderLayout.CENTER); getWizardPanel().getWizardController().setFinishButtonTextAndMnemonic("Extract!", 'E', 0); robotImporterContentPane.registerKeyboardAction(eventHandler, "Refresh", KeyStroke.getKeyStroke(KeyEvent.VK_R, MENU_SHORTCUT_KEY_MASK), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); robotImporterContentPane.registerKeyboardAction(eventHandler, "Refresh", KeyStroke.getKeyStroke(KeyEvent.VK_R, MENU_SHORTCUT_KEY_MASK), JComponent.WHEN_FOCUSED); } return robotImporterContentPane; } public RobotSelectionPanel getRobotSelectionPanel() { if (robotSelectionPanel == null) { robotSelectionPanel = new RobotSelectionPanel(repositoryManager.getManager(), minRobots, maxRobots, false, "Select the robot you would like to extract to the robots directory. Robots not shown do not include source.", true, true, true, false, true, true, null); } return robotSelectionPanel; } private WizardCardPanel getWizardPanel() { if (wizardPanel == null) { wizardPanel = new WizardCardPanel(this); wizardPanel.add(getRobotSelectionPanel(), "Select robot"); } return wizardPanel; } private void initialize() { setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); setTitle("Robot Extract"); setContentPane(getRobotImporterContentPane()); } private int extractRobot() { repositoryManager.clearRobotList(); int rv; output = new StringWriter(); PrintWriter out = new PrintWriter(output); out.println("Robot Extract"); List selectedRobots = getRobotSelectionPanel().getSelectedRobots(); FileSpecification spec = selectedRobots.get(0); try { WindowUtil.setStatusWriter(out); rv = repositoryManager.extractJar(spec.getJarFile(), repositoryManager.getRobotsDirectory(), "Extracting to " + repositoryManager.getRobotsDirectory(), false, true, false); WindowUtil.setStatusWriter(null); WindowUtil.setStatus(""); if (rv == 0) { out.println("Robot extracted successfully."); } else if (rv == -1) { out.println("Cancelled."); } } catch (Exception e) { out.println(e); rv = 8; } return rv; } } robocode/robocode/robocode/dialog/ConsoleDialog.java0000644000175000017500000001143011130241114022043 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup *******************************************************************************/ package robocode.dialog; import javax.swing.*; import java.awt.*; import java.awt.datatransfer.StringSelection; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ @SuppressWarnings("serial") public class ConsoleDialog extends JDialog { private JPanel consoleDialogContentPane; private JPanel buttonsPanel; private ConsoleScrollPane scrollPane; private JButton okButton; private JMenu editMenu; private JMenuItem editCopyMenuItem; private JMenuBar consoleDialogMenuBar; private final EventHandler eventHandler = new EventHandler(); private class EventHandler implements ActionListener { public void actionPerformed(ActionEvent e) { if (e.getSource() == ConsoleDialog.this.getOkButton() || e.getSource() == getConsoleDialogContentPane()) { okButtonActionPerformed(); } if (e.getSource() == getEditCopyMenuItem()) { editCopyActionPerformed(); } } } public ConsoleDialog() { super(); initialize(); } public ConsoleDialog(Frame owner, String title, boolean modal) { super(owner, title, modal); initialize(); } public void append(String text) { getScrollPane().append(text); } public void editCopyActionPerformed() { StringSelection ss; String s = getScrollPane().getSelectedText(); if (s == null) { s = getScrollPane().getText(); } ss = new StringSelection(s); Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, null); } private JPanel getButtonsPanel() { if (buttonsPanel == null) { buttonsPanel = new JPanel(); buttonsPanel.setPreferredSize(new Dimension(100, 30)); buttonsPanel.setLayout(new GridBagLayout()); buttonsPanel.setMinimumSize(new Dimension(20, 20)); buttonsPanel.setMaximumSize(new Dimension(1000, 30)); GridBagConstraints constraintsOKButton = new GridBagConstraints(); constraintsOKButton.gridx = 1; constraintsOKButton.gridy = 1; constraintsOKButton.ipadx = 34; constraintsOKButton.insets = new Insets(2, 173, 3, 168); getButtonsPanel().add(getOkButton(), constraintsOKButton); } return buttonsPanel; } private JPanel getConsoleDialogContentPane() { if (consoleDialogContentPane == null) { consoleDialogContentPane = new JPanel(); consoleDialogContentPane.setLayout(new BorderLayout()); consoleDialogContentPane.add(getButtonsPanel(), "South"); consoleDialogContentPane.add(getScrollPane(), "Center"); consoleDialogContentPane.registerKeyboardAction(eventHandler, KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), JComponent.WHEN_FOCUSED); } return consoleDialogContentPane; } public JMenuBar getConsoleDialogMenuBar() { if (consoleDialogMenuBar == null) { consoleDialogMenuBar = new JMenuBar(); consoleDialogMenuBar.add(getEditMenu()); } return consoleDialogMenuBar; } public JMenuItem getEditCopyMenuItem() { if (editCopyMenuItem == null) { editCopyMenuItem = new JMenuItem("Copy"); editCopyMenuItem.addActionListener(eventHandler); } return editCopyMenuItem; } public JMenu getEditMenu() { if (editMenu == null) { editMenu = new JMenu("Edit"); editMenu.add(getEditCopyMenuItem()); } return editMenu; } public JButton getOkButton() { if (okButton == null) { okButton = new JButton(); okButton.setText("OK"); okButton.addActionListener(eventHandler); } return okButton; } private ConsoleScrollPane getScrollPane() { if (scrollPane == null) { scrollPane = new ConsoleScrollPane(); } return scrollPane; } private void initialize() { setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); setSize(426, 240); setContentPane(getConsoleDialogContentPane()); setJMenuBar(getConsoleDialogMenuBar()); } public void okButtonActionPerformed() { dispose(); } public void processStream(java.io.InputStream in) { scrollPane.processStream(in); } public void scrollToBottom() { getScrollPane().scrollToBottom(); } public void setText(String text) { getScrollPane().setText(text); } } robocode/robocode/robocode/dialog/ResultsDialog.java0000644000175000017500000001021011130241114022075 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Rewritten to reuse RankingDialog, which contains buttons etc. *******************************************************************************/ package robocode.dialog; import robocode.BattleResults; import robocode.manager.RobocodeManager; import robocode.ui.BattleResultsTableModel; import javax.swing.*; import javax.swing.table.AbstractTableModel; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; /** * Dialog to display results (scores) of a battle. *

* This class is just a wrapper class used for storing the window position and * dimension. * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ @SuppressWarnings("serial") public class ResultsDialog extends BaseScoreDialog { private JPanel buttonPanel; private JButton okButton; private JButton saveButton; private final BattleResultsTableModel tableModel; private final ButtonEventHandler buttonEventHandler; public ResultsDialog(RobocodeManager manager, BattleResults[] results, int numRounds) { super(manager, true); tableModel = new BattleResultsTableModel(results, numRounds); buttonEventHandler = new ButtonEventHandler(); initialize(); setTitle(((BattleResultsTableModel) getTableModel()).getTitle()); addCancelByEscapeKey(); } private void saveButtonActionPerformed() { manager.getWindowManager().showSaveResultsDialog(tableModel); } private void okButtonActionPerformed() { setVisible(false); } @Override protected AbstractTableModel getTableModel() { return tableModel; } @Override protected JPanel getDialogContentPane() { if (contentPane == null) { contentPane = new JPanel(); contentPane.setLayout(new BorderLayout()); contentPane.add(getScrollPane(), "Center"); contentPane.add(getButtonPanel(), "South"); } return contentPane; } private JPanel getButtonPanel() { if (buttonPanel == null) { buttonPanel = new JPanel(); buttonPanel.setLayout(new BorderLayout()); buttonPanel.add(getOkButton(), "East"); buttonPanel.add(getSaveButton(), "West"); } return buttonPanel; } private JButton getOkButton() { if (okButton == null) { okButton = new JButton(); okButton.setText("OK"); okButton.addActionListener(buttonEventHandler); WindowUtil.setFixedSize(okButton, new Dimension(80, 25)); } return okButton; } private JButton getSaveButton() { if (saveButton == null) { saveButton = new JButton(); saveButton.setText("Save"); saveButton.addActionListener(buttonEventHandler); WindowUtil.setFixedSize(saveButton, new Dimension(80, 25)); } return saveButton; } private void addCancelByEscapeKey() { String CANCEL_ACTION_KEY = "CANCEL_ACTION_KEY"; int noModifiers = 0; KeyStroke escapeKey = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, noModifiers, false); InputMap inputMap = getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); inputMap.put(escapeKey, CANCEL_ACTION_KEY); AbstractAction cancelAction = new AbstractAction() { public void actionPerformed(ActionEvent e) { okButtonActionPerformed(); } }; getRootPane().getActionMap().put(CANCEL_ACTION_KEY, cancelAction); } private class ButtonEventHandler implements ActionListener { public void actionPerformed(ActionEvent e) { Object source = e.getSource(); if (source == ResultsDialog.this.getOkButton()) { okButtonActionPerformed(); } else if (source == ResultsDialog.this.getSaveButton()) { saveButtonActionPerformed(); } } } } robocode/robocode/robocode/dialog/PreferencesRenderingOptionsTab.java0000644000175000017500000002621611130241114025433 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen * - Initial API and implementation *******************************************************************************/ package robocode.dialog; import robocode.manager.RobocodeManager; import robocode.manager.RobocodeProperties; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; /** * @author Flemming N. Larsen (original) */ @SuppressWarnings("serial") public class PreferencesRenderingOptionsTab extends WizardPanel { private final RobocodeManager manager; private JPanel specificSettingsPanel; private JPanel predefinedSettingsPanel; private JPanel otherSettingsPanel; private JComboBox optionsRenderingAntialiasingComboBox; private JComboBox optionsRenderingTextAntialiasingComboBox; private JComboBox optionsRenderingMethodComboBox; private JComboBox optionsRenderingNoBuffersComboBox; private JCheckBox optionsRenderingBufferImagesCheckBox; private JCheckBox optionsRendereringForceBulletColorCheckBox; private JButton predefinedPlaformDefaultButton; private JButton predefinedSpeedButton; private JButton predefinedQualityButton; private EventHandler eventHandler; public PreferencesRenderingOptionsTab(RobocodeManager manager) { super(); this.manager = manager; initialize(); } private void initialize() { eventHandler = new EventHandler(); setLayout(new GridLayout(1, 3)); add(getSpecificSettingsPanel()); add(getPredefinedSettingsPanel()); add(getOtherSettingsPanel()); loadPreferences(manager.getProperties()); } private JPanel getSpecificSettingsPanel() { if (specificSettingsPanel == null) { specificSettingsPanel = new JPanel(); specificSettingsPanel.setBorder( BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Specific settings")); specificSettingsPanel.setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.HORIZONTAL; c.insets = new Insets(5, 5, 5, 5); c.anchor = GridBagConstraints.PAGE_START; c.weightx = 0; c.gridwidth = 2; c.gridx = 0; c.gridy = 0; specificSettingsPanel.add(new JLabel("Set individual rendering options:"), c); c.gridwidth = 1; c.gridy = 1; specificSettingsPanel.add(new JLabel("Antialiasing", SwingConstants.RIGHT), c); c.gridx = 1; specificSettingsPanel.add(getOptionsRenderingAntialiasingComboBox(), c); c.gridx = 0; c.gridy = 2; specificSettingsPanel.add(new JLabel("Text Antialiasing", SwingConstants.RIGHT), c); c.gridx = 1; specificSettingsPanel.add(getOptionsRenderingTextAntialiasingComboBox(), c); c.gridx = 0; c.gridy = 3; specificSettingsPanel.add(new JLabel("Rendering Method", SwingConstants.RIGHT), c); c.gridx = 1; specificSettingsPanel.add(getOptionsRenderingMethodComboBox(), c); c.gridx = 0; c.gridy = 4; specificSettingsPanel.add(new JLabel(" "), c); c.gridx = 0; c.gridy = 5; specificSettingsPanel.add(new JLabel("Number of buffers", SwingConstants.RIGHT), c); c.gridx = 1; specificSettingsPanel.add(getOptionsRenderingNoBuffersComboBox(), c); } return specificSettingsPanel; } private JPanel getPredefinedSettingsPanel() { if (predefinedSettingsPanel == null) { predefinedSettingsPanel = new JPanel(); predefinedSettingsPanel.setBorder( BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Predefined settings")); predefinedSettingsPanel.setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.HORIZONTAL; c.insets = new Insets(5, 5, 5, 5); c.anchor = GridBagConstraints.PAGE_START; c.gridx = 0; c.gridy = 0; c.gridwidth = 3; predefinedSettingsPanel.add(new JLabel("Set all rendering settings towards:"), c); c.weightx = 1f / 3; c.gridwidth = 1; c.gridy = 2; predefinedSettingsPanel.add(getPredefinedPlatformDefaultButton(), c); c.gridx = 1; predefinedSettingsPanel.add(getPredefinedSpeedButton(), c); c.gridx = 2; predefinedSettingsPanel.add(getPredefinedQualityButton(), c); } return predefinedSettingsPanel; } /** * Return the otherSettingsPanel * * @return JPanel */ private JPanel getOtherSettingsPanel() { if (otherSettingsPanel == null) { otherSettingsPanel = new JPanel(); otherSettingsPanel.setBorder( BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Other settings")); otherSettingsPanel.setLayout(new BoxLayout(otherSettingsPanel, BoxLayout.Y_AXIS)); otherSettingsPanel.add(getOptionsRenderingBufferImagesCheckBox()); otherSettingsPanel.add(getOptionsRendereringForceBulletColorCheckBox()); } return otherSettingsPanel; } private JComboBox getOptionsRenderingAntialiasingComboBox() { if (optionsRenderingAntialiasingComboBox == null) { optionsRenderingAntialiasingComboBox = new JComboBox(new String[] { "Default", "On", "Off"}); optionsRenderingAntialiasingComboBox.addActionListener(eventHandler); } return optionsRenderingAntialiasingComboBox; } private JComboBox getOptionsRenderingTextAntialiasingComboBox() { if (optionsRenderingTextAntialiasingComboBox == null) { optionsRenderingTextAntialiasingComboBox = new JComboBox(new String[] { "Default", "On", "Off"}); optionsRenderingTextAntialiasingComboBox.addActionListener(eventHandler); } return optionsRenderingTextAntialiasingComboBox; } private JComboBox getOptionsRenderingMethodComboBox() { if (optionsRenderingMethodComboBox == null) { optionsRenderingMethodComboBox = new JComboBox(new String[] { "Default", "Quality", "Speed"}); optionsRenderingMethodComboBox.addActionListener(eventHandler); } return optionsRenderingMethodComboBox; } private JComboBox getOptionsRenderingNoBuffersComboBox() { if (optionsRenderingNoBuffersComboBox == null) { optionsRenderingNoBuffersComboBox = new JComboBox( new String[] { "Single buffering", "Double buffering", "Tripple buffering"}); optionsRenderingNoBuffersComboBox.addActionListener(eventHandler); } return optionsRenderingNoBuffersComboBox; } private JButton getPredefinedPlatformDefaultButton() { if (predefinedPlaformDefaultButton == null) { predefinedPlaformDefaultButton = new JButton("Default"); predefinedPlaformDefaultButton.setMnemonic('u'); predefinedPlaformDefaultButton.setDisplayedMnemonicIndex(4); predefinedPlaformDefaultButton.addActionListener(eventHandler); } return predefinedPlaformDefaultButton; } private JButton getPredefinedSpeedButton() { if (predefinedSpeedButton == null) { predefinedSpeedButton = new JButton("Speed"); predefinedSpeedButton.setMnemonic('p'); predefinedSpeedButton.setDisplayedMnemonicIndex(1); predefinedSpeedButton.addActionListener(eventHandler); } return predefinedSpeedButton; } private JButton getPredefinedQualityButton() { if (predefinedQualityButton == null) { predefinedQualityButton = new JButton("Quality"); predefinedQualityButton.setMnemonic('Q'); predefinedQualityButton.addActionListener(eventHandler); } return predefinedQualityButton; } /** * Return the optionsRenderingBufferImagesCheckBox * * @return JCheckBox */ private JCheckBox getOptionsRenderingBufferImagesCheckBox() { if (optionsRenderingBufferImagesCheckBox == null) { optionsRenderingBufferImagesCheckBox = new JCheckBox("Buffer images (uses memory)"); optionsRenderingBufferImagesCheckBox.setMnemonic('i'); optionsRenderingBufferImagesCheckBox.setDisplayedMnemonicIndex(7); optionsRenderingBufferImagesCheckBox.addActionListener(eventHandler); } return optionsRenderingBufferImagesCheckBox; } /** * Return the optionsRendereringForceBulletColorBox * * @return JCheckBox */ private JCheckBox getOptionsRendereringForceBulletColorCheckBox() { if (optionsRendereringForceBulletColorCheckBox == null) { optionsRendereringForceBulletColorCheckBox = new JCheckBox("Make all bullets white"); optionsRendereringForceBulletColorCheckBox.setMnemonic('M'); optionsRendereringForceBulletColorCheckBox.addActionListener(eventHandler); } return optionsRendereringForceBulletColorCheckBox; } private void loadPreferences(RobocodeProperties props) { getOptionsRenderingAntialiasingComboBox().setSelectedIndex(props.getOptionsRenderingAntialiasing()); getOptionsRenderingTextAntialiasingComboBox().setSelectedIndex(props.getOptionsRenderingTextAntialiasing()); getOptionsRenderingMethodComboBox().setSelectedIndex(props.getOptionsRenderingMethod()); getOptionsRenderingNoBuffersComboBox().setSelectedIndex(props.getOptionsRenderingNoBuffers() - 1); getOptionsRenderingBufferImagesCheckBox().setSelected(props.getOptionsRenderingBufferImages()); getOptionsRendereringForceBulletColorCheckBox().setSelected(props.getOptionsRenderingForceBulletColor()); } public void storePreferences() { RobocodeProperties props = manager.getProperties(); props.setOptionsRenderingAntialiasing(optionsRenderingAntialiasingComboBox.getSelectedIndex()); props.setOptionsRenderingTextAntialiasing(optionsRenderingTextAntialiasingComboBox.getSelectedIndex()); props.setOptionsRenderingMethod(optionsRenderingMethodComboBox.getSelectedIndex()); props.setOptionsRenderingNoBuffers(optionsRenderingNoBuffersComboBox.getSelectedIndex() + 1); props.setOptionsRenderingBufferImages(optionsRenderingBufferImagesCheckBox.isSelected()); props.setOptionsRenderingForceBulletColor(optionsRendereringForceBulletColorCheckBox.isSelected()); manager.saveProperties(); } @Override public boolean isReady() { return true; } private void setPredefinedSettings(int index) { optionsRenderingAntialiasingComboBox.setSelectedIndex(index); optionsRenderingTextAntialiasingComboBox.setSelectedIndex(index); optionsRenderingMethodComboBox.setSelectedIndex(index); } private class EventHandler implements ActionListener { public void actionPerformed(ActionEvent e) { Object src = e.getSource(); if (src == predefinedPlaformDefaultButton) { setPredefinedSettings(0); } else if (src == predefinedQualityButton) { setPredefinedSettings(1); } else if (src == predefinedSpeedButton) { setPredefinedSettings(2); } else if (src == optionsRenderingBufferImagesCheckBox) { // Reset images so they are reloaded and gets buffered or unbuffered new Thread() { @Override public void run() { storePreferences(); manager.getImageManager().initialize(); } }.start(); return; } manager.getWindowManager().getRobocodeFrame().getBattleView().setInitialized(false); } } } robocode/robocode/robocode/dialog/BattleDialog.java0000644000175000017500000001544511130241114021666 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.dialog; import robocode.control.events.BattleAdaptor; import robocode.common.IXmlSerializable; import robocode.common.XmlWriter; import robocode.control.events.*; import robocode.control.snapshot.ITurnSnapshot; import robocode.io.Logger; import robocode.manager.RobocodeManager; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.io.StringWriter; /** * @author Pavel Savara (original) */ public class BattleDialog extends JFrame { private static final long serialVersionUID = 1L; private final BattleObserver battleObserver = new BattleObserver(); private ConsoleScrollPane scrollPane; private ConsoleScrollPane xmlPane; private JTabbedPane tabbedPane; private JButton okButton; private JButton clearButton; private JPanel battleDialogContentPane; private JPanel buttonPanel; private final RobocodeManager manager; private final BattleButton battleButton; private boolean isListening; private ITurnSnapshot lastSnapshot; private boolean paintSnapshot; public BattleDialog(RobocodeManager manager, BattleButton battleButton) { this.manager = manager; this.battleButton = battleButton; initialize(); } private void initialize() { this.setTitle("Main battle log"); this.add(getBattleDialogContentPane()); pack(); } public void detach() { if (isListening) { manager.getWindowManager().removeBattleListener(battleObserver); isListening = false; } battleButton.detach(); } public void reset() { getConsoleScrollPane().setText(null); getTurnScrollPane().setText(null); lastSnapshot = null; } public void attach() { if (!isListening) { isListening = true; manager.getWindowManager().addBattleListener(battleObserver); } } /** * When robotDialog is packed, we want to set a reasonable size. However, * after that, we need a null preferred size so the scrollpane will scroll. * (preferred size should be based on the text inside) */ @Override public void pack() { getConsoleScrollPane().setPreferredSize(new Dimension(426, 200)); super.pack(); getTabbedPane().setPreferredSize(null); } private JPanel getBattleDialogContentPane() { if (battleDialogContentPane == null) { battleDialogContentPane = new JPanel(); battleDialogContentPane.setLayout(new BorderLayout()); battleDialogContentPane.add(getTabbedPane()); battleDialogContentPane.add(getButtonPanel(), BorderLayout.SOUTH); } return battleDialogContentPane; } private JPanel getButtonPanel() { if (buttonPanel == null) { buttonPanel = new JPanel(); buttonPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); buttonPanel.add(getOkButton()); buttonPanel.add(getClearButton()); } return buttonPanel; } private JButton getOkButton() { if (okButton == null) { okButton = getNewButton("OK"); } return okButton; } private JButton getClearButton() { if (clearButton == null) { clearButton = getNewButton("Clear"); } return clearButton; } private JButton getNewButton(String text) { JButton button = new JButton(text); button.addActionListener(eventHandler); return button; } private final ActionListener eventHandler = new ActionListener() { public void actionPerformed(ActionEvent e) { Object src = e.getSource(); if (src == BattleDialog.this.getOkButton()) { okButtonActionPerformed(); } else if (src == BattleDialog.this.getClearButton()) { clearButtonActionPerformed(); } } }; private JTabbedPane getTabbedPane() { if (tabbedPane == null) { tabbedPane = new JTabbedPane(); tabbedPane.setLayout(new BorderLayout()); tabbedPane.addTab("Console", getConsoleScrollPane()); tabbedPane.addTab("Turn Snapshot", getTurnScrollPane()); // tabbedPane.setSelectedIndex(0); tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); tabbedPane.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { paintSnapshot = (tabbedPane.getSelectedIndex() == 1); paintSnapshot(); } }); } return tabbedPane; } private ConsoleScrollPane getConsoleScrollPane() { if (scrollPane == null) { scrollPane = new ConsoleScrollPane(); JTextArea textPane = scrollPane.getTextPane(); textPane.setBackground(Color.DARK_GRAY); textPane.setForeground(Color.WHITE); } return scrollPane; } private ConsoleScrollPane getTurnScrollPane() { if (xmlPane == null) { xmlPane = new ConsoleScrollPane(); } return xmlPane; } private void okButtonActionPerformed() { dispose(); } private void clearButtonActionPerformed() { reset(); } private void paintSnapshot() { if (paintSnapshot) { if (lastSnapshot != null) { final StringWriter writer = new StringWriter(); final XmlWriter xmlWriter = new XmlWriter(writer, true); try { ((IXmlSerializable) lastSnapshot).writeXml(xmlWriter, null); writer.close(); } catch (IOException e) { Logger.logError(e); } getTurnScrollPane().setText(writer.toString()); } else { getTurnScrollPane().setText(null); } } } private class BattleObserver extends BattleAdaptor { @Override public void onBattleMessage(BattleMessageEvent event) { final String text = event.getMessage(); if (text != null && text.length() > 0) { getConsoleScrollPane().append(text + "\n"); getConsoleScrollPane().scrollToBottom(); } } @Override public void onBattleError(BattleErrorEvent event) { final String text = event.getError(); if (text != null && text.length() > 0) { getConsoleScrollPane().append(text + "\n"); getConsoleScrollPane().scrollToBottom(); } } @Override public void onTurnEnded(TurnEndedEvent event) { lastSnapshot = event.getTurnSnapshot(); paintSnapshot(); } public void onBattleStarted(final BattleStartedEvent event) { reset(); } @Override public void onBattleFinished(BattleFinishedEvent event) { lastSnapshot = null; paintSnapshot(); } } } robocode/robocode/robocode/dialog/AboutBox.java0000644000175000017500000001701711130241114021053 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Rewritten to use a JEditorPane with HTML content *******************************************************************************/ package robocode.dialog; import robocode.manager.RobocodeManager; import javax.swing.*; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; /** * The About box * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ @SuppressWarnings("serial") public final class AboutBox extends JDialog { private final static Color BG_COLOR = SystemColor.controlHighlight; // Tag used for Robocode version replacement private final static String TAG_ROBOCODE_VERSION = ""; // Tag used for Robocode icon source replacement private final static String TAG_ROBOCODE_ICON_SRC = ""; // Tag used for Robocode icon source replacement private final static String TAG_SYSCOLOR_CTRL_HIGHLIGHT = ""; // Tag used for Java version replacement private final static String TAG_JAVA_VERSION = ""; // Tag used for Java vendor replacement private final static String TAG_JAVA_VENDOR = ""; // HTML template containing text for the AboutBox private final static String HTML_TEMPLATE = "" + "
" + "
Robocode

" + "© Copyright 2001, 2008
Mathew A. Nelson and Robocode contributors
Version: " + TAG_ROBOCODE_VERSION + "

robocode.sourceforge.net
 

" + "Original Author
Designed and programmed by Mathew A. Nelson
Graphics by Garett S. Hourihan

" + "Featuring RoboRumble@Home
Originally designed and programmed by Albert Prez

" + "Main Contributors:
Flemming N. Larsen (Robocode administrator, developer, integrator, lots of features),
" + "Pavel Savara (Robocode administrator, developer, integrator, robot interfaces, battle events, refactorings),

" + "Other Contributors:
Cubic Creative (the design and ideas for the JuniorRobot class),
" + "Christian D. Schnell (for the Codesize utility),
" + "Luis Crespo (sound engine, single-step debugging, ranking panel),
" + "Matthew Reeder (editor enhancements, keyboard shortcuts, HyperThreading bugfixes),
" + "Titus Chen (bugfixes for robot teleportation, bad wall collision detection, team ranking,
" + "replay scores and robot color flickering),
" + "Robert D. Maupin (optimizations with collections and improved CPU constant benchmark),
" + "Ascander Jr (graphics for ground tiles),
" + "Stefan Westen (onPaint method from RobocodeSG),
" + "Nathaniel Troutman (fixing memory leaks due to circular references)
" + "Aaron Rotenberg (for the Robot Cache Cleaner utility),
" + "Julian Kent (nano precision timing of allowed robot time),
" + "Joachim Hofer (fixing problem with wrong results in RoboRumble),
" + "Endre Palatinus, Eniko Nagy, Attila Csizofszki and Laszlo Vigh (score % in results/rankings)

" + "Java Runtime Environment
Java " + TAG_JAVA_VERSION + " by " + TAG_JAVA_VENDOR + "
"; // Robocode version private final String robocodeVersion; // Robocode icon URL private final java.net.URL iconURL; // Content pane private JPanel aboutBoxContentPane; // Main panel private JEditorPane mainPanel; // Button panel private JPanel buttonPanel; // OK button private JButton okButton; // HTML text after tag replacements private String htmlText; // General event handler private final ActionListener eventHandler = new ActionListener() { public void actionPerformed(ActionEvent e) { if (e.getSource() == AboutBox.this.getOkButton()) { AboutBox.this.dispose(); } } }; // Hyperlink event handler private final HyperlinkListener hyperlinkHandler = new HyperlinkListener() { public void hyperlinkUpdate(HyperlinkEvent event) { if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { try { robocode.manager.BrowserManager.openURL(event.getURL().toExternalForm()); } catch (IOException e) { e.printStackTrace(); } } } }; public AboutBox(Frame owner, RobocodeManager manager) { super(owner, true); robocodeVersion = manager.getVersionManager().getVersion(); iconURL = ClassLoader.class.getResource("/resources/icons/robocode-icon.png"); setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); setTitle("About Robocode"); setContentPane(getAboutBoxContentPane()); setResizable(false); } private JPanel getAboutBoxContentPane() { if (aboutBoxContentPane == null) { aboutBoxContentPane = new JPanel(); aboutBoxContentPane.setLayout(new BorderLayout()); aboutBoxContentPane.add(getButtonPanel(), BorderLayout.SOUTH); aboutBoxContentPane.add(getMainPanel(), BorderLayout.CENTER); } return aboutBoxContentPane; } private JEditorPane getMainPanel() { if (mainPanel == null) { mainPanel = new JEditorPane("text/html", getHtmlText()); mainPanel.setBackground(BG_COLOR); mainPanel.setEditable(false); mainPanel.addHyperlinkListener(hyperlinkHandler); } return mainPanel; } private JPanel getButtonPanel() { if (buttonPanel == null) { buttonPanel = new JPanel(); buttonPanel.setBackground(BG_COLOR); buttonPanel.setLayout(new FlowLayout()); buttonPanel.add(getOkButton()); } return buttonPanel; } private JButton getOkButton() { if (okButton == null) { okButton = new JButton(); okButton.setText("OK"); okButton.addActionListener(eventHandler); } return okButton; } private String getHtmlText() { if (htmlText == null) { htmlText = HTML_TEMPLATE.replaceAll(TAG_ROBOCODE_VERSION, robocodeVersion).replaceAll(TAG_ROBOCODE_ICON_SRC, iconURL.toString()).replaceAll(TAG_SYSCOLOR_CTRL_HIGHLIGHT, toHtmlColor(BG_COLOR)).replaceAll(TAG_JAVA_VERSION, System.getProperty("java.version")).replaceAll( TAG_JAVA_VENDOR, System.getProperty("java.vendor")); } return htmlText; } private static String toHtmlColor(Color color) { return "#" + toHexDigits(color.getRed()) + toHexDigits(color.getGreen()) + toHexDigits(color.getBlue()); } private static String toHexDigits(int value) { return "" + toHexDigit(value >> 4) + toHexDigit(value & 0x0f); } private static char toHexDigit(int value) { int v = (value & 0xf); if (v < 10) { return (char) ('0' + v); } return (char) ('A' + (v - 10)); } } robocode/robocode/robocode/dialog/BaseScoreDialog.java0000644000175000017500000001275511130241114022322 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.dialog; import robocode.manager.RobocodeManager; import javax.swing.*; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableColumn; import java.awt.*; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; /** * @author Pavel Savara (original) */ @SuppressWarnings("serial") public abstract class BaseScoreDialog extends JDialog { protected final RobocodeManager manager; private final EventHandler eventHandler = new EventHandler(); protected JPanel contentPane; protected JScrollPane scrollPane; protected JTable table; protected Dimension tableSize; public BaseScoreDialog(RobocodeManager manager, boolean modal) { super(manager.getWindowManager().getRobocodeFrame(), modal); this.manager = manager; } protected void initialize() { addComponentListener(eventHandler); setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE); setContentPane(getDialogContentPane()); } /** * Return the content pane. * * @return JPanel */ protected JPanel getDialogContentPane() { if (contentPane == null) { contentPane = new JPanel(); contentPane.setLayout(new BorderLayout()); contentPane.add(getScrollPane(), "Center"); } return contentPane; } /** * Return the scroll pane * * @return JScrollPane */ protected JScrollPane getScrollPane() { if (scrollPane == null) { scrollPane = new JScrollPane(); scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); scrollPane.getViewport().setScrollMode(JViewport.BLIT_SCROLL_MODE); scrollPane.setViewportView(getTable()); scrollPane.setColumnHeaderView(table.getTableHeader()); scrollPane.addComponentListener(eventHandler); tableSize = new Dimension(getTable().getColumnModel().getTotalColumnWidth(), getTable().getModel().getRowCount() * (getTable().getRowHeight())); table.setPreferredScrollableViewportSize(tableSize); table.setPreferredSize(tableSize); table.setMinimumSize(tableSize); } return scrollPane; } /** * Return the table. * * @return JTable */ protected JTable getTable() { if (table == null) { table = new JTable(); table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); table.setColumnSelectionAllowed(true); table.setRowSelectionAllowed(true); table.getTableHeader().setReorderingAllowed(false); setResultsData(); pack(); } return table; } private class EventHandler implements ComponentListener { public void componentShown(ComponentEvent e) { onDialogShown(); } public void componentHidden(ComponentEvent e) { onDialogHidden(); } public void componentResized(ComponentEvent e) { if (e.getSource() == BaseScoreDialog.this.getScrollPane()) { scrollPaneComponentResized(); } } public void componentMoved(ComponentEvent e) {} } protected abstract AbstractTableModel getTableModel(); protected void onDialogShown() {} protected void onDialogHidden() { dispose(); } protected void scrollPaneComponentResized() { // This code is not working... Dimension scrollPaneExtent = getScrollPane().getViewport().getExtentSize(); if (tableSize != null && (tableSize.width < scrollPaneExtent.width)) { getTable().setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS); getTable().setSize(scrollPaneExtent); getTable().sizeColumnsToFit(-1); } else { if (tableSize != null) { getTable().setSize(tableSize); getTable().sizeColumnsToFit(-1); } table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); } validate(); repaint(); } protected void setResultsData() { getTable().setModel(getTableModel()); int maxScoreColWidth = 0; for (int x = 0; x < getTableModel().getColumnCount(); x++) { if (x != 1) { getTable().getColumnModel().getColumn(x).setCellRenderer(new ResultsTableCellRenderer(false)); } TableColumn column = getTable().getColumnModel().getColumn(x); Component comp; column.setHeaderRenderer(new ResultsTableCellRenderer(true)); comp = column.getHeaderRenderer().getTableCellRendererComponent(null, column.getHeaderValue(), false, false, 0, 0); int width = comp.getPreferredSize().width; for (int y = 0; y < getTableModel().getRowCount(); y++) { comp = getTable().getDefaultRenderer(getTableModel().getColumnClass(x)).getTableCellRendererComponent( getTable(), getTableModel().getValueAt(y, x), false, false, 0, x); if (comp.getPreferredSize().width > width) { width = comp.getPreferredSize().width; } } TableColumn col = getTable().getColumnModel().getColumn(x); col.setPreferredWidth(width); col.setMinWidth(width); col.setWidth(width); if (x >= 3 && width > maxScoreColWidth) { maxScoreColWidth = width; } } } } robocode/robocode/robocode/dialog/WindowPositionManager.java0000644000175000017500000001234211130241112023611 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup * - Moved this class from the robocode.util package into the robocode.dialog * package * - Changed to use FileUtil.getWindowConfigFile() * - Added missing close() on FileInputStream and FileOutputStream *******************************************************************************/ package robocode.dialog; import robocode.io.FileUtil; import robocode.io.Logger; import java.awt.*; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.Properties; import java.util.StringTokenizer; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ public class WindowPositionManager implements ComponentListener { private Properties windowPositions; public WindowPositionManager() { super(); } public Properties getWindowPositions() { if (windowPositions == null) { windowPositions = new Properties(); FileInputStream in = null; try { in = new FileInputStream(FileUtil.getWindowConfigFile()); windowPositions.load(in); } catch (FileNotFoundException e) { Logger.logMessage("Creating " + FileUtil.getWindowConfigFile().getName() + " file"); } catch (Exception e) { Logger.logError(e); } finally { if (in != null) { try { in.close(); } catch (IOException ignored) {} } } } return windowPositions; } public void componentHidden(ComponentEvent e) {} public void componentMoved(ComponentEvent e) { // Hack, because we cannot detect maximized frame in Java 1.3 if (e.getComponent().getBounds().getWidth() >= Toolkit.getDefaultToolkit().getScreenSize().width || e.getComponent().getBounds().getHeight() >= Toolkit.getDefaultToolkit().getScreenSize().height) { return; } setWindowRect((Window) e.getComponent(), e.getComponent().getBounds()); } public void componentResized(ComponentEvent e) { // Hack, because we cannot detect maximized frame in Java 1.3 if (e.getComponent().getBounds().getWidth() >= Toolkit.getDefaultToolkit().getScreenSize().width || e.getComponent().getBounds().getHeight() >= Toolkit.getDefaultToolkit().getScreenSize().height) { return; } setWindowRect((Window) e.getComponent(), e.getComponent().getBounds()); } public void componentShown(ComponentEvent e) {} public void setWindowRect(Window w, Rectangle rect) { String rString = rect.x + "," + rect.y + "," + rect.width + "," + rect.height; getWindowPositions().put(w.getClass().getName(), rString); } public Rectangle getWindowRect(Window window) { window.addComponentListener(this); String rString = (String) getWindowPositions().get(window.getClass().getName()); if (rString == null) { return null; } StringTokenizer tokenizer = new StringTokenizer(rString, ","); int x = Integer.parseInt(tokenizer.nextToken()); int y = Integer.parseInt(tokenizer.nextToken()); int width = Integer.parseInt(tokenizer.nextToken()); int height = Integer.parseInt(tokenizer.nextToken()); return fitWindowBoundsToScreen(new Rectangle(x, y, width, height)); } public void saveWindowPositions() { FileOutputStream out = null; try { out = new FileOutputStream(FileUtil.getWindowConfigFile()); getWindowPositions().store(out, "Robocode window sizes"); } catch (IOException e) { Logger.logError("Warning: Unable to save window positions: ", e); } finally { if (out != null) { try { out.close(); } catch (IOException ignored) {} } } } private Rectangle fitWindowBoundsToScreen(Rectangle windowBounds) { if (windowBounds == null) { return null; } // Return the input window bounds, if we can find a screen device that contains these bounds final GraphicsEnvironment gfxEnv = GraphicsEnvironment.getLocalGraphicsEnvironment(); final GraphicsDevice[] screenDevices = gfxEnv.getScreenDevices(); for (int i = screenDevices.length - 1; i >= 0; i--) { GraphicsConfiguration[] gfxCfg = screenDevices[i].getConfigurations(); for (int j = gfxCfg.length - 1; j >= 0; j--) { if (gfxCfg[j].getBounds().contains(windowBounds.getLocation())) { return windowBounds; // Found the bounds } } } // Otherwise, return window bounds at a location within the current screen final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); int x = (screenSize.width - windowBounds.width) / 2; int y = (screenSize.height - windowBounds.height) / 2; return new Rectangle(x, y, windowBounds.width, windowBounds.height); } } robocode/robocode/robocode/dialog/ConsoleScrollPane.java0000644000175000017500000000620111130241114022706 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup * Pavel Savara * - number of rows limited *******************************************************************************/ package robocode.dialog; import javax.swing.*; import java.awt.*; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ @SuppressWarnings("serial") public class ConsoleScrollPane extends JScrollPane { private final int MAX_ROWS = 500; private JTextArea textPane; private int lines; private final Rectangle bottomRect = new Rectangle(0, 32767, 1, 1); public ConsoleScrollPane() { super(); initialize(); } public void append(String text) { lines++; getTextPane().append(text); if (lines > MAX_ROWS) { lines = 0; final String[] rows = getTextPane().getText().split("\n"); StringBuilder sb = new StringBuilder(); final int from = Math.min(rows.length, Math.max((MAX_ROWS / 2), rows.length - (MAX_ROWS / 2))); for (int i = from; i < rows.length; i++) { sb.append(rows[i]); sb.append('\n'); lines++; } getTextPane().setText(sb.toString()); } } public Dimension getAreaSize() { return getTextPane().getPreferredSize(); } public String getSelectedText() { return getTextPane().getSelectedText(); } public String getText() { return getTextPane().getText(); } public JTextArea getTextPane() { if (textPane == null) { textPane = new JTextArea(); textPane.setBackground(Color.lightGray); textPane.setBounds(0, 0, 1000, 1000); textPane.setEditable(false); } return textPane; } private void initialize() { lines = 0; setViewportView(getTextPane()); } public void processStream(InputStream input) { BufferedReader br = new BufferedReader(new InputStreamReader(input)); String line; try { while ((line = br.readLine()) != null) { int tabIndex = line.indexOf("\t"); while (tabIndex >= 0) { line = line.substring(0, tabIndex) + " " + line.substring(tabIndex + 1); tabIndex = line.indexOf("\t"); } append(line + "\n"); } } catch (IOException e) { append("IOException: " + e); } scrollToBottom(); } private final Runnable scroller = new Runnable() { public void run() { getViewport().scrollRectToVisible(bottomRect); getViewport().repaint(); } }; public void scrollToBottom() { SwingUtilities.invokeLater(scroller); } public void setText(String text) { getTextPane().setText(text); } } robocode/robocode/robocode/dialog/PreferencesDialog.java0000644000175000017500000001210411130241114022701 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Added Rendering Options tab * - Added Sound Options tab * - Added Common Options tab * - Code cleanup * Matthew Reeder * - Added keyboard mnemonics to View Options and Development Options tabs *******************************************************************************/ package robocode.dialog; import robocode.manager.RobocodeManager; import javax.swing.*; import java.awt.*; import java.awt.event.KeyEvent; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Matthew Reeder (contributor) */ @SuppressWarnings("serial") public class PreferencesDialog extends JDialog implements WizardListener { private JPanel preferencesDialogContentPane; private WizardTabbedPane tabbedPane; private WizardController buttonsPanel; private PreferencesViewOptionsTab viewOptionsTab; private PreferencesRenderingOptionsTab renderingOptionsTab; private PreferencesSoundOptionsTab soundOptionsTab; private PreferencesDevelopmentOptionsTab developmentOptionsTab; private PreferencesCommonOptionsTab commonOptionsTab; private final RobocodeManager manager; public PreferencesDialog(RobocodeManager manager) { super(manager.getWindowManager().getRobocodeFrame(), true); this.manager = manager; initialize(); } private void initialize() { setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); setTitle("Preferences"); setContentPane(getPreferencesDialogContentPane()); } public void cancelButtonActionPerformed() { dispose(); } private WizardController getButtonsPanel() { if (buttonsPanel == null) { buttonsPanel = getTabbedPane().getWizardController(); } return buttonsPanel; } private JPanel getPreferencesDialogContentPane() { getButtonsPanel(); if (preferencesDialogContentPane == null) { preferencesDialogContentPane = new JPanel(); preferencesDialogContentPane.setLayout(new BorderLayout()); preferencesDialogContentPane.add(getTabbedPane(), BorderLayout.CENTER); preferencesDialogContentPane.add(getButtonsPanel(), BorderLayout.SOUTH); } return preferencesDialogContentPane; } private WizardTabbedPane getTabbedPane() { if (tabbedPane == null) { tabbedPane = new WizardTabbedPane(this); tabbedPane.insertTab("View Options", null, getViewOptionsTab(), null, 0); tabbedPane.setMnemonicAt(0, KeyEvent.VK_W); tabbedPane.setDisplayedMnemonicIndexAt(0, 3); tabbedPane.insertTab("Rendering Options", null, getRenderingOptionsTab(), null, 1); tabbedPane.setMnemonicAt(1, KeyEvent.VK_R); tabbedPane.setDisplayedMnemonicIndexAt(1, 0); tabbedPane.insertTab("Sound Options", null, getSoundOptionsTab(), null, 2); tabbedPane.setMnemonicAt(2, KeyEvent.VK_S); tabbedPane.setDisplayedMnemonicIndexAt(2, 0); tabbedPane.insertTab("Development Options", null, getDevelopmentOptionsTab(), null, 3); tabbedPane.setMnemonicAt(3, KeyEvent.VK_D); tabbedPane.setDisplayedMnemonicIndexAt(3, 0); tabbedPane.insertTab("Common Options", null, getCommonOptionsTab(), null, 4); tabbedPane.setMnemonicAt(4, KeyEvent.VK_O); tabbedPane.setDisplayedMnemonicIndexAt(4, 1); } return tabbedPane; } private JPanel getViewOptionsTab() { if (viewOptionsTab == null) { viewOptionsTab = new PreferencesViewOptionsTab(manager); } return viewOptionsTab; } private JPanel getRenderingOptionsTab() { if (renderingOptionsTab == null) { renderingOptionsTab = new PreferencesRenderingOptionsTab(manager); } return renderingOptionsTab; } private JPanel getSoundOptionsTab() { if (soundOptionsTab == null) { soundOptionsTab = new PreferencesSoundOptionsTab(manager); } return soundOptionsTab; } private JPanel getDevelopmentOptionsTab() { if (developmentOptionsTab == null) { developmentOptionsTab = new PreferencesDevelopmentOptionsTab(manager); } return developmentOptionsTab; } private JPanel getCommonOptionsTab() { if (commonOptionsTab == null) { commonOptionsTab = new PreferencesCommonOptionsTab(manager); } return commonOptionsTab; } public void finishButtonActionPerformed() { viewOptionsTab.storePreferences(); renderingOptionsTab.storePreferences(); soundOptionsTab.storePreferences(); developmentOptionsTab.storePreferences(); commonOptionsTab.storePreferences(); // Make sure the BattleView will use the new setting immediately manager.getWindowManager().getRobocodeFrame().getBattleView().setDisplayOptions(); // TODO: Find better solution? dispose(); } } robocode/robocode/robocode/dialog/Wizard.java0000644000175000017500000000214111130241112020556 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation *******************************************************************************/ package robocode.dialog; import java.awt.*; /** * @author Mathew A. Nelson (original) */ public interface Wizard { public abstract void back(); public abstract Component getCurrentPanel(); public abstract WizardController getWizardController(); WizardListener getWizardListener(); public abstract boolean isBackAvailable(); public abstract boolean isNextAvailable(); public abstract boolean isReady(); public abstract void next(); void setWizardControllerOnPanel(WizardPanel panel); } robocode/robocode/robocode/dialog/TeamCreator.java0000644000175000017500000001536011130241112021533 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Matthew Reeder * - Added keyboard mnemonics to buttons * Flemming N. Larsen * - Code cleanup * - Changed the F5 key press for refreshing the list of available robots * into 'modifier key' + R to comply with other OSes like e.g. Mac OS *******************************************************************************/ package robocode.dialog; import robocode.manager.IRepositoryManager; import robocode.manager.RobocodeManager; import robocode.repository.TeamSpecification; import static robocode.ui.ShortcutUtil.MENU_SHORTCUT_KEY_MASK; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; /** * @author Mathew A. Nelson (original) * @author Matthew Reeder (contributor) * @author Flemming N. Larsen (contributor) */ @SuppressWarnings("serial") public class TeamCreator extends JDialog implements WizardListener { private JPanel teamCreatorContentPane; private WizardCardPanel wizardPanel; private WizardController wizardController; private RobotSelectionPanel robotSelectionPanel; private TeamCreatorOptionsPanel teamCreatorOptionsPanel; private final int minRobots = 2; private final int maxRobots = 10; private final IRepositoryManager repositoryManager; private final RobocodeManager manager; private final EventHandler eventHandler = new EventHandler(); class EventHandler implements ActionListener { public void actionPerformed(ActionEvent e) { if (e.getActionCommand().equals("Refresh")) { getRobotSelectionPanel().refreshRobotList(true); } } } public TeamCreator(IRepositoryManager repositoryManager) { super(repositoryManager.getManager().getWindowManager().getRobocodeFrame()); this.repositoryManager = repositoryManager; this.manager = repositoryManager.getManager(); initialize(); } protected TeamCreatorOptionsPanel getTeamCreatorOptionsPanel() { if (teamCreatorOptionsPanel == null) { teamCreatorOptionsPanel = new TeamCreatorOptionsPanel(this); } return teamCreatorOptionsPanel; } private JPanel getTeamCreatorContentPane() { if (teamCreatorContentPane == null) { teamCreatorContentPane = new JPanel(); teamCreatorContentPane.setLayout(new BorderLayout()); teamCreatorContentPane.add(getWizardController(), BorderLayout.SOUTH); teamCreatorContentPane.add(getWizardPanel(), BorderLayout.CENTER); getWizardPanel().getWizardController().setFinishButtonTextAndMnemonic("Create Team!", 'C', 0); teamCreatorContentPane.registerKeyboardAction(eventHandler, "Refresh", KeyStroke.getKeyStroke(KeyEvent.VK_R, MENU_SHORTCUT_KEY_MASK), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); teamCreatorContentPane.registerKeyboardAction(eventHandler, "Refresh", KeyStroke.getKeyStroke(KeyEvent.VK_R, MENU_SHORTCUT_KEY_MASK), JComponent.WHEN_FOCUSED); } return teamCreatorContentPane; } protected RobotSelectionPanel getRobotSelectionPanel() { if (robotSelectionPanel == null) { robotSelectionPanel = new RobotSelectionPanel(manager, minRobots, maxRobots, false, "Select the robots for this team.", false, true, true, false, false, false, null); } return robotSelectionPanel; } private WizardCardPanel getWizardPanel() { if (wizardPanel == null) { wizardPanel = new WizardCardPanel(this); wizardPanel.add(getRobotSelectionPanel(), "Select robots"); wizardPanel.add(getTeamCreatorOptionsPanel(), "Select options"); } return wizardPanel; } public void initialize() { setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); setTitle("Create a team"); setContentPane(getTeamCreatorContentPane()); } private WizardController getWizardController() { if (wizardController == null) { wizardController = getWizardPanel().getWizardController(); } return wizardController; } public void cancelButtonActionPerformed() { dispose(); } public void finishButtonActionPerformed() { try { int rc = createTeam(); if (rc == 0) { JOptionPane.showMessageDialog(this, "Team created successfully.", "Success", JOptionPane.INFORMATION_MESSAGE, null); this.dispose(); } else { JOptionPane.showMessageDialog(this, "Team creation cancelled", "Cancelled", JOptionPane.INFORMATION_MESSAGE, null); } } catch (IOException e) { JOptionPane.showMessageDialog(this, e.toString(), "Team Creation Failed", JOptionPane.ERROR_MESSAGE, null); } } public int createTeam() throws IOException { File f = new File(repositoryManager.getRobotsDirectory(), teamCreatorOptionsPanel.getTeamPackage().replace('.', File.separatorChar) + teamCreatorOptionsPanel.getTeamNameField().getText() + ".team"); if (f.exists()) { int ok = JOptionPane.showConfirmDialog(this, f + " already exists. Are you sure you want to replace it?", "Warning", JOptionPane.YES_NO_CANCEL_OPTION); if (ok == JOptionPane.NO_OPTION || ok == JOptionPane.CANCEL_OPTION) { return -1; } } if (!f.getParentFile().exists()) { f.getParentFile().mkdirs(); } TeamSpecification teamSpec = new TeamSpecification(); URL u = null; String w = teamCreatorOptionsPanel.getWebpageField().getText(); if (w != null && w.length() > 0) { try { u = new URL(w); } catch (MalformedURLException e) { try { u = new URL("http://" + w); teamCreatorOptionsPanel.getWebpageField().setText(u.toString()); } catch (MalformedURLException ignored) {} } } teamSpec.setTeamWebpage(u); teamSpec.setTeamDescription(teamCreatorOptionsPanel.getDescriptionArea().getText()); teamSpec.setTeamAuthorName(teamCreatorOptionsPanel.getAuthorField().getText()); teamSpec.setMembers(robotSelectionPanel.getSelectedRobotsAsString()); teamSpec.setRobocodeVersion(manager.getVersionManager().getVersion()); FileOutputStream out = null; try { out = new FileOutputStream(f); teamSpec.store(out, "Robocode robot team"); } finally { if (out != null) { out.close(); } } repositoryManager.clearRobotList(); return 0; } } robocode/robocode/robocode/dialog/RankingDialog.java0000644000175000017500000000755111130241114022043 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Luis Crespo & Mathew A. Nelson * - Original implementation * Flemming N. Larsen * - Totally rewritten to contain the functionality for both the * RankingDialog and ResultsDialog (code reuse) * - Changed to be a independent frame instead of a dialog * - Changed to pack the dialog to fit the table with the rankings * Nathaniel Troutman * - Bugfix: Added cleanup to prevent memory leaks with the battle object in * okButtonActionPerformed() *******************************************************************************/ package robocode.dialog; import robocode.control.events.BattleAdaptor; import robocode.control.events.BattleFinishedEvent; import robocode.control.events.TurnEndedEvent; import robocode.control.snapshot.ITurnSnapshot; import robocode.manager.RobocodeManager; import robocode.ui.BattleRankingTableModel; import javax.swing.*; import javax.swing.table.AbstractTableModel; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.concurrent.atomic.AtomicReference; /** * Frame to display the battle results or ranking during battles. * * @author Mathew A. Nelson (original) * @author Luis Crespo (original) * @author Flemming N. Larsen (contributor) * @author Nathaniel Troutman (contributor) */ @SuppressWarnings("serial") public class RankingDialog extends BaseScoreDialog { private final BattleRankingTableModel tableModel; private final Timer timerTask; private final BattleObserver battleObserver; private final AtomicReference snapshot; private ITurnSnapshot lastSnapshot; private int lastRows; public RankingDialog(RobocodeManager manager) { super(manager, false); battleObserver = new BattleObserver(); timerTask = new Timer(1000 / 2, new TimerTask()); snapshot = new AtomicReference(); lastRows = 0; tableModel = new BattleRankingTableModel(); initialize(); setTitle("Ranking"); } @Override protected AbstractTableModel getTableModel() { return tableModel; } private void update() { final ITurnSnapshot current = snapshot.get(); if (lastSnapshot != current) { lastSnapshot = current; tableModel.updateSource(lastSnapshot); if (table.getModel().getRowCount() != lastRows) { lastRows = table.getModel().getRowCount(); table.setPreferredSize( new Dimension(table.getColumnModel().getTotalColumnWidth(), table.getModel().getRowCount() * table.getRowHeight())); table.setPreferredScrollableViewportSize(table.getPreferredSize()); pack(); } repaint(); } } protected void onDialogShown() { manager.getWindowManager().addBattleListener(battleObserver); timerTask.start(); } protected void onDialogHidden() { manager.getWindowManager().getRobocodeFrame().getRobocodeMenuBar().getOptionsShowRankingCheckBoxMenuItem().setState( false); timerTask.stop(); manager.getWindowManager().removeBattleListener(battleObserver); dispose(); } private class BattleObserver extends BattleAdaptor { @Override public void onBattleFinished(BattleFinishedEvent event) { snapshot.set(null); } @Override public void onTurnEnded(TurnEndedEvent event) { snapshot.set(event.getTurnSnapshot()); } } private class TimerTask implements ActionListener { public void actionPerformed(ActionEvent e) { update(); } } } robocode/robocode/robocode/dialog/WizardController.java0000644000175000017500000001214011130241112022622 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Matthew Reeder * - Added keyboard mnemonics to standard wizard buttons * Flemming N. Larsen * - Code cleanup *******************************************************************************/ package robocode.dialog; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; /** * @author Mathew A. Nelson (original) * @author Matthew Reeder (contributor) * @author Flemming N. Larsen (contributor) */ @SuppressWarnings("serial") public class WizardController extends JPanel implements ChangeListener { private final EventHandler eventHandler = new EventHandler(); private JButton backButton; private JButton nextButton; private JButton finishButton; private JButton cancelButton; private boolean focusOnEnabled; class EventHandler implements ActionListener { public void actionPerformed(ActionEvent e) { if (e.getSource() == WizardController.this.getFinishButton()) { finishButtonActionPerformed(); } if (e.getSource() == WizardController.this.getCancelButton()) { cancelButtonActionPerformed(); } if (e.getSource() == WizardController.this.getNextButton()) { nextButtonActionPerformed(); } if (e.getSource() == WizardController.this.getBackButton()) { backButtonActionPerformed(); } } } private void backButtonActionPerformed() { wizard.back(); } private void cancelButtonActionPerformed() { wizard.getWizardListener().cancelButtonActionPerformed(); } private void finishButtonActionPerformed() { wizard.getWizardListener().finishButtonActionPerformed(); } /** * Return the backButton * * @return JButton */ private JButton getBackButton() { if (backButton == null) { backButton = new JButton(); backButton.setText("Back"); backButton.setMnemonic('B'); backButton.addActionListener(eventHandler); } return backButton; } /** * Return the cancelButton * * @return JButton */ private JButton getCancelButton() { if (cancelButton == null) { cancelButton = new JButton(); cancelButton.setText("Cancel"); cancelButton.setMnemonic('C'); cancelButton.addActionListener(eventHandler); } return cancelButton; } /** * Return the finishButton * * @return JButton */ private JButton getFinishButton() { if (finishButton == null) { finishButton = new JButton(); finishButton.setText("Finish"); finishButton.setMnemonic('F'); finishButton.addActionListener(eventHandler); } return finishButton; } public void setFinishButtonText(String text) { getFinishButton().setText(text); } public void setFinishButtonTextAndMnemonic(String text, char mnemonic, int mnemonicIndex) { getFinishButton().setText(text); getFinishButton().setMnemonic(mnemonic); getFinishButton().setDisplayedMnemonicIndex(mnemonicIndex); } /** * Return the nextButton * * @return JButton */ private JButton getNextButton() { if (nextButton == null) { nextButton = new JButton(); nextButton.setText("Next"); nextButton.setMnemonic('N'); nextButton.addActionListener(eventHandler); } return nextButton; } /** * Initialize the class. */ private void initialize() { add(getBackButton()); add(getNextButton()); add(new JLabel(" ")); add(getFinishButton()); add(getCancelButton()); } private void nextButtonActionPerformed() { wizard.next(); } private void setBackButtonEnabled(boolean enabled) { getBackButton().setEnabled(enabled); } public void setFinishButtonEnabled(boolean enabled) { getFinishButton().setEnabled(enabled); if (focusOnEnabled && enabled) { getFinishButton().requestFocus(); } } private void setNextButtonEnabled(boolean enabled) { getNextButton().setEnabled(enabled); } private Wizard wizard = null; protected WizardController(Wizard wizard) { super(); this.wizard = wizard; initialize(); stateChanged(null); } public void stateChanged(ChangeEvent e) { setBackButtonEnabled(wizard.isBackAvailable()); setNextButtonEnabled(wizard.isNextAvailable()); setFinishButtonEnabled(wizard.isReady()); } /** * Gets the focusOnEnabled. * * @return Returns a boolean */ public boolean getFocusOnEnabled() { return focusOnEnabled; } /** * Sets the focusOnEnabled. * * @param focusOnEnabled The focusOnEnabled to set */ public void setFocusOnEnabled(boolean focusOnEnabled) { this.focusOnEnabled = focusOnEnabled; } } robocode/robocode/robocode/dialog/PreferencesSoundOptionsTab.java0000644000175000017500000003241411130241114024603 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen * - Initial API and implementation *******************************************************************************/ package robocode.dialog; import robocode.manager.RobocodeManager; import robocode.manager.RobocodeProperties; import javax.sound.sampled.*; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Vector; /** * @author Flemming N. Larsen (original) */ @SuppressWarnings("serial") public class PreferencesSoundOptionsTab extends WizardPanel { private final RobocodeManager manager; private final EventHandler eventHandler = new EventHandler(); private JPanel soundOptionsPanel; private JPanel mixerOptionsPanel; private JCheckBox enableSoundCheckBox; private JCheckBox enableGunshotCheckBox; private JCheckBox enableBulletHitCheckBox; private JCheckBox enableRobotDeathCheckBox; private JCheckBox enableWallCollisionCheckBox; private JCheckBox enableRobotCollisionCheckBox; private JButton enableAllSoundsButton; private JButton disableAllSoundsButton; private JComboBox mixerComboBox; private JButton mixerDefaultButton; private JCheckBox enableMixerVolumeCheckBox; private JCheckBox enableMixerPanCheckBox; public PreferencesSoundOptionsTab(RobocodeManager manager) { super(); this.manager = manager; initialize(); } private void initialize() { setLayout(new GridLayout(1, 3)); add(getSoundOptionsPanel()); add(getMixerOptionsPanel()); add(new JPanel()); loadPreferences(manager.getProperties()); } private JPanel getSoundOptionsPanel() { if (soundOptionsPanel == null) { soundOptionsPanel = new JPanel(); soundOptionsPanel.setBorder( BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Sound Effects")); soundOptionsPanel.setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); c.fill = 1; c.weightx = 1; c.anchor = GridBagConstraints.NORTHWEST; c.gridwidth = GridBagConstraints.REMAINDER; soundOptionsPanel.add(getEnableSoundCheckBox(), c); soundOptionsPanel.add(getEnableGunshotCheckBox(), c); soundOptionsPanel.add(getEnableBulletHitCheckBox(), c); soundOptionsPanel.add(getEnableRobotDeathCheckBox(), c); soundOptionsPanel.add(getEnableWallCollisionCheckBox(), c); soundOptionsPanel.add(getEnableRobotCollisionCheckBox(), c); soundOptionsPanel.add(new JLabel(" "), c); c.gridwidth = 1; c.fill = 0; c.weighty = 1; c.weightx = 0; soundOptionsPanel.add(getEnableAllSoundsButton(), c); c.weightx = 1; c.gridwidth = GridBagConstraints.REMAINDER; soundOptionsPanel.add(getDisableAllSoundsButton(), c); if (AudioSystem.getMixerInfo().length == 0) { for (Component child : soundOptionsPanel.getComponents()) { child.setEnabled(false); } } } return soundOptionsPanel; } private JCheckBox getEnableSoundCheckBox() { if (enableSoundCheckBox == null) { enableSoundCheckBox = new JCheckBox("Enable Sound"); enableSoundCheckBox.setMnemonic('E'); } return enableSoundCheckBox; } private JCheckBox getEnableGunshotCheckBox() { if (enableGunshotCheckBox == null) { enableGunshotCheckBox = new JCheckBox("Gun Shots"); enableGunshotCheckBox.setMnemonic('G'); } return enableGunshotCheckBox; } private JCheckBox getEnableBulletHitCheckBox() { if (enableBulletHitCheckBox == null) { enableBulletHitCheckBox = new JCheckBox("Bullet Hit"); enableBulletHitCheckBox.setMnemonic('H'); enableBulletHitCheckBox.setDisplayedMnemonicIndex(7); } return enableBulletHitCheckBox; } private JCheckBox getEnableRobotDeathCheckBox() { if (enableRobotDeathCheckBox == null) { enableRobotDeathCheckBox = new JCheckBox("Robot Death Explosions"); enableRobotDeathCheckBox.setMnemonic('x'); enableRobotDeathCheckBox.setDisplayedMnemonicIndex(13); } return enableRobotDeathCheckBox; } private JCheckBox getEnableRobotCollisionCheckBox() { if (enableRobotCollisionCheckBox == null) { enableRobotCollisionCheckBox = new JCheckBox("Robot Collisions"); enableRobotCollisionCheckBox.setMnemonic('t'); enableRobotCollisionCheckBox.setDisplayedMnemonicIndex(4); } return enableRobotCollisionCheckBox; } private JCheckBox getEnableWallCollisionCheckBox() { if (enableWallCollisionCheckBox == null) { enableWallCollisionCheckBox = new JCheckBox("Wall Collisions"); enableWallCollisionCheckBox.setMnemonic('l'); enableWallCollisionCheckBox.setDisplayedMnemonicIndex(2); } return enableWallCollisionCheckBox; } private JButton getEnableAllSoundsButton() { if (enableAllSoundsButton == null) { enableAllSoundsButton = new JButton("Enable all"); enableAllSoundsButton.setMnemonic('a'); enableAllSoundsButton.setDisplayedMnemonicIndex(7); enableAllSoundsButton.addActionListener(eventHandler); } return enableAllSoundsButton; } private JButton getDisableAllSoundsButton() { if (disableAllSoundsButton == null) { disableAllSoundsButton = new JButton("Disable all"); disableAllSoundsButton.setMnemonic('i'); disableAllSoundsButton.setDisplayedMnemonicIndex(1); disableAllSoundsButton.addActionListener(eventHandler); } return disableAllSoundsButton; } private JPanel getMixerOptionsPanel() { if (mixerOptionsPanel == null) { mixerOptionsPanel = new JPanel(); mixerOptionsPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Mixer")); mixerOptionsPanel.setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); c.anchor = GridBagConstraints.NORTHWEST; c.fill = GridBagConstraints.NONE; c.weightx = 1; c.insets = new Insets(3, 3, 3, 3); mixerOptionsPanel.add(new JLabel("Select mixer:"), c); c.gridy = 1; mixerOptionsPanel.add(getMixerComboBox(), c); c.insets = new Insets(3, 3, 15, 3); c.gridy = 2; mixerOptionsPanel.add(getMixerDefaultButton(), c); c.insets = new Insets(3, 3, 3, 3); c.gridy = 3; mixerOptionsPanel.add(new JLabel("Enable mixer features:"), c); c.insets = new Insets(0, 0, 0, 0); c.gridy = 4; mixerOptionsPanel.add(getEnableMixerVolumeCheckBox(), c); c.gridy = 5; mixerOptionsPanel.add(getEnableMixerPanCheckBox(), c); if (AudioSystem.getMixerInfo().length == 0) { for (Component child : mixerOptionsPanel.getComponents()) { child.setEnabled(false); } } } return mixerOptionsPanel; } private JComboBox getMixerComboBox() { if (mixerComboBox == null) { Mixer.Info[] mixerInfo = AudioSystem.getMixerInfo(); Line.Info clipLineInfo = new Line.Info(Clip.class); Vector mixers = new Vector(); for (Mixer.Info mi : mixerInfo) { if (AudioSystem.getMixer(mi).getSourceLineInfo(clipLineInfo).length > 0) { mixers.add(mi); } } mixerComboBox = new JComboBox(mixers); mixerComboBox.setRenderer(new MixerInfoCellRenderer()); mixerComboBox.addActionListener(eventHandler); } return mixerComboBox; } private JButton getMixerDefaultButton() { if (mixerDefaultButton == null) { mixerDefaultButton = new JButton("Default"); mixerDefaultButton.setMnemonic('u'); mixerDefaultButton.setDisplayedMnemonicIndex(4); mixerDefaultButton.addActionListener(eventHandler); } return mixerDefaultButton; } private JCheckBox getEnableMixerVolumeCheckBox() { if (enableMixerVolumeCheckBox == null) { enableMixerVolumeCheckBox = new JCheckBox("Volume"); enableMixerVolumeCheckBox.setMnemonic('V'); enableMixerVolumeCheckBox.addActionListener(eventHandler); } return enableMixerVolumeCheckBox; } private JCheckBox getEnableMixerPanCheckBox() { if (enableMixerPanCheckBox == null) { enableMixerPanCheckBox = new JCheckBox("Pan"); enableMixerPanCheckBox.setMnemonic('P'); enableMixerPanCheckBox.addActionListener(eventHandler); } return enableMixerPanCheckBox; } private void loadPreferences(RobocodeProperties robocodeProperties) { getEnableSoundCheckBox().setSelected(robocodeProperties.getOptionsSoundEnableSound()); getEnableGunshotCheckBox().setSelected(robocodeProperties.getOptionsSoundEnableGunshot()); getEnableBulletHitCheckBox().setSelected(robocodeProperties.getOptionsSoundEnableBulletHit()); getEnableRobotDeathCheckBox().setSelected(robocodeProperties.getOptionsSoundEnableRobotDeath()); getEnableRobotCollisionCheckBox().setSelected(robocodeProperties.getOptionsSoundEnableRobotCollision()); getEnableWallCollisionCheckBox().setSelected(robocodeProperties.getOptionsSoundEnableWallCollision()); getEnableMixerVolumeCheckBox().setSelected(robocodeProperties.getOptionsSoundEnableMixerVolume()); getEnableMixerPanCheckBox().setSelected(robocodeProperties.getOptionsSoundEnableMixerPan()); setMixerCompoBox(robocodeProperties.getOptionsSoundMixer()); } public void storePreferences() { RobocodeProperties props = manager.getProperties(); props.setOptionsSoundEnableSound(getEnableSoundCheckBox().isSelected()); props.setOptionsSoundEnableGunshot(getEnableGunshotCheckBox().isSelected()); props.setOptionsSoundEnableBulletHit(getEnableBulletHitCheckBox().isSelected()); props.setOptionsSoundEnableRobotDeath(getEnableRobotDeathCheckBox().isSelected()); props.setOptionsSoundEnableRobotCollision(getEnableRobotCollisionCheckBox().isSelected()); props.setOptionsSoundEnableWallCollision(getEnableWallCollisionCheckBox().isSelected()); props.setOptionsSoundEnableMixerVolume(getEnableMixerVolumeCheckBox().isSelected()); props.setOptionsSoundEnableMixerPan(getEnableMixerPanCheckBox().isSelected()); Mixer mixer = AudioSystem.getMixer((Mixer.Info) getMixerComboBox().getSelectedItem()); props.setOptionsSoundMixer(mixer.getClass().getSimpleName()); manager.saveProperties(); } @Override public boolean isReady() { return true; } private void setMixerCompoBox(String mixerName) { for (Mixer.Info mi : AudioSystem.getMixerInfo()) { if (AudioSystem.getMixer(mi).getClass().getSimpleName().equals(mixerName)) { getMixerComboBox().setSelectedItem(mi); break; } } } private class EventHandler implements ActionListener { public void actionPerformed(ActionEvent e) { Object src = e.getSource(); if (src == enableAllSoundsButton) { enableAllSoundsButtonActionPerformed(); } else if (src == disableAllSoundsButton) { disableAllSoundsButtonActionPerformed(); } else if (src == mixerComboBox) { mixerComboBoxActionPerformed(); } else if (src == mixerDefaultButton) { mixerDefaultButtonActionPerformed(); } } } private void enableAllSoundsButtonActionPerformed() { enableSoundCheckBox.setSelected(true); enableGunshotCheckBox.setSelected(true); enableBulletHitCheckBox.setSelected(true); enableRobotDeathCheckBox.setSelected(true); enableWallCollisionCheckBox.setSelected(true); enableRobotCollisionCheckBox.setSelected(true); } private void disableAllSoundsButtonActionPerformed() { enableSoundCheckBox.setSelected(false); enableGunshotCheckBox.setSelected(false); enableBulletHitCheckBox.setSelected(false); enableRobotDeathCheckBox.setSelected(false); enableWallCollisionCheckBox.setSelected(false); enableRobotCollisionCheckBox.setSelected(false); } private void mixerComboBoxActionPerformed() { Mixer mixer = AudioSystem.getMixer((Mixer.Info) mixerComboBox.getSelectedItem()); Line.Info lineInfo = mixer.getSourceLineInfo(new Line.Info(Clip.class))[0]; boolean volumeSupported; boolean panSupported; try { Line line = mixer.getLine(lineInfo); volumeSupported = line.isControlSupported(FloatControl.Type.MASTER_GAIN); panSupported = line.isControlSupported(FloatControl.Type.PAN); } catch (LineUnavailableException e) { volumeSupported = false; panSupported = false; } enableMixerVolumeCheckBox.setEnabled(volumeSupported); enableMixerPanCheckBox.setEnabled(panSupported); } private void mixerDefaultButtonActionPerformed() { setMixerCompoBox("DirectAudioDevice"); } private static class MixerInfoCellRenderer extends javax.swing.plaf.basic.BasicComboBoxRenderer { @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { Component component = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); Mixer.Info mi = (Mixer.Info) value; if (mi != null) { String text = mi.getName(); if (!"Unknown Version".equals(mi.getVersion())) { text += ' ' + mi.getVersion(); } if (!"Unknown Vendor".equals(mi.getVendor())) { text += " by " + mi.getVendor(); } setText(text); } return component; } } } robocode/robocode/robocode/dialog/RcSplashScreen.java0000644000175000017500000000714211130241114022205 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup * - Changed to render the Robocode logo instead of using a bitmap image * - Replaced isPainted() and painted field with wait/notify *******************************************************************************/ package robocode.dialog; import robocode.gfx.RobocodeLogo; import robocode.manager.RobocodeManager; import javax.swing.*; import javax.swing.border.EtchedBorder; import java.awt.*; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import java.awt.image.BufferedImage; /** * The splash screen. * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ @SuppressWarnings("serial") public class RcSplashScreen extends JWindow { private final static Color LABEL_COLOR = Color.WHITE; private JLabel splashLabel; private JPanel splashPanel; private JPanel splashScreenContentPane; private Image splashImage; private final String version; private final WindowListener eventHandler = new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { if (e.getSource() == RcSplashScreen.this) { RcSplashScreen.this.dispose(); } } }; public RcSplashScreen(RobocodeManager manager) { super(); this.version = manager.getVersionManager().getVersion(); initialize(); } public JLabel getSplashLabel() { if (splashLabel == null) { splashLabel = new JLabel(); splashLabel.setText(""); splashLabel.setForeground(LABEL_COLOR); splashLabel.setOpaque(false); } return splashLabel; } private JPanel getSplashPanel() { if (splashPanel == null) { splashPanel = new JPanel() { @Override public void paintComponent(Graphics g) { g.drawImage(splashImage, 0, 0, null); g.setColor(LABEL_COLOR); g.setFont(new Font("Arial", 1, 12)); FontMetrics fm = g.getFontMetrics(); g.drawString("Version: " + version, splashImage.getWidth(null) - fm.stringWidth("Version: " + version), splashImage.getHeight(null) - 4); } @Override public Dimension getPreferredSize() { return new Dimension(splashImage.getWidth(null), splashImage.getHeight(null)); } }; splashPanel.setLayout(new BorderLayout()); splashPanel.add(getSplashLabel(), BorderLayout.NORTH); } return splashPanel; } private JPanel getSplashScreenContentPane() { if (splashScreenContentPane == null) { splashScreenContentPane = new JPanel(); splashScreenContentPane.setBorder(new EtchedBorder()); splashScreenContentPane.setLayout(new BorderLayout()); splashScreenContentPane.add(getSplashPanel(), "Center"); } return splashScreenContentPane; } private void initialize() { splashImage = new BufferedImage(RobocodeLogo.WIDTH, RobocodeLogo.HEIGHT, BufferedImage.TYPE_INT_RGB); new RobocodeLogo().paintLogoWithTanks(splashImage.getGraphics()); setContentPane(getSplashScreenContentPane()); addWindowListener(eventHandler); } @Override public void paint(Graphics g) { super.paint(g); } } robocode/robocode/robocode/dialog/TeamCreatorOptionsPanel.java0000644000175000017500000002160711130241112024070 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Replaced FileSpecificationVector with plain Vector * - LimitedClassnameDocument and LimitedDocument was moved to the * robocode.text package * - Code cleanup * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap *******************************************************************************/ package robocode.dialog; import robocode.repository.FileSpecification; import robocode.text.LimitedClassnameDocument; import robocode.text.LimitedDocument; import javax.swing.*; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import java.awt.*; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.net.URL; import java.util.List; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Robert D. Maupin (contributor) */ @SuppressWarnings("serial") public class TeamCreatorOptionsPanel extends WizardPanel { TeamCreator teamCreator; robocode.packager.RobotPackager teamPackager; final EventHandler eventHandler = new EventHandler(); JLabel authorLabel; JTextField authorField; JLabel descriptionLabel; JTextArea descriptionArea; JLabel webpageLabel; JTextField webpageField; JLabel webpageHelpLabel; JLabel teamNameLabel; JLabel teamPackageLabel; JTextField teamNameField; private String teamPackage; class EventHandler implements ComponentListener, DocumentListener { public void insertUpdate(DocumentEvent e) { fireStateChanged(); } public void changedUpdate(DocumentEvent e) { fireStateChanged(); } public void removeUpdate(DocumentEvent e) { fireStateChanged(); } public void componentMoved(ComponentEvent e) {} public void componentHidden(ComponentEvent e) {} public void componentShown(ComponentEvent e) { List selectedRobots; if (teamCreator != null) { selectedRobots = teamCreator.getRobotSelectionPanel().getSelectedRobots(); } else { selectedRobots = teamPackager.getRobotSelectionPanel().getSelectedRobots(); } if (selectedRobots != null) { FileSpecification robotSpecification = selectedRobots.get(0); getTeamNameLabel().setText("Please choose a name for your team: (Must be a valid Java classname)"); getTeamNameField().setText(robotSpecification.getNameManager().getShortClassName() + "Team"); getTeamPackageLabel().setText(robotSpecification.getNameManager().getFullPackage() + "."); teamPackage = robotSpecification.getNameManager().getFullPackage(); if (teamPackage != null) { teamPackage += "."; } String d = robotSpecification.getDescription(); if (d == null) { d = ""; } getDescriptionArea().setText(d); String a = robotSpecification.getAuthorName(); if (a == null) { a = ""; } getAuthorField().setText(a); URL u = robotSpecification.getWebpage(); if (u == null) { getWebpageField().setText(""); } else { getWebpageField().setText(u.toString()); } getAuthorLabel().setVisible(true); getAuthorField().setVisible(true); getWebpageLabel().setVisible(true); getWebpageField().setVisible(true); getWebpageHelpLabel().setVisible(true); getDescriptionLabel().setText( "Please enter a short description of this team (up to 3 lines of 72 chars each)."); } } public void componentResized(ComponentEvent e) {} } public JPanel robotListPanel; public TeamCreatorOptionsPanel(TeamCreator teamCreator) { super(); this.teamCreator = teamCreator; initialize(); } public TeamCreatorOptionsPanel(robocode.packager.RobotPackager teamPackager) { super(); this.teamPackager = teamPackager; initialize(); } private void initialize() { setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); getTeamNameLabel().setAlignmentX(Component.LEFT_ALIGNMENT); add(getTeamNameLabel()); JPanel p = new JPanel(); p.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); p.setAlignmentX(Component.LEFT_ALIGNMENT); getTeamNameField().setAlignmentX(Component.LEFT_ALIGNMENT); getTeamNameField().setMaximumSize(getTeamNameField().getPreferredSize()); // getVersionField().setMaximumSize(getVersionField().getPreferredSize()); p.setMaximumSize(new Dimension(Integer.MAX_VALUE, getTeamNameField().getPreferredSize().height)); p.add(getTeamPackageLabel()); p.add(getTeamNameField()); add(p); JLabel label = new JLabel(" "); label.setAlignmentX(Component.LEFT_ALIGNMENT); add(label); label = new JLabel(" "); label.setAlignmentX(Component.LEFT_ALIGNMENT); add(label); add(getDescriptionLabel()); JScrollPane scrollPane = new JScrollPane(getDescriptionArea(), ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); scrollPane.setMaximumSize(scrollPane.getPreferredSize()); scrollPane.setMinimumSize(new Dimension(100, scrollPane.getPreferredSize().height)); scrollPane.setAlignmentX(Component.LEFT_ALIGNMENT); add(scrollPane); label = new JLabel(" "); label.setAlignmentX(Component.LEFT_ALIGNMENT); add(label); add(getAuthorLabel()); getAuthorField().setAlignmentX(Component.LEFT_ALIGNMENT); getAuthorField().setMaximumSize(getAuthorField().getPreferredSize()); add(getAuthorField()); label = new JLabel(" "); label.setAlignmentX(Component.LEFT_ALIGNMENT); add(label); add(getWebpageLabel()); getWebpageField().setAlignmentX(Component.LEFT_ALIGNMENT); getWebpageField().setMaximumSize(getWebpageField().getPreferredSize()); add(getWebpageField()); getWebpageHelpLabel().setAlignmentX(Component.LEFT_ALIGNMENT); add(getWebpageHelpLabel()); JPanel panel = new JPanel(); panel.setAlignmentX(Component.LEFT_ALIGNMENT); add(panel); addComponentListener(eventHandler); } @Override public boolean isReady() { return getTeamNameField().getText().length() != 0 && getDescriptionArea().getText().length() != 0; } private JLabel getAuthorLabel() { if (authorLabel == null) { authorLabel = new JLabel("Please enter your name. (optional)"); authorLabel.setAlignmentX(Component.LEFT_ALIGNMENT); } return authorLabel; } public JTextField getAuthorField() { if (authorField == null) { authorField = new JTextField(40); } return authorField; } public JLabel getDescriptionLabel() { if (descriptionLabel == null) { descriptionLabel = new JLabel(""); descriptionLabel.setAlignmentX(Component.LEFT_ALIGNMENT); } return descriptionLabel; } public JTextArea getDescriptionArea() { if (descriptionArea == null) { LimitedDocument doc = new LimitedDocument(3, 72); descriptionArea = new JTextArea(doc, null, 3, 72); doc.addDocumentListener(eventHandler); // descriptionArea.setMaximumSize(descriptionArea.getPreferredScrollableViewportSize()); // descriptionArea.setLineWrap(true); // descriptionArea.setWrapStyleWord(true); } return descriptionArea; } public JLabel getWebpageLabel() { if (webpageLabel == null) { webpageLabel = new JLabel("Please enter a URL for your team's webpage (optional)"); webpageLabel.setAlignmentX(Component.LEFT_ALIGNMENT); } return webpageLabel; } public JTextField getWebpageField() { if (webpageField == null) { webpageField = new JTextField(40); } return webpageField; } public JLabel getWebpageHelpLabel() { if (webpageHelpLabel == null) { webpageHelpLabel = new JLabel(""); } return webpageHelpLabel; } public JTextField getTeamNameField() { if (teamNameField == null) { LimitedDocument doc = new LimitedClassnameDocument(1, 32); teamNameField = new JTextField(doc, null, 32); doc.addDocumentListener(eventHandler); } return teamNameField; } public JLabel getTeamNameLabel() { if (teamNameLabel == null) { teamNameLabel = new JLabel(""); } return teamNameLabel; } public JLabel getTeamPackageLabel() { if (teamPackageLabel == null) { teamPackageLabel = new JLabel(""); } return teamPackageLabel; } /** * Gets the teamPackage. * * @return Returns a String */ public String getTeamPackage() { return (teamPackage != null) ? teamPackage : "."; } } robocode/robocode/robocode/dialog/WizardPanel.java0000644000175000017500000000236411130241112021545 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup *******************************************************************************/ package robocode.dialog; import javax.swing.event.ChangeEvent; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ public abstract class WizardPanel extends javax.swing.JPanel { private static final long serialVersionUID = 1L; private WizardController wizardController; public void fireStateChanged() { if (wizardController != null) { wizardController.stateChanged(new ChangeEvent(this)); } } public abstract boolean isReady(); public void setWizardController(WizardController wizardController) { this.wizardController = wizardController; } } robocode/robocode/robocode/dialog/PreferencesViewOptionsTab.java0000644000175000017500000003676211130241114024437 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Added visible ground, visible explosions, and visible explosion debris * option * - Changed some keyboard mnemonics * - Changed from using FPS into using TPS (Turns per Second), but added a * "Display FPS in titlebar" option * - Added propery listener for getting TPS updated from TPS slider * - Removed "Allow color changes" as this is always possible with the * current rendering engine * - Code cleanup * Matthew Reeder * - Added keyboard mnemonics to buttons and other controls *******************************************************************************/ package robocode.dialog; import robocode.manager.RobocodeManager; import robocode.manager.RobocodeProperties; import javax.swing.*; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Matthew Reeder (contributor) */ @SuppressWarnings("serial") public class PreferencesViewOptionsTab extends WizardPanel { private static final int MIN_TPS = 1; private static final int DEFAULT_TPS = 30; private static final int FAST_TPS = 45; private static final int MAX_TPS = 10000; private final EventHandler eventHandler = new EventHandler(); private JCheckBox visibleRobotEnergyCheckBox; private JCheckBox visibleRobotNameCheckBox; private JCheckBox visibleScanArcsCheckBox; private JCheckBox visibleExplosionsCheckBox; private JCheckBox visibleGroundCheckBox; private JCheckBox visibleExplosionDebrisCheckBox; private JButton defaultViewOptionsButton; private JButton enableAllViewOptionsButton; private JButton disableAllViewOptionsButton; private JTextField desiredTpsTextField; private JLabel desiredTpsLabel; private JCheckBox displayFpsCheckBox; private JCheckBox displayTpsCheckBox; private JPanel visibleOptionsPanel; private JPanel tpsOptionsPanel; private JButton minTpsButton; private JButton defaultTpsButton; private JButton fastTpsButton; private JButton maxTpsButton; private final RobocodeManager manager; private class EventHandler implements ActionListener, DocumentListener { public void actionPerformed(ActionEvent e) { Object src = e.getSource(); if (src == enableAllViewOptionsButton) { enableAllViewOptionsButtonActionPerformed(); } else if (src == disableAllViewOptionsButton) { disableAllViewOptionsButtonActionPerformed(); } else if (src == defaultViewOptionsButton) { defaultViewOptionsButtonActionPerformed(); } else if (src == defaultTpsButton) { defaultTpsButtonActionPerformed(); } else if (src == minTpsButton) { minTpsButtonActionPerformed(); } else if (src == fastTpsButton) { fastTpsButtonActionPerformed(); } else if (src == maxTpsButton) { maxTpsButtonActionPerformed(); } } public void changedUpdate(DocumentEvent e) { PreferencesViewOptionsTab.this.desiredTpsTextFieldStateChanged(); } public void insertUpdate(DocumentEvent e) { PreferencesViewOptionsTab.this.desiredTpsTextFieldStateChanged(); } public void removeUpdate(DocumentEvent e) { PreferencesViewOptionsTab.this.desiredTpsTextFieldStateChanged(); } } public PreferencesViewOptionsTab(RobocodeManager manager) { super(); this.manager = manager; initialize(); } private void defaultViewOptionsButtonActionPerformed() { enableAllViewOptionsButtonActionPerformed(); getVisibleScanArcsCheckBox().setSelected(false); } private void enableAllViewOptionsButtonActionPerformed() { getVisibleRobotEnergyCheckBox().setSelected(true); getVisibleRobotNameCheckBox().setSelected(true); getVisibleScanArcsCheckBox().setSelected(true); getVisibleExplosionsCheckBox().setSelected(true); getVisibleGroundCheckBox().setSelected(true); getVisibleExplosionDebrisCheckBox().setSelected(true); } private void disableAllViewOptionsButtonActionPerformed() { getVisibleRobotEnergyCheckBox().setSelected(false); getVisibleRobotNameCheckBox().setSelected(false); getVisibleScanArcsCheckBox().setSelected(false); getVisibleExplosionsCheckBox().setSelected(false); getVisibleGroundCheckBox().setSelected(false); getVisibleExplosionDebrisCheckBox().setSelected(false); } private void desiredTpsTextFieldStateChanged() { fireStateChanged(); try { int tps = Integer.parseInt(getDesiredTpsTextField().getText()); String s = "" + tps; if (tps < MIN_TPS) { s = "Too low, must be at least " + MIN_TPS; } else if (tps > MAX_TPS) { s = "Too high, max is " + MAX_TPS; } getDesiredTpsLabel().setText("Desired TPS: " + s); } catch (NumberFormatException e) { getDesiredTpsLabel().setText("Desired TPS: ???"); } } private void maxTpsButtonActionPerformed() { getDesiredTpsTextField().setText("" + MAX_TPS); } private void minTpsButtonActionPerformed() { getDesiredTpsTextField().setText("" + MIN_TPS); } private void fastTpsButtonActionPerformed() { getDesiredTpsTextField().setText("" + FAST_TPS); } private void defaultTpsButtonActionPerformed() { getDesiredTpsTextField().setText("" + DEFAULT_TPS); } private JButton getDefaultViewOptionsButton() { if (defaultViewOptionsButton == null) { defaultViewOptionsButton = new JButton("Defaults"); defaultViewOptionsButton.setMnemonic('u'); defaultViewOptionsButton.setDisplayedMnemonicIndex(4); defaultViewOptionsButton.addActionListener(eventHandler); } return defaultViewOptionsButton; } private JButton getEnableAllViewOptionsButton() { if (enableAllViewOptionsButton == null) { enableAllViewOptionsButton = new JButton("Enable all"); enableAllViewOptionsButton.setMnemonic('a'); enableAllViewOptionsButton.setDisplayedMnemonicIndex(7); enableAllViewOptionsButton.addActionListener(eventHandler); } return enableAllViewOptionsButton; } private JButton getDisableAllViewOptionsButton() { if (disableAllViewOptionsButton == null) { disableAllViewOptionsButton = new JButton("Disable all"); disableAllViewOptionsButton.setMnemonic('i'); disableAllViewOptionsButton.setDisplayedMnemonicIndex(1); disableAllViewOptionsButton.addActionListener(eventHandler); } return disableAllViewOptionsButton; } private JLabel getDesiredTpsLabel() { if (desiredTpsLabel == null) { desiredTpsLabel = new JLabel("Desired TPS: "); } return desiredTpsLabel; } private JTextField getDesiredTpsTextField() { if (desiredTpsTextField == null) { desiredTpsTextField = new JTextField(); desiredTpsTextField.setColumns(5); desiredTpsTextField.getDocument().addDocumentListener(eventHandler); } return desiredTpsTextField; } private JCheckBox getDisplayFpsCheckBox() { if (displayFpsCheckBox == null) { displayFpsCheckBox = new JCheckBox("Display FPS in titlebar"); displayFpsCheckBox.setMnemonic('P'); displayFpsCheckBox.setDisplayedMnemonicIndex(9); } return displayFpsCheckBox; } private JCheckBox getDisplayTpsCheckBox() { if (displayTpsCheckBox == null) { displayTpsCheckBox = new JCheckBox("Display TPS in titlebar"); displayTpsCheckBox.setMnemonic('T'); displayTpsCheckBox.setDisplayedMnemonicIndex(8); } return displayTpsCheckBox; } private JButton getDefaultTpsButton() { if (defaultTpsButton == null) { defaultTpsButton = new JButton("Default"); defaultTpsButton.addActionListener(eventHandler); } return defaultTpsButton; } private JButton getMinTpsButton() { if (minTpsButton == null) { minTpsButton = new JButton("Minimum"); minTpsButton.addActionListener(eventHandler); } return minTpsButton; } private JButton getMaxTpsButton() { if (maxTpsButton == null) { maxTpsButton = new JButton("Max"); maxTpsButton.addActionListener(eventHandler); } return maxTpsButton; } private JButton getFastTpsButton() { if (fastTpsButton == null) { fastTpsButton = new JButton("Fast"); fastTpsButton.addActionListener(eventHandler); } return fastTpsButton; } private JPanel getTpsOptionsPanel() { if (tpsOptionsPanel == null) { tpsOptionsPanel = new JPanel(); tpsOptionsPanel.setBorder( BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Turns Per Second (TPS)")); tpsOptionsPanel.setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); c.fill = 1; c.weightx = 1; c.anchor = GridBagConstraints.NORTHWEST; c.gridwidth = GridBagConstraints.REMAINDER; tpsOptionsPanel.add(getDisplayTpsCheckBox(), c); tpsOptionsPanel.add(getDisplayFpsCheckBox(), c); tpsOptionsPanel.add(new JLabel(" "), c); tpsOptionsPanel.add(getDesiredTpsLabel(), c); getDesiredTpsLabel().setHorizontalAlignment(SwingConstants.CENTER); JPanel p = new JPanel(); JPanel q = new JPanel(); q.setLayout(new GridLayout(1, 3)); p.add(q); p.add(getDesiredTpsTextField()); q = new JPanel(); p.add(q); c.gridwidth = GridBagConstraints.REMAINDER; tpsOptionsPanel.add(p, c); tpsOptionsPanel.add(new JLabel(" "), c); c.gridwidth = 1; c.fill = 0; c.weighty = 1; c.weightx = 0; tpsOptionsPanel.add(getMinTpsButton(), c); tpsOptionsPanel.add(getDefaultTpsButton(), c); tpsOptionsPanel.add(getFastTpsButton(), c); tpsOptionsPanel.add(getMaxTpsButton(), c); } return tpsOptionsPanel; } private JPanel getVisibleOptionsPanel() { if (visibleOptionsPanel == null) { visibleOptionsPanel = new JPanel(); visibleOptionsPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Arena")); visibleOptionsPanel.setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); c.fill = 1; c.weightx = 1; c.anchor = GridBagConstraints.NORTHWEST; c.gridwidth = GridBagConstraints.REMAINDER; visibleOptionsPanel.add(getVisibleRobotEnergyCheckBox(), c); visibleOptionsPanel.add(getVisibleRobotNameCheckBox(), c); visibleOptionsPanel.add(getVisibleScanArcsCheckBox(), c); visibleOptionsPanel.add(getVisibleExplosionsCheckBox(), c); visibleOptionsPanel.add(getVisibleGroundCheckBox(), c); visibleOptionsPanel.add(getVisibleExplosionDebrisCheckBox(), c); visibleOptionsPanel.add(new JLabel(" "), c); c.gridwidth = 1; c.fill = 0; c.weighty = 1; c.weightx = 0; visibleOptionsPanel.add(getEnableAllViewOptionsButton(), c); visibleOptionsPanel.add(getDisableAllViewOptionsButton(), c); visibleOptionsPanel.add(new JLabel(" "), c); visibleOptionsPanel.add(getDefaultViewOptionsButton(), c); } return visibleOptionsPanel; } private JCheckBox getVisibleRobotEnergyCheckBox() { if (visibleRobotEnergyCheckBox == null) { visibleRobotEnergyCheckBox = new JCheckBox("Visible Robot Energy"); visibleRobotEnergyCheckBox.setMnemonic('y'); visibleRobotEnergyCheckBox.setDisplayedMnemonicIndex(19); } return visibleRobotEnergyCheckBox; } private JCheckBox getVisibleRobotNameCheckBox() { if (visibleRobotNameCheckBox == null) { visibleRobotNameCheckBox = new JCheckBox("Visible Robot Name"); visibleRobotNameCheckBox.setMnemonic('V'); } return visibleRobotNameCheckBox; } private JCheckBox getVisibleScanArcsCheckBox() { if (visibleScanArcsCheckBox == null) { visibleScanArcsCheckBox = new JCheckBox("Visible Scan Arcs"); visibleScanArcsCheckBox.setMnemonic('b'); visibleScanArcsCheckBox.setDisplayedMnemonicIndex(4); } return visibleScanArcsCheckBox; } private JCheckBox getVisibleExplosionsCheckBox() { if (visibleExplosionsCheckBox == null) { visibleExplosionsCheckBox = new JCheckBox("Visible Explosions"); visibleExplosionsCheckBox.setMnemonic('x'); visibleExplosionsCheckBox.setDisplayedMnemonicIndex(9); } return visibleExplosionsCheckBox; } private JCheckBox getVisibleGroundCheckBox() { if (visibleGroundCheckBox == null) { visibleGroundCheckBox = new JCheckBox("Visible Ground"); visibleGroundCheckBox.setMnemonic('G'); visibleGroundCheckBox.setDisplayedMnemonicIndex(8); } return visibleGroundCheckBox; } private JCheckBox getVisibleExplosionDebrisCheckBox() { if (visibleExplosionDebrisCheckBox == null) { visibleExplosionDebrisCheckBox = new JCheckBox("Visible Explosion Debris"); visibleExplosionDebrisCheckBox.setMnemonic('E'); visibleExplosionDebrisCheckBox.setDisplayedMnemonicIndex(8); } return visibleExplosionDebrisCheckBox; } private void initialize() { setLayout(new GridLayout(1, 2)); add(getVisibleOptionsPanel()); add(getTpsOptionsPanel()); RobocodeProperties props = manager.getProperties(); loadPreferences(props); props.addPropertyListener(props.new PropertyListener() { @Override public void desiredTpsChanged(int tps) { PreferencesViewOptionsTab.this.desiredTpsTextField.setText("" + tps); } }); } private void loadPreferences(RobocodeProperties robocodeProperties) { getDisplayFpsCheckBox().setSelected(robocodeProperties.getOptionsViewFPS()); getDisplayTpsCheckBox().setSelected(robocodeProperties.getOptionsViewTPS()); getVisibleRobotNameCheckBox().setSelected(robocodeProperties.getOptionsViewRobotNames()); getVisibleRobotEnergyCheckBox().setSelected(robocodeProperties.getOptionsViewRobotEnergy()); getVisibleScanArcsCheckBox().setSelected(robocodeProperties.getOptionsViewScanArcs()); getVisibleExplosionsCheckBox().setSelected(robocodeProperties.getOptionsViewExplosions()); getVisibleGroundCheckBox().setSelected(robocodeProperties.getOptionsViewGround()); getVisibleExplosionDebrisCheckBox().setSelected(robocodeProperties.getOptionsViewExplosionDebris()); getDesiredTpsTextField().setText("" + robocodeProperties.getOptionsBattleDesiredTPS()); } public void storePreferences() { RobocodeProperties props = manager.getProperties(); props.setOptionsViewFPS(getDisplayFpsCheckBox().isSelected()); props.setOptionsViewTPS(getDisplayTpsCheckBox().isSelected()); props.setOptionsViewRobotNames(getVisibleRobotNameCheckBox().isSelected()); props.setOptionsViewRobotEnergy(getVisibleRobotEnergyCheckBox().isSelected()); props.setOptionsViewScanArcs(getVisibleScanArcsCheckBox().isSelected()); props.setOptionsViewExplosions(getVisibleExplosionsCheckBox().isSelected()); props.setOptionsViewGround(getVisibleGroundCheckBox().isSelected()); props.setOptionsViewExplosionDebris(getVisibleExplosionDebrisCheckBox().isSelected()); props.setOptionsBattleDesiredTPS(Integer.parseInt(getDesiredTpsTextField().getText())); manager.saveProperties(); } @Override public boolean isReady() { try { int tps = Integer.parseInt(getDesiredTpsTextField().getText()); if (tps < MIN_TPS) { return false; } else if (tps > MAX_TPS) { return false; } } catch (Exception e) { return false; } return true; } } robocode/robocode/robocode/dialog/PreferencesCommonOptionsTab.java0000644000175000017500000000716011130241114024743 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen * - Initial API and implementation *******************************************************************************/ package robocode.dialog; import robocode.manager.RobocodeManager; import robocode.manager.RobocodeProperties; import javax.swing.*; import java.awt.*; /** * @author Flemming N. Larsen (original) */ @SuppressWarnings("serial") public class PreferencesCommonOptionsTab extends WizardPanel { private JPanel optionsPanel; private JCheckBox showResultsCheckBox; private JCheckBox appendWhenSavingResultsCheckBox; private JCheckBox enableReplayRecordingCheckBox; private final RobocodeManager manager; public PreferencesCommonOptionsTab(RobocodeManager manager) { super(); this.manager = manager; initialize(); } private void initialize() { setLayout(new GridLayout(1, 2)); add(getOptionsPanel()); loadPreferences(manager.getProperties()); } private JPanel getOptionsPanel() { if (optionsPanel == null) { optionsPanel = new JPanel(); optionsPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Common")); optionsPanel.setLayout(new BoxLayout(optionsPanel, BoxLayout.Y_AXIS)); optionsPanel.add(getShowResultsCheckBox()); optionsPanel.add(getAppendWhenSavingResultsCheckBox()); optionsPanel.add(new JLabel(" ")); optionsPanel.add(getEnableReplayRecordingCheckBox()); } return optionsPanel; } private JCheckBox getShowResultsCheckBox() { if (showResultsCheckBox == null) { showResultsCheckBox = new JCheckBox("Show results when battle(s) ends"); showResultsCheckBox.setMnemonic('h'); showResultsCheckBox.setDisplayedMnemonicIndex(1); } return showResultsCheckBox; } private JCheckBox getAppendWhenSavingResultsCheckBox() { if (appendWhenSavingResultsCheckBox == null) { appendWhenSavingResultsCheckBox = new JCheckBox("Append when saving results"); appendWhenSavingResultsCheckBox.setMnemonic('A'); } return appendWhenSavingResultsCheckBox; } private JCheckBox getEnableReplayRecordingCheckBox() { if (enableReplayRecordingCheckBox == null) { enableReplayRecordingCheckBox = new JCheckBox("Enable replay recording (uses memory and disk space)"); enableReplayRecordingCheckBox.setMnemonic('E'); } return enableReplayRecordingCheckBox; } private void loadPreferences(RobocodeProperties robocodeProperties) { getShowResultsCheckBox().setSelected(robocodeProperties.getOptionsCommonShowResults()); getAppendWhenSavingResultsCheckBox().setSelected(robocodeProperties.getOptionsCommonAppendWhenSavingResults()); getEnableReplayRecordingCheckBox().setSelected(robocodeProperties.getOptionsCommonEnableReplayRecording()); } public void storePreferences() { RobocodeProperties props = manager.getProperties(); props.setOptionsCommonShowResults(getShowResultsCheckBox().isSelected()); props.setOptionsCommonAppendWhenSavingResults(getAppendWhenSavingResultsCheckBox().isSelected()); props.setOptionsCommonEnableReplayRecording(getEnableReplayRecordingCheckBox().isSelected()); manager.saveProperties(); } @Override public boolean isReady() { return true; } } robocode/robocode/robocode/dialog/PreferencesDevelopmentOptionsTab.java0000644000175000017500000001017511130241114025775 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Rewritten + added browse button *******************************************************************************/ package robocode.dialog; import robocode.manager.RobocodeManager; import robocode.manager.RobocodeProperties; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ @SuppressWarnings("serial") public class PreferencesDevelopmentOptionsTab extends WizardPanel { private JPanel optionsPanel; private JButton browseButton; private JTextField pathTextField; public final RobocodeManager manager; private final EventHandler eventHandler = new EventHandler(); private class EventHandler implements ActionListener { public void actionPerformed(ActionEvent e) { if (e.getSource() == getBrowseButton()) { JFileChooser chooser = new JFileChooser(); chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); if (chooser.showOpenDialog(optionsPanel) == JFileChooser.APPROVE_OPTION) { pathTextField.setText(chooser.getSelectedFile().getAbsolutePath()); } } } } public PreferencesDevelopmentOptionsTab(RobocodeManager manager) { super(); this.manager = manager; initialize(); } private void initialize() { setLayout(new GridLayout(1, 2)); add(getOptionsPanel()); loadPreferences(manager.getProperties()); } private JPanel getOptionsPanel() { if (optionsPanel == null) { optionsPanel = new JPanel(); optionsPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Development")); GridBagLayout layout = new GridBagLayout(); optionsPanel.setLayout(layout); GridBagConstraints c = new GridBagConstraints(); c.insets = new Insets(5, 5, 5, 5); c.anchor = GridBagConstraints.NORTHWEST; c.fill = GridBagConstraints.HORIZONTAL; c.gridwidth = 2; c.weightx = 0; optionsPanel.add( new JLabel( "If you are using an external IDE to develop robots, you may enter the classpath to those robots here."), c); c.gridy = 1; optionsPanel.add( new JLabel( "Example: c:\\eclipse\\workspace\\MyRobotProject" + java.io.File.pathSeparator + "c:\\eclipse\\workspace\\AnotherRobotProject"), c); c.fill = GridBagConstraints.NONE; c.gridwidth = 1; c.gridy = 2; c.insets = new Insets(3, 3, 3, 3); optionsPanel.add(getBrowseButton(), c); c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; c.gridx = 1; c.insets = new Insets(5, 5, 5, 5); optionsPanel.add(getPathTextField(), c); c.fill = GridBagConstraints.VERTICAL; c.weighty = 1; c.gridy = 3; optionsPanel.add(new JPanel(), c); } return optionsPanel; } private JButton getBrowseButton() { if (browseButton == null) { browseButton = new JButton("Browse"); browseButton.setMnemonic('o'); browseButton.setDisplayedMnemonicIndex(2); browseButton.addActionListener(eventHandler); } return browseButton; } private JTextField getPathTextField() { if (pathTextField == null) { pathTextField = new JTextField("", 80); } return pathTextField; } private void loadPreferences(RobocodeProperties robocodeProperties) { getPathTextField().setText(robocodeProperties.getOptionsDevelopmentPath()); } public void storePreferences() { manager.getProperties().setOptionsDevelopmentPath(getPathTextField().getText()); manager.saveProperties(); } @Override public boolean isReady() { return true; } } robocode/robocode/robocode/repository/0000755000175000017500000000000011125273000017442 5ustar lambylambyrobocode/robocode/robocode/repository/FileSpecification.java0000644000175000017500000003155611130241112023672 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup * - Ported to Java 5 * - Updated to use methods from FileUtil and Logger, which replaces methods * that have been (re)moved from the robocode.util.Utils class * - Moved the compare() method from robocode.util.Utils into this class * - Bugfix: Removed NullPointerException from the exists() method *******************************************************************************/ package robocode.repository; import robocode.io.FileUtil; import robocode.manager.IRepositoryManager; import robocode.manager.NameManager; import java.io.*; import java.net.URL; import java.util.Properties; import java.util.StringTokenizer; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ public abstract class FileSpecification implements Comparable, Serializable, Cloneable { private static final long serialVersionUID = 1L; protected final Properties props = new Properties(); private final static String ROBOCODE_VERSION = "robocode.version"; private final static String LIBRARY_DESCRIPTION = "library.description"; private final static String UUID = "uuid"; protected String uuid; protected String name; protected String description; protected String authorName; protected String authorEmail; protected String authorWebsite; protected String version; protected String robocodeVersion; protected boolean developmentVersion; protected boolean valid; protected URL webpage; protected String libraryDescription; protected File rootDir; private File packageFile; private String filePath; private String fileName; private String propertiesFileName; private String thisFileName; private String fileType; protected NameManager nameManager; private long fileLastModified; private long fileLength; private boolean duplicate; @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } protected FileSpecification() {} public abstract String getUid(); public static FileSpecification createSpecification(IRepositoryManager repositoryManager, File f, File rootDir, String prefix, boolean developmentVersion) { String filename = f.getName(); String fileType = FileUtil.getFileType(filename); FileSpecification newSpec; if (fileType.equals(".team")) { newSpec = new TeamSpecification(f, rootDir, prefix, developmentVersion); } else if (fileType.equals(".jar") || fileType.equals(".zip")) { newSpec = new JarSpecification(f, rootDir, developmentVersion); } else { newSpec = new RobotFileSpecification(f, rootDir, prefix, developmentVersion); if (!(developmentVersion || newSpec.isValid())) { newSpec = new ClassSpecification((RobotFileSpecification) newSpec); } } newSpec.developmentVersion = developmentVersion; newSpec.rootDir = rootDir; newSpec.storeJarFile(repositoryManager.getRobotsDirectory(), repositoryManager.getRobotCache()); return newSpec; } private void storeJarFile(File robotDir, File robotCacheDir) { File src = null; if (rootDir.getName().indexOf(".jar_") == rootDir.getName().length() - 5 || rootDir.getName().indexOf(".zip_") == rootDir.getName().length() - 5) { if (rootDir.getParentFile().equals(robotCacheDir)) { src = new File(robotDir, rootDir.getName().substring(0, rootDir.getName().length() - 1)); } else if (rootDir.getParentFile().getParentFile().equals(robotCacheDir)) { src = new File(rootDir.getParentFile(), rootDir.getName().substring(0, rootDir.getName().length() - 1)); } } if (src != null && !src.exists()) { src = null; } this.packageFile = src; } public File getJarFile() { return packageFile; } @Override public String toString() { return getFileName() + ": length " + getFileLength() + " modified " + getFileLastModified(); } public boolean isDevelopmentVersion() { return developmentVersion; } public int compareTo(FileSpecification other) { return FileSpecification.compare(getNameManager().getFullPackage(), getNameManager().getFullClassName(), getNameManager().getVersion(), other.getNameManager().getFullPackage(), other.getNameManager().getFullClassName(), other.getNameManager().getVersion()); } public boolean isSameFile(String filePath, long fileLength, long fileLastModified) { return filePath.equals(this.filePath) && fileLength == this.fileLength && fileLastModified == this.fileLastModified; } public boolean isSameFile(FileSpecification other) { return other != null && other.getFileLength() == getFileLength() && other.getFileLastModified() == getFileLastModified(); } @Override public boolean equals(Object o) { if (o == null) { return false; } if (o instanceof FileSpecification) { FileSpecification other = (FileSpecification) o; if (!other.getName().equals(getName())) { return false; } if (getVersion() == null) { if (other.getVersion() != null) { return false; } } if (other.getVersion() == null) { if (getVersion() != null) { return false; } } if (other.getVersion() != null && getVersion() != null) { if (!other.getVersion().equals(getVersion())) { return false; } } return other.getFileLength() == getFileLength() && other.getFileLastModified() == getFileLastModified() && other.getFileType().equals(getFileType()); } return false; } /** * Gets the UUID. * * @return Returns a String */ public String getUUID() { return uuid; } /** * Sets the UUID. */ public void setUUID() { // Generate new UUID uuid = java.util.UUID.randomUUID().toString(); props.setProperty(UUID, uuid); } /** * Gets the robotName. * * @return Returns a String */ public String getName() { return name; } /** * Gets the robotDescription. * * @return Returns a String */ public String getDescription() { return description; } /** * Gets the robotAuthorName. * * @return Returns a String */ public String getAuthorName() { return authorName; } /** * Gets the robotAuthorEmail. * * @return Returns a String */ public String getAuthorEmail() { return authorEmail; } /** * Gets the robotAuthorWebsite. * * @return Returns a String */ public String getAuthorWebsite() { return authorWebsite; } /** * Gets the robotVersion. * * @return Returns a String */ public String getVersion() { return version; } /** * Gets the robocodeVersion * * @return Returns a String */ public String getRobocodeVersion() { return robocodeVersion; } /** * Sets the robocodeVersion * * @param robocodeVersion to set */ public void setRobocodeVersion(String robocodeVersion) { this.robocodeVersion = robocodeVersion; props.setProperty(ROBOCODE_VERSION, robocodeVersion); } public String getLibraryDescription() { return libraryDescription; } public void setLibraryDescription(String libraryDescription) { this.libraryDescription = libraryDescription; props.setProperty(LIBRARY_DESCRIPTION, libraryDescription); } /** * Gets the thisFilename. * * @return Returns a String */ public String getThisFileName() { return thisFileName; } /** * Sets the thisFilename. * * @param thisFileName The thisFilename to set */ public void setThisFileName(String thisFileName) { this.thisFileName = thisFileName; } /** * Gets the filePath. * * @return Returns a String */ public String getFilePath() { return filePath; } /** * Sets the filePath. * * @param filePath The filePath to set */ public void setFilePath(String filePath) { this.filePath = filePath; } /** * Gets the propertiesFilename. * * @return Returns a String */ public String getPropertiesFileName() { return propertiesFileName; } /** * Sets the propertiesFilename. * * @param propertiesFileName The propertiesFilename to set */ public void setPropertiesFileName(String propertiesFileName) { this.propertiesFileName = propertiesFileName; } /** * Gets the filename. * * @return Returns a String */ public String getFileName() { return fileName; } /** * Sets the filename. * * @param fileName The filename to set */ public void setFileName(String fileName) { this.fileName = fileName; } /** * Gets the fileType. * * @return Returns a String */ public String getFileType() { return fileType; } /** * Sets the fileType. * * @param fileType The fileType to set */ public void setFileType(String fileType) { this.fileType = fileType; } /** * Gets the robotWebpage. * * @return Returns a String */ public URL getWebpage() { return webpage; } /** * Gets the fileLastModified. * * @return Returns a String */ public long getFileLastModified() { return fileLastModified; } /** * Sets the fileLastModified. * * @param fileLastModified The fileLastModified to set */ public void setFileLastModified(long fileLastModified) { this.fileLastModified = fileLastModified; } /** * Gets the fileLength. * * @return Returns a String */ public long getFileLength() { return fileLength; } /** * Sets the fileLength. * * @param fileLength The fileLength to set */ public void setFileLength(long fileLength) { this.fileLength = fileLength; } public void store(OutputStream out, String desc) throws IOException { setUUID(); props.store(out, desc); } protected void load(FileInputStream in) throws IOException { props.load(in); uuid = props.getProperty(UUID); robocodeVersion = props.getProperty(ROBOCODE_VERSION); libraryDescription = props.getProperty(LIBRARY_DESCRIPTION); } public String getFullPackage() { return getNameManager().getFullPackage(); } public String getFullClassNameWithVersion() { return getNameManager().getFullClassNameWithVersion(); } public String getFullClassName() { return getNameManager().getFullClassName(); } public String getShortClassName() { return getNameManager().getShortClassName(); } public boolean isValid() { return valid; } public void setValid(boolean value) { valid = value; } public boolean isDuplicate() { return duplicate; } public void setDuplicate(boolean isDuplicate) { this.duplicate = isDuplicate; } public NameManager getNameManager() { throw new RuntimeException("Cannot get a nameManager for file type " + getFileType()); } public boolean exists() { return (getFilePath() != null) && new File(getFilePath()).exists(); } /** * Gets the rootDir. * * @return Returns a File */ public File getRootDir() { return rootDir; } public static int compare(String p1, String c1, String v1, String p2, String c2, String v2) { if (p1 == null && p2 != null) { return 1; } if (p2 == null && p1 != null) { return -1; } if (p1 != null) // then p2 isn't either { // If packages are different, return int pc = p1.compareToIgnoreCase(p2); if (pc != 0) { return pc; } } // Ok, same package... compare class: int cc = c1.compareToIgnoreCase(c2); if (cc != 0) { // Different classes, return return cc; } // Ok, same robot... compare version if (v1 == null && v2 == null) { return 0; } if (v1 == null) { return 1; } if (v2 == null) { return -1; } if (v1.equals(v2)) { return 0; } if (v1.indexOf(".") < 0 || v2.indexOf(".") < 0) { return v1.compareToIgnoreCase(v2); } // Dot separated versions. StringTokenizer s1 = new StringTokenizer(v1, "."); StringTokenizer s2 = new StringTokenizer(v2, "."); while (s1.hasMoreTokens() && s2.hasMoreTokens()) { String tok1 = s1.nextToken(); String tok2 = s2.nextToken(); try { int i1 = Integer.parseInt(tok1); int i2 = Integer.parseInt(tok2); if (i1 != i2) { return i1 - i2; } } catch (NumberFormatException e) { int tc = tok1.compareToIgnoreCase(tok2); if (tc != 0) { return tc; } } } if (s1.hasMoreTokens()) { return 1; } if (s2.hasMoreTokens()) { return -1; } return 0; } } robocode/robocode/robocode/repository/ClassSpecification.java0000644000175000017500000000274711130241112024060 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup *******************************************************************************/ package robocode.repository; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ @SuppressWarnings("serial") public class ClassSpecification extends FileSpecification { // Used in FileSpecification public ClassSpecification(RobotFileSpecification robotFileSpecification) { this.developmentVersion = robotFileSpecification.isDevelopmentVersion(); this.rootDir = robotFileSpecification.getRootDir(); this.name = robotFileSpecification.getName(); setFileName(robotFileSpecification.getFileName()); setFilePath(robotFileSpecification.getFilePath()); setFileType(robotFileSpecification.getFileType()); setFileLastModified(robotFileSpecification.getFileLastModified()); setFileLength(robotFileSpecification.getFileLength()); } @Override public String getUid() { return getFilePath(); } } robocode/robocode/robocode/repository/RobotFileSpecification.java0000644000175000017500000002445311130241112024676 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Updated to use methods from FileUtil and Logger, which replaces methods * that have been (re)moved from the robocode.util.Utils class * - Code cleanup * Pavel Savara * - Re-work of robot interfaces *******************************************************************************/ package robocode.repository; import robocode.io.FileUtil; import robocode.io.Logger; import robocode.manager.NameManager; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Pavel Savara (contributor) */ @SuppressWarnings("serial") public class RobotFileSpecification extends FileSpecification { private final static String ROBOT_DESCRIPTION = "robot.description"; private final static String ROBOT_AUTHOR_NAME = "robot.author.name"; private final static String ROBOT_AUTHOR_EMAIL = "robot.author.email"; private final static String ROBOT_AUTHOR_WEBSITE = "robot.author.website"; private final static String ROBOT_JAVA_SOURCE_INCLUDED = "robot.java.source.included"; private final static String ROBOT_VERSION = "robot.version"; private final static String ROBOT_CLASSNAME = "robot.classname"; private final static String ROBOT_WEBPAGE = "robot.webpage"; private String uid = ""; protected boolean robotJavaSourceIncluded; protected String robotClassPath; private boolean isJuniorRobot; private boolean isStandardRobot; private boolean isInteractiveRobot; private boolean isPaintRobot; private boolean isAdvancedRobot; private boolean isTeamRobot; private boolean isDroid; public final NameManager getNameManager() { if (nameManager == null) { nameManager = new NameManager(name, version, developmentVersion, false); } return nameManager; } // Used in RobotRepositoryManager protected RobotFileSpecification(File f, File rootDir, String prefix, boolean developmentVersion) { valid = true; String filename = f.getName(); String filepath = f.getPath(); String fileType = FileUtil.getFileType(filename); this.developmentVersion = developmentVersion; if (prefix.length() == 0 && fileType.equals(".jar")) { throw new RuntimeException("Robot Specification can only be constructed from a .class file"); } else if (fileType.equals(".team")) { throw new RuntimeException("Robot Specification can only be constructed from a .class file"); } else if (fileType.equals(".java")) { loadProperties(filepath); setName(prefix + FileUtil.getClassName(filename)); setRobotClassPath(rootDir.getPath()); } else if (fileType.equals(".class")) { loadProperties(filepath); setName(prefix + FileUtil.getClassName(filename)); setRobotClassPath(rootDir.getPath()); if (isDevelopmentVersion()) { String jfn = filepath.substring(0, filepath.lastIndexOf(".")) + ".java"; File jf = new File(jfn); if (jf.exists()) { setRobotJavaSourceIncluded(true); } } } else if (fileType.equals(".properties")) { loadProperties(filepath); setName(prefix + FileUtil.getClassName(filename)); setRobotClassPath(rootDir.getPath()); } } private void loadProperties(String filepath) { // Load properties if they exist... String pfn = filepath.substring(0, filepath.lastIndexOf(".")) + ".properties"; File pf = new File(pfn); FileInputStream in = null; try { if (pf.exists()) { in = new FileInputStream(pf); load(in); in.close(); if (pf.length() == 0) { setRobotVersion("?"); if (!developmentVersion) { valid = false; } } } // Don't accept robots in robotcache without .properties file else if (!developmentVersion) { valid = false; } } catch (IOException e) { // Oh well. Logger.logError("Warning: Could not load properties file: " + pfn); } finally { if (in != null) { try { in.close(); } catch (IOException ignored) {} } } setThisFileName(pfn); String htmlfn = filepath.substring(0, filepath.lastIndexOf(".")) + ".html"; File htmlFile = new File(htmlfn); if (htmlFile.exists() && (getWebpage() == null || getWebpage().toString().length() == 0)) { try { setRobotWebpage(htmlFile.toURI().toURL()); } catch (MalformedURLException e) { setRobotWebpage(null); } } File classFile = new File(filepath.substring(0, filepath.lastIndexOf(".")) + ".class"); if (classFile.exists()) { setFileLastModified(classFile.lastModified()); setFileLength(classFile.length()); setFileType(".class"); try { setFilePath(classFile.getCanonicalPath()); } catch (IOException e) { Logger.logError("Warning: Unable to determine canonical path for " + classFile.getPath()); setFilePath(classFile.getPath()); } setFileName(classFile.getName()); } } @Override public void load(FileInputStream in) throws IOException { super.load(in); authorEmail = props.getProperty(ROBOT_AUTHOR_EMAIL); authorName = props.getProperty(ROBOT_AUTHOR_NAME); authorWebsite = props.getProperty(ROBOT_AUTHOR_WEBSITE); description = props.getProperty(ROBOT_DESCRIPTION); version = props.getProperty(ROBOT_VERSION); name = props.getProperty(ROBOT_CLASSNAME); String w = props.getProperty(ROBOT_WEBPAGE); if (w == null) { webpage = null; } else if (w.length() == 0) { webpage = null; } else { try { webpage = new URL(w); } catch (MalformedURLException e) { try { webpage = new URL("http://" + w); } catch (MalformedURLException e2) { webpage = null; } } } robotJavaSourceIncluded = Boolean.valueOf(props.getProperty(ROBOT_JAVA_SOURCE_INCLUDED, "false")); } /** * Sets the robotName. * * @param name The robotName to set */ public void setName(String name) { this.name = name; props.setProperty(ROBOT_CLASSNAME, name); } /** * Sets the robotDescription. * * @param robotDescription The robotDescription to set */ public void setRobotDescription(String robotDescription) { this.description = robotDescription; props.setProperty(ROBOT_DESCRIPTION, robotDescription); } /** * Sets the robotAuthorName. * * @param robotAuthorName The robotAuthorName to set */ public void setRobotAuthorName(String robotAuthorName) { this.authorName = robotAuthorName; props.setProperty(ROBOT_AUTHOR_NAME, robotAuthorName); } /** * Sets the robotAuthorEmail. * * @param robotAuthorEmail The robotAuthorEmail to set */ public void setRobotAuthorEmail(String robotAuthorEmail) { this.authorEmail = robotAuthorEmail; props.setProperty(ROBOT_AUTHOR_EMAIL, robotAuthorEmail); } /** * Sets the robotAuthorWebsite. * * @param robotAuthorWebsite The robotAuthorWebsite to set */ public void setRobotAuthorWebsite(String robotAuthorWebsite) { this.authorWebsite = robotAuthorWebsite; props.setProperty(ROBOT_AUTHOR_WEBSITE, robotAuthorWebsite); } /** * Gets the robotJavaSourceIncluded. * * @return Returns a boolean */ public boolean getRobotJavaSourceIncluded() { return robotJavaSourceIncluded; } /** * Sets the robotJavaSourceIncluded. * * @param robotJavaSourceIncluded The robotJavaSourceIncluded to set */ public void setRobotJavaSourceIncluded(boolean robotJavaSourceIncluded) { this.robotJavaSourceIncluded = robotJavaSourceIncluded; props.setProperty(ROBOT_JAVA_SOURCE_INCLUDED, "" + robotJavaSourceIncluded); } /** * Sets the robotVersion. * * @param robotVersion The robotVersion to set */ public void setRobotVersion(String robotVersion) { this.version = robotVersion; if (robotVersion != null) { props.setProperty(ROBOT_VERSION, robotVersion); } else { props.remove(ROBOT_VERSION); } } /** * Gets the robotClasspath. * * @return Returns a String */ public String getRobotClassPath() { return robotClassPath; } /** * Sets the robotClasspath. * * @param robotClassPath The robotClasspath to set */ public void setRobotClassPath(String robotClassPath) { this.robotClassPath = robotClassPath; } /** * Sets the robotWebpage. * * @param robotWebpage The robotWebpage to set */ public void setRobotWebpage(URL robotWebpage) { this.webpage = robotWebpage; if (robotWebpage == null) { props.remove(ROBOT_WEBPAGE); } else { props.setProperty(ROBOT_WEBPAGE, this.webpage.toString()); } } /** * Gets the uid. * * @return Returns a String */ @Override public String getUid() { return uid; } /** * Sets the uid. * * @param uid The uid to set */ public void setUid(String uid) { this.uid = uid; } public boolean isDroid() { return isDroid; } public void setDroid(boolean value) { this.isDroid = value; } public boolean isTeamRobot() { return isTeamRobot; } public void setTeamRobot(boolean value) { this.isTeamRobot = value; } public boolean isAdvancedRobot() { return isAdvancedRobot; } public void setAdvancedRobot(boolean value) { this.isAdvancedRobot = value; } public boolean isStandardRobot() { return isStandardRobot; } public void setStandardRobot(boolean value) { this.isStandardRobot = value; } public boolean isInteractiveRobot() { return isInteractiveRobot; } public void setInteractiveRobot(boolean value) { this.isInteractiveRobot = value; } public boolean isPaintRobot() { return isPaintRobot; } public void setPaintRobot(boolean value) { this.isPaintRobot = value; } public boolean isJuniorRobot() { return isJuniorRobot; } public void setJuniorRobot(boolean value) { this.isJuniorRobot = value; } } robocode/robocode/robocode/repository/Repository.java0000644000175000017500000001027011130241112022457 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Replaced FileSpecificationVector with plain Vector * - Ported to Java 5 * - Code cleanup * - Bugfixed to handle TeamSpecification as well and the new sampleex * robots * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap *******************************************************************************/ package robocode.repository; import java.util.ArrayList; import java.util.Collections; import java.util.Hashtable; import java.util.List; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Robert D. Maupin (contributor) */ public class Repository { private final List fileSpecifications = Collections.synchronizedList( new ArrayList()); private final Hashtable fileSpecificationsDict = new Hashtable(); public void add(FileSpecification fileSpecification) { fileSpecifications.add(fileSpecification); final String name = fileSpecification.getNameManager().getFullClassNameWithVersion(); final String unname = fileSpecification.getNameManager().getUniqueFullClassNameWithVersion(); final String rootDir = fileSpecification.getRootDir().toString(); fileSpecificationsDict.put(name, fileSpecification); fileSpecificationsDict.put(rootDir + name, fileSpecification); if (!name.equals(unname)) { fileSpecificationsDict.put(unname, fileSpecification); fileSpecificationsDict.put(rootDir + unname, fileSpecification); } } public FileSpecification get(String fullClassNameWithVersion) { return fileSpecificationsDict.get(fullClassNameWithVersion); } public List getRobotSpecificationsList(boolean onlyWithSource, boolean onlyWithPackage, boolean onlyRobots, boolean onlyDevelopment, boolean onlyNotDevelopment, boolean ignoreTeamRobots) { List v = Collections.synchronizedList(new ArrayList()); for (FileSpecification spec : fileSpecifications) { if (!spec.isValid()) { continue; } if (spec.isDuplicate()) { continue; } if (!(spec instanceof RobotFileSpecification) && onlyRobots) { continue; } else { if (onlyWithPackage && spec.getFullPackage() == null) { continue; } if (onlyNotDevelopment && spec.isDevelopmentVersion()) { continue; } if (spec instanceof RobotFileSpecification) { RobotFileSpecification robotSpec = (RobotFileSpecification) spec; if (onlyWithSource && !robotSpec.getRobotJavaSourceIncluded()) { continue; } } else if (spec instanceof TeamSpecification) { TeamSpecification teamSpec = (TeamSpecification) spec; if (onlyWithSource && !teamSpec.getTeamJavaSourceIncluded()) { continue; } } } if (onlyDevelopment) { if (!spec.isDevelopmentVersion()) { continue; } String fullPackage = spec.getFullPackage(); if (fullPackage != null && (fullPackage.equals("sample") || fullPackage.equals("sampleteam") || fullPackage.equals("sampleex"))) { continue; } } String version = spec.getVersion(); if (version != null) { if ((version.indexOf(",") >= 0) || (version.indexOf(" ") >= 0) || (version.indexOf("*") >= 0) || (version.indexOf("(") >= 0) || (version.indexOf(")") >= 0) || (version.indexOf("{") >= 0) || (version.indexOf("}") >= 0)) { continue; } } v.add(spec); } return v; } public void sortRobotSpecifications() { Collections.sort(fileSpecifications); } } robocode/robocode/robocode/repository/TeamSpecification.java0000644000175000017500000001633511130241112023677 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup * - Updated to use methods from FileUtil and Logger, which replaces methods * that have been (re)moved from the robocode.util.Utils class *******************************************************************************/ package robocode.repository; import robocode.io.FileUtil; import robocode.io.Logger; import robocode.manager.NameManager; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ @SuppressWarnings("serial") public class TeamSpecification extends FileSpecification { private final static String TEAM_DESCRIPTION = "team.description"; private final static String TEAM_AUTHOR_NAME = "team.author.name"; private final static String TEAM_AUTHOR_EMAIL = "team.author.email"; private final static String TEAM_AUTHOR_WEBSITE = "team.author.website"; private final static String TEAM_VERSION = "team.version"; private final static String TEAM_WEBPAGE = "team.webpage"; private final static String TEAM_MEMBERS = "team.members"; private final static String TEAM_JAVA_SOURCE_INCLUDED = "team.java.source.included"; protected boolean teamJavaSourceIncluded = false; private String members = ""; private String uid = ""; public final NameManager getNameManager() { if (nameManager == null) { nameManager = new NameManager(name, version, developmentVersion, true); } return nameManager; } // Used in FileSpecification protected TeamSpecification(File f, File rootDir, String prefix, boolean developmentVersion) { this.developmentVersion = developmentVersion; this.rootDir = rootDir; valid = true; String filename = f.getName(); String fileType = FileUtil.getFileType(filename); if (fileType.equals(".team")) { try { FileInputStream in = new FileInputStream(f); load(in); } catch (IOException e) { Logger.logError("Warning: Could not load team: " + f); } if (filename.indexOf(" ") >= 0) { setName(prefix + FileUtil.getClassName(filename.substring(0, filename.indexOf(" ")))); } else { setName(prefix + FileUtil.getClassName(filename)); } setFileLastModified(f.lastModified()); setFileLength(f.length()); setFileType(".team"); try { setFilePath(f.getCanonicalPath()); } catch (IOException e) { Logger.logError("Warning: Unable to determine canonical path for " + f.getPath()); setFilePath(f.getPath()); } setThisFileName(f.getPath()); setFileName(f.getName()); } else { throw new RuntimeException("TeamSpecification can only be constructed from a .team file"); } byte mb[] = getMembers().getBytes(); long uid1 = 0; for (byte element : mb) { uid1 += element; } long uid2 = mb.length; uid = uid1 + "" + uid2; } @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } @Override public String getUid() { return uid; } public TeamSpecification() {} @Override public void load(FileInputStream in) throws IOException { super.load(in); authorEmail = props.getProperty(TEAM_AUTHOR_EMAIL); authorName = props.getProperty(TEAM_AUTHOR_NAME); authorWebsite = props.getProperty(TEAM_AUTHOR_WEBSITE); description = props.getProperty(TEAM_DESCRIPTION); version = props.getProperty(TEAM_VERSION); members = props.getProperty(TEAM_MEMBERS); try { String team_webpage = props.getProperty(TEAM_WEBPAGE); if (team_webpage != null) { webpage = new URL(team_webpage); } } catch (MalformedURLException e) { webpage = null; } teamJavaSourceIncluded = Boolean.valueOf(props.getProperty(TEAM_JAVA_SOURCE_INCLUDED, "false")); } /** * Sets the name of the team * * @param name The new name for the team */ public void setName(String name) { this.name = name; } /** * Sets the team description. * * @param teamDescription The new team description */ public void setTeamDescription(String teamDescription) { this.description = teamDescription; props.setProperty(TEAM_DESCRIPTION, teamDescription); } /** * Sets the the author name. * * @param teamAuthorName The new author name */ public void setTeamAuthorName(String teamAuthorName) { this.authorName = teamAuthorName; props.setProperty(TEAM_AUTHOR_NAME, teamAuthorName); } /** * Sets the e-mail address of the author. * * @param teamAuthorEmail The new e-mail address of the author. */ public void setTeamAuthorEmail(String teamAuthorEmail) { this.authorEmail = teamAuthorEmail; props.setProperty(TEAM_AUTHOR_EMAIL, teamAuthorEmail); } /** * Sets the website for the author/team. * * @param teamAuthorWebsite The new website for the author/team. */ public void setTeamAuthorWebsite(String teamAuthorWebsite) { this.authorWebsite = teamAuthorWebsite; props.setProperty(TEAM_AUTHOR_WEBSITE, teamAuthorWebsite); } /** * Sets the robot version. * * @param teamVersion The new robot version. */ public void setTeamVersion(String teamVersion) { this.version = teamVersion; props.setProperty(TEAM_VERSION, teamVersion); } /** * Sets the robot webpage. * * @param teamWebpage The new robot webpage. */ public void setTeamWebpage(URL teamWebpage) { this.webpage = teamWebpage; if (teamWebpage != null) { props.setProperty(TEAM_WEBPAGE, teamWebpage.toString()); } else { props.remove(TEAM_WEBPAGE); } } /** * Gets the members. * * @return Returns a String */ public String getMembers() { return members; } /** * Sets the members. * * @param members The members to set */ public void setMembers(String members) { this.members = members; props.setProperty(TEAM_MEMBERS, members); } public void addMember(RobotFileSpecification robotFileSpecification) { if (members == null || members.length() == 0) { members = robotFileSpecification.getFullClassNameWithVersion(); } else { members += "," + robotFileSpecification.getFullClassNameWithVersion(); } props.setProperty(TEAM_MEMBERS, members); } /** * Gets the teamJavaSourceIncluded. * * @return Returns a boolean */ public boolean getTeamJavaSourceIncluded() { return teamJavaSourceIncluded; } /** * Sets the teamJavaSourceIncluded. * * @param teamJavaSourceIncluded The teamJavaSourceIncluded to set */ public void setTeamJavaSourceIncluded(boolean teamJavaSourceIncluded) { this.teamJavaSourceIncluded = teamJavaSourceIncluded; props.setProperty(TEAM_JAVA_SOURCE_INCLUDED, "" + teamJavaSourceIncluded); } } robocode/robocode/robocode/repository/JarSpecification.java0000644000175000017500000000372011130241112023517 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Updated to use methods from FileUtil and Logger, which replaces methods * that have been (re)moved from the robocode.util.Utils class * - Code cleanup *******************************************************************************/ package robocode.repository; import robocode.io.FileUtil; import robocode.io.Logger; import java.io.File; import java.io.IOException; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ @SuppressWarnings("serial") public class JarSpecification extends FileSpecification { // Used in FileSpecification protected JarSpecification(File f, File rootDir, boolean developmentVersion) { this.rootDir = rootDir; this.developmentVersion = developmentVersion; valid = true; String filename = f.getName(); String fileType = FileUtil.getFileType(filename); if (fileType.equals(".jar") || fileType.equals(".zip")) { setFileLastModified(f.lastModified()); setFileLength(f.length()); setFileType(fileType); try { setFilePath(f.getCanonicalPath()); } catch (IOException e) { Logger.logError("Warning: Unable to determine canonical path for " + f.getPath()); setFilePath(f.getPath()); } setFileName(f.getName()); } else { throw new RuntimeException("JarSpecification can only be constructed from a .jar file"); } } @Override public String getUid() { return getFilePath(); } } robocode/robocode/robocode/repository/FileSpecificationDatabase.java0000644000175000017500000001445111130241112025312 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup * - Replaced FileSpecificationVector with plain Vector * - Ported to Java 5.0 * - Added missing close() on FileInputStream * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap *******************************************************************************/ package robocode.repository; import java.io.*; import java.util.*; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Robert D. Maupin (contributor) */ @SuppressWarnings("serial") public class FileSpecificationDatabase implements Serializable { private Map hash = new HashMap(); @SuppressWarnings("unchecked") public void load(File f) throws IOException, ClassNotFoundException { FileInputStream fis = null; try { fis = new FileInputStream(f); ObjectInputStream in = new ObjectInputStream(fis); Object obj = in.readObject(); if (obj instanceof Hashtable) { // The following provides backward compability for versions before 1.2.3A Hashtable hashtable = (Hashtable) obj; hash = new HashMap(hashtable); } else { // Using new container type for version 1.2.3B and followers hash = (HashMap) obj; } } finally { if (fis != null) { fis.close(); } } } public void store(File f) throws IOException { ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f)); out.writeObject(hash); out.close(); } public boolean contains(String fullClassName, String version, boolean isDevelopmentVersion) { for (FileSpecification fileSpecification : hash.values()) { if (fileSpecification instanceof RobotFileSpecification || fileSpecification instanceof TeamSpecification) { if (fileSpecification.isDuplicate()) { continue; } if (fileSpecification.isDevelopmentVersion() != isDevelopmentVersion) { continue; } if (fullClassName.equals(fileSpecification.getFullClassName())) { if (version == null && fileSpecification.getVersion() == null) { return true; } if (version != null && fileSpecification.getVersion() != null) { if (version.equals(fileSpecification.getVersion())) { return true; } } } } } return false; } public FileSpecification get(String fullClassName, String version, boolean isDevelopmentVersion) { for (FileSpecification fileSpecification : hash.values()) { if (fileSpecification instanceof RobotFileSpecification || fileSpecification instanceof TeamSpecification) { if (fileSpecification.isDuplicate()) { continue; } if (fileSpecification.isDevelopmentVersion() != isDevelopmentVersion) { continue; } if (fullClassName.equals(fileSpecification.getFullClassName())) { if (version == null && fileSpecification.getVersion() == null) { return fileSpecification; } if (version != null && fileSpecification.getVersion() != null) { if (version.equals(fileSpecification.getVersion())) { return fileSpecification; } } } } } return null; } public List getFileSpecifications() { List v = new ArrayList(); for (String key : hash.keySet()) { v.add(hash.get(key)); } return v; } public List getJarSpecifications() { List v = new ArrayList(); for (String key : hash.keySet()) { FileSpecification spec = hash.get(key); if (spec instanceof JarSpecification) { v.add((JarSpecification) spec); } } return v; } public FileSpecification get(String key) { Object o = hash.get(key); if (o == null) { return null; } if (!(o instanceof FileSpecification)) { return null; } return (FileSpecification) o; } public void remove(String key) { FileSpecification removedSpecification = hash.get(key); if (removedSpecification == null) { return; } hash.remove(key); // No concept of duplicates for classes if (!(removedSpecification instanceof RobotFileSpecification)) { return; } // If it's already a dupe we're removing, return if (removedSpecification.isDuplicate()) { return; } // Development versions are not considered for duplicates if (removedSpecification.isDevelopmentVersion()) { return; } // If there were any duplicates, we need to set one to not-duplicate FileSpecification unduplicatedSpec = null; String fullClassName = removedSpecification.getFullClassName(); String version = removedSpecification.getVersion(); for (FileSpecification fileSpecification : hash.values()) { if (fileSpecification instanceof RobotFileSpecification) { RobotFileSpecification spec = (RobotFileSpecification) fileSpecification; if (spec.isDevelopmentVersion()) { continue; } if (fullClassName.equals(spec.getFullClassName())) { if ((version == null && spec.getVersion() == null) || ((version != null && spec.getVersion() != null) && (version.equals(spec.getVersion())))) { if (unduplicatedSpec == null) { unduplicatedSpec = spec; unduplicatedSpec.setDuplicate(false); } else { if (spec.getFileLastModified() < unduplicatedSpec.getFileLastModified()) { unduplicatedSpec.setDuplicate(true); spec.setDuplicate(false); unduplicatedSpec = spec; } } } } } } } public void put(String key, FileSpecification spec) { hash.put(key, spec); } } robocode/robocode/robocode/util/0000755000175000017500000000000011124142410016177 5ustar lambylambyrobocode/robocode/robocode/util/Utils.java0000644000175000017500000001470511130241112020145 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Moved all methods to classes like FileUtil, StringUtil, WindowUtil, * Logger etc. exception for the following methods, which have been kept * here as legacy robots make use of these methods: * - normalAbsoluteAngle() * - normalNearAbsoluteAngle() * - normalRelativeAngle() * - The isNear() was made public * - Optimized and provided javadocs for all methods *******************************************************************************/ package robocode.util; import robocode.control.RandomFactory; import static java.lang.Math.PI; import java.util.Random; /** * Utility class that provide methods for normalizing angles. * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ public class Utils { private final static double TWO_PI = 2 * PI; private final static double THREE_PI_OVER_TWO = 3 * PI / 2; private final static double PI_OVER_TWO = PI / 2; public static final double NEAR_DELTA = .00001; // Hide the default constructor as this class only provides static method private Utils() {} /** * Normalizes an angle to an absolute angle. * The normalized angle will be in the range from 0 to 2*PI, where 2*PI * itself is not included. * * @param angle the angle to normalize * @return the normalized angle that will be in the range of [0,2*PI[ */ public static double normalAbsoluteAngle(double angle) { return (angle %= TWO_PI) >= 0 ? angle : (angle + TWO_PI); } /** * Normalizes an angle to an absolute angle. * The normalized angle will be in the range from 0 to 360, where 360 * itself is not included. * * @param angle the angle to normalize * @return the normalized angle that will be in the range of [0,360[ */ public static double normalAbsoluteAngleDegrees(double angle) { return (angle %= 360) >= 0 ? angle : (angle + 360); } /** * Normalizes an angle to a relative angle. * The normalized angle will be in the range from -PI to PI, where PI * itself is not included. * * @param angle the angle to normalize * @return the normalized angle that will be in the range of [-PI,PI[ */ public static double normalRelativeAngle(double angle) { return (angle %= TWO_PI) >= 0 ? (angle < PI) ? angle : angle - TWO_PI : (angle >= -PI) ? angle : angle + TWO_PI; } /** * Normalizes an angle to a relative angle. * The normalized angle will be in the range from -180 to 180, where 180 * itself is not included. * * @param angle the angle to normalize * @return the normalized angle that will be in the range of [-180,180[ */ public static double normalRelativeAngleDegrees(double angle) { return (angle %= 360) >= 0 ? (angle < 180) ? angle : angle - 360 : (angle >= -180) ? angle : angle + 360; } /** * Normalizes an angle to be near an absolute angle. * The normalized angle will be in the range from 0 to 360, where 360 * itself is not included. * If the normalized angle is near to 0, 90, 180, 270 or 360, that * angle will be returned. The {@link #isNear(double, double) isNear} * method is used for defining when the angle is near one of angles listed * above. * * @param angle the angle to normalize * @return the normalized angle that will be in the range of [0,360[ * @see #normalAbsoluteAngle(double) * @see #isNear(double, double) */ public static double normalNearAbsoluteAngleDegrees(double angle) { angle = (angle %= 360) >= 0 ? angle : (angle + 360); if (isNear(angle, 180)) { return 180; } else if (angle < 180) { if (isNear(angle, 0)) { return 0; } else if (isNear(angle, 90)) { return 90; } } else { if (isNear(angle, 270)) { return 270; } else if (isNear(angle, 360)) { return 0; } } return angle; } /** * Normalizes an angle to be near an absolute angle. * The normalized angle will be in the range from 0 to 2*PI, where 2*PI * itself is not included. * If the normalized angle is near to 0, PI/2, PI, 3*PI/2 or 2*PI, that * angle will be returned. The {@link #isNear(double, double) isNear} * method is used for defining when the angle is near one of angles listed * above. * * @param angle the angle to normalize * @return the normalized angle that will be in the range of [0,2*PI[ * @see #normalAbsoluteAngle(double) * @see #isNear(double, double) */ public static double normalNearAbsoluteAngle(double angle) { angle = (angle %= TWO_PI) >= 0 ? angle : (angle + TWO_PI); if (isNear(angle, PI)) { return PI; } else if (angle < PI) { if (isNear(angle, 0)) { return 0; } else if (isNear(angle, PI_OVER_TWO)) { return PI_OVER_TWO; } } else { if (isNear(angle, THREE_PI_OVER_TWO)) { return THREE_PI_OVER_TWO; } else if (isNear(angle, TWO_PI)) { return 0; } } return angle; } /** * Tests if the two {@code double} values are near to each other. * It is recommended to use this method instead of testing if the two * doubles are equal using an this expression: {@code value1 == value2}. * The reason being, that this expression might never become * {@code true} due to the precision of double values. * Whether or not the specified doubles are near to each other is defined by * the following expression: * {@code (Math.abs(value1 - value2) < .00001)} * * @param value1 the first double value * @param value2 the second double value * @return {@code true} if the two doubles are near to each other; * {@code false} otherwise. */ public static boolean isNear(double value1, double value2) { return (Math.abs(value1 - value2) < NEAR_DELTA); } /** * Returns random number generator. It might be configured for repeatable behavior by setting -DRANDOMSEED option. * * @return random number generator */ public static Random getRandom() { return RandomFactory.getRandom(); } } robocode/robocode/robocode/util/package.html0000644000175000017500000000020211006202516020455 0ustar lambylamby Utility classes that can be used when writing robots. Kept for compatibility with legacy robots. robocode/robocode/robocode/battle/0000755000175000017500000000000011124157566016517 5ustar lambylambyrobocode/robocode/robocode/battle/snapshot/0000755000175000017500000000000011124142270020340 5ustar lambylambyrobocode/robocode/robocode/battle/snapshot/ScoreSnapshot.java0000644000175000017500000002554111130241114023777 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Pavel Savara * - Xml Serialization, refactoring *******************************************************************************/ package robocode.battle.snapshot; import robocode.common.IXmlSerializable; import robocode.common.XmlReader; import robocode.common.XmlWriter; import robocode.control.snapshot.IScoreSnapshot; import robocode.peer.robot.RobotStatistics; import java.io.IOException; import java.io.Serializable; import java.util.Dictionary; /** * @author Pavel Savara (original) * @author Flemming N. Larsen (contributor) * @since 1.6.1 */ public final class ScoreSnapshot implements Comparable, Serializable, IXmlSerializable, IScoreSnapshot { private static final long serialVersionUID = 1L; private String name; private double totalScore; private double totalSurvivalScore; private double totalLastSurvivorBonus; private double totalBulletDamageScore; private double totalBulletKillBonus; private double totalRammingDamageScore; private double totalRammingKillBonus; private int totalFirsts; private int totalSeconds; private int totalThirds; private double currentScore; private double currentSurvivalScore; private double currentSurvivalBonus; private double currentBulletDamageScore; private double currentBulletKillBonus; private double currentRammingDamageScore; private double currentRammingKillBonus; public ScoreSnapshot(RobotStatistics statistics, String name) { this.name = name; totalScore = statistics.getTotalScore(); totalSurvivalScore = statistics.getTotalSurvivalScore(); totalLastSurvivorBonus = statistics.getTotalLastSurvivorBonus(); totalBulletDamageScore = statistics.getTotalBulletDamageScore(); totalBulletKillBonus = statistics.getTotalBulletKillBonus(); totalRammingDamageScore = statistics.getTotalRammingDamageScore(); totalRammingKillBonus = statistics.getTotalRammingKillBonus(); totalFirsts = statistics.getTotalFirsts(); totalSeconds = statistics.getTotalSeconds(); totalThirds = statistics.getTotalThirds(); currentScore = statistics.getCurrentScore(); currentBulletDamageScore = statistics.getCurrentBulletDamageScore(); currentSurvivalScore = statistics.getCurrentSurvivalScore(); currentSurvivalBonus = statistics.getCurrentSurvivalBonus(); currentBulletKillBonus = statistics.getCurrentBulletKillBonus(); currentRammingDamageScore = statistics.getCurrentRammingDamageScore(); currentRammingKillBonus = statistics.getCurrentRammingKillBonus(); } public ScoreSnapshot(IScoreSnapshot left, IScoreSnapshot right, String name) { this.name = name; totalScore = left.getTotalScore() + right.getTotalScore(); totalSurvivalScore = left.getTotalSurvivalScore() + right.getTotalSurvivalScore(); totalLastSurvivorBonus = left.getTotalLastSurvivorBonus() + right.getTotalLastSurvivorBonus(); totalBulletDamageScore = left.getTotalBulletDamageScore() + right.getTotalBulletDamageScore(); totalBulletKillBonus = left.getTotalBulletKillBonus() + right.getTotalBulletKillBonus(); totalRammingDamageScore = left.getTotalRammingDamageScore() + right.getTotalRammingDamageScore(); totalRammingKillBonus = left.getTotalRammingKillBonus() + right.getTotalRammingKillBonus(); totalFirsts = left.getTotalFirsts() + right.getTotalFirsts(); totalSeconds = left.getTotalSeconds() + right.getTotalSeconds(); totalThirds = left.getTotalThirds() + right.getTotalThirds(); currentScore = left.getCurrentScore() + right.getCurrentScore(); currentSurvivalScore = left.getCurrentSurvivalScore() + right.getCurrentSurvivalScore(); currentBulletDamageScore = left.getCurrentBulletDamageScore() + right.getCurrentBulletDamageScore(); currentBulletKillBonus = left.getCurrentBulletKillBonus() + right.getCurrentBulletKillBonus(); currentRammingDamageScore = left.getCurrentRammingDamageScore() + right.getCurrentRammingDamageScore(); currentRammingKillBonus = left.getCurrentBulletKillBonus() + right.getCurrentBulletKillBonus(); } public String getName() { return name; } public double getTotalScore() { return totalScore; } public double getTotalSurvivalScore() { return totalSurvivalScore; } public double getTotalLastSurvivorBonus() { return totalLastSurvivorBonus; } public double getTotalBulletDamageScore() { return totalBulletDamageScore; } public double getTotalBulletKillBonus() { return totalBulletKillBonus; } public double getTotalRammingDamageScore() { return totalRammingDamageScore; } public double getTotalRammingKillBonus() { return totalRammingKillBonus; } public int getTotalFirsts() { return totalFirsts; } public int getTotalSeconds() { return totalSeconds; } public int getTotalThirds() { return totalThirds; } public double getCurrentScore() { return currentScore; } public double getCurrentSurvivalScore() { return currentSurvivalScore; } public double getCurrentSurvivalBonus() { return currentSurvivalBonus; } public double getCurrentBulletDamageScore() { return currentBulletDamageScore; } public double getCurrentBulletKillBonus() { return currentBulletKillBonus; } public double getCurrentRammingDamageScore() { return currentRammingDamageScore; } public double getCurrentRammingKillBonus() { return currentRammingKillBonus; } public int compareTo(IScoreSnapshot o) { double myScore = getTotalScore(); double hisScore = o.getTotalScore(); myScore += getCurrentScore(); hisScore += o.getCurrentScore(); if (myScore < hisScore) { return -1; } if (myScore > hisScore) { return 1; } return 0; } public ScoreSnapshot() {} public void writeXml(XmlWriter writer, Dictionary options) throws IOException { writer.startElement("score"); { writer.writeAttribute("name", name); writer.writeAttribute("totalScore", totalScore); writer.writeAttribute("totalSurvivalScore", totalSurvivalScore); writer.writeAttribute("totalLastSurvivorBonus", totalLastSurvivorBonus); writer.writeAttribute("totalBulletDamageScore", totalBulletDamageScore); writer.writeAttribute("totalBulletKillBonus", totalBulletKillBonus); writer.writeAttribute("totalRammingDamageScore", totalRammingDamageScore); writer.writeAttribute("totalRammingKillBonus", totalRammingKillBonus); writer.writeAttribute("totalFirsts", totalFirsts); writer.writeAttribute("totalSeconds", totalSeconds); writer.writeAttribute("totalThirds", totalThirds); writer.writeAttribute("currentScore", currentScore); writer.writeAttribute("currentSurvivalScore", currentSurvivalScore); writer.writeAttribute("currentBulletDamageScore", currentBulletDamageScore); writer.writeAttribute("currentBulletKillBonus", currentBulletKillBonus); writer.writeAttribute("currentRammingDamageScore", currentRammingDamageScore); writer.writeAttribute("currentRammingKillBonus", currentRammingKillBonus); writer.writeAttribute("ver", serialVersionUID); } writer.endElement(); } public XmlReader.Element readXml(XmlReader reader) { return reader.expect("score", new XmlReader.Element() { public IXmlSerializable read(XmlReader reader) { final ScoreSnapshot snapshot = new ScoreSnapshot(); reader.expect("name", new XmlReader.Attribute() { public void read(String value) { snapshot.name = value; } }); reader.expect("totalScore", new XmlReader.Attribute() { public void read(String value) { snapshot.totalScore = Double.parseDouble(value); } }); reader.expect("totalSurvivalScore", new XmlReader.Attribute() { public void read(String value) { snapshot.totalSurvivalScore = Double.parseDouble(value); } }); reader.expect("totalLastSurvivorBonus", new XmlReader.Attribute() { public void read(String value) { snapshot.totalLastSurvivorBonus = Double.parseDouble(value); } }); reader.expect("totalBulletDamageScore", new XmlReader.Attribute() { public void read(String value) { snapshot.totalBulletDamageScore = Double.parseDouble(value); } }); reader.expect("totalBulletKillBonus", new XmlReader.Attribute() { public void read(String value) { snapshot.totalBulletKillBonus = Double.parseDouble(value); } }); reader.expect("totalRammingDamageScore", new XmlReader.Attribute() { public void read(String value) { snapshot.totalRammingDamageScore = Double.parseDouble(value); } }); reader.expect("totalRammingKillBonus", new XmlReader.Attribute() { public void read(String value) { snapshot.totalRammingKillBonus = Double.parseDouble(value); } }); reader.expect("totalFirsts", new XmlReader.Attribute() { public void read(String value) { snapshot.totalFirsts = Integer.parseInt(value); } }); reader.expect("totalSeconds", new XmlReader.Attribute() { public void read(String value) { snapshot.totalSeconds = Integer.parseInt(value); } }); reader.expect("totalThirds", new XmlReader.Attribute() { public void read(String value) { snapshot.totalThirds = Integer.parseInt(value); } }); reader.expect("currentScore", new XmlReader.Attribute() { public void read(String value) { snapshot.currentScore = Double.parseDouble(value); } }); reader.expect("currentSurvivalScore", new XmlReader.Attribute() { public void read(String value) { snapshot.currentSurvivalScore = Double.parseDouble(value); } }); reader.expect("currentBulletDamageScore", new XmlReader.Attribute() { public void read(String value) { snapshot.currentBulletDamageScore = Double.parseDouble(value); } }); reader.expect("currentBulletKillBonus", new XmlReader.Attribute() { public void read(String value) { snapshot.currentBulletKillBonus = Double.parseDouble(value); } }); reader.expect("currentRammingDamageScore", new XmlReader.Attribute() { public void read(String value) { snapshot.currentRammingDamageScore = Double.parseDouble(value); } }); reader.expect("currentRammingKillBonus", new XmlReader.Attribute() { public void read(String value) { snapshot.currentRammingKillBonus = Double.parseDouble(value); } }); return snapshot; } }); } } robocode/robocode/robocode/battle/snapshot/TurnSnapshot.java0000644000175000017500000001617011130241114023652 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen * - Initial implementation * Pavel Savara * - Xml Serialization, refactoring *******************************************************************************/ package robocode.battle.snapshot; import robocode.battle.Battle; import robocode.common.IXmlSerializable; import robocode.common.XmlReader; import robocode.common.XmlWriter; import robocode.control.snapshot.IBulletSnapshot; import robocode.control.snapshot.IRobotSnapshot; import robocode.control.snapshot.IScoreSnapshot; import robocode.control.snapshot.ITurnSnapshot; import robocode.peer.BulletPeer; import robocode.peer.RobotPeer; import java.io.IOException; import java.util.*; /** * A battle snapshot, which is a view of the data for the battle at a particular * instant in time. *

* Note that this class is implemented as an immutable object. The idea of the * immutable object is that it cannot be modified after it has been created. * See the
Immutable * object definition on Wikipedia. *

* Immutable objects are considered to be more thread-safe than mutable * objects, if implemented correctly. *

* All member fields must be final, and provided thru the constructor. * The constructor must make a deep copy of the data assigned to the * member fields and the getters of this class must return a copy of the data * that to return. * * @author Flemming N. Larsen (original) * @author Pavel Savara (contributor) * @since 1.6.1 */ public final class TurnSnapshot implements java.io.Serializable, IXmlSerializable, ITurnSnapshot { private static final long serialVersionUID = 1L; // The width of the battlefield // private final int fieldWidth; // The height of the battlefield // private final int fieldHeight; // List of all robots participating in the battle private List robots; // List of all bullets currently the battlefield private List bullets; // Current TPS (turns per second) private int tps; // Current turn private int turn; // Current round private int round; /** * Constructs a snapshot of the battle. * * @param battle the battle to make a snapshot of. * @param battleRobots TODO * @param battleBullets TODO * @param readoutText TODO */ public TurnSnapshot(Battle battle, List battleRobots, List battleBullets, boolean readoutText) { // fieldWidth = battle.getBattleField().getWidth(); // fieldHeight = battle.getBattleField().getHeight(); robots = new ArrayList(); bullets = new ArrayList(); for (RobotPeer robotPeer : battleRobots) { robots.add(new RobotSnapshot(robotPeer, readoutText)); } for (BulletPeer bulletPeer : battleBullets) { bullets.add(new BulletSnapshot(bulletPeer)); } tps = battle.getTPS(); turn = battle.getTime(); round = battle.getRoundNum(); } public IRobotSnapshot[] getRobots() { return robots.toArray(new IRobotSnapshot[robots.size()]); } public IBulletSnapshot[] getBullets() { return bullets.toArray(new IBulletSnapshot[bullets.size()]); } public int getTPS() { return tps; } public int getRound() { return round; } public int getTurn() { return turn; } public IScoreSnapshot[] getSortedTeamScores() { List copy = new ArrayList(Arrays.asList(getIndexedTeamScores())); Collections.sort(copy); Collections.reverse(copy); return copy.toArray(new IScoreSnapshot[copy.size()]); } public IScoreSnapshot[] getIndexedTeamScores() { // team scores are computed on demand from team scores to not duplicate data in the snapshot List results = new ArrayList(); // noinspection ForLoopReplaceableByForEach for (int i = 0; i < robots.size(); i++) { results.add(null); } for (IRobotSnapshot robot : robots) { final IScoreSnapshot snapshot = results.get(robot.getContestantIndex()); if (snapshot == null) { results.set(robot.getContestantIndex(), robot.getScoreSnapshot()); } else { final ScoreSnapshot sum = new ScoreSnapshot(snapshot, robot.getScoreSnapshot(), robot.getTeamName()); results.set(robot.getContestantIndex(), sum); } } List scores = new ArrayList(); for (IScoreSnapshot scoreSnapshot : results) { if (scoreSnapshot != null) { scores.add(scoreSnapshot); } } return scores.toArray(new IScoreSnapshot[scores.size()]); } @Override public String toString() { return this.round + "/" + turn + " (" + this.robots.size() + ")"; } public void writeXml(XmlWriter writer, Dictionary options) throws IOException { writer.startElement("turn"); { writer.writeAttribute("round", round); writer.writeAttribute("turn", turn); writer.writeAttribute("ver", serialVersionUID); writer.startElement("robots"); { for (IRobotSnapshot r : robots) { ((RobotSnapshot) r).writeXml(writer, options); } } writer.endElement(); writer.startElement("bullets"); { for (IBulletSnapshot b : bullets) { ((BulletSnapshot) b).writeXml(writer, options); } } writer.endElement(); } writer.endElement(); } public TurnSnapshot() {} public XmlReader.Element readXml(XmlReader reader) { return reader.expect("turn", new XmlReader.Element() { public IXmlSerializable read(XmlReader reader) { final TurnSnapshot snapshot = new TurnSnapshot(); reader.expect("turn", new XmlReader.Attribute() { public void read(String value) { snapshot.turn = Integer.parseInt(value); } }); reader.expect("round", new XmlReader.Attribute() { public void read(String value) { snapshot.round = Integer.parseInt(value); } }); reader.expect("robots", new XmlReader.ListElement() { public IXmlSerializable read(XmlReader reader) { snapshot.robots = new ArrayList(); // prototype return new RobotSnapshot(); } public void add(IXmlSerializable child) { snapshot.robots.add((RobotSnapshot) child); } public void close() {} }); reader.expect("bullets", new XmlReader.ListElement() { public IXmlSerializable read(XmlReader reader) { snapshot.bullets = new ArrayList(); // prototype return new BulletSnapshot(); } public void add(IXmlSerializable child) { snapshot.bullets.add((BulletSnapshot) child); } public void close() {} }); return snapshot; } }); } } robocode/robocode/robocode/battle/snapshot/BulletSnapshot.java0000644000175000017500000001505611130241114024153 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen * - Initial implementation * Pavel Savara * - Xml Serialization, refactoring *******************************************************************************/ package robocode.battle.snapshot; import robocode.common.IXmlSerializable; import robocode.common.XmlReader; import robocode.common.XmlWriter; import robocode.control.snapshot.IBulletSnapshot; import robocode.control.snapshot.BulletState; import robocode.peer.BulletPeer; import robocode.peer.ExecCommands; import robocode.peer.ExplosionPeer; import java.io.IOException; import java.util.Dictionary; /** * A bullet snapshot, which is a view of the data for the bullet at a particular * instant in time. *

* Note that this class is implemented as an immutable object. The idea of the * immutable object is that it cannot be modified after it has been created. * See the Immutable * object definition on Wikipedia. *

* Immutable objects are considered to be more thread-safe than mutable * objects, if implemented correctly. *

* All member fields must be final, and provided thru the constructor. * The constructor must make a deep copy of the data assigned to the * member fields and the getters of this class must return a copy of the data * that to return. * * @author Flemming N. Larsen (original) * @author Pavel Savara (contributor) * @since 1.6.1 */ public final class BulletSnapshot implements java.io.Serializable, IXmlSerializable, IBulletSnapshot { private static final long serialVersionUID = 1L; // The name of the robot that owns this bullet // private final String ownerName; // The bullet state private BulletState state; // The bullet power private double power; // The x coordinate private double x; // The y coordinate private double y; // The x coordinate for painting (due to offset on robot when bullet hits a robot) private double paintX; // The y coordinate for painting (due to offset on robot when bullet hits a robot) private double paintY; // The color of the bullet private int color = ExecCommands.defaultBulletColor; // The current frame number to display private int frame; // Flag specifying if this bullet has turned into an explosion private boolean isExplosion; // Index to which explosion image that must be rendered private int explosionImageIndex; /** * Constructs a snapshot of the bullet. * * @param peer the bullet peer to make a snapshot of. */ public BulletSnapshot(BulletPeer peer) { // ownerName = peer.getOwner().getName(); state = peer.getState(); power = peer.getPower(); x = peer.getX(); y = peer.getY(); paintX = peer.getPaintX(); paintY = peer.getPaintY(); color = peer.getColor(); frame = peer.getFrame(); isExplosion = peer instanceof ExplosionPeer; explosionImageIndex = peer.getExplosionImageIndex(); } /** * Returns the name of the robot that owns this bullet. * * @return the name of the robot that owns this bullet. */ // public String getOwnerName() { // return ownerName; // } public BulletState getState() { return state; } public double getPower() { return power; } public double getX() { return x; } public double getY() { return y; } public double getPaintX() { return paintX; } public double getPaintY() { return paintY; } public int getColor() { return color; } public int getFrame() { return frame; } public boolean isExplosion() { return isExplosion; } public int getExplosionImageIndex() { return explosionImageIndex; } public BulletSnapshot() {} public void writeXml(XmlWriter writer, Dictionary options) throws IOException { writer.startElement("bullet"); { writer.writeAttribute("state", state.toString()); writer.writeAttribute("power", power); writer.writeAttribute("x", paintX); writer.writeAttribute("y", paintY); if (color != ExecCommands.defaultBulletColor) { writer.writeAttribute("color", Integer.toHexString(color).toUpperCase()); } if (frame != 0) { writer.writeAttribute("frame", frame); } if (isExplosion) { writer.writeAttribute("isExplosion", true); writer.writeAttribute("explosion", explosionImageIndex); } writer.writeAttribute("ver", serialVersionUID); } writer.endElement(); } public XmlReader.Element readXml(XmlReader reader) { return reader.expect("bullet", new XmlReader.Element() { public IXmlSerializable read(XmlReader reader) { final BulletSnapshot snapshot = new BulletSnapshot(); reader.expect("state", new XmlReader.Attribute() { public void read(String value) { snapshot.state = BulletState.valueOf(value); } }); reader.expect("power", new XmlReader.Attribute() { public void read(String value) { snapshot.power = Double.parseDouble(value); } }); reader.expect("x", new XmlReader.Attribute() { public void read(String value) { snapshot.x = Double.parseDouble(value); snapshot.paintX = snapshot.x; } }); reader.expect("y", new XmlReader.Attribute() { public void read(String value) { snapshot.y = Double.parseDouble(value); snapshot.paintY = snapshot.y; } }); reader.expect("color", new XmlReader.Attribute() { public void read(String value) { snapshot.color = Long.valueOf(value.toUpperCase(), 16).intValue(); } }); reader.expect("isExplosion", new XmlReader.Attribute() { public void read(String value) { snapshot.isExplosion = Boolean.parseBoolean(value); } }); reader.expect("explosion", new XmlReader.Attribute() { public void read(String value) { snapshot.explosionImageIndex = Integer.parseInt(value); } }); reader.expect("frame", new XmlReader.Attribute() { public void read(String value) { snapshot.frame = Integer.parseInt(value); } }); return snapshot; } }); } } robocode/robocode/robocode/battle/snapshot/RobotSnapshot.java0000644000175000017500000003531411130241114024010 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen * - Initial implementation * Pavel Savara * - Xml Serialization, refactoring *******************************************************************************/ package robocode.battle.snapshot; import robocode.common.IXmlSerializable; import robocode.common.XmlReader; import robocode.common.XmlWriter; import robocode.control.snapshot.IRobotSnapshot; import robocode.control.snapshot.IScoreSnapshot; import robocode.control.snapshot.RobotState; import robocode.peer.DebugProperty; import robocode.peer.ExecCommands; import robocode.peer.RobotPeer; import robocode.robotpaint.Graphics2DProxy; import java.awt.geom.Arc2D; import java.io.IOException; import java.io.Serializable; import java.util.Dictionary; import java.util.List; /** * A robot snapshot, which is a view of the data for the robot at a particular * instant in time. *

* Note that this class is implemented as an immutable object. The idea of the * immutable object is that it cannot be modified after it has been created. * See the Immutable * object definition on Wikipedia. *

* Immutable objects are considered to be more thread-safe than mutable * objects, if implemented correctly. *

* All member fields must be final, and provided thru the constructor. * The constructor must make a deep copy of the data assigned to the * member fields and the getters of this class must return a copy of the data * that to return. * * @author Flemming N. Larsen (original) * @author Pavel Savara (contributor) * @since 1.6.1 */ public final class RobotSnapshot implements Serializable, IXmlSerializable, IRobotSnapshot { private static final long serialVersionUID = 1L; // The name of the robot private String name; // The short name of the robot private String shortName; // The very short name of the robot private String veryShortName; // The very short name of the team leader robot (might be null) private String teamName; private int contestIndex; // The robot state private RobotState state; // The energy level private double energy; // The energy level private double velocity; // The heat level private double gunHeat; // The body heading in radians private double bodyHeading; // The gun heading in radians private double gunHeading; // The radar heading in radians private double radarHeading; // The x coordinate private double x; // The y coordinate private double y; // The color of the body private int bodyColor = ExecCommands.defaultBodyColor; // The color of the gun private int gunColor = ExecCommands.defaultGunColor; // The color of the radar private int radarColor = ExecCommands.defaultRadarColor; // The color of the scan arc private int scanColor = ExecCommands.defaultScanColor; // The color of the bullet // Flag specifying if this robot is a Droid private boolean isDroid; // Flag specifying if this robot is a IPaintRobot or is asking for getGraphics private boolean isPaintRobot; // Flag specifying if robot's (onPaint) painting is enabled for the robot private boolean isPaintEnabled; // Flag specifying if RobocodeSG painting is enabled for the robot private boolean isSGPaintEnabled; // The scan arc private SerializableArc scanArc; // The Graphics2D proxy private List graphicsCalls; private DebugProperty[] debugProperties; // The output print stream proxy private String outputStreamSnapshot; // Snapshot of score for robot private IScoreSnapshot robotScoreSnapshot; /** * Constructs a snapshot of the robot. * * @param peer the robot peer to make a snapshot of. * @param readoutText true to send text from robot */ public RobotSnapshot(RobotPeer peer, boolean readoutText) { name = peer.getName(); shortName = peer.getShortName(); veryShortName = peer.getVeryShortName(); teamName = peer.getTeamName(); contestIndex = peer.getContestIndex(); state = peer.getState(); energy = peer.getEnergy(); velocity = peer.getVelocity(); gunHeat = peer.getGunHeat(); bodyHeading = peer.getBodyHeading(); gunHeading = peer.getGunHeading(); radarHeading = peer.getRadarHeading(); x = peer.getX(); y = peer.getY(); bodyColor = peer.getBodyColor(); gunColor = peer.getGunColor(); radarColor = peer.getRadarColor(); scanColor = peer.getScanColor(); isDroid = peer.isDroid(); isPaintRobot = peer.isPaintRobot() || peer.isTryingToPaint(); isPaintEnabled = peer.isPaintEnabled(); isSGPaintEnabled = peer.isSGPaintEnabled(); scanArc = peer.getScanArc() != null ? new SerializableArc((Arc2D.Double) peer.getScanArc()) : null; graphicsCalls = peer.getGraphicsCalls(); final List dp = peer.getDebugProperties(); debugProperties = dp != null ? dp.toArray(new DebugProperty[dp.size()]) : null; if (readoutText) { outputStreamSnapshot = peer.readOutText(); } robotScoreSnapshot = new ScoreSnapshot(peer.getRobotStatistics(), peer.getName()); } public String getName() { // used to identify buttons return name; } public String getShortName() { // used for text on buttons return shortName; } public String getVeryShortName() { // used for drawign text on battleview return veryShortName; } public String getTeamName() { return teamName; } public int getContestantIndex() { return contestIndex; } public RobotState getState() { return state; } public double getEnergy() { return energy; } public double getVelocity() { return velocity; } public double getBodyHeading() { return bodyHeading; } public double getGunHeading() { return gunHeading; } public double getRadarHeading() { return radarHeading; } public double getGunHeat() { return gunHeat; } public double getX() { return x; } public double getY() { return y; } public int getBodyColor() { return bodyColor; } public int getGunColor() { return gunColor; } public int getRadarColor() { return radarColor; } public int getScanColor() { return scanColor; } public boolean isDroid() { return isDroid; } public boolean isPaintRobot() { return isPaintRobot; } public boolean isPaintEnabled() { return isPaintEnabled; } /** * Updates a flag specifying if robot's (onPaint) painting is enabled for * the robot. * @param value new value */ public void overridePaintEnabled(boolean value) { isPaintEnabled = value; } public boolean isSGPaintEnabled() { return isSGPaintEnabled; } /** * Returns the scan arc for the robot. * * @return the scan arc for the robot. */ public Arc2D getScanArc() { return scanArc != null ? scanArc.create() : null; } /** * Returns the Graphics2D queued calls for this robot. * * @return the Graphics2D queued calls for this robot. */ public java.util.List getGraphicsCalls() { return graphicsCalls; } public DebugProperty[] getDebugProperties() { return debugProperties; } public String getOutputStreamSnapshot() { return outputStreamSnapshot; } /** * Sets new value of out text * * @param text new value */ public void updateOutputStreamSnapshot(String text) { outputStreamSnapshot = text; } public IScoreSnapshot getScoreSnapshot() { return robotScoreSnapshot; } // to overcome various serialization problems with Arc2D // to cope with bug in Java 6 // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6522514 private class SerializableArc implements Serializable { private static final long serialVersionUID = 1L; public double x; public double y; public double w; public double h; public double start; public double extent; public int type; public SerializableArc() {} public SerializableArc(Arc2D.Double arc) { x = arc.getX(); y = arc.getY(); w = arc.getWidth(); h = arc.getHeight(); start = arc.getAngleStart(); extent = arc.getAngleExtent(); type = arc.getArcType(); } public Arc2D create() { return new Arc2D.Double(x, y, w, h, start, extent, type); } } @Override public String toString() { return shortName + "(" + (int) energy + ") X" + (int) x + " Y" + (int) y + " " + state.toString(); } public void writeXml(XmlWriter writer, Dictionary options) throws IOException { writer.startElement("robot"); { final Object details = options == null ? null : options.get("skipDetails"); writer.writeAttribute("vsName", veryShortName); writer.writeAttribute("state", state.toString()); writer.writeAttribute("energy", energy); writer.writeAttribute("x", x); writer.writeAttribute("y", y); writer.writeAttribute("bodyHeading", bodyHeading); writer.writeAttribute("gunHeading", gunHeading); writer.writeAttribute("radarHeading", radarHeading); writer.writeAttribute("gunHeat", gunHeat); writer.writeAttribute("velocity", velocity); writer.writeAttribute("teamName", teamName); if (details == null) { writer.writeAttribute("name", name); writer.writeAttribute("sName", shortName); if (isDroid) { writer.writeAttribute("isDroid", true); } if (bodyColor != ExecCommands.defaultBodyColor) { writer.writeAttribute("bodyColor", Integer.toHexString(bodyColor).toUpperCase()); } if (gunColor != ExecCommands.defaultGunColor) { writer.writeAttribute("gunColor", Integer.toHexString(gunColor).toUpperCase()); } if (radarColor != ExecCommands.defaultRadarColor) { writer.writeAttribute("radarColor", Integer.toHexString(radarColor).toUpperCase()); } if (scanColor != ExecCommands.defaultScanColor) { writer.writeAttribute("scanColor", Integer.toHexString(scanColor).toUpperCase()); } } writer.writeAttribute("ver", serialVersionUID); if (outputStreamSnapshot != null && outputStreamSnapshot.length() != 0) { writer.writeAttribute("out", outputStreamSnapshot); } if (debugProperties != null) { writer.startElement("debugProperties"); { for (DebugProperty prop : debugProperties) { prop.writeXml(writer, options); } } writer.endElement(); } ((ScoreSnapshot) robotScoreSnapshot).writeXml(writer, options); } writer.endElement(); } public XmlReader.Element readXml(XmlReader reader) { return reader.expect("robot", new XmlReader.Element() { public IXmlSerializable read(XmlReader reader) { final RobotSnapshot snapshot = new RobotSnapshot(); reader.expect("name", new XmlReader.Attribute() { public void read(String value) { snapshot.name = value; } }); reader.expect("sName", new XmlReader.Attribute() { public void read(String value) { snapshot.shortName = value; } }); reader.expect("vsName", new XmlReader.Attribute() { public void read(String value) { snapshot.veryShortName = value; } }); reader.expect("teamName", new XmlReader.Attribute() { public void read(String value) { snapshot.teamName = value; } }); reader.expect("state", new XmlReader.Attribute() { public void read(String value) { snapshot.state = RobotState.valueOf(value); } }); reader.expect("isDroid", new XmlReader.Attribute() { public void read(String value) { snapshot.isDroid = Boolean.valueOf(value); } }); reader.expect("bodyColor", new XmlReader.Attribute() { public void read(String value) { snapshot.bodyColor = (Long.valueOf(value.toUpperCase(), 16).intValue()); } }); reader.expect("gunColor", new XmlReader.Attribute() { public void read(String value) { snapshot.gunColor = Long.valueOf(value.toUpperCase(), 16).intValue(); } }); reader.expect("radarColor", new XmlReader.Attribute() { public void read(String value) { snapshot.radarColor = Long.valueOf(value.toUpperCase(), 16).intValue(); } }); reader.expect("scanColor", new XmlReader.Attribute() { public void read(String value) { snapshot.scanColor = Long.valueOf(value.toUpperCase(), 16).intValue(); } }); reader.expect("energy", new XmlReader.Attribute() { public void read(String value) { snapshot.energy = Double.parseDouble(value); } }); reader.expect("velocity", new XmlReader.Attribute() { public void read(String value) { snapshot.velocity = Double.parseDouble(value); } }); reader.expect("gunHeat", new XmlReader.Attribute() { public void read(String value) { snapshot.gunHeat = Double.parseDouble(value); } }); reader.expect("bodyHeading", new XmlReader.Attribute() { public void read(String value) { snapshot.bodyHeading = Double.parseDouble(value); } }); reader.expect("gunHeading", new XmlReader.Attribute() { public void read(String value) { snapshot.gunHeading = Double.parseDouble(value); } }); reader.expect("radarHeading", new XmlReader.Attribute() { public void read(String value) { snapshot.radarHeading = Double.parseDouble(value); } }); reader.expect("x", new XmlReader.Attribute() { public void read(String value) { snapshot.x = Double.parseDouble(value); } }); reader.expect("y", new XmlReader.Attribute() { public void read(String value) { snapshot.y = Double.parseDouble(value); } }); reader.expect("out", new XmlReader.Attribute() { public void read(String value) { if (value != null && value.length() != 0) { snapshot.outputStreamSnapshot = value; } } }); final XmlReader.Element element = (new ScoreSnapshot()).readXml(reader); reader.expect("score", new XmlReader.Element() { public IXmlSerializable read(XmlReader reader) { snapshot.robotScoreSnapshot = (IScoreSnapshot) element.read(reader); return (ScoreSnapshot) snapshot.robotScoreSnapshot; } }); return snapshot; } }); } public RobotSnapshot() {} } robocode/robocode/robocode/battle/IBattle.java0000644000175000017500000000165511130241114020671 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.battle; /** * @author Pavel Savara (original) */ public interface IBattle extends Runnable { void cleanup(); boolean isRunning(); void stop(boolean waitTillEnd); void pause(); void resume(); void step(); void waitTillStarted(); void waitTillOver(); void setPaintEnabled(int robotIndex, boolean enable); } robocode/robocode/robocode/battle/events/0000755000175000017500000000000011124142356020012 5ustar lambylambyrobocode/robocode/robocode/battle/events/BattleEventDispatcher.java0000644000175000017500000001051011130241114025063 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen & Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.battle.events; import robocode.control.events.*; import static robocode.io.Logger.logError; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; /** * @author Flemming N. Larsen (original) * @author Pavel Savara (original) * @since 1.6.1 */ public class BattleEventDispatcher implements IBattleListener { // This list is guaranteed to be thread-safe, which is necessary as it will be accessed // by both the battle thread and battle manager thread. If this list is not thread-safe // then ConcurentModificationExceptions will occur from time to time. private final List listeners = new CopyOnWriteArrayList(); public BattleEventDispatcher() {} public void addListener(IBattleListener listener) { assert (listener != null); listeners.add(listener); } public void removeListener(IBattleListener listener) { assert (listener != null); listeners.remove(listener); } public void onBattleStarted(BattleStartedEvent event) { for (IBattleListener listener : listeners) { try { listener.onBattleStarted(event); } catch (Throwable ex) { logError("onBattleStarted " + listener.getClass(), ex); } } } public void onBattleCompleted(BattleCompletedEvent event) { for (IBattleListener listener : listeners) { try { listener.onBattleCompleted(event); } catch (Throwable ex) { logError("onBattleCompleted " + listener.getClass(), ex); } } } public void onBattleFinished(BattleFinishedEvent event) { for (IBattleListener listener : listeners) { try { listener.onBattleFinished(event); } catch (Throwable ex) { logError("onBattleFinished " + listener.getClass(), ex); } } } public void onBattlePaused(BattlePausedEvent event) { for (IBattleListener listener : listeners) { try { listener.onBattlePaused(event); } catch (Throwable ex) { logError("onBattlePaused " + listener.getClass(), ex); } } } public void onBattleResumed(BattleResumedEvent event) { for (IBattleListener listener : listeners) { try { listener.onBattleResumed(event); } catch (Throwable ex) { logError("onBattleResumed " + listener.getClass(), ex); } } } public void onRoundStarted(RoundStartedEvent event) { for (IBattleListener listener : listeners) { try { listener.onRoundStarted(event); } catch (Throwable ex) { logError("onRoundStarted " + listener.getClass(), ex); } } } public void onRoundEnded(RoundEndedEvent event) { for (IBattleListener listener : listeners) { try { listener.onRoundEnded(event); } catch (Throwable ex) { logError("onRoundEnded " + listener.getClass(), ex); } } } public void onTurnStarted(TurnStartedEvent event) { for (IBattleListener listener : listeners) { try { listener.onTurnStarted(event); } catch (Throwable ex) { logError("onTurnStarted " + listener.getClass(), ex); } } } public void onTurnEnded(TurnEndedEvent event) { for (IBattleListener listener : listeners) { try { listener.onTurnEnded(event); } catch (Throwable ex) { logError("onTurnEnded " + listener.getClass(), ex); } } } public void onBattleMessage(BattleMessageEvent event) { for (IBattleListener listener : listeners) { try { listener.onBattleMessage(event); } catch (Throwable ex) { logError("onBattleMessage " + listener.getClass(), ex); } } } public void onBattleError(BattleErrorEvent event) { for (IBattleListener listener : listeners) { try { listener.onBattleError(event); } catch (Throwable ex) { logError("onBattleError " + listener.getClass(), ex); } } } } robocode/robocode/robocode/battle/BattleProperties.java0000644000175000017500000001704711130241114022637 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Added setSelectedRobots(RobotSpecification[]) * - Added property for specifying initial positions and headings of the * selected robots *******************************************************************************/ package robocode.battle; import robocode.AdvancedRobot; import robocode.Robot; import robocode.control.RobotSpecification; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.Serializable; import java.util.Properties; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ public class BattleProperties implements Serializable { private static final long serialVersionUID = 1L; private final static String BATTLEFIELD_WIDTH = "robocode.battleField.width", BATTLEFIELD_HEIGHT = "robocode.battleField.height", BATTLE_NUMROUNDS = "robocode.battle.numRounds", BATTLE_GUNCOOLINGRATE = "robocode.battle.gunCoolingRate", BATTLE_RULES_INACTIVITYTIME = "robocode.battle.rules.inactivityTime", BATTLE_SELECTEDROBOTS = "robocode.battle.selectedRobots", BATTLE_INITIAL_POSITIONS = "robocode.battle.initialPositions"; private int battlefieldWidth = 800; private int battlefieldHeight = 600; private int numRounds = 10; private double gunCoolingRate = 0.1; private long inactivityTime = 450; private String selectedRobots; private String initialPositions; private final Properties props = new Properties(); /** * Gets the battlefieldWidth. * * @return Returns a int */ public int getBattlefieldWidth() { return battlefieldWidth; } /** * Sets the battlefieldWidth. * * @param battlefieldWidth The battlefieldWidth to set */ public void setBattlefieldWidth(int battlefieldWidth) { this.battlefieldWidth = battlefieldWidth; props.setProperty(BATTLEFIELD_WIDTH, "" + battlefieldWidth); } /** * Gets the battlefieldHeight. * * @return Returns a int */ public int getBattlefieldHeight() { return battlefieldHeight; } /** * Sets the battlefieldHeight. * * @param battlefieldHeight The battlefieldHeight to set */ public void setBattlefieldHeight(int battlefieldHeight) { this.battlefieldHeight = battlefieldHeight; props.setProperty(BATTLEFIELD_HEIGHT, "" + battlefieldHeight); } /** * Gets the numRounds. * * @return Returns a int */ public int getNumRounds() { return numRounds; } /** * Sets the numRounds. * * @param numRounds The numRounds to set */ public void setNumRounds(int numRounds) { this.numRounds = numRounds; props.setProperty(BATTLE_NUMROUNDS, "" + numRounds); } /** * Returns the rate at which the gun will cool down, i.e. the amount of heat the gun heat will drop per turn. *

* The gun cooling rate is default 0.1 per turn, but can be changed by the battle setup. * So don't count on the cooling rate being 0.1! * * @return the gun cooling rate * @see #setGunCoolingRate(double) * @see Robot#getGunHeat() * @see Robot#fire(double) * @see Robot#fireBullet(double) * @see robocode.BattleRules#getGunCoolingRate() */ public double getGunCoolingRate() { return gunCoolingRate; } /** * Sets the rate at which the gun will cool down, i.e. the amount of heat the gun heat will drop per turn. * * @param gunCoolingRate the new gun cooling rate * @see #getGunCoolingRate * @see Robot#getGunHeat() * @see Robot#fire(double) * @see Robot#fireBullet(double) * @see robocode.BattleRules#getGunCoolingRate() */ public void setGunCoolingRate(double gunCoolingRate) { this.gunCoolingRate = gunCoolingRate; props.setProperty(BATTLE_GUNCOOLINGRATE, "" + gunCoolingRate); } /** * Returns the allowed inactivity time, where the robot is not taking any action, before will begin to be zapped. * The inactivity time is measured in turns, and is the allowed time that a robot is allowed to omit taking * action before being punished by the game by zapping. *

* When a robot is zapped by the game, it will loose 0.1 energy points per turn. Eventually the robot will be * killed by zapping until the robot takes action. When the robot takes action, the inactivity time counter is * reset. *

* The allowed inactivity time is per default 450 turns, but can be changed by the battle setup. * So don't count on the inactivity time being 450 turns! * * @return the allowed inactivity time. * @see robocode.BattleRules#getInactivityTime() * @see Robot#doNothing() * @see AdvancedRobot#execute() */ public long getInactivityTime() { return inactivityTime; } /** * Sets the allowed inactivity time, where the robot is not taking any action, before will begin to be zapped. * * @param inactivityTime the new allowed inactivity time. * @see robocode.BattleRules#getInactivityTime() * @see Robot#doNothing() * @see AdvancedRobot#execute() */ public void setInactivityTime(long inactivityTime) { this.inactivityTime = inactivityTime; props.setProperty(BATTLE_RULES_INACTIVITYTIME, "" + inactivityTime); } /** * Gets the selectedRobots. * * @return Returns a String */ public String getSelectedRobots() { return selectedRobots; } /** * Sets the selectedRobots. * * @param selectedRobots The selectedRobots to set */ public void setSelectedRobots(String selectedRobots) { this.selectedRobots = selectedRobots; props.setProperty(BATTLE_SELECTEDROBOTS, "" + selectedRobots); } /** * Sets the selectedRobots. * * @param robots The robots to set */ public void setSelectedRobots(RobotSpecification[] robots) { String robotString = ""; RobotSpecification robot; for (int i = 0; i < robots.length; i++) { robot = robots[i]; if (robot == null) { continue; } robotString += robot.getClassName(); if (!(robot.getVersion() == null || robot.getVersion().length() == 0)) { robotString += " " + robot.getVersion(); } if (i < robots.length - 1) { robotString += ","; } } setSelectedRobots(robotString); } /** * Gets the initial robot positions and heading. * * @return a comma-separated string */ public String getInitialPositions() { return initialPositions; } public void store(FileOutputStream out, String desc) throws IOException { props.store(out, desc); } public void load(FileInputStream in) throws IOException { props.load(in); battlefieldWidth = Integer.parseInt(props.getProperty(BATTLEFIELD_WIDTH, "800")); battlefieldHeight = Integer.parseInt(props.getProperty(BATTLEFIELD_HEIGHT, "600")); gunCoolingRate = Double.parseDouble(props.getProperty(BATTLE_GUNCOOLINGRATE, "0.1")); inactivityTime = Long.parseLong(props.getProperty(BATTLE_RULES_INACTIVITYTIME, "450")); numRounds = Integer.parseInt(props.getProperty(BATTLE_NUMROUNDS, "10")); selectedRobots = props.getProperty(BATTLE_SELECTEDROBOTS, ""); initialPositions = props.getProperty(BATTLE_INITIAL_POSITIONS, ""); } } robocode/robocode/robocode/battle/Battle.java0000644000175000017500000007062311130241114020561 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup * - Replaced the ContestantPeerVector, BulletPeerVector, and RobotPeerVector * with plain Vector * - Integration of new render classes placed under the robocode.gfx package * - BattleView is not given via the constructor anymore, but is retrieved * from the RobocodeManager. In addition, the battleView is now allowed to * be null, e.g. if no GUI is available * - Ported to Java 5.0 * - Bugfixed sounds that were cut off after first battle * - Changed initialize() to use loadClass() instead of loadRobotClass() if * security is turned off * - Changed the way the TPS is loaded and updated * - Added updateTitle() in order to manage and update the title on the * RobocodeFrame * - Added replay feature * - Updated to use methods from the Logger, which replaces logger methods * that has been (re)moved from the robocode.util.Utils class * - Changed so robots die faster graphically when the battles are over * - Changed cleanup to only remove the robot in the robot peers, as the * robot peers themselves are used for replay recording * - Added support for playing background music when the battle is ongoing * - Removed unnecessary catches of NullPointerExceptions * - Added support for setting the initial robot positions on the battlefield * - Removed the showResultsDialog field which is replaced by the * getOptionsCommonShowResults() from the properties * - Simplified the code in the run() method when battle is stopped * - Changed so that stop() makes the current round stop immediately * - Added handling keyboard events thru a KeyboardEventDispatcher * - Added mouseMoved(), mouseClicked(), mouseReleased(), mouseEntered(), * mouseExited(), mouseDragged(), mouseWheelMoved() * - Changed to take the new JuniorRobot class into account * - When cleaning up robots their static fields are now being cleaned up * - Bugfix: Changed the runRound() so that the robot are painted after * they have made their turn * - The thread handling for unsafe robot loading has been put in an * independent UnsafeLoadRobotsThread class. In addition, the battle * thread is not sharing it's run() method anymore with the * UnsafeLoadRobotsThread, which has now got its own run() method * - The 'running' and 'aborted' flags are now synchronized towards * 'battleMonitor' instead of 'this' object * - Added waitTillRunning() method so another thread can be blocked until * the battle has started running * - Replaced synchronizedList on lists for deathEvent, robots, bullets, * and contestants with a CopyOnWriteArrayList in order to prevent * ConcurrentModificationExceptions when accessing these list via * Iterators using public methods to this class * - The moveBullets() was simplified and moved inside the runRound() method * - The flushOldEvents() method was moved into the runRound() method * - Major bugfix: Two robots running with exactly the same code was getting * different scores. Robots listed before other robots always got a better * score in the end. Hence, the getRobotsAtRandom() method has been added * in order to gain fair play, and this method should be used where robots * are checked and awakened in turn * - Simplified the repainting of the battle * - Bugfix: In wakeupRobots(), only wakeup a robot that is running and alive * - A StatusEvent is now send to all alive robot each turn * - Extended allowed max. length of a robot's full package name from 16 to * 32 characters * Luis Crespo * - Added sound features using the playSounds() method * - Added debug step feature * - Added isRunning() * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap * Titus Chen * - Bugfix: Added Battle parameter to the constructor that takes a * BulletRecord as parameter due to a NullPointerException that was raised * as the battleField variable was not intialized * Nathaniel Troutman * - Bugfix: In order to prevent memory leaks, the cleanup() method has now * been extended to cleanup all robots, but also all classes that this * class refers to in order to avoid circular references. In addition, * cleanup has been added to the KeyEventHandler * Julian Kent * - Fix: Method for using only nano second precision when using * RobotPeer.wait(0, nanoSeconds) in order to prevent the millisecond * granularity issue, which is typically were coarse compared to the one * with nano seconds * Pavel Savara * - Re-work of robot interfaces * - Refactored large methods into several smaller methods * - decomposed RobotPeer from RobotProxy, now sending messages beteen them *******************************************************************************/ package robocode.battle; import robocode.*; import robocode.battle.events.BattleEventDispatcher; import robocode.battle.snapshot.TurnSnapshot; import robocode.common.Command; import robocode.control.RandomFactory; import robocode.control.RobotResults; import robocode.control.RobotSpecification; import robocode.control.events.*; import robocode.control.snapshot.ITurnSnapshot; import robocode.control.snapshot.BulletState; import robocode.io.Logger; import robocode.manager.RobocodeManager; import robocode.peer.*; import robocode.peer.robot.RobotClassManager; import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * The {@code Battle} class is used for controlling a battle. * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Luis Crespo (contributor) * @author Robert D. Maupin (contributor) * @author Titus Chen (contributor) * @author Nathaniel Troutman (contributor) * @author Julian Kent (contributor) * @author Pavel Savara (contributor) */ public final class Battle extends BaseBattle { // Inactivity related items private int inactiveTurnCount; private double inactivityEnergy; // Turn skip related items private boolean parallelOn; static final int DEBUG_TURN_WAIT = 10 * 60 * 1000; private int millisWait; private int microWait; // Objects in the battle private final int robotsCount; private List robots = new ArrayList(); private List contestants = new ArrayList(); private final List bullets = new CopyOnWriteArrayList(); private int activeRobots; // Death events private final List deathRobots = new CopyOnWriteArrayList(); // Flag specifying if debugging is enabled thru the debug command line option private final boolean isDebugging; // Initial robot start positions (if any) private double[][] initialRobotPositions; public Battle(List battlingRobotsList, BattleProperties battleProperties, RobocodeManager manager, BattleEventDispatcher eventDispatcher, boolean paused) { super(manager, eventDispatcher, paused); isDebugging = System.getProperty("debug", "false").equals("true"); battleRules = new BattleRules(battleProperties); robotsCount = battlingRobotsList.size(); computeInitialPositions(battleProperties.getInitialPositions()); createPeers(battlingRobotsList); } private void createPeers(List battlingRobotsList) { // create teams Hashtable countedNames = new Hashtable(); List teams = new ArrayList(); List teamDuplicates = new ArrayList(); List robotDuplicates = new ArrayList(); // count duplicate robots, enumerate teams, enumerate team members for (RobotClassManager rcm : battlingRobotsList) { final String name = rcm.getClassNameManager().getFullClassNameWithVersion(); if (countedNames.containsKey(name)) { int value = countedNames.get(name); countedNames.put(name, value == 1 ? 3 : value + 1); } else { countedNames.put(name, 1); } String teamFullName = rcm.getTeamName(); if (teamFullName != null) { if (!teams.contains(teamFullName)) { teams.add(teamFullName); String teamName = teamFullName.substring(0, teamFullName.length() - 6); if (countedNames.containsKey(teamName)) { int value = countedNames.get(teamName); countedNames.put(teamName, value == 1 ? 3 : value + 1); } else { countedNames.put(teamName, 1); } } } } Hashtable> teamMembers = new Hashtable>(); // name teams for (int i = teams.size() - 1; i >= 0; i--) { String teamFullName = teams.get(i); String name = teamFullName.substring(0, teamFullName.length() - 6); Integer order = countedNames.get(name); String newTeamName = name; if (order > 1) { newTeamName = name + " (" + (order - 1) + ")"; } teamDuplicates.add(0, newTeamName); teamMembers.put(teamFullName, new ArrayList()); countedNames.put(name, order - 1); } // name robots for (int i = battlingRobotsList.size() - 1; i >= 0; i--) { RobotClassManager rcm = battlingRobotsList.get(i); String name = rcm.getClassNameManager().getFullClassNameWithVersion(); Integer order = countedNames.get(name); int duplicate = -1; String newName = name; if (order > 1) { duplicate = (order - 2); newName = name + " (" + (order - 1) + ")"; } countedNames.put(name, (order - 1)); robotDuplicates.add(0, duplicate); String teamFullName = rcm.getTeamName(); if (teamFullName != null) { List members = teamMembers.get(teamFullName); members.add(newName); } } // create teams Hashtable namedTeams = new Hashtable(); // create robots for (int i = 0; i < battlingRobotsList.size(); i++) { RobotClassManager rcm = battlingRobotsList.get(i); TeamPeer team = null; String teamFullName = rcm.getTeamName(); int cindex = contestants.size(); if (teamFullName != null) { if (!namedTeams.containsKey(teamFullName)) { final int teamIndex = teams.indexOf(teamFullName); String newTeamName = teamDuplicates.get(teamIndex); team = new TeamPeer(newTeamName, teamMembers.get(teamFullName), contestants.size()); namedTeams.put(teamFullName, team); contestants.add(team); } else { team = namedTeams.get(teamFullName); if (team != null) { cindex = team.getContestIndex(); } } } Integer duplicate = robotDuplicates.get(i); RobotPeer robotPeer = new RobotPeer(this, manager.getHostManager(), rcm, duplicate, team, robots.size(), cindex); robots.add(robotPeer); if (team == null) { contestants.add(robotPeer); } } } public void registerDeathRobot(RobotPeer r) { deathRobots.add(r); } public BattleRules getBattleRules() { return battleRules; } public int getRobotsCount() { return robotsCount; } public boolean isDebugging() { return isDebugging; } public void removeBullet(BulletPeer bullet) { bullets.remove(bullet); } public void addBullet(BulletPeer bullet) { bullets.add(bullet); } public void resetInactiveTurnCount(double energyLoss) { if (energyLoss < 0) { return; } inactivityEnergy += energyLoss; while (inactivityEnergy >= 10) { inactivityEnergy -= 10; inactiveTurnCount = 0; } } /** * Gets the activeRobots. * * @return Returns a int */ public int getActiveRobots() { return activeRobots; } @Override public void cleanup() { if (contestants != null) { contestants.clear(); contestants = null; } if (robots != null) { robots.clear(); robots = null; } super.cleanup(); battleManager = null; Logger.setLogListener(null); // Request garbage collecting for (int i = 4; i >= 0; i--) { // Make sure it is run System.gc(); } } @Override protected void initializeBattle() { super.initializeBattle(); parallelOn = System.getProperty("PARALLEL", "false").equals("true"); if (parallelOn) { // how could robots share CPUs ? double parallelConstant = robots.size() / Runtime.getRuntime().availableProcessors(); // four CPUs can't run two single threaded robot faster than two CPUs if (parallelConstant < 1) { parallelConstant = 1; } final long waitTime = (long) (manager.getCpuManager().getCpuConstant() * parallelConstant); millisWait = (int) (waitTime / 1000000); microWait = (int) (waitTime % 1000000); } else { final long waitTime = manager.getCpuManager().getCpuConstant(); millisWait = (int) (waitTime / 1000000); microWait = (int) (waitTime % 1000000); } if (microWait == 0) { microWait = 1; } } @Override protected void finalizeBattle() { eventDispatcher.onBattleFinished(new BattleFinishedEvent(isAborted())); if (!isAborted()) { eventDispatcher.onBattleCompleted(new BattleCompletedEvent(battleRules, computeBattleResults())); } for (RobotPeer robotPeer : robots) { robotPeer.cleanup(); } manager.getThreadManager().reset(); super.finalizeBattle(); } @Override protected void preloadRound() { super.preloadRound(); // At this point the unsafe loader thread will now set itself to wait for a notify for (RobotPeer robotPeer : robots) { robotPeer.initializeRound(robots, initialRobotPositions); robotPeer.println("========================="); robotPeer.println("Round " + (getRoundNum() + 1) + " of " + getNumRounds()); robotPeer.println("========================="); } if (getRoundNum() == 0) { eventDispatcher.onBattleStarted(new BattleStartedEvent(battleRules, robots.size(), false)); if (isPaused()) { eventDispatcher.onBattlePaused(new BattlePausedEvent()); } } computeActiveRobots(); manager.getThreadManager().reset(); } @Override protected void initializeRound() { super.initializeRound(); inactiveTurnCount = 0; // start robots final long waitTime = Math.min(300 * manager.getCpuManager().getCpuConstant(), 10000000000L); for (RobotPeer robotPeer : getRobotsAtRandom()) { robotPeer.getRobotStatistics().initialize(); robotPeer.startRound(waitTime); } Logger.logMessage(""); final ITurnSnapshot snapshot = new TurnSnapshot(this, robots, bullets, false); eventDispatcher.onRoundStarted(new RoundStartedEvent(snapshot, getRoundNum())); } @Override protected void finalizeRound() { super.finalizeRound(); for (RobotPeer robotPeer : robots) { robotPeer.waitForStop(); robotPeer.getRobotStatistics().generateTotals(); } bullets.clear(); eventDispatcher.onRoundEnded(new RoundEndedEvent(getRoundNum(), currentTime)); } @Override protected void initializeTurn() { super.initializeTurn(); eventDispatcher.onTurnStarted(new TurnStartedEvent()); } @Override protected void runTurn() { super.runTurn(); loadCommands(); updateBullets(); updateRobots(); handleDeathRobots(); if (isAborted() || oneTeamRemaining()) { shutdownTurn(); } inactiveTurnCount++; computeActiveRobots(); publishStatuses(); // Robot time! wakeupRobots(); } @Override protected void shutdownTurn() { if (getEndTimer() == 0) { if (isAborted()) { for (RobotPeer robotPeer : getRobotsAtRandom()) { if (!robotPeer.isDead()) { robotPeer.println("SYSTEM: game aborted."); } } } else if (oneTeamRemaining()) { boolean leaderFirsts = false; TeamPeer winningTeam = null; for (RobotPeer robotPeer : getRobotsAtRandom()) { if (!robotPeer.isDead()) { if (!robotPeer.isWinner()) { robotPeer.getRobotStatistics().scoreLastSurvivor(); robotPeer.setWinner(true); robotPeer.println("SYSTEM: " + robotPeer.getName() + " wins the round."); robotPeer.addEvent(new WinEvent()); if (robotPeer.getTeamPeer() != null) { if (robotPeer.isTeamLeader()) { leaderFirsts = true; } else { winningTeam = robotPeer.getTeamPeer(); } } } } } if (!leaderFirsts && winningTeam != null) { winningTeam.getTeamLeader().getRobotStatistics().scoreFirsts(); } } } if (getEndTimer() == 1 && (isAborted() || isLastRound())) { List orderedRobots = new ArrayList(robots); Collections.sort(orderedRobots); Collections.reverse(orderedRobots); for (int rank = 0; rank < robots.size(); rank++) { RobotPeer robotPeer = orderedRobots.get(rank); robotPeer.getStatistics().setRank(rank + 1); BattleResults resultsForRobot = robotPeer.getStatistics().getFinalResults(); robotPeer.addEvent(new BattleEndedEvent(isAborted(), resultsForRobot)); } } if (getEndTimer() > 4 * 30) { for (RobotPeer robotPeer : robots) { robotPeer.setHalt(true); } } super.shutdownTurn(); } @Override protected void finalizeTurn() { eventDispatcher.onTurnEnded(new TurnEndedEvent(new TurnSnapshot(this, robots, bullets, true))); super.finalizeTurn(); } private BattleResults[] computeBattleResults() { ArrayList results = new ArrayList(); List orderedContestants = new ArrayList(contestants); Collections.sort(orderedContestants); Collections.reverse(orderedContestants); // noinspection ForLoopReplaceableByForEach for (int i = 0; i < contestants.size(); i++) { results.add(null); } for (int rank = 0; rank < contestants.size(); rank++) { RobotSpecification robotSpec = null; ContestantPeer contestant = orderedContestants.get(rank); contestant.getStatistics().setRank(rank + 1); BattleResults battleResults = contestant.getStatistics().getFinalResults(); if (contestant instanceof RobotPeer) { robotSpec = ((RobotPeer) contestant).getControlRobotSpecification(); } else if (contestant instanceof TeamPeer) { robotSpec = ((TeamPeer) contestant).getTeamLeader().getControlRobotSpecification(); } results.set(contestant.getContestIndex(), new RobotResults(robotSpec, battleResults)); } return results.toArray(new BattleResults[results.size()]); } /** * Returns a list of all robots in random order. This method is used to gain fair play in Robocode, * so that a robot placed before another robot in the list will not gain any benefit when the game * checks if a robot has won, is dead, etc. * This method was introduced as two equal robots like sample.RamFire got different scores even * though the code was exactly the same. * * @return a list of robots */ private List getRobotsAtRandom() { List shuffledList = new ArrayList(robots); Collections.shuffle(shuffledList, RandomFactory.getRandom()); return shuffledList; } private void loadCommands() { // this will load commands, including bullets from last turn for (RobotPeer robotPeer : robots) { robotPeer.performLoadCommands(); } } private void updateBullets() { for (BulletPeer b : bullets) { b.update(robots, bullets); if (b.getState() == BulletState.INACTIVE) { bullets.remove(b); } } } private void updateRobots() { boolean zap = (inactiveTurnCount > battleRules.getInactivityTime()); final double zapEnergy = isAborted() ? 5 : zap ? .1 : 0; // Move all bots for (RobotPeer robotPeer : getRobotsAtRandom()) { robotPeer.performMove(robots, zapEnergy); // publish deaths to live robots if (!robotPeer.isDead()) { for (RobotPeer de : deathRobots) { robotPeer.addEvent(new RobotDeathEvent(de.getName())); if (robotPeer.getTeamPeer() == null || robotPeer.getTeamPeer() != de.getTeamPeer()) { robotPeer.getRobotStatistics().scoreSurvival(); } } } } // Scan after moved all for (RobotPeer robotPeer : getRobotsAtRandom()) { robotPeer.performScan(robots); } } private void handleDeathRobots() { // Compute scores for dead robots for (RobotPeer robotPeer : deathRobots) { if (robotPeer.getTeamPeer() == null) { robotPeer.getRobotStatistics().scoreRobotDeath(getActiveContestantCount(robotPeer)); } else { boolean teammatesalive = false; for (RobotPeer tm : robots) { if (tm.getTeamPeer() == robotPeer.getTeamPeer() && (!tm.isDead())) { teammatesalive = true; break; } } if (!teammatesalive) { robotPeer.getRobotStatistics().scoreRobotDeath(getActiveContestantCount(robotPeer)); } } } deathRobots.clear(); } private void publishStatuses() { for (RobotPeer robotPeer : robots) { robotPeer.publishStatus(currentTime); } } private void computeActiveRobots() { int ar = 0; // Compute active robots for (RobotPeer robotPeer : robots) { if (!robotPeer.isDead()) { ar++; } } this.activeRobots = ar; } private void wakeupRobots() { // Wake up all robot threads final List robotsAtRandom = getRobotsAtRandom(); if (parallelOn) { wakeupParallel(robotsAtRandom); } else { wakeupSerial(robotsAtRandom); } } private void wakeupSerial(List robotsAtRandom) { for (RobotPeer robotPeer : robotsAtRandom) { if (robotPeer.isRunning()) { // This call blocks until the // robot's thread actually wakes up. robotPeer.waitWakeup(); if (robotPeer.isAlive()) { if (isDebugging || robotPeer.isPaintEnabled() || robotPeer.isPaintRecorded()) { robotPeer.waitSleeping(DEBUG_TURN_WAIT, 1); } else { robotPeer.waitSleeping(millisWait, microWait); } } if (robotPeer.isRunning() && robotPeer.isAlive() && !robotPeer.isSleeping()) { robotPeer.setSkippedTurns(); } } } } private void wakeupParallel(List robotsAtRandom) { for (RobotPeer robotPeer : robotsAtRandom) { if (robotPeer.isRunning()) { robotPeer.waitWakeup(); } } for (RobotPeer robotPeer : robotsAtRandom) { if (robotPeer.isRunning() && robotPeer.isAlive()) { if (isDebugging || robotPeer.isPaintEnabled() || robotPeer.isPaintRecorded()) { robotPeer.waitSleeping(DEBUG_TURN_WAIT, 1); } else { robotPeer.waitSleeping(millisWait, microWait); } } } for (RobotPeer robotPeer : robotsAtRandom) { if (robotPeer.isRunning() && robotPeer.isAlive() && !robotPeer.isSleeping()) { robotPeer.setSkippedTurns(); } } } private int getActiveContestantCount(RobotPeer peer) { int count = 0; for (ContestantPeer c : contestants) { if (c instanceof RobotPeer && !((RobotPeer) c).isDead()) { count++; } else if (c instanceof TeamPeer && c != peer.getTeamPeer()) { for (RobotPeer robotPeer : (TeamPeer) c) { if (!robotPeer.isDead()) { count++; break; } } } } return count; } private void computeInitialPositions(String initialPositions) { initialRobotPositions = null; if (initialPositions == null || initialPositions.trim().length() == 0) { return; } List positions = new ArrayList(); Pattern pattern = Pattern.compile("([^,(]*[(][^)]*[)])?[^,]*,?"); Matcher matcher = pattern.matcher(initialPositions); while (matcher.find()) { String pos = matcher.group(); if (pos.length() > 0) { positions.add(pos); } } if (positions.size() == 0) { return; } initialRobotPositions = new double[positions.size()][3]; String[] coords; double x, y, heading; for (int i = 0; i < positions.size(); i++) { coords = positions.get(i).split(","); final Random random = RandomFactory.getRandom(); x = RobotPeer.WIDTH + random.nextDouble() * (battleRules.getBattlefieldWidth() - 2 * RobotPeer.WIDTH); y = RobotPeer.HEIGHT + random.nextDouble() * (battleRules.getBattlefieldHeight() - 2 * RobotPeer.HEIGHT); heading = 2 * Math.PI * random.nextDouble(); int len = coords.length; if (len >= 1) { // noinspection EmptyCatchBlock try { x = Double.parseDouble(coords[0].replaceAll("[\\D]", "")); } catch (NumberFormatException e) {} if (len >= 2) { // noinspection EmptyCatchBlock try { y = Double.parseDouble(coords[1].replaceAll("[\\D]", "")); } catch (NumberFormatException e) {} if (len >= 3) { // noinspection EmptyCatchBlock try { heading = Math.toRadians(Double.parseDouble(coords[2].replaceAll("[\\D]", ""))); } catch (NumberFormatException e) {} } } } initialRobotPositions[i][0] = x; initialRobotPositions[i][1] = y; initialRobotPositions[i][2] = heading; } } private boolean oneTeamRemaining() { if (getActiveRobots() <= 1) { return true; } boolean found = false; TeamPeer currentTeam = null; for (RobotPeer currentRobot : robots) { if (!currentRobot.isDead()) { if (!found) { found = true; currentTeam = currentRobot.getTeamPeer(); } else { if (currentTeam == null && currentRobot.getTeamPeer() == null) { return false; } if (currentTeam != currentRobot.getTeamPeer()) { return false; } } } } return true; } // -------------------------------------------------------------------------- // Processing and maintaining robot and battle controls // -------------------------------------------------------------------------- public void killRobot(int robotIndex) { sendCommand(new KillRobotCommand(robotIndex)); } public void setPaintEnabled(int robotIndex, boolean enable) { sendCommand(new EnableRobotPaintCommand(robotIndex, enable)); } public void setAllPaintRecorded(boolean enable) { sendCommand(new AllRobotsPaintRecordCommand(enable)); } public void setSGPaintEnabled(int robotIndex, boolean enable) { sendCommand(new EnableRobotSGPaintCommand(robotIndex, enable)); } public void sendInteractiveEvent(Event e) { sendCommand(new SendInteractiveEventCommand(e)); } private class KillRobotCommand extends RobotCommand { KillRobotCommand(int robotIndex) { super(robotIndex); } public void execute() { robots.get(robotIndex).kill(); } } private class AllRobotsPaintRecordCommand extends Command { final boolean enablePaintRecord; AllRobotsPaintRecordCommand(boolean enablePaintRecord) { this.enablePaintRecord = enablePaintRecord; } public void execute() { for (RobotPeer robot : robots) { robot.setPaintRecorded(enablePaintRecord); } } } private class EnableRobotPaintCommand extends RobotCommand { final boolean enablePaint; EnableRobotPaintCommand(int robotIndex, boolean enablePaint) { super(robotIndex); this.enablePaint = enablePaint; } public void execute() { robots.get(robotIndex).setPaintEnabled(enablePaint); } } private class EnableRobotSGPaintCommand extends RobotCommand { final boolean enableSGPaint; EnableRobotSGPaintCommand(int robotIndex, boolean enableSGPaint) { super(robotIndex); this.enableSGPaint = enableSGPaint; } public void execute() { robots.get(robotIndex).setSGPaintEnabled(enableSGPaint); } } private class SendInteractiveEventCommand extends Command { public final Event event; SendInteractiveEventCommand(Event event) { this.event = event; } public void execute() { for (RobotPeer robotPeer : robots) { if (robotPeer.isInteractiveRobot()) { robotPeer.addEvent(event); } } } } } robocode/robocode/robocode/battle/BaseBattle.java0000644000175000017500000002551211130241114021351 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Refactoring *******************************************************************************/ package robocode.battle; import robocode.BattleRules; import robocode.battle.events.BattleEventDispatcher; import robocode.common.Command; import robocode.control.events.BattlePausedEvent; import robocode.control.events.BattleResumedEvent; import robocode.io.Logger; import static robocode.io.Logger.logError; import static robocode.io.Logger.logMessage; import robocode.manager.IBattleManager; import robocode.manager.RobocodeManager; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicBoolean; /** * @author Pavel Savara (refactoring) */ public abstract class BaseBattle implements IBattle, Runnable { // Maximum turns to display the battle when battle ended private final static int TURNS_DISPLAYED_AFTER_ENDING = 30; private final static int MAX_TPS = 10000; // Objects we use protected Thread battleThread; protected IBattleManager battleManager; protected final BattleEventDispatcher eventDispatcher; protected final RobocodeManager manager; // rules protected BattleRules battleRules; // Current round items private int roundNum; protected int currentTime; private int endTimer; // TPS (turns per second) calculation stuff private int tps; private long turnStartTime; private long measuredTurnStartTime; private int measuredTurnCounter; // Battle state private final AtomicBoolean isRunning = new AtomicBoolean(false); protected boolean isAborted; // Battle control private boolean isPaused; private int stepCount; private boolean runBackward; private boolean roundOver; private final Queue pendingCommands = new ConcurrentLinkedQueue(); protected BaseBattle(RobocodeManager manager, BattleEventDispatcher eventDispatcher, boolean paused) { isPaused = paused; stepCount = 0; this.manager = manager; this.eventDispatcher = eventDispatcher; battleManager = manager.getBattleManager(); } protected int getEndTimer() { return endTimer; } protected boolean isPaused() { return isPaused; } public void setBattleThread(Thread newBattleThread) { battleThread = newBattleThread; } /** * Sets the roundNum. * * @param roundNum The roundNum to set */ public void setRoundNum(int roundNum) { this.roundNum = roundNum; } /** * Gets the roundNum. * * @return Returns a int */ public int getRoundNum() { return roundNum; } public int getNumRounds() { return battleRules.getNumRounds(); } public Thread getBattleThread() { return battleThread; } public int getTime() { return currentTime; } public boolean isLastRound() { return (roundNum + 1 == getNumRounds()); } public int getTPS() { return tps; } /** * Informs on whether the battle is running or not. * * @return true if the battle is running, false otherwise */ public boolean isRunning() { return isRunning.get(); } /** * Informs on whether the battle is aborted or not. * * @return true if the battle is aborted, false otherwise */ public boolean isAborted() { return isAborted; } public void cleanup() { battleRules = null; if (pendingCommands != null) { pendingCommands.clear(); // don't pendingCommands = null; } } public void waitTillStarted() { synchronized (isRunning) { while (!isRunning.get()) { try { isRunning.wait(); } catch (InterruptedException e) { // Immediately reasserts the exception by interrupting the caller thread itself Thread.currentThread().interrupt(); return; // Break out } } } } public void waitTillOver() { synchronized (isRunning) { while (isRunning.get()) { try { isRunning.wait(); } catch (InterruptedException e) { // Immediately reasserts the exception by interrupting the caller thread itself Thread.currentThread().interrupt(); return; // Break out } } } } /** * When an object implementing interface {@code Runnable} is used * to create a thread, starting the thread causes the object's * {@code run()} method to be called in that separately executing * thread. *

* The general contract of the method {@code run()} is that it may * take any action whatsoever. * * @see java.lang.Thread#run() */ public void run() { try { initializeBattle(); while (!isAborted && roundNum < getNumRounds()) { try { preloadRound(); initializeRound(); runRound(); finalizeRound(); cleanupRound(); } catch (Exception e) { logError("Exception running a battle round: ", e); isAborted = true; } roundNum++; } finalizeBattle(); cleanup(); } catch (Throwable e) { logError("Exception running a battle: ", e); } } protected void initializeBattle() { roundNum = 0; // Notify that the battle is now running synchronized (isRunning) { isRunning.set(true); isRunning.notifyAll(); } } protected void finalizeBattle() { // Notify that the battle is over synchronized (isRunning) { isRunning.set(false); isRunning.notifyAll(); } } protected void preloadRound() { logMessage("----------------------"); Logger.logMessage("Round " + (roundNum + 1) + " initializing..", false); } protected void initializeRound() { logMessage(""); logMessage("Let the games begin!"); roundOver = false; endTimer = 0; currentTime = 0; } private void runRound() { while (!roundOver) { processCommand(); if (shouldPause() && !shouldStep()) { shortSleep(); continue; } initializeTurn(); runTurn(); roundOver = isRoundOver(); finalizeTurn(); } } protected boolean isRoundOver() { return (endTimer > 5 * TURNS_DISPLAYED_AFTER_ENDING); } protected void finalizeRound() {} protected void cleanupRound() { logMessage("Round " + (roundNum + 1) + " cleaning up."); } protected void initializeTurn() { turnStartTime = System.nanoTime(); } protected void runTurn() { if (runBackward) { currentTime--; if (currentTime == 0 && !isPaused) { pauseImpl(); } } else { currentTime++; } } protected void shutdownTurn() { endTimer++; } protected void finalizeTurn() { synchronizeTPS(); calculateTPS(); } private void synchronizeTPS() { // Let the battle sleep is the GUI is enabled and is not minimized // in order to keep the desired TPS if (battleManager.isManagedTPS()) { long delay = 0; if (!isAborted() && endTimer < TURNS_DISPLAYED_AFTER_ENDING) { int desiredTPS = manager.getProperties().getOptionsBattleDesiredTPS(); if (desiredTPS < MAX_TPS) { long deltaTime = System.nanoTime() - turnStartTime; delay = Math.max(1000000000 / desiredTPS - deltaTime, 0); } } if (delay > 500000) { // sleep granularity is worse than 500000 try { Thread.sleep(delay / 1000000, (int) (delay % 1000000)); } catch (InterruptedException e) { // Immediately reasserts the exception by interrupting the caller thread itself Thread.currentThread().interrupt(); } } } } private void calculateTPS() { // Calculate the current turns per second (TPS) if (measuredTurnCounter++ == 0) { measuredTurnStartTime = turnStartTime; } long deltaTime = System.nanoTime() - measuredTurnStartTime; if (deltaTime / 500000000 >= 1) { tps = (int) (measuredTurnCounter * 1000000000L / deltaTime); measuredTurnCounter = 0; } } private boolean shouldPause() { return (isPaused && !isAborted); } private boolean shouldStep() { if (stepCount > 0) { stepCount--; return true; } return false; } // -------------------------------------------------------------------------- // Processing and maintaining robot and battle controls // -------------------------------------------------------------------------- protected void sendCommand(Command command) { pendingCommands.add(command); } private void processCommand() { Command command = pendingCommands.poll(); while (command != null) { try { command.execute(); } catch (Exception e) { logError(e); } command = pendingCommands.poll(); } } public void stop(boolean waitTillEnd) { sendCommand(new AbortCommand()); if (waitTillEnd) { waitTillOver(); } } public void pause() { sendCommand(new PauseCommand()); } public void resume() { sendCommand(new ResumeCommand()); } public void step() { sendCommand(new StepCommand()); } public void stepBack() { sendCommand(new StepBackCommand()); } private class PauseCommand extends Command { public void execute() { pauseImpl(); } } private void pauseImpl() { isPaused = true; stepCount = 0; eventDispatcher.onBattlePaused(new BattlePausedEvent()); } private class ResumeCommand extends Command { public void execute() { isPaused = false; stepCount = 0; eventDispatcher.onBattleResumed(new BattleResumedEvent()); } } private class StepCommand extends Command { public void execute() { runBackward = false; if (isPaused) { stepCount++; } } } public class StepBackCommand extends Command { public void execute() { runBackward = true; if (isPaused) { stepCount++; } } } private class AbortCommand extends Command { public void execute() { isAborted = true; } } protected class RobotCommand extends Command { protected final int robotIndex; protected RobotCommand(int robotIndex) { this.robotIndex = robotIndex; } } // // Utility // private void shortSleep() { try { Thread.sleep(100); } catch (InterruptedException e) { // Immediately reasserts the exception by interrupting the caller thread itself Thread.currentThread().interrupt(); } } public void printSystemThreads() { Thread systemThreads[] = new Thread[256]; battleThread.getThreadGroup().enumerate(systemThreads, false); logMessage("Threads: ------------------------"); for (Thread thread : systemThreads) { if (thread != null) { logError(thread.getName()); } } } } robocode/robocode/robocode/packager/0000755000175000017500000000000011124142010016773 5ustar lambylambyrobocode/robocode/robocode/packager/RobotPackager.java0000644000175000017500000005535411130241112022375 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Matthew Reeder * - Minor changes for UI keyboard accessibility * Flemming N. Larsen * - Code cleanup * - Renamed 'enum' variables to allow compiling with Java 1.5 * - Replaced FileSpecificationVector with plain Vector * - Updated to use methods from the Logger, which replaces logger methods * that have been (re)moved from the robocode.util.Utils class * - Moved the NoDuplicateJarOutputStream into the robocode.io package * - Added codesize information using the new outputSizeClass() method * - Added missing close() on FileInputStreams and FileOutputStreams * - Changed the F5 key press for refreshing the list of available robots * into 'modifier key' + R to comply with other OSes like e.g. Mac OS * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap *******************************************************************************/ package robocode.packager; import robocode.dialog.*; import robocode.io.Logger; import robocode.io.NoDuplicateJarOutputStream; import robocode.manager.IRepositoryManager; import robocode.peer.robot.RobotClassManager; import robocode.repository.FileSpecification; import robocode.repository.RobotFileSpecification; import robocode.repository.TeamSpecification; import robocode.security.RobocodeSecurityManager; import static robocode.ui.ShortcutUtil.MENU_SHORTCUT_KEY_MASK; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.io.*; import java.net.MalformedURLException; import java.net.URL; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.StringTokenizer; import java.util.jar.Attributes; import java.util.jar.JarEntry; import java.util.jar.Manifest; import java.util.zip.ZipException; /** * @author Mathew A. Nelson (original) * @author Matthew Reeder (contributor) * @author Flemming N. Larsen (contributor) * @author Robert D. Maupin (contributor) */ @SuppressWarnings("serial") public class RobotPackager extends JDialog implements WizardListener { private final int minRobots = 1; private final int maxRobots = 1; // 250; private JPanel robotPackagerContentPane; private WizardCardPanel wizardPanel; private WizardController buttonsPanel; private FilenamePanel filenamePanel; private ConfirmPanel confirmPanel; private RobotSelectionPanel robotSelectionPanel; private PackagerOptionsPanel packagerOptionsPanel; public final byte[] buf = new byte[4096]; private StringWriter output; private final IRepositoryManager repositoryManager; private final EventHandler eventHandler = new EventHandler(); private class EventHandler implements ActionListener { public void actionPerformed(ActionEvent e) { if (e.getActionCommand().equals("Refresh")) { getRobotSelectionPanel().refreshRobotList(true); } } } public RobotPackager(IRepositoryManager repositoryManager) { super(repositoryManager.getManager().getWindowManager().getRobocodeFrame()); this.repositoryManager = repositoryManager; initialize(); } public void cancelButtonActionPerformed() { dispose(); } public void copy(FileInputStream in, NoDuplicateJarOutputStream out) throws IOException { while (in.available() > 0) { int count = in.read(buf, 0, 4096); out.write(buf, 0, count); } } public void finishButtonActionPerformed() { String resultsString; int rc = packageRobots(); ConsoleDialog d = new ConsoleDialog(repositoryManager.getManager().getWindowManager().getRobocodeFrame(), "Packaging results", false); if (rc < 8) { outputSizeClass(); } if (rc == 0) { resultsString = "Robots Packaged Successfully.\n" + output.toString(); } else if (rc == 4) { resultsString = "Robots Packaged, but with warnings.\n" + output.toString(); } else if (rc == 8) { resultsString = "Robots Packaging failed.\n" + output.toString(); } else { resultsString = "FATAL: Unknown return code " + rc + " from packager.\n" + output.toString(); } d.setText(resultsString); d.pack(); d.pack(); WindowUtil.packCenterShow(this, d); if (rc < 8) { dispose(); } } /** * Return the buttonsPanel * * @return JButton */ private WizardController getButtonsPanel() { if (buttonsPanel == null) { buttonsPanel = getWizardPanel().getWizardController(); } return buttonsPanel; } public Set getClasses(RobotClassManager robotClassManager) throws ClassNotFoundException { robotClassManager.getRobotClassLoader().loadRobotClass(robotClassManager.getFullClassName(), true); return robotClassManager.getReferencedClasses(); } /** * Return the buttonsPanel * * @return JButton */ private ConfirmPanel getConfirmPanel() { if (confirmPanel == null) { confirmPanel = new ConfirmPanel(this); } return confirmPanel; } /** * Return the optionsPanel * * @return robocode.packager.PackagerOptionsPanel */ protected FilenamePanel getFilenamePanel() { if (filenamePanel == null) { filenamePanel = new FilenamePanel(this); } return filenamePanel; } /** * Return the optionsPanel * * @return robocode.packager.PackagerOptionsPanel */ protected PackagerOptionsPanel getPackagerOptionsPanel() { if (packagerOptionsPanel == null) { packagerOptionsPanel = new PackagerOptionsPanel(this); } return packagerOptionsPanel; } /** * Return the newBattleDialogContentPane * * @return JPanel */ private JPanel getRobotPackagerContentPane() { if (robotPackagerContentPane == null) { robotPackagerContentPane = new JPanel(); robotPackagerContentPane.setLayout(new BorderLayout()); robotPackagerContentPane.add(getButtonsPanel(), BorderLayout.SOUTH); robotPackagerContentPane.add(getWizardPanel(), BorderLayout.CENTER); getWizardPanel().getWizardController().setFinishButtonTextAndMnemonic("Package!", 'P', 0); robotPackagerContentPane.registerKeyboardAction(eventHandler, "Refresh", KeyStroke.getKeyStroke(KeyEvent.VK_R, MENU_SHORTCUT_KEY_MASK), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); robotPackagerContentPane.registerKeyboardAction(eventHandler, "Refresh", KeyStroke.getKeyStroke(KeyEvent.VK_R, MENU_SHORTCUT_KEY_MASK), JComponent.WHEN_FOCUSED); } return robotPackagerContentPane; } /** * Return the Page property value. * * @return JPanel */ public RobotSelectionPanel getRobotSelectionPanel() { if (robotSelectionPanel == null) { robotSelectionPanel = new RobotSelectionPanel(repositoryManager.getManager(), minRobots, maxRobots, false, "Select the robot or team you would like to package.", /* true */false, false, false/* true */, true, false, true, null); } return robotSelectionPanel; } /** * Return the tabbedPane. * * @return JTabbedPane */ private WizardCardPanel getWizardPanel() { if (wizardPanel == null) { wizardPanel = new WizardCardPanel(this); wizardPanel.add(getRobotSelectionPanel(), "Select robot"); wizardPanel.add(getPackagerOptionsPanel(), "Select options"); wizardPanel.add(getFilenamePanel(), "Select filename"); wizardPanel.add(getConfirmPanel(), "Confirm"); } return wizardPanel; } private void initialize() { setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); setTitle("Robot Packager"); setContentPane(getRobotPackagerContentPane()); } private int packageRobots() { repositoryManager.clearRobotList(); int rv = 0; output = new StringWriter(); PrintWriter out = new PrintWriter(output); out.println("Robot Packager"); List robotSpecificationsList = repositoryManager.getRobotRepository().getRobotSpecificationsList( false, false, false, false, false, false); String jarFilename = getFilenamePanel().getFilenameField().getText(); File f = new File(jarFilename); if (f.exists()) { int ok = JOptionPane.showConfirmDialog(this, jarFilename + " already exists. Are you sure you want to replace it?", "Warning", JOptionPane.YES_NO_CANCEL_OPTION); if (ok == JOptionPane.NO_OPTION || ok == JOptionPane.CANCEL_OPTION) { out.println("Cancelled by user."); return -1; } out.println("Overwriting " + jarFilename); } List selectedRobots = getRobotSelectionPanel().getSelectedRobots(); // Create the jar file Manifest manifest = new Manifest(); manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); StringBuilder robots = new StringBuilder(); for (int i = 0; i < selectedRobots.size(); i++) { robots.append(selectedRobots.get(i).getFullClassName()); if (i < selectedRobots.size() - 1) { robots.append(','); } } manifest.getMainAttributes().put(new Attributes.Name("robots"), robots.toString()); NoDuplicateJarOutputStream jarout; FileOutputStream fos = null; try { out.println("Creating Jar file: " + f.getName()); fos = new FileOutputStream(f); jarout = new NoDuplicateJarOutputStream(fos); jarout.setComment(repositoryManager.getManager().getVersionManager().getVersion() + " - Robocode version"); for (FileSpecification fileSpecification : selectedRobots) { if (fileSpecification instanceof RobotFileSpecification) { RobotFileSpecification robotFileSpecification = (RobotFileSpecification) fileSpecification; if (robotFileSpecification.isDevelopmentVersion()) { robotFileSpecification.setRobotDescription( getPackagerOptionsPanel().getDescriptionArea().getText()); robotFileSpecification.setRobotJavaSourceIncluded( getPackagerOptionsPanel().getIncludeSource().isSelected()); robotFileSpecification.setRobotAuthorName(getPackagerOptionsPanel().getAuthorField().getText()); URL u = null; String w = getPackagerOptionsPanel().getWebpageField().getText(); if (w.length() > 0) { try { u = new URL(w); } catch (MalformedURLException e) { try { u = new URL("http://" + w); getPackagerOptionsPanel().getWebpageField().setText(u.toString()); } catch (MalformedURLException ignored) {} } } robotFileSpecification.setRobotWebpage(u); robotFileSpecification.setRobocodeVersion( repositoryManager.getManager().getVersionManager().getVersion()); FileOutputStream fos2 = null; try { fos2 = new FileOutputStream(new File(robotFileSpecification.getThisFileName())); robotFileSpecification.store(fos2, "Robot Properties"); } catch (IOException e) { rv = 4; out.println("Unable to save properties: "); e.printStackTrace(out); out.println("Attempting to continue..."); } finally { if (fos2 != null) { try { fos2.close(); } catch (IOException ignored) {} } } // Create clone with version for jar try { robotFileSpecification = (RobotFileSpecification) robotFileSpecification.clone(); } catch (CloneNotSupportedException e) { out.println(e); return 8; } robotFileSpecification.setRobotVersion(getPackagerOptionsPanel().getVersionField().getText()); addRobotSpecification(out, jarout, robotFileSpecification); } else { out.println("You Cannot package a packaged robot!"); } } else if (fileSpecification instanceof TeamSpecification) { TeamSpecification teamSpecification = (TeamSpecification) fileSpecification; URL u = null; String w = getPackagerOptionsPanel().getWebpageField().getText(); if (w.length() > 0) { try { u = new URL(w); } catch (MalformedURLException e) { try { u = new URL("http://" + w); getPackagerOptionsPanel().getWebpageField().setText(u.toString()); } catch (MalformedURLException ignored) {} } } teamSpecification.setTeamWebpage(u); teamSpecification.setTeamDescription(getPackagerOptionsPanel().getDescriptionArea().getText()); teamSpecification.setTeamAuthorName(getPackagerOptionsPanel().getAuthorField().getText()); teamSpecification.setRobocodeVersion(repositoryManager.getManager().getVersionManager().getVersion()); FileOutputStream fos2 = null; try { fos2 = new FileOutputStream(new File(teamSpecification.getThisFileName())); teamSpecification.store(fos2, "Team Properties"); } catch (IOException e) { rv = 4; out.println("Unable to save .team file: " + e); out.println("Attempting to continue..."); } finally { if (fos2 != null) { try { fos2.close(); } catch (IOException ignored) {} } } try { teamSpecification = (TeamSpecification) teamSpecification.clone(); } catch (CloneNotSupportedException e) { out.println(e); return 8; } teamSpecification.setTeamVersion(getPackagerOptionsPanel().getVersionField().getText()); StringTokenizer teamTokenizer = new StringTokenizer(teamSpecification.getMembers(), ","); String bot; String newMembers = ""; while (teamTokenizer.hasMoreTokens()) { if (!(newMembers.length() == 0)) { newMembers += ","; } bot = teamTokenizer.nextToken(); for (FileSpecification currentFileSpecification : robotSpecificationsList) { // Teams cannot include teams if (currentFileSpecification instanceof TeamSpecification) { continue; } if (currentFileSpecification.getNameManager().getUniqueFullClassNameWithVersion().equals(bot)) { // Found team member RobotFileSpecification current = (RobotFileSpecification) currentFileSpecification; // Skip nonversioned packaged if (!current.isDevelopmentVersion() && (current.getVersion() == null || current.getVersion().length() == 0)) { continue; } if (current.isDevelopmentVersion() && (current.getVersion() == null || current.getVersion().length() == 0)) { try { current = (RobotFileSpecification) current.clone(); } catch (CloneNotSupportedException e) { out.println(e); return 8; } current.setRobotVersion( "[" + getPackagerOptionsPanel().getVersionField().getText() + "]"); } // Package this member newMembers += addRobotSpecification(out, jarout, current); break; } } } teamSpecification.setMembers(newMembers); try { try { JarEntry entry = new JarEntry( teamSpecification.getFullClassName().replace('.', '/') + ".team"); jarout.putNextEntry(entry); teamSpecification.store(jarout, "Robocode Robot Team"); jarout.closeEntry(); out.println("Added: " + entry); } catch (ZipException e) { if (e.getMessage().indexOf("duplicate entry") < 0) { throw e; } // ignore duplicate entry, fine, it's already there. } } catch (Throwable e) { rv = 8; out.println(e); } } } jarout.close(); } catch (IOException e) { out.println(e); return 8; } finally { if (fos != null) { try { fos.close(); } catch (IOException ignored) {} } } repositoryManager.clearRobotList(); out.println("Packaging complete."); return rv; } private final Object threadMonitor = new Object(); public void outputSizeClass() { // Codesize must be called within a safe thread to prevent security exception final RobocodeSecurityManager securityManager = (RobocodeSecurityManager) System.getSecurityManager(); Thread thread = new Thread() { @Override public void run() { File jarFile = new File(getFilenamePanel().getFilenameField().getText()); codesize.Codesize.Item item = codesize.Codesize.processZipFile(jarFile); int codesize = item.getCodeSize(); String weightClass; if (codesize >= 1500) { weightClass = "MegaBot (codesize >= 1500 bytes)"; } else if (codesize > 750) { weightClass = "MiniBot (codesize < 1500 bytes)"; } else if (codesize > 250) { weightClass = "MicroBot (codesize < 750 bytes)"; } else { weightClass = "NanoBot (codesize < 250 bytes)"; } StringBuffer out = output.getBuffer(); out.append("\n\n---- Codesize ----\n"); out.append("Codesize: ").append(codesize).append(" bytes\n"); out.append("Robot weight class: ").append(weightClass).append('\n'); synchronized (threadMonitor) { threadMonitor.notify(); } } }; securityManager.addSafeThread(thread); thread.start(); synchronized (threadMonitor) { try { threadMonitor.wait(); } catch (InterruptedException e) { // Immediately reasserts the exception by interrupting the caller thread itself Thread.currentThread().interrupt(); } } securityManager.removeSafeThread(thread); } public String addRobotSpecification(PrintWriter out, NoDuplicateJarOutputStream jarout, RobotFileSpecification robotFileSpecification) { int rv = 0; if (!robotFileSpecification.isDevelopmentVersion()) { try { File inputJar = robotFileSpecification.getJarFile(); FileInputStream input = null; try { JarEntry entry = new JarEntry(inputJar.getName()); jarout.putNextEntry(entry); input = new FileInputStream(inputJar); copy(input, jarout); jarout.closeEntry(); out.println("Added: " + entry); } catch (ZipException e) { if (e.getMessage().indexOf("duplicate entry") < 0) { throw e; } // ignore duplicate entry, fine, it's already there. } finally { if (input != null) { input.close(); } } } catch (Throwable e) { rv = 8; Logger.logError(e); out.println(e); } } else { addToJar(out, jarout, robotFileSpecification); } String name = robotFileSpecification.getName() + " " + robotFileSpecification.getVersion(); if (rv != 0) { return null; } return name; } public void addToJar(PrintWriter out, NoDuplicateJarOutputStream jarout, RobotFileSpecification robotFileSpecification) { RobotClassManager classManager = new RobotClassManager(robotFileSpecification); try { Iterator classes = getClasses(classManager).iterator(); String rootDirectory = classManager.getRobotClassLoader().getRootDirectory(); // Save props: try { JarEntry entry = new JarEntry(classManager.getFullClassName().replace('.', '/') + ".properties"); jarout.putNextEntry(entry); robotFileSpecification.store(jarout, "Robot Properties"); jarout.closeEntry(); out.println("Added: " + entry); } catch (ZipException e) { if (e.getMessage().indexOf("duplicate entry") < 0) { throw e; } // ignore duplicate entry, fine, it's already there. } File html = new File(rootDirectory, classManager.getFullClassName().replace('.', '/') + ".html"); if (html.exists()) { FileInputStream input = null; try { JarEntry entry = new JarEntry(classManager.getFullClassName().replace('.', '/') + ".html"); jarout.putNextEntry(entry); input = new FileInputStream(html); copy(input, jarout); jarout.closeEntry(); out.println("Added: " + entry); } catch (ZipException e) { if (e.getMessage().indexOf("duplicate entry") < 0) { throw e; } // ignore duplicate entry, fine, it's already there. } finally { if (input != null) { input.close(); } } } while (classes.hasNext()) { String className = classes.next(); // Add source file if selected (not inner classes of course) if (getPackagerOptionsPanel().getIncludeSource().isSelected()) { if (className.indexOf("$") < 0) { File javaFile = new File(rootDirectory, className.replace('.', File.separatorChar) + ".java"); if (javaFile.exists()) { try { JarEntry entry = new JarEntry(className.replace('.', '/') + ".java"); jarout.putNextEntry(entry); FileInputStream input = new FileInputStream(javaFile); copy(input, jarout); jarout.closeEntry(); out.println("Added: " + entry); } catch (ZipException e) { if (e.getMessage().indexOf("duplicate entry") < 0) { throw e; } // ignore duplicate entry, fine, it's already there. } } else { out.println(className.replace('.', '/') + ".java does not exist."); } } } // Add class file FileInputStream input = null; try { JarEntry entry = new JarEntry(className.replace('.', '/') + ".class"); jarout.putNextEntry(entry); input = new FileInputStream( new File(rootDirectory, className.replace('.', File.separatorChar) + ".class")); copy(input, jarout); jarout.closeEntry(); out.println("Added: " + entry); } catch (ZipException e) { if (e.getMessage().indexOf("duplicate entry") < 0) { throw e; } // ignore duplicate entry, fine, it's already there. } finally { if (input != null) { input.close(); } } } File dataDirectory = new File(rootDirectory, classManager.getFullClassName().replace('.', '/') + ".data"); if (dataDirectory.exists()) { File files[] = dataDirectory.listFiles(); for (File file : files) { FileInputStream input = null; try { JarEntry entry = new JarEntry( classManager.getFullClassName().replace('.', '/') + ".data/" + file.getName()); jarout.putNextEntry(entry); input = new FileInputStream(file); copy(input, jarout); jarout.closeEntry(); out.println("Added: " + entry); } catch (ZipException e) { if (e.getMessage().indexOf("duplicate entry") < 0) { throw e; } // ignore duplicate entry, fine, it's already there. } finally { if (input != null) { input.close(); } } } } } catch (Throwable e) { out.println(e); } } } robocode/robocode/robocode/packager/FilenamePanel.java0000644000175000017500000001766511130241112022355 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup * - Replaced FileSpecificationVector with plain Vector * - Replaced deprecated show() method with setVisible(true) * - Updated to use methods from the FileUtil, which replaces file operations * that have been (re)moved from the robocode.util.Utils class * - Changed to use FileUtil.getRobotsDir() * - Fixed the layout, where the filename field was too high * - Showing the frame is now performed in the Swing Event Thread * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap *******************************************************************************/ package robocode.packager; import robocode.dialog.WizardPanel; import robocode.io.FileUtil; import robocode.repository.FileSpecification; import javax.swing.*; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.text.Caret; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.util.List; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Robert D. Maupin (contributor) */ @SuppressWarnings("serial") public class FilenamePanel extends WizardPanel { private final RobotPackager robotPackager; private final EventHandler eventHandler = new EventHandler(); private boolean robocodeErrorShown; private JButton browseButton; private JTextField filenameField; private class EventHandler implements ActionListener, DocumentListener, ComponentListener { public void insertUpdate(DocumentEvent e) { fireStateChanged(); } public void changedUpdate(DocumentEvent e) { fireStateChanged(); } public void removeUpdate(DocumentEvent e) { fireStateChanged(); } public void actionPerformed(ActionEvent e) { if (e.getSource() == getBrowseButton()) { showFileSelectDialog(); } } public void componentMoved(ComponentEvent e) {} public void componentResized(ComponentEvent e) {} public void componentHidden(ComponentEvent e) {} public void componentShown(ComponentEvent e) { String fileName = FileUtil.getRobotsDir().getAbsolutePath() + File.separator; File outgoingFile = new File(fileName); if (!outgoingFile.exists()) { outgoingFile.mkdirs(); } String jarName = "myrobots.jar"; List selectedRobots = robotPackager.getRobotSelectionPanel().getSelectedRobots(); if (selectedRobots != null && selectedRobots.size() == 1) { jarName = selectedRobots.get(0).getFullClassName() + "_" + robotPackager.getPackagerOptionsPanel().getVersionField().getText() + ".jar"; } getFilenameField().setText(fileName + jarName); Caret caret = getFilenameField().getCaret(); caret.setDot(fileName.length()); caret.moveDot(fileName.length() + jarName.length() - 4); getFilenameField().requestFocus(); } } public FilenamePanel(RobotPackager robotPackager) { super(); this.robotPackager = robotPackager; initialize(); } private void initialize() { setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); addComponentListener(eventHandler); GridBagLayout layout = new GridBagLayout(); setLayout(layout); GridBagConstraints c = new GridBagConstraints(); c.insets = new Insets(5, 5, 5, 5); c.anchor = GridBagConstraints.NORTHWEST; c.fill = GridBagConstraints.HORIZONTAL; c.gridwidth = 1; c.weightx = 1; add(new JLabel("Please type in a .jar file to save this robot package to: "), c); c.gridy = 1; add(getFilenameField(), c); c.fill = GridBagConstraints.NONE; c.gridy = 2; c.insets = new Insets(3, 3, 3, 3); add(getBrowseButton(), c); c.fill = GridBagConstraints.VERTICAL; c.weighty = 1; c.gridy = 3; add(new JPanel(), c); } @Override public boolean isReady() { if (filenameField.getText() == null) { return false; } int robocodeIndex = filenameField.getText().lastIndexOf(File.separatorChar); if (robocodeIndex > 0) { if (filenameField.getText().substring(robocodeIndex + 1).indexOf("robocode") == 0) { if (!robocodeErrorShown) { robocodeErrorShown = true; new Thread(new Runnable() { public void run() { JOptionPane.showMessageDialog(FilenamePanel.this, "Filename cannot begin with robocode"); } }).start(); } return false; } } return (filenameField.getText().toLowerCase().indexOf(".jar") != 0); } public static void main(String[] args) { JFrame frame = new JFrame("options"); frame.setSize(new Dimension(500, 300)); frame.getContentPane().add(new FilenamePanel(null)); try { SwingUtilities.invokeAndWait(new ShowFrameWorker(frame)); } catch (InterruptedException e) { // Immediately reasserts the exception by interrupting the caller thread itself Thread.currentThread().interrupt(); e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } public JButton getBrowseButton() { if (browseButton == null) { browseButton = new JButton("Browse"); browseButton.addActionListener(eventHandler); } return browseButton; } public JTextField getFilenameField() { if (filenameField == null) { filenameField = new JTextField("(none selected)", 60); filenameField.getDocument().addDocumentListener(eventHandler); } return filenameField; } public void showFileSelectDialog() { File f = new File("outgoing" + File.separatorChar); JFileChooser chooser = new JFileChooser(f); chooser.setCurrentDirectory(f); javax.swing.filechooser.FileFilter filter = new javax.swing.filechooser.FileFilter() { @Override public boolean accept(File pathname) { if (pathname.isDirectory()) { return true; } String fn = pathname.getName(); int idx = fn.lastIndexOf('.'); String extension = ""; if (idx >= 0) { extension = fn.substring(idx); } return extension.equalsIgnoreCase(".jar"); } @Override public String getDescription() { return "JAR files"; } }; chooser.setFileFilter(filter); boolean done = false; while (!done) { done = true; int rv = chooser.showSaveDialog(this); String robotFileName; if (rv == JFileChooser.APPROVE_OPTION) { robotFileName = chooser.getSelectedFile().getPath(); if (robotFileName.toLowerCase().indexOf(".jar") < 0) { robotFileName += ".jar"; } File outFile = new File(robotFileName); if (outFile.exists()) { int ok = JOptionPane.showConfirmDialog(this, robotFileName + " already exists. Are you sure you want to replace it?", "Warning", JOptionPane.YES_NO_CANCEL_OPTION); if (ok == JOptionPane.NO_OPTION) { done = false; continue; } if (ok == JOptionPane.CANCEL_OPTION) { return; } } getFilenameField().setText(robotFileName); fireStateChanged(); } } } static class ShowFrameWorker implements Runnable { final JFrame frame; public ShowFrameWorker(JFrame frame) { this.frame = frame; } public void run() { if (frame != null) { frame.setVisible(true); } } } } robocode/robocode/robocode/packager/PackagerOptionsPanel.java0000644000175000017500000003024611130241112023714 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup * - Replaced FileSpecificationVector with plain Vector * - Replaced deprecated show() method with setVisible(true) * - Showing the frame is now performed in the Swing Event Thread * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap *******************************************************************************/ package robocode.packager; import robocode.dialog.WizardPanel; import robocode.repository.FileSpecification; import robocode.text.LimitedDocument; import javax.swing.*; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import java.awt.*; import java.awt.event.*; import java.lang.reflect.InvocationTargetException; import java.net.URL; import java.util.List; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Robert D. Maupin (contributor) */ @SuppressWarnings("serial") public class PackagerOptionsPanel extends WizardPanel { private final RobotPackager robotPackager; private JCheckBox includeSource; private final EventHandler eventHandler = new EventHandler(); private JLabel authorLabel; private JTextField authorField; private JLabel descriptionLabel; private JTextArea descriptionArea; private JLabel versionLabel; private JTextField versionField; private JLabel versionHelpLabel; private JLabel webpageLabel; private JTextField webpageField; private JLabel webpageHelpLabel; private class EventHandler implements ComponentListener, KeyListener, DocumentListener { public void insertUpdate(DocumentEvent e) { fireStateChanged(); } public void changedUpdate(DocumentEvent e) { fireStateChanged(); } public void removeUpdate(DocumentEvent e) { fireStateChanged(); } public void componentMoved(ComponentEvent e) {} public void componentHidden(ComponentEvent e) {} public void componentShown(ComponentEvent e) { List selectedRobots = robotPackager.getRobotSelectionPanel().getSelectedRobots(); if (selectedRobots != null) { if (selectedRobots.size() == 1) { FileSpecification fileSpecification = selectedRobots.get(0); String v = fileSpecification.getVersion(); if (v == null || v.length() == 0) { getVersionHelpLabel().setVisible(false); v = "1.0"; } else { if (v.length() == 10) { v = v.substring(0, 9); } v += "*"; getVersionHelpLabel().setVisible(true); } getVersionField().setText(v); String d = fileSpecification.getDescription(); if (d == null) { d = ""; } getDescriptionArea().setText(d); String a = fileSpecification.getAuthorName(); if (a == null) { a = ""; } getAuthorField().setText(a); URL u = fileSpecification.getWebpage(); if (u == null) { getWebpageField().setText(""); } else { getWebpageField().setText(u.toString()); } String filepath = fileSpecification.getFilePath(); String text = ""; if (filepath != null && filepath.indexOf(".") != -1) { String htmlfn = filepath.substring(0, filepath.lastIndexOf(".")) + ".html"; text = "(You may also leave this blank, and simply create the file: " + htmlfn + ")"; } getWebpageHelpLabel().setText(text); getVersionLabel().setVisible(true); getVersionField().setVisible(true); getAuthorLabel().setVisible(true); getAuthorField().setVisible(true); getWebpageLabel().setVisible(true); getWebpageField().setVisible(true); getWebpageHelpLabel().setVisible(true); getDescriptionLabel().setText( "Please enter a short description of your robot (up to 3 lines of 72 chars each)."); } else if (selectedRobots.size() > 1) { getVersionLabel().setVisible(false); getVersionField().setVisible(false); getVersionHelpLabel().setVisible(false); getAuthorLabel().setVisible(false); getAuthorField().setVisible(false); getWebpageLabel().setVisible(false); getWebpageField().setVisible(false); getWebpageHelpLabel().setVisible(false); getDescriptionLabel().setText( "Please enter a short description of this robot collection (up to 3 lines of 72 chars each)."); if (getDescriptionArea().getText() == null || getDescriptionArea().getText().length() == 0) { getDescriptionArea().setText("(Example)This robot comes from the ... robot collection\n"); } } } } public void componentResized(ComponentEvent e) {} public void keyPressed(KeyEvent e) {} public void keyReleased(KeyEvent e) {} public void keyTyped(KeyEvent e) {} } public JPanel robotListPanel; public PackagerOptionsPanel(RobotPackager robotPackager) { super(); this.robotPackager = robotPackager; initialize(); } public JCheckBox getIncludeSource() { if (includeSource == null) { includeSource = new JCheckBox("Include source", true); } return includeSource; } private void initialize() { setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); JLabel label = new JLabel("It is up to you whether or not to include the source when you distribute your robot."); label.setAlignmentX(Component.LEFT_ALIGNMENT); add(label); label = new JLabel( "If you include the source, other people will be able to look at your code and learn from it."); label.setAlignmentX(Component.LEFT_ALIGNMENT); add(label); getIncludeSource().setAlignmentX(Component.LEFT_ALIGNMENT); add(getIncludeSource()); label = new JLabel(" "); label.setAlignmentX(Component.LEFT_ALIGNMENT); add(label); add(getVersionLabel()); JPanel p = new JPanel(); p.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); p.setAlignmentX(Component.LEFT_ALIGNMENT); getVersionField().setAlignmentX(Component.LEFT_ALIGNMENT); getVersionField().setMaximumSize(getVersionField().getPreferredSize()); p.setMaximumSize(new Dimension(Integer.MAX_VALUE, getVersionField().getPreferredSize().height)); p.add(getVersionField()); p.add(getVersionHelpLabel()); add(p); label = new JLabel(" "); label.setAlignmentX(Component.LEFT_ALIGNMENT); add(label); add(getDescriptionLabel()); JScrollPane scrollPane = new JScrollPane(getDescriptionArea(), ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); scrollPane.setMaximumSize(scrollPane.getPreferredSize()); scrollPane.setMinimumSize(new Dimension(100, scrollPane.getPreferredSize().height)); scrollPane.setAlignmentX(Component.LEFT_ALIGNMENT); add(scrollPane); label = new JLabel(" "); label.setAlignmentX(Component.LEFT_ALIGNMENT); add(label); add(getAuthorLabel()); getAuthorField().setAlignmentX(Component.LEFT_ALIGNMENT); getAuthorField().setMaximumSize(getAuthorField().getPreferredSize()); add(getAuthorField()); label = new JLabel(" "); label.setAlignmentX(Component.LEFT_ALIGNMENT); add(label); add(getWebpageLabel()); getWebpageField().setAlignmentX(Component.LEFT_ALIGNMENT); getWebpageField().setMaximumSize(getWebpageField().getPreferredSize()); add(getWebpageField()); getWebpageHelpLabel().setAlignmentX(Component.LEFT_ALIGNMENT); add(getWebpageHelpLabel()); JPanel panel = new JPanel(); panel.setAlignmentX(Component.LEFT_ALIGNMENT); add(panel); addComponentListener(eventHandler); } @Override public boolean isReady() { if (getVersionLabel().isVisible()) { if (getVersionField().getText().length() == 0) { return false; } if (getVersionField().getText().indexOf(",") >= 0) { return false; } if (getVersionField().getText().indexOf(" ") >= 0) { return false; } if (getVersionField().getText().indexOf("*") >= 0) { return false; } if (getVersionField().getText().indexOf("(") >= 0) { return false; } if (getVersionField().getText().indexOf(")") >= 0) { return false; } if (getVersionField().getText().indexOf("[") >= 0) { return false; } if (getVersionField().getText().indexOf("]") >= 0) { return false; } if (getVersionField().getText().indexOf("{") >= 0) { return false; } if (getVersionField().getText().indexOf("}") >= 0) { return false; } } return getDescriptionArea().getText().length() != 0; } public static void main(String[] args) { JFrame frame = new JFrame("options"); frame.setSize(new Dimension(500, 300)); frame.getContentPane().add(new PackagerOptionsPanel(null)); frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { e.getWindow().dispose(); } @Override public void windowClosed(WindowEvent e) { System.exit(0); } }); try { SwingUtilities.invokeAndWait(new PackAndShowFrameWorker(frame)); } catch (InterruptedException e) { // Immediately reasserts the exception by interrupting the caller thread itself Thread.currentThread().interrupt(); e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } private JLabel getAuthorLabel() { if (authorLabel == null) { authorLabel = new JLabel("Please enter your name. (optional)"); authorLabel.setAlignmentX(Component.LEFT_ALIGNMENT); } return authorLabel; } public JTextField getAuthorField() { if (authorField == null) { authorField = new JTextField(40); } return authorField; } public JLabel getDescriptionLabel() { if (descriptionLabel == null) { descriptionLabel = new JLabel(""); descriptionLabel.setAlignmentX(Component.LEFT_ALIGNMENT); } return descriptionLabel; } public JTextArea getDescriptionArea() { if (descriptionArea == null) { LimitedDocument doc = new LimitedDocument(3, 72); descriptionArea = new JTextArea(doc, null, 3, 72); doc.addDocumentListener(eventHandler); } return descriptionArea; } private JLabel getVersionLabel() { if (versionLabel == null) { versionLabel = new JLabel( "Please enter a version number for this robot (up to 10 chars, no spaces,commas,asterisks, or brackets)."); versionLabel.setAlignmentX(Component.LEFT_ALIGNMENT); } return versionLabel; } public JTextField getVersionField() { if (versionField == null) { LimitedDocument doc = new LimitedDocument(1, 10); versionField = new JTextField(doc, null, 10); doc.addDocumentListener(eventHandler); } return versionField; } public JLabel getVersionHelpLabel() { if (versionHelpLabel == null) { versionHelpLabel = new JLabel("<-- Make sure to delete the asterisk and type in a new version number"); } return versionHelpLabel; } public JLabel getWebpageLabel() { if (webpageLabel == null) { webpageLabel = new JLabel("Please enter a URL for your robot's webpage. (optional)"); webpageLabel.setAlignmentX(Component.LEFT_ALIGNMENT); } return webpageLabel; } public JTextField getWebpageField() { if (webpageField == null) { webpageField = new JTextField(40); } return webpageField; } public JLabel getWebpageHelpLabel() { if (webpageHelpLabel == null) { webpageHelpLabel = new JLabel(""); } return webpageHelpLabel; } static class PackAndShowFrameWorker implements Runnable { final JFrame frame; public PackAndShowFrameWorker(JFrame frame) { this.frame = frame; } public void run() { if (frame != null) { frame.pack(); frame.setVisible(true); } } } } robocode/robocode/robocode/packager/ConfirmPanel.java0000644000175000017500000001034111130241112022212 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Replaced FileSpecificationVector with plain Vector * - Code cleanup * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap *******************************************************************************/ package robocode.packager; import robocode.dialog.WizardPanel; import robocode.repository.FileSpecification; import javax.swing.*; import java.awt.*; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.util.List; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Robert D. Maupin (contributor) */ @SuppressWarnings("serial") public class ConfirmPanel extends WizardPanel { private final RobotPackager robotPackager; private final EventHandler eventHandler = new EventHandler(); private boolean visible; private JPanel robotListPanel; private class EventHandler implements ComponentListener { public void componentMoved(ComponentEvent e) {} public void componentResized(ComponentEvent e) {} public void componentHidden(ComponentEvent e) { visible = false; fireStateChanged(); } public void componentShown(ComponentEvent e) { // logError("confirm panel shown."); if (robotPackager == null) { return; } visible = true; updateFields(); fireStateChanged(); repaint(); } } public ConfirmPanel(RobotPackager robotPackager) { super(); this.robotPackager = robotPackager; initialize(); } public JPanel getRobotListPanel() { if (robotListPanel == null) { robotListPanel = new JPanel(); robotListPanel.setLayout(new BoxLayout(robotListPanel, BoxLayout.Y_AXIS)); robotListPanel.setAlignmentX(Component.LEFT_ALIGNMENT); } return robotListPanel; } private void initialize() { setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); addComponentListener(eventHandler); add(new JPanel()); } @Override public boolean isReady() { return visible; } public void setSelectedRobots(List selectedRobots) { getRobotListPanel().removeAll(); if (selectedRobots == null || selectedRobots.size() == 0) { getRobotListPanel().add(new JLabel("You have not yet selected any robots.")); } else if (selectedRobots.size() == 1) { String robotName = (selectedRobots.get(0)).getFullClassName(); getRobotListPanel().add(new JLabel("You have selected " + robotName + " for packaging.")); } else { getRobotListPanel().add(new JLabel("You have selected the following robots for packaging:")); for (FileSpecification selected : selectedRobots) { getRobotListPanel().add(new JLabel(selected.getFullClassName())); } } getRobotListPanel().add(new JLabel("")); getRobotListPanel().setMaximumSize(new Dimension(10000, robotListPanel.getPreferredSize().height)); validate(); } public void updateFields() { removeAll(); setSelectedRobots(robotPackager.getRobotSelectionPanel().getSelectedRobots()); add(getRobotListPanel()); add(Box.createVerticalStrut(20)); if (robotPackager.getPackagerOptionsPanel().getIncludeSource().isSelected()) { add(new JLabel("Java source files will be included.")); } else { add(new JLabel("Only .class files will be included.")); } add(Box.createVerticalStrut(20)); add(new JLabel("The package will be saved in " + robotPackager.getFilenamePanel().getFilenameField().getText())); add(Box.createVerticalStrut(20)); add(new JLabel("If all of the above is correct, click the Package button to start packaging.")); add(new JPanel()); revalidate(); } } robocode/robocode/robocode/packager/ClassAnalyzer.java0000644000175000017500000001474511130241112022424 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Updated to use methods from the Logger, which replaces logger methods * that have been (re)moved from the robocode.util.Utils class * - Code cleanup * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap *******************************************************************************/ package robocode.packager; import robocode.io.Logger; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Robert D. Maupin (contributor) */ public class ClassAnalyzer { private final static byte CONSTANT_Class = 7; private final static byte CONSTANT_Fieldref = 9; private final static byte CONSTANT_Methodref = 10; private final static byte CONSTANT_InterfaceMethodref = 11; private final static byte CONSTANT_String = 8; private final static byte CONSTANT_Integer = 3; private final static byte CONSTANT_Float = 4; private final static byte CONSTANT_Long = 5; private final static byte CONSTANT_Double = 6; private final static byte CONSTANT_NameAndType = 12; private final static byte CONSTANT_Utf8 = 1; /** * ClassAnalyzer constructor comment. */ public ClassAnalyzer() { super(); } public static List getReferencedClasses(byte[] classFile) { /* http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html 4.1 The ClassFile Structure A class file consists of a single ClassFile structure: ClassFile { u4 magic; u2 minor_version; u2 major_version; u2 constant_pool_count; cp_info constant_pool[constant_pool_count-1]; u2 access_flags; u2 this_class; u2 super_class; u2 interfaces_count; u2 interfaces[interfaces_count]; u2 fields_count; field_info fields[fields_count]; u2 methods_count; method_info methods[methods_count]; u2 attributes_count; attribute_info attributes[attributes_count]; } */ List referencedClasses = new ArrayList(); String strings[]; List classNameIndexes = new ArrayList(); try { DataInputStream in = new DataInputStream(new ByteArrayInputStream(classFile)); long magic = in.readInt(); if (magic != 0xCAFEBABE) { Logger.logError("Not a class file!"); return null; } in.readUnsignedShort(); // minor version in.readUnsignedShort(); // major version int constant_pool_count = in.readUnsignedShort(); strings = new String[constant_pool_count]; /* All constant_pool table entries have the following general format: cp_info { u1 tag; u1 info[]; } Constant Type Value CONSTANT_Class 7 CONSTANT_Fieldref 9 CONSTANT_Methodref 10 CONSTANT_InterfaceMethodref 11 CONSTANT_String 8 CONSTANT_Integer 3 CONSTANT_Float 4 CONSTANT_Long 5 CONSTANT_Double 6 CONSTANT_NameAndType 12 CONSTANT_Utf8 1 */ for (int i = 1; i < constant_pool_count; i++) { byte tag = in.readByte(); switch (tag) { /* CONSTANT_Class_info { u1 tag; u2 name_index; } */ case CONSTANT_Class: { int name_index = in.readUnsignedShort(); classNameIndexes.add(name_index); } break; /* CONSTANT_Fieldref_info { u1 tag; u2 class_index; u2 name_and_type_index; } CONSTANT_Methodref_info { u1 tag; u2 class_index; u2 name_and_type_index; } CONSTANT_InterfaceMethodref_info { u1 tag; u2 class_index; u2 name_and_type_index; } */ case CONSTANT_Fieldref: case CONSTANT_Methodref: case CONSTANT_InterfaceMethodref: { in.readUnsignedShort(); // class index in.readUnsignedShort(); // name and type index } break; /* CONSTANT_String_info { u1 tag; u2 string_index; } */ case CONSTANT_String: { in.readUnsignedShort(); // string index } break; /* CONSTANT_Integer_info { u1 tag; u4 bytes; } CONSTANT_Float_info { u1 tag; u4 bytes; } */ case CONSTANT_Integer: case CONSTANT_Float: { in.readInt(); // bytes } break; /* CONSTANT_Long_info { u1 tag; u4 high_bytes; u4 low_bytes; } CONSTANT_Double_info { u1 tag; u4 high_bytes; u4 low_bytes; } All 8-byte constants take up two entries in the constant_pool table of the class file. If a CONSTANT_Long_info or CONSTANT_Double_info structure is the item in the constant_pool table at index n, then the next usable item in the pool is located at index n+2. The constant_pool index n+1 must be valid but is considered unusable.2 */ case CONSTANT_Long: case CONSTANT_Double: { in.readInt(); // high bytes in.readInt(); // low bytes i++; // see "all 8-byte..." comment above. } break; /* CONSTANT_NameAndType_info { u1 tag; u2 name_index; u2 descriptor_index; } */ case CONSTANT_NameAndType: { in.readUnsignedShort(); // name index in.readUnsignedShort(); // descriptor index } break; /* CONSTANT_Utf8_info { u1 tag; u2 length; u1 bytes[length]; } */ case CONSTANT_Utf8: { String utf8_string = in.readUTF(); strings[i] = utf8_string; } break; } // switch } // for i } catch (IOException e) { return null; } for (Integer classNameIndex : classNameIndexes) { String className = strings[classNameIndex]; if (className.indexOf("[") != 0) { referencedClasses.add(className); } } return referencedClasses; } } robocode/robocode/robocode/_AdvancedRadiansRobot.java0000644000175000017500000001112211130241112022232 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Minor cleanup * - Updated Javadocs * - The uninitializedException() method does not need a method name as input * parameter anymore * Pavel Savara * - Re-work of robot interfaces *******************************************************************************/ package robocode; import robocode.robotinterfaces.peer.IAdvancedRobotPeer; /** * This class is used by the system as a placeholder for all *Radians calls in * {@link AdvancedRobot}. You may refer to this class for documentation only. *

* You should create a {@link AdvancedRobot} instead. *

* There is no guarantee that this class will exist in future versions of Robocode. *

* (The Radians methods themselves will continue work, however). * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Pavel Savara (contributor) * @see AdvancedRobot */ public class _AdvancedRadiansRobot extends _AdvancedRobot { _AdvancedRadiansRobot() {} public double getHeadingRadians() { if (peer != null) { return peer.getBodyHeading(); } uninitializedException(); return 0; // never called } public void setTurnLeftRadians(double radians) { if (peer != null) { ((IAdvancedRobotPeer) peer).setTurnBody(-radians); } else { uninitializedException(); } } public void setTurnRightRadians(double radians) { if (peer != null) { ((IAdvancedRobotPeer) peer).setTurnBody(radians); } else { uninitializedException(); } } public void turnLeftRadians(double radians) { if (peer != null) { peer.turnBody(-radians); } else { uninitializedException(); } } public void turnRightRadians(double radians) { if (peer != null) { peer.turnBody(radians); } else { uninitializedException(); } } public double getGunHeadingRadians() { if (peer != null) { return peer.getGunHeading(); } uninitializedException(); return 0; // never called } public double getRadarHeadingRadians() { if (peer != null) { return peer.getRadarHeading(); } uninitializedException(); return 0; // never called } public void setTurnGunLeftRadians(double radians) { if (peer != null) { ((IAdvancedRobotPeer) peer).setTurnGun(-radians); } else { uninitializedException(); } } public void setTurnGunRightRadians(double radians) { if (peer != null) { ((IAdvancedRobotPeer) peer).setTurnGun(radians); } else { uninitializedException(); } } public void setTurnRadarLeftRadians(double radians) { if (peer != null) { ((IAdvancedRobotPeer) peer).setTurnRadar(-radians); } else { uninitializedException(); } } public void setTurnRadarRightRadians(double radians) { if (peer != null) { ((IAdvancedRobotPeer) peer).setTurnRadar(radians); } else { uninitializedException(); } } public void turnGunLeftRadians(double radians) { if (peer != null) { peer.turnGun(-radians); } else { uninitializedException(); } } public void turnGunRightRadians(double radians) { if (peer != null) { peer.turnGun(radians); } else { uninitializedException(); } } public void turnRadarLeftRadians(double radians) { if (peer != null) { ((IAdvancedRobotPeer) peer).turnRadar(-radians); } else { uninitializedException(); } } public void turnRadarRightRadians(double radians) { if (peer != null) { ((IAdvancedRobotPeer) peer).turnRadar(radians); } else { uninitializedException(); } } public double getGunTurnRemainingRadians() { if (peer != null) { return peer.getGunTurnRemaining(); } uninitializedException(); return 0; // never called } public double getRadarTurnRemainingRadians() { if (peer != null) { return peer.getRadarTurnRemaining(); } uninitializedException(); return 0; // never called } public double getTurnRemainingRadians() { if (peer != null) { return peer.getBodyTurnRemaining(); } uninitializedException(); return 0; // never called } } robocode/robocode/robocode/WinEvent.java0000644000175000017500000000347411130241112017630 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Updated Javadocs *******************************************************************************/ package robocode; import robocode.peer.RobotStatics; import robocode.robotinterfaces.IBasicEvents; import robocode.robotinterfaces.IBasicRobot; import java.awt.*; /** * This event is sent to {@link Robot#onWin(WinEvent) onWin()} when your robot * wins the round in a battle. * * @author Mathew A. Nelson (original) */ public final class WinEvent extends Event { private static final long serialVersionUID = 1L; private final static int DEFAULT_PRIORITY = 100; // System event -> cannot be changed!; /** * Called by the game to create a new WinEvent. */ public WinEvent() { super(); } /** * {@inheritDoc} */ @Override public final int getPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override final int getDefaultPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override final void dispatch(IBasicRobot robot, RobotStatics statics, Graphics2D graphics) { IBasicEvents listener = robot.getBasicEventListener(); if (listener != null) { listener.onWin(this); } } /** * {@inheritDoc} */ @Override final boolean isCriticalEvent() { return true; } } robocode/robocode/robocode/control/0000755000175000017500000000000011124141576016716 5ustar lambylambyrobocode/robocode/robocode/control/BattlefieldSpecification.java0000644000175000017500000000473411130241114024473 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - This class now implements java.io.Serializable * - Updated Javadocs *******************************************************************************/ package robocode.control; /** * Defines the size of a battlefield, which is a part of the * {@link BattleSpecification}. * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @see BattleSpecification#BattleSpecification(int, BattlefieldSpecification, RobotSpecification[]) * @see BattleSpecification#BattleSpecification(int, long, double, BattlefieldSpecification, RobotSpecification[]) * @see BattleSpecification#getBattlefield() */ public class BattlefieldSpecification implements java.io.Serializable { private static final long serialVersionUID = 1L; private int width; private int height; /** * Creates a standard 800 x 600 battlefield. */ public BattlefieldSpecification() { this(800, 600); } /** * Creates a battlefield of the specified width and height. * * @param width the width of the battlefield, where 400 >= width < 5000. * @param height the height of the battlefield, where 400 >= height < 5000. * @throws IllegalArgumentException if the width or height is less than 400 * or greater than 5000 */ public BattlefieldSpecification(int width, int height) { if (width < 400 || width > 5000) { throw new IllegalArgumentException("width must be: 400 >= width < 5000"); } if (height < 400 || height > 5000) { throw new IllegalArgumentException("height must be: 400 >= height < 5000"); } this.width = width; this.height = height; } /** * Returns the width of this battlefield. * * @return the width of this battlefield. */ public int getWidth() { return width; } /** * Returns the height of this battlefield. * * @return the height of this battlefield. */ public int getHeight() { return height; } } robocode/robocode/robocode/control/snapshot/0000755000175000017500000000000011124141546020552 5ustar lambylambyrobocode/robocode/robocode/control/snapshot/IBulletSnapshot.java0000644000175000017500000000460111130241114024463 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.control.snapshot; import robocode.control.snapshot.BulletState; /** * Interface of a bullet snapshot. * * @author Pavel Savara (original) * @author Flemming N. Larsen (contributor) * * @since 1.6.2 */ public interface IBulletSnapshot { /** * Returns the bullet state. * * @return the bullet state. */ BulletState getState(); /** * Returns the bullet power. * * @return the bullet power. */ double getPower(); /** * Returns the x coordinate of the bullet. * * @return the x coordinate of the bullet. */ double getX(); /** * Returns the y coordinate of the bullet. * * @return the y coordinate of the bullet. */ double getY(); /** * Returns the x coordinate where to paint the bullet. * * @return the x coordinate where to paint the bullet. */ double getPaintX(); /** * Returns the y coordinate where to paint the bullet. * * @return the y coordinate where to paint the bullet. */ double getPaintY(); /** * Returns the color of the bullet. * * @return a RGBA color value. (Bits 24-31 are alpha, 16-23 are red, 8-15 are green, 0-7 are blue) * * @see java.awt.Color#getRGB() */ int getColor(); /** * Returns the frame number to display. * * @return the frame number to display. */ int getFrame(); /** * Returns the flag specifying if this bullet has turned into an explosion. * * @return {@code true} if this bullet has turned into an explosion; * {@code false} otherwise */ boolean isExplosion(); /** * Returns the index to which explosion image that must be rendered. * * @return the index to which explosion image that must be rendered. */ int getExplosionImageIndex(); } robocode/robocode/robocode/control/snapshot/RobotState.java0000644000175000017500000000613111130241114023471 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen * - Initial implementation *******************************************************************************/ package robocode.control.snapshot; /** * Defines a robot state, where the robot can be: active on the battlefield, hitting a wall or robot this second, * or dead. * * @author Flemming N. Larsen (original) * @since 1.6.2 */ public enum RobotState { /** The robot is active on the battlefield and has not hit the wall or a robot at this time. */ ACTIVE(0), /** The robot has hit a wall, i.e. one of the four borders, at this time. This state only last one turn. */ HIT_WALL(1), /** The robot has hit another robot at this time. This state only last one turn. */ HIT_ROBOT(2), /** The robot is dead. */ DEAD(3); private final int value; private RobotState(int value) { this.value = value; } /** * Returns the state as an integer value. * * @return an integer value representing this state. * * @see #toState(int) */ public int getValue() { return value; } /** * Returns a RobotState based on an integer value that represents a RobotState. * * @param value the integer value that represents a specific RobotState. * @return a RobotState that corresponds to the specific integer value. * * @see #getValue() * * @throws IllegalArgumentException if the specified value does not correspond * to a RobotState and hence is invalid. */ public static RobotState toState(int value) { switch (value) { case 0: return ACTIVE; case 1: return HIT_WALL; case 2: return HIT_ROBOT; case 3: return DEAD; default: throw new IllegalArgumentException("unknown value"); } } /** * Checks if the robot is alive. * * @return {@code true} if the robot is alive; {@code false} otherwise. * * @see #isDead() */ public boolean isAlive() { return this != DEAD; } /** * Checks if the robot is dead. * * @return {@code true} if the robot is dead; {@code false} otherwise. * * @see #isAlive() */ public boolean isDead() { return this == DEAD; } /** * Checks if the robot has hit another robot. * * @return {@code true} if the robot has hit a robot; {@code false} otherwise. * * @see #isHitWall() */ public boolean isHitRobot() { return this == HIT_ROBOT; } /** * Checks if the robot has hit the wall, i.e. one of the four borders. * * @return {@code true} if the robot has hit the wall; {@code false} otherwise. * * @see #isHitRobot() */ public boolean isHitWall() { return this == HIT_WALL; } } robocode/robocode/robocode/control/snapshot/IRobotSnapshot.java0000644000175000017500000001177711130241114024335 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.control.snapshot; import robocode.control.snapshot.RobotState; /** * Interface of a robot snapshot. * * @author Pavel Savara (original) * @author Flemming N. Larsen (contributor) * * @since 1.6.2 */ public interface IRobotSnapshot { /** * Returns the name of the robot. * * @return the name of the robot. */ String getName(); /** * Returns the very short name of the robot. * * @return the very short name of the robot. */ String getShortName(); /** * Returns the very short name of the robot. * * @return the very short name of the robot. */ String getVeryShortName(); /** * Returns the name of the team, or name of the robot if the contestant is not a team. * * @return the name of the team, or name of the robot if the contestant is not a team. */ String getTeamName(); /** * Returns the index of the contestant that will not be changed during a battle. * * @return the index of the contestant that will not be changed during a battle. */ int getContestantIndex(); /** * Returns the robot status. * * @return the robot status. */ RobotState getState(); /** * Returns the energy level. * * @return the energy level. */ double getEnergy(); /** * Returns the velocity. * * @return the velocity. */ double getVelocity(); /** * Returns the body heading in radians. * * @return the body heading in radians. */ double getBodyHeading(); /** * Returns the gun heading in radians. * * @return the gun heading in radians. */ double getGunHeading(); /** * Returns the radar heading in radians. * * @return the radar heading in radians. */ double getRadarHeading(); /** * Returns the gun heat. * * @return the gun heat. */ double getGunHeat(); /** * Returns the x coordinate of the robot. * * @return the x coordinate of the robot. */ double getX(); /** * Returns the y coordinate of the robot. * * @return the y coordinate of the robot. */ double getY(); /** * Returns the color of the body. * * @return a RGBA color value. (Bits 24-31 are alpha, 16-23 are red, 8-15 are green, 0-7 are blue) * * @see java.awt.Color#getRGB() */ int getBodyColor(); /** * Returns the color of the gun. * * @return a RGBA color value. (Bits 24-31 are alpha, 16-23 are red, 8-15 are green, 0-7 are blue) * * @see java.awt.Color#getRGB() */ int getGunColor(); /** * Returns the color of the radar. * * @return a RGBA color value. (Bits 24-31 are alpha, 16-23 are red, 8-15 are green, 0-7 are blue) * * @see java.awt.Color#getRGB() */ int getRadarColor(); /** * Returns the color of the scan arc. * * @return a RGBA color value. (Bits 24-31 are alpha, 16-23 are red, 8-15 are green, 0-7 are blue) * * @see java.awt.Color#getRGB() */ int getScanColor(); /** * Returns a flag specifying if this robot is a {@link robocode.Droid Droid}. * * @return {@code true} if this robot is a Droid; {@code false} otherwise. */ boolean isDroid(); /** * Returns a flag specifying if this robot is an {@link robocode.robotinterfaces.IPaintRobot IPaintRobot} * or is asking for getGraphics(). * * @return {@code true} if this robot is a an IPaintRobot or is asking for getGraphics(); * {@code false} otherwise. */ boolean isPaintRobot(); /** * Returns a flag specifying if robot's (onPaint) painting is enabled for the robot. * * @return {@code true} if the paintings for this robot is enabled; * {@code false} otherwise. */ boolean isPaintEnabled(); /** * Returns a flag specifying if RobocodeSG painting is enabled for the robot. * * @return {@code true} if RobocodeSG painting is enabled for this robot; * {@code false} otherwise. */ boolean isSGPaintEnabled(); /** * Returns a list of all debug properties. * * @return a list of all debug properties. */ IDebugProperty[] getDebugProperties(); /** * Returns a snapshot of the output print stream for this robot. * * @return a string containing the snapshot of the output print stream. */ String getOutputStreamSnapshot(); /** * Returns snapshot current score. * * @return snapshot current score. */ IScoreSnapshot getScoreSnapshot(); } robocode/robocode/robocode/control/snapshot/BulletState.java0000644000175000017500000000517511130241114023642 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen * - Initial implementation *******************************************************************************/ package robocode.control.snapshot; /** * Defines a bullet state, where the robot can be: just fired, moving somewhere, hitting a victim, * hitting another bullet, hitting the wall, exploded, or inactive when it done an inactivated. * * @author Flemming N. Larsen (original) * @since 1.6.2 */ public enum BulletState { /** The bullet has just been fired this second and hence just been created. This state only last one turn. */ FIRED(0), /** The bullet is now moving across the battlefield, but has not hit anything so far. */ MOVING(1), /** The bullet has hit a robot victim. */ HIT_VICTIM(2), /** The bullet has hit another bullet. */ HIT_BULLET(3), /** The bullet has the wall, i.e. one of the four borders. */ HIT_WALL(4), /** The bullet currently represents a robot explosion, i.e. a robot death. */ EXPLODED(5), /** The bullet is currently inactive. Hence, it is not active or visible on the battlefield. */ INACTIVE(6); private final int value; private BulletState(int value) { this.value = value; } /** * Returns the state as an integer value. * * @return an integer value representing this state. * * @see #toState(int) */ public int getValue() { return value; } /** * Returns a BulletState based on an integer value that represents a BulletState. * * @param value the integer value that represents a specific BulletState. * @return a BulletState that corresponds to the specific integer value. * * @see #getValue() * * @throws IllegalArgumentException if the specified value does not correspond * to a BulletState and hence is invalid. */ public static BulletState toState(int value) { switch (value) { case 0: return FIRED; case 1: return MOVING; case 2: return HIT_VICTIM; case 3: return HIT_BULLET; case 4: return HIT_WALL; case 5: return EXPLODED; case 6: return INACTIVE; default: throw new IllegalArgumentException("unknown value"); } } } robocode/robocode/robocode/control/snapshot/package.html0000644000175000017500000000015011124141546023027 0ustar lambylamby

Snapshots of the battle turns, robots, bullets, and scores.

robocode/robocode/robocode/control/snapshot/IDebugProperty.java0000644000175000017500000000205011130241114024303 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.control.snapshot; /** * Interface of a debug property, which is a key-value pair. * * @author Pavel Savara (original) * * @since 1.6.2 */ public interface IDebugProperty { /** * Returns the key of the property. * * @return the key of the property. */ String getKey(); /** * Returns the value of the property. * * @return the value of the property. */ String getValue(); } robocode/robocode/robocode/control/snapshot/IScoreSnapshot.java0000644000175000017500000000643611130241114024317 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.control.snapshot; /** * Interface of a robot/team score snapshot. * * @author Pavel Savara (original) * @author Flemming N. Larsen (contributor) * * @since 1.6.2 */ public interface IScoreSnapshot extends Comparable { /** * Returns the name of the robot. * * @return the name of the robot. */ String getName(); /** * Returns the total score. * * @return the total score. */ double getTotalScore(); /** * Returns the total survival score. * * @return the total survival score. */ double getTotalSurvivalScore(); /** * Returns the total last survivor score. * * @return the total last survivor score. */ double getTotalLastSurvivorBonus(); /** * Returns the total bullet damage score. * * @return the total bullet damage score. */ double getTotalBulletDamageScore(); /** * Returns the total bullet kill bonus. * * @return the total bullet kill bonus. */ double getTotalBulletKillBonus(); /** * Returns the total ramming damage score. * * @return the total ramming damage score. */ double getTotalRammingDamageScore(); /** * Returns the total ramming kill bonus. * * @return the total ramming kill bonus. */ double getTotalRammingKillBonus(); /** * Returns the total number of first places. * * @return the total number of first places. */ int getTotalFirsts(); /** * Returns the total number of second places. * * @return the total number of second places. */ int getTotalSeconds(); /** * Returns the total number of third places. * * @return the total number of third places. */ int getTotalThirds(); /** * Returns the current score. * * @return the current score. */ double getCurrentScore(); /** * Returns the current survival score. * * @return the current survival score. */ double getCurrentSurvivalScore(); /** * Returns the current survival bonus. * * @return the current survival bonus. */ double getCurrentSurvivalBonus(); /** * Returns the current bullet damage score. * * @return the current bullet damage score. */ double getCurrentBulletDamageScore(); /** * Returns the current bullet kill bonus. * * @return the current bullet kill bonus. */ double getCurrentBulletKillBonus(); /** * Returns the current ramming damage score. * * @return the current ramming damage score. */ double getCurrentRammingDamageScore(); /** * Returns the current ramming kill bonus. * * @return the current ramming kill bonus. */ double getCurrentRammingKillBonus(); } robocode/robocode/robocode/control/snapshot/ITurnSnapshot.java0000644000175000017500000000333011130241114024162 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.control.snapshot; /** * Interface of a turn snapshot. * * @author Pavel Savara (original) * @author Flemming N. Larsen (contributor) * * @since 1.6.2 */ public interface ITurnSnapshot { /** * Returns all robots participating in the battle. * * @return a list containing all robots participating in the battle. */ IRobotSnapshot[] getRobots(); /** * Returns all bullets currently the battlefield. * * @return a list containing all bullets currently the battlefield. */ IBulletSnapshot[] getBullets(); /** * Returns the current TPS (turns per second). * * @return the current TPS (turns per second). */ int getTPS(); /** * Returns the current turn. * * @return the current turn. */ int getRound(); /** * Returns the current turn. * * @return the current turn. */ int getTurn(); /** * @return scores grouped by teams, ordered by position */ IScoreSnapshot[] getSortedTeamScores(); /** * @return scores grouped by teams, in stable order */ IScoreSnapshot[] getIndexedTeamScores(); } robocode/robocode/robocode/control/events/0000755000175000017500000000000011124141562020215 5ustar lambylambyrobocode/robocode/robocode/control/events/BattleEvent.java0000644000175000017500000000166711130241114023276 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.control.events; /** * This is the base class of all battle events. * * @author Pavel Savara (original) * @author Flemming N. Larsen (contributor) * * @since 1.6.2 */ public abstract class BattleEvent { /** * Creates a new BattleEvent. */ public BattleEvent() { super(); } } robocode/robocode/robocode/control/events/RoundEndedEvent.java0000644000175000017500000000326011130241114024101 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.control.events; /** * A RoundEndedEvent is sent to {@link IBattleListener#onRoundEnded(RoundEndedEvent) * onRoundEnded()} when the current round of a battle has ended. * * @see IBattleListener * @see RoundStartedEvent * * @author Pavel Savara (original) * @author Flemming N. Larsen (contributor) * * @since 1.6.2 */ public class RoundEndedEvent extends BattleEvent { private final int round; private final int turns; /** * Creates a new RoundEndedEvent. * * @param round the round number that was ended. * @param turns the number of turns that this round reached. */ public RoundEndedEvent(int round, int turns) { super(); this.round = round; this.turns = turns; } /** * Returns the round number that was ended. * * @return the round number that was ended. */ public int getRound() { return round; } /** * Returns the number of turns that this round reached. * * @return the number of turns that this round reached. */ public int getTurns() { return turns; } } robocode/robocode/robocode/control/events/RoundStartedEvent.java0000644000175000017500000000356611130241114024501 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.control.events; import robocode.control.snapshot.ITurnSnapshot; /** * A RoundStartedEvent is sent to {@link IBattleListener#onRoundStarted(RoundStartedEvent) * onRoundStarted()} when a new round in a battle is started. * * @see IBattleListener * @see RoundEndedEvent * * @author Pavel Savara (original) * @author Flemming N. Larsen (contributor) * * @since 1.6.2 */ public class RoundStartedEvent extends BattleEvent { private final ITurnSnapshot startSnapshot; private final int round; /** * Creates a new RoundStartedEvent. * * @param startSnapshot the start snapshot of the participating robots, initial starting positions etc. * @param round the round number. */ public RoundStartedEvent(ITurnSnapshot startSnapshot, int round) { super(); this.startSnapshot = startSnapshot; this.round = round; } /** * Returns the start snapshot of the participating robots, initial starting positions etc. * * @return a ITurnSnapshot instance that serves as the start snapshot of the round. */ public ITurnSnapshot getStartSnapshot() { return startSnapshot; } /** * Returns the round number. * * @return the round number. */ public int getRound() { return round; } } robocode/robocode/robocode/control/events/BattlePausedEvent.java0000644000175000017500000000216111130241114024426 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.control.events; /** * A BattlePausedEvent is sent to {@link IBattleListener#onBattlePaused(BattlePausedEvent) * onBattlePaused()} when the battle has been paused. * * @see IBattleListener * @see BattleResumedEvent * * @author Pavel Savara (original) * @author Flemming N. Larsen (contributor) * * @since 1.6.2 */ public class BattlePausedEvent extends BattleEvent { /** * Creates a new BattlePausedEvent. */ public BattlePausedEvent() { super(); } } robocode/robocode/robocode/control/events/BattleMessageEvent.java0000644000175000017500000000265711130241114024603 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.control.events; /** * A BattleMessageEvent is sent to {@link IBattleListener#onBattleMessage(BattleMessageEvent) * onBattleMessage()} when an information message is sent from the game in the during the battle. * * @see IBattleListener * @see BattleErrorEvent * * @author Pavel Savara (original) * @author Flemming N. Larsen (contributor) * * @since 1.6.2 */ public class BattleMessageEvent extends BattleEvent { private final String message; /** * Creates a new BattleMessageEvent. * * @param message the information message. */ public BattleMessageEvent(String message) { super(); this.message = message; } /** * Returns the information message. * * @return the information message. */ public String getMessage() { return message; } } robocode/robocode/robocode/control/events/BattleResumedEvent.java0000644000175000017500000000222211130241114024607 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.control.events; /** * A BattleResumedEvent is sent to {@link IBattleListener#onBattleResumed(BattleResumedEvent) * onBattleResumed()} when the battle has been resumed (after having been paused). * * @see IBattleListener * @see BattlePausedEvent * * @author Pavel Savara (original) * @author Flemming N. Larsen (contributor) * * @since 1.6.2 */ public class BattleResumedEvent extends BattleEvent { /** * Creates a new BattlePausedEvent. */ public BattleResumedEvent() { super(); } } robocode/robocode/robocode/control/events/BattleStartedEvent.java0000644000175000017500000000452711130241114024623 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.control.events; import robocode.BattleRules; /** * A BattleStartedEvent is sent to {@link IBattleListener#onBattleStarted(BattleStartedEvent) * onBattleStarted()} when a new battle is started. * * @see IBattleListener * @see BattleCompletedEvent * @see BattleFinishedEvent * * @author Pavel Savara (original) * @author Flemming N. Larsen (contributor) * * @since 1.6.2 */ public class BattleStartedEvent extends BattleEvent { private final BattleRules battleRules; private final boolean isReplay; private final int robotsCount; /** * Creates a new BattleStartedEvent. * * @param battleRules the rules that will be used in the battle. * @param robotsCount the number of robots participating in the battle. * @param isReplay a flag specifying if this battle is a replay or real battle: * {@code true} if the battle is a replay; {@code false} otherwise. */ public BattleStartedEvent(BattleRules battleRules, int robotsCount, boolean isReplay) { super(); this.battleRules = battleRules; this.isReplay = isReplay; this.robotsCount = robotsCount; } /** * Returns the rules that will be used in the battle. * * @return the rules that will be used in the battle. */ public BattleRules getBattleRules() { return battleRules; } /** * Returns the number of robots participating in the battle. * * @return the number of robots participating in the battle. */ public int getRobotsCount() { return robotsCount; } /** * Checks if this battle is a replay or real battle. * * @return {@code true} if the battle is a replay; {@code false} otherwise. */ public boolean isReplay() { return isReplay; } } robocode/robocode/robocode/control/events/BattleCompletedEvent.java0000644000175000017500000000554011130241114025125 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.control.events; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import robocode.BattleResults; import robocode.BattleRules; /** * A BattleCompletedEvent is sent to {@link IBattleListener#onBattleCompleted(BattleCompletedEvent) * onBattleCompleted()} when the battle is completed successfully and results are available. This event * will not occur if the battle is terminated or aborted by the user before the battle is completed. * * @see IBattleListener * @see BattleStartedEvent * @see BattleFinishedEvent * * @author Pavel Savara (original) * @author Flemming N. Larsen (contributor) * * @since 1.6.2 */ public class BattleCompletedEvent extends BattleEvent { private final BattleRules battleRules; private final BattleResults[] results; /** * Creates a new BattleCompletedEvent. * * @param battleRules the rules that was used in the battle. * @param results the indexed results of the battle. These are unsorted, but using robot indexes. */ public BattleCompletedEvent(BattleRules battleRules, BattleResults[] results) { super(); this.battleRules = battleRules; this.results = results; } /** * Returns the rules that was used in the battle. * * @return the rules of the battle. */ public BattleRules getBattleRules() { return battleRules; } /** * Returns the battle results sorted on score, meaning that robot indexes cannot be used. * * @return a sorted array of BattleResults, where the results with the biggest score are placed first in the list. */ public BattleResults[] getSortedResults() { List copy = new ArrayList(Arrays.asList(results)); Collections.sort(copy); Collections.reverse(copy); return copy.toArray(new BattleResults[copy.size()]); } /** * Returns the unsorted battle results so that robot indexes can be used. * * @return an unsorted array of BattleResults, where each index matches an index of a specific robot. */ public BattleResults[] getIndexedResults() { BattleResults[] copy = new BattleResults[results.length]; System.arraycopy(results, 0, copy, 0, results.length); return copy; } } robocode/robocode/robocode/control/events/TurnEndedEvent.java0000644000175000017500000000301711130241114023742 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.control.events; import robocode.control.snapshot.ITurnSnapshot; /** * A TurnEndedEvent is sent to {@link IBattleListener#onTurnEnded(TurnEndedEvent) * onTurnEnded()} when the current turn in a battle round is ended. * * @see IBattleListener * @see TurnStartedEvent * * @author Pavel Savara (original) * @author Flemming N. Larsen (contributor) * * @since 1.6.2 */ public class TurnEndedEvent extends BattleEvent { private final ITurnSnapshot turnSnapshot; /** * Creates a new TurnEndedEvent. * * @param turnSnapshot a snapshot of the turn that has ended. */ public TurnEndedEvent(ITurnSnapshot turnSnapshot) { super(); this.turnSnapshot = turnSnapshot; } /** * Returns a snapshot of the turn that has ended. * * @return a snapshot of the turn that has ended. */ public ITurnSnapshot getTurnSnapshot() { return turnSnapshot; } } robocode/robocode/robocode/control/events/package.html0000644000175000017500000000023011124141562022471 0ustar lambylamby

Battle events that occurs during a game, and which are used for the robocode.control.IBattleListener class.

robocode/robocode/robocode/control/events/BattleErrorEvent.java0000644000175000017500000000257511130241114024307 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.control.events; /** * A BattleErrorEvent is sent to {@link IBattleListener#onBattleError(BattleErrorEvent) * onBattleError()} when an error message is sent from the game in the during the battle. * * @see IBattleListener * @see BattleMessageEvent * * @author Pavel Savara (original) * @author Flemming N. Larsen (contributor) * * @since 1.6.2 */ public class BattleErrorEvent extends BattleEvent { private final String error; /** * Creates a new BattleErrorEvent. * * @param error the error message. */ public BattleErrorEvent(String error) { super(); this.error = error; } /** * Returns the error message. * * @return the error message. */ public String getError() { return error; } } robocode/robocode/robocode/control/events/BattleAdaptor.java0000644000175000017500000000525411130241114023603 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen * - Initial implementation *******************************************************************************/ package robocode.control.events; /** * An abstract adapter class for receiving battle events by implementing the {@link IBattleListener}. * The methods in this class are empty. This class exists as convenience for creating listener objects. *

* This is handy class to use when implementing the IBattleListener. * It saves you from implementing empty handlers for battle events you are not interested in handling. *

* Example: *

 *   private class BattleObserver extends BattleAdaptor {
 *       boolean isReplay;
 *
 *       public void onBattleStarted(BattleStartedEvent event) {
 *           isReplay = event.isReplay();
 *       }
 *
 *       public void onBattleCompleted(BattleCompletedEvent event) {
 *       if (!isReplay) {
 *           printResultsData(event);
 *       }
 *   }
 * 
* * @see IBattleListener * * @author Flemming N. Larsen (original) * @since 1.6.2 */ public abstract class BattleAdaptor implements IBattleListener { /** * Creates a BattleAdaptor. */ public BattleAdaptor() {} /** * {@inheritDoc} */ public void onBattleStarted(final BattleStartedEvent event) {} /** * {@inheritDoc} */ public void onBattleFinished(final BattleFinishedEvent event) {} /** * {@inheritDoc} */ public void onBattleCompleted(final BattleCompletedEvent event) {} /** * {@inheritDoc} */ public void onBattlePaused(final BattlePausedEvent event) {} /** * {@inheritDoc} */ public void onBattleResumed(final BattleResumedEvent event) {} /** * {@inheritDoc} */ public void onRoundStarted(final RoundStartedEvent event) {} /** * {@inheritDoc} */ public void onRoundEnded(final RoundEndedEvent event) {} /** * {@inheritDoc} */ public void onTurnStarted(final TurnStartedEvent event) {} /** * {@inheritDoc} */ public void onTurnEnded(final TurnEndedEvent event) {} /** * {@inheritDoc} */ public void onBattleMessage(final BattleMessageEvent event) {} /** * {@inheritDoc} */ public void onBattleError(final BattleErrorEvent event) {} } robocode/robocode/robocode/control/events/IBattleListener.java0000644000175000017500000001331411130241114024103 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen * - Initial implementation *******************************************************************************/ package robocode.control.events; /** * The listener interface for receiving "interesting" battle events from the game, e.g. when a battle, * round or turn is started or ended. *

* When implementing this battle listener you should implement the {@link BattleAdaptor} in order to * only implement the event handler methods you are interested in. * * @see BattleAdaptor * * @author Flemming N. Larsen (original) * @since 1.6.2 */ public interface IBattleListener { /** * This method is called when a new battle has started. *

* You must override this method in order to get informed about this event and receive the event details. * * @see BattleStartedEvent * @see #onBattleCompleted(BattleCompletedEvent) * @see #onBattleFinished(BattleFinishedEvent) * * @param event the event details. */ public void onBattleStarted(final BattleStartedEvent event); /** * This method is called when the battle has finished. This event is always sent as the last battle event, * both when the battle is completed successfully, terminated due to an error, or aborted by the user. * Hence, this events is well-suited for cleanup after the battle. *

* You must override this method in order to get informed about this event and receive the event details. * * @see BattleFinishedEvent * @see #onBattleStarted(BattleStartedEvent) * @see #onBattleCompleted(BattleCompletedEvent) * * @param event the event details. */ public void onBattleFinished(final BattleFinishedEvent event); /** * This method is called when the battle has completed successfully and results are available. * This event will not occur if the battle is terminated or aborted by the user before the battle is completed. *

* You must override this method in order to get informed about this event and receive the event details. * * @see BattleCompletedEvent * @see #onBattleStarted(BattleStartedEvent) * @see #onBattleFinished(BattleFinishedEvent) * * @param event the event details. */ public void onBattleCompleted(final BattleCompletedEvent event); /** * This method is called when the battle has been paused, either by the user or the game. *

* You must override this method in order to get informed about this event and receive the event details. * * @see BattlePausedEvent * @see #onBattleResumed(BattleResumedEvent) * * @param event the event details. */ public void onBattlePaused(final BattlePausedEvent event); /** * This method is called when the battle has been resumed (after having been paused). *

* You must override this method in order to get informed about this event and receive the event details. * * @see BattleResumedEvent * @see #onBattlePaused(BattlePausedEvent) * * @param event the event details. */ public void onBattleResumed(final BattleResumedEvent event); /** * This method is called when a new round in a battle has started. *

* You must override this method in order to get informed about this event and receive the event details. * * @see RoundEndedEvent * @see #onRoundEnded(RoundEndedEvent) * * @param event the event details. */ public void onRoundStarted(final RoundStartedEvent event); /** * This method is called when the current round of a battle has ended. *

* You must override this method in order to get informed about this event and receive the event details. * * @see RoundEndedEvent * @see #onRoundStarted(RoundStartedEvent) * * @param event the event details. */ public void onRoundEnded(final RoundEndedEvent event); /** * This method is called when a new turn in a battle round has started. *

* You must override this method in order to get informed about this event and receive the event details. * * @see TurnStartedEvent * @see #onTurnEnded(TurnEndedEvent) * * @param event the event details. */ public void onTurnStarted(final TurnStartedEvent event); /** * This method is called when the current turn in a battle round is ended. *

* You must override this method in order to get informed about this event and receive the event details. * * @see TurnEndedEvent * @see #onTurnStarted(TurnStartedEvent) * * @param event the event details. */ public void onTurnEnded(final TurnEndedEvent event); /** * This method is called when the game has sent a new information message. *

* You must override this method in order to get informed about this event and receive the event details. * * @see BattleMessageEvent * @see #onBattleError(BattleErrorEvent) * * @param event the event details. */ void onBattleMessage(final BattleMessageEvent event); /** * This method is called when the game has sent an error message. *

* You must override this method in order to get informed about this event and receive the event details. * * @see BattleErrorEvent * @see #onBattleMessage(BattleMessageEvent) * * @param event the event details. */ void onBattleError(final BattleErrorEvent event); } robocode/robocode/robocode/control/events/TurnStartedEvent.java0000644000175000017500000000216311130241114024332 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.control.events; /** * A TurnStartedEvent is sent to {@link IBattleListener#onTurnStarted(TurnStartedEvent) * onTurnStarted()} when a new turn in a battle round is started. * * @see IBattleListener * @see TurnEndedEvent * * @author Pavel Savara (original) * @author Flemming N. Larsen (contributor) * * @since 1.6.2 */ public class TurnStartedEvent extends BattleEvent { /** * Creates a new TurnStartedEvent. */ public TurnStartedEvent() { super(); } } robocode/robocode/robocode/control/events/BattleFinishedEvent.java0000644000175000017500000000345111130241114024741 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.control.events; /** * A BattleFinishedEvent is sent to {@link IBattleListener#onBattleFinished(BattleFinishedEvent) * onBattleFinished()} when the battle is finished. This event is always sent as the last battle event, * both when the battle is completed successfully, terminated due to an error, or aborted by the user. * Hence, this events is well-suited for cleanup after the battle. * * @see IBattleListener * @see BattleStartedEvent * @see BattleCompletedEvent * * @author Pavel Savara (original) * @author Flemming N. Larsen (contributor) * * @since 1.6.2 */ public class BattleFinishedEvent extends BattleEvent { private final boolean isAborted; /** * Creates a new BattleFinishedEvent. * * @param isAborted a flag specifying if the battle was aborted: * {@code true} if the battle was aborted; {@code false} otherwise. */ public BattleFinishedEvent(boolean isAborted) { super(); this.isAborted = isAborted; } /** * Checks if the battle was aborted. * * @return {@code true} if the battle was aborted; {@code false} otherwise. */ public boolean isAborted() { return isAborted; } } robocode/robocode/robocode/control/RobotSpecification.java0000644000175000017500000001033311130241114023331 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Lasen * - Code cleanup * - Added the getNameAndVersion() method * - Changed to use the FileSpecification as local specification instead of * RobotFileSpecification. This change was done in order to support teams * - This class now implements java.io.Serializable * - Updated the Javadocs *******************************************************************************/ package robocode.control; import robocode.repository.FileSpecification; import java.io.File; /** * Defines the properties of a robot, which is returned from * {@link RobocodeEngine#getLocalRepository()} or * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ public class RobotSpecification implements java.io.Serializable { private static final long serialVersionUID = 1L; private final FileSpecification fileSpecification; /** * This constructor is called by the game in order to construct a new * RobotSpecification. * * @param fileSpecification the file specification of the robot */ RobotSpecification(FileSpecification fileSpecification) { this.fileSpecification = fileSpecification; } /** * Returns the name of this robot or team. * * @return the name of this robot or team. * @see #getVersion() * @see #getNameAndVersion() */ public String getName() { return fileSpecification.getName(); } /** * Returns the version of this robot or team. * * @return the version of this robot or team. * @see #getName() * @see #getNameAndVersion() */ public String getVersion() { if (fileSpecification.getVersion() != null) { if (fileSpecification.isDevelopmentVersion()) { return fileSpecification.getVersion() + "*"; } } return fileSpecification.getVersion(); } /** * Returns the name and version of this robot or team. * * @return the name and version of this robot or team. * @see #getName() * @see #getVersion() * @since 1.3 */ public String getNameAndVersion() { String nameAndVersion = getName(); String version = getVersion(); if (version != null && version.trim().length() > 0) { nameAndVersion += ' ' + version; } return nameAndVersion; } /** * Returns the full class name of this robot or team. * * @return the full class name of this robot or team. */ public String getClassName() { return fileSpecification.getFullClassName(); } /** * Returns the JAR file containing this robot or team, or {@code null} if it * does not come from a JAR file (could be class files instead). * * @return the JAR file containing this robot or team, or {@code null} if it * does not come from a JAR file (could be class files instead). */ public File getJarFile() { return fileSpecification.getJarFile(); } /** * Returns the description provided by the author of this robot. * * @return the description provided by the author of this robot. */ public String getDescription() { return fileSpecification.getDescription(); } /** * Returns the version of Robocode this robot was based on. * * @return the version of Robocode this robot was based on. */ public String getRobocodeVersion() { return fileSpecification.getRobocodeVersion(); } /** * Returns the web page for this robot. * * @return the web page for this robot. */ public String getWebpage() { return (fileSpecification.getWebpage() != null) ? fileSpecification.getWebpage().toString() : null; } /** * Returns the name of this robot's author. * * @return the name of this robot's author. */ public String getAuthorName() { return fileSpecification.getAuthorName(); } } robocode/robocode/robocode/control/RobotResults.java0000644000175000017500000001012411130241114022210 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Changed to be consistent with the battle results and ranking scores * - This class now implements java.io.Serializable * - Updated Javadocs *******************************************************************************/ package robocode.control; import robocode.BattleResults; /** * Contains the battle results for an individual robot, which is given as input * parameter with the * {@link RobocodeListener#battleComplete(BattleSpecification, RobotResults[]) * RobocodeListener#battleComplete()} event handler. * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @see RobocodeListener */ public class RobotResults extends BattleResults { private static final long serialVersionUID = 2L; private final RobotSpecification robot; /** * Constructs new RobotResults. * * @param robot the robot these results are for * @param teamLeaderName team name * @param rank the rank of the robot in the battle * @param score the total score for the robot in the battle * @param survival the survival score for the robot in the battle * @param lastSurvivorBonus the last survivor bonus for the robot in the battle * @param bulletDamage the bullet damage score for the robot in the battle * @param bulletDamageBonus the bullet damage bonus for the robot in the battle * @param ramDamage the ramming damage for the robot in the battle * @param ramDamageBonus the ramming damage bonus for the robot in the battle * @param firsts the number of rounds this robot placed first * @param seconds the number of rounds this robot placed second * @param thirds the number of rounds this robot placed third */ public RobotResults( RobotSpecification robot, String teamLeaderName, int rank, double score, double survival, double lastSurvivorBonus, double bulletDamage, double bulletDamageBonus, double ramDamage, double ramDamageBonus, int firsts, int seconds, int thirds ) { super(teamLeaderName, rank, score, survival, lastSurvivorBonus, bulletDamage, bulletDamageBonus, ramDamage, ramDamageBonus, firsts, seconds, thirds); this.robot = robot; } /** * Constructs new RobotResults based on a {@link RobotSpecification} and {@link robocode.BattleResults * BattleResults}. * * @param robot the robot these results are for * @param results the battle results for the robot */ public RobotResults( RobotSpecification robot, BattleResults results) { super(results.getTeamLeaderName(), results.getRank(), results.getScore(), results.getSurvival(), results.getLastSurvivorBonus(), results.getBulletDamage(), results.getBulletDamageBonus(), results.getRamDamage(), results.getRamDamageBonus(), results.getFirsts(), results.getSeconds(), results.getThirds()); this.robot = robot; } /** * Returns the robot these results are meant for. * * @return the robot these results are meant for. */ public RobotSpecification getRobot() { return robot; } /** * Converts an array of {@link BattleResults} into an array of {@link RobotResults}. * * @param results an array of BattleResults to convert. * @return an array of RobotResults converted from BattleResults. * @since 1.6.2 */ public static RobotResults[] convertResults(BattleResults[] results) { RobotResults[] resultsConv = new RobotResults[results.length]; for (int i = 0; i < results.length; i++) { resultsConv[i] = (RobotResults) results[i]; } return resultsConv; } } robocode/robocode/robocode/control/RobocodeListener.java0000644000175000017500000000451111130241114023006 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Updated Javadocs *******************************************************************************/ package robocode.control; import robocode.control.events.IBattleListener; /** * @deprecated Since 1.6.2. Use the {@link IBattleListener} instead. *

* A listener interface for receiving callbacks from the {@link RobocodeEngine}. * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * * @see IBattleListener */ @Deprecated public interface RobocodeListener { /** * @deprecated Since 1.6.2. Use the * {@link IBattleListener#onBattleCompleted(robocode.control.events.BattleCompletedEvent) * IBattleListener.onBattleCompleted()} instead. *

* This method is called when a battle completes successfully. * * @param battle information about the battle that completed * @param results an array containing the results for the individual robot */ @Deprecated void battleComplete(BattleSpecification battle, RobotResults[] results); /** * @deprecated Since 1.6.2. Use the * {@link IBattleListener#onBattleFinished(robocode.control.events.BattleFinishedEvent) * IBattleListener.onBattleFinished()} instead. *

* This method is called when a battle has been aborted. * * @param battle information about the battle that was aborted */ @Deprecated void battleAborted(BattleSpecification battle); /** * @deprecated Since 1.6.2. Use the * {@link IBattleListener#onBattleMessage(robocode.control.events.BattleMessageEvent) * IBattleListener.onBattleMessage()} instead. *

* This method is called when the game logs messages that is normally * written out to the console. * * @param message the message logged by the game */ @Deprecated void battleMessage(String message); } robocode/robocode/robocode/control/package.html0000644000175000017500000000552111124141576021202 0ustar lambylamby

Control API used for controlling Robocode from an external application.

Example

Here is a simple application that runs a battle in Robocode for 5 rounds on the default battlefield of 800x600 pixels. The robots selected for the battle are sample.RamFire and sample.Corners.

import robocode.control.*;
import robocode.control.events.*;

/**
 * Application that demonstrates how to run two sample robots in Robocode using the
 * RobocodeEngine from the robocode.control package.
 *
 * @author Flemming N. Larsen
 */
public class RobocodeRunner {

    public static void main(String[] args) {

        // Create the RobocodeEngine
        //   RobocodeEngine engine = new RobocodeEngine(); // Run from current working directory
        RobocodeEngine engine = new RobocodeEngine(new java.io.File("C:/Robocode")); // Run from C:/Robocode

        // Add our own battle listener to the RobocodeEngine 
        engine.addBattleListener(new BattleObserver());

        // Show the Robocode battle view
        engine.setVisible(true);

        // Setup the battle specification

        int numberOfRounds = 5;
        BattlefieldSpecification battlefield = new BattlefieldSpecification(800, 600); // 800x600
        RobotSpecification[] selectedRobots = engine.getLocalRepository("sample.RamFire, sample.Corners");

        BattleSpecification battleSpec = new BattleSpecification(numberOfRounds, battlefield, selectedRobots);

        // Run our specified battle and let it run till it is over
        engine.runBattle(battleSpec, true/* wait till the battle is over */);

        // Cleanup our RobocodeEngine
        engine.close();

        // Make sure that the Java VM is shut down properly
        System.exit(0);
    }
}


/**
 * Our private battle listener for handling the battle event we are interested in.
 */
class BattleObserver extends BattleAdaptor {

    // Called when the battle is completed successfully with battle results
    public void onBattleCompleted(BattleCompletedEvent e) {
        System.out.println("-- Battle has completed --");
        
        // Print out the sorted results with the robot names
        System.out.println("Battle results:");
        for (robocode.BattleResults result : e.getSortedResults()) {
            System.out.println("  " + result.getTeamLeaderName() + ": " + result.getScore());
        }
    }

    // Called when the game sends out an information message during the battle
    public void onBattleMessage(BattleMessageEvent e) {
        System.out.println("Msg> " + e.getMessage());
    }

    // Called when the game sends out an error message during the battle
    public void onBattleError(BattleErrorEvent e) {
        System.out.println("Err> " + e.getError());
    }
}
robocode/robocode/robocode/control/RandomFactory.java0000644000175000017500000000715211130241114022320 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.control; import static robocode.io.Logger.logError; import static robocode.io.Logger.logMessage; import java.lang.reflect.Field; import java.util.Random; /** * The RandomFactory is used for controlling the generation of random numbers, * and supports generating random numbers that are deterministic, which is * useful for testing purposes. * * @author Pavel Savara (original) * @since 1.6.1 */ public class RandomFactory { private static Random randomNumberGenerator; private static boolean warningNotSupportedLogged; /** * Returns the random number generator used for generating a stream of * random numbers. * * @return a {@link java.util.Random} instance. * @see java.util.Random */ public static Random getRandom() { if (randomNumberGenerator == null) { try { Math.random(); final Field field = Math.class.getDeclaredField("randomNumberGenerator"); final boolean savedFieldAccessible = field.isAccessible(); field.setAccessible(true); randomNumberGenerator = (Random) field.get(null); field.setAccessible(savedFieldAccessible); } catch (NoSuchFieldException e) { logWarningNotSupported(); randomNumberGenerator = new Random(); } catch (IllegalAccessException e) { logError(e); randomNumberGenerator = new Random(); } } return randomNumberGenerator; } /** * Sets the random number generator instance used for generating a * stream of random numbers. * * @param random a {@link java.util.Random} instance. * @see java.util.Random */ public static void setRandom(Random random) { randomNumberGenerator = random; try { Math.random(); final Field field = Math.class.getDeclaredField("randomNumberGenerator"); final boolean savedFieldAccessible = field.isAccessible(); field.setAccessible(true); field.set(null, randomNumberGenerator); field.setAccessible(savedFieldAccessible); } catch (NoSuchFieldException e) { logWarningNotSupported(); } catch (IllegalAccessException e) { logError(e); } // TODO ZAMO using Robot classloader inject seed also for all instances being created by robots } /** * Resets the random number generator instance to be deterministic when * generating random numbers. * * @param seed the seed to use for the new deterministic random generator. */ public static void resetDeterministic(long seed) { setRandom(new Random(seed)); } /** * Logs a warning that the deterministic random feature is not supported by the JVM. */ private static void logWarningNotSupported() { if (!(warningNotSupportedLogged || System.getProperty("RANDOMSEED", "none").equals("none"))) { logMessage( "Warning: The deterministic random generator feature is not supported by this JVM:\n" + System.getProperty("java.vm.vendor") + " " + System.getProperty("java.vm.name") + " " + System.getProperty("java.vm.version")); warningNotSupportedLogged = true; } } } robocode/robocode/robocode/control/BattleSpecification.java0000644000175000017500000001121511130241114023457 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Removed the battlefield field, which can be created when calling * getBattlefield() and optimized constructor * - Changed getRobots() to return a copy of the robots * - This class now implements java.io.Serializable * - Updated Javadocs *******************************************************************************/ package robocode.control; import robocode.battle.BattleProperties; /** * A BattleSpecification defines battle configuration used by the * {@link RobocodeEngine}. * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ public class BattleSpecification implements java.io.Serializable { private static final long serialVersionUID = 1L; private final RobotSpecification[] robots; private final BattleProperties battleProperties; /** * Creates a new BattleSpecification with the given number of rounds, * battlefield size, and robots. Inactivity time for the robots defaults to * 450, and the gun cooling rate defaults to 0.1. * * @param numRounds the number of rounds in this battle * @param battlefieldSize the battlefield size * @param robots the robots participating in this battle */ public BattleSpecification(int numRounds, BattlefieldSpecification battlefieldSize, RobotSpecification[] robots) { this(numRounds, 450, .1, battlefieldSize, robots); } /** * Creates a new BattleSpecification with the given settings. * * @param numRounds the number of rounds in this battle * @param inactivityTime the inactivity time allowed for the robots before * they will loose energy * @param gunCoolingRate the gun cooling rate for the robots * @param battlefieldSize the battlefield size * @param robots the robots participating in this battle */ public BattleSpecification(int numRounds, long inactivityTime, double gunCoolingRate, BattlefieldSpecification battlefieldSize, RobotSpecification[] robots) { battleProperties = new BattleProperties(); battleProperties.setNumRounds(numRounds); battleProperties.setInactivityTime(inactivityTime); battleProperties.setGunCoolingRate(gunCoolingRate); battleProperties.setBattlefieldWidth(battlefieldSize.getWidth()); battleProperties.setBattlefieldHeight(battlefieldSize.getHeight()); if (robots != null) { battleProperties.setSelectedRobots(robots); } this.robots = robots; } /** * Returns the allowed inactivity time for the robots in this battle. * * @return the allowed inactivity time for the robots in this battle. */ public long getInactivityTime() { return battleProperties.getInactivityTime(); } /** * Returns the gun cooling rate of the robots in this battle. * * @return the gun cooling rate of the robots in this battle. */ public double getGunCoolingRate() { return battleProperties.getGunCoolingRate(); } /** * Returns the battlefield size for this battle. * * @return the battlefield size for this battle. */ public BattlefieldSpecification getBattlefield() { return new BattlefieldSpecification(battleProperties.getBattlefieldWidth(), battleProperties.getBattlefieldHeight()); } /** * Returns the number of rounds in this battle. * * @return the number of rounds in this battle. */ public int getNumRounds() { return battleProperties.getNumRounds(); } /** * Returns the specifications of the robots participating in this battle. * * @return the specifications of the robots participating in this battle. */ public RobotSpecification[] getRobots() { if (robots == null) { return null; } RobotSpecification[] robotsCopy = new RobotSpecification[robots.length]; System.arraycopy(robots, 0, robotsCopy, 0, robots.length); return robotsCopy; } /** * Do not call this method! * * @return the properties of this battle. * @deprecated This methods is called by the game and is very likely to be * removed in a future version of Robocode. */ @Deprecated public BattleProperties getBattleProperties() { return battleProperties; } } robocode/robocode/robocode/control/RobocodeEngine.java0000644000175000017500000003526011130241114022433 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup * - Replaced FileSpecificationVector with plain Vector * - GUI is disabled per default. If the setVisible() is called, the GUI will * be enabled. The close() method is only calling dispose() on the * RobocodeFrame if the GUI is enabled * - Updated to use methods from FileUtil and Logger, which replaces * methods that have been (re)moved from the robocode.util.Utils class * - Changed to use FileUtil.getRobotsDir() * - Modified getLocalRepository() to support teams by using * FileSpecification instead of RobotFileSpecification * - System.out, System.err, and System.in is now only set once, as new * instances of the RobocodeEngine causes memory leaks with * System.setOut() and System.setErr() * - Updated Javadocs * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap * Nathaniel Troutman * - Bugfix: Inconsistent Behavior of RobocodeEngine.setVisible() * - Bugfix: Added cleanup of the Robocode manager to the close() method * Joachim Hofer * - Bugfix in onBattleCompleted() where the RobotResults were ordered * incorrectly when calling the battleComplete() so the results were given * for the wrong robots *******************************************************************************/ package robocode.control; import robocode.control.events.*; import robocode.io.FileUtil; import robocode.manager.RobocodeManager; import robocode.repository.FileSpecification; import robocode.repository.Repository; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; /** * The RobocodeEngine is the old interface provided for external applications * in order to let these applications run battles within the Robocode application, * and to get the results from these battles. *

* This class in the main class of the {@code robocode.control} package, and the * reason for having this control package. *

* The RobocodeEngine is used by RoboRumble@Home, which is integrated in * Robocode, but also RoboLeague and RobocodeJGAP. In addition, the * RobocodeEngine is also used by the test units for testing the Robocode * application itself. * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Robert D. Maupin (contributor) * @author Nathaniel Troutman (contributor) * @author Joachim Hofer (contributor) * @author Pavel Savara (contributor) */ public class RobocodeEngine { RobocodeManager manager; private BattleObserver battleObserver; private BattleSpecification battleSpecification; /** * Creates a new RobocodeEngine for controlling Robocode. The JAR file of * Robocode is used to determine the root directory of Robocode. * * @see #RobocodeEngine(File) * @see #close() * @since 1.6.2 */ public RobocodeEngine() { init(FileUtil.getCwd(), null); } /** * Creates a new RobocodeEngine for controlling Robocode. * * @param robocodeHome the root directory of Robocode, e.g. C:\Robocode. * @see #RobocodeEngine() * @see #close() * @since 1.6.2 */ public RobocodeEngine(File robocodeHome) { init(robocodeHome, null); } /** * @deprecated Since 1.6.2. Use {@link #RobocodeEngine(File)} and * {@link #addBattleListener(IBattleListener) addBattleListener()} instead. *

* Creates a new RobocodeEngine for controlling Robocode. * * @param robocodeHome the root directory of Robocode, e.g. C:\Robocode. * @param listener the listener that must receive the callbacks from this * RobocodeEngine. * @see #RobocodeEngine() * @see #RobocodeEngine(File) * @see #close() */ @Deprecated public RobocodeEngine(File robocodeHome, RobocodeListener listener) { init(robocodeHome, listener); } /** * @deprecated Since 1.6.2. Use {@link #RobocodeEngine()} and * {@link #addBattleListener(IBattleListener) addBattleListener()} instead. *

* Creates a new RobocodeEngine for controlling Robocode. The JAR file of * Robocode is used to determine the root directory of Robocode. * * @param listener the listener that must receive the callbacks from this * RobocodeEngine. * @see #RobocodeEngine() * @see #RobocodeEngine(File) * @see #close() */ @Deprecated public RobocodeEngine(RobocodeListener listener) { init(FileUtil.getCwd(), listener); } /** * {@inheritDoc} */ @Override protected void finalize() throws Throwable { try { // Make sure close() is called to prevent memory leaks close(); } finally { super.finalize(); } } @SuppressWarnings("deprecation") // We must still support deprecated RobocodeListener private void init(File robocodeHome, RobocodeListener listener) { File robotsDir = FileUtil.getRobotsDir(); if (robotsDir == null) { throw new RuntimeException("No valid robot directory is specified"); } else if (!(robotsDir.exists() && robotsDir.isDirectory())) { throw new RuntimeException('\'' + robotsDir.getAbsolutePath() + "' is not a valid robot directory"); } manager = new RobocodeManager(true); manager.setEnableGUI(false); try { FileUtil.setCwd(robocodeHome); } catch (IOException e) { System.err.println(e); return; } manager.initSecurity(true, System.getProperty("EXPERIMENTAL", "false").equals("true")); if (listener != null) { battleObserver = new BattleObserver(); battleObserver.listener = listener; manager.getBattleManager().addListener(battleObserver); } } /** * Adds a battle listener that must receive events occurring in battles. * * @param listener the battle listener that must retrieve the event from * the battles. * @see #removeBattleListener(IBattleListener) * @since 1.6.2 */ public void addBattleListener(IBattleListener listener) { manager.getBattleManager().addListener(listener); } /** * Removes a battle listener that has previously been added to this object. * * @param listener the battle listener that must be removed. * @see #addBattleListener(IBattleListener) * @since 1.6.2 */ public void removeBattleListener(IBattleListener listener) { manager.getBattleManager().removeListener(listener); } /** * Closes the RobocodeEngine and releases any allocated resources. * You should call this when you have finished using the RobocodeEngine. * This method automatically disposes the Robocode window if it open. */ public void close() { if (manager.isGUIEnabled()) { manager.getWindowManager().getRobocodeFrame().dispose(); } if (battleObserver != null) { manager.getBattleManager().removeListener(battleObserver); } if (manager != null) { manager.cleanup(); manager = null; } } /** * Returns the installed version of Robocode. * * @return the installed version of Robocode. */ public String getVersion() { return manager.getVersionManager().getVersion(); } /** * Shows or hides the Robocode window. * * @param visible {@code true} if the Robocode window must be set visible; * {@code false} otherwise. */ public void setVisible(boolean visible) { if (visible && !manager.isGUIEnabled()) { // The GUI must be enabled in order to show the window manager.setEnableGUI(true); // Set the Look and Feel (LAF) robocode.manager.LookAndFeelManager.setLookAndFeel(); } if (manager.isGUIEnabled()) { manager.getWindowManager().showRobocodeFrame(visible); manager.getProperties().setOptionsCommonShowResults(visible); } } /** * Returns all robots available from the local robot repository of Robocode. * These robots must exists in the /robocode/robots directory, and must be * compiled in advance. * * @return an array of all available robots from the local robot repository. * @see RobotSpecification * @see #getLocalRepository(String) */ public RobotSpecification[] getLocalRepository() { Repository robotRepository = manager.getRobotRepositoryManager().getRobotRepository(); List list = robotRepository.getRobotSpecificationsList(false, false, false, false, false, false); RobotSpecification robotSpecs[] = new RobotSpecification[list.size()]; for (int i = 0; i < robotSpecs.length; i++) { final FileSpecification specification = list.get(i); if (specification.isValid()) { robotSpecs[i] = new RobotSpecification(specification); } } return robotSpecs; } /** * Returns a selection of robots available from the local robot repository * of Robocode. These robots must exists in the /robocode/robots directory, * and must be compiled in advance. *

* Notice: If a specified robot cannot be found in the repository, it will * not be returned in the array of robots returned by this method. * * @param selectedRobotList a comma or space separated list of robots to * return. The full class name must be used for * specifying the individual robot, e.g. * "sample.Corners, sample.Crazy" * @return an array containing the available robots from the local robot * repository based on the selected robots specified with the * {@code selectedRobotList} parameter. * @see RobotSpecification * @see #getLocalRepository() * @since 1.6.2 */ public RobotSpecification[] getLocalRepository(String selectedRobotList) { RobotSpecification[] repository = getLocalRepository(); HashMap robotSpecMap = new HashMap(); for (RobotSpecification spec : repository) { robotSpecMap.put(spec.getNameAndVersion(), spec); } String[] selectedRobots = selectedRobotList.split("[\\s,;]+"); List selectedRobotSpecs = new ArrayList(); RobotSpecification spec; for (String robot : selectedRobots) { spec = robotSpecMap.get(robot); if (spec != null) { selectedRobotSpecs.add(spec); } } return selectedRobotSpecs.toArray(new RobotSpecification[selectedRobotSpecs.size()]); } /** * Runs the specified battle. * * @param battleSpecification the specification of the battle to play including the * participation robots. * @see #runBattle(BattleSpecification, boolean) * @see RobocodeListener#battleComplete(BattleSpecification, RobotResults[]) * @see RobocodeListener#battleMessage(String) * @see BattleSpecification * @see #getLocalRepository() */ public void runBattle(BattleSpecification battleSpecification) { this.battleSpecification = battleSpecification; manager.getBattleManager().startNewBattle(battleSpecification, false); } /** * Runs the specified battle. * * @param battleSpecification the specification of the battle to run including the * participating robots. * @param waitTillOver will block caller till end of battle if set * @see #runBattle(BattleSpecification) * @see RobocodeListener#battleComplete(BattleSpecification, RobotResults[]) * @see RobocodeListener#battleMessage(String) * @see BattleSpecification * @see #getLocalRepository() * @since 1.6.2 */ public void runBattle(BattleSpecification battleSpecification, boolean waitTillOver) { this.battleSpecification = battleSpecification; manager.getBattleManager().startNewBattle(battleSpecification, waitTillOver); } /** * Will block caller until current battle is over * @see #runBattle(BattleSpecification) * @see #runBattle(BattleSpecification, boolean) * @since 1.6.2 */ public void waitTillBattleOver() { manager.getBattleManager().waitTillOver(); } /** * Aborts the current battle if it is running. * * @see #runBattle(BattleSpecification) * @see RobocodeListener#battleAborted(BattleSpecification) */ public void abortCurrentBattle() { manager.getBattleManager().stop(true); } /** * Print out all running threads to standard system out. * * @since 1.6.2 */ public static void printRunningThreads() { ThreadGroup currentGroup = Thread.currentThread().getThreadGroup(); if (currentGroup == null) { return; } while (currentGroup.getParent() != null) { currentGroup = currentGroup.getParent(); } ThreadGroup groups[] = new ThreadGroup[256]; Thread threads[] = new Thread[256]; int numGroups = currentGroup.enumerate(groups, true); for (int i = 0; i < numGroups; i++) { currentGroup = groups[i]; if (currentGroup.isDaemon()) { System.out.print(" "); } else { System.out.print("* "); } System.out.println("In group: " + currentGroup.getName()); int numThreads = currentGroup.enumerate(threads); for (int j = 0; j < numThreads; j++) { if (threads[j].isDaemon()) { System.out.print(" "); } else { System.out.print("* "); } System.out.println(threads[j].getName()); } System.out.println("---------------"); } } /** * Registered only if listener in not null. */ private class BattleObserver extends BattleAdaptor { @SuppressWarnings("deprecation") // We must still support deprecated RobocodeListener private RobocodeListener listener; @SuppressWarnings("deprecation") // We must still support deprecated RobocodeListener @Override public void onBattleFinished(BattleFinishedEvent event) { if (event.isAborted()) { listener.battleAborted(battleSpecification); } } @SuppressWarnings("deprecation") // We must still support deprecated RobocodeListener @Override public void onBattleCompleted(BattleCompletedEvent event) { listener.battleComplete(battleSpecification, RobotResults.convertResults(event.getSortedResults())); } @SuppressWarnings("deprecation") // We must still support deprecated RobocodeListener @Override public void onBattleMessage(BattleMessageEvent event) { listener.battleMessage(event.getMessage()); } } } robocode/robocode/robocode/sound/0000755000175000017500000000000011124142462016361 5ustar lambylambyrobocode/robocode/robocode/sound/ISoundManager.java0000644000175000017500000000152011130241112021703 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.sound; import robocode.battle.events.BattleEventDispatcher; /** * @author Pavel Savara (original) */ public interface ISoundManager { void playThemeMusic(); void setBattleEventDispatcher(BattleEventDispatcher battleEventDispatcher); } robocode/robocode/robocode/sound/SoundManager.java0000644000175000017500000002547011130241112021604 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Luis Crespo * - Initial API and implementation * Flemming N. Larsen * - Integration into Robocode regarding controlling the sound from the Sound * Options and Command Line * - Bugfix: When enabling sounds on-the-fly when it was originally disabled, * the PlaySound caused a NullPointerException because the sounds field had * not been intialized yet. Therefore a getSounds() factory methods has * been added which allocated the SoundCache instance and initializes the * SoundManager if the sounds field is null * - The resources for the sound effects are now loaded from the properties * file * - Added support for playing and stopping music * - The init() method was replaced by a getMixer() factory method * - Extended playSound() to handle loops, and also checking if volume and/or * panning are supported before adjusting these * Titus Chen: * - Slight optimization with pan calculation in playBulletSound() *******************************************************************************/ package robocode.sound; import robocode.control.events.BattleAdaptor; import robocode.battle.events.BattleEventDispatcher; import robocode.control.events.BattleFinishedEvent; import robocode.control.events.BattleStartedEvent; import robocode.control.events.TurnEndedEvent; import robocode.control.snapshot.IBulletSnapshot; import robocode.control.snapshot.IRobotSnapshot; import robocode.manager.RobocodeManager; import robocode.manager.RobocodeProperties; import robocode.control.snapshot.RobotState; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.Clip; import javax.sound.sampled.FloatControl; import javax.sound.sampled.Mixer; /** * The sound manager is responsible of keeping a table of sound effects and * play the appropriate sound for each bullet or robot event that is supposed * to make any noise. * * @author Luis Crespo (original) * @author Flemming N. Larsen (contributor) * @author Titus Chen (contributor) */ public class SoundManager implements ISoundManager { // Cache containing sound clips private SoundCache sounds; // Access to properties private final RobocodeProperties properties; private BattleObserver battleObserver = null; private final RobocodeManager manager; /** * Constructs a new sound manager. * * @param manager the Robocode manager */ public SoundManager(RobocodeManager manager) { this.manager = manager; properties = manager.getProperties(); } /** * Returns the current mixer selected from the Robocode properties. * * @return the current Mixer instance */ public Mixer getMixer() { return findMixer(properties.getOptionsSoundMixer()); } /** * Returns the cache containing sound clips. * * @return a SoundCache instance */ private SoundCache getSounds() { if (sounds == null) { sounds = new SoundCache(getMixer()); // Sound effects sounds.addSound("gunshot", properties.getFileGunshotSfx(), 5); sounds.addSound("robot death", properties.getRobotDeathSfx(), 3); sounds.addSound("bullet hits robot", properties.getBulletHitsRobotSfx(), 3); sounds.addSound("bullet hits bullet", properties.getBulletHitsBulletSfx(), 2); sounds.addSound("robot collision", properties.getRobotCollisionSfx(), 2); sounds.addSound("wall collision", properties.getWallCollisionSfx(), 2); // Music sounds.addSound("theme", properties.getFileThemeMusic(), 1); sounds.addSound("background", properties.getFileBackgroundMusic(), 1); sounds.addSound("endOfBattle", properties.getFileEndOfBattleMusic(), 1); } return sounds; } /** * Iterates over the available mixers, looking for the one that matches a given * class name. * * @param mixerClassName the class name of the mixer to be used. * @return the requested mixer, if found. Otherwise, it returns null. */ private Mixer findMixer(String mixerClassName) { for (Mixer.Info mi : AudioSystem.getMixerInfo()) { Mixer m = AudioSystem.getMixer(mi); if (m.getClass().getSimpleName().equals(mixerClassName)) { return m; } } return null; } /** * Performs shutdown, by liberating the sound table */ public void dispose() { if (sounds != null) { // Do not call getSounds()! sounds.clear(); } } /** * Plays a specific sound at a given volume, panning and loop count * * @param key the sound name, as stored in the sound table * @param pan panning to be used (-1=left, 0=middle, +1=right) * @param volume volume to be used, from 0 to 1 * @param loop the number of times to loop the sound */ private void playSound(Object key, float pan, float volume, int loop) { Clip c = getSounds().getSound(key); if (c == null) { return; } if (properties.getOptionsSoundEnableMixerPan() && c.isControlSupported(FloatControl.Type.PAN)) { FloatControl panCtrl = (FloatControl) c.getControl(FloatControl.Type.PAN); panCtrl.setValue(pan); } if (properties.getOptionsSoundEnableMixerVolume() && c.isControlSupported(FloatControl.Type.MASTER_GAIN)) { FloatControl volCtrl = (FloatControl) c.getControl(FloatControl.Type.MASTER_GAIN); float min = volCtrl.getMinimum() / 4; if (volume != 1) { volCtrl.setValue(min * (1 - volume)); } } c.loop(loop); } /** * Plays a specific sound at a given panning with max. volume and without looping. * * @param key the sound name, as stored in the sound table * @param pan panning to be used (-1=left, 0=middle, +1=right) */ private void playSound(Object key, float pan) { playSound(key, pan, 1, 0); } /** * Plays a specific piece of music with a given loop count with no panning and * max. volume. * * @param key the sound name, as stored in the sound table * @param loop the number of times to loop the music */ private void playMusic(Object key, int loop) { playSound(key, 0, 1, loop); } /** * Plays a bullet sound depending on the bullet's state * * @param bp the bullet peer * @param battleFieldWidth the width of the battle field used for panning. */ public void playBulletSound(IBulletSnapshot bp, int battleFieldWidth) { float pan = 0; if (properties.getOptionsSoundEnableMixerPan()) { pan = calcPan((float) bp.getPaintX(), battleFieldWidth); } switch (bp.getState()) { case FIRED: if (properties.getOptionsSoundEnableGunshot()) { playSound("gunshot", pan, calcBulletVolume(bp), 0); } break; case HIT_VICTIM: if (properties.getOptionsSoundEnableBulletHit()) { playSound("bullet hits robot", pan); } break; case HIT_BULLET: if (properties.getOptionsSoundEnableBulletHit()) { playSound("bullet hits bullet", pan); } break; case HIT_WALL: // Currently, no sound break; case EXPLODED: if (properties.getOptionsSoundEnableRobotDeath()) { playSound("robot death", pan); } break; } } /** * Plays a robot sound depending on the robot's state * * @param robotPeer the robot peer * @param battleFieldWidth the battle field width used for panning */ public void playRobotSound(IRobotSnapshot robotPeer, int battleFieldWidth) { float pan = 0; if (properties.getOptionsSoundEnableMixerPan()) { pan = calcPan((float) robotPeer.getX(), battleFieldWidth); } switch (robotPeer.getState()) { case HIT_ROBOT: if (properties.getOptionsSoundEnableRobotCollision()) { playSound("robot collision", pan); } break; case HIT_WALL: if (properties.getOptionsSoundEnableWallCollision()) { playSound("wall collision", pan); } break; } } /** * Plays the theme music once. */ public void playThemeMusic() { playMusic("theme", 0); } /** * Plays the background music, which is looping forever until stopped. */ public void playBackgroundMusic() { playMusic("background", -1); } /** * Stops the background music. */ public void stopBackgroundMusic() { Clip c = getSounds().getSound("background"); if (c != null) { c.stop(); } } /** * Plays the end of battle music once. */ public void playEndOfBattleMusic() { playMusic("endOfBattle", 0); } /** * Determines pan based on the relative position to the battlefield's width * * @param x the bullet or robot position * @param width the battlefield's width * @return the panning value, ranging from -1 to +1 */ private float calcPan(float x, float width) { float semiWidth = width / 2; return (x - semiWidth) / semiWidth; } /** * Determines volume based on the bullets's energy * * @param bp the bullet peer * @return the volume value, ranging from 0 to 1 */ private float calcBulletVolume(IBulletSnapshot bp) { return (float) (bp.getPower() / robocode.Rules.MAX_BULLET_POWER); } public void setBattleEventDispatcher(BattleEventDispatcher battleEventDispatcher) { if (battleObserver != null) { battleObserver.dispose(); } battleObserver = new BattleObserver(battleEventDispatcher); } private class BattleObserver extends BattleAdaptor { final robocode.battle.events.BattleEventDispatcher dispatcher; public BattleObserver(BattleEventDispatcher dispatcher) { this.dispatcher = dispatcher; dispatcher.addListener(this); } public void dispose() { dispatcher.removeListener(this); } @Override public void onBattleStarted(BattleStartedEvent event) { playBackgroundMusic(); } @Override public void onBattleFinished(BattleFinishedEvent event) { stopBackgroundMusic(); playEndOfBattleMusic(); } @Override public void onTurnEnded(TurnEndedEvent event) { int battleFieldWidth = manager.getBattleManager().getBattleProperties().getBattlefieldWidth(); for (IBulletSnapshot bp : event.getTurnSnapshot().getBullets()) { if (bp.getFrame() == 0) { playBulletSound(bp, battleFieldWidth); } } boolean playedRobotHitRobot = false; for (IRobotSnapshot rp : event.getTurnSnapshot().getRobots()) { // Make sure that robot-hit-robot events do not play twice (one per colliding robot) if (rp.getState() == RobotState.HIT_ROBOT) { if (playedRobotHitRobot) { continue; } playedRobotHitRobot = true; } playRobotSound(rp, battleFieldWidth); } } } } robocode/robocode/robocode/sound/SoundCache.java0000644000175000017500000001452711130241112021236 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Luis Crespo * - Initial API and implementation * Flemming N. Larsen * - Updated to use methods from the Logger, which replaces logger methods * that have been (re)moved from the robocode.util.Utils class * - The addSound() will now return if the resource name is not specified * - Improved the error message in addSound() if the line is unavailable *******************************************************************************/ package robocode.sound; import robocode.io.Logger; import javax.sound.sampled.*; import java.io.IOException; import java.net.URL; import java.util.HashMap; import java.util.Map; /** * SoundCache maintains a table of sound clips. More than one instance of the same * sample can be stored, so a given sound effect can be played more than once * symultaneously. * * @author Luis Crespo (original) * @author Flemming N. Larsen (contributor) */ public class SoundCache { /** * Table containing all sound clips */ private final Map soundTable; /** * Mixer used for creating clip instances */ private final Mixer mixer; /** * Holds data, length and format for a given sound effect, which can be used to create * multiple instances of the same clip. */ private static class SoundData { private final AudioFormat format; private final int length; private final byte[] byteData; private SoundData(AudioInputStream ais) throws IOException { int bytesRead, pos; format = ais.getFormat(); length = (int) (ais.getFrameLength() * format.getFrameSize()); byteData = new byte[length]; pos = 0; do { bytesRead = ais.read(byteData, pos, length - pos); if (bytesRead > 0) { pos += bytesRead; } } while (bytesRead > 0 && pos < length); ais.close(); } } /** * Holds an array of clips from the same sample stream, and takes care of * returning the next available clip. If all clips are active, the least * recently used clip will be returned. */ private static class ClipClones { private final Clip[] clips; private int idx; private ClipClones(Mixer mixer, SoundData soundData, int size) throws LineUnavailableException { idx = 0; clips = new Clip[size]; DataLine.Info info = new DataLine.Info(Clip.class, soundData.format); if (!AudioSystem.isLineSupported(info)) { throw new LineUnavailableException("Required data line is not supported by the audio system"); } for (int i = 0; i < size; i++) { clips[i] = (Clip) mixer.getLine(info); clips[i].open(soundData.format, soundData.byteData, 0, soundData.length); } } private void dispose() { for (Clip c : clips) { c.close(); } } private Clip next() { Clip c = clips[idx]; idx = (idx + 1) % clips.length; c.stop(); c.setFramePosition(0); return c; } } /** * Constructs a sound cache to hold sound clips that is created based on the * specified mixer. * * @param mixer the mixer to be used for creating the clip instances */ public SoundCache(Mixer mixer) { this.mixer = mixer; soundTable = new HashMap(); } /** * Adds a number of clip clones for a given resource holding the audio data. * If there is any error, the method returns silently, and clip instances will * not be found later for the provided key. * * @param key the key to be used for later retrieval of the sound * @param resourceName the resource holding the audio data * @param numClones the number of copies of the clip to be created */ public void addSound(Object key, String resourceName, int numClones) { if (mixer == null || resourceName == null || (resourceName.trim().length() == 0)) { return; } SoundData data = createSoundData(resourceName); if (data == null) { return; } ClipClones clones; try { clones = new ClipClones(mixer, data, numClones); soundTable.put(key, clones); } catch (LineUnavailableException e) { Logger.logError( "The audio mixer " + mixer.getMixerInfo().getName() + " does not support the audio format of the sound clip: " + resourceName); } } /** * Creates an instance of SoundData, to be used later for creating the clip clones. * * @param resourceName the name of the resource holding the audio data * @return the newly created sound data */ private SoundData createSoundData(String resourceName) { SoundData data; URL url = ClassLoader.class.getResource(resourceName); if (url == null) { Logger.logError("Could not load sound because of invalid resource name: " + resourceName); return null; } try { AudioInputStream ais = AudioSystem.getAudioInputStream(url); data = new SoundData(ais); } catch (Exception e) { Logger.logError("Error while reading sound from resource: " + resourceName, e); data = null; } return data; } /** * Gets the next available clip instance of a given sound. If all clips for that * sound are active (playing), the least recently used will be returned. * * @param key the key that was used when adding the sound * @return a clip instance ready to be played through Clip.start() */ public Clip getSound(Object key) { ClipClones clones = soundTable.get(key); if (clones == null) { return null; } return clones.next(); } /** * Removes all clip copies of a given sound, closing all its dependent resources * * @param key the key that was used when adding the sound */ public void removeSound(Object key) { ClipClones clones = soundTable.get(key); if (clones == null) { return; } clones.dispose(); soundTable.remove(key); } /** * Empties all clips from the sound cache */ public void clear() { for (ClipClones clones : soundTable.values()) { clones.dispose(); } soundTable.clear(); } } robocode/robocode/robocode/package.html0000644000175000017500000000012011006202516017477 0ustar lambylamby Robot API used for writing robots for Robocode robocode/robocode/robocode/recording/0000755000175000017500000000000011125256070017207 5ustar lambylambyrobocode/robocode/robocode/recording/BattleRecordInfo.java0000644000175000017500000002477411130241112023241 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara & Flemming N. Larsen * - Initial implementation *******************************************************************************/ package robocode.recording; import robocode.BattleResults; import robocode.BattleRules; import robocode.battle.BattleProperties; import robocode.common.IXmlSerializable; import robocode.common.XmlReader; import robocode.common.XmlWriter; import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; import java.util.Dictionary; import java.util.List; /** * @author Pavel Savara (original) * @author Flemming N. Larsen (original) */ public class BattleRecordInfo implements Serializable, IXmlSerializable { private static final long serialVersionUID = 1L; public int robotCount; public int roundsCount; public BattleRules battleRules; public Integer[] turnsInRounds; public List results; public void writeXml(XmlWriter writer, Dictionary options) throws IOException { writer.startElement("recordInfo"); { writer.writeAttribute("robotCount", robotCount); writer.writeAttribute("roundsCount", roundsCount); writer.writeAttribute("ver", serialVersionUID); writer.startElement("rules"); { writer.writeAttribute("battlefieldWidth", battleRules.getBattlefieldWidth()); writer.writeAttribute("battlefieldHeight", battleRules.getBattlefieldHeight()); writer.writeAttribute("numRounds", battleRules.getNumRounds()); writer.writeAttribute("gunCoolingRate", battleRules.getGunCoolingRate()); writer.writeAttribute("inactivityTime", battleRules.getInactivityTime()); writer.writeAttribute("ver", serialVersionUID); } writer.endElement(); writer.startElement("rounds"); { for (int n : turnsInRounds) { writer.startElement("turns"); { writer.writeAttribute("value", Integer.toString(n)); } writer.endElement(); } } writer.endElement(); if (results != null) { writer.startElement("results"); { for (BattleResults result : results) { new BattleResultsWrapper(result).writeXml(writer, options); } } writer.endElement(); } } writer.endElement(); } public XmlReader.Element readXml(XmlReader reader) { return reader.expect("recordInfo", new XmlReader.Element() { public IXmlSerializable read(XmlReader reader) { final BattleRecordInfo recordInfo = new BattleRecordInfo(); reader.expect("robotCount", new XmlReader.Attribute() { public void read(String value) { recordInfo.robotCount = Integer.parseInt(value); } }); reader.expect("roundsCount", new XmlReader.Attribute() { public void read(String value) { recordInfo.roundsCount = Integer.parseInt(value); } }); new BattleRulesWrapper(recordInfo).readXml(reader); reader.expect("rounds", new XmlReader.ListElement() { final ArrayList ints = new ArrayList(); public IXmlSerializable read(XmlReader reader) { // prototype return new IntValue("turns"); } public void add(IXmlSerializable child) { ints.add(((IntValue) child).intValue); } public void close() { recordInfo.turnsInRounds = new Integer[ints.size()]; ints.toArray(recordInfo.turnsInRounds); } }); reader.expect("results", new XmlReader.ListElement() { public IXmlSerializable read(XmlReader reader) { recordInfo.results = new ArrayList(); // prototype return new BattleResultsWrapper(); } public void add(IXmlSerializable child) { recordInfo.results.add((BattleResults) child); } public void close() {} }); return recordInfo; } }); } public class IntValue implements IXmlSerializable { IntValue(String name) { this.name = name; } private final String name; public int intValue; public void writeXml(XmlWriter writer, Dictionary options) throws IOException {} public XmlReader.Element readXml(XmlReader reader) { return reader.expect(name, new XmlReader.Element() { public IXmlSerializable read(XmlReader reader) { final IntValue recordInfo = new IntValue(name); reader.expect("value", new XmlReader.Attribute() { public void read(String value) { recordInfo.intValue = Integer.parseInt(value); } }); return recordInfo; } }); } } /** * This class is used for wrapping a robocode.BattleResults object and provides * methods for XML serialization that are hidden from the BattleResults class, * which is a part of the public Robot API for Robocode. * * @author Flemming N. Larsen (original) */ class BattleResultsWrapper extends BattleResults implements IXmlSerializable { private static final long serialVersionUID = BattleResults.serialVersionUID; public BattleResultsWrapper() { super(null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); } public BattleResultsWrapper(BattleResults results) { super(results.getTeamLeaderName(), results.getRank(), results.getScore(), results.getSurvival(), results.getLastSurvivorBonus(), results.getBulletDamage(), results.getBulletDamageBonus(), results.getRamDamage(), results.getRamDamageBonus(), results.getFirsts(), results.getSeconds(), results.getThirds()); } public void writeXml(XmlWriter writer, Dictionary options) throws IOException { writer.startElement("result"); { writer.writeAttribute("teamLeaderName", teamLeaderName); writer.writeAttribute("rank", rank); writer.writeAttribute("score", score); writer.writeAttribute("survival", survival); writer.writeAttribute("lastSurvivorBonus", lastSurvivorBonus); writer.writeAttribute("bulletDamage", bulletDamage); writer.writeAttribute("bulletDamageBonus", bulletDamageBonus); writer.writeAttribute("ramDamage", ramDamage); writer.writeAttribute("ramDamageBonus", ramDamageBonus); writer.writeAttribute("firsts", firsts); writer.writeAttribute("seconds", seconds); writer.writeAttribute("thirds", thirds); writer.writeAttribute("ver", serialVersionUID); } writer.endElement(); } public XmlReader.Element readXml(XmlReader reader) { return reader.expect("result", new XmlReader.Element() { public IXmlSerializable read(XmlReader reader) { final BattleResultsWrapper rules = new BattleResultsWrapper(); reader.expect("teamLeaderName", new XmlReader.Attribute() { public void read(String value) { rules.teamLeaderName = value; } }); reader.expect("rank", new XmlReader.Attribute() { public void read(String value) { rules.rank = Integer.parseInt(value); } }); reader.expect("score", new XmlReader.Attribute() { public void read(String value) { rules.score = Double.parseDouble(value); } }); reader.expect("survival", new XmlReader.Attribute() { public void read(String value) { rules.survival = Double.parseDouble(value); } }); reader.expect("lastSurvivorBonus", new XmlReader.Attribute() { public void read(String value) { rules.lastSurvivorBonus = Double.parseDouble(value); } }); reader.expect("bulletDamage", new XmlReader.Attribute() { public void read(String value) { rules.bulletDamage = Double.parseDouble(value); } }); reader.expect("bulletDamageBonus", new XmlReader.Attribute() { public void read(String value) { rules.bulletDamageBonus = Double.parseDouble(value); } }); reader.expect("ramDamage", new XmlReader.Attribute() { public void read(String value) { rules.ramDamage = Double.parseDouble(value); } }); reader.expect("ramDamageBonus", new XmlReader.Attribute() { public void read(String value) { rules.ramDamageBonus = Double.parseDouble(value); } }); reader.expect("firsts", new XmlReader.Attribute() { public void read(String value) { rules.firsts = Integer.parseInt(value); } }); reader.expect("seconds", new XmlReader.Attribute() { public void read(String value) { rules.seconds = Integer.parseInt(value); } }); reader.expect("thirds", new XmlReader.Attribute() { public void read(String value) { rules.thirds = Integer.parseInt(value); } }); return rules; } }); } } class BattleRulesWrapper implements IXmlSerializable { BattleRulesWrapper(BattleRecordInfo recinfo) { this.recinfo = recinfo; } final BattleProperties props = new BattleProperties(); BattleRecordInfo recinfo; public void writeXml(XmlWriter writer, Dictionary options) throws IOException {} public XmlReader.Element readXml(XmlReader reader) { return reader.expect("rules", new XmlReader.ElementClose() { public IXmlSerializable read(XmlReader reader) { reader.expect("battlefieldWidth", new XmlReader.Attribute() { public void read(String value) { props.setBattlefieldWidth(Integer.parseInt(value)); } }); reader.expect("battlefieldHeight", new XmlReader.Attribute() { public void read(String value) { props.setBattlefieldHeight(Integer.parseInt(value)); } }); reader.expect("numRounds", new XmlReader.Attribute() { public void read(String value) { props.setNumRounds(Integer.parseInt(value)); } }); reader.expect("inactivityTime", new XmlReader.Attribute() { public void read(String value) { props.setInactivityTime(Integer.parseInt(value)); } }); reader.expect("gunCoolingRate", new XmlReader.Attribute() { public void read(String value) { props.setGunCoolingRate(Double.parseDouble(value)); } }); return BattleRulesWrapper.this; } public void close() { recinfo.battleRules = new BattleRules(props); } }); } } } robocode/robocode/robocode/recording/BattleRecorder.java0000644000175000017500000000537511130241112022750 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara & Flemming N. Larsen * - Initial implementation *******************************************************************************/ package robocode.recording; import robocode.control.events.BattleAdaptor; import robocode.battle.events.BattleEventDispatcher; import robocode.control.events.*; import java.util.Arrays; /** * @author Pavel Savara (original) * @author Flemming N. Larsen (original) */ public class BattleRecorder { private final RecordManager recordmanager; private BattleObserver battleObserver; public BattleRecorder(RecordManager recordmanager) { this.recordmanager = recordmanager; } public void attachRecorder(BattleEventDispatcher battleEventDispatcher) { if (battleObserver != null) { battleObserver.dispose(); } battleObserver = new BattleObserver(battleEventDispatcher); } public void detachRecorder() { if (battleObserver != null) { battleObserver.dispose(); } } private class BattleObserver extends BattleAdaptor { private final robocode.battle.events.BattleEventDispatcher dispatcher; private int currentTurn; private int currentRound; public BattleObserver(BattleEventDispatcher dispatcher) { this.dispatcher = dispatcher; dispatcher.addListener(this); } public void dispose() { dispatcher.removeListener(this); recordmanager.cleanupStreams(); } @Override public void onBattleStarted(BattleStartedEvent event) { recordmanager.cleanupStreams(); recordmanager.createRecordInfo(event.getBattleRules(), event.getRobotsCount()); currentRound = 0; currentTurn = 0; } @Override public void onBattleFinished(BattleFinishedEvent event) { recordmanager.cleanupStreams(); } @Override public void onBattleCompleted(BattleCompletedEvent event) { recordmanager.updateRecordInfoResults(Arrays.asList(event.getIndexedResults())); } @Override public void onRoundStarted(RoundStartedEvent event) { currentRound = event.getRound(); currentTurn = 0; recordmanager.writeTurn(event.getStartSnapshot(), currentRound, currentTurn); } @Override public void onTurnEnded(TurnEndedEvent event) { currentTurn = event.getTurnSnapshot().getTurn(); recordmanager.writeTurn(event.getTurnSnapshot(), currentRound, currentTurn); } } } robocode/robocode/robocode/recording/BattlePlayer.java0000644000175000017500000000776311130241112022442 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara & Flemming N. Larsen * - Initial implementation *******************************************************************************/ package robocode.recording; import robocode.BattleResults; import robocode.battle.BaseBattle; import robocode.battle.events.BattleEventDispatcher; import robocode.battle.snapshot.RobotSnapshot; import robocode.control.events.*; import robocode.control.snapshot.IRobotSnapshot; import robocode.control.snapshot.ITurnSnapshot; import robocode.manager.RobocodeManager; /** * @author Pavel Savara (original) * @author Flemming N. Larsen (original) */ public final class BattlePlayer extends BaseBattle { private final RecordManager recordManager; private boolean[] paint; public BattlePlayer(RobocodeManager manager, RecordManager recordManager, BattleEventDispatcher eventDispatcher) { super(manager, eventDispatcher, false); this.recordManager = recordManager; } @Override protected void initializeBattle() { super.initializeBattle(); battleRules = recordManager.recordInfo.battleRules; paint = new boolean[recordManager.recordInfo.robotCount]; eventDispatcher.onBattleStarted(new BattleStartedEvent(battleRules, recordManager.recordInfo.robotCount, true)); if (isPaused()) { eventDispatcher.onBattlePaused(new BattlePausedEvent()); } } @Override protected void finalizeBattle() { boolean aborted = recordManager.recordInfo.results == null || isAborted(); eventDispatcher.onBattleFinished(new BattleFinishedEvent(aborted)); if (!aborted) { eventDispatcher.onBattleCompleted( new BattleCompletedEvent(battleRules, recordManager.recordInfo.results.toArray(new BattleResults[] {}))); } super.finalizeBattle(); cleanup(); } @Override protected void initializeRound() { super.initializeRound(); final ITurnSnapshot snapshot = recordManager.readSnapshot(currentTime); if (snapshot != null) { eventDispatcher.onRoundStarted(new RoundStartedEvent(snapshot, getRoundNum())); } } @Override protected void finalizeRound() { super.finalizeRound(); eventDispatcher.onRoundEnded(new RoundEndedEvent(getRoundNum(), getTime())); } @Override protected void initializeTurn() { super.initializeTurn(); eventDispatcher.onTurnStarted(new TurnStartedEvent()); } @Override protected void finalizeTurn() { final ITurnSnapshot snapshot = recordManager.readSnapshot(currentTime); if (snapshot != null) { final IRobotSnapshot[] robots = snapshot.getRobots(); for (int i = 0; i < robots.length; i++) { RobotSnapshot robot = (RobotSnapshot) robots[i]; robot.overridePaintEnabled(paint[i]); } eventDispatcher.onTurnEnded(new TurnEndedEvent(snapshot)); } super.finalizeTurn(); } @Override protected boolean isRoundOver() { final boolean end = getTime() >= recordManager.recordInfo.turnsInRounds[getRoundNum()] - 1; if (end) { if (recordManager.recordInfo.turnsInRounds.length > getRoundNum() && recordManager.recordInfo.turnsInRounds[getRoundNum()] == 0) { isAborted = true; } } return (isAborted || end); } public void setPaintEnabled(int robotIndex, boolean enable) { sendCommand(new EnableRobotPaintCommand(robotIndex, enable)); } private class EnableRobotPaintCommand extends RobotCommand { final boolean enablePaint; EnableRobotPaintCommand(int robotIndex, boolean enablePaint) { super(robotIndex); this.enablePaint = enablePaint; } public void execute() { paint[robotIndex] = enablePaint; } } } robocode/robocode/robocode/recording/BattleRecordFormat.java0000644000175000017500000000124711130241112023564 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen * - Initial implementation *******************************************************************************/ package robocode.recording; public enum BattleRecordFormat { BINARY, BINARY_ZIP, XML } robocode/robocode/robocode/recording/IRecordManager.java0000644000175000017500000000221311130241112022655 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara & Flemming N. Larsen * - Initial implementation *******************************************************************************/ package robocode.recording; import robocode.battle.IBattle; import robocode.battle.events.BattleEventDispatcher; /** * @author Pavel Savara (original) * @author Flemming N. Larsen (original) */ public interface IRecordManager { void attachRecorder(BattleEventDispatcher battleEventDispatcher); void detachRecorder(); IBattle createPlayer(BattleEventDispatcher battleEventDispatcher); void saveRecord(String fileName, BattleRecordFormat format); void loadRecord(String fileName, BattleRecordFormat format); boolean hasRecord(); } robocode/robocode/robocode/recording/RecordManager.java0000644000175000017500000003017511130241112022554 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.recording; import robocode.BattleResults; import robocode.BattleRules; import robocode.battle.IBattle; import robocode.battle.events.BattleEventDispatcher; import robocode.battle.snapshot.TurnSnapshot; import robocode.common.IXmlSerializable; import robocode.common.XmlReader; import robocode.common.XmlWriter; import robocode.control.snapshot.ITurnSnapshot; import static robocode.io.Logger.logError; import robocode.manager.RobocodeManager; import java.io.*; import java.nio.charset.Charset; import java.util.Dictionary; import java.util.Hashtable; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; /** * @author Pavel Savara (original) */ public class RecordManager implements IRecordManager { private File tempFile; private final RobocodeManager manager; private BattleRecorder recorder; public BattleRecordInfo recordInfo; private FileOutputStream fileWriteStream; private BufferedOutputStream bufferedWriteStream; private ObjectOutputStream objectWriteStream; private FileInputStream fileReadStream; private BufferedInputStream bufferedReadStream; private ObjectInputStream objectReadStream; public RecordManager(RobocodeManager manager) { this.manager = manager; recorder = new BattleRecorder(this); } protected void finalize() throws Throwable { try { cleanup(); } finally { super.finalize(); } } private void cleanup() { cleanupStreams(); if (tempFile != null && tempFile.exists()) { // noinspection ResultOfMethodCallIgnored tempFile.delete(); tempFile = null; } recordInfo = null; } public void cleanupStreams() { cleanupStream(objectWriteStream); objectWriteStream = null; cleanupStream(bufferedWriteStream); bufferedWriteStream = null; cleanupStream(fileWriteStream); fileWriteStream = null; cleanupStream(objectReadStream); objectReadStream = null; cleanupStream(bufferedReadStream); bufferedReadStream = null; cleanupStream(fileReadStream); fileReadStream = null; } private void cleanupStream(Object stream) { if (stream instanceof Flushable) { try { ((Flushable) stream).flush(); } catch (IOException e) { logError(e); } } if (stream instanceof Closeable) { try { ((Closeable) stream).close(); } catch (IOException e) { logError(e); } } } public void attachRecorder(BattleEventDispatcher battleEventDispatcher) { recorder.attachRecorder(battleEventDispatcher); } public void detachRecorder() { recorder.detachRecorder(); } public IBattle createPlayer(BattleEventDispatcher battleEventDispatcher) { prepareInputStream(); return new BattlePlayer(manager, this, battleEventDispatcher); } private void createTempFile() { try { if (tempFile == null) { tempFile = File.createTempFile("robocode-battle-records", ".tmp"); tempFile.deleteOnExit(); } else { // noinspection ResultOfMethodCallIgnored tempFile.delete(); // noinspection ResultOfMethodCallIgnored tempFile.createNewFile(); } } catch (IOException e) { logError(e); throw new Error("Temp file creation failed", e); } } public void prepareInputStream() { try { fileReadStream = new FileInputStream(tempFile); bufferedReadStream = new BufferedInputStream(fileReadStream); objectReadStream = new ObjectInputStream(bufferedReadStream); } catch (FileNotFoundException e) { logError(e); } catch (IOException e) { logError(e); } } public ITurnSnapshot readSnapshot(int currentTime) { if (objectReadStream == null) { return null; } try { // TODO implement seek to currentTime, warn you. turns don't have same size in bytes return (ITurnSnapshot) objectReadStream.readObject(); } catch (EOFException e) { logError(e); return null; } catch (Exception e) { logError(e); return null; } } public void loadRecord(String recordFilename, BattleRecordFormat format) { FileInputStream fis = null; BufferedInputStream bis = null; ZipInputStream zis = null; ObjectInputStream ois = null; FileOutputStream fos = null; BufferedOutputStream bos = null; ObjectOutputStream oos = null; try { createTempFile(); fis = new FileInputStream(recordFilename); bis = new BufferedInputStream(fis, 1024 * 1024); if (format == BattleRecordFormat.BINARY) { ois = new ObjectInputStream(bis); } else if (format == BattleRecordFormat.BINARY_ZIP) { zis = new ZipInputStream(bis); zis.getNextEntry(); ois = new ObjectInputStream(zis); } if (format == BattleRecordFormat.BINARY || format == BattleRecordFormat.BINARY_ZIP) { recordInfo = (BattleRecordInfo) ois.readObject(); if (recordInfo.turnsInRounds != null) { fos = new FileOutputStream(tempFile); bos = new BufferedOutputStream(fos, 1024 * 1024); oos = new ObjectOutputStream(bos); for (int i = 0; i < recordInfo.turnsInRounds.length; i++) { for (int j = recordInfo.turnsInRounds[i] - 1; j >= 0; j--) { try { ITurnSnapshot turn = (ITurnSnapshot) ois.readObject(); oos.writeObject(turn); } catch (ClassNotFoundException e) { logError(e); } } } } } else { final RecordRoot root = new RecordRoot(); fos = new FileOutputStream(tempFile); bos = new BufferedOutputStream(fos, 1024 * 1024); root.oos = new ObjectOutputStream(bos); XmlReader.deserialize(bis, root); if (root.lastException != null) { logError(root.lastException); } recordInfo = root.recordInfo; } } catch (IOException e) { logError(e); createTempFile(); recordInfo = null; } catch (ClassNotFoundException e) { logError(e); createTempFile(); recordInfo = null; } finally { cleanupStream(oos); cleanupStream(bos); cleanupStream(fos); cleanupStream(ois); cleanupStream(zis); cleanupStream(bis); cleanupStream(fis); } } private class RecordRoot implements IXmlSerializable { public RecordRoot() { me = this; } public ObjectOutputStream oos; public IOException lastException; public final RecordRoot me; public BattleRecordInfo recordInfo; public void writeXml(XmlWriter writer, Dictionary options) throws IOException {} public XmlReader.Element readXml(XmlReader reader) { return reader.expect("record", new XmlReader.Element() { public IXmlSerializable read(XmlReader reader) { final XmlReader.Element element = (new BattleRecordInfo()).readXml(reader); reader.expect("recordInfo", new XmlReader.Element() { public IXmlSerializable read(XmlReader reader) { recordInfo = (BattleRecordInfo) element.read(reader); return recordInfo; } }); reader.expect("turns", new XmlReader.ListElement() { public IXmlSerializable read(XmlReader reader) { // prototype return new TurnSnapshot(); } public void add(IXmlSerializable child) { try { me.oos.writeObject(child); } catch (IOException e) { me.lastException = e; } } public void close() {} }); return me; } }); } } public void saveRecord(String recordFilename, BattleRecordFormat format) { FileOutputStream fos = null; BufferedOutputStream bos = null; ZipOutputStream zos = null; ObjectOutputStream oos = null; OutputStreamWriter osw = null; XmlWriter xwr = null; FileInputStream fis = null; BufferedInputStream bis = null; ObjectInputStream ois = null; Hashtable xmlOptions; try { fos = new FileOutputStream(recordFilename); bos = new BufferedOutputStream(fos, 1024 * 1024); if (format == BattleRecordFormat.BINARY) { oos = new ObjectOutputStream(bos); } else if (format == BattleRecordFormat.BINARY_ZIP) { zos = new ZipOutputStream(bos); zos.putNextEntry(new ZipEntry("robocode.br")); oos = new ObjectOutputStream(zos); } else if (format == BattleRecordFormat.XML) { final Charset utf8 = Charset.forName("UTF-8"); osw = new OutputStreamWriter(bos, utf8); xwr = new XmlWriter(osw, true); } if (format == BattleRecordFormat.BINARY || format == BattleRecordFormat.BINARY_ZIP) { oos.writeObject(recordInfo); } else if (format == BattleRecordFormat.XML) { xmlOptions = new Hashtable(); xwr.startDocument(); xwr.startElement("record"); xwr.writeAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); xwr.writeAttribute("xsi:noNamespaceSchemaLocation", "battleRecord.xsd"); recordInfo.writeXml(xwr, xmlOptions); xwr.startElement("turns"); } if (recordInfo.turnsInRounds != null) { fis = new FileInputStream(tempFile); bis = new BufferedInputStream(fis, 1024 * 1024); ois = new ObjectInputStream(bis); /* if (format == BattleRecordFormat.XML) { xmlOptions.put("skipDetails", true); }*/ for (int i = 0; i < recordInfo.turnsInRounds.length; i++) { if (recordInfo.turnsInRounds[i] > 0) { for (int j = 0; j <= recordInfo.turnsInRounds[i] - 1; j++) { try { TurnSnapshot turn = (TurnSnapshot) ois.readObject(); if (j != turn.getTurn()) { throw new Error("Something rotten"); } if (format == BattleRecordFormat.BINARY || format == BattleRecordFormat.BINARY_ZIP) { oos.writeObject(turn); } else if (format == BattleRecordFormat.XML) { turn.writeXml(xwr, null); } } catch (ClassNotFoundException e) { logError(e); } } if (format == BattleRecordFormat.BINARY || format == BattleRecordFormat.BINARY_ZIP) { oos.flush(); } else if (format == BattleRecordFormat.XML) { osw.flush(); } bos.flush(); fos.flush(); } } if (format == BattleRecordFormat.XML) { xwr.endElement(); // turns xwr.endElement(); // record osw.flush(); } } } catch (IOException e) { logError(e); recorder = new BattleRecorder(this); createTempFile(); } finally { cleanupStream(ois); cleanupStream(bis); cleanupStream(fis); cleanupStream(oos); cleanupStream(zos); cleanupStream(bos); cleanupStream(fos); cleanupStream(osw); } } public boolean hasRecord() { return recordInfo != null; } public void createRecordInfo(BattleRules rules, int numRobots) { try { createTempFile(); fileWriteStream = new FileOutputStream(tempFile); bufferedWriteStream = new BufferedOutputStream(fileWriteStream, 1024 * 1024); objectWriteStream = new ObjectOutputStream(bufferedWriteStream); } catch (IOException e) { logError(e); } recordInfo = new BattleRecordInfo(); recordInfo.robotCount = numRobots; recordInfo.battleRules = rules; recordInfo.turnsInRounds = new Integer[rules.getNumRounds()]; for (int i = 0; i < rules.getNumRounds(); i++) { recordInfo.turnsInRounds[i] = 0; } } public void updateRecordInfoResults(List results) { recordInfo.results = results; } public void writeTurn(ITurnSnapshot turn, int round, int time) { try { if (time != recordInfo.turnsInRounds[round]) { throw new Error("Something rotten"); } recordInfo.turnsInRounds[round]++; recordInfo.roundsCount = round + 1; objectWriteStream.writeObject(turn); } catch (IOException e) { logError(e); } } } robocode/robocode/robocode/RobotStatus.java0000644000175000017500000002561411130241112020362 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen * - Initial implementation *******************************************************************************/ package robocode; import robocode.battle.Battle; import robocode.peer.ExecCommands; import robocode.peer.RobotPeer; import java.io.Serializable; /** * Contains the status of a robot for a specific time/turn returned by * {@link StatusEvent#getStatus()}. * * @author Flemming N. Larsen (original) * @since 1.5 */ public final class RobotStatus implements Serializable { private static final long serialVersionUID = 1L; private final double energy; private final double x; private final double y; private final double bodyHeading; private final double gunHeading; private final double radarHeading; private final double velocity; private final double bodyTurnRemaining; private final double radarTurnRemaining; private final double gunTurnRemaining; private final double distanceRemaining; private final double gunHeat; private final int others; private final int roundNum; private final int numRounds; private final long time; /** * Creates a new RobotStatus based a a RobotPeer. * This constructor is called internally from the game. * * @param robotPeer the RobotPeer containing the states we must make a snapshot of * @param commands data from commands * @param battle data from battle */ public RobotStatus(RobotPeer robotPeer, ExecCommands commands, Battle battle) { energy = robotPeer.getEnergy(); x = robotPeer.getX(); y = robotPeer.getY(); bodyHeading = robotPeer.getBodyHeading(); gunHeading = robotPeer.getGunHeading(); radarHeading = robotPeer.getRadarHeading(); velocity = robotPeer.getVelocity(); gunHeat = robotPeer.getGunHeat(); bodyTurnRemaining = commands.getBodyTurnRemaining(); radarTurnRemaining = commands.getRadarTurnRemaining(); gunTurnRemaining = commands.getGunTurnRemaining(); distanceRemaining = commands.getDistanceRemaining(); others = battle.getActiveRobots() - (robotPeer.isAlive() ? 1 : 0); roundNum = battle.getRoundNum(); numRounds = battle.getNumRounds(); time = battle.getTime(); } /** * Returns the robot's current energy. * * @return the robot's current energy */ public double getEnergy() { return energy; } /** * Returns the X position of the robot. (0,0) is at the bottom left of the * battlefield. * * @return the X position of the robot * @see #getY() */ public double getX() { return x; } /** * Returns the Y position of the robot. (0,0) is at the bottom left of the * battlefield. * * @return the Y position of the robot * @see #getX() */ public double getY() { return y; } /** * Returns the direction that the robot's body is facing, in radians. * The value returned will be between 0 and 2 * PI (is excluded). *

* Note that the heading in Robocode is like a compass, where 0 means North, * PI / 2 means East, PI means South, and 3 * PI / 4 means West. * * @return the direction that the robot's body is facing, in radians. */ public double getHeadingRadians() { return bodyHeading; } /** * Returns the direction that the robot's body is facing, in degrees. * The value returned will be between 0 and 360 (is excluded). *

* Note that the heading in Robocode is like a compass, where 0 means North, * 90 means East, 180 means South, and 270 means West. * * @return the direction that the robot's body is facing, in degrees. */ public double getHeading() { return Math.toDegrees(bodyHeading); } /** * Returns the direction that the robot's gun is facing, in radians. * The value returned will be between 0 and 2 * PI (is excluded). *

* Note that the heading in Robocode is like a compass, where 0 means North, * PI / 2 means East, PI means South, and 3 * PI / 4 means West. * * @return the direction that the robot's gun is facing, in radians. */ public double getGunHeadingRadians() { return gunHeading; } /** * Returns the direction that the robot's gun is facing, in degrees. * The value returned will be between 0 and 360 (is excluded). *

* Note that the heading in Robocode is like a compass, where 0 means North, * 90 means East, 180 means South, and 270 means West. * * @return the direction that the robot's gun is facing, in degrees. */ public double getGunHeading() { return Math.toDegrees(gunHeading); } /** * Returns the direction that the robot's radar is facing, in radians. * The value returned will be between 0 and 2 * PI (is excluded). *

* Note that the heading in Robocode is like a compass, where 0 means North, * PI / 2 means East, PI means South, and 3 * PI / 4 means West. * * @return the direction that the robot's radar is facing, in radians. */ public double getRadarHeadingRadians() { return radarHeading; } /** * Returns the direction that the robot's radar is facing, in degrees. * The value returned will be between 0 and 360 (is excluded). *

* Note that the heading in Robocode is like a compass, where 0 means North, * 90 means East, 180 means South, and 270 means West. * * @return the direction that the robot's radar is facing, in degrees. */ public double getRadarHeading() { return Math.toDegrees(radarHeading); } /** * Returns the velocity of the robot measured in pixels/turn. *

* The maximum velocity of a robot is defined by {@link Rules#MAX_VELOCITY} * (8 pixels / turn). * * @return the velocity of the robot measured in pixels/turn * @see Rules#MAX_VELOCITY */ public double getVelocity() { return velocity; } /** * Returns the angle remaining in the robots's turn, in radians. *

* This call returns both positive and negative values. Positive values * means that the robot is currently turning to the right. Negative values * means that the robot is currently turning to the left. * * @return the angle remaining in the robots's turn, in radians */ public double getTurnRemainingRadians() { return bodyTurnRemaining; } /** * Returns the angle remaining in the robots's turn, in degrees. *

* This call returns both positive and negative values. Positive values * means that the robot is currently turning to the right. Negative values * means that the robot is currently turning to the left. * * @return the angle remaining in the robots's turn, in degrees */ public double getTurnRemaining() { return Math.toDegrees(bodyTurnRemaining); } /** * Returns the angle remaining in the radar's turn, in radians. *

* This call returns both positive and negative values. Positive values * means that the radar is currently turning to the right. Negative values * means that the radar is currently turning to the left. * * @return the angle remaining in the radar's turn, in radians */ public double getRadarTurnRemainingRadians() { return radarTurnRemaining; } /** * Returns the angle remaining in the radar's turn, in degrees. *

* This call returns both positive and negative values. Positive values * means that the radar is currently turning to the right. Negative values * means that the radar is currently turning to the left. * * @return the angle remaining in the radar's turn, in degrees */ public double getRadarTurnRemaining() { return Math.toDegrees(radarTurnRemaining); } /** * Returns the angle remaining in the gun's turn, in radians. *

* This call returns both positive and negative values. Positive values * means that the gun is currently turning to the right. Negative values * means that the gun is currently turning to the left. * * @return the angle remaining in the gun's turn, in radians */ public double getGunTurnRemainingRadians() { return gunTurnRemaining; } /** * Returns the angle remaining in the gun's turn, in degrees. *

* This call returns both positive and negative values. Positive values * means that the gun is currently turning to the right. Negative values * means that the gun is currently turning to the left. * * @return the angle remaining in the gun's turn, in degrees */ public double getGunTurnRemaining() { return Math.toDegrees(gunTurnRemaining); } /** * Returns the distance remaining in the robot's current move measured in * pixels. *

* This call returns both positive and negative values. Positive values * means that the robot is currently moving forwards. Negative values means * that the robot is currently moving backwards. * * @return the distance remaining in the robot's current move measured in * pixels. */ public double getDistanceRemaining() { return distanceRemaining; } /** * Returns the current heat of the gun. The gun cannot fire unless this is * 0. (Calls to fire will succeed, but will not actually fire unless * getGunHeat() == 0). *

* The amount of gun heat generated when the gun is fired is * 1 + (firePower / 5). Each turn the gun heat drops by the amount returned * by {@link Robot#getGunCoolingRate()}, which is a battle setup. *

* Note that all guns are "hot" at the start of each round, where the gun * heat is 3. * * @return the current gun heat * @see Robot#getGunCoolingRate() * @see Robot#fire(double) * @see Robot#fireBullet(double) */ public double getGunHeat() { return gunHeat; } /** * Returns how many opponents that are left in the current round. * * @return how many opponents that are left in the current round. * @since 1.6.2 */ public int getOthers() { return others; } /** * Returns the number of rounds in the current battle. * * @return the number of rounds in the current battle * @see #getRoundNum() * @since 1.6.2 */ public int getNumRounds() { return numRounds; } /** * Returns the current round number (0 to {@link #getNumRounds()} - 1) of * the battle. * * @return the current round number of the battle * @see #getNumRounds() * @since 1.6.2 */ public int getRoundNum() { return roundNum; } /** * Returns the game time of the round, where the time is equal to the current turn in the round. * * @return the game time/turn of the current round. * @since 1.6.2 */ public long getTime() { return time; } } robocode/robocode/robocode/MouseEvent.java0000644000175000017500000000267211130241112020162 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode; /** * Super class of all events that originates from the mouse. * * @author Pavel Savara (original) * @since 1.6.1 */ public abstract class MouseEvent extends Event { private static final long serialVersionUID = 1L; private final java.awt.event.MouseEvent source; /** * Called by the game to create a new MouseEvent. * * @param source the source mouse event originating from the AWT. */ public MouseEvent(java.awt.event.MouseEvent source) { this.source = source; } /** * Do not call this method! *

* This method is used by the game to determine the type of the source mouse * event that occurred in the AWT. * * @return the source mouse event that originates from the AWT. */ public java.awt.event.MouseEvent getSourceEvent() { return source; } } robocode/robocode/robocode/PaintEvent.java0000644000175000017500000000350211130241112020136 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen * - Initial implementation *******************************************************************************/ package robocode; import robocode.peer.RobotStatics; import robocode.robotinterfaces.IBasicRobot; import robocode.robotinterfaces.IPaintEvents; import robocode.robotinterfaces.IPaintRobot; import java.awt.*; /** * This event occurs when your robot should paint, where the {@link * Robot#onPaint(Graphics2D) onPaint()} is called on your robot. *

* You can use this event for setting the event priority by calling * {@link AdvancedRobot#setEventPriority(String, int) * setEventPriority("PaintEvent", priority)} * * @author Flemming N. Larsen (original) */ public final class PaintEvent extends Event { private static final long serialVersionUID = 1L; private final static int DEFAULT_PRIORITY = 5; /** * Called by the game to create a new PaintEvent. */ public PaintEvent() { super(); } /** * {@inheritDoc} */ @Override final int getDefaultPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override final void dispatch(IBasicRobot robot, RobotStatics statics, Graphics2D graphics) { if (statics.isPaintRobot()) { IPaintEvents listener = ((IPaintRobot) robot).getPaintEventListener(); if (listener != null) { listener.onPaint(graphics); } } } } robocode/robocode/robocode/SkippedTurnEvent.java0000644000175000017500000000571311130241112021341 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Updated Javadocs *******************************************************************************/ package robocode; import robocode.peer.RobotStatics; import robocode.robotinterfaces.IAdvancedEvents; import robocode.robotinterfaces.IAdvancedRobot; import robocode.robotinterfaces.IBasicRobot; import java.awt.*; /** * A SkippedTurnEvent is sent to {@link AdvancedRobot#onSkippedTurn(SkippedTurnEvent) * onSkippedTurn()} when your robot is forced to skipping a turn. * You must take an action every turn in order to participate in the game. * For example, *
 *    try {
 *        Thread.sleep(1000);
 *    } catch (InterruptedException e) {
 *        // Immediately reasserts the exception by interrupting the caller thread
 *        // itself.
 *        Thread.currentThread().interrupt();
 *    }
 * 
* will cause many SkippedTurnEvents, because you are not responding to the game. * If you receive 30 SkippedTurnEvents, you will be removed from the round. *

* Instead, you should do something such as: *

 *     for (int i = 0; i < 30; i++) {
 *         doNothing(); // or perhaps scan();
 *     }
 * 
*

* This event may also be generated if you are simply doing too much processing * between actions, that is using too much processing power for the calculations * etc. in your robot. * * @author Mathew A. Nelson (original) * @see AdvancedRobot#onSkippedTurn(SkippedTurnEvent) * @see SkippedTurnEvent */ public final class SkippedTurnEvent extends Event { private static final long serialVersionUID = 1L; private final static int DEFAULT_PRIORITY = 100; // System event -> cannot be changed!; /** * Called by the game to create a new SkippedTurnEvent. */ public SkippedTurnEvent() { super(); } /** * {@inheritDoc} */ @Override public final int getPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override final int getDefaultPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override final void dispatch(IBasicRobot robot, RobotStatics statics, Graphics2D graphics) { if (statics.isAdvancedRobot()) { IAdvancedEvents listener = ((IAdvancedRobot) robot).getAdvancedEventListener(); if (listener != null) { listener.onSkippedTurn(this); } } } /** * {@inheritDoc} */ @Override final boolean isCriticalEvent() { return true; } } robocode/robocode/robocode/MoveCompleteCondition.java0000644000175000017500000000451011130241112022327 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Updated Javadocs * Nathaniel Troutman * - Added cleanup() method for cleaning up references to internal classes * to prevent circular references causing memory leaks *******************************************************************************/ package robocode; /** * A prebuilt condition you can use that indicates your robot has finished * moving. * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Nathaniel Troutman (contributor) * @see Condition */ public class MoveCompleteCondition extends Condition { private AdvancedRobot robot; /** * Creates a new MoveCompleteCondition with default priority. * The default priority is 80. * * @param robot your robot, which must be a {@link AdvancedRobot} */ public MoveCompleteCondition(AdvancedRobot robot) { super(); this.robot = robot; } /** * Creates a new MoveCompleteCondition with the specified priority. * A condition priority is a value from 0 - 99. The higher value, the * higher priority. The default priority is 80. * * @param robot your robot, which must be a {@link AdvancedRobot} * @param priority the priority of this condition * @see Condition#setPriority(int) */ public MoveCompleteCondition(AdvancedRobot robot, int priority) { super(); this.robot = robot; this.priority = priority; } /** * Tests if the robot has stopped moving. * * @return {@code true} if the robot has stopped moving; {@code false} * otherwise */ @Override public boolean test() { return (robot.getDistanceRemaining() == 0); } /** * Called by the system in order to clean up references to internal objects. * * @since 1.4.3 */ @Override public void cleanup() { robot = null; } } robocode/robocode/robocode/_Robot.java0000644000175000017500000001062611130241112017312 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Updated Javadocs * - Code cleanup * - Changed to extend the new _RobotBase class instead of being top class * - The uninitializedException() method does not need a method name as input * parameter anymore, and was moved to the new _RobotBase class * - The setPeer() methods has been moved to the _RobotPeer class * Pavel Savara * - Re-work of robot interfaces *******************************************************************************/ package robocode; /** * This class is used by the system, as well as being a placeholder for all deprecated * (meaning, you should not use them) calls for {@link Robot}. *

* You should create a {@link Robot} instead. *

* There is no guarantee that this class will exist in future versions of Robocode. * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Pavel Savara (contributor) * @see Robot */ public abstract class _Robot extends _RobotBase { private String robotImageName; private String gunImageName; private String radarImageName; _Robot() {} /** * @return 5 - {@link robocode.Robot#getGunHeat() getGunHeat()}. * @deprecated Use {@link Robot#getGunHeat() getGunHeat()} instead. */ @Deprecated public double getGunCharge() { if (peer != null) { return 5 - peer.getGunHeat(); } uninitializedException(); return 0; // never called } /** * @return the robot's current life/energy. * @deprecated Use {@link Robot#getEnergy() getEnergy()} instead. */ @Deprecated public double getLife() { if (peer != null) { return peer.getEnergy(); } uninitializedException(); return 0; // never called } /** * @return the number of rounds in the current battle * @deprecated Use {@link Robot#getNumRounds() getNumRounds()} instead. */ @Deprecated public int getNumBattles() { if (peer != null) { return peer.getNumRounds(); } uninitializedException(); return 0; // never called } /** * @return the current round number of the battle * @deprecated Use {@link Robot#getRoundNum() getRoundNum()} instead. */ @Deprecated public int getBattleNum() { if (peer != null) { return peer.getRoundNum(); } uninitializedException(); return 0; // never called } /** * This call has moved to {@link AdvancedRobot}, and will no longer function in * the {@link Robot} class. * * @param interruptible {@code true} if the event handler should be * interrupted if new events of the same priority occurs; {@code false} * otherwise */ public void setInterruptible(boolean interruptible) {} /** * @return the name of the gun image * @deprecated This call is not used. */ @Deprecated public String getGunImageName() { return gunImageName; } /** * @param newGunImageName the name of the new gun image * @deprecated This call is not used. */ @Deprecated public void setGunImageName(String newGunImageName) { gunImageName = newGunImageName; } /** * @param newRadarImageName the name of the new radar image * @deprecated This call is not used. */ @Deprecated public void setRadarImageName(String newRadarImageName) { radarImageName = newRadarImageName; } /** * @param newRobotImageName the name of the new robot body image * @deprecated This call is not used. */ @Deprecated public void setRobotImageName(String newRobotImageName) { robotImageName = newRobotImageName; } /** * @return the name of the radar image * @deprecated This call is not used. */ @Deprecated public String getRadarImageName() { return radarImageName; } /** * @return the name of the robot image * @deprecated This call is not used. */ @Deprecated public String getRobotImageName() { return robotImageName; } } robocode/robocode/robocode/MessageEvent.java0000644000175000017500000000455611130241112020461 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Updated Javadocs *******************************************************************************/ package robocode; import robocode.peer.RobotStatics; import robocode.robotinterfaces.IBasicRobot; import robocode.robotinterfaces.ITeamEvents; import robocode.robotinterfaces.ITeamRobot; import java.awt.*; import java.io.Serializable; /** * A MessageEvent is sent to {@link TeamRobot#onMessageReceived(MessageEvent) * onMessageReceived()} when a teammate sends a message to your robot. * You can use the information contained in this event to determine what to do. * * @author Mathew A. Nelson (original) */ public final class MessageEvent extends Event { private static final long serialVersionUID = 1L; private final static int DEFAULT_PRIORITY = 75; private final String sender; private final Serializable message; /** * Called by the game to create a new MessageEvent. * * @param sender the name of the sending robot * @param message the message for your robot */ public MessageEvent(String sender, Serializable message) { this.sender = sender; this.message = message; } /** * Returns the name of the sending robot. * * @return the name of the sending robot */ public String getSender() { return sender; } /** * Returns the message itself. * * @return the message */ public Serializable getMessage() { return message; } /** * {@inheritDoc} */ @Override final int getDefaultPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override final void dispatch(IBasicRobot robot, RobotStatics statics, Graphics2D graphics) { if (statics.isTeamRobot()) { ITeamEvents listener = ((ITeamRobot) robot).getTeamEventListener(); if (listener != null) { listener.onMessageReceived(this); } } } } robocode/robocode/robocode/MouseExitedEvent.java0000644000175000017500000000411311130241112021315 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode; import robocode.peer.RobotStatics; import robocode.robotinterfaces.IBasicRobot; import robocode.robotinterfaces.IInteractiveEvents; import robocode.robotinterfaces.IInteractiveRobot; import java.awt.*; /** * A MouseExitedEvent is sent to {@link Robot#onMouseExited(java.awt.event.MouseEvent) * onMouseExited()} when the mouse has exited the battle view. * * @author Pavel Savara (original) * @see MouseClickedEvent * @see MousePressedEvent * @see MouseReleasedEvent * @see MouseEnteredEvent * @see MouseMovedEvent * @see MouseDraggedEvent * @see MouseWheelMovedEvent * @since 1.6.1 */ public final class MouseExitedEvent extends MouseEvent { private static final long serialVersionUID = 1L; private final static int DEFAULT_PRIORITY = 98; /** * Called by the game to create a new MouseExitedEvent. * * @param source the source mouse event originating from the AWT. */ public MouseExitedEvent(java.awt.event.MouseEvent source) { super(source); } /** * {@inheritDoc} */ @Override final int getDefaultPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override final void dispatch(IBasicRobot robot, RobotStatics statics, Graphics2D graphics) { if (statics.isInteractiveRobot()) { IInteractiveEvents listener = ((IInteractiveRobot) robot).getInteractiveEventListener(); if (listener != null) { listener.onMouseExited(getSourceEvent()); } } } } robocode/robocode/robocode/robotpaint/0000755000175000017500000000000011124142544017413 5ustar lambylambyrobocode/robocode/robocode/robotpaint/Graphics2DProxy.java0000644000175000017500000013335111130241112023240 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen * - Initial implementation * Pavel Savara * - calls are not queued if we don't have painting enabled *******************************************************************************/ package robocode.robotpaint; import static robocode.common.ObjectCloner.deepCopy; import java.awt.*; import java.awt.RenderingHints.Key; import java.awt.font.FontRenderContext; import java.awt.font.GlyphVector; import java.awt.geom.AffineTransform; import java.awt.geom.Area; import java.awt.geom.GeneralPath; import java.awt.image.BufferedImage; import java.awt.image.BufferedImageOp; import java.awt.image.ImageObserver; import java.awt.image.RenderedImage; import java.awt.image.renderable.RenderableImage; import java.text.AttributedCharacterIterator; import java.util.*; import java.util.List; /** * The Graphics2DProxy is a Graphics2D class that is not able to render graphics * by itself. Instead it acts as a Graphics2D and queues up all the Graphics2D * method calls, which will then later be processed to a real Graphics2D object. *

* Example: *
 *    // Create the Graphics2D proxy
 *    Graphics2D gfxProxy = new Graphics2DProxy();
 *    ...
 *    // Paint on the Graphics2D proxy like an ordinary Graphics2D object
 *    gfxProxy.setColor(Color.RED);
 *    gfxProxy.fillRect(0, 0, 100, 100);
 *    ...
 *    // Process all pending method call to the real Graphics2D object
 *    gfxProxy.processTo(g); // where g is a real Graphics2D object
 *    ...
 *    // Clear the queue method calls
 *    gfxProxy.clearQueue(g);
 * 
* * @author Flemming N. Larsen (original) * @since 1.6.1 */ public class Graphics2DProxy extends Graphics2D implements java.io.Serializable { private static final long serialVersionUID = 1L; private enum Method { TRANSLATE_INT, // translate(int, int) SET_COLOR, // setColor(Color) SET_PAINT_MODE, // setPaintMode() SET_XOR_MODE, // setXORMode(Color) SET_FONT, // setFont(Font) CLIP_RECT, // clipRect(int, int, int, int) SET_CLIP, // setClip(int, int, int, int) SET_CLIP_SHAPE, // setClip(Shape) COPY_AREA, // copyArea(int, int, int, int, int, int) DRAW_LINE, // drawLine(int, int, int, int) FILL_RECT, // fillRect(int, int, int, int) DRAW_RECT, // drawRect(int, int, int, int) CLEAR_RECT, // clearRect(int, int, int, int) DRAW_ROUND_RECT, // drawRoundRect(int, int, int, int, int, int) FILL_ROUND_RECT, // fillRoundRect(int, int, int, int, int, int) DRAW_3D_RECT, // draw3DRect(int, int, int, int, boolean) FILL_3D_RECT, // draw3DRect(int, int, int, int, boolean) DRAW_OVAL, // drawOval(int, int, int, int) FILL_OVAL, // fillOval(int, int, int, int) DRAW_ARC, // drawArc(int, int, int, int, int, int) FILL_ARC, // fillArc(int, int, int, int, int, int) DRAW_POLYLINE, // drawPolyline(int[], int[], int) DRAW_POLYGON, // drawPolygon(int[], int[], int) FILL_POLYGON, // fillPolygon(int[], int[], int) DRAW_STRING_INT, // drawString(String, int, int) DRAW_STRING_ACI_INT, // drawString(AttributedCharacterIterator, int, int) DRAW_CHARS, // drawChars(char[], int, int, int, int) DRAW_BYTES, // drawBytes(byte[], int, int, int, int) DRAW_IMAGE_1, // drawImage(Image, int, int, ImageObserver) DRAW_IMAGE_2, // drawImage(Image, int, int, int, int, ImageObserver) DRAW_IMAGE_3, // drawImage(Image, int, int, Color, ImageObserver) DRAW_IMAGE_4, // drawImage(Image, int, int, int, int, Color, ImageObserver) DRAW_IMAGE_5, // drawImage(Image, int, int, int, int, int, int, int, int, ImageObserver) DRAW_IMAGE_6, // drawImage(Image, int, int, int, int, int, int, int, int, Color, ImageObserver) DRAW, // draw(Shape) DRAW_IMAGE_7, // drawImage(Image, AffineTransform, ImageObserver) DRAW_IMAGE_8, // drawImage(BufferedImage, BufferedImageOp, int, int) DRAW_RENDERED_IMAGE, // drawRenderedImage(RenderedImage, AffineTransform) DRAW_RENDERABLE_IMGAGE, // drawRenderableImage(RenderableImage, AffineTransform) DRAW_STRING_FLOAT, // drawString(String, float, float) DRAW_STRING_ACI_FLOAT, // drawString(AttributedCharacterIterator, float, float) DRAW_GLYPH_VECTOR, // drawGlyphVector(GlyphVector gv, float x, float y) FILL, // fill(Shape) SET_COMPOSITE, // setComposite(Composite) SET_PAINT, // setPaint(Paint) SET_STROKE, // setStroke(Stroke) SET_RENDERING_HINT, // setRenderingHint(Key, Object) SET_RENDERING_HINTS, // setRenderingHints(Map) ADD_RENDERING_HINTS, // addRenderingHints(Map) TRANSLATE_DOUBLE, // translate(double, double) ROTATE, // rotate(double) ROTATE_XY, // rotate(double, double, double) SCALE, // scale(double, double) SHEAR, // shear(double, double) TRANSFORM, // transform(AffineTransform) SET_TRANSFORM, // setTransform(AffineTransform Tx) SET_BACKGROUND, // setBackground(Color) CLIP, // clip(Shape) } // Queue of calls. Must be synchronized to avoid ArrayOutOfBoundsException when it is being copied private List queuedCalls = Collections.synchronizedList(new LinkedList()); // Needed for getTransform() private transient AffineTransform transform; // Needed for getComposite() private transient Composite composite; // Needed for getPaint() private transient Paint paint; // Needed for getStroke() private transient Stroke stroke; // Needed for getRenderingHint() and getRenderingHints() private transient RenderingHints renderingHints; // Needed for getBackground() private transient Color background; // Needed for getClip() private transient Shape clip; // Needed for getColor() private transient Color color; // Needed for getFont() private transient Font font; // Flag indicating if this proxy has been initialized private transient boolean isInitialized; // Flag indicating if this proxy has been initialized private transient boolean isPaintingEnabled; // -------------------------------------------------------------------------- // Overriding all methods from the extended Graphics class // -------------------------------------------------------------------------- // Methods that should not be overridden or implemented: // - finalize() // - toString() @Override public Graphics create() { Graphics2DProxy gfxProxyCopy = new Graphics2DProxy(); gfxProxyCopy.queuedCalls = Collections.synchronizedList(new LinkedList(queuedCalls)); gfxProxyCopy.transform = copyOf(transform); gfxProxyCopy.composite = copyOf(composite); gfxProxyCopy.paint = copyOf(paint); gfxProxyCopy.stroke = copyOf(stroke); gfxProxyCopy.renderingHints = copyOf(renderingHints); gfxProxyCopy.background = deepCopy(background); gfxProxyCopy.clip = copyOf(clip); gfxProxyCopy.color = deepCopy(color); gfxProxyCopy.font = copyOf(font); gfxProxyCopy.isInitialized = isInitialized; return gfxProxyCopy; } public static Graphics createFromCalls(List queuedCalls) { Graphics2DProxy gfxProxyCopy = new Graphics2DProxy(); gfxProxyCopy.queuedCalls = Collections.synchronizedList(new LinkedList(queuedCalls)); return gfxProxyCopy; } public void setPaintingEnabled(boolean value) { isPaintingEnabled = value; } @Override public Graphics create(int x, int y, int width, int height) { Graphics g = create(); g.translate(x, y); g.setClip(0, 0, width, height); return g; } @Override public void translate(int x, int y) { // for getTransform() this.transform.translate(x, y); if (isPaintingEnabled) { queueCall(Method.TRANSLATE_INT, x, y); } } @Override public Color getColor() { return color; } @Override public void setColor(Color c) { // for getColor() this.color = c; if (isPaintingEnabled) { queueCall(Method.SET_COLOR, copyOf(c)); } } @Override public void setPaintMode() { if (isPaintingEnabled) { queueCall(Method.SET_PAINT_MODE); } } @Override public void setXORMode(Color c1) { if (isPaintingEnabled) { queueCall(Method.SET_XOR_MODE, copyOf(c1)); } } @Override public Font getFont() { return font; } @Override public void setFont(Font font) { // for getFont() this.font = font; if (isPaintingEnabled) { queueCall(Method.SET_FONT, copyOf(font)); } } @Override public FontMetrics getFontMetrics(Font f) { return new FontMetricsByFont(f); } @Override public Rectangle getClipBounds() { return clip.getBounds(); } @Override public void clipRect(int x, int y, int width, int height) { // for getClip() Area clipArea = new Area(clip); Area clipRectArea = new Area(new Rectangle(x, y, width, height)); clipArea.intersect(clipRectArea); this.clip = clipArea; if (isPaintingEnabled) { queueCall(Method.CLIP_RECT, x, y, width, height); } } @Override public void setClip(int x, int y, int width, int height) { // for getClip() this.clip = new Rectangle(x, y, width, height); if (isPaintingEnabled) { queueCall(Method.SET_CLIP, x, y, width, height); } } @Override public Shape getClip() { return clip; } @Override public void setClip(Shape clip) { // for getClip() this.clip = clip; if (isPaintingEnabled) { queueCall(Method.SET_CLIP_SHAPE, copyOf(clip)); } } @Override public void copyArea(int x, int y, int width, int height, int dx, int dy) { if (isPaintingEnabled) { queueCall(Method.COPY_AREA, x, y, width, height, dx, dy); } } @Override public void drawLine(int x1, int y1, int x2, int y2) { if (isPaintingEnabled) { queueCall(Method.DRAW_LINE, x1, y1, x2, y2); } } @Override public void fillRect(int x, int y, int width, int height) { if (isPaintingEnabled) { queueCall(Method.FILL_RECT, x, y, width, height); } } @Override public void drawRect(int x, int y, int width, int height) { if (isPaintingEnabled) { queueCall(Method.DRAW_RECT, x, y, width, height); } } @Override public void clearRect(int x, int y, int width, int height) { if (isPaintingEnabled) { queueCall(Method.CLEAR_RECT, x, y, width, height); } } @Override public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { if (isPaintingEnabled) { queueCall(Method.DRAW_ROUND_RECT, x, y, width, height, arcWidth, arcHeight); } } @Override public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { if (isPaintingEnabled) { queueCall(Method.FILL_ROUND_RECT, x, y, width, height, arcWidth, arcHeight); } } @Override public void draw3DRect(int x, int y, int width, int height, boolean raised) { if (isPaintingEnabled) { queueCall(Method.DRAW_3D_RECT, x, y, width, height, raised); } } @Override public void fill3DRect(int x, int y, int width, int height, boolean raised) { if (isPaintingEnabled) { queueCall(Method.FILL_3D_RECT, x, y, width, height, raised); } } @Override public void drawOval(int x, int y, int width, int height) { if (isPaintingEnabled) { queueCall(Method.DRAW_OVAL, x, y, width, height); } } @Override public void fillOval(int x, int y, int width, int height) { if (isPaintingEnabled) { queueCall(Method.FILL_OVAL, x, y, width, height); } } @Override public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) { if (isPaintingEnabled) { queueCall(Method.DRAW_ARC, x, y, width, height, startAngle, arcAngle); } } @Override public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) { if (isPaintingEnabled) { queueCall(Method.FILL_ARC, x, y, width, height, startAngle, arcAngle); } } @Override public void drawPolyline(int[] xPoints, int[] yPoints, int npoints) { if (isPaintingEnabled) { queueCall(Method.DRAW_POLYLINE, copyOf(xPoints), copyOf(yPoints), npoints); } } @Override public void drawPolygon(int[] xPoints, int[] yPoints, int npoints) { if (isPaintingEnabled) { queueCall(Method.DRAW_POLYGON, copyOf(xPoints), copyOf(yPoints), npoints); } } @Override public void drawPolygon(Polygon p) { if (isPaintingEnabled) { drawPolygon(p.xpoints, p.ypoints, p.npoints); // Reuse sister method } } @Override public void fillPolygon(int[] xPoints, int[] yPoints, int npoints) { if (isPaintingEnabled) { queueCall(Method.FILL_POLYGON, copyOf(xPoints), copyOf(yPoints), npoints); } } @Override public void fillPolygon(Polygon p) { if (isPaintingEnabled) { fillPolygon(p.xpoints, p.ypoints, p.npoints); // Reuse sister method } } @Override public void drawString(String str, int x, int y) { if (str == null) { throw new NullPointerException("str is null"); // According to the specification! } if (isPaintingEnabled) { queueCall(Method.DRAW_STRING_INT, str, x, y); } } @Override public void drawString(AttributedCharacterIterator iterator, int x, int y) { if (isPaintingEnabled) { queueCall(Method.DRAW_STRING_ACI_INT, copyOf(iterator), x, y); } } @Override public void drawChars(char[] data, int offset, int length, int x, int y) { if (isPaintingEnabled) { queueCall(Method.DRAW_CHARS, copyOf(data), offset, length, x, y); } } @Override public void drawBytes(byte[] data, int offset, int length, int x, int y) { if (isPaintingEnabled) { queueCall(Method.DRAW_BYTES, copyOf(data), offset, length, x, y); } } @Override public boolean drawImage(Image img, int x, int y, ImageObserver observer) { if (isPaintingEnabled) { queueCall(Method.DRAW_IMAGE_1, copyOf(img), x, y, copyOf(observer)); } return false; // as if if the image pixels are still changing (as the call is queued) } @Override public boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer) { if (isPaintingEnabled) { queueCall(Method.DRAW_IMAGE_2, copyOf(img), x, y, width, height, copyOf(observer)); } return false; // as if if the image pixels are still changing (as the call is queued) } @Override public boolean drawImage(Image img, int x, int y, Color bgcolor, ImageObserver observer) { if (isPaintingEnabled) { queueCall(Method.DRAW_IMAGE_3, copyOf(img), x, y, copyOf(bgcolor), copyOf(observer)); } return false; // as if if the image pixels are still changing (as the call is queued) } @Override public boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor, ImageObserver observer) { if (isPaintingEnabled) { queueCall(Method.DRAW_IMAGE_4, copyOf(img), x, y, width, height, copyOf(bgcolor), copyOf(observer)); } return false; // as if if the image pixels are still changing (as the call is queued) } @Override public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer) { if (isPaintingEnabled) { queueCall(Method.DRAW_IMAGE_5, copyOf(img), dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, copyOf(observer)); } return false; // as if if the image pixels are still changing (as the call is queued) } @Override public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, Color bgcolor, ImageObserver observer) { if (isPaintingEnabled) { queueCall(Method.DRAW_IMAGE_6, copyOf(img), dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, copyOf(bgcolor), copyOf(observer)); } return false; // as if if the image pixels are still changing (as the call is queued) } @Override public void dispose() {// Ignored here } @Override @Deprecated public Rectangle getClipRect() { return getClipBounds(); // Must use getClipBounds() instead of this deprecated method } @Override public boolean hitClip(int x, int y, int width, int height) { return (clip != null) && clip.intersects(x, y, width, height); } @Override public Rectangle getClipBounds(Rectangle r) { Rectangle bounds = clip.getBounds(); r.setBounds(bounds); return bounds; } // -------------------------------------------------------------------------- // Overriding all methods from the extended Graphics2D class // -------------------------------------------------------------------------- @Override public void draw(Shape s) { if (isPaintingEnabled) { queueCall(Method.DRAW, copyOf(s)); } } @Override public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) { if (isPaintingEnabled) { queueCall(Method.DRAW_IMAGE_7, copyOf(img), copyOf(xform), copyOf(obs)); } return false; // as if the image is still being rendered (as the call is queued) } @Override public void drawImage(BufferedImage img, BufferedImageOp op, int x, int y) { if (isPaintingEnabled) { queueCall(Method.DRAW_IMAGE_8, copyOf(img), deepCopy(op), x, y); } } @Override public void drawRenderedImage(RenderedImage img, AffineTransform xform) { if (isPaintingEnabled) { queueCall(Method.DRAW_RENDERED_IMAGE, deepCopy(img), copyOf(xform)); } } @Override public void drawRenderableImage(RenderableImage img, AffineTransform xform) { if (isPaintingEnabled) { queueCall(Method.DRAW_RENDERABLE_IMGAGE, deepCopy(img), copyOf(xform)); } } @Override public void drawString(String str, float x, float y) { if (str == null) { throw new NullPointerException("str is null"); // According to the specification! } if (isPaintingEnabled) { queueCall(Method.DRAW_STRING_FLOAT, str, x, y); } } @Override public void drawString(AttributedCharacterIterator iterator, float x, float y) { if (isPaintingEnabled) { queueCall(Method.DRAW_STRING_ACI_FLOAT, copyOf(iterator), x, y); } } @Override public void drawGlyphVector(GlyphVector gv, float x, float y) { if (isPaintingEnabled) { queueCall(Method.DRAW_GLYPH_VECTOR, deepCopy(gv), x, y); } } @Override public void fill(Shape s) { if (isPaintingEnabled) { queueCall(Method.FILL, copyOf(s)); } } @Override public boolean hit(Rectangle rect, Shape s, boolean onStroke) { if (onStroke && getStroke() != null) { s = getStroke().createStrokedShape(s); } if (getTransform() != null) { s = getTransform().createTransformedShape(s); } Area area = new Area(s); if (getClip() != null) { area.intersect(new Area(getClip())); } return area.intersects(rect); } @Override public GraphicsConfiguration getDeviceConfiguration() { return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration(); } @Override public void setComposite(Composite comp) { // for getComposite() this.composite = comp; if (isPaintingEnabled) { queueCall(Method.SET_COMPOSITE, copyOf(comp)); } } @Override public void setPaint(Paint paint) { // for getPaint() this.paint = paint; if (isPaintingEnabled) { queueCall(Method.SET_PAINT, copyOf(paint)); } } @Override public void setStroke(Stroke s) { // for getStroke() this.stroke = s; if (isPaintingEnabled) { queueCall(Method.SET_STROKE, copyOf(s)); } } @Override public void setRenderingHint(Key hintKey, Object hintValue) { // for getRenderingHint() and getRenderingHints() this.renderingHints.put(hintKey, hintValue); if (isPaintingEnabled) { queueCall(Method.SET_RENDERING_HINT, deepCopy(hintKey), deepCopy(hintValue)); } } @Override public Object getRenderingHint(Key hintKey) { return renderingHints.get(hintKey); } @Override public void setRenderingHints(Map hints) { // for getRenderingHint() and getRenderingHints() this.renderingHints.clear(); // Needs to clear first this.renderingHints.putAll(hints); // Only overrides existing keys if (isPaintingEnabled) { queueCall(Method.SET_RENDERING_HINTS, deepCopy(hints)); } } @Override public void addRenderingHints(Map hints) { // for getRenderingHint() and getRenderingHints() this.renderingHints.putAll(hints); if (isPaintingEnabled) { queueCall(Method.ADD_RENDERING_HINTS, deepCopy(hints)); } } @Override public RenderingHints getRenderingHints() { return renderingHints; } @Override public void translate(double tx, double ty) { // for getTransform() transform.translate(tx, ty); if (isPaintingEnabled) { queueCall(Method.TRANSLATE_DOUBLE, tx, ty); } } @Override public void rotate(double theta) { // for getTransform() transform.rotate(theta); if (isPaintingEnabled) { queueCall(Method.ROTATE, theta); } } @Override public void rotate(double theta, double x, double y) { // for getTransform() transform.rotate(theta, x, y); if (isPaintingEnabled) { queueCall(Method.ROTATE_XY, theta, x, y); } } @Override public void scale(double sx, double sy) { // for getTransform() transform.scale(sx, sy); if (isPaintingEnabled) { queueCall(Method.SCALE, sx, sy); } } @Override public void shear(double shx, double shy) { // for getTransform() transform.shear(shx, shy); if (isPaintingEnabled) { queueCall(Method.SHEAR, shx, shy); } } @Override public void transform(AffineTransform Tx) { // for getTransform() transform.concatenate(Tx); if (isPaintingEnabled) { queueCall(Method.TRANSFORM, copyOf(Tx)); } } @Override public void setTransform(AffineTransform Tx) { // for getTransform() this.transform = Tx; if (isPaintingEnabled) { queueCall(Method.SET_TRANSFORM, copyOf(Tx)); } } @Override public AffineTransform getTransform() { return copyOf(transform); } @Override public Paint getPaint() { return paint; } @Override public Composite getComposite() { return composite; } @Override public void setBackground(Color color) { // for getBackground() background = color; if (isPaintingEnabled) { queueCall(Method.SET_BACKGROUND, copyOf(color)); } } @Override public Color getBackground() { return background; } @Override public Stroke getStroke() { return stroke; } @Override public void clip(Shape s) { // for getClip() if (s == null) { this.clip = null; } else { Area shapeArea = new Area(s); Area clipArea = new Area(clip); shapeArea.transform(transform); // transform by the current transform clipArea.intersect(shapeArea); // intersect current clip by the transformed shape this.clip = clipArea; } if (isPaintingEnabled) { queueCall(Method.CLIP, copyOf(s)); } } @Override public FontRenderContext getFontRenderContext() { RenderingHints hints = getRenderingHints(); boolean isAntiAliased = (hints.get(RenderingHints.KEY_TEXT_ANTIALIASING).equals( RenderingHints.VALUE_FRACTIONALMETRICS_ON)); boolean usesFractionalMetrics = (hints.get(RenderingHints.KEY_FRACTIONALMETRICS).equals( RenderingHints.VALUE_FRACTIONALMETRICS_ON)); return new FontRenderContext(null, isAntiAliased, usesFractionalMetrics); } // -------------------------------------------------------------------------- // Helper methods for cloning objects // -------------------------------------------------------------------------- private byte[] copyOf(byte[] array) { if (array == null) { return null; } byte[] copy = new byte[array.length]; System.arraycopy(array, 0, copy, 0, array.length); return copy; } private char[] copyOf(char[] array) { if (array == null) { return null; } char[] copy = new char[array.length]; System.arraycopy(array, 0, copy, 0, array.length); return copy; } private int[] copyOf(int[] array) { if (array == null) { return null; } int[] copy = new int[array.length]; System.arraycopy(array, 0, copy, 0, array.length); return copy; } private Font copyOf(Font f) { return (Font) deepCopy(f); } private Shape copyOf(Shape s) { return (s != null) ? new GeneralPath(s) : null; } private AttributedCharacterIterator copyOf(AttributedCharacterIterator it) { return it != null ? (AttributedCharacterIterator) it.clone() : null; } private Image copyOf(Image img) { return (Image) deepCopy(img); } private ImageObserver copyOf(ImageObserver obs) { return (ImageObserver) deepCopy(obs); } private AffineTransform copyOf(AffineTransform tx) { return tx != null ? (AffineTransform) tx.clone() : null; } private Composite copyOf(Composite c) { if (c == null) { return null; } if (c instanceof AlphaComposite) { AlphaComposite ac = (AlphaComposite) c; return AlphaComposite.getInstance(ac.getRule(), ac.getAlpha()); } throw new UnsupportedOperationException("The Composite type '" + c.getClass().getName() + "' is not supported"); } private Paint copyOf(Paint p) { return (Paint) deepCopy(p); } private Integer copyOf(Color c) { return c.getRGB(); } private Stroke copyOf(Stroke s) { if (s == null) { return null; } if (s instanceof BasicStroke) { BasicStroke bs = (BasicStroke) s; return new BasicStroke(bs.getLineWidth(), bs.getEndCap(), bs.getLineJoin(), bs.getMiterLimit(), bs.getDashArray(), bs.getDashPhase()); } throw new UnsupportedOperationException("The Stroke type '" + s.getClass().getName() + "' is not supported"); } private RenderingHints copyOf(RenderingHints hints) { return hints != null ? (RenderingHints) hints.clone() : null; } // -------------------------------------------------------------------------- // Processing of queued method calls to a Graphics2D object // -------------------------------------------------------------------------- private void queueCall(Method method, Object... args) { queuedCalls.add(new QueuedCall(method, args)); } public void appendCalls(List graphicsCalls) { for (QueuedCall call : graphicsCalls) { try { processQueuedCall(call, this); } catch (Exception e) { e.printStackTrace(); } } } public void processTo(Graphics2D g) { if (!isInitialized) { initialize(g); } for (QueuedCall call : queuedCalls) { try { processQueuedCall(call, g); } catch (Exception e) { e.printStackTrace(); } } } public void clearQueue() { queuedCalls.clear(); } public List getQueuedCalls() { final List now = queuedCalls; return now.size() == 0 ? null : new ArrayList(now); } private void initialize(Graphics2D g) { // Make sure the transform is not null transform = g.getTransform(); transform = transform == null ? new AffineTransform() : new AffineTransform(transform); color = deepCopy(g.getColor()); font = copyOf(g.getFont()); clip = copyOf(g.getClip()); composite = copyOf(g.getComposite()); paint = copyOf(g.getPaint()); stroke = copyOf(g.getStroke()); renderingHints = copyOf(g.getRenderingHints()); background = deepCopy(g.getBackground()); isInitialized = true; } private void processQueuedCall(QueuedCall call, Graphics2D g) { switch (call.method) { case TRANSLATE_INT: processTranslate_int(call, g); break; case SET_COLOR: processSetColor(call, g); break; case SET_PAINT_MODE: processSetPaintMode(g); break; case SET_XOR_MODE: processSetXORMode(call, g); break; case SET_FONT: processSetFont(call, g); break; case CLIP_RECT: processClipRect(call, g); break; case SET_CLIP: processSetClip(call, g); break; case SET_CLIP_SHAPE: processSetClip_Shape(call, g); break; case COPY_AREA: processCopyArea(call, g); break; case DRAW_LINE: processDrawLine(call, g); break; case FILL_RECT: processFillRect(call, g); break; case DRAW_RECT: processDrawRect(call, g); break; case CLEAR_RECT: processClearRect(call, g); break; case DRAW_ROUND_RECT: processDrawRoundRect(call, g); break; case FILL_ROUND_RECT: processFillRoundRect(call, g); break; case DRAW_3D_RECT: processDraw3DRect(call, g); break; case FILL_3D_RECT: processFill3DRect(call, g); break; case DRAW_OVAL: processDrawOval(call, g); break; case FILL_OVAL: processFillOval(call, g); break; case DRAW_ARC: processDrawArc(call, g); break; case FILL_ARC: processFillArc(call, g); break; case DRAW_POLYLINE: processDrawPolyline(call, g); break; case DRAW_POLYGON: processDrawPolygon(call, g); break; case FILL_POLYGON: processFillPolygon(call, g); break; case DRAW_STRING_INT: processDrawString_int(call, g); break; case DRAW_STRING_ACI_INT: processDrawString_ACIterator_int(call, g); break; case DRAW_CHARS: processDrawChars(call, g); break; case DRAW_BYTES: processDrawBytes(call, g); break; case DRAW_IMAGE_1: processDrawImage1(call, g); break; case DRAW_IMAGE_2: processDrawImage2(call, g); break; case DRAW_IMAGE_3: processDrawImage3(call, g); break; case DRAW_IMAGE_4: processDrawImage4(call, g); break; case DRAW_IMAGE_5: processDrawImage5(call, g); break; case DRAW_IMAGE_6: processDrawImage6(call, g); break; case DRAW: processDraw(call, g); break; case DRAW_IMAGE_7: processDrawImage7(call, g); break; case DRAW_IMAGE_8: processDrawImage8(call, g); break; case DRAW_RENDERED_IMAGE: processDrawRenderedImage(call, g); break; case DRAW_RENDERABLE_IMGAGE: processDrawRenderableImage(call, g); break; case DRAW_STRING_FLOAT: processDrawString_float(call, g); break; case DRAW_STRING_ACI_FLOAT: processDrawString_ACIterator_float(call, g); break; case DRAW_GLYPH_VECTOR: processDrawGlyphVector(call, g); break; case FILL: processFill(call, g); break; case SET_COMPOSITE: processSetComposite(call, g); break; case SET_PAINT: processSetPaint(call, g); break; case SET_STROKE: processSetStroke(call, g); break; case SET_RENDERING_HINT: processSetRenderingHint(call, g); break; case SET_RENDERING_HINTS: processSetRenderingHints(call, g); break; case ADD_RENDERING_HINTS: processAddRenderingHints(call, g); break; case TRANSLATE_DOUBLE: processTranslate_double(call, g); break; case ROTATE: processRotate(call, g); break; case ROTATE_XY: processRotate_xy(call, g); break; case SCALE: processScale(call, g); break; case SHEAR: processShear(call, g); break; case TRANSFORM: processTransform(call, g); break; case SET_TRANSFORM: processSetTransform(call, g); break; case SET_BACKGROUND: processSetBackground(call, g); break; case CLIP: processClip(call, g); break; } } private void processTranslate_int(QueuedCall call, Graphics2D g) { // translate(int, int) g.translate(((Integer) call.args[0]).intValue(), ((Integer) call.args[1]).intValue()); } private void processSetColor(QueuedCall call, Graphics2D g) { // setColor(Color) g.setColor(new Color((Integer) call.args[0], true)); } private void processSetPaintMode(Graphics2D g) { // setPaintMode() g.setPaintMode(); } private void processSetXORMode(QueuedCall call, Graphics2D g) { // setXORMode(Color) g.setXORMode(new Color((Integer) call.args[0], true)); } private void processSetFont(QueuedCall call, Graphics2D g) { // setFont(Font) g.setFont((Font) call.args[0]); } private void processClipRect(QueuedCall call, Graphics2D g) { // clipRect(int, int, int, int) g.clipRect((Integer) call.args[0], (Integer) call.args[1], (Integer) call.args[2], (Integer) call.args[3]); } private void processSetClip(QueuedCall call, Graphics2D g) { // setClip(int, int, int, int) g.setClip((Integer) call.args[0], (Integer) call.args[1], (Integer) call.args[2], (Integer) call.args[3]); } private void processSetClip_Shape(QueuedCall call, Graphics2D g) { // setClip(Shape) g.setClip((Shape) call.args[0]); } private void processCopyArea(QueuedCall call, Graphics2D g) { // copyArea(int, int, int, int, int, int) g.copyArea((Integer) call.args[0], (Integer) call.args[1], (Integer) call.args[2], (Integer) call.args[3], (Integer) call.args[4], (Integer) call.args[5]); } private void processDrawLine(QueuedCall call, Graphics2D g) { // drawLine(int, int, int, int) g.drawLine((Integer) call.args[0], (Integer) call.args[1], (Integer) call.args[2], (Integer) call.args[3]); } private void processFillRect(QueuedCall call, Graphics2D g) { // fillRect(int, int, int, int) g.fillRect((Integer) call.args[0], (Integer) call.args[1], (Integer) call.args[2], (Integer) call.args[3]); } private void processDrawRect(QueuedCall call, Graphics2D g) { // drawRect(int, int, int, int) g.drawRect((Integer) call.args[0], (Integer) call.args[1], (Integer) call.args[2], (Integer) call.args[3]); } private void processClearRect(QueuedCall call, Graphics2D g) { // clearRect(int, int, int, int) g.clearRect((Integer) call.args[0], (Integer) call.args[1], (Integer) call.args[2], (Integer) call.args[3]); } private void processDrawRoundRect(QueuedCall call, Graphics2D g) { // drawRoundRect(int, int, int, int, int, int) g.drawRoundRect((Integer) call.args[0], (Integer) call.args[1], (Integer) call.args[2], (Integer) call.args[3], (Integer) call.args[4], (Integer) call.args[5]); } private void processFillRoundRect(QueuedCall call, Graphics2D g) { // fillRoundRect(int, int, int, int, int, int) g.fillRoundRect((Integer) call.args[0], (Integer) call.args[1], (Integer) call.args[2], (Integer) call.args[3], (Integer) call.args[4], (Integer) call.args[5]); } private void processDraw3DRect(QueuedCall call, Graphics2D g) { // draw3DRect(int, int, int, int, boolean) g.draw3DRect(((Integer) call.args[0]).intValue(), ((Integer) call.args[1]).intValue(), ((Integer) call.args[2]).intValue(), ((Integer) call.args[3]).intValue(), ((Boolean) call.args[4]).booleanValue()); } private void processFill3DRect(QueuedCall call, Graphics2D g) { // fill3DRect(int, int, int, int, boolean) g.fill3DRect(((Integer) call.args[0]).intValue(), ((Integer) call.args[1]).intValue(), ((Integer) call.args[2]).intValue(), ((Integer) call.args[3]).intValue(), ((Boolean) call.args[4]).booleanValue()); } private void processDrawOval(QueuedCall call, Graphics2D g) { // drawOval(int, int, int, int) g.drawOval((Integer) call.args[0], (Integer) call.args[1], (Integer) call.args[2], (Integer) call.args[3]); } private void processFillOval(QueuedCall call, Graphics2D g) { // fillOval(int, int, int, int) g.fillOval((Integer) call.args[0], (Integer) call.args[1], (Integer) call.args[2], (Integer) call.args[3]); } private void processDrawArc(QueuedCall call, Graphics2D g) { // drawArc(int, int, int, int, int, int) g.drawArc((Integer) call.args[0], (Integer) call.args[1], (Integer) call.args[2], (Integer) call.args[3], (Integer) call.args[4], (Integer) call.args[5]); } private void processFillArc(QueuedCall call, Graphics2D g) { // fillArc(int, int, int, int, int, int) g.fillArc((Integer) call.args[0], (Integer) call.args[1], (Integer) call.args[2], (Integer) call.args[3], (Integer) call.args[4], (Integer) call.args[5]); } private void processDrawPolyline(QueuedCall call, Graphics2D g) { // drawPolyline(int[], int[], int) g.drawPolyline((int[]) call.args[0], (int[]) call.args[1], (Integer) call.args[2]); } private void processDrawPolygon(QueuedCall call, Graphics2D g) { // drawPolygon(int[], int[], int) g.drawPolygon((int[]) call.args[0], (int[]) call.args[1], (Integer) call.args[2]); } private void processFillPolygon(QueuedCall call, Graphics2D g) { // fillPolygon(int[], int[], int) g.fillPolygon((int[]) call.args[0], (int[]) call.args[1], (Integer) call.args[2]); } private void processDrawString_int(QueuedCall call, Graphics2D g) { // drawString(String, int, int) g.drawString((String) call.args[0], ((Integer) call.args[1]).intValue(), ((Integer) call.args[2]).intValue()); } private void processDrawString_ACIterator_int(QueuedCall call, Graphics2D g) { // drawString(AttributedCharacterIterator, int, int) g.drawString((AttributedCharacterIterator) call.args[0], ((Integer) call.args[1]).intValue(), ((Integer) call.args[2]).intValue()); } private void processDrawChars(QueuedCall call, Graphics2D g) { // drawBytes(char[], int, int, int, int) g.drawChars((char[]) call.args[0], (Integer) call.args[1], (Integer) call.args[2], (Integer) call.args[3], (Integer) call.args[4]); } private void processDrawBytes(QueuedCall call, Graphics2D g) { // drawBytes(byte[], int, int, int, int) g.drawBytes((byte[]) call.args[0], (Integer) call.args[1], (Integer) call.args[2], (Integer) call.args[3], (Integer) call.args[4]); } private void processDrawImage1(QueuedCall call, Graphics2D g) { // drawImage(Image, int, int, ImageObserver) g.drawImage((Image) call.args[0], (Integer) call.args[1], (Integer) call.args[2], (ImageObserver) call.args[3]); } private void processDrawImage2(QueuedCall call, Graphics2D g) { // drawImage(Image, int, int, int, int, ImageObserver) g.drawImage((Image) call.args[0], (Integer) call.args[1], (Integer) call.args[2], (Integer) call.args[3], (Integer) call.args[4], (ImageObserver) call.args[5]); } private void processDrawImage3(QueuedCall call, Graphics2D g) { // drawImage(Image, int, int, Color, ImageObserver) g.drawImage((Image) call.args[0], (Integer) call.args[1], (Integer) call.args[2], new Color((Integer) call.args[3], true), (ImageObserver) call.args[4]); } private void processDrawImage4(QueuedCall call, Graphics2D g) { // drawImage(Image, int, int, int, int, Color, ImageObserver) g.drawImage((Image) call.args[0], (Integer) call.args[1], (Integer) call.args[2], (Integer) call.args[3], (Integer) call.args[4], new Color((Integer) call.args[5], true), (ImageObserver) call.args[6]); } private void processDrawImage5(QueuedCall call, Graphics2D g) { // drawImage(Image, int, int, int, int, int, int, int, int, ImageObserver) g.drawImage((Image) call.args[0], (Integer) call.args[1], (Integer) call.args[2], (Integer) call.args[3], (Integer) call.args[4], (Integer) call.args[4], (Integer) call.args[5], (Integer) call.args[6], (Integer) call.args[7], (ImageObserver) call.args[8]); } private void processDrawImage6(QueuedCall call, Graphics2D g) { // drawImage(Image, int, int, int, int, int, int, int, int, Color, ImageObserver) g.drawImage((Image) call.args[0], (Integer) call.args[1], (Integer) call.args[2], (Integer) call.args[3], (Integer) call.args[4], (Integer) call.args[4], (Integer) call.args[5], (Integer) call.args[6], (Integer) call.args[7], new Color((Integer) call.args[8], true), (ImageObserver) call.args[9]); } private void processDraw(QueuedCall call, Graphics2D g) { // draw(Shape) g.draw((Shape) call.args[0]); } private void processDrawImage7(QueuedCall call, Graphics2D g) { // drawImage(Image, AffineTransform, ImageObserver) g.drawImage((Image) call.args[0], (AffineTransform) call.args[1], (ImageObserver) call.args[2]); } private void processDrawImage8(QueuedCall call, Graphics2D g) { // drawImage(BufferedImage, BufferedImageOp, int, int) g.drawImage((BufferedImage) call.args[0], (BufferedImageOp) call.args[1], (Integer) call.args[2], (Integer) call.args[3]); } private void processDrawRenderedImage(QueuedCall call, Graphics2D g) { // drawRenderedImage(RenderedImage, AffineTransform) g.drawRenderedImage((RenderedImage) call.args[0], (AffineTransform) call.args[1]); } private void processDrawRenderableImage(QueuedCall call, Graphics2D g) { // drawRenderableImage(RenderableImage, AffineTransform) g.drawRenderableImage((RenderableImage) call.args[0], (AffineTransform) call.args[1]); } private void processDrawString_float(QueuedCall call, Graphics2D g) { // drawString(String, float, float) g.drawString((String) call.args[0], (Float) call.args[1], (Float) call.args[2]); } private void processDrawString_ACIterator_float(QueuedCall call, Graphics2D g) { // drawString(AttributedCharacterIterator, float, float) g.drawString((AttributedCharacterIterator) call.args[0], (Float) call.args[1], (Float) call.args[2]); } private void processDrawGlyphVector(QueuedCall call, Graphics2D g) { // drawGlyphVector(GlyphVector gv, float x, float y) g.drawGlyphVector((GlyphVector) call.args[0], (Float) call.args[1], (Float) call.args[2]); } private void processFill(QueuedCall call, Graphics2D g) { // fill(Shape) g.fill((Shape) call.args[0]); } private void processSetComposite(QueuedCall call, Graphics2D g) { // setComposite(Composite) g.setComposite((Composite) call.args[0]); } private void processSetPaint(QueuedCall call, Graphics2D g) { // setPaint(Paint) g.setPaint((Paint) call.args[0]); } private void processSetStroke(QueuedCall call, Graphics2D g) { // setStroke(Stroke) g.setStroke((Stroke) call.args[0]); } private void processSetRenderingHint(QueuedCall call, Graphics2D g) { // setRenderingHint(Key, Object) g.setRenderingHint((Key) call.args[0], call.args[1]); } private void processSetRenderingHints(QueuedCall call, Graphics2D g) { // setRenderingHints(Map) g.setRenderingHints((Map) call.args[0]); } private void processAddRenderingHints(QueuedCall call, Graphics2D g) { // addRenderingHints(Map) g.addRenderingHints((Map) call.args[0]); } private void processTranslate_double(QueuedCall call, Graphics2D g) { // translate(double, double) g.translate((Double) call.args[0], (Double) call.args[1]); } private void processRotate(QueuedCall call, Graphics2D g) { // rotate(double) g.rotate((Double) call.args[0]); } private void processRotate_xy(QueuedCall call, Graphics2D g) { // rotate(double) g.rotate((Double) call.args[0], (Double) call.args[1], (Double) call.args[2]); } private void processScale(QueuedCall call, Graphics2D g) { // scale(double, double) g.scale((Double) call.args[0], (Double) call.args[1]); } private void processShear(QueuedCall call, Graphics2D g) { // shear(double, double) g.shear((Double) call.args[0], (Double) call.args[1]); } private void processTransform(QueuedCall call, Graphics2D g) { // transform(AffineTransform) g.transform((AffineTransform) call.args[0]); } private void processSetTransform(QueuedCall call, Graphics2D g) { // setTransform(AffineTransform) g.setTransform((AffineTransform) call.args[0]); } private void processSetBackground(QueuedCall call, Graphics2D g) { // setBackground(Color) g.setBackground(new Color((Integer) call.args[0], true)); } private void processClip(QueuedCall call, Graphics2D g) { // clip(Shape) g.clip((Shape) call.args[0]); } // -------------------------------------------------------------------------- // Worker classes // -------------------------------------------------------------------------- /** * Class used for containing a queued call with a method and it's parameter * values. * * @author Flemming N. Larsen */ public class QueuedCall implements java.io.Serializable { private static final long serialVersionUID = 1L; public final Method method; public final Object[] args; public QueuedCall(Method method, Object... args) { this.method = method; this.args = args; } } /** * Extended FontMetrics class which only purpose is to let us access its * protected contructor taking a Font as input parameter. * * @author Flemming N. Larsen */ private class FontMetricsByFont extends FontMetrics { private static final long serialVersionUID = 1L; FontMetricsByFont(Font font) { super(font); } } /* // For testing purpose public static void main(String... args) { Graphics2DProxy gfx = new Graphics2DProxy(); gfx.setTransform(AffineTransform.getRotateInstance(0.5)); gfx.setColor(Color.red); gfx.fillRect(0, 0, 100, 100); gfx.setColor(Color.BLACK); gfx.setFont(new Font("Monospace", Font.PLAIN, 22)); gfx.drawString("Hello World", 25, 25); final String filename = "C:/temp/tmp.bin"; try { FileOutputStream fos = new FileOutputStream(filename); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(gfx); oos.close(); } catch (Exception e) { e.printStackTrace(); System.exit(-1); } Graphics2DProxy gfx2 = null; try { FileInputStream fis = new FileInputStream(filename); ObjectInputStream ois = new ObjectInputStream(fis); gfx2 = (Graphics2DProxy) ois.readObject(); ois.close(); } catch (Exception e) { e.printStackTrace(); System.exit(-2); } final Graphics2DProxy paintGfx = gfx2; JFrame frame = new JFrame("Test"); frame.setBounds(50, 50, 300, 200); JPanel panel = new JPanel() { private static final long serialVersionUID = 1L; public void paint(Graphics g) { paintGfx.processTo((Graphics2D) g); } }; frame.add(panel); frame.setVisible(true); }*/ } robocode/robocode/robocode/MouseWheelMovedEvent.java0000644000175000017500000000425711130241112022143 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode; import robocode.peer.RobotStatics; import robocode.robotinterfaces.IBasicRobot; import robocode.robotinterfaces.IInteractiveEvents; import robocode.robotinterfaces.IInteractiveRobot; import java.awt.*; import java.awt.event.MouseWheelEvent; /** * A MouseWheelMovedEvent is sent to {@link Robot#onMouseWheelMoved(MouseWheelEvent) * onMouseWheelMoved()} when the mouse wheel is rotated inside the battle view. * * @author Pavel Savara (original) * @see MouseClickedEvent * @see MousePressedEvent * @see MouseReleasedEvent * @see MouseEnteredEvent * @see MouseExitedEvent * @see MouseMovedEvent * @see MouseDraggedEvent * @since 1.6.1 */ public final class MouseWheelMovedEvent extends MouseEvent { private static final long serialVersionUID = 1L; private final static int DEFAULT_PRIORITY = 98; /** * Called by the game to create a new MouseWheelMovedEvent. * * @param source the source mouse event originating from the AWT. */ public MouseWheelMovedEvent(java.awt.event.MouseEvent source) { super(source); } /** * {@inheritDoc} */ @Override final int getDefaultPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override final void dispatch(IBasicRobot robot, RobotStatics statics, Graphics2D graphics) { if (statics.isInteractiveRobot()) { IInteractiveEvents listener = ((IInteractiveRobot) robot).getInteractiveEventListener(); if (listener != null) { listener.onMouseWheelMoved((java.awt.event.MouseWheelEvent) getSourceEvent()); } } } } robocode/robocode/robocode/MouseDraggedEvent.java0000644000175000017500000000413011130241112021427 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode; import robocode.peer.RobotStatics; import robocode.robotinterfaces.IBasicRobot; import robocode.robotinterfaces.IInteractiveEvents; import robocode.robotinterfaces.IInteractiveRobot; import java.awt.*; /** * A MouseDraggedEvent is sent to {@link Robot#onMouseDragged(java.awt.event.MouseEvent) * onMouseDragged()} when the mouse is dragged inside the battle view. * * @author Pavel Savara (original) * @see MouseClickedEvent * @see MousePressedEvent * @see MouseReleasedEvent * @see MouseEnteredEvent * @see MouseExitedEvent * @see MouseMovedEvent * @see MouseWheelMovedEvent * @since 1.6.1 */ public final class MouseDraggedEvent extends MouseEvent { private static final long serialVersionUID = 1L; private final static int DEFAULT_PRIORITY = 98; /** * Called by the game to create a new MouseDraggedEvent. * * @param source the source mouse event originating from the AWT. */ public MouseDraggedEvent(java.awt.event.MouseEvent source) { super(source); } /** * {@inheritDoc} */ @Override final int getDefaultPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override final void dispatch(IBasicRobot robot, RobotStatics statics, Graphics2D graphics) { if (statics.isInteractiveRobot()) { IInteractiveEvents listener = ((IInteractiveRobot) robot).getInteractiveEventListener(); if (listener != null) { listener.onMouseDragged(getSourceEvent()); } } } } robocode/robocode/robocode/ScannedRobotEvent.java0000644000175000017500000001511111130241112021443 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Updated Javadocs *******************************************************************************/ package robocode; import robocode.peer.RobotStatics; import robocode.robotinterfaces.IBasicEvents; import robocode.robotinterfaces.IBasicRobot; import java.awt.*; /** * A ScannedRobotEvent is sent to {@link Robot#onScannedRobot(ScannedRobotEvent) * onScannedRobot()} when you scan a robot. * You can use the information contained in this event to determine what to do. * * @author Mathew A. Nelson (original) */ public final class ScannedRobotEvent extends Event { private static final long serialVersionUID = 1L; private final static int DEFAULT_PRIORITY = 10; private final String name; private final double energy; private final double heading; private final double bearing; private final double distance; private final double velocity; /** * Called by the game to create a new ScannedRobotEvent. * * @param name the name of the scanned robot * @param energy the energy of the scanned robot * @param bearing the bearing of the scanned robot, in radians * @param distance the distance from your robot to the scanned robot * @param heading the heading of the scanned robot * @param velocity the velocity of the scanned robot */ public ScannedRobotEvent(String name, double energy, double bearing, double distance, double heading, double velocity) { super(); this.name = name; this.energy = energy; this.bearing = bearing; this.distance = distance; this.heading = heading; this.velocity = velocity; } /** * Returns the bearing to the robot you scanned, relative to your robot's * heading, in degrees (-180 <= getBearing() < 180) * * @return the bearing to the robot you scanned, in degrees */ public double getBearing() { return bearing * 180.0 / Math.PI; } /** * Returns the bearing to the robot you scanned, relative to your robot's * heading, in radians (-PI <= getBearingRadians() < PI) * * @return the bearing to the robot you scanned, in radians */ public double getBearingRadians() { return bearing; } /** * Returns the distance to the robot (your center to his center). * * @return the distance to the robot. */ public double getDistance() { return distance; } /** * Returns the energy of the robot. * * @return the energy of the robot */ public double getEnergy() { return energy; } /** * Returns the heading of the robot, in degrees (0 <= getHeading() < 360) * * @return the heading of the robot, in degrees */ public double getHeading() { return heading * 180.0 / Math.PI; } /** * Returns the heading of the robot, in radians (0 <= getHeading() < 2 * PI) * * @return the heading of the robot, in radians */ public double getHeadingRadians() { return heading; } /** * @return the energy of the robot * @deprecated Use {@link #getEnergy()} instead. */ @Deprecated public double getLife() { return energy; } /** * Returns the name of the robot. * * @return the name of the robot */ public String getName() { return name; } /** * @return the bearing to the robot you scanned, in degrees * @deprecated Use {@link #getBearing()} instead. */ @Deprecated public double getRobotBearing() { return getBearing(); } /** * @return the robot bearing in degrees * @deprecated Use {@link #getBearing()} instead. */ @Deprecated public double getRobotBearingDegrees() { return getBearing(); } /** * @return the bearing to the robot you scanned, in radians * @deprecated Use {@link #getBearingRadians()} instead. */ @Deprecated public double getRobotBearingRadians() { return getBearingRadians(); } /** * @return the distance to the robot. * @deprecated Use {@link #getDistance()} instead. */ @Deprecated public double getRobotDistance() { return getDistance(); } /** * @return the heading of the robot, in degrees * @deprecated Use {@link #getHeading()} instead. */ @Deprecated public double getRobotHeading() { return getHeading(); } /** * @return the heading of the robot, in degrees * @deprecated Use {@link #getHeading()} instead. */ @Deprecated public double getRobotHeadingDegrees() { return getHeading(); } /** * @return the heading of the robot, in radians * @deprecated Use {@link #getHeadingRadians()} instead. */ @Deprecated public double getRobotHeadingRadians() { return getHeadingRadians(); } /** * @return the energy of the robot * @deprecated Use {@link #getEnergy()} instead. */ @Deprecated public double getRobotLife() { return getEnergy(); } /** * @return the name of the robot * @deprecated Use {@link #getName()} instead. */ @Deprecated public String getRobotName() { return getName(); } /** * @return the velocity of the robot * @deprecated Use {@link #getVelocity()} instead. */ @Deprecated public double getRobotVelocity() { return getVelocity(); } /** * Returns the velocity of the robot. * * @return the velocity of the robot */ public double getVelocity() { return velocity; } /** * {@inheritDoc} */ @Override public final int compareTo(Event event) { final int res = super.compareTo(event); if (res != 0) { return res; } // Compare the distance, if the events are ScannedRobotEvents // The shorter distance to the robot, the higher priority if (event instanceof ScannedRobotEvent) { return (int) (this.getDistance() - ((ScannedRobotEvent) event).getDistance()); } // No difference found return 0; } /** * {@inheritDoc} */ @Override final int getDefaultPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override final void dispatch(IBasicRobot robot, RobotStatics statics, Graphics2D graphics) { IBasicEvents listener = robot.getBasicEventListener(); if (listener != null) { listener.onScannedRobot(this); } } } robocode/robocode/robocode/text/0000755000175000017500000000000011107420624016215 5ustar lambylambyrobocode/robocode/robocode/text/StringUtil.java0000644000175000017500000000225311130241112021153 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Moved the getPlacementString() from robocode.util.Utils into this new * class *******************************************************************************/ package robocode.text; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ public class StringUtil { public static String getPlacementString(int i) { String result = "" + i; if (i > 3 && i < 20) { result += "th"; } else if (i % 10 == 1) { result += "st"; } else if (i % 10 == 2) { result += "nd"; } else if (i % 10 == 3) { result += "rd"; } else { result += "th"; } return result; } } robocode/robocode/robocode/text/LimitedClassnameDocument.java0000644000175000017500000000320211130241112023757 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation *******************************************************************************/ package robocode.text; import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; /** * @author Mathew A. Nelson (original) */ @SuppressWarnings("serial") public class LimitedClassnameDocument extends LimitedDocument { public LimitedClassnameDocument() { super(); } public LimitedClassnameDocument(int maxRows, int maxCols) { super(maxRows, maxCols); } @Override public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { if (offs == 0 && str.length() > 0) { if (!Character.isJavaIdentifierStart(str.charAt(0))) { java.awt.Toolkit.getDefaultToolkit().beep(); return; } } else { for (int i = 0; i < str.length(); i++) { if (!Character.isJavaIdentifierPart(str.charAt(i))) { java.awt.Toolkit.getDefaultToolkit().beep(); return; } } } if (offs == 0) { if (!Character.isUpperCase(str.charAt(0))) { str = str.substring(0, 1).toUpperCase() + str.substring(1); } } super.insertString(offs, str, a); } } robocode/robocode/robocode/text/LimitedDocument.java0000644000175000017500000000537111130241112022141 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation *******************************************************************************/ package robocode.text; import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; import javax.swing.text.Element; import javax.swing.text.PlainDocument; import java.awt.*; /** * @author Mathew A. Nelson (original) */ @SuppressWarnings("serial") public class LimitedDocument extends PlainDocument { int maxRows = Integer.MAX_VALUE; int maxCols = Integer.MAX_VALUE; public LimitedDocument() { super(); } public LimitedDocument(int maxRows, int maxCols) { super(); this.maxRows = maxRows; this.maxCols = maxCols; } @Override public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { Element rootElement = getDefaultRootElement(); int i = str.indexOf("\n"); int newlines = 0; while (i < str.length() && i >= 0) { newlines++; i = str.indexOf("\n", i + 1); } int currentLines = rootElement.getElementCount(); if (newlines > 0 && currentLines + newlines > maxRows) { Toolkit.getDefaultToolkit().beep(); return; } int lineIndex = rootElement.getElementIndex(offs); boolean done = false; int carry = rootElement.getElement(lineIndex).getEndOffset() - offs - 1; int lineStart = 0; while (!done) { int lineEnd = str.indexOf("\n", lineStart); if (lineEnd == -1 || lineEnd == str.length()) { if (lineStart == 0) { carry = 0; lineEnd = str.length(); } else { lineEnd = str.length() + carry; } done = true; } int lineLen = lineEnd - lineStart; // Increment for last line... int currentLen; if (!done && lineStart > 0) { currentLen = 0; } else { if (done && lineStart > 0) { lineIndex++; } Element currentLine = rootElement.getElement(lineIndex); if (currentLine != null) { currentLen = currentLine.getEndOffset() - currentLine.getStartOffset(); } else { currentLen = 1; } if (lineStart == 0) { currentLen -= carry; } } if (lineLen + currentLen > maxCols + 1) { Toolkit.getDefaultToolkit().beep(); return; } lineStart = lineEnd + 1; } super.insertString(offs, str, a); } } robocode/robocode/robocode/gfx/0000755000175000017500000000000011124142450016012 5ustar lambylambyrobocode/robocode/robocode/gfx/GraphicsState.java0000644000175000017500000000337711130241112021420 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen * - Initial implementation *******************************************************************************/ package robocode.gfx; import java.awt.*; import java.awt.geom.AffineTransform; /** * This class is used for storing the state of a Graphics object, which can be * restored later. * * @author Flemming N. Larsen (original) */ public class GraphicsState { private Paint paint; private Font font; private Stroke stroke; private AffineTransform transform; private Composite composite; private Shape clip; private RenderingHints renderingHints; private Color color; private Color background; public void save(Graphics g) { Graphics2D g2 = (Graphics2D) g; paint = g2.getPaint(); font = g2.getFont(); stroke = g2.getStroke(); transform = g2.getTransform(); composite = g2.getComposite(); clip = g2.getClip(); renderingHints = g2.getRenderingHints(); color = g2.getColor(); background = g2.getBackground(); } public void restore(Graphics g) { Graphics2D g2 = (Graphics2D) g; g2.setPaint(paint); g2.setFont(font); g2.setStroke(stroke); g2.setTransform(transform); g2.setComposite(composite); g2.setClip(clip); g2.setRenderingHints(renderingHints); g2.setColor(color); g2.setBackground(background); } } robocode/robocode/robocode/gfx/RobocodeLogo.java0000644000175000017500000003212011130241112021220 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen * - Initial implementation *******************************************************************************/ package robocode.gfx; import java.awt.*; import java.awt.geom.*; /** * This class is used for rendering the Robocode logo. * * @author Flemming N. Larsen (original) */ public class RobocodeLogo { public final static int WIDTH = 570; public final static int HEIGHT = 213; private final static Color WHITE_ALPHA_7F = new Color(0xff, 0xff, 0xff, 0x7f); private final static Color GLOW_GREEN = new Color(0x0A, 0xff, 0x0A, 0x66); private final static Color DARK_GREEN_ALPHA_80 = new Color(0x00, 0x70, 0x00, 0x80); private final static Color GREEN_ALPHA_08 = new Color(0x00, 0xff, 0x00, 0x08); private final static Color GREEN_ALPHA_20 = new Color(0x00, 0xff, 0x00, 0x20); private final static Color GREEN_ALPHA_40 = new Color(0x00, 0xff, 0x00, 0x40); private final static Color GREEN_ALPHA_48 = new Color(0x00, 0xff, 0x00, 0x48); private final static Color GREEN_ALPHA_80 = new Color(0x00, 0xff, 0x00, 0x80); private final static Shape I_SHAPE = new Rectangle2D.Float(0, 0, 13, 46); private final static Stroke THIN_STROKE = new BasicStroke(1.5f); public void paintLogoWithTanks(Graphics graphics) { Graphics2D g = (Graphics2D) graphics; AffineTransform origTransform = g.getTransform(); g.setColor(Color.BLACK); g.fillRect(0, 0, WIDTH, HEIGHT); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); drawTanks(g); drawOuterDecoration(g); drawMiddleEllipse(g); drawMiddleDecoration(g); drawInnerDecoration(g); drawInnerSubDecoration(g); drawRobocodeText(g); g.setTransform(origTransform); } private void transform(Graphics2D g, AffineTransform tx) { AffineTransform at = new AffineTransform(); if (tx != null) { at.concatenate(tx); } g.setTransform(at); } private void drawTanks(Graphics2D g) { AffineTransform origTransform = g.getTransform(); drawRobot(g, 22, 192, (float) Math.PI / 2, -0.2f, -0.2f, new Color(0x30, 0x00, 0x10, 0xff)); drawRobot(g, 22, 92, (float) Math.PI / 2, (float) Math.PI, (float) Math.PI, new Color(0x16, 0x00, 0x2c, 0xff)); drawRobot(g, 212, 173, 0.75f, 0.75f, 0.75f, new Color(0x02, 0x01, 0x00, 0xff)); drawRobot(g, 455, 50, 2.4f, 2f, 2f, new Color(0x02, 0x00, 0x01, 0xff)); drawRobot(g, 492, 82, -0.3f, -0.27f, -0.27f, new Color(0x00, 0x00, 0x01, 0xff)); transform(g, AffineTransform.getTranslateInstance(270, -25)); RenderImage explRenderImage1 = new RenderImage( ImageUtil.getImage("/resources/images/explosion/explosion2-24.png")); explRenderImage1.paint(g); transform(g, AffineTransform.getTranslateInstance(23, 102)); RenderImage explRenderImage2 = new RenderImage( ImageUtil.getImage("/resources/images/explosion/explosion1-8.png")); explRenderImage2.setTransform(AffineTransform.getScaleInstance(0.3, 0.3)); explRenderImage2.paint(g); transform(g, AffineTransform.getTranslateInstance(464, 55)); RenderImage explRenderImage3 = new RenderImage( ImageUtil.getImage("/resources/images/explosion/explosion1-1.png")); explRenderImage3.setTransform(AffineTransform.getScaleInstance(0.5, 0.5)); explRenderImage3.paint(g); transform(g, AffineTransform.getTranslateInstance(488, 72)); RenderImage explRenderImage4 = new RenderImage( ImageUtil.getImage("/resources/images/explosion/explosion1-6.png")); explRenderImage4.setTransform(AffineTransform.getScaleInstance(0.4, 0.4)); explRenderImage4.paint(g); transform(g, origTransform); g.setColor(Color.LIGHT_GRAY); g.fillOval(20, 154, 3, 3); } private void drawRobot(Graphics2D g, int x, int y, float bodyAngle, float gunAngle, float radarAngle, Color color) { transform(g, AffineTransform.getTranslateInstance(x, y)); RenderImage bodyRenderImage = new RenderImage( ImageUtil.createColouredRobotImage(ImageUtil.getImage("/resources/images/body.png"), color)); bodyRenderImage.setTransform(AffineTransform.getRotateInstance(bodyAngle)); bodyRenderImage.paint(g); RenderImage gunRenderImage = new RenderImage( ImageUtil.createColouredRobotImage(ImageUtil.getImage("/resources/images/turret.png"), color)); gunRenderImage.setTransform(AffineTransform.getRotateInstance(gunAngle)); gunRenderImage.paint(g); RenderImage radarRenderImage = new RenderImage( ImageUtil.createColouredRobotImage(ImageUtil.getImage("/resources/images/radar.png"), color)); radarRenderImage.setTransform(AffineTransform.getRotateInstance(radarAngle)); radarRenderImage.paint(g); } private void drawOuterDecoration(Graphics2D g) { Shape shape = getOuterDecoration(); transform(g, AffineTransform.getTranslateInstance(26, 24)); g.setColor(WHITE_ALPHA_7F); g.fill(shape); g.setStroke(THIN_STROKE); g.drawOval(16, 5, 490, 163); } private void drawMiddleEllipse(Graphics2D g) { transform(g, null); Shape ellipse = new Ellipse2D.Float(68, 38, 440, 146); g.setColor(DARK_GREEN_ALPHA_80); g.fill(ellipse); g.setColor(GREEN_ALPHA_40); g.setStroke(THIN_STROKE); g.draw(ellipse); } private void drawMiddleDecoration(Graphics2D g) { Shape shape = getMiddleDecoration(); transform(g, AffineTransform.getTranslateInstance(77, 41)); g.setColor(GREEN_ALPHA_20); g.fill(shape); g.setStroke(THIN_STROKE); g.setColor(GREEN_ALPHA_48); g.draw(shape); } private void drawInnerDecoration(Graphics2D g) { Shape shape = getInnerDecoration(); transform(g, AffineTransform.getTranslateInstance(103, 52)); g.setColor(DARK_GREEN_ALPHA_80); g.fill(shape); g.setStroke(THIN_STROKE); g.setColor(GLOW_GREEN); g.draw(shape); } private void drawInnerSubDecoration(Graphics2D g) { Shape shape = getInnerSubDecoration(); transform(g, AffineTransform.getTranslateInstance(110, 54)); g.setColor(GREEN_ALPHA_08); g.fill(shape); g.setStroke(THIN_STROKE); g.setColor(GREEN_ALPHA_48); g.draw(shape); } private void drawRobocodeText(Graphics2D g) { Shape shape = getRobocodeText(); transform(g, AffineTransform.getTranslateInstance(121, 88)); g.setColor(GREEN_ALPHA_40); g.fill(shape); g.setStroke(THIN_STROKE); g.setColor(GREEN_ALPHA_80); g.draw(shape); } private Area outerDecoration; private Shape getOuterDecoration() { if (outerDecoration == null) { float W = 523; float H = 174; outerDecoration = new Area(new Ellipse2D.Float(0, 0, W, H)); outerDecoration.subtract(new Area(new Ellipse2D.Float(16, 5, W - 2 * 16, H - 2 * 5))); outerDecoration.subtract(new Area(new Rectangle2D.Float(W / 2, 0, W / 2, H / 2))); outerDecoration.subtract(new Area(new Rectangle2D.Float(0, H / 2, W / 2, H / 2))); } return outerDecoration; } private Area middleDecoration; private Shape getMiddleDecoration() { if (middleDecoration == null) { middleDecoration = new Area(new Ellipse2D.Float(0, 0, 420, 140)); Rectangle2D.Float rect = new Rectangle2D.Float(180, 69, 500, 3); for (float deg = 120; deg <= 335; deg += 4.8f) { Area rectArea = new Area(rect); rectArea.transform(AffineTransform.getRotateInstance(Math.toRadians(deg), 151, 72)); middleDecoration.subtract(rectArea); } middleDecoration.subtract(new Area(new Ellipse2D.Float(18, 2, 408, 144))); } return middleDecoration; } private Area innerSubDecoration; private Shape getInnerSubDecoration() { if (innerSubDecoration == null) { innerSubDecoration = new Area(new Ellipse2D.Float(0, 0, 356, 114)); innerSubDecoration.subtract( new Area(new Rectangle2D.Float(Float.MIN_VALUE, Float.MIN_VALUE, Float.MAX_VALUE, 88))); innerSubDecoration.subtract( new Area(new Rectangle2D.Float(Float.MIN_VALUE, Float.MIN_VALUE, 184, Float.MAX_VALUE))); innerSubDecoration.subtract(new Area(new Rectangle2D.Float(209, Float.MIN_VALUE, 3, Float.MAX_VALUE))); } return innerSubDecoration; } private Area innerDecoration; private Shape getInnerDecoration() { if (innerDecoration == null) { innerDecoration = new Area(new Ellipse2D.Float(0, 0, 368, 120)); innerDecoration.subtract(new Area(new Rectangle2D.Float(Float.MIN_VALUE, 30, Float.MAX_VALUE, 56))); innerDecoration.subtract(new Area(new Rectangle2D.Float(181, Float.MIN_VALUE, 7, Float.MAX_VALUE))); } return innerDecoration; } private GeneralPath robocodeTextPath; public GeneralPath getRobocodeText() { if (robocodeTextPath == null) { robocodeTextPath = new GeneralPath(); GeneralPath R = getPathR(); GeneralPath o = getPathO(); GeneralPath b = getPathB(); GeneralPath c = getPathC(); GeneralPath d = getPathD(); GeneralPath e = getPathE(); robocodeTextPath.append(R, false); o.transform(AffineTransform.getTranslateInstance(42, 16)); robocodeTextPath.append(o, false); b.transform(AffineTransform.getTranslateInstance(84, 0)); robocodeTextPath.append(b, false); o.transform(AffineTransform.getTranslateInstance(127 - 42, 0)); robocodeTextPath.append(o, false); c.transform(AffineTransform.getTranslateInstance(170, 16)); robocodeTextPath.append(c, false); o.transform(AffineTransform.getTranslateInstance(204 - 127, 0)); robocodeTextPath.append(o, false); d.transform(AffineTransform.getTranslateInstance(246, 0)); robocodeTextPath.append(d, false); e.transform(AffineTransform.getTranslateInstance(290, 16)); robocodeTextPath.append(e, false); } return robocodeTextPath; } private GeneralPath getPathR() { GeneralPath path = new GeneralPath(I_SHAPE); GeneralPath bow = getPathPBow(); bow.transform(AffineTransform.getTranslateInstance(15, 0)); path.append(bow, false); path.moveTo(21, 29); path.lineTo(31, 46); path.lineTo(44.5f, 46); path.lineTo(33.5f, 27); path.curveTo(33.5f, 27, 31, 29, 21, 29); path.closePath(); return path; } private GeneralPath getPathO() { GeneralPath path = getPathOBow(); path.transform(AffineTransform.getTranslateInstance(20, 0)); GeneralPath bow2 = getPathOBow(); bow2.transform(AffineTransform.getScaleInstance(-1, 1)); bow2.transform(AffineTransform.getTranslateInstance(18, 0)); path.append(bow2, false); return path; } private GeneralPath getPathB() { GeneralPath path = new GeneralPath(I_SHAPE); GeneralPath bow = getPathPBow(); bow.transform(AffineTransform.getTranslateInstance(15, 20)); path.append(bow, false); return path; } private GeneralPath getPathC() { GeneralPath path = getPathCBow(); GeneralPath bow2 = getPathCBow(); bow2.transform(AffineTransform.getScaleInstance(1, -1)); bow2.transform(AffineTransform.getTranslateInstance(0, 31)); path.append(bow2, false); return path; } private GeneralPath getPathD() { GeneralPath path = new GeneralPath(I_SHAPE); path.transform(AffineTransform.getTranslateInstance(27, 0)); GeneralPath bow = getPathPBow(); bow.transform(AffineTransform.getScaleInstance(-1, 1)); bow.transform(AffineTransform.getTranslateInstance(25, 20)); path.append(bow, false); return path; } private GeneralPath getPathE() { GeneralPath path = new GeneralPath(); path.moveTo(0, 14.5f); path.lineTo(31, 14.5f); path.curveTo(31, -4.5f, 0, -4.5f, 0, 14.5f); path.closePath(); path.moveTo(12, 11); path.lineTo(20, 11); path.curveTo(20, 8, 12, 8, 12, 11); path.closePath(); GeneralPath bow2 = getPathCBow(); bow2.transform(AffineTransform.getScaleInstance(1, -1)); bow2.transform(AffineTransform.getTranslateInstance(0, 31)); path.append(bow2, false); return path; } private GeneralPath getPathPBow() { GeneralPath path = new GeneralPath(); path.moveTo(0, 0); path.lineTo(10, 0); path.curveTo(30, 0, 30, 26, 10, 26); path.lineTo(0, 26); path.lineTo(0, 17); path.lineTo(8, 17); path.curveTo(14, 18, 14, 9, 8, 9); path.lineTo(0, 9); path.lineTo(0, 0); path.closePath(); return path; } private GeneralPath getPathOBow() { GeneralPath path = new GeneralPath(); path.moveTo(0, 0); path.curveTo(23, 0, 23, 31, 0, 31); path.lineTo(0, 20); path.curveTo(8, 20, 8, 11, 0, 11); path.lineTo(0, 0); path.closePath(); return path; } private GeneralPath getPathCBow() { GeneralPath path = new GeneralPath(); path.moveTo(31, 12); path.curveTo(29, -3.5f, 2, -5.5f, 0, 14.5f); path.lineTo(11, 14.5f); path.curveTo(11, 8.5f, 18, 9, 18, 12); path.lineTo(31, 12); path.closePath(); return path; } } robocode/robocode/robocode/gfx/ImageUtil.java0000644000175000017500000000640011130241112020525 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen * - Initial implementation *******************************************************************************/ package robocode.gfx; import robocode.io.Logger; import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.awt.image.FilteredImageSource; import java.awt.image.RGBImageFilter; import java.net.URL; /** * Class used for utilizing images. * * @author Flemming N. Larsen (original) */ public class ImageUtil { /** * Returns an image resource. * * @param filename the filename of the image to load * @return the loaded image */ public static Image getImage(String filename) { URL url = ClassLoader.class.getResource(filename); if (url == null) { Logger.logError("Could not load image because of invalid filename: " + filename); return null; } try { return ImageIO.read(url); } catch (Exception e) { Logger.logError("Could not load image: " + filename); return null; } } /** * Creates and returns a buffered version of the specified image. * * @param image the image to create a buffered image for * @return a buffered image based on the specified image */ public static BufferedImage getBufferedImage(Image image) { BufferedImage bufferedImage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB); Graphics g = bufferedImage.getGraphics(); g.drawImage(image, 0, 0, null); return bufferedImage; } /** * Create a copy of an robot image into a coloured robot image. The colors of the * input image are changed into the input color, but with the same lumination. * * @param img the source image * @param color the new color that substitutes the old color(s) in the source image * @return a new image */ public static Image createColouredRobotImage(Image img, Color color) { return (color == null) ? img : (img == null) ? null : Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(img.getSource(), new ColorFilter(color))); } /** * A color filter used for changing colors into another color. * * @author Flemming N. Larsen */ private static class ColorFilter extends RGBImageFilter { private final float[] hsl; public ColorFilter(Color color) { hsl = ColorUtil.fromRGBtoHSL(color.getRed(), color.getGreen(), color.getBlue()); } @Override public int filterRGB(int x, int y, int argb) { int r = (argb >> 16) & 0xff; int g = (argb >> 8) & 0xff; int b = argb & 0xff; float[] HSL = ColorUtil.fromRGBtoHSL(r, g, b); if (HSL[1] > 0) { float L = Math.min(1, (hsl[2] + HSL[2]) / 2 + hsl[2] / 7); return argb & 0xff000000 | ColorUtil.fromHSLtoRGB(hsl[0], hsl[1], L); } return argb; } } } robocode/robocode/robocode/gfx/RenderObject.java0000644000175000017500000000702511130241112021217 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen * - Initial implementation *******************************************************************************/ package robocode.gfx; import java.awt.*; import java.awt.geom.AffineTransform; /** * The base of all renderable objects. * An {@code RenderObject} is an object that can be painted and transformed. * * @author Flemming N. Larsen (original) */ public class RenderObject { /** * Base transform, e.g. the initial rotation and translation */ protected AffineTransform baseTransform; /** * Current transform that is concatenated with the base transform */ protected final AffineTransform transform; /** * Current frame that must be rendered */ protected int frame; /** * Constructs a new {@code RenderObject}. */ public RenderObject() { baseTransform = new AffineTransform(); transform = new AffineTransform(); } /** * Constructs a new {@code RenderObject} that is a copy of another {@code RenderObject}. * * @param renderObject the RenderObject to copy. */ public RenderObject(RenderObject renderObject) { baseTransform = new AffineTransform(renderObject.baseTransform); transform = new AffineTransform(renderObject.transform); frame = renderObject.frame; } /** * Sets the base transform which is pre-concatenated with the current transform. * * @param Tx the new transform */ public void setBaseTransform(AffineTransform Tx) { baseTransform.setTransform(Tx); } /** * Returns a copy of the base transform * * @return a copy of the base transform */ public AffineTransform getBaseTransform() { return new AffineTransform(baseTransform); } /** * Sets the current transform, which is concatenated with the base transform. * * @param Tx the new transform */ public void setTransform(AffineTransform Tx) { transform.setTransform(Tx); transform.concatenate(baseTransform); } /** * Returns a copy of the current transform * * @return a copy of the current transform */ public AffineTransform getTransform() { return transform; } /** * Sets the current frame number * * @param frame the new frame number */ public void setFrame(int frame) { this.frame = frame; } /** * Returns the current frame number * * @return the current frame number */ public int getFrame() { return frame; } /** * Paint this object. * This method must be overridden in derived classes. * * @param g the graphics context where this object must be painted. */ public void paint(Graphics2D g) {} /** * Returns the bounds of this object based on it's current transform. * This method must be overridden in derived classes. * * @return the bounds of this object based on it's current transform. */ public Rectangle getBounds() { return new Rectangle(); } /** * Returns a copy of this object. * This method must be overridden in derived classes. * * @return a copy of this object. */ public RenderObject copy() { return new RenderObject(this); } } robocode/robocode/robocode/gfx/RenderImage.java0000644000175000017500000000453611130241112021037 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen * - Initial implementation *******************************************************************************/ package robocode.gfx; import java.awt.*; import java.awt.geom.AffineTransform; import java.awt.geom.Area; /** * An image that can be rendered. * * @author Flemming N. Larsen (original) */ public class RenderImage extends RenderObject { /** * Image */ protected final Image image; /** * Area containing the bounds of the image to paint */ protected final Area boundArea; /** * Constructs a new {@code RenderImage}, which has it's origin in the center * of the image. * * @param image the image to be rendered */ public RenderImage(Image image) { this(image, ((double) image.getWidth(null) / 2), ((double) image.getHeight(null) / 2)); } /** * Constructs a new {@code RenderImage} * * @param image the image to be rendered * @param originX the x coordinate of the origin for the rendered image * @param originY the y coordinate of the origin for the rendered image */ public RenderImage(Image image, double originX, double originY) { super(); this.image = image; baseTransform = AffineTransform.getTranslateInstance(-originX, -originY); boundArea = new Area(new Rectangle(0, 0, image.getWidth(null), image.getHeight(null))); } /** * Constructs a new {@code RenderImage} that is a copy of another * {@code RenderImage}. * * @param ri the {@code RenderImage} to copy */ public RenderImage(RenderImage ri) { super(ri); image = ri.image; boundArea = new Area(ri.boundArea); } @Override public void paint(Graphics2D g) { g.drawImage(image, transform, null); } @Override public Rectangle getBounds() { return boundArea.createTransformedArea(transform).getBounds(); } @Override public RenderObject copy() { return new RenderImage(this); } } robocode/robocode/robocode/gfx/ColorUtil.java0000644000175000017500000001006311130241112020561 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen * - Initial implementation *******************************************************************************/ package robocode.gfx; import static robocode.util.Utils.isNear; import java.awt.*; /** * Class used for utilizing colors. * * @author Flemming N. Larsen (original) */ public class ColorUtil { /** * Return a Color based on a color in RGB565 format. * * @param rgb565 the color in RGB565 format. * @return a Color based on the specifed color in RGB565 format. */ public static Color toColor(short rgb565) { if (rgb565 == 0) { return null; } if (rgb565 == 0x20) { return Color.BLACK; } return new Color(255 * ((rgb565 & 0xF800) >> 11) / 31, 255 * ((rgb565 & 0x07e0) >> 5) / 63, 255 * (rgb565 & 0x001f) / 31); } /** * Returns a color in the RGB565 format based on a Color instance. * * @param c the color to convert into a RGB565 color. * @return a color in the RGB565 format based on the specified Color. */ public static short toRGB565(Color c) { if (c == null) { return 0; } short rgb = (short) (((c.getRed() & 0xf8) << 8) | ((c.getGreen() & 0xfc) << 3) | (c.getBlue() >> 3)); // 0 is reserved for null -> set green (has highest resolution) to 1 if (rgb == 0) { return 0x20; } // If the color actually was 0x20 then set it to 0x40 (to the nearest green) if (rgb == 0x20) { return 0x40; } return rgb; } /** * Converts a RGB color into a HSL color. * * @param r the red color component. * @param g the green color component. * @param b the blue color component. * @return a {@code float[] { H, S, L }} representing the HSL color. */ public static float[] fromRGBtoHSL(int r, int g, int b) { float R = (float) r / 255; float G = (float) g / 255; float B = (float) b / 255; float min = Math.min(Math.min(R, G), B); // Min. value of RGB float max = Math.max(Math.max(R, G), B); // Max. value of RGB float delta = max - min; // Delta RGB value float L = (max + min) / 2; float H, S; if (delta == 0) { // This is a gray, no chroma... H = 0; S = 0; } else { // Chromatic data... if (L < 0.5f) { S = delta / (max + min); } else { S = delta / (2 - max - min); } float deltaR = (((max - R) / 6) + (delta / 2)) / delta; float deltaG = (((max - G) / 6) + (delta / 2)) / delta; float deltaB = (((max - B) / 6) + (delta / 2)) / delta; if (isNear(R, max)) { H = deltaB - deltaG; } else if (isNear(G, max)) { H = (1f / 3) + deltaR - deltaB; } else { H = (2f / 3) + deltaG - deltaR; } if (H < 0) { H++; } if (H > 1) { H--; } } return new float[] { H, S, L}; } /** * Converts a HSL color into a RGB color integer value. * * @param h the color hue. * @param s the color saturation. * @param l the color lumination. * @return an RGB integer value. */ public static int fromHSLtoRGB(float h, float s, float l) { float m2 = (l <= 0.5f) ? (l * (s + 1)) : (l + s - l * s); float m1 = 2 * l - m2; int r = (int) (255 * fromHUEtoRGB(m1, m2, h + (1f / 3))); int g = (int) (255 * fromHUEtoRGB(m1, m2, h)); int b = (int) (255 * fromHUEtoRGB(m1, m2, h - (1f / 3))); return (((r << 8) | g) << 8) | b; } private static float fromHUEtoRGB(float m1, float m2, float h) { if (h < 0) { h++; } if (h > 1) { h--; } if ((h * 6) < 1) { return m1 + (m2 - m1) * h * 6; } if ((h * 2) < 1) { return m2; } if ((h * 3) < 2) { return m1 + (m2 - m1) * ((2f / 3) - h) * 6; } return m1; } } robocode/robocode/robocode/robotinterfaces/0000755000175000017500000000000011107420736020426 5ustar lambylambyrobocode/robocode/robocode/robotinterfaces/IJuniorRobot.java0000644000175000017500000000332311130241112023640 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.robotinterfaces; /** * A robot interface for creating the most primitive robot type, which is a * {@link robocode.JuniorRobot}. A junior robot is simpler than the * {@link robocode.Robot} class. *

* A junior robot has a simplified model, in purpose of teaching programming * skills to inexperienced in programming students. * The simplified robot model will keep player from overwhelming of Robocode's * rules, programming syntax and programming concept. *

* Instead of using getters and setters, public fields are provided for * receiving information like the last scanned robot, the coordinate of the * robot etc. *

* All methods on a junior robot are blocking calls, i.e. they do not return * before their action has been completed and will at least take one turn to * execute. * * @author Pavel Savara (original) * @author Flemming N. Larsen (javadoc) * @see robocode.JuniorRobot * @see IBasicRobot * @see IAdvancedRobot * @see IInteractiveRobot * @see ITeamRobot * @since 1.6 */ public interface IJuniorRobot extends IBasicRobot {} robocode/robocode/robocode/robotinterfaces/IBasicEvents.java0000644000175000017500000002161211130241112023573 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.robotinterfaces; import robocode.*; /** * An event interface for receiving basic robot events with an * {@link IBasicRobot}. * * @author Pavel Savara (original) * @author Flemming N. Larsen (javadoc) * @see IBasicRobot * @since 1.6 */ public interface IBasicEvents { /** * This method is called every turn in a battle round in order to provide * the robot status as a complete snapshot of the robot's current state at * that specific time. *

* The main benefit of this method is that you'll automatically receive all * current data values of the robot like e.g. the x and y coordinate, * heading, gun heat etc., which are grouped into the exact same time/turn. *

* This is the only way to map the robots data values to a specific time. * For example, it is not possible to determine the exact time of the * robot's heading by calling first calling {@link Robot#getTime()} and then * {@link Robot#getHeading()} afterwards, as the time might change * after between the {@link Robot#getTime()} and {@link Robot#getHeading()} * call. * * @param event the event containing the robot status at the time it occurred. * @see StatusEvent * @see Event * @since 1.5 */ void onStatus(StatusEvent event); /** * This method is called when one of your bullets hits another robot. * You should override it in your robot if you want to be informed of this * event. *

* Example: *

	 *   public void onBulletHit(BulletHitEvent event) {
	 *       out.println("I hit " + event.getName() + "!");
	 *   }
	 * 
* * @param event the bullet-hit event set by the game * @see BulletHitEvent * @see Event */ void onBulletHit(BulletHitEvent event); /** * This method is called when one of your bullets hits another bullet. * You should override it in your robot if you want to be informed of this * event. *

* Example: *

	 *   public void onBulletHitBullet(BulletHitBulletEvent event) {
	 *       out.println("I hit a bullet fired by " + event.getBullet().getName() + "!");
	 *   }
	 * 
* * @param event the bullet-hit-bullet event set by the game * @see BulletHitBulletEvent * @see Event */ void onBulletHitBullet(BulletHitBulletEvent event); /** * This method is called when one of your bullets misses, i.e. hits a wall. * You should override it in your robot if you want to be informed of this * event. *

* Example: *

	 *   public void onBulletHit(BulletMissedEvent event) {
	 *       out.println("Drat, I missed.");
	 *   }
	 * 
* * @param event the bullet-missed event set by the game * @see BulletMissedEvent * @see Event */ void onBulletMissed(BulletMissedEvent event); /** * This method is called if your robot dies. *

* You should override it in your robot if you want to be informed of this * event. Actions will have no effect if called from this section. The * intent is to allow you to perform calculations or print something out * when the robot is killed. * * @param event the death event set by the game * @see DeathEvent * @see WinEvent * @see BattleEndedEvent * @see Event */ public void onDeath(DeathEvent event); /** * This method is called when your robot is hit by a bullet. * You should override it in your robot if you want to be informed of this * event. *

* Example: *

	 *   void onHitByBullet(HitByBulletEvent event) {
	 *       out.println(event.getRobotName() + " hit me!");
	 *   }
	 * 
* * @param event the hit-by-bullet event set by the game * @see HitByBulletEvent * @see Event */ void onHitByBullet(HitByBulletEvent event); /** * This method is called when your robot collides with another robot. * You should override it in your robot if you want to be informed of this * event. *

* Example: *

	 *   void onHitRobot(HitRobotEvent event) {
	 *       if (event.getBearing() > -90 && event.getBearing() <= 90) {
	 *           back(100);
	 *       } else {
	 *           ahead(100);
	 *       }
	 *   }
	 * 

* -- or perhaps, for a more advanced robot -- *

* public void onHitRobot(HitRobotEvent event) { * if (event.getBearing() > -90 && event.getBearing() <= 90) { * setBack(100); * } else { * setAhead(100); * } * } *

*

* The angle is relative to your robot's facing. So 0 is straight ahead of * you. *

* This event can be generated if another robot hits you, in which case * {@link HitRobotEvent#isMyFault() event.isMyFault()} will return * {@code false}. In this case, you will not be automatically stopped by the * game -- but if you continue moving toward the robot you will hit it (and * generate another event). If you are moving away, then you won't hit it. * * @param event the hit-robot event set by the game * @see HitRobotEvent * @see Event */ void onHitRobot(HitRobotEvent event); /** * This method is called when your robot collides with a wall. * You should override it in your robot if you want to be informed of this * event. *

* The wall at the top of the screen is 0 degrees, right is 90 degrees, * bottom is 180 degrees, left is 270 degrees. But this event is relative to * your heading, so: The bearing is such that {@link Robot#turnRight(double) * turnRight} {@link HitWallEvent#getBearing() (event.getBearing())} will * point you perpendicular to the wall. *

* Example: *

	 *   void onHitWall(HitWallEvent event) {
	 *       out.println("Ouch, I hit a wall bearing " + event.getBearing() + " degrees.");
	 *   }
	 * 
* * @param event the hit-wall event set by the game * @see HitWallEvent * @see Event */ void onHitWall(HitWallEvent event); /** * This method is called when your robot sees another robot, i.e. when the * robot's radar scan "hits" another robot. * You should override it in your robot if you want to be informed of this * event. (Almost all robots should override this!) *

* This event is automatically called if there is a robot in range of your * radar. *

* Note that the robot's radar can only see robot within the range defined * by {@link Rules#RADAR_SCAN_RADIUS} (1200 pixels). *

* Also not that the bearing of the scanned robot is relative to your * robot's heading. *

* Example: *

	 *   void onScannedRobot(ScannedRobotEvent event) {
	 *       // Assuming radar and gun are aligned...
	 *       if (event.getDistance() < 100) {
	 *           fire(3);
	 *       } else {
	 *           fire(1);
	 *       }
	 *   }
	 * 
*

* Note:
* The game assists Robots in firing, as follows: *

    *
  • If the gun and radar are aligned (and were aligned last turn), *
  • and the event is current, *
  • and you call fire() before taking any other actions, {@link * Robot#fire(double) fire()} will fire directly at the robot. *
*

* In essence, this means that if you can see a robot, and it doesn't move, * then fire will hit it. *

* AdvancedRobots will NOT be assisted in this manner, and are expected to * examine the event to determine if {@link Robot#fire(double) fire()} would * hit. (i.e. you are spinning your gun around, but by the time you get the * event, your gun is 5 degrees past the robot). * * @param event the scanned-robot event set by the game * @see ScannedRobotEvent * @see Event * @see Rules#RADAR_SCAN_RADIUS */ void onScannedRobot(ScannedRobotEvent event); /** * This method is called when another robot dies. * You should override it in your robot if you want to be informed of this * event. * * @param event The robot-death event set by the game * @see RobotDeathEvent * @see Event */ void onRobotDeath(RobotDeathEvent event); /** * This method is called if your robot wins a battle. *

* Your robot could perform a victory dance here! :-) * * @param event the win event set by the game * @see DeathEvent * @see BattleEndedEvent * @see Event */ void onWin(WinEvent event); } robocode/robocode/robocode/robotinterfaces/IAdvancedEvents.java0000644000175000017500000000416211130241112024260 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.robotinterfaces; import robocode.CustomEvent; import robocode.SkippedTurnEvent; /** * An event interface for receiving advanced robot events with an * {@link IAdvancedRobot}. * * @author Pavel Savara (original) * @author Flemming N. Larsen (javadoc) * @see IAdvancedRobot * @since 1.6 */ public interface IAdvancedEvents { /** * This method is called if the robot is using too much time between * actions. When this event occur, the robot's turn is skipped, meaning that * it cannot take action anymore in this turn. *

* If you receive 30 skipped turn event, your robot will be removed from the * round and loose the round. *

* You will only receive this event after taking an action. So a robot in an * infinite loop will not receive any events, and will simply be stopped. *

* No correctly working, reasonable robot should ever receive this event * unless it is using too many CPU cycles. * * @param event the skipped turn event set by the game * @see robocode.SkippedTurnEvent * @see robocode.Event */ void onSkippedTurn(SkippedTurnEvent event); /** * This method is called when a custom condition is met. *

* See the sample robots for examples of use, e.g. the {@code sample.Target} * robot. * * @param event the custom event that occurred * @see robocode.AdvancedRobot#addCustomEvent * @see robocode.CustomEvent * @see robocode.Event */ void onCustomEvent(CustomEvent event); } robocode/robocode/robocode/robotinterfaces/IPaintRobot.java0000644000175000017500000000237511130241112023453 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.robotinterfaces; /** * A robot interface that makes it possible for a robot to receive paint events. * * @author Pavel Savara (original) * @author Flemming N. Larsen (javadoc) * @since 1.6 */ public interface IPaintRobot extends IBasicRobot { /** * This method is called by the game to notify this robot about painting * events. Hence, this method must be implemented so it returns your * {@link IPaintEvents} listener. * * @return listener to paint events or {@code null} if this robot should * not receive the notifications. * @since 1.6 */ IPaintEvents getPaintEventListener(); } robocode/robocode/robocode/robotinterfaces/IBasicEvents2.java0000644000175000017500000000265411130241112023662 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.robotinterfaces; import robocode.BattleEndedEvent; /** * First extended version of the {@link IBasicEvents} interface. * * @author Pavel Savara (original) * @since 1.6.1 */ public interface IBasicEvents2 extends IBasicEvents { /** * This method is called after end of the battle, even when the battle is aborted. * You should override it in your robot if you want to be informed of this event. *

* Example: *

	 *   public void onBattleEnded(BattleEndedEvent event) {
	 *       out.println("The battle has ended");
	 *   }
	 * 
* * @param event the battle-ended event set by the game * @see BattleEndedEvent * @see robocode.WinEvent * @see robocode.DeathEvent * @see robocode.Event */ void onBattleEnded(BattleEndedEvent event); } robocode/robocode/robocode/robotinterfaces/IAdvancedRobot.java0000644000175000017500000000314511130241112024101 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.robotinterfaces; /** * A robot interface for creating a more advanced type of robot like * {@link robocode.AdvancedRobot} that is able to handle advanced robot events. * An advanced robot allows non-blocking calls, custom events, get notifications * about skipped turns, and also allow writes to the file system. * * @author Pavel Savara (original) * @author Flemming N. Larsen (javadoc) * @see robocode.AdvancedRobot * @see IBasicRobot * @see IJuniorRobot * @see IInteractiveRobot * @see ITeamRobot * @since 1.6 */ public interface IAdvancedRobot extends IBasicRobot { /** * This method is called by the game to notify this robot about advanced * robot event. Hence, this method must be implemented so it returns your * {@link IAdvancedEvents} listener. * * @return listener to advanced events or {@code null} if this robot should * not receive the notifications. * @since 1.6 */ IAdvancedEvents getAdvancedEventListener(); } robocode/robocode/robocode/robotinterfaces/ITeamRobot.java0000644000175000017500000000303411130241112023257 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.robotinterfaces; /** * A robot interface for creating a team robot like {@link robocode.TeamRobot} * that is able to receive team events. * A team robot is an advanced type of robot that supports sending messages * between teammates that participates in a team. * * @author Pavel Savara (original) * @author Flemming N. Larsen (javadoc) * @see robocode.TeamRobot * @see IBasicRobot * @see IJuniorRobot * @see IInteractiveRobot * @see IAdvancedRobot * @see ITeamRobot * @since 1.6 */ public interface ITeamRobot extends IAdvancedRobot { /** * This method is called by the game to notify this robot about team events. * Hence, this method must be implemented so it returns your * {@link ITeamEvents} listener. * * @return listener to team events or {@code null} if this robot should * not receive the notifications. */ ITeamEvents getTeamEventListener(); } robocode/robocode/robocode/robotinterfaces/IInteractiveRobot.java0000644000175000017500000000356011130241112024652 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.robotinterfaces; /** * A robot interface for creating an interactive type of robot like * {@link robocode.Robot} and {@link robocode.AdvancedRobot} that is able to * receive interactive events from the keyboard or mouse. * If a robot is directly inherited from this class it will behave as similar to * a {@link IBasicRobot}. If you need it to behave similar to a * {@link IAdvancedRobot} or {@link ITeamRobot}, you should inherit from these * interfaces instead, as these are inherited from this interface. * * @author Pavel Savara (original) * @author Flemming N. Larsen (javadoc) * @see robocode.Robot * @see robocode.AdvancedRobot * @see IBasicRobot * @see IJuniorRobot * @see IAdvancedRobot * @see ITeamRobot * @since 1.6 */ public interface IInteractiveRobot extends IBasicRobot { /** * This method is called by the game to notify this robot about interactive * events, i.e. keyboard and mouse events. Hence, this method must be * implemented so it returns your {@link IInteractiveEvents} listener. * * @return listener to interactive events or {@code null} if this robot * should not receive the notifications. * @since 1.6 */ IInteractiveEvents getInteractiveEventListener(); } robocode/robocode/robocode/robotinterfaces/ITeamEvents.java0000644000175000017500000000270611130241112023443 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.robotinterfaces; import robocode.MessageEvent; /** * An event interface for receiving robot team events with an * {@link ITeamRobot}. * * @author Pavel Savara (original) * @author Flemming N. Larsen (javadoc) * @see ITeamRobot * @since 1.6 */ public interface ITeamEvents { /** * This method is called when your robot receives a message from a teammate. * You should override it in your robot if you want to be informed of this * event. *

* Example: *

	 *   public void onMessageReceived(MessageEvent event) {
	 *       out.println(event.getSender() + " sent me: " + event.getMessage());
	 *   }
	 * 
* * @param event the message event sent by the game * @see robocode.MessageEvent * @see robocode.Event */ void onMessageReceived(MessageEvent event); } robocode/robocode/robocode/robotinterfaces/package.html0000644000175000017500000000017411006202516022701 0ustar lambylamby Robot Interfaces used for creating new robot types, e.g. with other programming languages. robocode/robocode/robocode/robotinterfaces/IInteractiveEvents.java0000644000175000017500000001640511130241112025033 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.robotinterfaces; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseWheelEvent; /** * An event interface for receiving interactive events with an * {@link IInteractiveRobot}. * * @author Pavel Savara (original) * @author Flemming N. Larsen (javadoc) * @see IInteractiveRobot * @since 1.6 */ public interface IInteractiveEvents { /** * This method is called when a key has been pressed. *

* See the {@code sample.Interactive} robot for an example of how to use * key events. * * @param event holds details about current event * @see java.awt.event.KeyListener#keyPressed(KeyEvent) * @see #onKeyReleased(KeyEvent) * @see #onKeyTyped(KeyEvent) * @since 1.3.4 */ void onKeyPressed(KeyEvent event); /** * This method is called when a key has been released. *

* See the {@code sample.Interactive} robot for an example of how to use * key events. * * @param event holds details about current event * @see java.awt.event.KeyListener#keyReleased(KeyEvent) * @see #onKeyPressed(KeyEvent) * @see #onKeyTyped(KeyEvent) * @since 1.3.4 */ void onKeyReleased(KeyEvent event); /** * This method is called when a key has been typed (pressed and released). *

* See the {@code sample.Interactive} robot for an example of how to use * key events. * * @param event holds details about current event * @see java.awt.event.KeyListener#keyTyped(KeyEvent) * @see #onKeyPressed(KeyEvent) * @see #onKeyReleased(KeyEvent) * @since 1.3.4 */ void onKeyTyped(KeyEvent event); /** * This method is called when a mouse button has been clicked (pressed and * released). *

* See the {@code sample.Interactive} robot for an example of how to use * mouse events. * * @param event holds details about current event * @see java.awt.event.MouseListener#mouseClicked(MouseEvent) * @see #onMouseMoved(MouseEvent) * @see #onMousePressed(MouseEvent) * @see #onMouseReleased(MouseEvent) * @see #onMouseEntered(MouseEvent) * @see #onMouseExited(MouseEvent) * @see #onMouseDragged(MouseEvent) * @see #onMouseWheelMoved(MouseWheelEvent) * @since 1.3.4 */ void onMouseClicked(MouseEvent event); /** * This method is called when the mouse has entered the battle view. *

* See the {@code sample.Interactive} robot for an example of how to use * mouse events. * * @param event holds details about current event * @see java.awt.event.MouseListener#mouseEntered(MouseEvent) * @see #onMouseMoved(MouseEvent) * @see #onMousePressed(MouseEvent) * @see #onMouseReleased(MouseEvent) * @see #onMouseClicked(MouseEvent) * @see #onMouseExited(MouseEvent) * @see #onMouseDragged(MouseEvent) * @see #onMouseWheelMoved(MouseWheelEvent) * @since 1.3.4 */ void onMouseEntered(MouseEvent event); /** * This method is called when the mouse has exited the battle view. *

* See the {@code sample.Interactive} robot for an example of how to use * mouse events. * * @param event holds details about current event * @see java.awt.event.MouseListener#mouseExited(MouseEvent) * @see #onMouseMoved(MouseEvent) * @see #onMousePressed(MouseEvent) * @see #onMouseReleased(MouseEvent) * @see #onMouseClicked(MouseEvent) * @see #onMouseEntered(MouseEvent) * @see #onMouseDragged(MouseEvent) * @see #onMouseWheelMoved(MouseWheelEvent) * @since 1.3.4 */ void onMouseExited(MouseEvent event); /** * This method is called when a mouse button has been pressed. *

* See the {@code sample.Interactive} robot for an example of how to use * mouse events. * * @param event holds details about current event * @see java.awt.event.MouseListener#mousePressed(MouseEvent) * @see #onMouseMoved(MouseEvent) * @see #onMouseReleased(MouseEvent) * @see #onMouseClicked(MouseEvent) * @see #onMouseEntered(MouseEvent) * @see #onMouseExited(MouseEvent) * @see #onMouseDragged(MouseEvent) * @see #onMouseWheelMoved(MouseWheelEvent) * @since 1.3.4 */ void onMousePressed(MouseEvent event); /** * This method is called when a mouse button has been released. *

* See the {@code sample.Interactive} robot for an example of how to use * mouse events. * * @param event holds details about current event * @see java.awt.event.MouseListener#mouseReleased(MouseEvent) * @see #onMouseMoved(MouseEvent) * @see #onMousePressed(MouseEvent) * @see #onMouseClicked(MouseEvent) * @see #onMouseEntered(MouseEvent) * @see #onMouseExited(MouseEvent) * @see #onMouseDragged(MouseEvent) * @see #onMouseWheelMoved(MouseWheelEvent) * @since 1.3.4 */ void onMouseReleased(MouseEvent event); /** * This method is called when the mouse has been moved. *

* See the {@code sample.Interactive} robot for an example of how to use * mouse events. * * @param event holds details about current event * @see java.awt.event.MouseMotionListener#mouseMoved(MouseEvent) * @see #onMousePressed(MouseEvent) * @see #onMouseReleased(MouseEvent) * @see #onMouseClicked(MouseEvent) * @see #onMouseEntered(MouseEvent) * @see #onMouseExited(MouseEvent) * @see #onMouseDragged(MouseEvent) * @see #onMouseWheelMoved(MouseWheelEvent) * @since 1.3.4 */ void onMouseMoved(MouseEvent event); /** * This method is called when a mouse button has been pressed and then * dragged. *

* See the {@code sample.Interactive} robot for an example of how to use * mouse events. * * @param event holds details about current event * @see java.awt.event.MouseMotionListener#mouseDragged(MouseEvent) * @see #onMouseMoved(MouseEvent) * @see #onMousePressed(MouseEvent) * @see #onMouseReleased(MouseEvent) * @see #onMouseClicked(MouseEvent) * @see #onMouseEntered(MouseEvent) * @see #onMouseExited(MouseEvent) * @see #onMouseWheelMoved(MouseWheelEvent) * @since 1.3.4 */ void onMouseDragged(MouseEvent event); /** * This method is called when the mouse wheel has been rotated. *

* See the {@code sample.Interactive} robot for an example of how to use * mouse events. * * @param event holds details about current event * @see java.awt.event.MouseWheelListener#mouseWheelMoved(MouseWheelEvent) * @see #onMouseMoved(MouseEvent) * @see #onMousePressed(MouseEvent) * @see #onMouseReleased(MouseEvent) * @see #onMouseClicked(MouseEvent) * @see #onMouseEntered(MouseEvent) * @see #onMouseExited(MouseEvent) * @see #onMouseDragged(MouseEvent) */ void onMouseWheelMoved(MouseWheelEvent event); } robocode/robocode/robocode/robotinterfaces/IBasicRobot.java0000644000175000017500000000511611130241112023415 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.robotinterfaces; import robocode.robotinterfaces.peer.IBasicRobotPeer; /** * A robot interface for creating a basic type of robot like {@link robocode.Robot} * that is able to receive common robot events, but not interactive events as * with the {@link robocode.Robot} class. * A basic robot allows blocking calls only and cannot handle custom events nor * writes to the file system like an advanced robot. * * @author Pavel Savara (original) * @author Flemming N. Larsen (javadoc) * @see robocode.Robot * @see IJuniorRobot * @see IInteractiveRobot * @see IAdvancedRobot * @see ITeamRobot * @since 1.6 */ public interface IBasicRobot { /** * This method is called by the game to invoke the * {@link java.lang.Runnable#run() run()} method of your robot, where the program * of your robot is implemented. * * @return a runnable implementation * @see java.lang.Runnable#run() * @since 1.6 */ Runnable getRobotRunnable(); /** * This method is called by the game to notify this robot about basic * robot event. Hence, this method must be implemented so it returns your * {@link IBasicEvents} listener. * * @return listener to basic events or {@code null} if this robot should * not receive the notifications. * @since 1.6 */ IBasicEvents getBasicEventListener(); /** * Do not call this method! Your robot will simply stop interacting with * the game. *

* This method is called by the game. A robot peer is the object that deals * with game mechanics and rules, and makes sure your robot abides by them. * * @param peer the robot peer supplied by the game */ void setPeer(IBasicRobotPeer peer); /** * Do not call this method! *

* This method is called by the game when setting the output stream for your * robot. * * @param out the new output print stream for this robot * @since 1.6 */ void setOut(java.io.PrintStream out); } robocode/robocode/robocode/robotinterfaces/IPaintEvents.java0000644000175000017500000000373411130241112023632 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.robotinterfaces; import java.awt.*; /** * An event interface for receiving paint events with an * {@link robocode.robotinterfaces.IPaintRobot}. * * @author Pavel Savara (original) * @author Flemming N. Larsen (javadoc) * @see robocode.robotinterfaces.IPaintRobot * @since 1.6 */ public interface IPaintEvents { /** * This method is called every time the robot is painted. You should * override this method if you want to draw items for your robot on the * battle field, e.g. targets, virtual bullets etc. *

* This method is very useful for debugging your robot. *

* Note that the robot will only be painted if the "Paint" is enabled on the * robot's console window; otherwise the robot will never get painted (the * reason being that all robots might have graphical items that must be * painted, and then you might not be able to tell what graphical items that * have been painted for your robot). *

* Also note that the coordinate system for the graphical context where you * paint items fits for the Robocode coordinate system where (0, 0) is at * the bottom left corner of the battlefield, where X is towards right and Y * is upwards. * * @param g the graphics context to use for painting graphical items for the * robot * @see java.awt.Graphics2D * @since 1.1 */ void onPaint(Graphics2D g); } robocode/robocode/robocode/robotinterfaces/peer/0000755000175000017500000000000011124142030021344 5ustar lambylambyrobocode/robocode/robocode/robotinterfaces/peer/IAdvancedRobotPeer.java0000644000175000017500000006506111130241112025655 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.robotinterfaces.peer; import robocode.*; import java.io.File; import java.util.List; /** * The advanced robot peer for advanced robot types like * {@link robocode.AdvancedRobot} and {@link robocode.TeamRobot}. *

* A robot peer is the object that deals with game mechanics and rules, and * makes sure your robot abides by them. * * @author Pavel Savara (original) * @author Flemming N. Larsen (javadoc) * @see IBasicRobotPeer * @see IStandardRobotPeer * @see ITeamRobotPeer * @see IJuniorRobotPeer * @since 1.6 */ public interface IAdvancedRobotPeer extends IStandardRobotPeer { /** * Checks if the gun is set to adjust for the robot turning, i.e. to turn * independent from the robot's body turn. *

* This call returns {@code true} if the gun is set to turn independent of * the turn of the robot's body. Otherwise, {@code false} is returned, * meaning that the gun is set to turn with the robot's body turn. * * @return {@code true} if the gun is set to turn independent of the robot * turning; {@code false} if the gun is set to turn with the robot * turning * @see #setAdjustGunForBodyTurn(boolean) setAdjustGunForBodyTurn(boolean) * @see #isAdjustRadarForBodyTurn() * @see #isAdjustRadarForGunTurn() */ boolean isAdjustGunForBodyTurn(); /** * Checks if the radar is set to adjust for the robot turning, i.e. to turn * independent from the robot's body turn. *

* This call returns {@code true} if the radar is set to turn independent of * the turn of the robot. Otherwise, {@code false} is returned, meaning that * the radar is set to turn with the robot's turn. * * @return {@code true} if the radar is set to turn independent of the robot * turning; {@code false} if the radar is set to turn with the robot * turning * @see #setAdjustRadarForBodyTurn(boolean) setAdjustRadarForBodyTurn(boolean) * @see #isAdjustGunForBodyTurn() * @see #isAdjustRadarForGunTurn() */ boolean isAdjustRadarForGunTurn(); /** * Checks if the radar is set to adjust for the gun turning, i.e. to turn * independent from the gun's turn. *

* This call returns {@code true} if the radar is set to turn independent of * the turn of the gun. Otherwise, {@code false} is returned, meaning that * the radar is set to turn with the gun's turn. * * @return {@code true} if the radar is set to turn independent of the gun * turning; {@code false} if the radar is set to turn with the gun * turning * @see #setAdjustRadarForGunTurn(boolean) setAdjustRadarForGunTurn(boolean) * @see #isAdjustGunForBodyTurn() * @see #isAdjustRadarForBodyTurn() */ boolean isAdjustRadarForBodyTurn(); /** * This call is identical to {@link IStandardRobotPeer#stop(boolean) * stop(boolean)}, but returns immediately, and will not execute until you * call {@link IBasicRobotPeer#execute() execute()} or take an action that executes. *

* If there is already movement saved from a previous stop, you can * overwrite it by calling {@code setStop(true)}. * * @param overwrite {@code true} if the movement saved from a previous stop * should be overwritten; {@code false} otherwise. * @see IStandardRobotPeer#stop(boolean) stop(boolean) * @see IStandardRobotPeer#resume() resume() * @see #setResume() * @see IBasicRobotPeer#execute() execute() */ void setStop(boolean overwrite); /** * Sets the robot to resume the movement stopped by * {@link IStandardRobotPeer#stop(boolean) stop(boolean)} or * {@link #setStop(boolean)}, if any. *

* This call returns immediately, and will not execute until you call * {@link IBasicRobotPeer#execute() execute()} or take an action that executes. * * @see IStandardRobotPeer#resume() resume() * @see IStandardRobotPeer#stop(boolean) stop(boolean) * @see #setStop(boolean) * @see IBasicRobotPeer#execute() execute() */ void setResume(); /** * Sets the robot to move forward or backward by distance measured in pixels * when the next execution takes place. *

* This call returns immediately, and will not execute until you call * {@link IBasicRobotPeer#execute() execute()} or take an action that executes. *

* Note that both positive and negative values can be given as input, where * positive values means that the robot is set to move forward, and negative * values means that the robot is set to move backward. If 0 is given as * input, the robot will stop its movement, but will have to decelerate * till it stands still, and will thus not be able to stop its movement * immediately, but eventually. *

* Example: *

	 *   // Set the robot to move 50 pixels forward
	 *   setMove(50);
	 * 

* // Set the robot to move 100 pixels backward * // (overrides the previous order) * setMove(-100); *

* ... * // Executes the last setMove() * execute(); *

* * @param distance the distance to move measured in pixels. * If {@code distance} > 0 the robot is set to move forward. * If {@code distance} < 0 the robot is set to move backward. * If {@code distance} = 0 the robot is set to stop its movement. * @see IBasicRobotPeer#move(double) move(double) * @see #setMaxVelocity(double) * @see #setTurnBody(double) * @see #setTurnGun(double) * @see #setTurnRadar(double) */ void setMove(double distance); /** * Sets the robot's body to turn right or left by radians when the next * execution takes place. *

* This call returns immediately, and will not execute until you call * {@link IBasicRobotPeer#execute() execute()} or take an action that * executes. *

* Note that both positive and negative values can be given as input, where * positive values means that the robot's body is set to turn right, and * negative values means that the robot's body is set to turn left. * If 0 is given as input, the robot's body will stop turning. *

* Example: *

	 *   // Set the robot's body to turn 180 degrees to the right
	 *   setTurnBody(Math.PI);
	 * 

* // Set the robot's body to turn 90 degrees to the left instead of right * // (overrides the previous order) * setTurnBody(-Math.PI / 2); *

* ... * // Executes the last setTurnBody() * execute(); *

* * @param radians the amount of radians to turn the robot's body. * If {@code radians} > 0 the robot's body is set to turn right. * If {@code radians} < 0 the robot's body is set to turn left. * If {@code radians} = 0 the robot's body is set to stop turning. * @see IBasicRobotPeer#turnBody(double) turnBody(double) * @see #setTurnGun(double) * @see #setTurnRadar(double) * @see #setMaxTurnRate(double) * @see #setMove(double) */ void setTurnBody(double radians); /** * Sets the robot's gun to turn right or left by radians when the next * execution takes place. *

* This call returns immediately, and will not execute until you call * {@link IBasicRobotPeer#execute() execute()} or take an action that * executes. *

* Note that both positive and negative values can be given as input, where * positive values means that the robot's gun is set to turn right, and * negative values means that the robot's gun is set to turn left. * If 0 is given as input, the robot's gun will stop turning. *

* Example: *

	 *   // Set the robot's gun to turn 180 degrees to the right
	 *   setTurnGun(Math.PI);
	 * 

* // Set the robot's gun to turn 90 degrees to the left instead of right * // (overrides the previous order) * setTurnGun(-Math.PI / 2); *

* ... * // Executes the last setTurnFun() * execute(); *

* * @param radians the amount of radians to turn the robot's gun. * If {@code radians} > 0 the robot's gun is set to turn right. * If {@code radians} < 0 the robot's gun is set to turn left. * If {@code radians} = 0 the robot's gun is set to stop turning. * @see IBasicRobotPeer#turnGun(double) turnGun(double) * @see #setTurnBody(double) * @see #setTurnRadar(double) * @see #setMove(double) */ void setTurnGun(double radians); /** * Sets the robot's radar to turn right or left by radians when the next * execution takes place. *

* This call returns immediately, and will not execute until you call * {@link IBasicRobotPeer#execute() execute()} or take an action that * executes. *

* Note that both positive and negative values can be given as input, where * positive values means that the robot's radar is set to turn right, and * negative values means that the robot's radar is set to turn left. * If 0 is given as input, the robot's radar will stop turning. *

* Example: *

	 *   // Set the robot's radar to turn 180 degrees to the right
	 *   setTurnRadar(Math.PI);
	 * 

* // Set the robot's radar to turn 90 degrees to the left instead of right * // (overrides the previous order) * setTurnRadar(-Math.PI / 2); *

* ... * // Executes the last setTurnRadar() * execute(); *

* * @param radians the amount of radians to turn the robot's radar. * If {@code radians} > 0 the robot's radar is set to turn right. * If {@code radians} < 0 the robot's radar is set to turn left. * If {@code radians} = 0 the robot's radar is set to stop turning. * @see IStandardRobotPeer#turnRadar(double) turnRadar(double) * @see #setTurnBody(double) * @see #setTurnGun(double) * @see #setMove(double) */ void setTurnRadar(double radians); /** * Sets the maximum turn rate of the robot measured in degrees if the robot * should turn slower than {@link Rules#MAX_TURN_RATE} (10 degress/turn). * * @param newMaxTurnRate the new maximum turn rate of the robot measured in * degrees. Valid values are 0 - {@link Rules#MAX_TURN_RATE} * @see IBasicRobotPeer#turnBody(double) turnBody(double) * @see #setTurnBody(double) * @see #setMaxVelocity(double) */ void setMaxTurnRate(double newMaxTurnRate); /** * Sets the maximum velocity of the robot measured in pixels/turn if the * robot should move slower than {@link Rules#MAX_VELOCITY} (8 pixels/turn). * * @param newMaxVelocity the new maximum turn rate of the robot measured in * pixels/turn. Valid values are 0 - {@link Rules#MAX_VELOCITY} * @see IBasicRobotPeer#move(double) move(double) * @see #setMove(double) * @see #setMaxTurnRate(double) */ void setMaxVelocity(double newMaxVelocity); /** * Does not return until a condition is met, i.e. when a * {@link Condition#test()} returns {@code true}. *

* This call executes immediately. *

* See the {@code sample.Crazy} robot for how this method can be used. * * @param condition the condition that must be met before this call returns * @see Condition * @see Condition#test() */ void waitFor(Condition condition); /** * Call this during an event handler to allow new events of the same * priority to restart the event handler. *

*

Example: *

	 *   public void onScannedRobot(ScannedRobotEvent e) {
	 *       fire(1);
	 *       setInterruptible(true);
	 *       move(100);  // If you see a robot while moving ahead,
	 *                   // this handler will start from the top
	 *                   // Without setInterruptible(true), we wouldn't
	 *                   // receive scan events at all!
	 *       // We'll only get here if we don't see a robot during the move.
	 *       getOut().println("Ok, I can't see anyone");
	 *   }
	 * 
* * @param interruptible {@code true} if the event handler should be * interrupted if new events of the same priority occurs; {@code false} * otherwise * @see #setEventPriority(String, int) * @see robocode.robotinterfaces.IBasicEvents#onScannedRobot(ScannedRobotEvent) * onScannedRobot(ScannedRobotEvent) */ void setInterruptible(boolean interruptible); /** * Sets the priority of a class of events. *

* Events are sent to the onXXX handlers in order of priority. * Higher priority events can interrupt lower priority events. * For events with the same priority, newer events are always sent first. * Valid priorities are 0 - 99, where 100 is reserved and 80 is the default * priority. *

* Example: *

	 *   setEventPriority("RobotDeathEvent", 15);
	 * 
*

* The default priorities are, from highest to lowest: *

	 *   {@link BattleEndedEvent}:     100 (reserved)
	 *   {@link WinEvent}:             100 (reserved)
	 *   {@link SkippedTurnEvent}:     100 (reserved)
	 *   {@link StatusEvent}:           99
	 *   Key and mouse events:  98
	 *   {@link CustomEvent}:           80 (default value)
	 *   {@link MessageEvent}:          75
	 *   {@link RobotDeathEvent}:       70
	 *   {@link BulletMissedEvent}:     60
	 *   {@link BulletHitBulletEvent}:  55
	 *   {@link BulletHitEvent}:        50
	 *   {@link HitByBulletEvent}:      40
	 *   {@link HitWallEvent}:          30
	 *   {@link HitRobotEvent}:         20
	 *   {@link ScannedRobotEvent}:     10
	 *   {@link PaintEvent}:             5
	 *   {@link DeathEvent}:            -1 (reserved)
	 * 
*

* Note that you cannot change the priority for events with the special * priority value -1 or 100 (reserved) as these event are system events. * Also note that you cannot change the priority of CustomEvent. * Instead you must change the priority of the condition(s) for your custom * event(s). * * @param eventClass the name of the event class (string) to set the * priority for * @param priority the new priority for that event class * @see #getEventPriority(String) * @see #setInterruptible(boolean) * @since 1.5, the priority of DeathEvent was changed from 100 to -1 in * order to let robots process pending events on its event queue before * it dies. When the robot dies, it will not be able to process events. */ void setEventPriority(String eventClass, int priority); /** * Returns the current priority of a class of events. * An event priority is a value from 0 - 99. The higher value, the higher * priority. *

* Example: *

	 *   int myHitRobotPriority = getEventPriority("HitRobotEvent");
	 * 
*

* The default priorities are, from highest to lowest: *

	 *   {@link BattleEndedEvent}:     100 (reserved)
	 *   {@link WinEvent}:             100 (reserved)
	 *   {@link SkippedTurnEvent}:     100 (reserved)
	 *   {@link StatusEvent}:           99
	 *   Key and mouse events:  98
	 *   {@link CustomEvent}:           80 (default value)
	 *   {@link MessageEvent}:          75
	 *   {@link RobotDeathEvent}:       70
	 *   {@link BulletMissedEvent}:     60
	 *   {@link BulletHitBulletEvent}:  55
	 *   {@link BulletHitEvent}:        50
	 *   {@link HitByBulletEvent}:      40
	 *   {@link HitWallEvent}:          30
	 *   {@link HitRobotEvent}:         20
	 *   {@link ScannedRobotEvent}:     10
	 *   {@link PaintEvent}:             5
	 *   {@link DeathEvent}:            -1 (reserved)
	 * 
* * @param eventClass the name of the event class (string) * @return the current priority of a class of events * @see #setEventPriority(String, int) */ int getEventPriority(String eventClass); /** * Registers a custom event to be called when a condition is met. * When you are finished with your condition or just want to remove it you * must call {@link #removeCustomEvent(Condition)}. *

* Example: *

	 *   // Create the condition for our custom event
	 *   Condition triggerHitCondition = new Condition("triggerhit") {
	 *       public boolean test() {
	 *           return (getEnergy() <= trigger);
	 *       };
	 *   }
	 * 

* // Add our custom event based on our condition * addCustomEvent(triggerHitCondition); *

* * @param condition the condition that must be met. * @throws NullPointerException if the condition parameter has been set to * {@code null}. * @see Condition * @see #removeCustomEvent(Condition) */ void addCustomEvent(Condition condition); /** * Removes a custom event that was previously added by calling * {@link #addCustomEvent(Condition)}. *

* Example: *

	 *   // Create the condition for our custom event
	 *   Condition triggerHitCondition = new Condition("triggerhit") {
	 *       public boolean test() {
	 *           return (getEnergy() <= trigger);
	 *       };
	 *   }
	 * 

* // Add our custom event based on our condition * addCustomEvent(triggerHitCondition); * ... * do something with your robot * ... * // Remove the custom event based on our condition * removeCustomEvent(triggerHitCondition); *

* * @param condition the condition that was previous added and that must be * removed now. * @throws NullPointerException if the condition parameter has been set to * {@code null}. * @see Condition * @see #addCustomEvent(Condition) */ void removeCustomEvent(Condition condition); /** * Clears out any pending events in the robot's event queue immediately. * * @see #getAllEvents() */ void clearAllEvents(); /** * Returns a vector containing all events currently in the robot's queue. * You might, for example, call this while processing another event. *

* Example: *

	 *   for (Event event : getAllEvents()) {
	 *       if (event instanceof HitRobotEvent) {
	 *           // do something with the event
	 *       } else if (event instanceof HitByBulletEvent) {
	 *           // do something with the event
	 *       }
	 *   }
	 * 
* * @return a vector containing all events currently in the robot's queue * @see Event * @see #clearAllEvents() * @see #getStatusEvents() * @see #getScannedRobotEvents() * @see #getBulletHitEvents() * @see #getBulletMissedEvents() * @see #getBulletHitBulletEvents() * @see #getRobotDeathEvents() */ java.util.List getAllEvents(); /** * Returns a vector containing all StatusEvents currently in the robot's * queue. You might, for example, call this while processing another event. *

* Example: *

	 *   for (StatusEvent event : getStatusEvents()) {
	 *       // do something with the event
	 *   }
	 * 
* * @return a vector containing all StatusEvents currently in the robot's * queue * @see robocode.robotinterfaces.IBasicEvents#onStatus(StatusEvent) * onStatus(StatusEvent) * @see StatusEvent * @see #getAllEvents() * @since 1.6.1 */ List getStatusEvents(); /** * Returns a vector containing all BulletMissedEvents currently in the * robot's queue. You might, for example, call this while processing another * event. *

* Example: *

	 *   for (BulletMissedEvent event : getBulletMissedEvents()) {
	 *       // do something with the event
	 *   }
	 * 
* * @return a vector containing all BulletMissedEvents currently in the * robot's queue * @see robocode.robotinterfaces.IBasicEvents#onBulletMissed(BulletMissedEvent) * onBulletMissed(BulletMissedEvent) * @see BulletMissedEvent * @see #getAllEvents() */ List getBulletMissedEvents(); /** * Returns a vector containing all BulletHitBulletEvents currently in the * robot's queue. You might, for example, call this while processing another * event. *

* Example: *

	 *   for (BulletHitBulletEvent event : getBulletHitBulletEvents()) {
	 *       // do something with the event
	 *   }
	 * 
* * @return a vector containing all BulletHitBulletEvents currently in the * robot's queue * @see robocode.robotinterfaces.IBasicEvents#onBulletHitBullet(BulletHitBulletEvent) * onBulletHitBullet(BulletHitBulletEvent) * @see BulletHitBulletEvent * @see #getAllEvents() */ List getBulletHitBulletEvents(); /** * Returns a vector containing all BulletHitEvents currently in the robot's * queue. You might, for example, call this while processing another event. *

* Example: *

	 *   for (BulletHitEvent event: getBulletHitEvents()) {
	 *       // do something with the event
	 *   }
	 * 
* * @return a vector containing all BulletHitEvents currently in the robot's * queue * @see robocode.robotinterfaces.IBasicEvents#onBulletHit(BulletHitEvent) * onBulletHit(BulletHitEvent) * @see BulletHitEvent * @see #getAllEvents() */ List getBulletHitEvents(); /** * Returns a vector containing all HitByBulletEvents currently in the * robot's queue. You might, for example, call this while processing * another event. *

* Example: *

	 *   for (HitByBulletEvent event : getHitByBulletEvents()) {
	 *       // do something with the event
	 *   }
	 * 
* * @return a vector containing all HitByBulletEvents currently in the * robot's queue * @see robocode.robotinterfaces.IBasicEvents#onHitByBullet(HitByBulletEvent) * onHitByBullet(HitByBulletEvent) * @see HitByBulletEvent * @see #getAllEvents() */ List getHitByBulletEvents(); /** * Returns a vector containing all HitRobotEvents currently in the robot's * queue. You might, for example, call this while processing another event. *

* Example: *

	 *   for (HitRobotEvent event : getHitRobotEvents()) {
	 *       // do something with the event
	 *   }
	 * 
* * @return a vector containing all HitRobotEvents currently in the robot's * queue * @see robocode.robotinterfaces.IBasicEvents#onHitRobot(HitRobotEvent) * onHitRobot(HitRobotEvent) * @see HitRobotEvent * @see #getAllEvents() */ List getHitRobotEvents(); /** * Returns a vector containing all HitWallEvents currently in the robot's * queue. You might, for example, call this while processing another event. *

* Example: *

	 *   for (HitWallEvent event : getHitWallEvents()) {
	 *       // do something with the event
	 *   }
	 * 
* * @return a vector containing all HitWallEvents currently in the robot's * queue * @see robocode.robotinterfaces.IBasicEvents#onHitWall(HitWallEvent) * onHitWall(HitWallEvent) * @see HitWallEvent * @see #getAllEvents() */ List getHitWallEvents(); /** * Returns a vector containing all RobotDeathEvents currently in the robot's * queue. You might, for example, call this while processing another event. *

* Example: *

	 *   for (RobotDeathEvent event : getRobotDeathEvents()) {
	 *       // do something with the event
	 *   }
	 * 
* * @return a vector containing all RobotDeathEvents currently in the robot's * queue * @see robocode.robotinterfaces.IBasicEvents#onRobotDeath(RobotDeathEvent) * onRobotDeath(RobotDeathEvent) * @see RobotDeathEvent * @see #getAllEvents() */ List getRobotDeathEvents(); /** * Returns a vector containing all ScannedRobotEvents currently in the * robot's queue. You might, for example, call this while processing another * event. *

* Example: *

	 *   for (ScannedRobotEvent event : getScannedRobotEvents()) {
	 *       // do something with the event
	 *   }
	 * 
* * @return a vector containing all ScannedRobotEvents currently in the * robot's queue * @see robocode.robotinterfaces.IBasicEvents#onScannedRobot(ScannedRobotEvent) * onScannedRobot(ScannedRobotEvent) * @see ScannedRobotEvent * @see #getAllEvents() */ List getScannedRobotEvents(); /** * Returns a file representing a data directory for the robot, which can be * written to using {@link RobocodeFileOutputStream} or * {@link RobocodeFileWriter}. *

* The system will automatically create the directory for you, so you do not * need to create it by yourself. * * @return a file representing the data directory for your robot * @see #getDataFile(String) * @see RobocodeFileOutputStream * @see RobocodeFileWriter */ File getDataDirectory(); /** * Returns a file in your data directory that you can write to using * {@link RobocodeFileOutputStream} or {@link RobocodeFileWriter}. *

* The system will automatically create the directory for you, so you do not * need to create it by yourself. *

* Please notice that the max. size of your data file is set to 200000 * (~195 KB). *

* See the {@code sample.SittingDuck} to see an example of how to use this * method. * * @param filename the file name of the data file for your robot * @return a file representing the data file for your robot * @see #getDataDirectory() * @see RobocodeFileOutputStream * @see RobocodeFileWriter */ File getDataFile(String filename); /** * Returns the data quota available in your data directory, i.e. the amount * of bytes left in the data directory for the robot. * * @return the amount of bytes left in the robot's data directory * @see #getDataDirectory() * @see #getDataFile(String) */ long getDataQuotaAvailable(); } robocode/robocode/robocode/robotinterfaces/peer/IStandardRobotPeer.java0000644000175000017500000002207211130241112025703 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.robotinterfaces.peer; import robocode.ScannedRobotEvent; import robocode.robotinterfaces.IBasicEvents; /** * The standard robot peer for standard robot types like {@link robocode.Robot}, * {@link robocode.AdvancedRobot}, and {@link robocode.TeamRobot}. *

* A robot peer is the object that deals with game mechanics and rules, and * makes sure your robot abides by them. * * @author Pavel Savara (original) * @author Flemming N. Larsen (javadoc) * @see IBasicRobotPeer * @see IAdvancedRobotPeer * @see ITeamRobotPeer * @see IJuniorRobotPeer * @since 1.6 */ public interface IStandardRobotPeer extends IBasicRobotPeer { /** * Immediately stops all movement, and saves it for a call to * {@link #resume()}. If there is already movement saved from a previous * stop, you can overwrite it by calling {@code stop(true)}. * * @param overwrite If there is already movement saved from a previous stop, * you can overwrite it by calling {@code stop(true)}. * @see #resume() */ void stop(boolean overwrite); /** * Immediately resumes the movement you stopped by {@link #stop(boolean)}, * if any. *

* This call executes immediately, and does not return until it is complete. * * @see #stop(boolean) */ void resume(); /** * Rescan for other robots. This method is called automatically by the game, * as long as the robot is moving, turning its body, turning its gun, or * turning its radar. *

* Rescan will cause {@link IBasicEvents#onScannedRobot(ScannedRobotEvent) * onScannedRobot(ScannedRobotEvent)} to be called if you see a robot. *

* There are 2 reasons to call {@code rescan()} manually: *

    *
  1. You want to scan after you stop moving. *
  2. You want to interrupt the {@code onScannedRobot} event. This is more * likely. If you are in {@code onScannedRobot} and call {@code scan()}, * and you still see a robot, then the system will interrupt your * {@code onScannedRobot} event immediately and start it from the top. *
*

* This call executes immediately. * * @see IBasicEvents#onScannedRobot(ScannedRobotEvent) * onScannedRobot(ScannedRobotEvent) * @see ScannedRobotEvent */ void rescan(); /** * Immediately turns the robot's radar to the right or left by radians. * This call executes immediately, and does not return until it is complete, * i.e. when the angle remaining in the radar's turn is 0. *

* Note that both positive and negative values can be given as input, where * positive values means that the robot's radar is set to turn right, and * negative values means that the robot's radar is set to turn left. * If 0 is given as input, the robot's radar will stop turning. *

* Example: *

	 *   // Turn the robot's radar 180 degrees to the right
	 *   turnRadar(Math.PI);
	 * 

* // Afterwards, turn the robot's radar 90 degrees to the left * turnRadar(-Math.PI / 2); *

* * @param radians the amount of radians to turn the robot's radar. * If {@code radians} > 0 the robot's radar is set to turn right. * If {@code radians} < 0 the robot's radar is set to turn left. * If {@code radians} = 0 the robot's radar is set to stop turning. * @see #turnBody(double) * @see #turnGun(double) * @see #move(double) */ void turnRadar(double radians); /** * Sets the gun to turn independent from the robot's turn. *

* Ok, so this needs some explanation: The gun is mounted on the robot's * body. So, normally, if the robot turns 90 degrees to the right, then the * gun will turn with it as it is mounted on top of the robot's body. To * compensate for this, you can call {@code setAdjustGunForBodyTurn(true)}. * When this is set, the gun will turn independent from the robot's turn, * i.e. the gun will compensate for the robot's body turn. *

* Example, assuming both the robot and gun start out facing up (0 degrees): *

	 *   // Set gun to turn with the robot's turn
	 *   setAdjustGunForBodyTurn(false); // This is the default
	 *   turnBodyRight(Math.PI / 2);
	 *   // At this point, both the robot and gun are facing right (90 degrees)
	 *   turnBodyLeft(Math.PI / 2);
	 *   // Both are back to 0 degrees
	 * 

* -- or -- *

* // Set gun to turn independent from the robot's turn * setAdjustGunForBodyTurn(true); * turnBodyRight(Math.PI / 2); * // At this point, the robot is facing right (90 degrees), but the gun is still facing up. * turnBodyLeft(Math.PI / 2); * // Both are back to 0 degrees. *

*

* Note: The gun compensating this way does count as "turning the gun". * See {@link #setAdjustRadarForGunTurn(boolean)} for details. * * @param independent {@code true} if the gun must turn independent from the * robot's turn; {@code false} if the gun must turn with the robot's turn. * @see #setAdjustRadarForGunTurn(boolean) */ void setAdjustGunForBodyTurn(boolean independent); /** * Sets the radar to turn independent from the gun's turn. *

* Ok, so this needs some explanation: The radar is mounted on the robot's * gun. So, normally, if the gun turns 90 degrees to the right, then the * radar will turn with it as it is mounted on top of the gun. To compensate * for this, you can call {@code setAdjustRadarForGunTurn(true)}. When this * is set, the radar will turn independent from the robot's turn, i.e. the * radar will compensate for the gun's turn. *

* Example, assuming both the gun and radar start out facing up (0 degrees): *

	 *   // Set radar to turn with the gun's turn
	 *   setAdjustRadarForGunTurn(false); // This is the default
	 *   turnGunRight(Math.PI / 2);
	 *   // At this point, both the radar and gun are facing right (90 degrees);
	 * 

* -- or -- *

* // Set radar to turn independent from the gun's turn * setAdjustRadarForGunTurn(true); * turnGunRight(Math.PI / 2); * // At this point, the gun is facing right (90 degrees), but the radar is still facing up. *

* Note: Calling {@code setAdjustRadarForGunTurn(boolean)} will * automatically call {@link #setAdjustRadarForBodyTurn(boolean)} with the * same value, unless you have already called it earlier. This behavior is * primarily for backward compatibility with older Robocode robots. * * @param independent {@code true} if the radar must turn independent from * the gun's turn; {@code false} if the radar must turn with the gun's * turn. * @see #setAdjustRadarForBodyTurn(boolean) * @see #setAdjustGunForBodyTurn(boolean) */ void setAdjustRadarForGunTurn(boolean independent); /** * Sets the radar to turn independent from the robot's turn. *

* Ok, so this needs some explanation: The radar is mounted on the gun, and * the gun is mounted on the robot's body. So, normally, if the robot turns * 90 degrees to the right, the gun turns, as does the radar. Hence, if the * robot turns 90 degrees to the right, then the gun and radar will turn * with it as the radar is mounted on top of the gun. To compensate for * this, you can call {@code setAdjustRadarForBodyTurn(true)}. When this is * set, the radar will turn independent from the robot's turn, i.e. the * radar will compensate for the robot's turn. *

* Example, assuming the robot, gun, and radar all start out facing up (0 * degrees): *

	 *   // Set radar to turn with the robots's turn
	 *   setAdjustRadarForBodyTurn(false); // This is the default
	 *   turnRight(Math.PI / 2);
	 *   // At this point, the body, gun, and radar are all facing right (90 degrees);
	 * 

* -- or -- *

* // Set radar to turn independent from the robot's turn * setAdjustRadarForBodyTurn(true); * turnRight(Math.PI / 2); * // At this point, the robot and gun are facing right (90 degrees), but the radar is still facing up. *

* * @param independent {@code true} if the radar must turn independent from * the robots's turn; {@code false} if the radar must turn with the robot's * turn. * @see #setAdjustGunForBodyTurn(boolean) * @see #setAdjustRadarForGunTurn(boolean) */ void setAdjustRadarForBodyTurn(boolean independent); } robocode/robocode/robocode/robotinterfaces/peer/ITeamRobotPeer.java0000644000175000017500000001035411130241112025031 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.robotinterfaces.peer; import robocode.MessageEvent; import java.io.IOException; import java.io.Serializable; import java.util.List; /** * The team robot peer for team robots like {@link robocode.TeamRobot}. *

* A robot peer is the object that deals with game mechanics and rules, and * makes sure your robot abides by them. * * @author Pavel Savara (original) * @author Flemming N. Larsen (javadoc) * @see IBasicRobotPeer * @see IStandardRobotPeer * @see IAdvancedRobotPeer * @see IJuniorRobotPeer * @since 1.6 */ public interface ITeamRobotPeer extends IAdvancedRobotPeer { /** * Returns the names of all teammates, or {@code null} there is no * teammates. *

* Example: *

	 *   public void run() {
	 *       // Prints out all teammates
	 *       String[] teammates = getTeammates();
	 *       if (teammates != null) {
	 *           for (String member : teammates) {
	 *               out.println(member);
	 *           }
	 *       }
	 *   }
	 * 
* * @return a String array containing the names of all your teammates, or * {@code null} if there is no teammates. The length of the String array * is equal to the number of teammates. * @see #isTeammate(String) * @see #broadcastMessage(Serializable) * @see #sendMessage(String, Serializable) */ String[] getTeammates(); /** * Checks if a given robot name is the name of one of your teammates. *

* Example: *

	 *   public void onScannedRobot(ScannedRobotEvent e) {
	 *       if (isTeammate(e.getName()) {
	 *           return;
	 *       }
	 *       fire(1);
	 *   }
	 * 
* * @param name the robot name to check * @return {@code true} if the specified name belongs to one of your * teammates; {@code false} otherwise. * @see #getTeammates() * @see #broadcastMessage(Serializable) * @see #sendMessage(String, Serializable) */ boolean isTeammate(String name); /** * Broadcasts a message to all teammates. *

* Example: *

	 *   public void run() {
	 *       broadcastMessage("I'm here!");
	 *   }
	 * 
* * @param message the message to broadcast to all teammates * @throws IOException if the message could not be broadcasted to the * teammates * @see #isTeammate(String) * @see #getTeammates() * @see #sendMessage(String, Serializable) */ void broadcastMessage(Serializable message) throws IOException; /** * Sends a message to one (or more) teammates. *

* Example: *

	 *   public void run() {
	 *       sendMessage("sample.DroidBot", "I'm here!");
	 *   }
	 * 
* * @param name the name of the intended recipient of the message * @param message the message to send * @throws IOException if the message could not be sent * @see #isTeammate(String) * @see #getTeammates() * @see #broadcastMessage(Serializable) */ void sendMessage(String name, Serializable message) throws IOException; /** * Returns a vector containing all MessageEvents currently in the robot's * queue. You might, for example, call this while processing another event. *

* Example: *

	 *   for (MessageEvent e : getMessageEvents()) {
	 *      // do something with e
	 *   }
	 * 
* * @return a vector containing all MessageEvents currently in the robot's * queue * @see robocode.robotinterfaces.ITeamEvents#onMessageReceived(MessageEvent) * onMessageReceived(MessageEvent) * @see MessageEvent * @since 1.2.6 */ List getMessageEvents(); } robocode/robocode/robocode/robotinterfaces/peer/package.html0000644000175000017500000000016711006202516023636 0ustar lambylamby Robot peers available for implementing new robot types based on the Robot Interfaces. robocode/robocode/robocode/robotinterfaces/peer/IJuniorRobotPeer.java0000644000175000017500000000623511130241112025414 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.robotinterfaces.peer; /** * The junior robot peer for junior robot types like {@link robocode.JuniorRobot}. *

* A robot peer is the object that deals with game mechanics and rules, and * makes sure your robot abides by them. * * @author Pavel Savara (original) * @author Flemming N. Larsen (javadoc) * @see IBasicRobotPeer * @see IStandardRobotPeer * @see IAdvancedRobotPeer * @see ITeamRobotPeer * @since 1.6 */ public interface IJuniorRobotPeer extends IBasicRobotPeer { /** * Moves this robot forward or backwards by pixels and turns this robot * right or left by degrees at the same time. The robot will move in a curve * that follows a perfect circle, and the moving and turning will end at * exactly the same time. *

* Note that the max. velocity and max. turn rate is automatically adjusted, * which means that the robot will move slower the sharper the turn is * compared to the distance. *

* Note that both positive and negative values can be given as input: *

    *
  • If the {@code distance} parameter is set to a positive value, it * means that the robot is set to move forward, and a negative value means * that the robot is set to move backward. If set to 0, the robot will not * move, but will be able to turn. *
  • If the {@code radians} parameter is set to a positive value, it means * that the robot is set to turn to the right, and a negative value means * that the robot is set to turn to the left. If set to 0, the robot will * not turn, but will be able to move. *
* * @param distance the distance to move measured in pixels. * If {@code distance} > 0 the robot is set to move forward. * If {@code distance} < 0 the robot is set to move backward. * If {@code distance} = 0 the robot will not move anywhere, but just * finish its turn. * @param radians the amount of radians to turn the robot's body. * If {@code radians} > 0 the robot's body is set to turn right. * If {@code radians} < 0 the robot's body is set to turn left. * If {@code radians} = 0 the robot's body is set to stop turning. * @see IBasicRobotPeer#move(double) move(double) * @see IBasicRobotPeer#turnBody(double) turnBody(double) * @see IBasicRobotPeer#getBodyHeading() getBodyHeading() * @see IBasicRobotPeer#getX() getX() * @see IBasicRobotPeer#getY() getY() */ void turnAndMove(double distance, double radians); } robocode/robocode/robocode/robotinterfaces/peer/IBasicRobotPeer.java0000644000175000017500000005531011130241112025165 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * This is private interface. You should build any external component (or robot) * based on it's current methods because it will change in the future. * * Contributors: * Pavel Savara * - Initial implementation * - Added getGraphics() * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode.robotinterfaces.peer; import robocode.*; import java.awt.*; /** * The basic robot peer for all robot types. *

* A robot peer is the object that deals with game mechanics and rules, and * makes sure your robot abides by them. * * @author Pavel Savara (original) * @author Flemming N. Larsen (javadoc) * @see IStandardRobotPeer * @see IAdvancedRobotPeer * @see ITeamRobotPeer * @see IJuniorRobotPeer * @since 1.6 */ public interface IBasicRobotPeer { /** * Returns the robot's name. * * @return the robot's name. */ String getName(); /** * Returns the game time of the current round, where the time is equal to * the current turn in the round. *

* A battle consists of multiple rounds. *

* Time is reset to 0 at the beginning of every round. * * @return the game time/turn of the current round. */ long getTime(); /** * Returns the robot's current energy. * * @return the robot's current energy. */ double getEnergy(); /** * Returns the X position of the robot. (0,0) is at the bottom left of the * battlefield. * * @return the X position of the robot. * @see #getY() */ double getX(); /** * Returns the Y position of the robot. (0,0) is at the bottom left of the * battlefield. * * @return the Y position of the robot. * @see #getX() */ double getY(); /** * Returns the velocity of the robot measured in pixels/turn. *

* The maximum velocity of a robot is defined by * {@link Rules#MAX_VELOCITY} (8 pixels / turn). * * @return the velocity of the robot measured in pixels/turn. * @see Rules#MAX_VELOCITY */ double getVelocity(); /** * Returns the direction that the robot's body is facing, in radians. * The value returned will be between 0 and 2 * PI (is excluded). *

* Note that the heading in Robocode is like a compass, where 0 means North, * PI / 2 means East, PI means South, and 3 * PI / 4 means West. * * @return the direction that the robot's body is facing, in radians. * @see #getGunHeading() * @see #getRadarHeading() */ double getBodyHeading(); /** * Returns the direction that the robot's gun is facing, in radians. * The value returned will be between 0 and 2 * PI (is excluded). *

* Note that the heading in Robocode is like a compass, where 0 means North, * PI / 2 means East, PI means South, and 3 * PI / 4 means West. * * @return the direction that the robot's gun is facing, in radians. * @see #getBodyHeading() * @see #getRadarHeading() */ double getGunHeading(); /** * Returns the direction that the robot's radar is facing, in radians. * The value returned will be between 0 and 2 * PI (is excluded). *

* Note that the heading in Robocode is like a compass, where 0 means North, * PI / 2 means East, PI means South, and 3 * PI / 4 means West. * * @return the direction that the robot's radar is facing, in radians. * @see #getBodyHeading() * @see #getGunHeading() */ double getRadarHeading(); /** * Returns the current heat of the gun. The gun cannot fire unless this is * 0. (Calls to fire will succeed, but will not actually fire unless * getGunHeat() == 0). *

* The amount of gun heat generated when the gun is fired is * 1 + (firePower / 5). Each turn the gun heat drops by the amount returned * by {@link #getGunCoolingRate()}, which is a battle setup. *

* Note that all guns are "hot" at the start of each round, where the gun * heat is 3. * * @return the current gun heat * @see #getGunCoolingRate() * @see #setFire(double) */ double getGunHeat(); /** * Returns the width of the current battlefield measured in pixels. * * @return the width of the current battlefield measured in pixels. */ double getBattleFieldWidth(); /** * Returns the height of the current battlefield measured in pixels. * * @return the height of the current battlefield measured in pixels. */ double getBattleFieldHeight(); /** * Returns how many opponents that are left in the current round. * * @return how many opponents that are left in the current round. */ int getOthers(); /** * Returns the number of rounds in the current battle. * * @return the number of rounds in the current battle * @see #getRoundNum() */ int getNumRounds(); /** * Returns the number of the current round (0 to {@link #getNumRounds()} - 1) * in the battle. * * @return the number of the current round in the battle * @see #getNumRounds() */ int getRoundNum(); /** * Returns the rate at which the gun will cool down, i.e. the amount of heat * the gun heat will drop per turn. *

* The gun cooling rate is default 0.1 / turn, but can be changed by the * battle setup. So don't count on the cooling rate being 0.1! * * @return the gun cooling rate * @see #getGunHeat() * @see #setFire(double) */ double getGunCoolingRate(); /** * Returns the distance remaining in the robot's current move measured in * pixels. *

* This call returns both positive and negative values. Positive values * means that the robot is currently moving forwards. Negative values means * that the robot is currently moving backwards. If the returned value is 0, * the robot currently stands still. * * @return the distance remaining in the robot's current move measured in * pixels. * @see #getBodyTurnRemaining() * @see #getGunTurnRemaining() * @see #getRadarTurnRemaining() */ double getDistanceRemaining(); /** * Returns the angle remaining in the robot's turn, in radians. *

* This call returns both positive and negative values. Positive values * means that the robot is currently turning to the right. Negative values * means that the robot is currently turning to the left. * * @return the angle remaining in the robot's turn, in radians * @see #getDistanceRemaining() * @see #getGunTurnRemaining() * @see #getRadarTurnRemaining() */ double getBodyTurnRemaining(); /** * Returns the angle remaining in the gun's turn, in radians. *

* This call returns both positive and negative values. Positive values * means that the gun is currently turning to the right. Negative values * means that the gun is currently turning to the left. * * @return the angle remaining in the gun's turn, in radians * @see #getDistanceRemaining() * @see #getBodyTurnRemaining() * @see #getRadarTurnRemaining() */ double getGunTurnRemaining(); /** * Returns the angle remaining in the radar's turn, in radians. *

* This call returns both positive and negative values. Positive values * means that the radar is currently turning to the right. Negative values * means that the radar is currently turning to the left. * * @return the angle remaining in the radar's turn, in radians * @see #getDistanceRemaining() * @see #getBodyTurnRemaining() * @see #getGunTurnRemaining() */ double getRadarTurnRemaining(); /** * Executes any pending actions, or continues executing actions that are * in process. This call returns after the actions have been started. *

* Note that advanced robots must call this function in order to * execute pending set* calls like e.g. {@link * IAdvancedRobotPeer#setMove(double) setMove(double)}, * {@link IAdvancedRobotPeer#setFire(double) setFire(double)}, {@link * IAdvancedRobotPeer#setTurnBody(double) setTurnBody(double)} etc. * Otherwise, these calls will never get executed. *

* In this example the robot will move while turning: *

	 *   setTurnBody(90);
	 *   setMove(100);
	 *   execute();
	 * 

* while (getDistanceRemaining() > 0 && getTurnRemaining() > 0) { * execute(); * } *

*/ void execute(); /** * Immediately moves your robot forward or backward by distance measured in * pixels. *

* This call executes immediately, and does not return until it is complete, * i.e. when the remaining distance to move is 0. *

* If the robot collides with a wall, the move is complete, meaning that the * robot will not move any further. If the robot collides with another * robot, the move is complete if you are heading toward the other robot. *

* Note that both positive and negative values can be given as input, where * positive values means that the robot is set to move forward, and negative * values means that the robot is set to move backward. *

* Example: *

	 *   // Move the robot 100 pixels forward
	 *   ahead(100);
	 * 

* // Afterwards, move the robot 50 pixels backward * ahead(-50); *

* * @param distance the distance to move measured in pixels. * If {@code distance} > 0 the robot is set to move forward. * If {@code distance} < 0 the robot is set to move backward. * If {@code distance} = 0 the robot will not move anywhere, but just * finish its turn. * @see robocode.robotinterfaces.IBasicEvents#onHitWall(robocode.HitWallEvent) * @see robocode.robotinterfaces.IBasicEvents#onHitRobot(robocode.HitRobotEvent) */ void move(double distance); /** * Immediately turns the robot's body to the right or left by radians. * This call executes immediately, and does not return until it is complete, * i.e. when the angle remaining in the body's turn is 0. *

* Note that both positive and negative values can be given as input, where * positive values means that the robot's body is set to turn right, and * negative values means that the robot's body is set to turn left. * If 0 is given as input, the robot's body will stop turning. *

* Example: *

	 *   // Turn the robot's body 180 degrees to the right
	 *   turnBody(Math.PI);
	 * 

* // Afterwards, turn the robot's body 90 degrees to the left * turnBody(-Math.PI / 2); *

* * @param radians the amount of radians to turn the robot's body. * If {@code radians} > 0 the robot's body is set to turn right. * If {@code radians} < 0 the robot's body is set to turn left. * If {@code radians} = 0 the robot's body is set to stop turning. * @see #turnGun(double) * @see IStandardRobotPeer#turnRadar(double) turnRadar(double) * @see #move(double) */ void turnBody(double radians); /** * Immediately turns the robot's gun to the right or left by radians. * This call executes immediately, and does not return until it is complete, * i.e. when the angle remaining in the gun's turn is 0. *

* Note that both positive and negative values can be given as input, where * positive values means that the robot's gun is set to turn right, and * negative values means that the robot's gun is set to turn left. * If 0 is given as input, the robot's gun will stop turning. *

* Example: *

	 *   // Turn the robot's gun 180 degrees to the right
	 *   turnGun(Math.PI);
	 * 

* // Afterwards, turn the robot's gun 90 degrees to the left * turnGun(-Math.PI / 2); *

* * @param radians the amount of radians to turn the robot's gun. * If {@code radians} > 0 the robot's gun is set to turn right. * If {@code radians} < 0 the robot's gun is set to turn left. * If {@code radians} = 0 the robot's gun is set to stop turning. * @see #turnBody(double) * @see IStandardRobotPeer#turnRadar(double) turnRadar(double) * @see #move(double) */ void turnGun(double radians); /** * Immediately fires a bullet. The bullet will travel in the direction the * gun is pointing. *

* The specified bullet power is an amount of energy that will be taken from * the robot's energy. Hence, the more power you want to spend on the * bullet, the more energy is taken from your robot. *

* The bullet will do (4 * power) damage if it hits another robot. If power * is greater than 1, it will do an additional 2 * (power - 1) damage. * You will get (3 * power) back if you hit the other robot. You can call * {@link Rules#getBulletDamage(double)} for getting the damage that a * bullet with a specific bullet power will do. *

* The specified bullet power should be between * {@link Rules#MIN_BULLET_POWER} and {@link Rules#MAX_BULLET_POWER}. *

* Note that the gun cannot fire if the gun is overheated, meaning that * {@link #getGunHeat()} returns a value > 0. *

* A event is generated when the bullet hits a robot * ({@link BulletHitEvent}), wall ({@link BulletMissedEvent}), or another * bullet ({@link BulletHitBulletEvent}). *

* Example: *

	 *   // Fire a bullet with maximum power if the gun is ready
	 *   if (getGunHeat() == 0) {
	 *       Bullet bullet = fire(Rules.MAX_BULLET_POWER);
	 * 

* // Get the velocity of the bullet * if (bullet != null) { * double bulletVelocity = bullet.getVelocity(); * } * } *

* * @param power the amount of energy given to the bullet, and subtracted * from the robot's energy. * @return a {@link Bullet} that contains information about the bullet if it * was actually fired, which can be used for tracking the bullet after it * has been fired. If the bullet was not fired, {@code null} is returned. * @see #setFire(double) * @see Bullet * @see #getGunHeat() * @see #getGunCoolingRate() * @see robocode.robotinterfaces.IBasicEvents#onBulletHit(BulletHitEvent) * onBulletHit(BulletHitEvent) * @see robocode.robotinterfaces.IBasicEvents#onBulletHitBullet(BulletHitBulletEvent) * onBulletHitBullet(BulletHitBulletEvent) * @see robocode.robotinterfaces.IBasicEvents#onBulletMissed(BulletMissedEvent) * onBulletMissed(BulletMissedEvent) */ Bullet fire(double power); /** * Sets the gun to fire a bullet when the next execution takes place. * The bullet will travel in the direction the gun is pointing. *

* This call returns immediately, and will not execute until you call * execute() or take an action that executes. *

* The specified bullet power is an amount of energy that will be taken from * the robot's energy. Hence, the more power you want to spend on the * bullet, the more energy is taken from your robot. *

* The bullet will do (4 * power) damage if it hits another robot. If power * is greater than 1, it will do an additional 2 * (power - 1) damage. * You will get (3 * power) back if you hit the other robot. You can call * {@link Rules#getBulletDamage(double)} for getting the damage that a * bullet with a specific bullet power will do. *

* The specified bullet power should be between * {@link Rules#MIN_BULLET_POWER} and {@link Rules#MAX_BULLET_POWER}. *

* Note that the gun cannot fire if the gun is overheated, meaning that * {@link #getGunHeat()} returns a value > 0. *

* A event is generated when the bullet hits a robot * ({@link BulletHitEvent}), wall ({@link BulletMissedEvent}), or another * bullet ({@link BulletHitBulletEvent}). *

* Example: *

	 *   Bullet bullet = null;
	 * 

* // Fire a bullet with maximum power if the gun is ready * if (getGunHeat() == 0) { * bullet = setFireBullet(Rules.MAX_BULLET_POWER); * } * ... * execute(); * ... * // Get the velocity of the bullet * if (bullet != null) { * double bulletVelocity = bullet.getVelocity(); * } *

* * @param power the amount of energy given to the bullet, and subtracted * from the robot's energy. * @return a {@link Bullet} that contains information about the bullet if it * was actually fired, which can be used for tracking the bullet after it * has been fired. If the bullet was not fired, {@code null} is returned. * @see #fire(double) * @see Bullet * @see #getGunHeat() * @see #getGunCoolingRate() * @see robocode.robotinterfaces.IBasicEvents#onBulletHit(BulletHitEvent) * onBulletHit(BulletHitEvent) * @see robocode.robotinterfaces.IBasicEvents#onBulletHitBullet(BulletHitBulletEvent) * onBulletHitBullet(BulletHitBulletEvent) * @see robocode.robotinterfaces.IBasicEvents#onBulletMissed(BulletMissedEvent) * onBulletMissed(BulletMissedEvent) */ Bullet setFire(double power); /** * Sets the color of the robot's body. *

* A {@code null} indicates the default (blue) color. *

*

	 * Example:
	 *   // Don't forget to import java.awt.Color at the top...
	 *   import java.awt.Color;
	 *   ...
	 * 

* public void run() { * setBodyColor(Color.BLACK); * ... * } *

* * @param color the new body color * @see #setGunColor(Color) * @see #setRadarColor(Color) * @see #setBulletColor(Color) * @see #setScanColor(Color) * @see Color * @since 1.1.2 */ void setBodyColor(Color color); /** * Sets the color of the robot's gun. *

* A {@code null} indicates the default (blue) color. *

*

	 * Example:
	 *   // Don't forget to import java.awt.Color at the top...
	 *   import java.awt.Color;
	 *   ...
	 * 

* public void run() { * setGunColor(Color.RED); * ... * } *

* * @param color the new gun color * @see #setBodyColor(Color) * @see #setRadarColor(Color) * @see #setBulletColor(Color) * @see #setScanColor(Color) * @see Color * @since 1.1.2 */ void setGunColor(Color color); /** * Sets the color of the robot's radar. *

* A {@code null} indicates the default (blue) color. *

*

	 * Example:
	 *   // Don't forget to import java.awt.Color at the top...
	 *   import java.awt.Color;
	 *   ...
	 * 

* public void run() { * setRadarColor(Color.YELLOW); * ... * } *

* * @param color the new radar color * @see #setBodyColor(Color) * @see #setGunColor(Color) * @see #setBulletColor(Color) * @see #setScanColor(Color) * @see Color * @since 1.1.2 */ void setRadarColor(Color color); /** * Sets the color of the robot's bullets. *

* A {@code null} indicates the default white color. *

*

	 * Example:
	 *   // Don't forget to import java.awt.Color at the top...
	 *   import java.awt.Color;
	 *   ...
	 * 

* public void run() { * setBulletColor(Color.GREEN); * ... * } *

* * @param color the new bullet color * @see #setBodyColor(Color) * @see #setGunColor(Color) * @see #setRadarColor(Color) * @see #setScanColor(Color) * @see Color * @since 1.1.2 */ void setBulletColor(Color color); /** * Sets the color of the robot's scan arc. *

* A {@code null} indicates the default (blue) color. *

*

	 * Example:
	 *   // Don't forget to import java.awt.Color at the top...
	 *   import java.awt.Color;
	 *   ...
	 * 

* public void run() { * setScanColor(Color.WHITE); * ... * } *

* * @param color the new scan arc color * @see #setBodyColor(Color) * @see #setGunColor(Color) * @see #setRadarColor(Color) * @see #setBulletColor(Color) * @see Color * @since 1.1.2 */ void setScanColor(Color color); /** * This call must be made from a robot call to inform the game * that the robot made a {@code get*} call like e.g. {@link #getX()} or * {@link #getVelocity()}. *

* This method is used by the game to determine if the robot is inactive or * not. Note: You should only make this call once in a {@code get*} method! * * @see #setCall() */ void getCall(); /** * This call must be made from a robot call to inform the game * that the robot made a {@code set*} call like e.g. {@link * #setFire(double)} or {@link #setBodyColor(Color)}. *

* This method is used by the game to determine if the robot is inactive or * not. Note: You should only make this call once in a {@code set*} method! * * @see #getCall() */ void setCall(); /** * Returns a graphics context used for painting graphical items for the robot. *

* This method is very useful for debugging your robot. *

* Note that the robot will only be painted if the "Paint" is enabled on the * robot's console window; otherwise the robot will never get painted (the * reason being that all robots might have graphical items that must be * painted, and then you might not be able to tell what graphical items that * have been painted for your robot). *

* Also note that the coordinate system for the graphical context where you * paint items fits for the Robocode coordinate system where (0, 0) is at * the bottom left corner of the battlefield, where X is towards right and Y * is upwards. * * @return a graphics context used for painting graphical items for the robot. * @see robocode.robotinterfaces.IPaintEvents#onPaint(Graphics2D) * @since 1.6.1 */ Graphics2D getGraphics(); /** * Sets the debug property with the specified key to the specified value. *

* This method is very useful when debugging or reviewing your robot as you * will be able to see this property displayed in the robot console for your * robots under the Debug Properties tab page. * * @param key the name/key of the debug property. * @param value the new value of the debug property, where {@code null} or * the empty string is used for removing this debug property. * @since 1.6.2 */ void setDebugProperty(String key, String value); } robocode/robocode/robocode/HitByBulletEvent.java0000644000175000017500000001146411130241112021260 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Updated Javadocs *******************************************************************************/ package robocode; import robocode.peer.RobotStatics; import robocode.robotinterfaces.IBasicEvents; import robocode.robotinterfaces.IBasicRobot; import java.awt.*; /** * A HitByBulletEvent is sent to {@link Robot#onHitByBullet(HitByBulletEvent) * onHitByBullet()} when your robot has been hit by a bullet. * You can use the information contained in this event to determine what to do. * * @author Mathew A. Nelson (original) */ public final class HitByBulletEvent extends Event { private static final long serialVersionUID = 1L; private final static int DEFAULT_PRIORITY = 20; private final double bearing; private final Bullet bullet; /** * Called by the game to create a new HitByBulletEvent. * * @param bearing the bearing of the bullet that hit your robot, in radians * @param bullet the bullet that has hit your robot */ public HitByBulletEvent(double bearing, Bullet bullet) { super(); this.bearing = bearing; this.bullet = bullet; } /** * Returns the bearing to the bullet, relative to your robot's heading, * in degrees (-180 < getBearing() <= 180) *

* If you were to turnRight(e.getBearing()), you would be facing the * direction the bullet came from. The calculation used here is: * (bullet's heading in degrees + 180) - (your heading in degrees) * * @return the bearing to the bullet, in degrees */ public double getBearing() { return bearing * 180.0 / Math.PI; } /** * Returns the bearing to the bullet, relative to your robot's heading, * in radians (-Math.PI < getBearingRadians() <= Math.PI) *

* If you were to turnRightRadians(e.getBearingRadians()), you would be * facing the direction the bullet came from. The calculation used here is: * (bullet's heading in radians + Math.PI) - (your heading in radians) * * @return the bearing to the bullet, in radians */ public double getBearingRadians() { return bearing; } /** * Returns the bullet that hit your robot. * * @return the bullet that hit your robot */ public Bullet getBullet() { return bullet; } /** * Returns the heading of the bullet when it hit you, in degrees * (0 <= getHeading() < 360) *

* Note: This is not relative to the direction you are facing. The robot * that fired the bullet was in the opposite direction of getHeading() when * it fired the bullet. * * @return the heading of the bullet, in degrees */ public double getHeading() { return bullet.getHeading(); } /** * @return the heading of the bullet, in degrees * @deprecated Use {@link #getHeading()} instead. */ @Deprecated public double getHeadingDegrees() { return getHeading(); } /** * Returns the heading of the bullet when it hit you, in radians * (0 <= getHeadingRadians() < 2 * PI) *

* Note: This is not relative to the direction you are facing. The robot * that fired the bullet was in the opposite direction of * getHeadingRadians() when it fired the bullet. * * @return the heading of the bullet, in radians */ public double getHeadingRadians() { return bullet.getHeadingRadians(); } /** * Returns the name of the robot that fired the bullet. * * @return the name of the robot that fired the bullet */ public String getName() { return bullet.getName(); } /** * Returns the power of this bullet. The damage you take (in fact, already * took) is 4 * power, plus 2 * (power-1) if power > 1. The robot that fired * the bullet receives 3 * power back. * * @return the power of the bullet */ public double getPower() { return bullet.getPower(); } /** * Returns the velocity of this bullet. * * @return the velocity of the bullet */ public double getVelocity() { return bullet.getVelocity(); } /** * {@inheritDoc} */ @Override final int getDefaultPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override final void dispatch(IBasicRobot robot, RobotStatics statics, Graphics2D graphics) { IBasicEvents listener = robot.getBasicEventListener(); if (listener != null) { listener.onHitByBullet(this); } } } robocode/robocode/robocode/RadarTurnCompleteCondition.java0000644000175000017500000000454511130241112023333 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Updated Javadocs * Nathaniel Troutman * - Added cleanup() method for cleaning up references to internal classes * to prevent circular references causing memory leaks *******************************************************************************/ package robocode; /** * A prebuilt condition you can use that indicates your radar has finished * turning. * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Nathaniel Troutman (contributor) * @see Condition */ public class RadarTurnCompleteCondition extends Condition { private AdvancedRobot robot; /** * Creates a new RadarTurnCompleteCondition with default priority. * The default priority is 80. * * @param robot your robot, which must be a {@link AdvancedRobot} */ public RadarTurnCompleteCondition(AdvancedRobot robot) { super(); this.robot = robot; } /** * Creates a new RadarTurnCompleteCondition with the specified priority. * A condition priority is a value from 0 - 99. The higher value, the * higher priority. The default priority is 80. * * @param robot your robot, which must be a {@link AdvancedRobot} * @param priority the priority of this condition * @see Condition#setPriority(int) */ public RadarTurnCompleteCondition(AdvancedRobot robot, int priority) { super(); this.robot = robot; this.priority = priority; } /** * Tests if the radar has stopped turning. * * @return {@code true} if the radar has stopped turning; {@code false} * otherwise */ @Override public boolean test() { return (robot.getRadarTurnRemaining() == 0); } /** * Called by the system in order to clean up references to internal objects. * * @since 1.4.3 */ @Override public void cleanup() { robot = null; } } robocode/robocode/robocode/BattleResults.java0000644000175000017500000001336111130241114020664 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode; /** * Contains the battle results returned by {@link BattleEndedEvent#getResults()} * when a battle has ended. * * @author Pavel Savara (original) * @see BattleEndedEvent#getResults() * @see Robot#onBattleEnded(BattleEndedEvent) * @since 1.6.1 */ public class BattleResults implements java.io.Serializable, Comparable { protected static final long serialVersionUID = 1L; protected String teamLeaderName; protected int rank; protected double score; protected double survival; protected double lastSurvivorBonus; protected double bulletDamage; protected double bulletDamageBonus; protected double ramDamage; protected double ramDamageBonus; protected int firsts; protected int seconds; protected int thirds; /** * Constructs this BattleResults object. * * @param teamLeaderName the name of the team leader. * @param rank the rank of the robot in the battle. * @param score the total score for the robot in the battle. * @param survival the survival score for the robot in the battle. * @param lastSurvivorBonus the last survivor bonus for the robot in the battle. * @param bulletDamage the bullet damage score for the robot in the battle. * @param bulletDamageBonus the bullet damage bonus for the robot in the battle. * @param ramDamage the ramming damage for the robot in the battle. * @param ramDamageBonus the ramming damage bonus for the robot in the battle. * @param firsts the number of rounds this robot placed first. * @param seconds the number of rounds this robot placed second. * @param thirds the number of rounds this robot placed third. */ public BattleResults( String teamLeaderName, int rank, double score, double survival, double lastSurvivorBonus, double bulletDamage, double bulletDamageBonus, double ramDamage, double ramDamageBonus, int firsts, int seconds, int thirds ) { this.teamLeaderName = teamLeaderName; this.rank = rank; this.score = score; this.survival = survival; this.lastSurvivorBonus = lastSurvivorBonus; this.bulletDamage = bulletDamage; this.bulletDamageBonus = bulletDamageBonus; this.ramDamage = ramDamage; this.ramDamageBonus = ramDamageBonus; this.firsts = firsts; this.seconds = seconds; this.thirds = thirds; } /** * Returns the name of the team leader in the team or the name of the * robot if the robot is not participating in a team. * * @return the name of the team leader in the team or the name of the robot. */ public String getTeamLeaderName() { return teamLeaderName; } /** * Returns the rank of this robot in the battle results. * * @return the rank of this robot in the battle results. */ public int getRank() { return rank; } /** * Returns the total score of this robot in the battle. * * @return the total score of this robot in the battle. */ public int getScore() { return (int) (score + 0.5); } /** * Returns the survival score of this robot in the battle. * * @return the survival score of this robot in the battle. */ public int getSurvival() { return (int) (survival + 0.5); } /** * Returns the last survivor score of this robot in the battle. * * @return the last survivor score of this robot in the battle. */ public int getLastSurvivorBonus() { return (int) (lastSurvivorBonus + 0.5); } /** * Returns the bullet damage score of this robot in the battle. * * @return the bullet damage score of this robot in the battle. */ public int getBulletDamage() { return (int) (bulletDamage + 0.5); } /** * Returns the bullet damage bonus of this robot in the battle. * * @return the bullet damage bonus of this robot in the battle. */ public int getBulletDamageBonus() { return (int) (bulletDamageBonus + 0.5); } /** * Returns the ram damage score of this robot in the battle. * * @return the ram damage score of this robot in the battle. */ public int getRamDamage() { return (int) (ramDamage + 0.5); } /** * Returns the ram damage bonus of this robot in the battle. * * @return the ram damage bonus of this robot in the battle. */ public int getRamDamageBonus() { return (int) (ramDamageBonus + 0.5); } /** * Returns the number of rounds this robot placed first in the battle. * * @return the number of rounds this robot placed first in the battle. */ public int getFirsts() { return firsts; } /** * Returns the number of rounds this robot placed second in the battle. * * @return the number of rounds this robot placed second in the battle. */ public int getSeconds() { return seconds; } /** * Returns the number of rounds this robot placed third in the battle. * * @return the number of rounds this robot placed third in the battle. */ public int getThirds() { return thirds; } /** * {@inheritDoc} */ public int compareTo(BattleResults o) { return ((Double) score).compareTo(o.score); } } robocode/robocode/robocode/common/0000755000175000017500000000000011124142636016524 5ustar lambylambyrobocode/robocode/robocode/common/Command.java0000644000175000017500000000013711130241114020732 0ustar lambylambypackage robocode.common; public abstract class Command { public void execute() {} } robocode/robocode/robocode/common/IXmlSerializable.java0000644000175000017500000000157311130241114022561 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.common; import java.io.IOException; import java.util.Dictionary; /** * @author Pavel Savara (original) */ public interface IXmlSerializable { void writeXml(XmlWriter writer, Dictionary options) throws IOException; XmlReader.Element readXml(XmlReader reader); } robocode/robocode/robocode/common/ObjectCloner.java0000644000175000017500000000502411130241114021725 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Flemming N. Larsen * - Initial implementation *******************************************************************************/ package robocode.common; import java.awt.*; import java.io.*; /** * This utility class is used for cloning objects. * * @author Flemming N. Larsen (original) */ public class ObjectCloner { /** * Returns a deep copy of the specified object, or {@code null} if the * object cannot be serialized. * * @param orig the object to deep copy. * @return a new object that is a deep copy of the specified input object; or * {@code null} if the object was not copied for some reason. */ public static Object deepCopy(Object orig) { // Write the object out to a byte array ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream out = null; try { out = new ObjectOutputStream(baos); out.writeObject(orig); out.flush(); } catch (IOException e) { return null; } finally { if (out != null) { try { out.close(); } catch (IOException ignored) {} } } // Now, create a new object by reading it in from the byte array where the // original object was written to. Object obj = null; ObjectInputStream in = null; try { in = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())); obj = in.readObject(); } catch (IOException e) { return null; } catch (ClassNotFoundException e) { return null; } finally { if (in != null) { try { in.close(); } catch (IOException ignored) {} } } return obj; } /** * Returns a deep copy of the specified {@code Color}, or {@code null} if * the reference to the {@code Color} is {@code null}. * * @param c the {@code Color} to deep copy. * @return a new {@code Color} that is a deep copy if the specified input * {@code Color}; or {@code null} if the reference to the * {@code Color} is {@code null}. */ public static Color deepCopy(Color c) { return (c != null) ? new Color(c.getRGB(), true) : null; } } robocode/robocode/robocode/common/XmlReader.java0000644000175000017500000001173011130241114021240 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.common; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import java.io.IOException; import java.io.InputStream; import java.util.Dictionary; import java.util.Hashtable; import java.util.Stack; /** * @author Pavel Savara (original) */ public class XmlReader { SAXParser parser; final InputStream input; final Stack elements = new Stack(); final Stack items = new Stack(); final Stack> elementNames = new Stack>(); final Stack> attributeNames = new Stack>(); IXmlSerializable result; public XmlReader(InputStream input) throws SAXException, ParserConfigurationException { this.input = input; SAXParserFactory factory = SAXParserFactory.newInstance(); parser = factory.newSAXParser(); } private Object deserialize(IXmlSerializable prototype) throws IOException, SAXException { elementNames.push(new Hashtable()); attributeNames.push(new Hashtable()); items.push(null); elements.push(new ListElement() { public IXmlSerializable read(XmlReader reader) { return null; } public void add(IXmlSerializable child) { result = child; } public void close() {} }); prototype.readXml(this); parser.parse(input, new Handler(this)); items.pop(); elements.pop(); elementNames.pop(); attributeNames.pop(); return result; } private class Handler extends DefaultHandler { final XmlReader parent; public Handler(XmlReader parent) { this.parent = parent; } public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { final Dictionary names = XmlReader.this.elementNames.peek(); final Element element = names == null ? null : names.get(qName); if (element != null) { elements.push(element); XmlReader.this.elementNames.push(new Hashtable()); attributeNames.push(new Hashtable()); final IXmlSerializable item = element.read(parent); item.readXml(parent); for (int i = 0; i < attributes.getLength(); i++) { Attribute attribute = attributeNames.peek().get(attributes.getQName(i)); if (attribute != null) { attribute.read(attributes.getValue(i)); } } items.push(item); } else { items.push(null); elements.push(null); XmlReader.this.elementNames.push(null); attributeNames.push(null); } } public void endElement(String uri, String localName, String qName) throws SAXException { elements.pop(); final IXmlSerializable item = items.peek(); final Element parentElement = elements.peek(); if (parentElement instanceof ListElement) { ListElement le = (ListElement) parentElement; le.add(item); } items.pop(); elementNames.pop(); attributeNames.pop(); final Dictionary names = XmlReader.this.elementNames.peek(); final Element element = names == null ? null : names.get(qName); if (element != null) { if (element instanceof ElementClose) { ElementClose ec = (ElementClose) element; ec.close(); } } } } public Element expect(String name, Element element) { elementNames.peek().put(name, element); return element; } public Attribute expect(String name, Attribute attribute) { attributeNames.peek().put(name, attribute); return attribute; } public interface Element { IXmlSerializable read(XmlReader reader); } public interface ElementClose extends Element { void close(); } public interface ListElement extends ElementClose { void add(IXmlSerializable child); } public interface Attribute { void read(String value); } public static Object deserialize(InputStream input, IXmlSerializable prototype) throws IOException { try { XmlReader xr = new XmlReader(input); return xr.deserialize(prototype); } catch (SAXException e) { throw new IOException(); } catch (ParserConfigurationException e) { throw new IOException(); } } } robocode/robocode/robocode/common/BoundingRectangle.java0000644000175000017500000000421311130241114022745 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation *******************************************************************************/ package robocode.common; /* * Class exists to fix two bugs, both related to bug# 4320890 referenced below * 1. intersectsLine can cause an infinite loop in Java 1.3 * -- This is why the outcode() method is here, below * 2. The problem still exists with Rectangle2D.Double as of Java 1.4, * -- This is why we're using Rectangle2D.Float * * @author Mathew A. Nelson (original) */ public class BoundingRectangle extends java.awt.geom.Rectangle2D.Float { private static final long serialVersionUID = 1L; public BoundingRectangle() { super(); } public BoundingRectangle(double x, double y, double w, double h) { super((float) x, (float) y, (float) w, (float) h); } @Override public int outcode(double x, double y) { /* * Note on casts to double below. If the arithmetic of * x+w or y+h is done in float, then some bits may be * lost if the binary exponents of x/y and w/h are not * similar. By converting to double before the addition * we force the addition to be carried out in double to * avoid rounding error in the comparison. * * See bug 4320890 for problems that this inaccuracy causes. */ int out = 0; if (this.width <= 0) { out |= OUT_LEFT | OUT_RIGHT; } else if (x < this.x) { out |= OUT_LEFT; } else if (x > this.x + (double) this.width) { out |= OUT_RIGHT; } if (this.height <= 0) { out |= OUT_TOP | OUT_BOTTOM; } else if (y < this.y) { out |= OUT_TOP; } else if (y > this.y + (double) this.height) { out |= OUT_BOTTOM; } return out; } } robocode/robocode/robocode/common/XmlWriter.java0000644000175000017500000000706511130241114021320 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.common; import java.io.IOException; import java.io.Writer; import java.text.CharacterIterator; import java.text.StringCharacterIterator; import java.util.Stack; /** * @author Pavel Savara (original) */ public class XmlWriter { final Writer writer; final Stack elements = new Stack(); boolean headClosed = true; boolean innerElement = false; boolean indent = true; public XmlWriter(Writer writer, boolean indent) { this.writer = writer; this.indent = indent; } public void startDocument() throws IOException { writer.write("\n"); } public void startElement(String name) throws IOException { closeHead(); indent(elements.size()); elements.push(name); writer.write('<'); writer.write(encode(name)); headClosed = false; innerElement = false; } public void writeAttribute(String name, String value) throws IOException { if (value != null) { writer.write(' '); writer.write(encode(name)); writer.write("=\""); writer.write(encode(value)); writer.write('"'); } } public void writeAttribute(String name, boolean value) throws IOException { writeAttribute(name, Boolean.toString(value)); } public void writeAttribute(String name, long value) throws IOException { writeAttribute(name, Long.toString(value)); } public void writeAttribute(String name, double value) throws IOException { writeAttribute(name, Double.toString(value)); } public void endElement() throws IOException { String name = elements.pop(); if (innerElement || headClosed) { closeHead(); indent(elements.size()); writer.write(""); } else { writer.write("/>"); headClosed = true; } newline(); innerElement = true; } private void newline() throws IOException { if (indent) { writer.write("\n"); } } private void closeHead() throws IOException { if (!headClosed) { writer.write('>'); newline(); headClosed = true; } } private void indent(int level) throws IOException { if (indent) { for (int i = 0; i < level; i++) { writer.write("\t"); } } } public static String encode(String text) { final StringBuilder result = new StringBuilder(); final StringCharacterIterator iterator = new StringCharacterIterator(text); char character = iterator.current(); while (character != CharacterIterator.DONE) { if (character == '<') { result.append("<"); } else if (character == '>') { result.append(">"); } else if (character == '&') { result.append("&"); } else if (character == '\"') { result.append("""); } else if (character == '\n') { result.append(" "); } else { // the char is not a special one // add it to the result as is result.append(character); } character = iterator.next(); } return result.toString(); } } robocode/robocode/robocode/RobotDeathEvent.java0000644000175000017500000000412311130241112021116 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Updated Javadocs *******************************************************************************/ package robocode; import robocode.peer.RobotStatics; import robocode.robotinterfaces.IBasicEvents; import robocode.robotinterfaces.IBasicRobot; import java.awt.*; /** * This event is sent to {@link Robot#onRobotDeath(RobotDeathEvent) onRobotDeath()} * when another robot (not your robot) dies. * * @author Mathew A. Nelson (original) */ public final class RobotDeathEvent extends Event { private static final long serialVersionUID = 1L; private final static int DEFAULT_PRIORITY = 70; private final String robotName; /** * Called by the game to create a new RobotDeathEvent. * * @param robotName the name of the robot that died */ public RobotDeathEvent(String robotName) { super(); this.robotName = robotName; } /** * Returns the name of the robot that died. * * @return the name of the robot that died */ public String getName() { return robotName; } /** * @return the name of the robot that died * @deprecated Use {@link #getName()} instead. */ @Deprecated public String getRobotName() { return robotName; } /** * {@inheritDoc} */ @Override final int getDefaultPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override final void dispatch(IBasicRobot robot, RobotStatics statics, Graphics2D graphics) { IBasicEvents listener = robot.getBasicEventListener(); if (listener != null) { listener.onRobotDeath(this); } } } robocode/robocode/robocode/KeyReleasedEvent.java0000644000175000017500000000366711130241112021274 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Javadocs *******************************************************************************/ package robocode; import robocode.peer.RobotStatics; import robocode.robotinterfaces.IBasicRobot; import robocode.robotinterfaces.IInteractiveEvents; import robocode.robotinterfaces.IInteractiveRobot; import java.awt.*; /** * A KeyReleasedEvent is sent to {@link Robot#onKeyReleased(java.awt.event.KeyEvent) * onKeyReleased()} when a key has been released on the keyboard. * * @author Pavel Savara (original) * @see KeyPressedEvent * @see KeyTypedEvent * @since 1.6.1 */ public final class KeyReleasedEvent extends KeyEvent { private static final long serialVersionUID = 1L; private final static int DEFAULT_PRIORITY = 98; /** * Called by the game to create a new KeyReleasedEvent. * * @param source the source key event originating from the AWT. */ public KeyReleasedEvent(java.awt.event.KeyEvent source) { super(source); } /** * {@inheritDoc} */ @Override final int getDefaultPriority() { return DEFAULT_PRIORITY; } /** * {@inheritDoc} */ @Override final void dispatch(IBasicRobot robot, RobotStatics statics, Graphics2D graphics) { if (statics.isInteractiveRobot()) { IInteractiveEvents listener = ((IInteractiveRobot) robot).getInteractiveEventListener(); if (listener != null) { listener.onKeyReleased(getSourceEvent()); } } } } robocode/robocode/robocode/RobocodeFileOutputStream.java0000644000175000017500000001637211130241112023023 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup * - Updated to use methods from the Logger, which replaces logger methods * that has been (re)moved from the robocode.util.Utils class * - Fixed potential NullPointerExceptions * - Updated Javadocs *******************************************************************************/ package robocode; import robocode.exception.RobotException; import robocode.io.Logger; import robocode.manager.IThreadManager; import robocode.peer.proxies.IHostedThread; import robocode.peer.robot.RobotFileSystemManager; import robocode.security.RobocodePermission; import robocode.security.RobocodeSecurityManager; import java.io.*; /** * RobocodeFileOutputStream is similar to a {@link java.io.FileOutputStream} * and is used for streaming/writing data out to a file, which you got * previously by calling {@link AdvancedRobot#getDataFile(String) getDataFile()}. *

* You should read {@link java.io.FileOutputStream} for documentation of this * class. *

* Please notice that the max. size of your data file is set to 200000 * (~195 KB). * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @see AdvancedRobot#getDataFile(String) * @see java.io.FileOutputStream */ public class RobocodeFileOutputStream extends OutputStream { private static IThreadManager threadManager; private FileOutputStream out; private String fileName; private RobotFileSystemManager fileSystemManager; /** * Constructs a new RobocodeFileOutputStream. * See {@link java.io.FileOutputStream#FileOutputStream(File)} * for documentation about this constructor. * * @see java.io.FileOutputStream#FileOutputStream(File) */ public RobocodeFileOutputStream(File file) throws IOException { this(file.getPath()); } /** * Constructs a new RobocodeFileOutputStream. * See {@link java.io.FileOutputStream#FileOutputStream(FileDescriptor)} * for documentation about this constructor. * * @see java.io.FileOutputStream#FileOutputStream(FileDescriptor) */ public RobocodeFileOutputStream(FileDescriptor fdObj) { throw new RobotException("Creating a RobocodeFileOutputStream with a FileDescriptor is not supported."); } /** * Constructs a new RobocodeFileOutputStream. * See {@link java.io.FileOutputStream#FileOutputStream(String)} * for documentation about this constructor. * * @see java.io.FileOutputStream#FileOutputStream(String) */ public RobocodeFileOutputStream(String fileName) throws java.io.IOException { this(fileName, false); } /** * Constructs a new RobocodeFileOutputStream. * See {@link java.io.FileOutputStream#FileOutputStream(String, boolean)} * for documentation about this constructor. * * @see java.io.FileOutputStream#FileOutputStream(String, boolean) */ public RobocodeFileOutputStream(String fileName, boolean append) throws IOException { if (threadManager == null) { Logger.logError("RobocodeFileOutputStream.threadManager cannot be null!"); return; } Thread c = Thread.currentThread(); this.fileName = fileName; IHostedThread robotProxy = threadManager.getRobotProxy(c); if (robotProxy == null) { Logger.logError("RobotProxy is null"); return; } if (!robotProxy.getStatics().isAdvancedRobot()) { throw new RobotException("Only advanced robots may write to the filesystem"); } this.fileSystemManager = robotProxy.getRobotFileSystemManager(); // First, we see if the file exists: File f = new File(fileName); long len; if (f.exists()) { len = f.length(); } else { fileSystemManager.checkQuota(); len = 0; } RobocodeSecurityManager securityManager; if (System.getSecurityManager() instanceof RobocodeSecurityManager) { securityManager = (RobocodeSecurityManager) System.getSecurityManager(); securityManager.getFileOutputStream(this, append); if (!append) { fileSystemManager.adjustQuota(-len); } fileSystemManager.addStream(this); } else { throw new RobotException("Non robocode security manager?"); } } /** * Closes this output stream. See {@link java.io.FileOutputStream#close()} * for documentation about this method. * * @see java.io.FileOutputStream#close() */ @Override public final void close() throws IOException { fileSystemManager.removeStream(this); out.close(); } /** * Flushes this output stream. See {@link java.io.FileOutputStream#flush()} * for documentation about this method. * * @see java.io.FileOutputStream#flush() */ @Override public final void flush() throws IOException { out.flush(); } /** * Returns the filename of this output stream. * * @return the filename of this output stream. */ public final String getName() { return fileName; } /** * The system calls this method, you should not call it. */ public final void setFileOutputStream(FileOutputStream out) { this.out = out; } /** * The system calls this method, you should not call it. */ public static void setThreadManager(IThreadManager threadManager) { System.getSecurityManager().checkPermission(new RobocodePermission("setThreadManager")); RobocodeFileOutputStream.threadManager = threadManager; } /** * Writes a byte array to this output stream. * See {@link java.io.FileOutputStream#write(byte[])} for documentation * about this method. * * @see java.io.FileOutputStream#write(byte[]) */ @Override public final void write(byte[] b) throws IOException { try { fileSystemManager.checkQuota(b.length); out.write(b); } catch (IOException e) { try { close(); } catch (IOException ignored) {} throw e; } } /** * Writes a byte array to this output stream. * See {@link java.io.FileOutputStream#write(byte[], int, int)} for * documentation about this method. * * @see java.io.FileOutputStream#write(byte[], int, int) */ @Override public final void write(byte[] b, int off, int len) throws IOException { if (len < 0) { throw new IndexOutOfBoundsException(); } try { fileSystemManager.checkQuota(len); out.write(b, off, len); } catch (IOException e) { close(); try { close(); } catch (IOException ignored) {} throw e; } } /** * Writes a single byte to this output stream. * See {@link java.io.FileOutputStream#write(int)} for documentation about * this method. * * @see java.io.FileOutputStream#write(int) */ @Override public final void write(int b) throws IOException { try { fileSystemManager.checkQuota(1); out.write(b); } catch (IOException e) { close(); try { close(); } catch (IOException ignored) {} throw e; } } } robocode/robocode/robocode/peer/0000755000175000017500000000000011125266034016167 5ustar lambylambyrobocode/robocode/robocode/peer/ContestantPeer.java0000644000175000017500000000171711130241112021760 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Ported to Java 5 *******************************************************************************/ package robocode.peer; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ public interface ContestantPeer extends Comparable { public ContestantStatistics getStatistics(); public String getName(); public String toString(); public int getContestIndex(); } robocode/robocode/robocode/peer/ExecResults.java0000644000175000017500000000551711130241112021272 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.peer; import robocode.Event; import robocode.RobotStatus; import robocode.peer.robot.TeamMessage; import java.io.Serializable; import java.util.List; public class ExecResults implements Serializable { private static final long serialVersionUID = 1L; private ExecCommands commands; private RobotStatus status; private List events; private List teamMessages; private List bulletUpdates; private boolean halt; private boolean shouldWait; private boolean paintEnabled; public ExecResults(ExecCommands commands, RobotStatus status, List events, List teamMessages, List bulletUpdates, boolean halt, boolean shouldWait, boolean paintEnabled) { this.commands = commands; this.status = status; this.events = events; this.teamMessages = teamMessages; this.bulletUpdates = bulletUpdates; this.halt = halt; this.shouldWait = shouldWait; this.paintEnabled = paintEnabled; } public static long getSerialVersionUID() { return serialVersionUID; } public ExecCommands getCommands() { return commands; } public void setCommands(ExecCommands commands) { this.commands = commands; } public RobotStatus getStatus() { return status; } public void setStatus(RobotStatus status) { this.status = status; } public List getEvents() { return events; } public void setEvents(List events) { this.events = events; } public List getTeamMessages() { return teamMessages; } public void setTeamMessages(List teamMessages) { this.teamMessages = teamMessages; } public List getBulletUpdates() { return bulletUpdates; } public void setBulletUpdates(List bulletUpdates) { this.bulletUpdates = bulletUpdates; } public boolean isHalt() { return halt; } public void setHalt(boolean halt) { this.halt = halt; } public boolean isShouldWait() { return shouldWait; } public void setShouldWait(boolean shouldWait) { this.shouldWait = shouldWait; } public boolean isPaintEnabled() { return paintEnabled; } public void setPaintEnabled(boolean paintEnabled) { this.paintEnabled = paintEnabled; } } robocode/robocode/robocode/peer/robot/0000755000175000017500000000000011127773704017325 5ustar lambylambyrobocode/robocode/robocode/peer/robot/RobotFileSystemManager.java0000644000175000017500000001277611130241112024543 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Ported to Java 5.0 * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap *******************************************************************************/ package robocode.peer.robot; import robocode.RobocodeFileOutputStream; import robocode.peer.proxies.IHostedThread; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Robert D. Maupin (contributor) */ public class RobotFileSystemManager { private final IHostedThread robotProxy; private long quotaUsed = 0; private boolean quotaMessagePrinted = false; private final List streams = new ArrayList(); private long maxQuota = 0; private final String classDirectory; private final String rootPackageDirectory; public RobotFileSystemManager(IHostedThread robotProxy, long maxQuota, String classDirectory, String rootPackageDirectory) { this.robotProxy = robotProxy; this.maxQuota = maxQuota; this.classDirectory = classDirectory; this.rootPackageDirectory = rootPackageDirectory; } public void addStream(RobocodeFileOutputStream s) throws IOException { if (s == null) { throw new SecurityException("You may not add a null stream."); } if (!streams.contains(s)) { if (streams.size() < 5) { streams.add(s); } else { throw new IOException( "You may only have 5 streams open at a time.\n Make sure you call close() on your streams when you are finished with them."); } } } public synchronized void adjustQuota(long len) { quotaUsed += len; } public void checkQuota() throws IOException { checkQuota(0); } public void checkQuota(long numBytes) throws IOException { if (numBytes < 0) { throw new IndexOutOfBoundsException("checkQuota on negative numBytes!"); } if (quotaUsed + numBytes <= maxQuota) { adjustQuota(numBytes); return; } if (!quotaMessagePrinted) { robotProxy.getOut().println("SYSTEM: You have reached your filesystem quota of: " + maxQuota + " bytes."); quotaMessagePrinted = true; } throw new IOException("You have reached your filesystem quota of: " + maxQuota + " bytes."); } public long getMaxQuota() { return maxQuota; } public long getQuotaUsed() { return quotaUsed; } public File getReadableDirectory() { try { final String dir = rootPackageDirectory; return (dir == null) ? null : new File(dir).getCanonicalFile(); } catch (java.io.IOException e) { return null; } } public File getWritableDirectory() { try { final String dir = classDirectory; return (dir == null) ? null : new File(classDirectory, robotProxy.getStatics().getShortClassName() + ".data").getCanonicalFile(); } catch (java.io.IOException e) { return null; } } public void initializeQuota() { File dataDirectory = getWritableDirectory(); if (dataDirectory == null) { quotaUsed = maxQuota; return; } if (!dataDirectory.exists()) { this.quotaUsed = 0; return; } quotaMessagePrinted = false; File[] dataFiles = dataDirectory.listFiles(); quotaUsed = 0; for (File file : dataFiles) { quotaUsed += file.length(); } } public boolean isReadable(String fileName) { File allowedDirectory = getReadableDirectory(); if (allowedDirectory == null) { return false; } File attemptedFile; try { attemptedFile = new File(fileName).getCanonicalFile(); } catch (java.io.IOException e) { return false; } if (attemptedFile.equals(allowedDirectory)) { return true; // recursive check } if (attemptedFile.getParent().indexOf(allowedDirectory.toString()) == 0) { String fs = attemptedFile.toString(); int dataIndex = fs.indexOf(".data", allowedDirectory.toString().length()); if (dataIndex >= 0) { if (isWritable(fileName) || attemptedFile.equals(getWritableDirectory())) { return true; } throw new java.security.AccessControlException( "Preventing " + Thread.currentThread().getName() + " from access to: " + fileName + ": You may not read another robot's data directory."); } return true; } return false; } public boolean isWritable(String fileName) { File allowedDirectory = getWritableDirectory(); if (allowedDirectory == null) { return false; } File attemptedFile; try { attemptedFile = new File(fileName).getCanonicalFile(); } catch (java.io.IOException e) { return false; } return attemptedFile.equals(allowedDirectory) || attemptedFile.getParentFile().equals(allowedDirectory); } public void removeStream(RobocodeFileOutputStream s) { if (s == null) { throw new SecurityException("You may not remove a null stream."); } if (streams.contains(s)) { streams.remove(s); } } } robocode/robocode/robocode/peer/robot/RobotOutputStream.java0000644000175000017500000001207111130241112023624 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Optimized regarding thread synchronization *******************************************************************************/ package robocode.peer.robot; import robocode.io.BufferedPipedOutputStream; import java.io.PrintWriter; import java.io.StringWriter; import java.util.Arrays; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ public class RobotOutputStream extends java.io.PrintStream { private final static int MAX = 100; private int count = 0; private boolean messaged = false; private final StringBuilder text; private final Object syncRoot = new Object(); public RobotOutputStream() { super(new BufferedPipedOutputStream(128, true)); this.text = new StringBuilder(8192); } public String readAndReset() { synchronized (syncRoot) { // Out's counter must be reset before processing event. // Otherwise, it will not be reset when printing in the onScannedEvent() // before a scan() call, which will potentially cause a new onScannedEvent() // and therefore not be able to reset the counter. count = 0; if (text.length() > 0) { final String result = text.toString(); text.setLength(0); return result; } return ""; } } private boolean isOkToPrint() { synchronized (syncRoot) { if (count++ > MAX) { if (!messaged) { text.append("\n"); text.append( "SYSTEM: This robot is printing too much between actions. Output stopped until next action."); text.append("\n"); messaged = true; } return false; } messaged = false; return true; } } @Override public void print(char[] s) { synchronized (syncRoot) { if (isOkToPrint()) { text.append(s); if (s != null) { count += (s.length / 1000); } } } } @Override public void print(char c) { synchronized (syncRoot) { if (isOkToPrint()) { text.append(c); } } } @Override public void print(double d) { synchronized (syncRoot) { if (isOkToPrint()) { text.append(d); } } } @Override public void print(float f) { synchronized (syncRoot) { if (isOkToPrint()) { text.append(f); } } } @Override public void print(int i) { synchronized (syncRoot) { if (isOkToPrint()) { text.append(i); } } } @Override public void print(long l) { synchronized (syncRoot) { if (isOkToPrint()) { text.append(l); } } } @Override public void print(Object obj) { synchronized (syncRoot) { if (isOkToPrint()) { if (obj != null) { String s = obj.toString(); text.append(s); count += (s.length() / 1000); } else { text.append((Object) null); } } } } @Override public void print(String s) { synchronized (syncRoot) { if (isOkToPrint()) { text.append(s); if (s != null) { count += (s.length() / 1000); } } } } @Override public void print(boolean b) { synchronized (syncRoot) { if (isOkToPrint()) { text.append(b); } } } @Override public void println() { print('\n'); } @Override public void println(char[] x) { print(x); print('\n'); } @Override public void println(char x) { print(x); print('\n'); } @Override public void println(double x) { print(x); print('\n'); } @Override public void println(float x) { print(x); print('\n'); } @Override public void println(int x) { print(x); print('\n'); } @Override public void println(long x) { print(x); print('\n'); } @Override public void println(Object x) { print(x); print('\n'); } @Override public void println(String x) { print(x); print('\n'); } @Override public void println(boolean x) { print(x); print('\n'); } @Override public void write(byte[] buf) { synchronized (syncRoot) { if (isOkToPrint()) { text.append(Arrays.toString(buf)); if (buf != null) { count += (buf.length / 1000); } } } } @Override public void write(int b) { synchronized (syncRoot) { if (isOkToPrint()) { text.append(b); } } } public void printStackTrace(Throwable t) { if (t != null) { synchronized (syncRoot) { if (isOkToPrint()) { StringWriter sw = new StringWriter(); final PrintWriter writer = new PrintWriter(sw); t.printStackTrace(writer); writer.flush(); text.append(sw.toString()); } } } } } robocode/robocode/robocode/peer/robot/EventQueue.java0000644000175000017500000000274511130241112022237 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.net/license/CPLv1.0.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Updated for Java 5 * - Optimized * - Code cleanup *******************************************************************************/ package robocode.peer.robot; import robocode.Event; import java.util.ArrayList; import java.util.Collections; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ @SuppressWarnings("serial") public class EventQueue extends ArrayList { public void clear(boolean includingSystemEvents) { if (includingSystemEvents) { super.clear(); return; } for (int i = 0; i < size(); i++) { Event e = get(i); if (!RobotClassManager.isCriticalEvent(e)) { remove(i--); } } } public void clear(long clearTime) { for (int i = 0; i < size(); i++) { Event e = get(i); if ((e.getTime() <= clearTime) && !RobotClassManager.isCriticalEvent(e)) { remove(i--); } } } public void sort() { Collections.sort(this); } } robocode/robocode/robocode/peer/robot/NameStuff.jpage0000644000175000017500000001215611006202516022212 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation *******************************************************************************/ private java.lang.String fullClassName = null; private java.lang.String fullClassNameWithVersion = null; private java.lang.String uniqueFullClassNameWithVersion = null; private java.lang.String version = null; private java.lang.String fullPackage = null; private java.lang.String rootPackage = null; private java.lang.String shortClassName = null; private java.lang.String veryShortClassName = null; private java.lang.String shortClassNameWithVersion = null; private java.lang.String veryShortClassNameWithVersion = null; private java.lang.String uniqueVeryShortClassNameWithVersion = null; private java.lang.String uniqueShortClassNameWithVersion = null; public java.lang.String getRootPackage() { if (rootPackage == null) { if (getFullClassName().indexOf(".") > 0) rootPackage=getFullClassName().substring(0,getFullClassName().indexOf(".")); else rootPackage = null; } return rootPackage; } public java.lang.String getShortClassName() { if (shortClassName == null) { if (getFullClassName().lastIndexOf(".") > 0) shortClassName = getFullClassName().substring(getFullClassName().lastIndexOf(".") + 1); else shortClassName = getFullClassName(); } return shortClassName; } public java.lang.String getShortClassNameWithVersion() { if (shortClassNameWithVersion == null) { if (getVersion().equals("")) { shortClassNameWithVersion = getShortClassName(); } else { shortClassNameWithVersion = getShortClassName() + " " + getVersion(); } } return shortClassNameWithVersion; } public java.lang.String getUniqueFullClassNameWithVersion() { if (uniqueFullClassNameWithVersion == null) { if (getFullClassNameWithVersion().equals(getFullClassName())) { uniqueFullClassNameWithVersion = getFullClassName(); } else { if (robotSpecification.getFileFromCache() == true) uniqueFullClassNameWithVersion = getFullClassNameWithVersion(); else uniqueFullClassNameWithVersion = getFullClassNameWithVersion() + "*"; } } return uniqueFullClassNameWithVersion; } public java.lang.String getUniqueShortClassNameWithVersion() { if (uniqueShortClassNameWithVersion == null) { if (getShortClassName().equals(getShortClassNameWithVersion())) { uniqueShortClassNameWithVersion = getShortClassName(); } else { if (robotSpecification.getFileFromCache() == true) uniqueShortClassNameWithVersion = getShortClassNameWithVersion(); else uniqueShortClassNameWithVersion = getShortClassNameWithVersion() + "*"; } } return uniqueShortClassNameWithVersion; } public java.lang.String getUniqueVeryShortClassNameWithVersion() { if (uniqueVeryShortClassNameWithVersion == null) { if (getVeryShortClassName().equals(getVeryShortClassNameWithVersion())) { uniqueVeryShortClassNameWithVersion = getVeryShortClassName(); } else { if (robotSpecification.getFileFromCache() == true) uniqueVeryShortClassNameWithVersion = getVeryShortClassNameWithVersion(); else uniqueVeryShortClassNameWithVersion = getVeryShortClassNameWithVersion() + "*"; } } return uniqueVeryShortClassNameWithVersion; } public java.lang.String getVersion() { if (version == null) { version = robotSpecification.getRobotVersion(); if (version == null) version = ""; if (version.length() > 10) version = version.substring(0,10); } return version; } public java.lang.String getVeryShortClassName() { if (veryShortClassName == null) { veryShortClassName = getShortClassName(); if (veryShortClassName.length() > 12) veryShortClassName = veryShortClassName.substring(0,12) + "..."; } return veryShortClassName; } public java.lang.String getVeryShortClassNameWithVersion() { if (veryShortClassNameWithVersion == null) { if (getVersion().equals("")) { veryShortClassNameWithVersion = getVeryShortClassName(); } else { veryShortClassNameWithVersion = getVeryShortClassName() + " " + getVersion(); } } return veryShortClassNameWithVersion; } public java.lang.String getFullClassNameWithVersion() { if (fullClassNameWithVersion == null) { if (getVersion().equals("")) { fullClassNameWithVersion = getFullClassName(); } else { fullClassNameWithVersion = getFullClassName() + " " + getVersion(); } } return fullClassNameWithVersion; } public java.lang.String getFullPackage() { if (fullPackage == null) { if (getFullClassName().lastIndexOf(".") > 0) fullPackage=getFullClassName().substring(0,getFullClassName().lastIndexOf(".")); else fullPackage = null; } return fullPackage; }robocode/robocode/robocode/peer/robot/EventManager.java0000644000175000017500000004551211130241112022524 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Matthew Reeder * - Fix for HyperThreading hang issue with the getTime() method that was * synchronized before, which sometimes caused a deadlock to occur in the * code processing the hitWall event. * Flemming N. Larsen * - Ported to Java 5.0 * - Bugfix: Added setting and getting the priority of BulletHitBulletEvent * - Added missing getMessageEvents() * - Code cleanup * - Added features to support the new JuniorRobot class * - Bugfix: Fixed ConcurrentModificationExceptions due to lack of * synchronization with the event queue. Now all getXXXEvents() methods * are synchronized against the event queue, and the list of customEvents * is a CopyOnWriteArrayList which is fully thread-safe * - Changed the priority of the DeathEvent from 100 to -1 in order to let * robots process events before they die * - Added handling of the new StatusEvent, which is used for calling the new * Robot.onStatus(StatusEvent e) event handler, and added the * getStatusEvents() method * - Added PaintEvent with the onPaint() handler and also getPaintEvents() * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap * Nathaniel Troutman * - Added cleanup() method for cleaning up references to internal classes * to prevent circular references causing memory leaks * Pavel Savara * - Re-work of robot interfaces * - dispatch and priorities redesign *******************************************************************************/ package robocode.peer.robot; import robocode.*; import robocode.exception.EventInterruptedException; import robocode.peer.proxies.BasicRobotProxy; import robocode.robotinterfaces.IBasicRobot; import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Matthew Reeder (contributor) * @author Robert D. Maupin (contributor) * @author Nathaniel Troutman (contributor) * @author Pavel Savara (contributor) */ public class EventManager implements IEventManager { private BasicRobotProxy robotProxy; private final static int MAX_PRIORITY = 100; public final static int MAX_EVENT_STACK = 2; private int currentTopEventPriority; private Event currentTopEvent; private final List customEvents = new CopyOnWriteArrayList(); private final EventQueue eventQueue; private final boolean[] interruptible = new boolean[MAX_PRIORITY + 1]; private Dictionary namedEvents; private ScannedRobotEvent dummyScannedRobotEvent; public final static int MAX_QUEUE_SIZE = 256; private IBasicRobot robot; /** * EventManager constructor comment. * * @param robotProxy robotProxy */ public EventManager(BasicRobotProxy robotProxy) { super(); registerNamedEvents(); this.robotProxy = robotProxy; eventQueue = new EventQueue(); reset(); } public void add(Event e) { if (!RobotClassManager.isCriticalEvent(e)) { RobotClassManager.setEventPriority(e, getEventPriority(e.getClass().getName())); } addImpl(e); } private void addImpl(Event e) { if (eventQueue != null) { if (eventQueue.size() > MAX_QUEUE_SIZE) { System.out.println( "Not adding to " + robotProxy.getStatics().getName() + "'s queue, exceeded " + MAX_QUEUE_SIZE + " events in queue."); return; } eventQueue.add(e); } } public void addCustomEvent(Condition condition) { customEvents.add(condition); } public void clearAllEvents(boolean includingSystemEvents) { eventQueue.clear(includingSystemEvents); } public void cleanup() { // Remove all events reset(); // Remove all references to robots robot = null; robotProxy = null; } /** * Returns a list containing all events currently in the robot's queue. * You might, for example, call this while processing another event. *

*

Example: *

	 *    for (Event e : getAllEvents()) {
	 *       if (e instanceof HitByRobotEvent)
	 *         (do something with e) 
	 *       else if (e instanceof HitByBulletEvent)
	 *         (so something else with e) 
	 *    }
	 * 
* * @see BulletHitEvent * @see BulletMissedEvent * @see HitByBulletEvent * @see HitRobotEvent * @see HitWallEvent * @see SkippedTurnEvent * @see Event * @see List */ public List getAllEvents() { List events = Collections.synchronizedList(new ArrayList()); synchronized (eventQueue) { for (Event e : eventQueue) { events.add(e); } } return events; } /** * Returns a list containing all BulletHitBulletEvents currently in the robot's queue. * You might, for example, call this while processing another event. *

*

Example: *

	 *    for (BulletHitBulletEvent e : getBulletHitBulletEvents()) {
	 *       (do something with e) 
	 *    }
	 * 
* * @see BulletHitBulletEvent * @see List */ public List getBulletHitBulletEvents() { List events = Collections.synchronizedList(new ArrayList()); synchronized (eventQueue) { for (Event e : eventQueue) { if (e instanceof BulletHitBulletEvent) { events.add((BulletHitBulletEvent) e); } } } return events; } /** * Returns a list containing all BulletHitEvents currently in the robot's queue. * You might, for example, call this while processing another event. *

*

Example: *

	 *    for (BulletHitEvent e : getBulletHitEvents()) {
	 *       (do something with e) 
	 *    }
	 * 
* * @see BulletHitEvent * @see List */ public List getBulletHitEvents() { List events = Collections.synchronizedList(new ArrayList()); synchronized (eventQueue) { for (Event e : eventQueue) { if (e instanceof BulletHitEvent) { events.add((BulletHitEvent) e); } } } return events; } /** * Returns a list containing all BulletMissedEvents currently in the robot's queue. * You might, for example, call this while processing another event. *

*

Example: *

	 *    for (BulletMissedEvent e : getBulletMissedEvents()) {
	 *       (do something with e) 
	 *    }
	 * 
* * @see BulletMissedEvent * @see List */ public List getBulletMissedEvents() { List events = Collections.synchronizedList(new ArrayList()); synchronized (eventQueue) { for (Event e : eventQueue) { if (e instanceof BulletMissedEvent) { events.add((BulletMissedEvent) e); } } } return events; } public int getCurrentTopEventPriority() { return currentTopEventPriority; } public Event getCurrentTopEvent() { return currentTopEvent; } /** * Returns a list containing all HitByBulletEvents currently in the robot's queue. * You might, for example, call this while processing another event. *

*

Example: *

	 *    for (HitByBulletEvent e : getHitByBulletEvents()) {
	 *       (do something with e) 
	 *    }
	 * 
* * @see HitByBulletEvent * @see List */ public List getHitByBulletEvents() { List events = Collections.synchronizedList(new ArrayList()); synchronized (eventQueue) { for (Event e : eventQueue) { if (e instanceof HitByBulletEvent) { events.add((HitByBulletEvent) e); } } } return events; } /** * Returns a list containing all HitRobotEvents currently in the robot's queue. * You might, for example, call this while processing another event. *

*

Example: *

	 *    for (HitRobotEvent e : getHitRobotEvents()) {
	 *       (do something with e) 
	 *    }
	 * 
* * @see HitRobotEvent * @see List */ public List getHitRobotEvents() { List events = Collections.synchronizedList(new ArrayList()); synchronized (eventQueue) { for (Event e : eventQueue) { if (e instanceof HitRobotEvent) { events.add((HitRobotEvent) e); } } } return events; } /** * Returns a list containing all HitWallEvents currently in the robot's queue. * You might, for example, call this while processing another event. *

*

Example: *

	 *    for (HitWallEvent e : getHitWallEvents()) {
	 *       (do something with e) 
	 *    }
	 * 
* * @see HitWallEvent * @see List */ public List getHitWallEvents() { List events = Collections.synchronizedList(new ArrayList()); synchronized (eventQueue) { for (Event e : eventQueue) { if (e instanceof HitWallEvent) { events.add((HitWallEvent) e); } } } return events; } public boolean getInterruptible(int priority) { return this.interruptible[priority]; } private IBasicRobot getRobot() { return robot; } public void setRobot(IBasicRobot r) { this.robot = r; } /** * Returns a list containing all RobotDeathEvents currently in the robot's queue. * You might, for example, call this while processing another event. *

*

Example: *

	 *    for (RobotDeathEvent e : getRobotDeathEvents()) {
	 *       (do something with e) 
	 *    }
	 * 
* * @see RobotDeathEvent * @see List */ public List getRobotDeathEvents() { List events = Collections.synchronizedList(new ArrayList()); synchronized (eventQueue) { for (Event e : eventQueue) { if (e instanceof RobotDeathEvent) { events.add((RobotDeathEvent) e); } } } return events; } public int getScannedRobotEventPriority() { return dummyScannedRobotEvent.getPriority(); } /** * Returns a list containing all ScannedRobotEvents currently in the robot's queue. * You might, for example, call this while processing another event. *

*

Example: *

	 *    for (ScannedRobotEvent e : getScannedRobotEvents()) {
	 *       (do something with e) 
	 *    }
	 * 
* * @see ScannedRobotEvent * @see List */ public List getScannedRobotEvents() { List events = Collections.synchronizedList(new ArrayList()); synchronized (eventQueue) { for (Event e : eventQueue) { if (e instanceof ScannedRobotEvent) { events.add((ScannedRobotEvent) e); } } } return events; } public long getTime() { return robotProxy.getTimeImpl(); } public void processEvents() { // remove too old stuff eventQueue.clear(getTime() - MAX_EVENT_STACK); // Process custom events for (Condition customEvent : customEvents) { boolean conditionSatisfied = false; robotProxy.setTestingCondition(true); try { conditionSatisfied = customEvent.test(); } finally { robotProxy.setTestingCondition(false); } if (conditionSatisfied) { CustomEvent event = new CustomEvent(customEvent); RobotClassManager.setTime(event, getTime()); addImpl(event); } } // Process event queue here eventQueue.sort(); Event currentEvent = null; if (eventQueue.size() > 0) { currentEvent = eventQueue.get(0); } while (currentEvent != null && currentEvent.getPriority() >= currentTopEventPriority) { if (currentEvent.getPriority() == currentTopEventPriority) { if (currentTopEventPriority > Integer.MIN_VALUE && getInterruptible(currentTopEventPriority)) { setInterruptible(currentTopEventPriority, false); // we're going to restart it, so reset. // We are already in an event handler, took action, and a new event was generated. // So we want to break out of the old handler to process it here. throw new EventInterruptedException(currentEvent.getPriority()); } break; } int oldTopEventPriority = currentTopEventPriority; currentTopEventPriority = currentEvent.getPriority(); currentTopEvent = currentEvent; eventQueue.remove(currentEvent); try { dispatch(currentEvent); setInterruptible(currentTopEventPriority, false); } catch (EventInterruptedException e) { currentTopEvent = null; } catch (RuntimeException e) { currentTopEventPriority = oldTopEventPriority; currentTopEvent = null; throw e; } catch (Error e) { currentTopEventPriority = oldTopEventPriority; currentTopEvent = null; throw e; } currentTopEventPriority = oldTopEventPriority; currentEvent = (eventQueue.size() > 0) ? eventQueue.get(0) : null; } } private void dispatch(Event currentEvent) { final IBasicRobot robot = getRobot(); if (robot != null && currentEvent != null) { try { // skip too old events if ((currentEvent.getTime() > getTime() - MAX_EVENT_STACK) || RobotClassManager.isCriticalEvent(currentEvent)) { RobotClassManager.dispatch(currentEvent, robot, robotProxy.getStatics(), robotProxy.getGraphicsImpl()); } } catch (Exception ex) { robotProxy.getOut().println("SYSTEM: Exception occurred on " + currentEvent.getClass().getName()); ex.printStackTrace(robotProxy.getOut()); } } } public void removeCustomEvent(Condition condition) { customEvents.remove(condition); } public void resetCustomEvents() { customEvents.clear(); } public synchronized void reset() { currentTopEventPriority = Integer.MIN_VALUE; clearAllEvents(true); customEvents.clear(); } public void setInterruptible(int priority, boolean interruptable) { if (priority < 0 || priority > 99) { return; } this.interruptible[priority] = interruptable; } /** * Returns a vector containing all MessageEvents currently in the robot's * queue. You might, for example, call this while processing another event. *

* Example: *

	 *   for (MessageEvent e : getMessageEvents()) {
	 *       (do something with e) 
	 *   }
	 * 
* * @return a vector containing all MessageEvents currently in the robot's * queue * @see MessageEvent * @since 1.2.6 */ public List getMessageEvents() { List events = Collections.synchronizedList(new ArrayList()); synchronized (eventQueue) { for (Event e : eventQueue) { if (e instanceof MessageEvent) { events.add((MessageEvent) e); } } } return events; } /** * Returns a vector containing all StatusEvents currently in the robot's * queue. You might, for example, call this while processing another event. *

* Example: *

	 *   for (StatusEvent e : getStatusEvents()) {
	 *       (do something with e) 
	 *   }
	 * 
* * @return a vector containing all StatusEvents currently in the robot's * queue. * @see StatusEvent * @since 1.5 */ public List getStatusEvents() { List events = Collections.synchronizedList(new ArrayList()); synchronized (eventQueue) { for (Event e : eventQueue) { if (e instanceof StatusEvent) { events.add((StatusEvent) e); } } } return events; } public int getEventPriority(String eventClass) { if (eventClass == null) { return -1; } final Event event = namedEvents.get(eventClass); if (event == null) { return -1; } return event.getPriority(); } public void setEventPriority(String eventClass, int priority) { if (eventClass == null) { return; } final Event event = namedEvents.get(eventClass); if (event == null) { robotProxy.getOut().println("SYSTEM: Unknown event class: " + eventClass); return; } if (RobotClassManager.isCriticalEvent(event)) { System.out.println("SYSTEM: You may not change the priority of system event. setPriority ignored."); } RobotClassManager.setEventPriority(event, priority); } private void registerNamedEvents() { namedEvents = new Hashtable(); dummyScannedRobotEvent = new ScannedRobotEvent(null, 0, 0, 0, 0, 0); registerNamedEvent(new BattleEndedEvent(false, null)); registerNamedEvent(new BulletHitBulletEvent(null, null)); registerNamedEvent(new BulletHitEvent(null, 0, null)); registerNamedEvent(new BulletMissedEvent(null)); registerNamedEvent(new DeathEvent()); registerNamedEvent(new HitByBulletEvent(0, null)); registerNamedEvent(new HitRobotEvent(null, 0, 0, false)); registerNamedEvent(new HitWallEvent(0)); registerNamedEvent(new KeyPressedEvent(null)); registerNamedEvent(new KeyReleasedEvent(null)); registerNamedEvent(new KeyTypedEvent(null)); registerNamedEvent(new MessageEvent(null, null)); registerNamedEvent(new MouseClickedEvent(null)); registerNamedEvent(new MouseDraggedEvent(null)); registerNamedEvent(new MouseEnteredEvent(null)); registerNamedEvent(new MouseExitedEvent(null)); registerNamedEvent(new MouseMovedEvent(null)); registerNamedEvent(new MousePressedEvent(null)); registerNamedEvent(new MouseReleasedEvent(null)); registerNamedEvent(new MouseWheelMovedEvent(null)); registerNamedEvent(new PaintEvent()); registerNamedEvent(new RobotDeathEvent(null)); registerNamedEvent(dummyScannedRobotEvent); registerNamedEvent(new SkippedTurnEvent()); registerNamedEvent(new StatusEvent(null)); registerNamedEvent(new WinEvent()); // same as any line above but for custom event final DummyCustomEvent custom = new DummyCustomEvent(); namedEvents.put("robocode.CustomEvent", custom); namedEvents.put("CustomEvent", custom); } private void registerNamedEvent(Event e) { final String name = e.getClass().getName(); if (!RobotClassManager.isCriticalEvent(e)) { RobotClassManager.setDefaultPriority(e); } namedEvents.put(name, e); namedEvents.put(name.substring(9), e); } private static final class DummyCustomEvent extends CustomEvent { private static final long serialVersionUID = 1L; public DummyCustomEvent() { super(null); } } } robocode/robocode/robocode/peer/robot/IEventManager.java0000644000175000017500000000272111130241112022630 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.peer.robot; import robocode.*; import java.util.List; /** * @author Pavel Savara (original) */ public interface IEventManager { void addCustomEvent(Condition condition); void removeCustomEvent(Condition condition); void clearAllEvents(boolean includingSystemEvents); void setEventPriority(String eventClass, int priority); int getEventPriority(String eventClass); java.util.List getAllEvents(); List getBulletMissedEvents(); List getBulletHitBulletEvents(); List getBulletHitEvents(); List getHitByBulletEvents(); List getHitRobotEvents(); List getHitWallEvents(); List getRobotDeathEvents(); List getScannedRobotEvents(); // team List getMessageEvents(); } robocode/robocode/robocode/peer/robot/IHiddenBulletHelper.java0000644000175000017500000000145411130241112023761 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.peer.robot; import robocode.Bullet; import robocode.peer.BulletStatus; /** * @author Pavel Savara (original) */ public interface IHiddenBulletHelper { void update(Bullet bullet, BulletStatus status); } robocode/robocode/robocode/peer/robot/TeamMessage.java0000644000175000017500000000203411130241112022333 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.peer.robot; import java.io.Serializable; /** * @author Pavel Savara (original) */ public class TeamMessage implements Serializable { private static final long serialVersionUID = 1L; public TeamMessage(String sender, String recipient, byte[] message) { this.sender = sender; this.recipient = recipient; this.message = message; } public final String sender; public final String recipient; public final byte[] message; } robocode/robocode/robocode/peer/robot/RobotThreadManager.java0000644000175000017500000001535311130241112023660 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup * - Updated to use methods from the Logger, which replaces logger methods * that have been (re)moved from the robocode.util.Utils class * - Moved the stopThread() method from the RobocodeDeprecated class into * this class * - Bugfix: The waitForStop() was using 'runThreadGroup.activeCount > 0' * instead of runThread.isAlive() causing some robots to be forced to stop. * In the same time this method was simplified up updated for faster CPU's * Pavel Savara * - moved to RobotProxy side * - forceStop is faster and smarter * - start of thread is creating safe ATW queue *******************************************************************************/ package robocode.peer.robot; import robocode.exception.RobotException; import robocode.io.Logger; import static robocode.io.Logger.logError; import static robocode.io.Logger.logMessage; import robocode.manager.IThreadManager; import robocode.peer.proxies.IHostedThread; import robocode.security.LoggingThreadGroup; import robocode.security.RobocodeSecurityManager; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ public class RobotThreadManager { private final IHostedThread robotProxy; private Thread runThread; private LoggingThreadGroup runThreadGroup; private Object awtForThreadGroup; public RobotThreadManager(IHostedThread robotProxy) { this.robotProxy = robotProxy; createThreadGroup(); } public void cleanup() { try { if (runThread == null || !runThread.isAlive()) { if (!discardAWT()) { runThreadGroup.destroy(); } } else { Logger.logError("Warning, could not destroy " + runThread.getName()); } } catch (Exception e) { Logger.logError("Warning, could not destroy " + runThreadGroup.getName(), e); } } public void initAWT() { if (awtForThreadGroup == null) { awtForThreadGroup = RobocodeSecurityManager.createNewAppContext(); } } public boolean discardAWT() { boolean res = false; if (awtForThreadGroup != null && !(awtForThreadGroup instanceof Integer)) { res = RobocodeSecurityManager.disposeAppContext(awtForThreadGroup); awtForThreadGroup = null; } return res; } public void checkRunThread() { if (Thread.currentThread() != runThread) { throw new RobotException("You cannot take action in this thread!"); } } public void start(IThreadManager threadManager) { try { threadManager.addThreadGroup(runThreadGroup, robotProxy); runThread = new Thread(runThreadGroup, robotProxy, robotProxy.getStatics().getName()); runThread.setDaemon(true); runThread.setPriority(Thread.NORM_PRIORITY - 1); runThread.start(); } catch (Exception e) { logError("Exception starting thread: ", e); } } /** * @return true as peacefull stop */ public boolean waitForStop() { boolean stop = false; if (runThread != null && runThread.isAlive()) { runThread.interrupt(); waitForStop(runThread); stop = runThread.isAlive(); } Thread[] threads = new Thread[100]; runThreadGroup.enumerate(threads); for (Thread thread : threads) { if (thread != null && thread != runThread && thread.isAlive()) { thread.interrupt(); waitForStop(thread); stop |= thread.isAlive(); } } if (stop) { if (!System.getProperty("NOSECURITY", "false").equals("true")) { logError("Robot " + robotProxy.getStatics().getName() + " is not stopping. Forcing a stop."); return forceStop(); } else { logError( "Robot " + robotProxy.getStatics().getName() + " is still running. Not stopping it because security is off."); } } return true; } /** * @return true as peacefull stop */ public boolean forceStop() { int res = stopSteps(runThread); Thread[] threads = new Thread[100]; runThreadGroup.enumerate(threads); for (Thread thread : threads) { if (thread != null && thread != runThread && thread.isAlive()) { res += stopSteps(thread); } } if (res > 0) { robotProxy.println("SYSTEM: This robot has been stopped. No score will be generated."); // recycle thread group createThreadGroup(); } runThread = null; return res == 0; } /** * @param t thread to stop * @return 0 as peacefull stop */ private int stopSteps(Thread t) { if (t != null && t.isAlive()) { interrupt(t); if (t.isAlive()) { stop(t); } if (t.isAlive()) { // noinspection deprecation // t.suspend(); logError("Warning! Unable to stop thread: " + runThread.getName()); } else { logMessage(robotProxy.getStatics().getName() + " has been stopped."); } return 1; } return 0; } @SuppressWarnings("deprecation") private void stop(Thread t) { if (t != null) { // noinspection deprecation t.stop(); try { t.join(1500); } catch (InterruptedException e) { // Immediately reasserts the exception by interrupting the caller thread itself Thread.currentThread().interrupt(); } } } private void interrupt(Thread t) { if (t != null) { try { t.setPriority(Thread.MIN_PRIORITY); } catch (NullPointerException e) { logError("Sometimes this occurs in the Java core?!", e); } t.interrupt(); try { t.join(500); } catch (InterruptedException e) { // Immediately reasserts the exception by interrupting the caller thread itself Thread.currentThread().interrupt(); } } } private void waitForStop(Thread thread) { for (int j = 0; j < 100 && thread.isAlive(); j++) { if (j == 50) { logError( "Waiting for robot " + robotProxy.getStatics().getName() + " to stop thread " + thread.getName()); } try { Thread.sleep(10); } catch (InterruptedException e) { // Immediately reasserts the exception by interrupting the caller thread itself Thread.currentThread().interrupt(); break; // We are in a loop } } } private void createThreadGroup() { runThreadGroup = new LoggingThreadGroup(robotProxy.getStatics().getName()); // bit lower than battle have runThreadGroup.setMaxPriority(Thread.NORM_PRIORITY - 1); } } robocode/robocode/robocode/peer/robot/RobotStatistics.java0000644000175000017500000002077511130241112023314 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Luis Crespo * - Added getCurrentScore() * Flemming N. Larsen * - Bugfix: scoreDeath() incremented totalFirsts even if the robot was * already a winner, where scoreWinner() has already been called previously * - Added constructor that takes an additonal RobotResults that must be * copied into this object and added the getResults() in order to support * the replay feature * - Changed the survivalScore and totalSurvivalScore fields to be integers * - Renamed method names and removed unused methods * - Ordered all methods more naturally * - Added methods for getting current scores * - Optimizations * - Removed damage parameter from the scoreRammingDamage() method, as the * damage is constant and defined by Rules.ROBOT_HIT_DAMAGE and the score * of hitting a robot is defined by Rules.ROBOT_HIT_BONUS * Titus Chen * - Bugfix: Initial getResults() method only factored in the most recent * round * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap * Nathaniel Troutman * - Added cleanup() method for cleaning up references to internal classes * to prevent circular references causing memory leaks *******************************************************************************/ package robocode.peer.robot; import robocode.BattleResults; import robocode.peer.RobotPeer; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Luis Crespo (contributor) * @author Titus Chen (contributor) * @author Robert D. Maupin (contributor) * @author Nathaniel Troutman (contributor) */ public class RobotStatistics implements robocode.peer.ContestantStatistics { private final RobotPeer robotPeer; private int rank; private final int robots; private boolean isActive; private boolean isInRound; private double survivalScore; private double lastSurvivorBonus; private double bulletDamageScore; private double bulletKillBonus; private double rammingDamageScore; private double rammingKillBonus; private double robotDamage[]; private double totalScore; private double totalSurvivalScore; private double totalLastSurvivorBonus; private double totalBulletDamageScore; private double totalBulletKillBonus; private double totalRammingDamageScore; private double totalRammingKillBonus; private int totalFirsts; private int totalSeconds; private int totalThirds; public RobotStatistics(RobotPeer robotPeer, int robots) { super(); this.robotPeer = robotPeer; this.robots = robots; } public RobotStatistics(RobotPeer robotPeer, int robots, BattleResults results) { this(robotPeer, robots); totalScore = results.getScore(); totalSurvivalScore = results.getSurvival(); totalLastSurvivorBonus = results.getLastSurvivorBonus(); totalBulletDamageScore = results.getBulletDamage(); totalBulletKillBonus = results.getBulletDamageBonus(); totalRammingDamageScore = results.getRamDamage(); totalRammingKillBonus = results.getRamDamageBonus(); totalFirsts = results.getFirsts(); totalSeconds = results.getSeconds(); totalThirds = results.getThirds(); } public void setRank(int rank) { this.rank = rank; } public void initialize() { resetScores(); robotDamage = null; isActive = true; isInRound = true; } public void resetScores() { survivalScore = 0; lastSurvivorBonus = 0; bulletDamageScore = 0; bulletKillBonus = 0; rammingDamageScore = 0; rammingKillBonus = 0; } public void generateTotals() { totalSurvivalScore += survivalScore; totalLastSurvivorBonus += lastSurvivorBonus; totalBulletDamageScore += bulletDamageScore; totalBulletKillBonus += bulletKillBonus; totalRammingDamageScore += rammingDamageScore; totalRammingKillBonus += rammingKillBonus; totalScore = totalBulletDamageScore + totalRammingDamageScore + totalSurvivalScore + totalRammingKillBonus + totalBulletKillBonus + totalLastSurvivorBonus; isInRound = false; } public double getTotalScore() { return totalScore; } public double getTotalSurvivalScore() { return totalSurvivalScore; } public double getTotalLastSurvivorBonus() { return totalLastSurvivorBonus; } public double getTotalBulletDamageScore() { return totalBulletDamageScore; } public double getTotalBulletKillBonus() { return totalBulletKillBonus; } public double getTotalRammingDamageScore() { return totalRammingDamageScore; } public double getTotalRammingKillBonus() { return totalRammingKillBonus; } public int getTotalFirsts() { return totalFirsts; } public int getTotalSeconds() { return totalSeconds; } public int getTotalThirds() { return totalThirds; } public double getCurrentScore() { return bulletDamageScore + rammingDamageScore + survivalScore + rammingKillBonus + bulletKillBonus + lastSurvivorBonus; } public double getCurrentSurvivalScore() { return survivalScore; } public double getCurrentSurvivalBonus() { return lastSurvivorBonus; } public double getCurrentBulletDamageScore() { return bulletDamageScore; } public double getCurrentBulletKillBonus() { return bulletKillBonus; } public double getCurrentRammingDamageScore() { return rammingDamageScore; } public double getCurrentRammingKillBonus() { return rammingKillBonus; } public void scoreSurvival() { if (isActive) { survivalScore += 50; } } public void scoreLastSurvivor() { if (isActive) { int enemyCount = robots - 1; if (robotPeer.getTeamPeer() != null) { enemyCount -= (robotPeer.getTeamPeer().size() - 1); } lastSurvivorBonus += 10 * enemyCount; if (robotPeer.getTeamPeer() == null || robotPeer.isTeamLeader()) { totalFirsts++; } } } public void scoreBulletDamage(int robot, double damage) { if (isActive) { getRobotDamage()[robot] += damage; bulletDamageScore += damage; } } public double scoreBulletKill(int robot) { if (isActive) { double bonus = 0; if (robotPeer.getTeamPeer() == null) { bonus = getRobotDamage()[robot] * .2; } else { for (RobotPeer teammate : robotPeer.getTeamPeer()) { bonus += teammate.getRobotStatistics().getRobotDamage()[robot] * .2; } } bulletKillBonus += bonus; return bonus; } return 0; } public void scoreRammingDamage(int robot) { if (isActive) { getRobotDamage()[robot] += robocode.Rules.ROBOT_HIT_DAMAGE; rammingDamageScore += robocode.Rules.ROBOT_HIT_BONUS; } } public double scoreRammingKill(int robot) { if (isActive) { double bonus = 0; if (robotPeer.getTeamPeer() == null) { bonus = getRobotDamage()[robot] * .3; } else { for (RobotPeer teammate : robotPeer.getTeamPeer()) { bonus += teammate.getRobotStatistics().getRobotDamage()[robot] * .3; } } rammingKillBonus += bonus; return bonus; } return 0; } public void scoreRobotDeath(int enemiesRemaining) { switch (enemiesRemaining) { case 0: if (!robotPeer.isWinner()) { totalFirsts++; } break; case 1: totalSeconds++; break; case 2: totalThirds++; break; } } public void scoreFirsts() { if (isActive) { totalFirsts++; } } public void setInactive() { resetScores(); isActive = false; } public BattleResults getFinalResults() { return new BattleResults(robotPeer.getTeamName(), rank, totalScore, totalSurvivalScore, totalLastSurvivorBonus, totalBulletDamageScore, totalBulletKillBonus, totalRammingDamageScore, totalRammingKillBonus, totalFirsts, totalSeconds, totalThirds); } private double[] getRobotDamage() { if (robotDamage == null) { robotDamage = new double[robots]; } return robotDamage; } public void cleanup() {// Do nothing, for now } public boolean isInRound() { return isInRound; } } robocode/robocode/robocode/peer/robot/RobotClassManager.java0000644000175000017500000002016711130241112023515 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Added isSecurityOn() * - Changed loadUnresolvedClasses() to use loadClass() instead of * loadRobotClass() if security is turned off * - Ported to Java 5.0 * - Updated to use methods from the Logger, which replaces logger methods * that have been (re)moved from the robocode.util.Utils class * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap * Nathaniel Troutman * - Added cleanup() method for cleaning up references to internal classes * to prevent circular references causing memory leaks *******************************************************************************/ package robocode.peer.robot; import robocode.Bullet; import robocode.Event; import robocode.io.Logger; import robocode.manager.NameManager; import robocode.peer.BulletStatus; import robocode.peer.RobotStatics; import robocode.repository.RobotFileSpecification; import robocode.robotinterfaces.IBasicRobot; import robocode.security.RobocodeClassLoader; import java.awt.*; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.*; import java.util.List; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Robert D. Maupin (contributor) * @author Nathaniel Troutman (contributor) */ public class RobotClassManager { private RobotFileSpecification robotFileSpecification; private Class robotClass; private final Map referencedClasses = Collections.synchronizedMap(new HashMap()); private RobocodeClassLoader robotClassLoader = null; // only used if we're being controlled by RobocodeEngine: private robocode.control.RobotSpecification controlRobotSpecification; private final String fullClassName; private final String teamName; private String uid = ""; /** * RobotClassHandler constructor * * @param robotFileSpecification specification */ public RobotClassManager(RobotFileSpecification robotFileSpecification) { this(robotFileSpecification, null); } public RobotClassManager(RobotFileSpecification robotFileSpecification, String teamName) { this.robotFileSpecification = robotFileSpecification; this.fullClassName = robotFileSpecification.getName(); this.teamName = teamName; } public String getRootPackage() { return getClassNameManager().getRootPackage(); } public NameManager getClassNameManager() { return robotFileSpecification.getNameManager(); } public void addReferencedClasses(List refClasses) { if (refClasses == null) { return; } for (String refClass : refClasses) { String className = refClass.replace('/', '.'); if (getRootPackage() == null || !(className.startsWith("java") || className.startsWith("robocode"))) { // TODO ZAMO || className.startsWith("scala") if (getRootPackage() == null && !className.equals(fullClassName)) { continue; } if (!referencedClasses.containsKey(className)) { referencedClasses.put(className, "false"); } } } } public void addResolvedClass(String className) { if (!referencedClasses.containsKey(className)) { Logger.logError( fullClassName + ": Cannot set " + className + " to resolved, did not know it was referenced."); return; } referencedClasses.put(className, "true"); } public String getFullClassName() { // Better not be null... return fullClassName; } public Set getReferencedClasses() { return referencedClasses.keySet(); } public Class getRobotClass() { return robotClass; } public RobocodeClassLoader getRobotClassLoader() { if (robotClassLoader == null) { robotClassLoader = new RobocodeClassLoader(getClass().getClassLoader(), this); } return robotClassLoader; } public RobotFileSpecification getRobotSpecification() { return robotFileSpecification; } public void loadUnresolvedClasses() throws ClassNotFoundException { Iterator keys = referencedClasses.keySet().iterator(); while (keys.hasNext()) { String s = keys.next(); if (referencedClasses.get(s).equals("false")) { // resolve, then rebuild keys... if (isSecutityOn()) { robotClassLoader.loadRobotClass(s, false); } else { robotClassLoader.loadClass(s, true); addResolvedClass(s); } keys = referencedClasses.keySet().iterator(); } } } public void setRobotClass(Class newRobotClass) { robotClass = newRobotClass; } @Override public String toString() { return getRobotSpecification().getNameManager().getUniqueFullClassNameWithVersion(); } /** * Gets the robotSpecification. * * @return Returns a RobotSpecification */ public robocode.control.RobotSpecification getControlRobotSpecification() { return controlRobotSpecification; } /** * Sets the robotSpecification. * * @param controlRobotSpecification The robotSpecification to set */ public void setControlRobotSpecification(robocode.control.RobotSpecification controlRobotSpecification) { this.controlRobotSpecification = controlRobotSpecification; } /** * Gets the teamManager. * * @return Returns a name of team */ public String getTeamName() { return teamName; } /** * Gets the uid. * * @return Returns a long */ public String getUid() { return uid; } /** * Sets the uid. * * @param uid The uid to set */ public void setUid(String uid) { this.uid = uid; } /** * @return true if the security is enabled; false otherwise */ public static boolean isSecutityOn() { return !System.getProperty("NOSECURITY", "false").equals("true"); } public void cleanup() { robotClass = null; if (robotClassLoader != null) { robotClassLoader.cleanup(); robotClassLoader = null; } if (referencedClasses != null) { referencedClasses.clear(); } robotFileSpecification = null; } // ----------- // helpers for accessing hidden methods on events // ----------- private static IHiddenEventHelper eventHelper; private static IHiddenBulletHelper bulletHelper; static { Method method; try { method = Event.class.getDeclaredMethod("createHiddenHelper"); method.setAccessible(true); eventHelper = (IHiddenEventHelper) method.invoke(null); method.setAccessible(false); method = Bullet.class.getDeclaredMethod("createHiddenHelper"); method.setAccessible(true); bulletHelper = (IHiddenBulletHelper) method.invoke(null); method.setAccessible(false); } catch (NoSuchMethodException e) { Logger.logError(e); } catch (InvocationTargetException e) { Logger.logError(e); } catch (IllegalAccessException e) { Logger.logError(e); } } public static boolean isCriticalEvent(Event e) { return eventHelper.isCriticalEvent(e); } public static void setTime(Event e, long newTime) { eventHelper.setTime(e, newTime); } public static void setEventPriority(Event e, int newPriority) { eventHelper.setPriority(e, newPriority); } public static void dispatch(Event event, IBasicRobot robot, RobotStatics statics, Graphics2D graphics) { eventHelper.dispatch(event, robot, statics, graphics); } public static void setDefaultPriority(Event e) { eventHelper.setDefaultPriority(e); } public static void updateBullets(Event e, Hashtable bullets) { eventHelper.updateBullets(e, bullets); } public static void update(Bullet bullet, BulletStatus status) { bulletHelper.update(bullet, status); } } robocode/robocode/robocode/peer/robot/IHiddenEventHelper.java0000644000175000017500000000230111130241112023603 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.peer.robot; import robocode.Bullet; import robocode.Event; import robocode.peer.RobotStatics; import robocode.robotinterfaces.IBasicRobot; import java.awt.*; import java.util.Hashtable; /** * @author Pavel Savara (original) */ public interface IHiddenEventHelper { void setDefaultPriority(Event event); void setPriority(Event event, int newPriority); void setTime(Event event, long newTime); boolean isCriticalEvent(Event event); void dispatch(Event event, IBasicRobot robot, RobotStatics statics, Graphics2D graphics); void updateBullets(Event event, Hashtable bullets); } robocode/robocode/robocode/peer/DebugProperty.java0000644000175000017500000000434011130241112021610 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.peer; import robocode.common.IXmlSerializable; import robocode.common.XmlReader; import robocode.common.XmlWriter; import robocode.control.snapshot.IDebugProperty; import java.io.IOException; import java.io.Serializable; import java.util.Dictionary; /** * @author Pavel Savara (original) */ public class DebugProperty implements Serializable, IXmlSerializable, IDebugProperty { private static final long serialVersionUID = 1L; public DebugProperty() {} public DebugProperty(String key, String value) { this.setKey(key); this.setValue(value); } private String key; private String value; public void writeXml(XmlWriter writer, Dictionary options) throws IOException { writer.startElement("debug"); { writer.writeAttribute("key", getKey()); writer.writeAttribute("value", getValue()); } writer.endElement(); } public XmlReader.Element readXml(XmlReader reader) { return reader.expect("debug", new XmlReader.Element() { public IXmlSerializable read(XmlReader reader) { final DebugProperty snapshot = new DebugProperty(); reader.expect("key", new XmlReader.Attribute() { public void read(String value) { snapshot.setKey(value); } }); reader.expect("value", new XmlReader.Attribute() { public void read(String value) { snapshot.setValue(value); } }); return snapshot; } }); } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } } robocode/robocode/robocode/peer/IRobotPeerBattle.java0000644000175000017500000000323111130241112022161 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.peer; import robocode.Event; import robocode.peer.robot.RobotStatistics; import java.util.List; /** * @author Pavel Savara (original) */ public interface IRobotPeerBattle extends ContestantPeer { void setSGPaintEnabled(boolean enabled); RobotStatistics getRobotStatistics(); TeamPeer getTeamPeer(); void publishStatus(long currentTurn); void addEvent(Event event); void setPaintEnabled(boolean enabled); void kill(); void cleanup(); boolean isDead(); boolean isAlive(); boolean isRunning(); boolean isWinner(); boolean isTeamLeader(); void setHalt(boolean value); void println(String s); void waitWakeup(); void waitSleeping(int millisWait, int microWait); void waitForStop(); void setWinner(boolean newWinner); void initializeRound(List robots, double[][] initialRobotPositions); void startRound(long waitTime); void setSkippedTurns(); void performLoadCommands(); void performMove(List robots, double zapEnergy); void performScan(List robots); } robocode/robocode/robocode/peer/ExecCommands.java0000644000175000017500000001742311130241112021371 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.peer; import robocode.Rules; import robocode.peer.robot.TeamMessage; import robocode.robotpaint.Graphics2DProxy; import java.io.Serializable; import static java.lang.Math.abs; import static java.lang.Math.min; import java.util.ArrayList; import java.util.List; /** * @author Pavel Savara (original) */ public final class ExecCommands implements Serializable { private static final long serialVersionUID = 1L; public static final int defaultBodyColor = 0xFF29298C; public static final int defaultGunColor = 0xFF29298C; public static final int defaultRadarColor = 0xFF29298C; public static final int defaultScanColor = 0xFF0000FF; public static final int defaultBulletColor = 0xFFFFFFFF; private double bodyTurnRemaining; private double radarTurnRemaining; private double gunTurnRemaining; private double distanceRemaining; private boolean isAdjustGunForBodyTurn; private boolean isAdjustRadarForGunTurn; private boolean isAdjustRadarForBodyTurn; private boolean isAdjustRadarForBodyTurnSet; private int bodyColor = defaultBodyColor; private int gunColor = defaultGunColor; private int radarColor = defaultRadarColor; private int scanColor = defaultScanColor; private int bulletColor = defaultBulletColor; private double maxTurnRate; private double maxVelocity; private boolean moved; private boolean scan; private boolean isIORobot; private boolean isTryingToPaint; private List bullets = new ArrayList(2); private List graphicsCalls; private String outputText; private List teamMessages = new ArrayList(); private List debugProperties; public ExecCommands() { setMaxVelocity(Double.MAX_VALUE); setMaxTurnRate(Double.MAX_VALUE); } public ExecCommands(ExecCommands origin, boolean fromRobot) { bodyTurnRemaining = origin.bodyTurnRemaining; radarTurnRemaining = origin.radarTurnRemaining; gunTurnRemaining = origin.gunTurnRemaining; distanceRemaining = origin.distanceRemaining; isAdjustGunForBodyTurn = origin.isAdjustGunForBodyTurn; isAdjustRadarForGunTurn = origin.isAdjustRadarForGunTurn; isAdjustRadarForBodyTurn = origin.isAdjustRadarForBodyTurn; isAdjustRadarForBodyTurnSet = origin.isAdjustRadarForBodyTurnSet; bodyColor = origin.bodyColor; gunColor = origin.gunColor; radarColor = origin.radarColor; bulletColor = origin.bulletColor; scanColor = origin.scanColor; maxTurnRate = origin.maxTurnRate; maxVelocity = origin.maxVelocity; if (fromRobot) { debugProperties = origin.debugProperties; bullets = origin.bullets; scan = origin.scan; moved = origin.moved; graphicsCalls = origin.graphicsCalls; outputText = origin.outputText; teamMessages = origin.teamMessages; isTryingToPaint = origin.isTryingToPaint; } } public void validate(RobotPeer peer) { if (Double.isNaN(maxTurnRate)) { peer.println("You cannot setMaxTurnRate to: " + maxTurnRate); return; } maxTurnRate = min(abs(maxTurnRate), Rules.MAX_TURN_RATE_RADIANS); if (Double.isNaN(maxVelocity)) { peer.println("You cannot setMaxVelocity to: " + maxVelocity); return; } maxVelocity = min(abs(maxVelocity), Rules.MAX_VELOCITY); } public int getBodyColor() { return bodyColor; } public int getRadarColor() { return radarColor; } public int getGunColor() { return gunColor; } public int getBulletColor() { return bulletColor; } public int getScanColor() { return scanColor; } public void setBodyColor(int color) { bodyColor = color; } public void setRadarColor(int color) { radarColor = color; } public void setGunColor(int color) { gunColor = color; } public void setBulletColor(int color) { bulletColor = color; } public void setScanColor(int color) { scanColor = color; } public double getBodyTurnRemaining() { return bodyTurnRemaining; } public void setBodyTurnRemaining(double bodyTurnRemaining) { this.bodyTurnRemaining = bodyTurnRemaining; } public double getRadarTurnRemaining() { return radarTurnRemaining; } public void setRadarTurnRemaining(double radarTurnRemaining) { this.radarTurnRemaining = radarTurnRemaining; } public double getGunTurnRemaining() { return gunTurnRemaining; } public void setGunTurnRemaining(double gunTurnRemaining) { this.gunTurnRemaining = gunTurnRemaining; } public double getDistanceRemaining() { return distanceRemaining; } public void setDistanceRemaining(double distanceRemaining) { this.distanceRemaining = distanceRemaining; } public boolean isAdjustGunForBodyTurn() { return isAdjustGunForBodyTurn; } public void setAdjustGunForBodyTurn(boolean adjustGunForBodyTurn) { isAdjustGunForBodyTurn = adjustGunForBodyTurn; } public boolean isAdjustRadarForGunTurn() { return isAdjustRadarForGunTurn; } public void setAdjustRadarForGunTurn(boolean adjustRadarForGunTurn) { isAdjustRadarForGunTurn = adjustRadarForGunTurn; } public boolean isAdjustRadarForBodyTurn() { return isAdjustRadarForBodyTurn; } public void setAdjustRadarForBodyTurn(boolean adjustRadarForBodyTurn) { isAdjustRadarForBodyTurn = adjustRadarForBodyTurn; } public boolean isAdjustRadarForBodyTurnSet() { return isAdjustRadarForBodyTurnSet; } public void setAdjustRadarForBodyTurnSet(boolean adjustRadarForBodyTurnSet) { isAdjustRadarForBodyTurnSet = adjustRadarForBodyTurnSet; } public double getMaxTurnRate() { return maxTurnRate; } public void setMaxTurnRate(double maxTurnRate) { this.maxTurnRate = min(abs(maxTurnRate), Rules.MAX_TURN_RATE_RADIANS); } public double getMaxVelocity() { return maxVelocity; } public void setMaxVelocity(double maxVelocity) { this.maxVelocity = min(abs(maxVelocity), Rules.MAX_VELOCITY); } public boolean isMoved() { return moved; } public void setMoved(boolean moved) { this.moved = moved; } public boolean isScan() { return scan; } public void setScan(boolean scan) { this.scan = scan; } public List getBullets() { return bullets; } public List getGraphicsCalls() { return graphicsCalls; } public List getDebugProperties() { return debugProperties; } public void setGraphicsCalls(List graphicsCalls) { this.graphicsCalls = graphicsCalls; } public String getOutputText() { final String out = outputText; outputText = ""; return out; } public void setOutputText(String out) { outputText = out; } public List getTeamMessages() { return teamMessages; } public boolean isIORobot() { return isIORobot; } public void setIORobot() { isIORobot = true; } public void setDebugProperty(String key, String value) { if (debugProperties == null) { debugProperties = new ArrayList(); } debugProperties.add(new DebugProperty(key, value)); } public boolean isTryingToPaint() { return isTryingToPaint; } public void setTryingToPaint(boolean tryingToPaint) { isTryingToPaint = tryingToPaint; } } robocode/robocode/robocode/peer/IRobotPeer.java0000644000175000017500000000152611130241112021032 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.peer; /** * @author Pavel Savara (original) */ public interface IRobotPeer { void drainEnergy(); void punishBadBehavior(); ExecResults waitForBattleEndImpl(ExecCommands newCommands); ExecResults executeImpl(ExecCommands newCommands); } robocode/robocode/robocode/peer/TextPeer.java0000644000175000017500000000476511130241112020570 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Removed dirty rectangle *******************************************************************************/ package robocode.peer; import java.awt.*; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) */ public class TextPeer { private String text; private int x; private int y; private long duration; private long visibleTime; private boolean ready = true; /** * Gets the text. * * @return Returns a String */ public String getText() { return text; } /** * Sets the text. * * @param text The text to set */ public void setText(String text) { this.text = text; ready = false; visibleTime = 0; } /** * Gets the x. * * @return Returns a int */ public int getX() { return x; } /** * Sets the x. * * @param x The x to set */ public void setX(int x) { this.x = x; } /** * Gets the y. * * @return Returns a int */ public int getY() { return y; } /** * Sets the y. * * @param y The y to set */ public void setY(int y) { this.y = y; } /** * Sets the duration. * * @param duration The new duration. */ public void setDuration(long duration) { this.duration = duration; } public void tick() { if (text == null) { return; } visibleTime++; if (visibleTime > duration) { setText(null); setReady(true); } } public Color getColor() { if (duration - visibleTime > 3) { return Color.white; } else if (duration - visibleTime > 2) { return Color.lightGray; } else if (duration - visibleTime > 1) { return Color.gray; } else { return Color.darkGray; } } /** * Gets the ready. * * @return Returns a boolean */ public boolean isReady() { return ready; } /** * Sets the ready. * * @param ready The ready to set */ public void setReady(boolean ready) { this.ready = ready; } } robocode/robocode/robocode/peer/ExplosionPeer.java0000644000175000017500000000437011130241112021614 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Luis Crespo * - Added states * Flemming N. Larsen * - Code cleanup * - Added constructor for the BulletPeer in order to support replay feature * - Fixed synchronization issue with update() * - Replaced getting the number of explosion frames from image manager with * integer constant * - Added getExplosionLength() that overrides the one at the super class * - Changed so that the update() method is no longer removing the bullet * from the battle field, which is now handled by updateBulletState() * Titus Chen * - Bugfix: Added Battle parameter to the constructor that takes a * BulletRecord as parameter due to a NullPointerException that was raised * as the battleField variable was not intialized *******************************************************************************/ package robocode.peer; import robocode.battle.Battle; import robocode.control.snapshot.BulletState; import java.util.List; /** * @author Mathew A. Nelson (original) * @author Luis Crespo (contributor) * @author Flemming N. Larsen (contributor) * @author Titus Chen (contributor) */ public class ExplosionPeer extends BulletPeer { private static final int EXPLOSION_LENGTH = 71; public ExplosionPeer(RobotPeer owner, Battle battle) { super(owner, battle, -1); x = owner.getX(); y = owner.getY(); victim = owner; power = 1; state = BulletState.EXPLODED; explosionImageIndex = 1; } @Override public final void update(List robots, List bullets) { x = owner.getX(); y = owner.getY(); nextFrame(); updateBulletState(); } @Override protected int getExplosionLength() { return EXPLOSION_LENGTH; } } robocode/robocode/robocode/peer/BulletPeer.java0000644000175000017500000002460211130241112021063 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup & optimizations * - Bugfix: checkBulletCollision() now uses a workaround for the Java 5 bug * #6457965 with Line2D.intersectsLine via intersect(Line2D.Double line) * - Integration of robocode.Rules * - Replaced width and height with radius * - Added constructor for the BulletRecord to support the replay feature * - Fixed synchonization issues on member fields and methods * - Some private methods were declared public, and have therefore been * redeclared as private * - Replaced getting the number of explosion frames from image manager with * integer constant * - Removed hitTime and resetHitTime(), which is handled thru frame instead * - Added getExplosionLength() to get the exact number of explosion frames * for this class and sub classes * - The update() method is now removing the bullet from the battle field, * when the bullet reaches the inactive state (i.e. is finished) * - Bugfix: Changed the delta coordinates of a bullet explosion on a robot, * so that it will be on the true bullet line for all bullet events * - The coordinates of the bullet when it hits, and the coordinates for the * explosion rendering on a robot has been split. So now the bullet is * painted using the new getPaintX() and getPaintY() methods * Luis Crespo * - Added states * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap * Titus Chen * - Bugfix: Added Battle parameter to the constructor that takes a * BulletRecord as parameter due to a NullPointerException that was raised * as the battleField variable was not intialized * Pavel Savara * - disconnected from Bullet, now we rather send BulletStatus to proxy side *******************************************************************************/ package robocode.peer; import robocode.*; import robocode.control.snapshot.BulletState; import robocode.battle.Battle; import java.awt.geom.Line2D; import static java.lang.Math.cos; import static java.lang.Math.sin; import java.util.List; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Luis Crespo (contributor) * @author Robert D. Maupin (contributor) * @author Titus Chen (constributor) */ public class BulletPeer { private static final int EXPLOSION_LENGTH = 17; private static final int RADIUS = 3; protected final RobotPeer owner; protected final Battle battle; private final BattleRules battleRules; private final int bulletId; protected RobotPeer victim; protected BulletState state; private double heading; protected double x; protected double y; private double lastX; private double lastY; protected double power; private double deltaX; private double deltaY; private final Line2D.Double boundingLine = new Line2D.Double(); protected int frame; private final int color; protected int explosionImageIndex; /** * BulletPeer constructor * * @param owner who fire the bullet * @param battle root battle * @param bulletId bullet */ public BulletPeer(RobotPeer owner, Battle battle, int bulletId) { super(); this.owner = owner; this.battle = battle; battleRules = battle.getBattleRules(); this.bulletId = bulletId; state = BulletState.FIRED; color = owner.getBulletColor(); // Store current bullet color set on robot } private void checkBulletCollision(List bullets) { for (BulletPeer b : bullets) { if (!(b == null || b == this) && b.isActive() && intersect(b.boundingLine)) { state = BulletState.HIT_BULLET; b.setState(state); frame = 0; x = lastX; y = lastY; owner.addEvent(new BulletHitBulletEvent(createBullet(), b.createBullet())); b.owner.addEvent(new BulletHitBulletEvent(b.createBullet(), createBullet())); break; } } } private Bullet createBullet() { final Bullet bullet = new Bullet(heading, x, y, power, owner == null ? null : owner.getName(), victim == null ? null : victim.getName(), isActive(), bulletId); return bullet; } private BulletStatus createStatus() { return new BulletStatus(bulletId, x, y, victim == null ? null : victim.getName(), isActive()); } // Workaround for http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6457965 private boolean intersect(Line2D.Double line) { double x1 = line.x1, x2 = line.x2, x3 = boundingLine.x1, x4 = boundingLine.x2; double y1 = line.y1, y2 = line.y2, y3 = boundingLine.y1, y4 = boundingLine.y2; double dx13 = (x1 - x3), dx21 = (x2 - x1), dx43 = (x4 - x3); double dy13 = (y1 - y3), dy21 = (y2 - y1), dy43 = (y4 - y3); double dn = dy43 * dx21 - dx43 * dy21; double ua = (dx43 * dy13 - dy43 * dx13) / dn; double ub = (dx21 * dy13 - dy21 * dx13) / dn; return (ua >= 0 && ua <= 1) && (ub >= 0 && ub <= 1); } private void checkRobotCollision(List robots) { RobotPeer robotPeer; for (int i = 0; i < robots.size(); i++) { robotPeer = robots.get(i); if (!(robotPeer == null || robotPeer == owner || robotPeer.isDead()) && robotPeer.getBoundingBox().intersectsLine(boundingLine)) { double damage = Rules.getBulletDamage(power); double score = damage; if (score > robotPeer.getEnergy()) { score = robotPeer.getEnergy(); } robotPeer.updateEnergy(-damage); boolean teamFire = (owner.getTeamPeer() != null && owner.getTeamPeer() == robotPeer.getTeamPeer()); if (!teamFire) { owner.getRobotStatistics().scoreBulletDamage(i, score); } if (robotPeer.getEnergy() <= 0) { if (robotPeer.isAlive()) { robotPeer.kill(); if (!teamFire) { final double bonus = owner.getRobotStatistics().scoreBulletKill(i); if (bonus > 0) { owner.println( "SYSTEM: Bonus for killing " + (robotPeer.getName() + ": " + (int) (bonus + .5))); } } } } owner.updateEnergy(Rules.getBulletHitBonus(power)); HitByBulletEvent event = new HitByBulletEvent( robocode.util.Utils.normalRelativeAngle(heading + Math.PI - robotPeer.getBodyHeading()), createBullet()); robotPeer.addEvent(event); state = BulletState.HIT_VICTIM; final BulletHitEvent bhe = new BulletHitEvent(robotPeer.getName(), robotPeer.getEnergy(), createBullet()); owner.addEvent(bhe); frame = 0; victim = robotPeer; double newX, newY; if (robotPeer.getBoundingBox().contains(lastX, lastY)) { newX = lastX; newY = lastY; setX(newX); setY(newY); } else { newX = x; newY = y; } deltaX = newX - robotPeer.getX(); deltaY = newY - robotPeer.getY(); break; } } } private void checkWallCollision() { if ((x - RADIUS <= 0) || (y - RADIUS <= 0) || (x + RADIUS >= battleRules.getBattlefieldWidth()) || (y + RADIUS >= battleRules.getBattlefieldHeight())) { state = BulletState.HIT_WALL; owner.addEvent(new BulletMissedEvent(createBullet())); } } public int getBulletId() { return bulletId; } public int getFrame() { return frame; } public double getHeading() { return heading; } public RobotPeer getOwner() { return owner; } public double getPower() { return power; } public double getVelocity() { return Rules.getBulletSpeed(power); } public RobotPeer getVictim() { return victim; } public double getX() { return x; } public double getY() { return y; } public double getPaintX() { return (state == BulletState.HIT_VICTIM && victim != null) ? victim.getX() + deltaX : x; } public double getPaintY() { return (state == BulletState.HIT_VICTIM && victim != null) ? victim.getY() + deltaY : y; } public boolean isActive() { return state.getValue() <= BulletState.MOVING.getValue(); } public BulletState getState() { return state; } public int getColor() { return color; } public void setHeading(double newHeading) { heading = newHeading; } public void setPower(double newPower) { power = newPower; } public void setVictim(RobotPeer newVictim) { victim = newVictim; } public void setX(double newX) { x = lastX = newX; } public void setY(double newY) { y = lastY = newY; } public void setState(BulletState newState) { state = newState; } public void update(List robots, List bullets) { if (isActive()) { updateMovement(); if (bullets != null) { checkBulletCollision(bullets); } if (isActive()) { checkRobotCollision(robots); } if (isActive()) { checkWallCollision(); } } else if (state == BulletState.HIT_VICTIM || state == BulletState.HIT_BULLET) { frame++; } updateBulletState(); owner.addBulletStatus(createStatus()); } protected void updateBulletState() { switch (state) { case FIRED: state = BulletState.MOVING; break; case HIT_BULLET: case HIT_VICTIM: case EXPLODED: if (frame >= getExplosionLength()) { state = BulletState.INACTIVE; } break; case HIT_WALL: state = BulletState.INACTIVE; break; } } private void updateMovement() { lastX = x; lastY = y; double v = getVelocity(); x += v * sin(heading); y += v * cos(heading); boundingLine.setLine(lastX, lastY, x, y); } public void nextFrame() { frame++; } public int getExplosionImageIndex() { return explosionImageIndex; } protected int getExplosionLength() { return EXPLOSION_LENGTH; } @Override public String toString() { return getOwner().getName() + " V" + getVelocity() + " *" + (int) power + " X" + (int) x + " Y" + (int) y + " H" + heading + " " + state.toString(); } } robocode/robocode/robocode/peer/TeamStatistics.java0000644000175000017500000001144311130241112021760 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Luis Crespo * - Added getCurrentScore() * Flemming N. Larsen * - Ported to Java 5 * - Renamed method names and removed unused methods * - Ordered all methods more naturally * - Added methods for getting current scores *******************************************************************************/ package robocode.peer; import robocode.BattleResults; /** * @author Mathew A. Nelson (original) * @author Luis Crespo (contributor) * @author Flemming N. Larsen (contributor) */ public class TeamStatistics implements ContestantStatistics { private final TeamPeer teamPeer; private int rank; public TeamStatistics(TeamPeer teamPeer) { this.teamPeer = teamPeer; } public void setRank(int rank) { this.rank = rank; } public double getTotalScore() { double d = 0; for (RobotPeer teammate : teamPeer) { d += teammate.getRobotStatistics().getTotalScore(); } return d; } public double getTotalSurvivalScore() { double d = 0; for (RobotPeer teammate : teamPeer) { d += teammate.getRobotStatistics().getTotalSurvivalScore(); } return d; } public double getTotalLastSurvivorBonus() { double d = 0; for (RobotPeer teammate : teamPeer) { d += teammate.getRobotStatistics().getTotalLastSurvivorBonus(); } return d; } public double getTotalBulletDamageScore() { double d = 0; for (RobotPeer teammate : teamPeer) { d += teammate.getRobotStatistics().getTotalBulletDamageScore(); } return d; } public double getTotalBulletKillBonus() { double d = 0; for (RobotPeer teammate : teamPeer) { d += teammate.getRobotStatistics().getTotalBulletKillBonus(); } return d; } public double getTotalRammingDamageScore() { double d = 0; for (RobotPeer teammate : teamPeer) { d += teammate.getRobotStatistics().getTotalRammingDamageScore(); } return d; } public double getTotalRammingKillBonus() { double d = 0; for (RobotPeer teammate : teamPeer) { d += teammate.getRobotStatistics().getTotalRammingKillBonus(); } return d; } public int getTotalFirsts() { int d = 0; for (RobotPeer teammate : teamPeer) { d += teammate.getRobotStatistics().getTotalFirsts(); } return d; } public int getTotalSeconds() { int d = 0; for (RobotPeer teammate : teamPeer) { d += teammate.getRobotStatistics().getTotalSeconds(); } return d; } public int getTotalThirds() { int d = 0; for (RobotPeer teammate : teamPeer) { d += teammate.getRobotStatistics().getTotalThirds(); } return d; } public double getCurrentScore() { double d = 0; for (RobotPeer teammate : teamPeer) { d += teammate.getRobotStatistics().getCurrentScore(); } return d; } public double getCurrentSurvivalScore() { double d = 0; for (RobotPeer teammate : teamPeer) { d += teammate.getRobotStatistics().getCurrentSurvivalScore(); } return d; } public double getCurrentSurvivalBonus() { double d = 0; for (RobotPeer teammate : teamPeer) { d += teammate.getRobotStatistics().getCurrentSurvivalBonus(); } return d; } public double getCurrentBulletDamageScore() { double d = 0; for (RobotPeer teammate : teamPeer) { d += teammate.getRobotStatistics().getCurrentBulletDamageScore(); } return d; } public double getCurrentBulletKillBonus() { double d = 0; for (RobotPeer teammate : teamPeer) { d += teammate.getRobotStatistics().getCurrentBulletKillBonus(); } return d; } public double getCurrentRammingDamageScore() { double d = 0; for (RobotPeer teammate : teamPeer) { d += teammate.getRobotStatistics().getCurrentRammingDamageScore(); } return d; } public double getCurrentRammingKillBonus() { double d = 0; for (RobotPeer teammate : teamPeer) { d += teammate.getRobotStatistics().getCurrentRammingKillBonus(); } return d; } public BattleResults getFinalResults() { return new BattleResults(teamPeer.getName(), rank, getTotalScore(), getTotalSurvivalScore(), getTotalLastSurvivorBonus(), getTotalBulletDamageScore(), getTotalBulletKillBonus(), getTotalRammingDamageScore(), getTotalRammingKillBonus(), getTotalFirsts(), getTotalSeconds(), getTotalThirds()); } } robocode/robocode/robocode/peer/BulletCommand.java0000644000175000017500000000262511130241112021547 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.peer; import java.io.Serializable; /** * @author Pavel Savara (original) */ public class BulletCommand implements Serializable { private static final long serialVersionUID = 1L; public BulletCommand(double power, boolean fireAssistValid, double fireAssistAngle, int bulletId) { this.fireAssistValid = fireAssistValid; this.fireAssistAngle = fireAssistAngle; this.bulletId = bulletId; this.power = power; } private final double power; private final boolean fireAssistValid; private final double fireAssistAngle; private final int bulletId; public boolean isFireAssistValid() { return fireAssistValid; } public int getBulletId() { return bulletId; } public double getPower() { return power; } public double getFireAssistAngle() { return fireAssistAngle; } } robocode/robocode/robocode/peer/ContestantStatistics.java0000644000175000017500000000344111130241112023213 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Luis Crespo * - Added getCurrentScore() * Flemming N. Larsen * - Renamed method names and removed unused methods * - Added methods for getting current scores *******************************************************************************/ package robocode.peer; import robocode.BattleResults; /** * @author Mathew A. Nelson (original) * @author Luis Crespo (contributor) * @author Flemming N. Larsen (contributor) */ public interface ContestantStatistics { public double getTotalScore(); public double getTotalSurvivalScore(); public double getTotalLastSurvivorBonus(); public double getTotalBulletDamageScore(); public double getTotalBulletKillBonus(); public double getTotalRammingDamageScore(); public double getTotalRammingKillBonus(); public int getTotalFirsts(); public int getTotalSeconds(); public int getTotalThirds(); public double getCurrentScore(); public double getCurrentSurvivalScore(); public double getCurrentSurvivalBonus(); public double getCurrentBulletDamageScore(); public double getCurrentBulletKillBonus(); public double getCurrentRammingDamageScore(); public double getCurrentRammingKillBonus(); public BattleResults getFinalResults(); public void setRank(int rank); } robocode/robocode/robocode/peer/BulletStatus.java0000644000175000017500000000220611130241112021447 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.peer; import java.io.Serializable; /** * @author Pavel Savara (original) */ public class BulletStatus implements Serializable { private static final long serialVersionUID = 1L; public BulletStatus(int bulletId, double x, double y, String victimName, boolean isActive) { this.bulletId = bulletId; this.x = x; this.y = y; this.isActive = isActive; this.victimName = victimName; } public final int bulletId; public final String victimName; public final boolean isActive; public final double x; public final double y; } robocode/robocode/robocode/peer/RobotPeer.java0000644000175000017500000013220411130241112020717 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Code cleanup * - Bugfix: updateMovement() checked for distanceRemaining > 1 instead of * distanceRemaining > 0 if slowingDown and moveDirection == -1 * - Bugfix: Substituted wait(10000) with wait() in execute() method, so * that robots do not hang when game is paused * - Bugfix: Teleportation when turning the robot to 0 degrees while forcing * the robot towards the bottom * - Added setPaintEnabled() and isPaintEnabled() * - Added setSGPaintEnabled() and isSGPaintEnabled() * - Replaced the colorIndex with bodyColor, gunColor, and radarColor * - Replaced the setColors() with setBodyColor(), setGunColor(), and * setRadarColor() * - Added bulletColor, scanColor, setBulletColor(), and setScanColor() and * removed getColorIndex() * - Optimizations * - Ported to Java 5 * - Bugfix: HitRobotEvent.isMyFault() returned false despite the fact that * the robot was moving toward the robot it collides with. This was the * case when distanceRemaining == 0 * - Removed isDead field as the robot state is used as replacement * - Added isAlive() method * - Added constructor for creating a new robot with a name only * - Added the set() that copies a RobotRecord into this robot in order to * support the replay feature * - Fixed synchronization issues with several member fields * - Added features to support the new JuniorRobot class * - Added cleanupStaticFields() for clearing static fields on robots * - Added getMaxTurnRate() * - Added turnAndMove() in order to support the turnAheadLeft(), * turnAheadRight(), turnBackLeft(), and turnBackRight() for the * JuniorRobot, which moves the robot in a perfect curve that follows a * circle * - Changed the behaviour of checkRobotCollision() so that HitRobotEvents * are only created and sent to robot when damage do occur. Previously, a * robot could receive HitRobotEvents even when no damage was done * - Renamed scanReset() to rescan() * - Added getStatusEvents() * - Added getGraphicsProxy(), getPaintEvents() * Luis Crespo * - Added states * Titus Chen * - Bugfix: Hit wall and teleporting problems with checkWallCollision() * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap * Nathaniel Troutman * - Added cleanup() method for cleaning up references to internal classes * to prevent circular references causing memory leaks * Pavel Savara * - Re-work of robot interfaces * - hosting related logic moved to robot proxy * - interlocked synchronization * - (almost) minimized surface between RobotPeer and RobotProxy to serializable messages. *******************************************************************************/ package robocode.peer; import robocode.*; import robocode.battle.Battle; import robocode.common.BoundingRectangle; import robocode.control.RandomFactory; import robocode.control.RobotSpecification; import robocode.control.snapshot.RobotState; import robocode.control.snapshot.BulletState; import robocode.exception.AbortedException; import robocode.exception.DeathException; import robocode.exception.WinException; import robocode.io.Logger; import static robocode.io.Logger.logMessage; import robocode.manager.IHostManager; import robocode.peer.proxies.*; import robocode.peer.robot.*; import robocode.repository.RobotFileSpecification; import robocode.robotpaint.Graphics2DProxy; import static robocode.util.Utils.*; import java.awt.geom.Arc2D; import java.awt.geom.Rectangle2D; import static java.lang.Math.*; import java.security.AccessControlException; import java.util.ArrayList; import java.util.List; import java.util.Random; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; /** * RobotPeer is an object that deals with game mechanics and rules, and makes * sure that robots abides the rules. * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Luis Crespo (contributor) * @author Titus Chen (contributor) * @author Robert D. Maupin (contributor) * @author Nathaniel Troutman (contributor) * @author Pavel Savara (contributor) */ public final class RobotPeer implements IRobotPeerBattle, IRobotPeer { public static final int WIDTH = 40, HEIGHT = 40; private static final int HALF_WIDTH_OFFSET = (WIDTH / 2 - 2), HALF_HEIGHT_OFFSET = (HEIGHT / 2 - 2); private static final int maxSkippedTurns = 30; private static final int maxSkippedTurnsWithIO = 240; private Battle battle; private RobotStatistics statistics; private final TeamPeer teamPeer; private final RobotSpecification controlRobotSpecification; private final RobotFileSpecification robotSpecification; private IHostingRobotProxy robotProxy; private AtomicReference status = new AtomicReference(); private AtomicReference commands = new AtomicReference(); private AtomicReference events = new AtomicReference(new EventQueue()); private AtomicReference> teamMessages = new AtomicReference>( new ArrayList()); private AtomicReference> bulletUpdates = new AtomicReference>( new ArrayList()); private final StringBuilder battleText = new StringBuilder(1024); private final StringBuilder proxyText = new StringBuilder(1024); private RobotStatics statics; private BattleRules battleRules; // for battle thread, during robots processing private ExecCommands currentCommands; private double lastHeading; private double lastGunHeading; private double lastRadarHeading; private double energy; private double velocity; private double bodyHeading; private double radarHeading; private double gunHeading; private double gunHeat; private double x; private double y; private int skippedTurns; private boolean slowingDown; private int moveDirection; private double acceleration; private boolean scan; private boolean turnedRadarWithGun; // last round private boolean isIORobot; private boolean isPaintRecorded; private boolean isPaintEnabled; private boolean sgPaintEnabled; // waiting for next tick private final AtomicBoolean isSleeping = new AtomicBoolean(false); private final AtomicBoolean halt = new AtomicBoolean(false); private boolean disableExec = false; private boolean isWinner; private boolean inCollision; private RobotState state; private final Arc2D scanArc; private final BoundingRectangle boundingBox; public RobotPeer(Battle battle, IHostManager hostManager, RobotClassManager robotClassManager, int duplicate, TeamPeer team, int index, int contestantIndex) { super(); if (team != null) { team.add(this); } robotSpecification = robotClassManager.getRobotSpecification(); this.battle = battle; boundingBox = new BoundingRectangle(); scanArc = new Arc2D.Double(); teamPeer = team; state = RobotState.ACTIVE; boolean isLeader = teamPeer != null && teamPeer.size() == 1; statistics = new RobotStatistics(this, battle.getRobotsCount()); statics = new RobotStatics(robotSpecification, duplicate, isLeader, battle.getBattleRules(), team, index, contestantIndex); battleRules = battle.getBattleRules(); controlRobotSpecification = robotClassManager.getControlRobotSpecification(); if (robotSpecification.isTeamRobot()) { robotProxy = new TeamRobotProxy(robotClassManager, hostManager, this, statics); } else if (robotSpecification.isAdvancedRobot()) { robotProxy = new AdvancedRobotProxy(robotClassManager, hostManager, this, statics); } else if (robotSpecification.isStandardRobot()) { robotProxy = new StandardRobotProxy(robotClassManager, hostManager, this, statics); } else if (robotSpecification.isJuniorRobot()) { robotProxy = new JuniorRobotProxy(robotClassManager, hostManager, this, statics); } else { throw new AccessControlException("Unknown robot type"); } } public void println(String s) { synchronized (proxyText) { battleText.append(s); battleText.append("\n"); } } public void print(Throwable ex) { println(ex.toString()); StackTraceElement[] trace = ex.getStackTrace(); for (StackTraceElement aTrace : trace) { println("\tat " + aTrace); } Throwable ourCause = ex.getCause(); if (ourCause != null) { print(ourCause); } } public void printProxy(String s) { synchronized (proxyText) { proxyText.append(s); } } public String readOutText() { synchronized (proxyText) { final String robotText = battleText.toString() + proxyText.toString(); battleText.setLength(0); proxyText.setLength(0); return robotText; } } public RobotStatistics getRobotStatistics() { return statistics; } public ContestantStatistics getStatistics() { return statistics; } public RobotSpecification getControlRobotSpecification() { return controlRobotSpecification; } // ------------------- // statics // ------------------- public boolean isDroid() { return statics.isDroid(); } public boolean isJuniorRobot() { return statics.isJuniorRobot(); } public boolean isInteractiveRobot() { return statics.isInteractiveRobot(); } public boolean isPaintRobot() { return statics.isPaintRobot(); } public boolean isAdvancedRobot() { return statics.isAdvancedRobot(); } public boolean isTeamRobot() { return statics.isTeamRobot(); } public String getName() { return statics.getName(); } public String getShortName() { return statics.getShortName(); } public String getVeryShortName() { return statics.getVeryShortName(); } public int getIndex() { return statics.getIndex(); } public int getContestIndex() { return statics.getContestIndex(); } // ------------------- // status // ------------------- public void setPaintEnabled(boolean enabled) { isPaintEnabled = enabled; } public void setPaintRecorded(boolean enabled) { isPaintRecorded = enabled; } public boolean isPaintRecorded() { return isPaintRecorded; } public boolean isPaintEnabled() { return isPaintEnabled; } public void setSGPaintEnabled(boolean enabled) { sgPaintEnabled = enabled; } public boolean isSGPaintEnabled() { return sgPaintEnabled; } public RobotState getState() { return state; } public void setState(RobotState state) { this.state = state; } public boolean isDead() { return state == RobotState.DEAD; } public boolean isAlive() { return state != RobotState.DEAD; } public boolean isWinner() { return isWinner; } public boolean isRunning() { return robotProxy.isRunning(); } public boolean isSleeping() { return isSleeping.get(); } public boolean getHalt() { return halt.get(); } public void setHalt(boolean value) { halt.set(value); } public BoundingRectangle getBoundingBox() { return boundingBox; } public Arc2D getScanArc() { return scanArc; } // ------------------- // robot space // ------------------- public double getGunHeading() { return gunHeading; } public double getBodyHeading() { return bodyHeading; } public double getRadarHeading() { return radarHeading; } public double getVelocity() { return velocity; } public double getX() { return x; } public double getY() { return y; } public double getEnergy() { return energy; } public double getGunHeat() { return gunHeat; } public int getBodyColor() { return commands.get().getBodyColor(); } public int getRadarColor() { return commands.get().getRadarColor(); } public int getGunColor() { return commands.get().getGunColor(); } public int getBulletColor() { return commands.get().getBulletColor(); } public int getScanColor() { return commands.get().getScanColor(); } // ------------ // team // ------------ public TeamPeer getTeamPeer() { return teamPeer; } public String getTeamName() { return statics.getTeamName(); } public boolean isTeamLeader() { return statics.isTeamLeader(); } // ----------- // execute // ----------- // TODO this is there just to prove that now is possible play over the wire // public final ExecResults executeImpl(ExecCommands newCommands) { // return (ExecResults) ObjectCloner.deepCopy(executeImplIn((ExecCommands) ObjectCloner.deepCopy(newCommands))); // } public final ExecResults executeImpl(ExecCommands newCommands) { newCommands.validate(this); if (!disableExec) { // from robot to battle commands.set(new ExecCommands(newCommands, true)); printProxy(newCommands.getOutputText()); } else { // slow down spammer try { Thread.sleep(100); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } // If we are stopping, yet the robot took action (in onWin or onDeath), stop now. if (battle.isAborted()) { disableExec = true; throw new AbortedException(); } if (isDead()) { disableExec = true; throw new DeathException(); } if (getHalt()) { disableExec = true; if (isWinner) { throw new WinException(); } else { throw new AbortedException(); } } waitForNextRound(); // from battle to robot final ExecCommands resCommands = new ExecCommands(this.commands.get(), false); final RobotStatus resStatus = status.get(); final boolean shouldWait = battle.isAborted() || (battle.isLastRound() && isWinner()); return new ExecResults(resCommands, resStatus, readoutEvents(), readoutTeamMessages(), readoutBullets(), getHalt(), shouldWait, isPaintEnabled() || isPaintRecorded); } public final ExecResults waitForBattleEndImpl(ExecCommands newCommands) { if (!getHalt()) { // from robot to battle commands.set(new ExecCommands(newCommands, true)); printProxy(newCommands.getOutputText()); waitForNextRound(); } // from battle to robot final ExecCommands resCommands = new ExecCommands(this.commands.get(), false); final RobotStatus resStatus = status.get(); final boolean shouldWait = battle.isAborted() || (battle.isLastRound() && !isWinner()); readoutTeamMessages(); // throw away return new ExecResults(resCommands, resStatus, readoutEvents(), new ArrayList(), readoutBullets(), getHalt(), shouldWait, false); } private List readoutEvents() { return events.getAndSet(new EventQueue()); } private List readoutTeamMessages() { return teamMessages.getAndSet(new ArrayList()); } private List readoutBullets() { return bulletUpdates.getAndSet(new ArrayList()); } private void waitForNextRound() { synchronized (isSleeping) { // Notify the battle that we are now asleep. // This ends any pending wait() call in battle.runRound(). // Should not actually take place until we release the lock in wait(), below. isSleeping.set(true); isSleeping.notifyAll(); // Notifying battle that we're asleep // Sleeping and waiting for battle to wake us up. try { isSleeping.wait(); } catch (InterruptedException e) { // We are expecting this to happen when a round is ended! // Immediately reasserts the exception by interrupting the caller thread itself Thread.currentThread().interrupt(); } isSleeping.set(false); // Notify battle thread, which is waiting in // our wakeup() call, to return. // It's quite possible, by the way, that we'll be back in sleep (above) // before the battle thread actually wakes up isSleeping.notifyAll(); } } // ----------- // called on battle thread // ----------- public void waitWakeup() { synchronized (isSleeping) { if (isSleeping()) { // Wake up the thread isSleeping.notifyAll(); try { isSleeping.wait(10000); } catch (InterruptedException e) { // Immediately reasserts the exception by interrupting the caller thread itself Thread.currentThread().interrupt(); } } } } public void waitWakeupNoWait() { synchronized (isSleeping) { if (isSleeping()) { // Wake up the thread isSleeping.notifyAll(); } } } public void waitSleeping(int millisWait, int microWait) { synchronized (isSleeping) { // It's quite possible for simple robots to // complete their processing before we get here, // so we test if the robot is already asleep. if (!isSleeping()) { try { for (int i = millisWait; i > 0 && !isSleeping() && isRunning(); i--) { isSleeping.wait(0, 999999); } if (!isSleeping()) { isSleeping.wait(0, microWait); } } catch (InterruptedException e) { // Immediately reasserts the exception by interrupting the caller thread itself Thread.currentThread().interrupt(); logMessage("Wait for " + getName() + " interrupted."); } } } } public void setSkippedTurns() { if (battle.isDebugging() || isPaintEnabled()) { skippedTurns = 0; } else { println("SYSTEM: you skipped turn"); skippedTurns++; events.get().clear(false); if (!isDead()) { addEvent(new SkippedTurnEvent()); } if ((!isIORobot && (skippedTurns > maxSkippedTurns)) || (isIORobot && (skippedTurns > maxSkippedTurnsWithIO))) { println("SYSTEM: " + getName() + " has not performed any actions in a reasonable amount of time."); println("SYSTEM: No score will be generated."); setHalt(true); waitWakeupNoWait(); punishBadBehavior(); robotProxy.forceStopThread(); } } } public void initializeRound(List robots, double[][] initialRobotPositions) { boolean valid = false; if (initialRobotPositions != null) { if (statics.getIndex() >= 0 && statics.getIndex() < initialRobotPositions.length) { double[] pos = initialRobotPositions[statics.getIndex()]; x = pos[0]; y = pos[1]; bodyHeading = pos[2]; gunHeading = radarHeading = bodyHeading; updateBoundingBox(); valid = validSpot(robots); } } if (!valid) { final Random random = RandomFactory.getRandom(); for (int j = 0; j < 1000; j++) { x = RobotPeer.WIDTH + random.nextDouble() * (battleRules.getBattlefieldWidth() - 2 * RobotPeer.WIDTH); y = RobotPeer.HEIGHT + random.nextDouble() * (battleRules.getBattlefieldHeight() - 2 * RobotPeer.HEIGHT); bodyHeading = 2 * Math.PI * random.nextDouble(); gunHeading = radarHeading = bodyHeading; updateBoundingBox(); if (validSpot(robots)) { break; } } } setState(RobotState.ACTIVE); isWinner = false; acceleration = velocity = 0; if (statics.isTeamLeader() && statics.isDroid()) { energy = 220; } else if (statics.isTeamLeader()) { energy = 200; } else if (statics.isDroid()) { energy = 120; } else { energy = 100; } gunHeat = 3; setHalt(false); disableExec = false; scan = false; inCollision = false; scanArc.setAngleStart(0); scanArc.setAngleExtent(0); scanArc.setFrame(-100, -100, 1, 1); skippedTurns = 0; status = new AtomicReference(); commands = new AtomicReference(new ExecCommands()); readoutEvents(); readoutTeamMessages(); readoutBullets(); battleText.setLength(0); proxyText.setLength(0); } private boolean validSpot(List robots) { for (RobotPeer otherRobot : robots) { if (otherRobot != null && otherRobot != this) { if (getBoundingBox().intersects(otherRobot.getBoundingBox())) { return false; } } } return true; } public void startRound(long waitTime) { synchronized (isSleeping) { try { Logger.logMessage(".", false); currentCommands = new ExecCommands(); RobotStatus stat = new RobotStatus(this, currentCommands, battle); status.set(stat); robotProxy.startRound(currentCommands, stat); if (!battle.isDebugging()) { // Wait for the robot to go to sleep (take action) isSleeping.wait(waitTime / 1000000, (int) (waitTime % 1000000)); } } catch (InterruptedException e) { logMessage("Wait for " + getName() + " interrupted."); // Immediately reasserts the exception by interrupting the caller thread itself Thread.currentThread().interrupt(); } } if (!(isSleeping() || battle.isDebugging())) { logMessage("\n" + getName() + " still has not started after " + (waitTime / 100000) + " ms... giving up."); } } public void performLoadCommands() { currentCommands = commands.get(); fireBullets(currentCommands.getBullets()); if (currentCommands.isScan()) { scan = true; } if (currentCommands.isIORobot()) { isIORobot = true; } if (currentCommands.isMoved()) { acceleration = 0; if (currentCommands.getDistanceRemaining() == 0) { moveDirection = 0; } else if (currentCommands.getDistanceRemaining() > 0) { moveDirection = 1; } else { moveDirection = -1; } slowingDown = false; currentCommands.setMoved(false); } } private void fireBullets(List bulletCommands) { BulletPeer newBullet = null; for (BulletCommand bulletCmd : bulletCommands) { if (Double.isNaN(bulletCmd.getPower())) { println("SYSTEM: You cannot call fire(NaN)"); continue; } if (gunHeat > 0 || energy == 0) { return; } double firePower = min(energy, min(max(bulletCmd.getPower(), Rules.MIN_BULLET_POWER), Rules.MAX_BULLET_POWER)); updateEnergy(-firePower); gunHeat += Rules.getGunHeat(firePower); newBullet = new BulletPeer(this, battle, bulletCmd.getBulletId()); newBullet.setPower(firePower); if (!turnedRadarWithGun || !bulletCmd.isFireAssistValid() || statics.isAdvancedRobot()) { newBullet.setHeading(gunHeading); } else { newBullet.setHeading(bulletCmd.getFireAssistAngle()); } newBullet.setX(x); newBullet.setY(y); } // there is only last bullet in one turn if (newBullet != null) { // newBullet.update(robots, bullets); battle.addBullet(newBullet); } } public final void performMove(List robots, double zapEnergy) { // Reset robot state to active if it is not dead if (isDead()) { return; } setState(RobotState.ACTIVE); updateGunHeat(); lastHeading = bodyHeading; lastGunHeading = gunHeading; lastRadarHeading = radarHeading; final double lastX = x; final double lastY = y; if (!inCollision) { updateHeading(); } updateGunHeading(); updateRadarHeading(); updateMovement(); // At this point, robot has turned then moved. // We could be touching a wall or another bot... // First and foremost, we can never go through a wall: checkWallCollision(); // Now check for robot collision checkRobotCollision(robots); // Scan false means robot did not call scan() manually. // But if we're moving, scan if (!scan) { scan = (lastHeading != bodyHeading || lastGunHeading != gunHeading || lastRadarHeading != radarHeading || lastX != x || lastY != y); } if (isDead()) { return; } // zap if (zapEnergy != 0) { zap(zapEnergy); } } public void performScan(List robots) { if (isDead()) { return; } turnedRadarWithGun = false; // scan if (scan) { scan(lastRadarHeading, robots); turnedRadarWithGun = (lastGunHeading == lastRadarHeading) && (gunHeading == radarHeading); scan = false; } // dispatch messages if (statics.isTeamRobot() && teamPeer != null) { for (TeamMessage teamMessage : currentCommands.getTeamMessages()) { for (RobotPeer member : teamPeer) { if (checkDispatchToMember(member, teamMessage.recipient)) { member.addTeamMessage(teamMessage); } } } } currentCommands = null; lastHeading = -1; lastGunHeading = -1; lastRadarHeading = -1; } private void addTeamMessage(TeamMessage message) { final List queue = teamMessages.get(); queue.add(message); } private boolean checkDispatchToMember(RobotPeer member, String recipient) { if (member.isAlive()) { if (recipient == null) { if (member != this) { return true; } } else { final int nl = recipient.length(); final String currentName = member.getName(); final String currentNonVerName = member.statics.getNonVersionedName(); if ((currentName.length() >= nl && currentName.substring(0, nl).equals(recipient)) || (currentNonVerName.length() >= nl && member.statics.getNonVersionedName().substring(0, nl).equals(recipient))) { return true; } } } return false; } private void checkRobotCollision(List robots) { inCollision = false; for (int i = 0; i < robots.size(); i++) { RobotPeer otherRobot = robots.get(i); if (!(otherRobot == null || otherRobot == this || otherRobot.isDead()) && boundingBox.intersects(otherRobot.boundingBox)) { // Bounce back double angle = atan2(otherRobot.x - x, otherRobot.y - y); double movedx = velocity * sin(bodyHeading); double movedy = velocity * cos(bodyHeading); boolean atFault; double bearing = normalRelativeAngle(angle - bodyHeading); if ((velocity > 0 && bearing > -PI / 2 && bearing < PI / 2) || (velocity < 0 && (bearing < -PI / 2 || bearing > PI / 2))) { inCollision = true; atFault = true; velocity = 0; currentCommands.setDistanceRemaining(0); x -= movedx; y -= movedy; boolean teamFire = (teamPeer != null && teamPeer == otherRobot.teamPeer); if (!teamFire) { statistics.scoreRammingDamage(i); } this.updateEnergy(-Rules.ROBOT_HIT_DAMAGE); otherRobot.updateEnergy(-Rules.ROBOT_HIT_DAMAGE); if (otherRobot.energy == 0) { if (otherRobot.isAlive()) { otherRobot.kill(); if (!teamFire) { final double bonus = statistics.scoreRammingKill(i); if (bonus > 0) { println( "SYSTEM: Ram bonus for killing " + otherRobot.getName() + ": " + (int) (bonus + .5)); } } } } addEvent( new HitRobotEvent(otherRobot.getName(), normalRelativeAngle(angle - bodyHeading), otherRobot.energy, atFault)); otherRobot.addEvent( new HitRobotEvent(getName(), normalRelativeAngle(PI + angle - otherRobot.getBodyHeading()), energy, false)); } } } if (inCollision) { setState(RobotState.HIT_ROBOT); } } private void checkWallCollision() { boolean hitWall = false; double fixx = 0, fixy = 0; double angle = 0; if (x > getBattleFieldWidth() - HALF_WIDTH_OFFSET) { hitWall = true; fixx = getBattleFieldWidth() - HALF_WIDTH_OFFSET - x; angle = normalRelativeAngle(PI / 2 - bodyHeading); } if (x < HALF_WIDTH_OFFSET) { hitWall = true; fixx = HALF_WIDTH_OFFSET - x; angle = normalRelativeAngle(3 * PI / 2 - bodyHeading); } if (y > getBattleFieldHeight() - HALF_HEIGHT_OFFSET) { hitWall = true; fixy = getBattleFieldHeight() - HALF_HEIGHT_OFFSET - y; angle = normalRelativeAngle(-bodyHeading); } if (y < HALF_HEIGHT_OFFSET) { hitWall = true; fixy = HALF_HEIGHT_OFFSET - y; angle = normalRelativeAngle(PI - bodyHeading); } if (hitWall) { addEvent(new HitWallEvent(angle)); // only fix both x and y values if hitting wall at an angle if ((bodyHeading % (Math.PI / 2)) != 0) { double tanHeading = tan(bodyHeading); // if it hits bottom or top wall if (fixx == 0) { fixx = fixy * tanHeading; } // if it hits a side wall else if (fixy == 0) { fixy = fixx / tanHeading; } // if the robot hits 2 walls at the same time (rare, but just in case) else if (abs(fixx / tanHeading) > abs(fixy)) { fixy = fixx / tanHeading; } else if (abs(fixy * tanHeading) > abs(fixx)) { fixx = fixy * tanHeading; } } x += fixx; y += fixy; x = (HALF_WIDTH_OFFSET >= x) ? HALF_WIDTH_OFFSET : ((getBattleFieldWidth() - HALF_WIDTH_OFFSET < x) ? getBattleFieldWidth() - HALF_WIDTH_OFFSET : x); y = (HALF_HEIGHT_OFFSET >= y) ? HALF_HEIGHT_OFFSET : ((getBattleFieldHeight() - HALF_HEIGHT_OFFSET < y) ? getBattleFieldHeight() - HALF_HEIGHT_OFFSET : y); // Update energy, but do not reset inactiveTurnCount if (statics.isAdvancedRobot()) { setEnergy(energy - Rules.getWallHitDamage(velocity), false); } updateBoundingBox(); currentCommands.setDistanceRemaining(0); velocity = 0; acceleration = 0; } if (hitWall) { setState(RobotState.HIT_WALL); } } private double getBattleFieldHeight() { return battleRules.getBattlefieldHeight(); } private double getBattleFieldWidth() { return battleRules.getBattlefieldWidth(); } public void updateBoundingBox() { boundingBox.setRect(x - WIDTH / 2 + 2, y - HEIGHT / 2 + 2, WIDTH - 4, HEIGHT - 4); } public void addEvent(Event event) { if (isRunning()) { final EventQueue queue = events.get(); if ((queue.size() > EventManager.MAX_QUEUE_SIZE) && !(event instanceof DeathEvent || event instanceof WinEvent || event instanceof SkippedTurnEvent)) { println( "Not adding to " + statics.getName() + "'s queue, exceeded " + EventManager.MAX_QUEUE_SIZE + " events in queue."); // clean up old stuff queue.clear(battle.getTime() - EventManager.MAX_EVENT_STACK); return; } RobotClassManager.setTime(event, battle.getTime()); queue.add(event); } } private void updateGunHeading() { if (currentCommands.getGunTurnRemaining() > 0) { if (currentCommands.getGunTurnRemaining() < Rules.GUN_TURN_RATE_RADIANS) { gunHeading += currentCommands.getGunTurnRemaining(); radarHeading += currentCommands.getGunTurnRemaining(); if (currentCommands.isAdjustRadarForGunTurn()) { currentCommands.setRadarTurnRemaining( currentCommands.getRadarTurnRemaining() - currentCommands.getGunTurnRemaining()); } currentCommands.setGunTurnRemaining(0); } else { gunHeading += Rules.GUN_TURN_RATE_RADIANS; radarHeading += Rules.GUN_TURN_RATE_RADIANS; currentCommands.setGunTurnRemaining(currentCommands.getGunTurnRemaining() - Rules.GUN_TURN_RATE_RADIANS); if (currentCommands.isAdjustRadarForGunTurn()) { currentCommands.setRadarTurnRemaining( currentCommands.getRadarTurnRemaining() - Rules.GUN_TURN_RATE_RADIANS); } } } else if (currentCommands.getGunTurnRemaining() < 0) { if (currentCommands.getGunTurnRemaining() > -Rules.GUN_TURN_RATE_RADIANS) { gunHeading += currentCommands.getGunTurnRemaining(); radarHeading += currentCommands.getGunTurnRemaining(); if (currentCommands.isAdjustRadarForGunTurn()) { currentCommands.setRadarTurnRemaining( currentCommands.getRadarTurnRemaining() - currentCommands.getGunTurnRemaining()); } currentCommands.setGunTurnRemaining(0); } else { gunHeading -= Rules.GUN_TURN_RATE_RADIANS; radarHeading -= Rules.GUN_TURN_RATE_RADIANS; currentCommands.setGunTurnRemaining(currentCommands.getGunTurnRemaining() + Rules.GUN_TURN_RATE_RADIANS); if (currentCommands.isAdjustRadarForGunTurn()) { currentCommands.setRadarTurnRemaining( currentCommands.getRadarTurnRemaining() + Rules.GUN_TURN_RATE_RADIANS); } } } gunHeading = normalAbsoluteAngle(gunHeading); } private void updateHeading() { boolean normalizeHeading = true; double turnRate = min(currentCommands.getMaxTurnRate(), (.4 + .6 * (1 - (abs(velocity) / Rules.MAX_VELOCITY))) * Rules.MAX_TURN_RATE_RADIANS); if (currentCommands.getBodyTurnRemaining() > 0) { if (currentCommands.getBodyTurnRemaining() < turnRate) { bodyHeading += currentCommands.getBodyTurnRemaining(); gunHeading += currentCommands.getBodyTurnRemaining(); radarHeading += currentCommands.getBodyTurnRemaining(); if (currentCommands.isAdjustGunForBodyTurn()) { currentCommands.setGunTurnRemaining( currentCommands.getGunTurnRemaining() - currentCommands.getBodyTurnRemaining()); } if (currentCommands.isAdjustRadarForBodyTurn()) { currentCommands.setRadarTurnRemaining( currentCommands.getRadarTurnRemaining() - currentCommands.getBodyTurnRemaining()); } currentCommands.setBodyTurnRemaining(0); } else { bodyHeading += turnRate; gunHeading += turnRate; radarHeading += turnRate; currentCommands.setBodyTurnRemaining(currentCommands.getBodyTurnRemaining() - turnRate); if (currentCommands.isAdjustGunForBodyTurn()) { currentCommands.setGunTurnRemaining(currentCommands.getGunTurnRemaining() - turnRate); } if (currentCommands.isAdjustRadarForBodyTurn()) { currentCommands.setRadarTurnRemaining(currentCommands.getRadarTurnRemaining() - turnRate); } } } else if (currentCommands.getBodyTurnRemaining() < 0) { if (currentCommands.getBodyTurnRemaining() > -turnRate) { bodyHeading += currentCommands.getBodyTurnRemaining(); gunHeading += currentCommands.getBodyTurnRemaining(); radarHeading += currentCommands.getBodyTurnRemaining(); if (currentCommands.isAdjustGunForBodyTurn()) { currentCommands.setGunTurnRemaining( currentCommands.getGunTurnRemaining() - currentCommands.getBodyTurnRemaining()); } if (currentCommands.isAdjustRadarForBodyTurn()) { currentCommands.setRadarTurnRemaining( currentCommands.getRadarTurnRemaining() - currentCommands.getBodyTurnRemaining()); } currentCommands.setBodyTurnRemaining(0); } else { bodyHeading -= turnRate; gunHeading -= turnRate; radarHeading -= turnRate; currentCommands.setBodyTurnRemaining(currentCommands.getBodyTurnRemaining() + turnRate); if (currentCommands.isAdjustGunForBodyTurn()) { currentCommands.setGunTurnRemaining(currentCommands.getGunTurnRemaining() + turnRate); } if (currentCommands.isAdjustRadarForBodyTurn()) { currentCommands.setRadarTurnRemaining(currentCommands.getRadarTurnRemaining() + turnRate); } } } else { normalizeHeading = false; } if (normalizeHeading) { if (currentCommands.getBodyTurnRemaining() == 0) { bodyHeading = normalNearAbsoluteAngle(bodyHeading); } else { bodyHeading = normalAbsoluteAngle(bodyHeading); } } if (Double.isNaN(bodyHeading)) { System.out.println("HOW IS HEADING NAN HERE"); } } private void updateRadarHeading() { if (currentCommands.getRadarTurnRemaining() > 0) { if (currentCommands.getRadarTurnRemaining() < Rules.RADAR_TURN_RATE_RADIANS) { radarHeading += currentCommands.getRadarTurnRemaining(); currentCommands.setRadarTurnRemaining(0); } else { radarHeading += Rules.RADAR_TURN_RATE_RADIANS; currentCommands.setRadarTurnRemaining( currentCommands.getRadarTurnRemaining() - Rules.RADAR_TURN_RATE_RADIANS); } } else if (currentCommands.getRadarTurnRemaining() < 0) { if (currentCommands.getRadarTurnRemaining() > -Rules.RADAR_TURN_RATE_RADIANS) { radarHeading += currentCommands.getRadarTurnRemaining(); currentCommands.setRadarTurnRemaining(0); } else { radarHeading -= Rules.RADAR_TURN_RATE_RADIANS; currentCommands.setRadarTurnRemaining( currentCommands.getRadarTurnRemaining() + Rules.RADAR_TURN_RATE_RADIANS); } } radarHeading = normalAbsoluteAngle(radarHeading); } private void updateMovement() { if (currentCommands.getDistanceRemaining() == 0 && velocity == 0) { return; } if (!slowingDown) { // Set moveDir and slow down for move(0) if (moveDirection == 0) { // On move(0), we're always slowing down. slowingDown = true; // Pretend we were moving in the direction we're heading, if (velocity > 0) { moveDirection = 1; } else if (velocity < 0) { moveDirection = -1; } else { moveDirection = 0; } } } double desiredDistanceRemaining = currentCommands.getDistanceRemaining(); if (slowingDown) { if (moveDirection == 1 && currentCommands.getDistanceRemaining() < 0) { desiredDistanceRemaining = 0; } else if (moveDirection == -1 && currentCommands.getDistanceRemaining() > 0) { desiredDistanceRemaining = 0; } } double slowDownVelocity = (int) ((sqrt(4 * abs(desiredDistanceRemaining) + 1) - 1)); if (moveDirection == -1) { slowDownVelocity = -slowDownVelocity; } if (!slowingDown) { // Calculate acceleration if (moveDirection == 1) { // Brake or accelerate if (velocity < 0) { acceleration = Rules.DECELERATION; } else { acceleration = Rules.ACCELERATION; } if (velocity + acceleration > slowDownVelocity) { slowingDown = true; } } else if (moveDirection == -1) { if (velocity > 0) { acceleration = -Rules.DECELERATION; } else { acceleration = -Rules.ACCELERATION; } if (velocity + acceleration < slowDownVelocity) { slowingDown = true; } } } if (slowingDown) { // note: if slowing down, velocity and distanceremaining have same sign if (currentCommands.getDistanceRemaining() != 0 && abs(velocity) <= Rules.DECELERATION && abs(currentCommands.getDistanceRemaining()) <= Rules.DECELERATION) { slowDownVelocity = currentCommands.getDistanceRemaining(); } double perfectAccel = slowDownVelocity - velocity; if (perfectAccel > Rules.DECELERATION) { perfectAccel = Rules.DECELERATION; } else if (perfectAccel < -Rules.DECELERATION) { perfectAccel = -Rules.DECELERATION; } acceleration = perfectAccel; } // Calculate velocity if (velocity > currentCommands.getMaxVelocity() || velocity < -currentCommands.getMaxVelocity()) { acceleration = 0; } velocity += acceleration; if (velocity > currentCommands.getMaxVelocity()) { velocity -= min(Rules.DECELERATION, velocity - currentCommands.getMaxVelocity()); } if (velocity < -currentCommands.getMaxVelocity()) { velocity += min(Rules.DECELERATION, -velocity - currentCommands.getMaxVelocity()); } double dx = velocity * sin(bodyHeading); double dy = velocity * cos(bodyHeading); x += dx; y += dy; boolean updateBounds = false; if (dx != 0 || dy != 0) { updateBounds = true; } if (slowingDown && velocity == 0) { currentCommands.setDistanceRemaining(0); moveDirection = 0; slowingDown = false; acceleration = 0; } if (updateBounds) { updateBoundingBox(); } currentCommands.setDistanceRemaining(currentCommands.getDistanceRemaining() - velocity); } private void updateGunHeat() { gunHeat -= battleRules.getGunCoolingRate(); if (gunHeat < 0) { gunHeat = 0; } } private void scan(double lastRadarHeading, List robots) { if (statics.isDroid()) { return; } double startAngle = lastRadarHeading; double scanRadians = getRadarHeading() - startAngle; // Check if we passed through 360 if (scanRadians < -PI) { scanRadians = 2 * PI + scanRadians; } else if (scanRadians > PI) { scanRadians = scanRadians - 2 * PI; } // In our coords, we are scanning clockwise, with +y up // In java coords, we are scanning counterclockwise, with +y down // All we need to do is adjust our angle by -90 for this to work. startAngle -= PI / 2; startAngle = normalAbsoluteAngle(startAngle); scanArc.setArc(x - Rules.RADAR_SCAN_RADIUS, y - Rules.RADAR_SCAN_RADIUS, 2 * Rules.RADAR_SCAN_RADIUS, 2 * Rules.RADAR_SCAN_RADIUS, 180.0 * startAngle / PI, 180.0 * scanRadians / PI, Arc2D.PIE); for (RobotPeer otherRobot : robots) { if (!(otherRobot == null || otherRobot == this || otherRobot.isDead()) && intersects(scanArc, otherRobot.boundingBox)) { double dx = otherRobot.x - x; double dy = otherRobot.y - y; double angle = atan2(dx, dy); double dist = Math.hypot(dx, dy); final ScannedRobotEvent event = new ScannedRobotEvent(otherRobot.getName(), otherRobot.energy, normalRelativeAngle(angle - getBodyHeading()), dist, otherRobot.getBodyHeading(), otherRobot.getVelocity()); addEvent(event); } } } private boolean intersects(Arc2D arc, Rectangle2D rect) { return (rect.intersectsLine(arc.getCenterX(), arc.getCenterY(), arc.getStartPoint().getX(), arc.getStartPoint().getY())) || arc.intersects(rect); } private void zap(double zapAmount) { if (energy == 0) { kill(); return; } energy -= abs(zapAmount); if (energy < .1) { energy = 0; currentCommands.setDistanceRemaining(0); currentCommands.setBodyTurnRemaining(0); } } public void drainEnergy() { setEnergy(0, true); } public void punishBadBehavior() { setState(RobotState.DEAD); statistics.setInactive(); // disable for next time robotSpecification.setValid(false); } public void updateEnergy(double delta) { setEnergy(energy + delta, true); } private void setEnergy(double newEnergy, boolean resetInactiveTurnCount) { if (resetInactiveTurnCount && (energy != newEnergy)) { battle.resetInactiveTurnCount(energy - newEnergy); } energy = newEnergy; if (energy < .01) { energy = 0; ExecCommands localCommands = commands.get(); localCommands.setDistanceRemaining(0); localCommands.setBodyTurnRemaining(0); } } public void setWinner(boolean newWinner) { isWinner = newWinner; } public void kill() { battle.resetInactiveTurnCount(10.0); if (isAlive()) { addEvent(new DeathEvent()); if (statics.isTeamLeader()) { for (RobotPeer teammate : teamPeer) { if (!(teammate.isDead() || teammate == this)) { teammate.updateEnergy(-30); BulletPeer sBullet = new BulletPeer(this, battle, -1); sBullet.setState(BulletState.HIT_VICTIM); sBullet.setX(teammate.x); sBullet.setY(teammate.y); sBullet.setVictim(teammate); sBullet.setPower(4); battle.addBullet(sBullet); } } } battle.registerDeathRobot(this); // 'fake' bullet for explosion on self final ExplosionPeer fake = new ExplosionPeer(this, battle); battle.addBullet(fake); } updateEnergy(-energy); setState(RobotState.DEAD); } public void waitForStop() { robotProxy.waitForStopThread(); } /** * Clean things up removing all references to the robot. */ public void cleanup() { if (statistics != null) { statistics.cleanup(); statistics = null; } battle = null; if (robotProxy != null) { robotProxy.cleanup(); } // Cleanup robot proxy robotProxy = null; status = null; commands = null; events = null; teamMessages = null; bulletUpdates = null; battleText.setLength(0); proxyText.setLength(0); statics = null; battleRules = null; } public List getGraphicsCalls() { return commands.get().getGraphicsCalls(); } public boolean isTryingToPaint() { return commands.get().isTryingToPaint(); } public List getDebugProperties() { return commands.get().getDebugProperties(); } public void publishStatus(long currentTurn) { RobotStatus stat = new RobotStatus(this, commands.get(), battle); status.set(stat); if (!isDead()) { addEvent(new StatusEvent(stat)); // Add paint event, if robot is a paint robot and its painting is enabled if (isPaintRobot() && (isPaintEnabled() || isPaintRecorded) && currentTurn > 0) { addEvent(new PaintEvent()); } } } public void addBulletStatus(BulletStatus bulletStatus) { if (isAlive()) { bulletUpdates.get().add(bulletStatus); } } public int compareTo(ContestantPeer cp) { double myScore = statistics.getTotalScore(); double hisScore = cp.getStatistics().getTotalScore(); if (statistics.isInRound()) { myScore += statistics.getCurrentScore(); hisScore += cp.getStatistics().getCurrentScore(); } if (myScore < hisScore) { return -1; } if (myScore > hisScore) { return 1; } return 0; } @Override public String toString() { return statics.getShortName() + "(" + (int) energy + ") X" + (int) x + " Y" + (int) y + " " + state.toString() + (isSleeping() ? " sleeping " : "") + (isRunning() ? " running" : "") + (getHalt() ? " halted" : ""); } } robocode/robocode/robocode/peer/RobotStatics.java0000644000175000017500000001003711130241112021435 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.peer; import robocode.BattleRules; import robocode.manager.NameManager; import robocode.repository.RobotFileSpecification; import java.util.List; /** * @author Pavel Savara (original) */ public final class RobotStatics { private final boolean isJuniorRobot; private final boolean isInteractiveRobot; private final boolean isPaintRobot; private final boolean isAdvancedRobot; private final boolean isTeamRobot; private final boolean isTeamLeader; private final boolean isDroid; private final String name; private final String shortName; private final String veryShortName; private final String nonVersionedName; private final String shortClassName; private final BattleRules battleRules; private final String[] teammates; private final String teamName; private final int index; private final int contestantIndex; public RobotStatics(RobotFileSpecification spec, int duplicate, boolean isLeader, BattleRules rules, TeamPeer team, int index, int contestantIndex) { NameManager cnm = spec.getNameManager(); if (duplicate >= 0) { String countString = " (" + (duplicate + 1) + ')'; name = cnm.getFullClassNameWithVersion() + countString; shortName = cnm.getUniqueShortClassNameWithVersion() + countString; veryShortName = cnm.getUniqueVeryShortClassNameWithVersion() + countString; nonVersionedName = cnm.getFullClassName() + countString; } else { name = cnm.getFullClassNameWithVersion(); shortName = cnm.getUniqueShortClassNameWithVersion(); veryShortName = cnm.getUniqueVeryShortClassNameWithVersion(); nonVersionedName = cnm.getFullClassName(); } shortClassName = spec.getNameManager().getShortClassName(); isJuniorRobot = spec.isJuniorRobot(); isInteractiveRobot = spec.isInteractiveRobot(); isPaintRobot = spec.isPaintRobot(); isAdvancedRobot = spec.isAdvancedRobot(); isTeamRobot = spec.isTeamRobot(); isDroid = spec.isDroid(); isTeamLeader = isLeader; battleRules = rules; this.index = index; this.contestantIndex = contestantIndex; if (team != null) { List memberNames = team.getMemberNames(); teammates = new String[memberNames.size() - 1]; int i = 0; for (String mate : memberNames) { if (!name.equals(mate)) { teammates[i++] = mate; } } teamName = team.getName(); } else { teammates = new String[0]; teamName = name; } } public boolean isJuniorRobot() { return isJuniorRobot; } public boolean isInteractiveRobot() { return isInteractiveRobot; } public boolean isPaintRobot() { return isPaintRobot; } public boolean isAdvancedRobot() { return isAdvancedRobot; } public boolean isTeamRobot() { return isTeamRobot; } public boolean isTeamLeader() { return isTeamLeader; } public boolean isDroid() { return isDroid; } public String getName() { return name; } public String getShortName() { return shortName; } public String getVeryShortName() { return veryShortName; } public String getNonVersionedName() { return nonVersionedName; } public String getShortClassName() { return shortClassName; } public BattleRules getBattleRules() { return battleRules; } public String[] getTeammates() { return teammates.clone(); } public String getTeamName() { return teamName; } public int getIndex() { return index; } public int getContestIndex() { return contestantIndex; } } robocode/robocode/robocode/peer/proxies/0000755000175000017500000000000011124141722017653 5ustar lambylambyrobocode/robocode/robocode/peer/proxies/StandardRobotProxy.java0000644000175000017500000000752211130241112024323 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.peer.proxies; import robocode.RobotStatus; import robocode.manager.IHostManager; import robocode.peer.ExecCommands; import robocode.peer.IRobotPeer; import robocode.peer.RobotStatics; import robocode.peer.robot.RobotClassManager; import robocode.robotinterfaces.peer.IStandardRobotPeer; /** * @author Pavel Savara (original) */ public class StandardRobotProxy extends BasicRobotProxy implements IStandardRobotPeer { private boolean isStopped; private double saveAngleToTurn; private double saveDistanceToGo; private double saveGunAngleToTurn; private double saveRadarAngleToTurn; public StandardRobotProxy(RobotClassManager robotClassManager, IHostManager hostManager, IRobotPeer peer, RobotStatics statics) { super(robotClassManager, hostManager, peer, statics); } @Override protected void initializeRound(ExecCommands commands, RobotStatus status) { super.initializeRound(commands, status); isStopped = true; } // blocking actions public void stop(boolean overwrite) { setStopImpl(overwrite); execute(); } public void resume() { setResumeImpl(); execute(); } public void rescan() { boolean reset = false; boolean resetValue = false; if (eventManager.getCurrentTopEventPriority() == eventManager.getScannedRobotEventPriority()) { reset = true; resetValue = eventManager.getInterruptible(eventManager.getScannedRobotEventPriority()); eventManager.setInterruptible(eventManager.getScannedRobotEventPriority(), true); } commands.setScan(true); executeImpl(); if (reset) { eventManager.setInterruptible(eventManager.getScannedRobotEventPriority(), resetValue); } } public void turnRadar(double radians) { setTurnRadarImpl(radians); do { execute(); // Always tick at least once } while (getRadarTurnRemaining() != 0); } // fast setters public void setAdjustGunForBodyTurn(boolean newAdjustGunForBodyTurn) { setCall(); commands.setAdjustGunForBodyTurn(newAdjustGunForBodyTurn); } public void setAdjustRadarForGunTurn(boolean newAdjustRadarForGunTurn) { setCall(); commands.setAdjustRadarForGunTurn(newAdjustRadarForGunTurn); if (!commands.isAdjustRadarForBodyTurnSet()) { commands.setAdjustRadarForBodyTurn(newAdjustRadarForGunTurn); } } public void setAdjustRadarForBodyTurn(boolean newAdjustRadarForBodyTurn) { setCall(); commands.setAdjustRadarForBodyTurn(newAdjustRadarForBodyTurn); commands.setAdjustRadarForBodyTurnSet(true); } protected final void setResumeImpl() { if (isStopped) { isStopped = false; commands.setDistanceRemaining(saveDistanceToGo); commands.setBodyTurnRemaining(saveAngleToTurn); commands.setGunTurnRemaining(saveGunAngleToTurn); commands.setRadarTurnRemaining(saveRadarAngleToTurn); } } protected final void setStopImpl(boolean overwrite) { if (!isStopped || overwrite) { this.saveDistanceToGo = getDistanceRemaining(); this.saveAngleToTurn = getBodyTurnRemaining(); this.saveGunAngleToTurn = getGunTurnRemaining(); this.saveRadarAngleToTurn = getRadarTurnRemaining(); } isStopped = true; commands.setDistanceRemaining(0); commands.setBodyTurnRemaining(0); commands.setGunTurnRemaining(0); commands.setRadarTurnRemaining(0); } } robocode/robocode/robocode/peer/proxies/JuniorRobotProxy.java0000644000175000017500000001007611130241112024027 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * This is temporary implementation of the interface. You should not build any external component on top of it. * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.peer.proxies; import robocode.Rules; import robocode.manager.IHostManager; import robocode.peer.IRobotPeer; import robocode.peer.RobotStatics; import robocode.peer.robot.RobotClassManager; import robocode.robotinterfaces.peer.IJuniorRobotPeer; /** * @author Pavel Savara (original) */ public class JuniorRobotProxy extends BasicRobotProxy implements IJuniorRobotPeer { public JuniorRobotProxy(RobotClassManager robotClassManager, IHostManager hostManager, IRobotPeer peer, RobotStatics statics) { super(robotClassManager, hostManager, peer, statics); } public void turnAndMove(double distance, double radians) { if (distance == 0) { turnBody(radians); return; } // Save current max. velocity and max. turn rate so they can be restored final double savedMaxVelocity = commands.getMaxVelocity(); final double savedMaxTurnRate = commands.getMaxTurnRate(); final double absDegrees = Math.abs(Math.toDegrees(radians)); final double absDistance = Math.abs(distance); // -- Calculate max. velocity for moving perfect in a circle -- // maxTurnRate = 10 * 0.75 * velocity (Robocode rule), and // maxTurnRate = velocity * degrees / distance (curve turn rate) // // Hence, max. velocity = 10 / (degrees / distance + 0.75) final double maxVelocity = Math.min(Rules.MAX_VELOCITY, 10 / (absDegrees / absDistance + 0.75)); // -- Calculate number of turns for acceleration + deceleration -- double accDist = 0; // accumulated distance during acceleration double decDist = 0; // accumulated distance during deceleration int turns = 0; // number of turns to it will take to move the distance // Calculate the amount of turn it will take to accelerate + decelerate // up to the max. velocity, but stop if the distance for used for // acceleration + deceleration gets bigger than the total distance to move for (int t = 1; t < maxVelocity; t++) { // Add the current velocity to the acceleration distance accDist += t; // Every 2nd time we add the deceleration distance needed to // get to a velocity of 0 if (t > 2 && (t % 2) > 0) { decDist += t - 2; } // Stop if the acceleration + deceleration > total distance to move if ((accDist + decDist) >= absDistance) { break; } // Increment turn for acceleration turns++; // Every 2nd time we increment time for deceleration if (t > 2 && (t % 2) > 0) { turns++; } } // Add number of turns for the remaining distance at max velocity if ((accDist + decDist) < absDistance) { turns += (int) ((absDistance - accDist - decDist) / maxVelocity + 1); } // -- Move and turn in a curve -- // Set the calculated max. velocity commands.setMaxVelocity(maxVelocity); // Set the robot to move the specified distance setMoveImpl(distance); // Set the robot to turn its body to the specified amount of radians setTurnBodyImpl(radians); // Loop thru the number of turns it will take to move the distance and adjust // the max. turn rate so it fit the current velocity of the robot for (int t = turns; t >= 0; t--) { commands.setMaxTurnRate(getVelocity() * radians / absDistance); execute(); // Perform next turn } // Restore the saved max. velocity and max. turn rate commands.setMaxVelocity(savedMaxVelocity); commands.setMaxTurnRate(savedMaxTurnRate); } } robocode/robocode/robocode/peer/proxies/IHostedThread.java0000644000175000017500000000177111130241112023202 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.peer.proxies; import robocode.peer.RobotStatics; import robocode.peer.robot.RobotFileSystemManager; import robocode.peer.robot.RobotOutputStream; /** * @author Pavel Savara (original) */ public interface IHostedThread extends Runnable { void println(String s); void drainEnergy(); RobotStatics getStatics(); RobotFileSystemManager getRobotFileSystemManager(); RobotOutputStream getOut(); } robocode/robocode/robocode/peer/proxies/TeamRobotProxy.java0000644000175000017500000000733711130241112023455 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * - messages are now serialized and deserialized on sender and receiver threads *******************************************************************************/ package robocode.peer.proxies; import robocode.MessageEvent; import robocode.io.RobocodeObjectInputStream; import robocode.manager.IHostManager; import robocode.peer.IRobotPeer; import robocode.peer.RobotStatics; import robocode.peer.robot.RobotClassManager; import robocode.peer.robot.TeamMessage; import robocode.robotinterfaces.peer.ITeamRobotPeer; import java.io.*; import java.util.List; /** * @author Pavel Savara (original) */ public class TeamRobotProxy extends AdvancedRobotProxy implements ITeamRobotPeer { final int MAX_MESSAGE_SIZE = 32768; private final ByteArrayOutputStream byteStreamWriter; public TeamRobotProxy(RobotClassManager robotClassManager, IHostManager hostManager, IRobotPeer peer, RobotStatics statics) { super(robotClassManager, hostManager, peer, statics); byteStreamWriter = new ByteArrayOutputStream(MAX_MESSAGE_SIZE); } // team public String[] getTeammates() { getCall(); return statics.getTeammates(); } public boolean isTeammate(String name) { getCall(); if (name.equals(statics.getName())) { return true; } for (String mate : statics.getTeammates()) { if (mate.equals(name)) { return true; } } return false; } public void broadcastMessage(Serializable message) throws IOException { sendMessage(null, message); } public void sendMessage(String name, Serializable message) throws IOException { setCall(); try { if (!statics.isTeamRobot()) { throw new IOException("You are not on a team."); } byteStreamWriter.reset(); ObjectOutputStream objectStreamWriter = new ObjectOutputStream(byteStreamWriter); objectStreamWriter.writeObject(message); objectStreamWriter.flush(); byteStreamWriter.flush(); final byte[] bytes = byteStreamWriter.toByteArray(); objectStreamWriter.reset(); if (bytes.length > MAX_MESSAGE_SIZE) { throw new IOException("Message too big. " + bytes.length + ">" + MAX_MESSAGE_SIZE); } commands.getTeamMessages().add(new TeamMessage(getName(), name, bytes)); } catch (IOException e) { out.printStackTrace(e); throw e; } } @Override protected final void loadTeamMessages(List teamMessages) { if (teamMessages == null) { return; } for (TeamMessage teamMessage : teamMessages) { try { ByteArrayInputStream byteStreamReader = new ByteArrayInputStream(teamMessage.message); byteStreamReader.reset(); RobocodeObjectInputStream objectStreamReader = new RobocodeObjectInputStream(byteStreamReader, robotClassManager.getRobotClassLoader()); Serializable message = (Serializable) objectStreamReader.readObject(); final MessageEvent event = new MessageEvent(teamMessage.sender, message); RobotClassManager.setTime(event, getTime()); eventManager.add(event); } catch (IOException e) { out.printStackTrace(e); } catch (ClassNotFoundException e) { out.printStackTrace(e); } } } // events public List getMessageEvents() { getCall(); return eventManager.getMessageEvents(); } } robocode/robocode/robocode/peer/proxies/IHostingRobotProxy.java0000644000175000017500000000165011130241112024303 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.peer.proxies; import robocode.RobotStatus; import robocode.peer.ExecCommands; /** * @author Pavel Savara (original) */ public interface IHostingRobotProxy { void startRound(ExecCommands commands, RobotStatus status); boolean isRunning(); void forceStopThread(); void waitForStopThread(); void cleanup(); } robocode/robocode/robocode/peer/proxies/AdvancedRobotProxy.java0000644000175000017500000001233411130241112024265 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * Flemming N. Larsen * - Added getPaintEvents() *******************************************************************************/ package robocode.peer.proxies; import robocode.*; import robocode.manager.IHostManager; import robocode.peer.IRobotPeer; import robocode.peer.RobotStatics; import robocode.peer.robot.RobotClassManager; import robocode.robotinterfaces.peer.IAdvancedRobotPeer; import java.io.File; import java.util.List; /** * @author Pavel Savara (original) * @author Flemming N. Larsen (contributor) */ public class AdvancedRobotProxy extends StandardRobotProxy implements IAdvancedRobotPeer { public AdvancedRobotProxy(RobotClassManager robotClassManager, IHostManager hostManager, IRobotPeer peer, RobotStatics statics) { super(robotClassManager, hostManager, peer, statics); } public boolean isAdjustGunForBodyTurn() { getCall(); return commands.isAdjustGunForBodyTurn(); } public boolean isAdjustRadarForGunTurn() { getCall(); return commands.isAdjustRadarForGunTurn(); } public boolean isAdjustRadarForBodyTurn() { getCall(); return commands.isAdjustRadarForBodyTurn(); } // asynchronous actions public void setResume() { setCall(); setResumeImpl(); } public void setStop(boolean overwrite) { setCall(); setStopImpl(overwrite); } public void setMove(double distance) { setCall(); setMoveImpl(distance); } public void setTurnBody(double radians) { setCall(); setTurnBodyImpl(radians); } public void setTurnGun(double radians) { setCall(); setTurnGunImpl(radians); } public void setTurnRadar(double radians) { setCall(); setTurnRadarImpl(radians); } // blocking actions public void waitFor(Condition condition) { waitCondition = condition; do { execute(); // Always tick at least once } while (!condition.test()); waitCondition = null; } // fast setters public void setMaxTurnRate(double newTurnRate) { setCall(); if (Double.isNaN(newTurnRate)) { println("You cannot setMaxTurnRate to: " + newTurnRate); return; } commands.setMaxTurnRate(newTurnRate); } public void setMaxVelocity(double newVelocity) { setCall(); if (Double.isNaN(newVelocity)) { println("You cannot setMaxVelocity to: " + newVelocity); return; } commands.setMaxVelocity(newVelocity); } // events manipulation public void setInterruptible(boolean interruptable) { setCall(); eventManager.setInterruptible(eventManager.getCurrentTopEventPriority(), interruptable); } public void setEventPriority(String eventClass, int priority) { setCall(); eventManager.setEventPriority(eventClass, priority); } public int getEventPriority(String eventClass) { getCall(); return eventManager.getEventPriority(eventClass); } public void removeCustomEvent(Condition condition) { setCall(); eventManager.removeCustomEvent(condition); } public void addCustomEvent(Condition condition) { setCall(); eventManager.addCustomEvent(condition); } public void clearAllEvents() { setCall(); eventManager.clearAllEvents(false); } public List getAllEvents() { getCall(); return eventManager.getAllEvents(); } public List getStatusEvents() { getCall(); return eventManager.getStatusEvents(); } public List getBulletMissedEvents() { getCall(); return eventManager.getBulletMissedEvents(); } public List getBulletHitBulletEvents() { getCall(); return eventManager.getBulletHitBulletEvents(); } public List getBulletHitEvents() { getCall(); return eventManager.getBulletHitEvents(); } public List getHitByBulletEvents() { getCall(); return eventManager.getHitByBulletEvents(); } public List getHitRobotEvents() { getCall(); return eventManager.getHitRobotEvents(); } public List getHitWallEvents() { getCall(); return eventManager.getHitWallEvents(); } public List getRobotDeathEvents() { getCall(); return eventManager.getRobotDeathEvents(); } public List getScannedRobotEvents() { getCall(); return eventManager.getScannedRobotEvents(); } // data public File getDataDirectory() { getCall(); commands.setIORobot(); return robotFileSystemManager.getWritableDirectory(); } public File getDataFile(String filename) { getCall(); commands.setIORobot(); return new File(robotFileSystemManager.getWritableDirectory(), filename); } public long getDataQuotaAvailable() { getCall(); return robotFileSystemManager.getMaxQuota() - robotFileSystemManager.getQuotaUsed(); } } robocode/robocode/robocode/peer/proxies/HostingRobotProxy.java0000644000175000017500000002071711130241112024177 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package robocode.peer.proxies; import robocode.RobotStatus; import robocode.exception.AbortedException; import robocode.exception.DeathException; import robocode.exception.DisabledException; import robocode.exception.WinException; import static robocode.io.Logger.logMessage; import robocode.manager.IHostManager; import robocode.peer.ExecCommands; import robocode.peer.IRobotPeer; import robocode.peer.RobotStatics; import robocode.peer.robot.*; import robocode.robotinterfaces.IBasicRobot; import robocode.robotinterfaces.peer.IBasicRobotPeer; import robocode.security.RobocodeClassLoader; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.concurrent.atomic.AtomicBoolean; /** * @author Pavel Savara (original) */ public abstract class HostingRobotProxy implements IHostingRobotProxy, IHostedThread { protected EventManager eventManager; protected RobotThreadManager robotThreadManager; protected RobotFileSystemManager robotFileSystemManager; protected RobotClassManager robotClassManager; protected final RobotStatics statics; protected RobotOutputStream out; protected final IRobotPeer peer; protected final IHostManager hostManager; protected IBasicRobot robot; // thread is running private final AtomicBoolean isRunning = new AtomicBoolean(false); HostingRobotProxy(RobotClassManager robotClassManager, IHostManager hostManager, IRobotPeer peer, RobotStatics statics) { this.peer = peer; this.statics = statics; this.hostManager = hostManager; this.robotClassManager = robotClassManager; out = new RobotOutputStream(); robotThreadManager = new RobotThreadManager(this); loadClassBattle(); robotFileSystemManager = new RobotFileSystemManager(this, hostManager.getRobotFilesystemQuota(), robotClassManager.getRobotClassLoader().getClassDirectory(), robotClassManager.getRobotClassLoader().getRootPackageDirectory()); robotFileSystemManager.initializeQuota(); } public void cleanup() { // Clear all static field on the robot (at class level) cleanupStaticFields(); robot = null; // Remove the file system and the manager robotFileSystemManager = null; if (out != null) { out.close(); out = null; } if (robotThreadManager != null) { robotThreadManager.cleanup(); } robotThreadManager = null; // Cleanup and remove class manager if (robotClassManager != null) { robotClassManager.cleanup(); robotClassManager = null; } } private void cleanupStaticFields() { if (robot == null) { return; } Field[] fields = new Field[0]; // This try-catch-throwable must be here, as it is not always possible to get the // declared fields without getting a Throwable like java.lang.NoClassDefFoundError. try { fields = robot.getClass().getDeclaredFields(); } catch (Throwable t) {// Do nothing } for (Field f : fields) { int m = f.getModifiers(); if (Modifier.isStatic(m) && !(Modifier.isFinal(m) || f.getType().isPrimitive())) { try { f.setAccessible(true); f.set(robot, null); } catch (Exception e) { e.printStackTrace(); } } } } public RobotOutputStream getOut() { return out; } public void println(String s) { out.println(s); } public void println(Throwable ex) { ex.printStackTrace(out); } public RobotStatics getStatics() { return statics; } public RobotFileSystemManager getRobotFileSystemManager() { return robotFileSystemManager; } // ----------- // battle driven methods // ----------- protected abstract void initializeRound(ExecCommands commands, RobotStatus status); public void startRound(ExecCommands commands, RobotStatus status) { initializeRound(commands, status); robotThreadManager.start(hostManager.getThreadManager()); } public void forceStopThread() { if (!robotThreadManager.forceStop()) { peer.punishBadBehavior(); isRunning.set(false); } } public void waitForStopThread() { if (!robotThreadManager.waitForStop()) { peer.punishBadBehavior(); isRunning.set(false); } } private void loadClassBattle() { try { Class c; String className = robotClassManager.getFullClassName(); RobocodeClassLoader classLoader = robotClassManager.getRobotClassLoader(); // Pre-load robot classes without security... // loadClass WILL NOT LINK the class, so static "cheats" will not work. // in the safe robot loader the class is linked. if (RobotClassManager.isSecutityOn()) { c = classLoader.loadRobotClass(className, true); } else { c = classLoader.loadClass(className); } robotClassManager.setRobotClass(c); } catch (Throwable e) { println("SYSTEM: Could not load " + statics.getName() + " : "); println(e); drainEnergy(); } } private boolean loadRobotRound() { robot = null; Class robotClass; try { hostManager.getThreadManager().setLoadingRobot(this); robotClass = robotClassManager.getRobotClass(); if (robotClass == null) { println("SYSTEM: Skipping robot: " + statics.getName()); return false; } robot = (IBasicRobot) robotClass.newInstance(); robot.setOut(getOut()); robot.setPeer((IBasicRobotPeer) this); eventManager.setRobot(robot); } catch (IllegalAccessException e) { println("SYSTEM: Unable to instantiate this robot: " + e); println("SYSTEM: Is your constructor marked public?"); println(e); robot = null; logMessage(e); return false; } catch (Throwable e) { println("SYSTEM: An error occurred during initialization of " + statics.getName()); println("SYSTEM: " + e); println(e); robot = null; logMessage(e); return false; } finally { hostManager.getThreadManager().setLoadingRobot(null); } return true; } // / protected abstract void executeImpl(); public void run() { robotThreadManager.initAWT(); isRunning.set(true); if (!robotClassManager.getRobotSpecification().isValid() || !loadRobotRound()) { drainEnergy(); peer.punishBadBehavior(); waitForBattleEndImpl(); } else { try { if (robot != null) { // Process all events for the first turn. // This is done as the first robot status event must occur before the robot // has started running. eventManager.processEvents(); Runnable runnable = robot.getRobotRunnable(); if (runnable != null) { runnable.run(); } } // noinspection InfiniteLoopStatement for (;;) { executeImpl(); } } catch (WinException e) {// Do nothing } catch (AbortedException e) {// Do nothing } catch (DeathException e) { println("SYSTEM: " + statics.getName() + " has died"); } catch (DisabledException e) { drainEnergy(); String msg = e.getMessage(); if (msg == null) { msg = ""; } else { msg = ": " + msg; } println("SYSTEM: Robot disabled" + msg); logMessage(statics.getName() + "Robot disabled"); } catch (Exception e) { drainEnergy(); println(e); logMessage(statics.getName() + ": Exception: " + e); // without stack here } catch (Throwable t) { drainEnergy(); if (t instanceof ThreadDeath) { logMessage(statics.getName() + " stopped successfully."); } else { println(t); logMessage(statics.getName() + ": Throwable: " + t); // without stack here } } finally { waitForBattleEndImpl(); } } // If battle is waiting for us, well, all done! synchronized (this) { isRunning.set(false); notifyAll(); } } protected abstract void waitForBattleEndImpl(); // TODO minimize border crossing between battle and proxy spaces public void drainEnergy() { peer.drainEnergy(); } // TODO minimize border crossing between battle and proxy spaces public boolean isRunning() { return isRunning.get(); } } robocode/robocode/robocode/peer/proxies/BasicRobotProxy.java0000644000175000017500000003216011130241112023600 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Pavel Savara * - Initial implementation * - hosting related logic moved here from robot peer * - interlocked synchronization * - (almost) minimized surface between RobotPeer and RobotProxy to serializable messages. *******************************************************************************/ package robocode.peer.proxies; import robocode.*; import robocode.Event; import robocode.exception.DisabledException; import robocode.exception.RobotException; import robocode.manager.IHostManager; import robocode.peer.*; import robocode.peer.robot.EventManager; import robocode.peer.robot.RobotClassManager; import robocode.peer.robot.TeamMessage; import robocode.robotinterfaces.peer.IBasicRobotPeer; import robocode.robotpaint.Graphics2DProxy; import robocode.util.Utils; import java.awt.*; import static java.lang.Math.max; import static java.lang.Math.min; import java.util.Hashtable; import java.util.concurrent.atomic.AtomicInteger; /** * @author Pavel Savara (original) */ public class BasicRobotProxy extends HostingRobotProxy implements IBasicRobotPeer { private static final long MAX_SET_CALL_COUNT = 10000, MAX_GET_CALL_COUNT = 10000; private Graphics2DProxy graphicsProxy; protected RobotStatus status; protected ExecCommands commands; private ExecResults execResults; private final Hashtable bullets = new Hashtable(); private int bulletCounter; private final AtomicInteger setCallCount = new AtomicInteger(0); private final AtomicInteger getCallCount = new AtomicInteger(0); protected Condition waitCondition; protected boolean testingCondition; protected double firedEnergy; protected double firedHeat; public BasicRobotProxy(RobotClassManager robotClassManager, IHostManager hostManager, IRobotPeer peer, RobotStatics statics) { super(robotClassManager, hostManager, peer, statics); eventManager = new EventManager(this); graphicsProxy = new Graphics2DProxy(); // dummy execResults = new ExecResults(null, null, null, null, null, false, false, false); setSetCallCount(0); setGetCallCount(0); } protected void initializeRound(ExecCommands commands, RobotStatus status) { updateStatus(commands, status); eventManager.reset(); final StatusEvent start = new StatusEvent(status); RobotClassManager.setTime(start, 0); eventManager.add(start); setSetCallCount(0); setGetCallCount(0); } @Override public void cleanup() { super.cleanup(); // Cleanup and remove current wait condition if (waitCondition != null) { waitCondition.cleanup(); waitCondition = null; } // Cleanup and remove the event manager if (eventManager != null) { eventManager.cleanup(); eventManager = null; } // Cleanup graphics proxy graphicsProxy = null; execResults = null; status = null; commands = null; } // asynchronous actions public Bullet setFire(double power) { setCall(); return setFireImpl(power); } // blocking actions public void execute() { executeImpl(); } public void move(double distance) { setMoveImpl(distance); do { execute(); // Always tick at least once } while (getDistanceRemaining() != 0); } public void turnBody(double radians) { setTurnBodyImpl(radians); do { execute(); // Always tick at least once } while (getBodyTurnRemaining() != 0); } public void turnGun(double radians) { setTurnGunImpl(radians); do { execute(); // Always tick at least once } while (getGunTurnRemaining() != 0); } public Bullet fire(double power) { Bullet bullet = setFire(power); execute(); return bullet; } // fast setters public void setBodyColor(Color color) { setCall(); commands.setBodyColor(color != null ? color.getRGB() : ExecCommands.defaultBodyColor); } public void setGunColor(Color color) { setCall(); commands.setGunColor(color != null ? color.getRGB() : ExecCommands.defaultGunColor); } public void setRadarColor(Color color) { setCall(); commands.setRadarColor(color != null ? color.getRGB() : ExecCommands.defaultRadarColor); } public void setBulletColor(Color color) { setCall(); commands.setBulletColor(color != null ? color.getRGB() : ExecCommands.defaultBulletColor); } public void setScanColor(Color color) { setCall(); commands.setScanColor(color != null ? color.getRGB() : ExecCommands.defaultScanColor); } // counters public void setCall() { final int res = setCallCount.incrementAndGet(); if (res >= MAX_SET_CALL_COUNT) { println("SYSTEM: You have made " + res + " calls to setXX methods without calling execute()"); throw new DisabledException("Too many calls to setXX methods"); } } public void getCall() { final int res = getCallCount.incrementAndGet(); if (res >= MAX_GET_CALL_COUNT) { println("SYSTEM: You have made " + res + " calls to getXX methods without calling execute()"); throw new DisabledException("Too many calls to getXX methods"); } } public double getDistanceRemaining() { getCall(); return commands.getDistanceRemaining(); } public double getRadarTurnRemaining() { getCall(); return commands.getRadarTurnRemaining(); } public double getBodyTurnRemaining() { getCall(); return commands.getBodyTurnRemaining(); } public double getGunTurnRemaining() { getCall(); return commands.getGunTurnRemaining(); } public double getVelocity() { getCall(); return status.getVelocity(); } public double getGunCoolingRate() { getCall(); return statics.getBattleRules().getGunCoolingRate(); } public String getName() { getCall(); return statics.getName(); } public long getTime() { getCall(); return getTimeImpl(); } public double getBodyHeading() { getCall(); return status.getHeadingRadians(); } public double getGunHeading() { getCall(); return status.getGunHeadingRadians(); } public double getRadarHeading() { getCall(); return status.getRadarHeadingRadians(); } public double getEnergy() { getCall(); return getEnergyImpl(); } public double getGunHeat() { getCall(); return getGunHeatImpl(); } public double getX() { getCall(); return status.getX(); } public double getY() { getCall(); return status.getY(); } public int getOthers() { getCall(); return status.getOthers(); } public double getBattleFieldHeight() { getCall(); return statics.getBattleRules().getBattlefieldHeight(); } public double getBattleFieldWidth() { getCall(); return statics.getBattleRules().getBattlefieldWidth(); } public int getNumRounds() { getCall(); return statics.getBattleRules().getNumRounds(); } public int getRoundNum() { getCall(); return status.getRoundNum(); } public Graphics2D getGraphics() { getCall(); commands.setTryingToPaint(true); return getGraphicsImpl(); } public void setDebugProperty(String key, String value) { setCall(); commands.setDebugProperty(key, value); } // ----------- // implementations // ----------- public long getTimeImpl() { return status.getTime(); } public Graphics2D getGraphicsImpl() { return graphicsProxy; } @Override protected final void executeImpl() { if (execResults == null) { // this is to slow down undead robot after cleanup, from fast exception-loop try { Thread.sleep(1000); } catch (InterruptedException e) {// just swalow here } } // Entering tick robotThreadManager.checkRunThread(); if (testingCondition) { throw new RobotException( "You cannot take action inside Condition.test(). You should handle onCustomEvent instead."); } setSetCallCount(0); setGetCallCount(0); // This stops autoscan from scanning... if (waitCondition != null && waitCondition.test()) { waitCondition = null; commands.setScan(true); } commands.setOutputText(out.readAndReset()); commands.setGraphicsCalls(graphicsProxy.getQueuedCalls()); graphicsProxy.clearQueue(); // call server execResults = peer.executeImpl(commands); updateStatus(execResults.getCommands(), execResults.getStatus()); graphicsProxy.setPaintingEnabled(execResults.isPaintEnabled()); firedEnergy = 0; firedHeat = 0; // add new events first if (execResults.getEvents() != null) { for (Event event : execResults.getEvents()) { eventManager.add(event); RobotClassManager.updateBullets(event, bullets); } } for (BulletStatus s : execResults.getBulletUpdates()) { final Bullet bullet = bullets.get(s.bulletId); if (bullet != null) { RobotClassManager.update(bullet, s); if (!s.isActive) { bullets.remove(s.bulletId); } } } // add new team messages loadTeamMessages(execResults.getTeamMessages()); eventManager.processEvents(); } @Override protected final void waitForBattleEndImpl() { eventManager.clearAllEvents(false); graphicsProxy.setPaintingEnabled(false); do { commands.setOutputText(out.readAndReset()); commands.setGraphicsCalls(graphicsProxy.getQueuedCalls()); graphicsProxy.clearQueue(); // call server execResults = peer.waitForBattleEndImpl(commands); updateStatus(execResults.getCommands(), execResults.getStatus()); // add new events if (execResults.getEvents() != null) { for (Event event : execResults.getEvents()) { if (event instanceof BattleEndedEvent) { eventManager.add(event); } } } eventManager.resetCustomEvents(); eventManager.processEvents(); } while (!execResults.isHalt() && execResults.isShouldWait()); } private void updateStatus(ExecCommands commands, RobotStatus status) { this.status = status; this.commands = commands; } protected void loadTeamMessages(java.util.List teamMessages) {} protected final double getEnergyImpl() { return status.getEnergy() - firedEnergy; } protected final double getGunHeatImpl() { return status.getGunHeat() + firedHeat; } protected final void setMoveImpl(double distance) { if (getEnergyImpl() == 0) { return; } commands.setDistanceRemaining(distance); commands.setMoved(true); } protected final Bullet setFireImpl(double power) { if (Double.isNaN(power)) { println("SYSTEM: You cannot call fire(NaN)"); return null; } if (getGunHeatImpl() > 0 || getEnergyImpl() == 0) { return null; } power = min(getEnergyImpl(), min(max(power, Rules.MIN_BULLET_POWER), Rules.MAX_BULLET_POWER)); Bullet bullet; BulletCommand wrapper; Event currentTopEvent = eventManager.getCurrentTopEvent(); bulletCounter++; if (currentTopEvent != null && currentTopEvent.getTime() == status.getTime() && !statics.isAdvancedRobot() && status.getGunHeadingRadians() == status.getRadarHeadingRadians() && ScannedRobotEvent.class.isAssignableFrom(currentTopEvent.getClass())) { // this is angle assisted bullet ScannedRobotEvent e = (ScannedRobotEvent) currentTopEvent; double fireAssistAngle = Utils.normalAbsoluteAngle(status.getHeadingRadians() + e.getBearingRadians()); bullet = new Bullet(fireAssistAngle, getX(), getY(), power, statics.getName(), null, true, bulletCounter); wrapper = new BulletCommand(power, true, fireAssistAngle, bulletCounter); } else { // this is normal bullet bullet = new Bullet(status.getGunHeadingRadians(), getX(), getY(), power, statics.getName(), null, true, bulletCounter); wrapper = new BulletCommand(power, false, 0, bulletCounter); } firedEnergy += power; firedHeat += Rules.getGunHeat(power); commands.getBullets().add(wrapper); bullets.put(bulletCounter, bullet); return bullet; } protected final void setTurnGunImpl(double radians) { commands.setGunTurnRemaining(radians); } protected final void setTurnBodyImpl(double radians) { if (getEnergyImpl() > 0) { commands.setBodyTurnRemaining(radians); } } protected final void setTurnRadarImpl(double radians) { commands.setRadarTurnRemaining(radians); } // ----------- // battle driven methods // ----------- private void setSetCallCount(int setCallCount) { this.setCallCount.set(setCallCount); } private void setGetCallCount(int getCallCount) { this.getCallCount.set(getCallCount); } // ----------- // for robot thread // ----------- public void setTestingCondition(boolean testingCondition) { this.testingCondition = testingCondition; } @Override public String toString() { return statics.getShortName() + "(" + (int) status.getEnergy() + ") X" + (int) status.getX() + " Y" + (int) status.getY(); } } robocode/robocode/robocode/peer/TeamPeer.java0000644000175000017500000000523211130241112020520 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Rewritten for Java 5 * - Changed contains(String) into contains(Object), as the first listed * shadowed the second one * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap * Pavel Savara * - member names are known in constructor *******************************************************************************/ package robocode.peer; import java.util.ArrayList; import java.util.List; /** * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Robert D. Maupin (contributor) */ @SuppressWarnings("serial") public class TeamPeer extends ArrayList implements ContestantPeer { private final List memberNames; private final String name; private final int contestIndex; private RobotPeer teamLeader; private final TeamStatistics teamStatistics; public TeamPeer(String name, List memberNames, int contestIndex) { this.name = name; this.contestIndex = contestIndex; this.memberNames = memberNames; this.teamStatistics = new TeamStatistics(this); } public int compareTo(ContestantPeer cp) { double myScore = teamStatistics.getTotalScore(); double hisScore = cp.getStatistics().getTotalScore(); if (teamLeader != null && teamLeader.getRobotStatistics().isInRound()) { myScore += teamStatistics.getCurrentScore(); hisScore += cp.getStatistics().getCurrentScore(); } if (myScore < hisScore) { return -1; } if (myScore > hisScore) { return 1; } return 0; } public ContestantStatistics getStatistics() { return teamStatistics; } public String getName() { return name; } public int getContestIndex() { return contestIndex; } public List getMemberNames() { return memberNames; } public RobotPeer getTeamLeader() { return teamLeader; } @Override public boolean add(RobotPeer r) { if (teamLeader == null) { teamLeader = r; } return super.add(r); } @Override public String toString() { return " [" + size() + "] " + getName(); } } robocode/robocode/robocode/AdvancedRobot.java0000644000175000017500000022055611130241114020610 0ustar lambylamby/******************************************************************************* * Copyright (c) 2001, 2008 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/cpl-v10.html * * Contributors: * Mathew A. Nelson * - Initial API and implementation * Flemming N. Larsen * - Ported to Java 5 * - Updated Javadocs * - The uninitializedException() method does not need a method name as input * parameter anymore * - Changed the priority of the DeathEvent from 100 to -1 in order to let * robots process events before they die * - Added getStatusEvents() * Robert D. Maupin * - Replaced old collection types like Vector and Hashtable with * synchronized List and HashMap * Pavel Savara * - Re-work of robot interfaces *******************************************************************************/ package robocode; import robocode.robotinterfaces.IAdvancedEvents; import robocode.robotinterfaces.IAdvancedRobot; import robocode.robotinterfaces.peer.IAdvancedRobotPeer; import java.io.File; import java.util.Vector; /** * A more advanced type of robot than Robot that allows non-blocking calls, * custom events, and writes to the filesystem. *

* If you have not already, you should create a {@link Robot} first. * * @author Mathew A. Nelson (original) * @author Flemming N. Larsen (contributor) * @author Robert D. Maupin (contributor) * @author Pavel Savara (contributor) * @see * robocode.sourceforge.net * @see * Building your first robot * @see JuniorRobot * @see Robot * @see TeamRobot * @see Droid */ public class AdvancedRobot extends _AdvancedRadiansRobot implements IAdvancedRobot, IAdvancedEvents { /** * Returns the distance remaining in the robot's current move measured in * pixels. *

* This call returns both positive and negative values. Positive values * means that the robot is currently moving forwards. Negative values means * that the robot is currently moving backwards. If the returned value is 0, * the robot currently stands still. * * @return the distance remaining in the robot's current move measured in * pixels. * @see #getTurnRemaining() getTurnRemaining() * @see #getTurnRemainingRadians() getTurnRemainingRadians() * @see #getGunTurnRemaining() getGunTurnRemaining() * @see #getGunTurnRemainingRadians() getGunTurnRemainingRadians() * @see #getRadarTurnRemaining() getRadarTurnRemaining() * @see #getRadarTurnRemainingRadians() getRadarTurnRemainingRadians() */ public double getDistanceRemaining() { if (peer != null) { return peer.getDistanceRemaining(); } uninitializedException(); return 0; // never called } /** * Returns the angle remaining in the robots's turn, in degrees. *

* This call returns both positive and negative values. Positive values * means that the robot is currently turning to the right. Negative values * means that the robot is currently turning to the left. If the returned * value is 0, the robot is currently not turning. * * @return the angle remaining in the robots's turn, in degrees * @see #getTurnRemainingRadians() getTurnRemainingRadians() * @see #getDistanceRemaining() getDistanceRemaining() * @see #getGunTurnRemaining() getGunTurnRemaining() * @see #getGunTurnRemainingRadians() getGunTurnRemainingRadians() * @see #getRadarTurnRemaining() getRadarTurnRemaining() * @see #getRadarTurnRemainingRadians() getRadarTurnRemainingRadians() */ public double getTurnRemaining() { if (peer != null) { return Math.toDegrees(peer.getBodyTurnRemaining()); } uninitializedException(); return 0; // never called } /** * Returns the angle remaining in the gun's turn, in degrees. *

* This call returns both positive and negative values. Positive values * means that the gun is currently turning to the right. Negative values * means that the gun is currently turning to the left. If the returned * value is 0, the gun is currently not turning. * * @return the angle remaining in the gun's turn, in degrees * @see #getGunTurnRemainingRadians() getGunTurnRemainingRadians() * @see #getDistanceRemaining() getDistanceRemaining() * @see #getTurnRemaining() getTurnRemaining() * @see #getTurnRemainingRadians() getTurnRemainingRadians() * @see #getRadarTurnRemaining() getRadarTurnRemaining() * @see #getRadarTurnRemainingRadians() getRadarTurnRemainingRadians() */ public double getGunTurnRemaining() { if (peer != null) { return Math.toDegrees(peer.getGunTurnRemaining()); } uninitializedException(); return 0; // never called } /** * Returns the angle remaining in the radar's turn, in degrees. *

* This call returns both positive and negative values. Positive values * means that the radar is currently turning to the right. Negative values * means that the radar is currently turning to the left. If the returned * value is 0, the radar is currently not turning. * * @return the angle remaining in the radar's turn, in degrees * @see #getRadarTurnRemainingRadians() getRadarTurnRemainingRadians() * @see #getDistanceRemaining() getDistanceRemaining() * @see #getGunTurnRemaining() getGunTurnRemaining() * @see #getGunTurnRemainingRadians() getGunTurnRemainingRadians() * @see #getRadarTurnRemaining() getRadarTurnRemaining() * @see #getRadarTurnRemainingRadians() getRadarTurnRemainingRadians() */ public double getRadarTurnRemaining() { if (peer != null) { return Math.toDegrees(peer.getRadarTurnRemaining()); } uninitializedException(); return 0; // never called } /** * Sets the robot to move ahead (forward) by distance measured in pixels * when the next execution takes place. *

* This call returns immediately, and will not execute until you call * {@link #execute()} or take an action that executes. *

* Note that both positive and negative values can be given as input, where * positive values means that the robot is set to move ahead, and negative * values means that the robot is set to move back. If 0 is given as input, * the robot will stop its movement, but will have to decelerate * till it stands still, and will thus not be able to stop its movement * immediately, but eventually. *

* Example: *

	 *   // Set the robot to move 50 pixels ahead
	 *   setAhead(50);
	 * 

* // Set the robot to move 100 pixels back * // (overrides the previous order) * setAhead(-100); *

* ... * // Executes the last setAhead() * execute(); *

* * @param distance the distance to move measured in pixels. * If {@code distance} > 0 the robot is set to move ahead. * If {@code distance} < 0 the robot is set to move back. * If {@code distance} = 0 the robot is set to stop its movement. * @see #ahead(double) ahead(double) * @see #back(double) back(double) * @see #setBack(double) */ public void setAhead(double distance) { if (peer != null) { ((IAdvancedRobotPeer) peer).setMove(distance); } else { uninitializedException(); } } /** * Sets the robot to move back by distance measured in pixels when the next * execution takes place. *

* This call returns immediately, and will not execute until you call * {@link #execute()} or take an action that executes. *

* Note that both positive and negative values can be given as input, where * positive values means that the robot is set to move back, and negative * values means that the robot is set to move ahead. If 0 is given as input, * the robot will stop its movement, but will have to decelerate * till it stands still, and will thus not be able to stop its movement * immediately, but eventually. *

* Example: *

	 *   // Set the robot to move 50 pixels back
	 *   setBack(50);
	 * 

* // Set the robot to move 100 pixels ahead * // (overrides the previous order) * setBack(-100); *

* ... * // Executes the last setBack() * execute(); *

* * @param distance the distance to move measured in pixels. * If {@code distance} > 0 the robot is set to move back. * If {@code distance} < 0 the robot is set to move ahead. * If {@code distance} = 0 the robot is set to stop its movement. * @see #back(double) back(double) * @see #ahead(double) ahead(double) * @see #setAhead(double) */ public void setBack(double distance) { if (peer != null) { ((IAdvancedRobotPeer) peer).setMove(-distance); } else { uninitializedException(); } } /** * Sets the robot's body to turn left by degrees when the next execution * takes place. *

* This call returns immediately, and will not execute until you call * execute() or take an action that executes. *

* Note that both positive and negative values can be given as input, * where negative values means that the robot's body is set to turn right * instead of left. *

* Example: *

	 *   // Set the robot to turn 180 degrees to the left
	 *   setTurnLeft(180);
	 * 

* // Set the robot to turn 90 degrees to the right instead of left * // (overrides the previous order) * setTurnLeft(-90); *

* ... * // Executes the last setTurnLeft() * execute(); *

* * @param degrees the amount of degrees to turn the robot's body to the left. * If {@code degrees} > 0 the robot is set to turn left. * If {@code degrees} < 0 the robot is set to turn right. * If {@code degrees} = 0 the robot is set to stop turning. * @see #setTurnLeftRadians(double) setTurnLeftRadians(double) * @see #turnLeft(double) turnLeft(double) * @see #turnLeftRadians(double) turnLeftRadians(double) * @see #turnRight(double) turnRight(double) * @see #turnRightRadians(double) turnRightRadians(double) * @see #setTurnRight(double) setTurnRight(double) * @see #setTurnRightRadians(double) setTurnRightRadians(double) */ public void setTurnLeft(double degrees) { if (peer != null) { ((IAdvancedRobotPeer) peer).setTurnBody(-Math.toRadians(degrees)); } else { uninitializedException(); } } /** * Sets the robot's body to turn right by degrees when the next execution * takes place. *

* This call returns immediately, and will not execute until you call * execute() or take an action that executes. *

* Note that both positive and negative values can be given as input, * where negative values means that the robot's body is set to turn left * instead of right. *

* Example: *

	 *   // Set the robot to turn 180 degrees to the right
	 *   setTurnRight(180);
	 * 

* // Set the robot to turn 90 degrees to the left instead of right * // (overrides the previous order) * setTurnRight(-90); *

* ... * // Executes the last setTurnRight() * execute(); *

* * @param degrees the amount of degrees to turn the robot's body to the right. * If {@code degrees} > 0 the robot is set to turn right. * If {@code degrees} < 0 the robot is set to turn left. * If {@code degrees} = 0 the robot is set to stop turning. * @see #setTurnRightRadians(double) setTurnRightRadians(double) * @see #turnRight(double) turnRight(double) * @see #turnRightRadians(double) turnRightRadians(double) * @see #turnLeft(double) turnLeft(double) * @see #turnLeftRadians(double) turnLeftRadians(double) * @see #setTurnLeft(double) setTurnLeft(double) * @see #setTurnLeftRadians(double) setTurnLeftRadians(double) */ public void setTurnRight(double degrees) { if (peer != null) { ((IAdvancedRobotPeer) peer).setTurnBody(Math.toRadians(degrees)); } else { uninitializedException(); } } /** * Sets the gun to fire a bullet when the next execution takes place. * The bullet will travel in the direction the gun is pointing. *

* This call returns immediately, and will not execute until you call * execute() or take an action that executes. *

* The specified bullet power is an amount of energy that will be taken from * the robot's energy. Hence, the more power you want to spend on the * bullet, the more energy is taken from your robot. *

* The bullet will do (4 * power) damage if it hits another robot. If power * is greater than 1, it will do an additional 2 * (power - 1) damage. * You will get (3 * power) back if you hit the other robot. You can call * Rules#getBulletDamage(double)} for getting the damage that a * bullet with a specific bullet power will do. *

* The specified bullet power should be between * {@link Rules#MIN_BULLET_POWER} and {@link Rules#MAX_BULLET_POWER}. *

* Note that the gun cannot fire if the gun is overheated, meaning that * {@link #getGunHeat()} returns a value > 0. *

* An event is generated when the bullet hits a robot, wall, or another * bullet. *

* Example: *

	 *   // Fire a bullet with maximum power if the gun is ready
	 *   if (getGunHeat() == 0) {
	 *       setFire(Rules.MAX_BULLET_POWER);
	 *   }
	 *   ...
	 *   execute();
	 * 
* * @param power the amount of energy given to the bullet, and subtracted * from the robot's energy. * @see #setFireBullet(double) * @see #fire(double) fire(double) * @see #fireBullet(double) fireBullet(double) * @see #getGunHeat() getGunHeat() * @see #getGunCoolingRate() getGunCoolingRate() * @see #onBulletHit(BulletHitEvent) onBulletHit(BulletHitEvent) * @see #onBulletHitBullet(BulletHitBulletEvent) onBulletHitBullet(BulletHitBulletEvent) * @see #onBulletMissed(BulletMissedEvent) onBulletMissed(BulletMissedEvent) */ public void setFire(double power) { if (peer != null) { peer.setFire(power); } else { uninitializedException(); } } /** * Sets the gun to fire a bullet when the next execution takes place. * The bullet will travel in the direction the gun is pointing. *

* This call returns immediately, and will not execute until you call * execute() or take an action that executes. *

* The specified bullet power is an amount of energy that will be taken from * the robot's energy. Hence, the more power you want to spend on the * bullet, the more energy is taken from your robot. *

* The bullet will do (4 * power) damage if it hits another robot. If power * is greater than 1, it will do an additional 2 * (power - 1) damage. * You will get (3 * power) back if you hit the other robot. You can call * {@link Rules#getBulletDamage(double)} for getting the damage that a * bullet with a specific bullet power will do. *

* The specified bullet power should be between * {@link Rules#MIN_BULLET_POWER} and {@link Rules#MAX_BULLET_POWER}. *

* Note that the gun cannot fire if the gun is overheated, meaning that * {@link #getGunHeat()} returns a value > 0. *

* A event is generated when the bullet hits a robot * ({@link BulletHitEvent}), wall ({@link BulletMissedEvent}), or another * bullet ({@link BulletHitBulletEvent}). *

* Example: *

	 *   Bullet bullet = null;
	 * 

* // Fire a bullet with maximum power if the gun is ready * if (getGunHeat() == 0) { * bullet = setFireBullet(Rules.MAX_BULLET_POWER); * } * ... * execute(); * ... * // Get the velocity of the bullet * if (bullet != null) { * double bulletVelocity = bullet.getVelocity(); * } *

* * @param power the amount of energy given to the bullet, and subtracted * from the robot's energy. * @return a {@link Bullet} that contains information about the bullet if it * was actually fired, which can be used for tracking the bullet after it * has been fired. If the bullet was not fired, {@code null} is returned. * @see #setFire(double) * @see Bullet * @see #fire(double) fire(double) * @see #fireBullet(double) fireBullet(double) * @see #getGunHeat() getGunHeat() * @see #getGunCoolingRate() getGunCoolingRate() * @see #onBulletHit(BulletHitEvent) onBulletHit(BulletHitEvent) * @see #onBulletHitBullet(BulletHitBulletEvent) onBulletHitBullet(BulletHitBulletEvent) * @see #onBulletMissed(BulletMissedEvent) onBulletMissed(BulletMissedEvent) */ public Bullet setFireBullet(double power) { if (peer != null) { return peer.setFire(power); } uninitializedException(); return null; } /** * Registers a custom event to be called when a condition is met. * When you are finished with your condition or just want to remove it you * must call {@link #removeCustomEvent(Condition)}. *

* Example: *

	 *   // Create the condition for our custom event
	 *   Condition triggerHitCondition = new Condition("triggerhit") {
	 *       public boolean test() {
	 *           return (getEnergy() <= trigger);
	 *       };
	 *   }
	 * 

* // Add our custom event based on our condition * addCustomEvent(triggerHitCondition); *

* * @param condition the condition that must be met. * @throws NullPointerException if the condition parameter has been set to * {@code null}. * @see Condition * @see #removeCustomEvent(Condition) */ public void addCustomEvent(Condition condition) { if (condition == null) { throw new NullPointerException("the condition cannot be null"); } if (peer != null) { ((IAdvancedRobotPeer) peer).addCustomEvent(condition); } else { uninitializedException(); } } /** * Removes a custom event that was previously added by calling * {@link #addCustomEvent(Condition)}. *

* Example: *

	 *   // Create the condition for our custom event
	 *   Condition triggerHitCondition = new Condition("triggerhit") {
	 *       public boolean test() {
	 *           return (getEnergy() <= trigger);
	 *       };
	 *   }
	 * 

* // Add our custom event based on our condition * addCustomEvent(triggerHitCondition); * ... * do something with your robot * ... * // Remove the custom event based on our condition * removeCustomEvent(triggerHitCondition); *

* * @param condition the condition that was previous added and that must be * removed now. * @throws NullPointerException if the condition parameter has been set to * {@code null}. * @see Condition * @see #addCustomEvent(Condition) */ public void removeCustomEvent(Condition condition) { if (condition == null) { throw new NullPointerException("the condition cannot be null"); } if (peer != null) { ((IAdvancedRobotPeer) peer).removeCustomEvent(condition); } else { uninitializedException(); } } /** * Clears out any pending events in the robot's event queue immediately. * * @see #getAllEvents() */ public void clearAllEvents() { if (peer != null) { ((IAdvancedRobotPeer) peer).clearAllEvents(); } else { uninitializedException(); } } /** * Executes any pending actions, or continues executing actions that are * in process. This call returns after the actions have been started. *

* Note that advanced robots must call this function in order to * execute pending set* calls like e.g. {@link #setAhead(double)}, * {@link #setFire(double)}, {@link #setTurnLeft(double)} etc. Otherwise, * these calls will never get executed. *

* In this example the robot will move while turning: *

	 *   setTurnRight(90);
	 *   setAhead(100);
	 *   execute();
	 * 

* while (getDistanceRemaining() > 0 && getTurnRemaining() > 0) { * execute(); * } *

*/ public void execute() { if (peer != null) { peer.execute(); } else { uninitializedException(); } } /** * Returns a vector containing all events currently in the robot's queue. * You might, for example, call this while processing another event. *

* Example: *

	 *   for (Event event : getAllEvents()) {
	 *       if (event instanceof HitRobotEvent) {
	 *           // do something with the event
	 *       } else if (event instanceof HitByBulletEvent) {
	 *           // do something with the event
	 *       }
	 *   }
	 * 
* * @return a vector containing all events currently in the robot's queue * @see Event * @see #clearAllEvents() * @see #getStatusEvents() * @see #getScannedRobotEvents() * @see #getBulletHitEvents() * @see #getBulletMissedEvents() * @see #getBulletHitBulletEvents() * @see #getRobotDeathEvents() */ public Vector getAllEvents() { if (peer != null) { return new Vector(((IAdvancedRobotPeer) peer).getAllEvents()); } uninitializedException(); return null; // never called } /** * Returns a vector containing all BulletHitBulletEvents currently in the * robot's queue. You might, for example, call this while processing another * event. *

* Example: *

	 *   for (BulletHitBulletEvent event : getBulletHitBulletEvents()) {
	 *       // do something with the event
	 *   }
	 * 
* * @return a vector containing all BulletHitBulletEvents currently in the * robot's queue * @see #onBulletHitBullet(BulletHitBulletEvent) onBulletHitBullet(BulletHitBulletEvent) * @see BulletHitBulletEvent * @see #getAllEvents() */ public Vector getBulletHitBulletEvents() { if (peer != null) { return new Vector(((IAdvancedRobotPeer) peer).getBulletHitBulletEvents()); } uninitializedException(); return null; // never called } /** * Returns a vector containing all BulletHitEvents currently in the robot's * queue. You might, for example, call this while processing another event. *

* Example: *

	 *   for (BulletHitEvent event: getBulletHitEvents()) {
	 *       // do something with the event
	 *   }
	 * 
* * @return a vector containing all BulletHitEvents currently in the robot's * queue * @see #onBulletHit(BulletHitEvent) onBulletHit(BulletHitEvent) * @see BulletHitEvent * @see #getAllEvents() */ public Vector getBulletHitEvents() { if (peer != null) { return new Vector(((IAdvancedRobotPeer) peer).getBulletHitEvents()); } uninitializedException(); return null; // never called } /** * Returns a vector containing all BulletMissedEvents currently in the * robot's queue. You might, for example, call this while processing another * event. *

* Example: *

	 *   for (BulletMissedEvent event : getBulletMissedEvents()) {
	 *       // do something with the event
	 *   }
	 * 
* * @return a vector containing all BulletMissedEvents currently in the * robot's queue * @see #onBulletMissed(BulletMissedEvent) onBulletMissed(BulletMissedEvent) * @see BulletMissedEvent * @see #getAllEvents() */ public Vector getBulletMissedEvents() { if (peer != null) { return new Vector(((IAdvancedRobotPeer) peer).getBulletMissedEvents()); } uninitializedException(); return null; // never called } /** * Returns a file representing a data directory for the robot, which can be * written to using {@link RobocodeFileOutputStream} or * {@link RobocodeFileWriter}. *

* The system will automatically create the directory for you, so you do not * need to create it by yourself. * * @return a file representing the data directory for your robot * @see #getDataFile(String) * @see RobocodeFileOutputStream * @see RobocodeFileWriter */ public File getDataDirectory() { if (peer != null) { return ((IAdvancedRobotPeer) peer).getDataDirectory(); } uninitializedException(); return null; // never called } /** * Returns a file in your data directory that you can write to using * {@link RobocodeFileOutputStream} or {@link RobocodeFileWriter}. *

* The system will automatically create the directory for you, so you do not * need to create it by yourself. *

* Please notice that the max. size of your data file is set to 200000 * (~195 KB). *

* See the {@code sample.SittingDuck} to see an example of how to use this * method. * * @param filename the file name of the data file for your robot * @return a file representing the data file for your robot * @see #getDataDirectory() * @see RobocodeFileOutputStream * @see RobocodeFileWriter */ public File getDataFile(String filename) { if (peer != null) { return ((IAdvancedRobotPeer) peer).getDataFile(filename); } uninitializedException(); return null; // never called } /** * Returns the data quota available in your data directory, i.e. the amount * of bytes left in the data directory for the robot. * * @return the amount of bytes left in the robot's data directory * @see #getDataDirectory() * @see #getDataFile(String) */ public long getDataQuotaAvailable() { if (peer != null) { return ((IAdvancedRobotPeer) peer).getDataQuotaAvailable(); } uninitializedException(); return 0; // never called } /** * Returns the current priority of a class of events. * An event priority is a value from 0 - 99. The higher value, the higher * priority. *

* Example: *

	 *   int myHitRobotPriority = getEventPriority("HitRobotEvent");
	 * 
*

* The default priorities are, from highest to lowest: *

	 *   {@link BattleEndedEvent}:     100 (reserved)
	 *   {@link WinEvent}:             100 (reserved)
	 *   {@link SkippedTurnEvent}:     100 (reserved)
	 *   {@link StatusEvent}:           99
	 *   Key and mouse events:  98
	 *   {@link CustomEvent}:           80 (default value)
	 *   {@link MessageEvent}:          75
	 *   {@link RobotDeathEvent}:       70
	 *   {@link BulletMissedEvent}:     60
	 *   {@link BulletHitBulletEvent}:  55
	 *   {@link BulletHitEvent}:        50
	 *   {@link HitByBulletEvent}:      40
	 *   {@link HitWallEvent}:          30
	 *   {@link HitRobotEvent}:         20
	 *   {@link ScannedRobotEvent}:     10
	 *   {@link PaintEvent}:             5
	 *   {@link DeathEvent}:            -1 (reserved)
	 * 
* * @param eventClass the name of the event class (string) * @return the current priority of a class of events * @see #setEventPriority(String, int) */ public int getEventPriority(String eventClass) { if (peer != null) { return ((IAdvancedRobotPeer) peer).getEventPriority(eventClass); } uninitializedException(); return 0; // never called } /** * Returns a vector containing all HitByBulletEvents currently in the * robot's queue. You might, for example, call this while processing * another event. *

* Example: *

	 *   for (HitByBulletEvent event : getHitByBulletEvents()) {
	 *       // do something with the event
	 *   }
	 * 
* * @return a vector containing all HitByBulletEvents currently in the * robot's queue * @see #onHitByBullet(HitByBulletEvent) onHitByBullet(HitByBulletEvent) * @see HitByBulletEvent * @see #getAllEvents() */ public Vector getHitByBulletEvents() { if (peer != null) { return new Vector(((IAdvancedRobotPeer) peer).getHitByBulletEvents()); } uninitializedException(); return null; // never called } /** * Returns a vector containing all HitRobotEvents currently in the robot's * queue. You might, for example, call this while processing another event. *

* Example: *

	 *   for (HitRobotEvent event : getHitRobotEvents()) {
	 *       // do something with the event
	 *   }
	 * 
* * @return a vector containing all HitRobotEvents currently in the robot's * queue * @see #onHitRobot(HitRobotEvent) onHitRobot(HitRobotEvent) * @see HitRobotEvent * @see #getAllEvents() */ public Vector getHitRobotEvents() { if (peer != null) { return new Vector(((IAdvancedRobotPeer) peer).getHitRobotEvents()); } uninitializedException(); return null; // never called } /** * Returns a vector containing all HitWallEvents currently in the robot's * queue. You might, for example, call this while processing another event. *

* Example: *

	 *   for (HitWallEvent event : getHitWallEvents()) {
	 *       // do something with the event
	 *   }
	 * 
* * @return a vector containing all HitWallEvents currently in the robot's * queue * @see #onHitWall(HitWallEvent) onHitWall(HitWallEvent) * @see HitWallEvent * @see #getAllEvents() */ public Vector getHitWallEvents() { if (peer != null) { return new Vector(((IAdvancedRobotPeer) peer).getHitWallEvents()); } uninitializedException(); return null; // never called } /** * Returns a vector containing all RobotDeathEvents currently in the robot's * queue. You might, for example, call this while processing another event. *

* Example: *

	 *   for (RobotDeathEvent event : getRobotDeathEvents()) {
	 *       // do something with the event
	 *   }
	 * 
* * @return a vector containing all RobotDeathEvents currently in the robot's * queue * @see #onRobotDeath(RobotDeathEvent) onRobotDeath(RobotDeathEvent) * @see RobotDeathEvent * @see #getAllEvents() */ public Vector getRobotDeathEvents() { if (peer != null) { return new Vector(((IAdvancedRobotPeer) peer).getRobotDeathEvents()); } uninitializedException(); return null; // never called } /** * Returns a vector containing all ScannedRobotEvents currently in the * robot's queue. You might, for example, call this while processing another * event. *

* Example: *

	 *   for (ScannedRobotEvent event : getScannedRobotEvents()) {
	 *       // do something with the event
	 *   }
	 * 
* * @return a vector containing all ScannedRobotEvents currently in the * robot's queue * @see #onScannedRobot(ScannedRobotEvent) onScannedRobot(ScannedRobotEvent) * @see ScannedRobotEvent * @see #getAllEvents() */ public Vector getScannedRobotEvents() { if (peer != null) { return new Vector(((IAdvancedRobotPeer) peer).getScannedRobotEvents()); } uninitializedException(); return null; // never called } /** * Returns a vector containing all StatusEvents currently in the robot's * queue. You might, for example, call this while processing another event. *

* Example: *

	 *   for (StatusEvent event : getStatusEvents()) {
	 *       // do something with the event
	 *   }
	 * 
* * @return a vector containing all StatusEvents currently in the robot's queue * @see #onStatus(StatusEvent) onStatus(StatusEvent) * @see StatusEvent * @see #getAllEvents() * @since 1.6.1 */ public Vector getStatusEvents() { if (peer != null) { return new Vector(((IAdvancedRobotPeer) peer).getStatusEvents()); } uninitializedException(); return null; // never called } /** * Checks if the gun is set to adjust for the robot turning, i.e. to turn * independent from the robot's body turn. *

* This call returns {@code true} if the gun is set to turn independent of * the turn of the robot's body. Otherwise, {@code false} is returned, * meaning that the gun is set to turn with the robot's body turn. * * @return {@code true} if the gun is set to turn independent of the robot * turning; {@code false} if the gun is set to turn with the robot * turning * @see #setAdjustGunForRobotTurn(boolean) setAdjustGunForRobotTurn(boolean) * @see #isAdjustRadarForRobotTurn() * @see #isAdjustRadarForGunTurn() */ public boolean isAdjustGunForRobotTurn() { if (peer != null) { return ((IAdvancedRobotPeer) peer).isAdjustGunForBodyTurn(); } uninitializedException(); return false; // never called } /** * Checks if the radar is set to adjust for the robot turning, i.e. to turn * independent from the robot's body turn. *

* This call returns {@code true} if the radar is set to turn independent of * the turn of the robot. Otherwise, {@code false} is returned, meaning that * the radar is set to turn with the robot's turn. * * @return {@code true} if the radar is set to turn independent of the robot * turning; {@code false} if the radar is set to turn with the robot * turning * @see #setAdjustRadarForRobotTurn(boolean) setAdjustRadarForRobotTurn(boolean) * @see #isAdjustGunForRobotTurn() * @see #isAdjustRadarForGunTurn() */ public boolean isAdjustRadarForRobotTurn() { if (peer != null) { return ((IAdvancedRobotPeer) peer).isAdjustRadarForBodyTurn(); } uninitializedException(); return false; // never called } /** * Checks if the radar is set to adjust for the gun turning, i.e. to turn * independent from the gun's turn. *

* This call returns {@code true} if the radar is set to turn independent of * the turn of the gun. Otherwise, {@code false} is returned, meaning that * the radar is set to turn with the gun's turn. * * @return {@code true} if the radar is set to turn independent of the gun * turning; {@code false} if the radar is set to turn with the gun * turning * @see #setAdjustRadarForGunTurn(boolean) setAdjustRadarForGunTurn(boolean) * @see #isAdjustGunForRobotTurn() * @see #isAdjustRadarForRobotTurn() */ public boolean isAdjustRadarForGunTurn() { if (peer != null) { return ((IAdvancedRobotPeer) peer).isAdjustRadarForGunTurn(); } uninitializedException(); return false; // never called } /** * {@inheritDoc} */ public void onCustomEvent(CustomEvent event) {} /** * Sets the priority of a class of events. *

* Events are sent to the onXXX handlers in order of priority. * Higher priority events can interrupt lower priority events. * For events with the same priority, newer events are always sent first. * Valid priorities are 0 - 99, where 100 is reserved and 80 is the default * priority. *

* Example: *

	 *   setEventPriority("RobotDeathEvent", 15);
	 * 
*

* The default priorities are, from highest to lowest: *

	 * 	 {@link WinEvent}:             100 (reserved)
	 * 	 {@link SkippedTurnEvent}:     100 (reserved)
	 *   {@link StatusEvent}:           99
	 * 	 {@link CustomEvent}:           80
	 * 	 {@link MessageEvent}:          75
	 * 	 {@link RobotDeathEvent}:       70
	 * 	 {@link BulletMissedEvent}:     60
	 * 	 {@link BulletHitBulletEvent}:  55
	 * 	 {@link BulletHitEvent}:        50
	 * 	 {@link HitByBulletEvent}:      40
	 * 	 {@link HitWallEvent}:          30
	 * 	 {@link HitRobotEvent}:         20
	 * 	 {@link ScannedRobotEvent}:     10
	 *   {@link PaintEvent}:             5
	 * 	 {@link DeathEvent}:            -1 (reserved)
	 * 
*

* Note that you cannot change the priority for events with the special * priority value -1 or 100 (reserved) as these event are system events. * Also note that you cannot change the priority of CustomEvent. * Instead you must change the priority of the condition(s) for your custom * event(s). * * @param eventClass the name of the event class (string) to set the * priority for * @param priority the new priority for that event class * @see #getEventPriority(String) * @see #setInterruptible(boolean) * @since 1.5, the priority of DeathEvent was changed from 100 to -1 in * order to let robots process pending events on its event queue before * it dies. When the robot dies, it will not be able to process events. */ public void setEventPriority(String eventClass, int priority) { if (peer != null) { ((IAdvancedRobotPeer) peer).setEventPriority(eventClass, priority); } else { uninitializedException(); } } /** * Call this during an event handler to allow new events of the same * priority to restart the event handler. *

*

Example: *

	 *   public void onScannedRobot(ScannedRobotEvent e) {
	 *       fire(1);
	 *       setInterruptible(true);
	 *       ahead(100); // If you see a robot while moving ahead,
	 *                   // this handler will start from the top
	 *                   // Without setInterruptible(true), we wouldn't
	 *                   // receive scan events at all!
	 *       // We'll only get here if we don't see a robot during the move.
	 *       out.println("Ok, I can't see anyone");
	 *   }
	 * 
* * @param interruptible {@code true} if the event handler should be * interrupted if new events of the same priority occurs; {@code false} * otherwise * @see #setEventPriority(String, int) * @see Robot#onScannedRobot(ScannedRobotEvent) onScannedRobot(ScannedRobotEvent) */ @Override public void setInterruptible(boolean interruptible) { if (peer != null) { ((IAdvancedRobotPeer) peer).setInterruptible(interruptible); } else { uninitializedException(); } } /** * Sets the maximum turn rate of the robot measured in degrees if the robot * should turn slower than {@link Rules#MAX_TURN_RATE} (10 degress/turn). * * @param newMaxTurnRate the new maximum turn rate of the robot measured in * degrees. Valid values are 0 - {@link Rules#MAX_TURN_RATE} * @see #turnRight(double) turnRight(double) * @see #turnLeft(double) turnLeft(double) * @see #setTurnRight(double) * @see #setTurnLeft(double) * @see #setMaxVelocity(double) */ public void setMaxTurnRate(double newMaxTurnRate) { if (peer != null) { ((IAdvancedRobotPeer) peer).setMaxTurnRate(newMaxTurnRate); } else { uninitializedException(); } } /** * Sets the maximum velocity of the robot measured in pixels/turn if the * robot should move slower than {@link Rules#MAX_VELOCITY} (8 pixels/turn). * * @param newMaxVelocity the new maximum turn rate of the robot measured in * pixels/turn. Valid values are 0 - {@link Rules#MAX_VELOCITY} * @see #ahead(double) * @see #setAhead(double) * @see #back(double) * @see #setBack(double) * @see #setMaxTurnRate(double) */ public void setMaxVelocity(double newMaxVelocity) { if (peer != null) { ((IAdvancedRobotPeer) peer).setMaxVelocity(newMaxVelocity); } else { uninitializedException(); } } /** * Sets the robot to resume the movement stopped by {@link #stop() stop()} * or {@link #setStop()}, if any. *

* This call returns immediately, and will not execute until you call * {@link #execute()} or take an action that executes. * * @see #resume() resume() * @see #stop() stop() * @see #stop(boolean) stop(boolean) * @see #setStop() * @see #setStop(boolean) * @see #execute() */ public void setResume() { if (peer != null) { ((IAdvancedRobotPeer) peer).setResume(); } else { uninitializedException(); } } /** * This call is identical to {@link #stop() stop()}, but returns immediately, and * will not execute until you call {@link #execute()} or take an action that * executes. *

* If there is already movement saved from a previous stop, this will have * no effect. *

* This call is equivalent to calling {@code setStop(false)}; * * @see #stop() stop() * @see #stop(boolean) stop(boolean) * @see #resume() resume() * @see #setResume() * @see #setStop(boolean) * @see #execute() */ public void setStop() { setStop(false); } /** * This call is identical to {@link #stop(boolean) stop(boolean)}, but * returns immediately, and will not execute until you call * {@link #execute()} or take an action that executes. *

* If there is already movement saved from a previous stop, you can * overwrite it by calling {@code setStop(true)}. * * @param overwrite {@code true} if the movement saved from a previous stop * should be overwritten; {@code false} otherwise. * @see #stop() stop() * @see #stop(boolean) stop(boolean) * @see #resume() resume() * @see #setResume() * @see #setStop() * @see #execute() */ public void setStop(boolean overwrite) { if (peer != null) { ((IAdvancedRobotPeer) peer).setStop(overwrite); } else { uninitializedException(); } } /** * Sets the robot's gun to turn left by degrees when the next execution * takes place. *

* This call returns immediately, and will not execute until you call * execute() or take an action that executes. *

* Note that both positive and negative values can be given as input, * where negative values means that the robot's gun is set to turn right * instead of left. *

* Example: *

	 *   // Set the gun to turn 180 degrees to the left
	 *   setTurnGunLeft(180);
	 * 

* // Set the gun to turn 90 degrees to the right instead of left * // (overrides the previous order) * setTurnGunLeft(-90); *

* ... * // Executes the last setTurnGunLeft() * execute(); *

* * @param degrees the amount of degrees to turn the robot's gun to the left. * If {@code degrees} > 0 the robot's gun is set to turn left. * If {@code degrees} < 0 the robot's gun is set to turn right. * If {@code degrees} = 0 the robot's gun is set to stop turning. * @see #setTurnGunLeftRadians(double) setTurnGunLeftRadians(double) * @see #turnGunLeft(double) turnGunLeft(double) * @see #turnGunLeftRadians(double) turnGunLeftRadians(double) * @see #turnGunRight(double) turnGunRight(double) * @see #turnGunRightRadians(double) turnGunRightRadians(double) * @see #setTurnGunRight(double) setTurnGunRight(double) * @see #setTurnGunRightRadians(double) setTurnGunRightRadians(double) * @see #setAdjustGunForRobotTurn(boolean) setAdjustGunForRobotTurn(boolean) */ public void setTurnGunLeft(double degrees) { if (peer != null) { ((IAdvancedRobotPeer) peer).setTurnGun(-Math.toRadians(degrees)); } else { uninitializedException(); } } /** * Sets the robot's gun to turn right by degrees when the next execution * takes place. *

* This call returns immediately, and will not execute until you call * execute() or take an action that executes. *

* Note that both positive and negative values can be given as input, * where negative values means that the robot's gun is set to turn left * instead of right. *

* Example: *

	 *   // Set the gun to turn 180 degrees to the right
	 *   setTurnGunRight(180);
	 * 

* // Set the gun to turn 90 degrees to the left instead of right * // (overrides the previous order) * setTurnGunRight(-90); *

* ... * // Executes the last setTurnGunRight() * execute(); *

* * @param degrees the amount of degrees to turn the robot's gun to the right. * If {@code degrees} > 0 the robot's gun is set to turn right. * If {@code degrees} < 0 the robot's gun is set to turn left. * If {@code degrees} = 0 the robot's gun is set to stop turning. * @see #setTurnGunRightRadians(double) setTurnGunRightRadians(double) * @see #turnGunRight(double) turnGunRight(double) * @see #turnGunRightRadians(double) turnGunRightRadians(double) * @see #turnGunLeft(double) turnGunLeft(double) * @see #turnGunLeftRadians(double) turnGunLeftRadians(double) * @see #setTurnGunLeft(double) setTurnGunLeft(double) * @see #setTurnGunLeftRadians(double) setTurnGunLeftRadians(double) * @see #setAdjustGunForRobotTurn(boolean) setAdjustGunForRobotTurn(boolean) */ public void setTurnGunRight(double degrees) { if (peer != null) { ((IAdvancedRobotPeer) peer).setTurnGun(Math.toRadians(degrees)); } else { uninitializedException(); } } /** * Sets the robot's radar to turn left by degrees when the next execution * takes place. *

* This call returns immediately, and will not execute until you call * execute() or take an action that executes. *

* Note that both positive and negative values can be given as input, * where negative values means that the robot's radar is set to turn right * instead of left. *

* Example: *

	 *   // Set the radar to turn 180 degrees to the left
	 *   setTurnRadarLeft(180);
	 * 

* // Set the radar to turn 90 degrees to the right instead of left * // (overrides the previous order) * setTurnRadarLeft(-90); *

* ... * // Executes the last setTurnRadarLeft() * execute(); *

* * @param degrees the amount of degrees to turn the robot's radar to the left. * If {@code degrees} > 0 the robot's radar is set to turn left. * If {@code degrees} < 0 the robot's radar is set to turn right. * If {@code degrees} = 0 the robot's radar is set to stop turning. * @see #setTurnRadarLeftRadians(double) setTurnRadarLeftRadians(double) * @see #turnRadarLeft(double) turnRadarLeft(double) * @see #turnRadarLeftRadians(double) turnRadarLeftRadians(double) * @see #turnRadarRight(double) turnRadarRight(double) * @see #turnRadarRightRadians(double) turnRadarRightRadians(double) * @see #setTurnRadarRight(double) setTurnRadarRight(double) * @see #setTurnRadarRightRadians(double) setTurnRadarRightRadians(double) * @see #setAdjustRadarForRobotTurn(boolean) setAdjustRadarForRobotTurn(boolean) * @see #setAdjustRadarForGunTurn(boolean) setAdjustRadarForGunTurn(boolean) */ public void setTurnRadarLeft(double degrees) { if (peer != null) { ((IAdvancedRobotPeer) peer).setTurnRadar(-Math.toRadians(degrees)); } else { uninitializedException(); } } /** * Sets the robot's radar to turn right by degrees when the next execution * takes place. *

* This call returns immediately, and will not execute until you call * execute() or take an action that executes. *

* Note that both positive and negative values can be given as input, * where negative values means that the robot's radar is set to turn left * instead of right. *

* Example: *

	 *   // Set the radar to turn 180 degrees to the right
	 *   setTurnRadarRight(180);
	 * 

* // Set the radar to turn 90 degrees to the right instead of right * // (overrides the previous order) * setTurnRadarRight(-90); *

* ... * // Executes the last setTurnRadarRight() * execute(); *

* * @param degrees the amount of degrees to turn the robot's radar to the right. * If {@code degrees} > 0 the robot's radar is set to turn right. * If {@code degrees} < 0 the robot's radar is set to turn left. * If {@code degrees} = 0 the robot's radar is set to stop turning. * @see #setTurnRadarRightRadians(double) setTurnRadarRightRadians(double) * @see #turnRadarRight(double) turnRadarRight(double) * @see #turnRadarRightRadians(double) turnRadarRightRadians(double) * @see #turnRadarLeft(double) turnRadarLeft(double) * @see #turnRadarLeftRadians(double) turnRadarLeftRadians(double) * @see #setTurnRadarLeft(double) setTurnRadarLeft(double) * @see #setTurnRadarLeftRadians(double) setTurnRadarLeftRadians(double) * @see #setAdjustRadarForRobotTurn(boolean) setAdjustRadarForRobotTurn(boolean) * @see #setAdjustRadarForGunTurn(boolean) setAdjustRadarForGunTurn(boolean) */ public void setTurnRadarRight(double degrees) { if (peer != null) { ((IAdvancedRobotPeer) peer).setTurnRadar(Math.toRadians(degrees)); } else { uninitializedException(); } } /** * Does not return until a condition is met, i.e. when a * {@link Condition#test()} returns {@code true}. *

* This call executes immediately. *

* See the {@code sample.Crazy} robot for how this method can be used. * * @param condition the condition that must be met before this call returns * @see Condition * @see Condition#test() */ public void waitFor(Condition condition) { if (peer != null) { ((IAdvancedRobotPeer) peer).waitFor(condition); } else { uninitializedException(); } } /** * This method is called if your robot dies. *

* You should override it in your robot if you want to be informed of this * event. Actions will have no effect if called from this section. The * intent is to allow you to perform calculations or print something out * when the robot is killed. * * @param event the death event set by the game * @see DeathEvent * @see Event */ @Override public void onDeath(DeathEvent event) {} /** * {@inheritDoc} */ public void onSkippedTurn(SkippedTurnEvent event) {} /** * Returns the direction that the robot's body is facing, in radians. * The value returned will be between 0 and 2 * PI (is excluded). *

* Note that the heading in Robocode is like a compass, where 0 means North, * PI / 2 means East, PI means South, and 3 * PI / 4 means West. * * @return the direction that the robot's body is facing, in radians. * @see #getHeadingDegrees() * @see #getGunHeadingRadians() * @see #getRadarHeadingRadians() */ public double getHeadingRadians() { return super.getHeadingRadians(); } /** * Sets the robot's body to turn left by radians when the next execution * takes place. *

* This call returns immediately, and will not execute until you call * execute() or take an action that executes. *

* Note that both positive and negative values can be given as input, * where negative values means that the robot's body is set to turn right * instead of left. *

* Example: *

	 *   // Set the robot to turn 180 degrees to the left
	 *   setTurnLeftRadians(Math.PI);
	 * 

* // Set the robot to turn 90 degrees to the right instead of left * // (overrides the previous order) * setTurnLeftRadians(-Math.PI / 2); *

* ... * // Executes the last setTurnLeftRadians() * execute(); *

* * @param radians the amount of radians to turn the robot's body to the left. * If {@code radians} > 0 the robot is set to turn left. * If {@code radians} < 0 the robot is set to turn right. * If {@code radians} = 0 the robot is set to stop turning. * @see AdvancedRobot#setTurnLeft(double) setTurnLeft(double) * @see #turnLeft(double) * @see #turnLeftRadians(double) * @see #turnRight(double) * @see #turnRightRadians(double) * @see AdvancedRobot#setTurnRight(double) setTurnRight(double) * @see AdvancedRobot#setTurnRightRadians(double) setTurnRightRadians(double) */ public void setTurnLeftRadians(double radians) { super.setTurnLeftRadians(radians); } /** * Sets the robot's body to turn right by radians when the next execution * takes place. *

* This call returns immediately, and will not execute until you call * execute() or take an action that executes. *

* Note that both positive and negative values can be given as input, * where negative values means that the robot's body is set to turn left * instead of right. *

* Example: *

	 *   // Set the robot to turn 180 degrees to the right
	 *   setTurnRightRadians(Math.PI);
	 * 

* // Set the robot to turn 90 degrees to the left instead of right * // (overrides the previous order) * setTurnRightRadians(-Math.PI / 2); *

* ... * // Executes the last setTurnRightRadians() * execute(); *

* * @param radians the amount of radians to turn the robot's body to the right. * If {@code radians} > 0 the robot is set to turn right. * If {@code radians} < 0 the robot is set to turn left. * If {@code radians} = 0 the robot is set to stop turning. * @see AdvancedRobot#setTurnRight(double) setTurnRight(double) * @see #turnRight(double) * @see #turnRightRadians(double) * @see #turnLeft(double) * @see #turnLeftRadians(double) * @see AdvancedRobot#setTurnLeft(double) setTurnLeft(double) * @see AdvancedRobot#setTurnLeftRadians(double) setTurnLeftRadians(double) */ public void setTurnRightRadians(double radians) { super.setTurnRightRadians(radians); } /** * Immediately turns the robot's body to the left by radians. *

* This call executes immediately, and does not return until it is complete, * i.e. when the angle remaining in the robot's turn is 0. *

* Note that both positive and negative values can be given as input, * where negative values means that the robot's body is set to turn right * instead of left. *

* Example: *

	 *   // Turn the robot 180 degrees to the left
	 *   turnLeftRadians(Math.PI);
	 * 

* // Afterwards, turn the robot 90 degrees to the right * turnLeftRadians(-Math.PI / 2); *

* * @param radians the amount of radians to turn the robot's body to the left. * If {@code radians} > 0 the robot will turn right. * If {@code radians} < 0 the robot will turn left. * If {@code radians} = 0 the robot will not turn, but execute. * @see #turnLeft(double) * @see #turnRight(double) * @see #turnRightRadians(double) * @see #turnGunLeft(double) * @see #turnGunLeftRadians(double) * @see #turnGunRight(double) * @see #turnGunRightRadians(double) * @see #turnRadarLeft(double) * @see #turnRadarLeftRadians(double) * @see #turnRadarRight(double) * @see #turnRadarRightRadians(double) * @see #setAdjustGunForRobotTurn(boolean) */ public void turnLeftRadians(double radians) { super.turnLeftRadians(radians); } /** * Immediately turns the robot's body to the right by radians. * This call executes immediately, and does not return until it is complete, * i.e. when the angle remaining in the robot's turn is 0. *

* Note that both positive and negative values can be given as input, * where negative values means that the robot's body is set to turn left * instead of right. *

* Example: *

	 *   // Turn the robot 180 degrees to the right
	 *   turnRightRadians(Math.PI);
	 * 

* // Afterwards, turn the robot 90 degrees to the left * turnRightRadians(-Math.PI / 2); *

* * @param radians the amount of radians to turn the robot's body to the right. * If {@code radians} > 0 the robot will turn right. * If {@code radians} < 0 the robot will turn left. * If {@code radians} = 0 the robot will not turn, but execute. * @see #turnRight(double) * @see #turnLeft(double) * @see #turnLeftRadians(double) * @see #turnGunLeft(double) * @see #turnGunLeftRadians(double) * @see #turnGunRight(double) * @see #turnGunRightRadians(double) * @see #turnRadarLeft(double) * @see #turnRadarLeftRadians(double) * @see #turnRadarRight(double) * @see #turnRadarRightRadians(double) * @see #setAdjustGunForRobotTurn(boolean) */ public void turnRightRadians(double radians) { super.turnRightRadians(radians); } /** * Returns the direction that the robot's gun is facing, in radians. * The value returned will be between 0 and 2 * PI (is excluded). *

* Note that the heading in Robocode is like a compass, where 0 means North, * PI / 2 means East, PI means South, and 3 * PI / 4 means West. * * @return the direction that the robot's gun is facing, in radians. * @see #getGunHeadingDegrees() * @see #getHeadingRadians() * @see #getRadarHeadingRadians() */ public double getGunHeadingRadians() { return super.getGunHeadingRadians(); } /** * Returns the direction that the robot's radar is facing, in radians. * The value returned will be between 0 and 2 * PI (is excluded). *

* Note that the heading in Robocode is like a compass, where 0 means North, * PI / 2 means East, PI means South, and 3 * PI / 4 means West. * * @return the direction that the robot's radar is facing, in radians. * @see #getRadarHeadingDegrees() * @see #getHeadingRadians() * @see #getGunHeadingRadians() */ public double getRadarHeadingRadians() { return super.getRadarHeadingRadians(); } /** * Sets the robot's gun to turn left by radians when the next execution * takes place. *

* This call returns immediately, and will not execute until you call * execute() or take an action that executes. *

* Note that both positive and negative values can be given as input, * where negative values means that the robot's gun is set to turn right * instead of left. *

* Example: *

	 *   // Set the gun to turn 180 degrees to the left
	 *   setTurnGunLeftRadians(Math.PI);
	 * 

* // Set the gun to turn 90 degrees to the right instead of left * // (overrides the previous order) * setTurnGunLeftRadians(-Math.PI / 2); *

* ... * // Executes the last setTurnGunLeftRadians() * execute(); *

* * @param radians the amount of radians to turn the robot's gun to the left. * If {@code radians} > 0 the robot's gun is set to turn left. * If {@code radians} < 0 the robot's gun is set to turn right. * If {@code radians} = 0 the robot's gun is set to stop turning. * @see AdvancedRobot#setTurnGunLeft(double) setTurnGunLeft(double) * @see #turnGunLeft(double) * @see #turnGunLeftRadians(double) * @see #turnGunRight(double) * @see #turnGunRightRadians(double) * @see AdvancedRobot#setTurnGunRight(double) setTurnGunRight(double) * @see AdvancedRobot#setTurnGunRightRadians(double) setTurnGunRightRadians(double) * @see #setAdjustGunForRobotTurn(boolean) */ public void setTurnGunLeftRadians(double radians) { super.setTurnGunLeftRadians(radians); } /** * Sets the robot's gun to turn right by radians when the next execution * takes place. *

* This call returns immediately, and will not execute until you call * execute() or take an action that executes. *

* Note that both positive and negative values can be given as input, * where negative values means that the robot's gun is set to turn left * instead of right. *

* Example: *

	 *   // Set the gun to turn 180 degrees to the right
	 *   setTurnGunRightRadians(Math.PI);
	 * 

* // Set the gun to turn 90 degrees to the left instead of right * // (overrides the previous order) * setTurnGunRightRadians(-Math.PI / 2); *

* ... * // Executes the last setTurnGunRightRadians() * execute(); *

* * @param radians the amount of radians to turn the robot's gun to the right. * If {@code radians} > 0 the robot's gun is set to turn left. * If {@code radians} < 0 the robot's gun is set to turn right. * If {@code radians} = 0 the robot's gun is set to stop turning. * @see AdvancedRobot#setTurnGunRight(double) setTurnGunRight(double) * @see #turnGunRight(double) * @see #turnGunRightRadians(double) * @see #turnGunLeft(double) * @see #turnGunLeftRadians(double) * @see AdvancedRobot#setTurnGunLeft(double) setTurnGunLeft(double) * @see AdvancedRobot#setTurnGunLeftRadians(double) setTurnGunLeftRadians(double) * @see #setAdjustGunForRobotTurn(boolean) */ public void setTurnGunRightRadians(double radians) { super.setTurnGunRightRadians(radians); } /** * Sets the robot's radar to turn left by radians when the next execution * takes place. *

* This call returns immediately, and will not execute until you call * execute() or take an action that executes. *

* Note that both positive and negative values can be given as input, * where negative values means that the robot's radar is set to turn right * instead of left. *

* Example: *

	 *   // Set the radar to turn 180 degrees to the left
	 *   setTurnRadarLeftRadians(Math.PI);
	 * 

* // Set the radar to turn 90 degrees to the right instead of left * // (overrides the previous order) * setTurnRadarLeftRadians(-Math.PI / 2); *

* ... * // Executes the last setTurnRadarLeftRadians() * execute(); *

* * @param radians the amount of radians to turn the robot's radar to the left. * If {@code radians} > 0 the robot's radar is set to turn left. * If {@code radians} < 0 the robot's radar is set to turn right. * If {@code radians} = 0 the robot's radar is set to stop turning. * @see AdvancedRobot#setTurnRadarLeft(double) setTurnRadarLeft(double) * @see #turnRadarLeft(double) * @see #turnRadarLeftRadians(double) * @see #turnRadarRight(double) * @see #turnRadarRightRadians(double) * @see AdvancedRobot#setTurnRadarRight(double) setTurnRadarRight(double) * @see AdvancedRobot#setTurnRadarRightRadians(double) setTurnRadarRightRadians(double) * @see #setAdjustRadarForRobotTurn(boolean) * @see #setAdjustRadarForGunTurn(boolean) */ public void setTurnRadarLeftRadians(double radians) { super.setTurnRadarLeftRadians(radians); } /** * Sets the robot's radar to turn right by radians when the next execution * takes place. *

* This call returns immediately, and will not execute until you call * execute() or take an action that executes. *

* Note that both positive and negative values can be given as input, * where negative values means that the robot's radar is set to turn left * instead of right. *

* Example: *

	 *   // Set the radar to turn 180 degrees to the right
	 *   setTurnRadarRightRadians(Math.PI);
	 * 

* // Set the radar to turn 90 degrees to the right instead of right * // (overrides the previous order) * setTurnRadarRightRadians(-Math.PI / 2); *

* ... * // Executes the last setTurnRadarRightRadians() * execute(); *

* * @param radians the amount of radians to turn the robot's radar to the right. * If {@code radians} > 0 the robot's radar is set to turn left. * If {@code radians} < 0 the robot's radar is set to turn right. * If {@code radians} = 0 the robot's radar is set to stop turning. * @see AdvancedRobot#setTurnRadarRight(double) setTurnRadarRight(double) * @see #turnRadarRight(double) * @see #turnRadarRightRadians(double) * @see #turnRadarLeft(double) * @see #turnRadarLeftRadians(double) * @see AdvancedRobot#setTurnRadarLeft(double) setTurnRadarLeft(double) * @see AdvancedRobot#setTurnRadarLeftRadians(double) setTurnRadarLeftRadians(double) * @see #setAdjustRadarForRobotTurn(boolean) * @see #setAdjustRadarForGunTurn(boolean) */ public void setTurnRadarRightRadians(double radians) { super.setTurnRadarRightRadians(radians); } /** * Immediately turns the robot's gun to the left by radians. *

* This call executes immediately, and does not return until it is complete, * i.e. when the angle remaining in the gun's turn is 0. *

* Note that both positive and negative values can be given as input, * where negative values means that the robot's gun is set to turn right * instead of left. *

* Example: *

	 *   // Turn the robot's gun 180 degrees to the left
	 *   turnGunLeftRadians(Math.PI);
	 * 

* // Afterwards, turn the robot's gun 90 degrees to the right * turnGunLeftRadians(-Math.PI / 2); *

* * @param radians the amount of radians to turn the robot's gun to the left. * If {@code radians} > 0 the robot's gun will turn left. * If {@code radians} < 0 the robot's gun will turn right. * If {@code radians} = 0 the robot's gun will not turn, but execute. * @see #turnGunLeft(double) * @see #turnGunRight(double) * @see #turnGunRightRadians(double) * @see #turnLeft(double) * @see #turnLeftRadians(double) * @see #turnRight(double) * @see #turnRightRadians(double) * @see #turnRadarLeft(double) * @see #turnRadarLeftRadians(double) * @see #turnRadarRight(double) * @see #turnRadarRightRadians(double) * @see #setAdjustGunForRobotTurn(boolean) */ public void turnGunLeftRadians(double radians) { super.turnGunLeftRadians(radians); } /** * Immediately turns the robot's gun to the right by radians. * This call executes immediately, and does not return until it is complete, * i.e. when the angle remaining in the gun's turn is 0. *

* Note that both positive and negative values can be given as input, * where negative values means that the robot's gun is set to turn left * instead of right. *

* Example: *

	 *   // Turn the robot's gun 180 degrees to the right
	 *   turnGunRightRadians(Math.PI);
	 * 

* // Afterwards, turn the robot's gun 90 degrees to the left * turnGunRightRadians(-Math.PI / 2); *

* * @param radians the amount of radians to turn the robot's gun to the right. * If {@code radians} > 0 the robot's gun will turn right. * If {@code radians} < 0 the robot's gun will turn left. * If {@code radians} = 0 the robot's gun will not turn, but execute. * @see #turnGunRight(double) * @see #turnGunLeft(double) * @see #turnGunLeftRadians(double) * @see #turnLeft(double) * @see #turnLeftRadians(double) * @see #turnRight(double) * @see #turnRightRadians(double) * @see #turnRadarLeft(double) * @see #turnRadarLeftRadians(double) * @see #turnRadarRight(double) * @see #turnRadarRightRadians(double) * @see #setAdjustGunForRobotTurn(boolean) */ public void turnGunRightRadians(double radians) { super.turnGunRightRadians(radians); } /** * Immediately turns the robot's radar to the left by radians. *

* This call executes immediately, and does not return until it is complete, * i.e. when the angle remaining in the radar's turn is 0. *

* Note that both positive and negative values can be given as input, * where negative values means that the robot's radar is set to turn right * instead of left. *

* Example: *

	 *   // Turn the robot's radar 180 degrees to the left
	 *   turnRadarLeftRadians(Math.PI);
	 * 

* // Afterwards, turn the robot's radar 90 degrees to the right * turnRadarLeftRadians(-Math.PI / 2); *

* * @param radians the amount of radians to turn the robot's radar to the left. * If {@code radians} > 0 the robot's radar will turn left. * If {@code radians} < 0 the robot's radar will turn right. * If {@code radians} = 0 the robot's radar will not turn, but execute. * @see #turnRadarLeft(double) * @see #turnRadarRight(double) * @see #turnGunRightRadians(double) * @see #turnLeft(double) * @see #turnLeftRadians(double) * @see #turnRight(double) * @see #turnRightRadians(double) * @see #turnGunLeft(double) * @see #turnGunLeftRadians(double) * @see #turnGunRight(double) * @see #turnGunRightRadians(double) * @see #setAdjustRadarForRobotTurn(boolean) * @see #setAdjustRadarForGunTurn(boolean) */ public void turnRadarLeftRadians(double radians) { super.turnRadarLeftRadians(radians); } /** * Immediately turns the robot's radar to the right by radians. * This call executes immediately, and does not return until it is complete, * i.e. when the angle remaining in the radar's turn is 0. *

* Note that both positive and negative values can be given as input, * where negative values means that the robot's radar is set to turn left * instead of right. *

* Example: *

	 *   // Turn the robot's radar 180 degrees to the right
	 *   turnRadarRightRadians(Math.PI);
	 * 

* // Afterwards, turn the robot's radar 90 degrees to the left * turnRadarRightRadians(-Math.PI / 2); *

* * @param radians the amount of radians to turn the robot's radar to the right. * If {@code radians} > 0 the robot's radar will turn right. * If {@code radians} < 0 the robot's radar will turn left. * If {@code radians} = 0 the robot's radar will not turn, but execute. * @see #turnRadarRight(double) * @see #turnRadarLeft(double) * @see #turnGunLeftRadians(double) * @see #turnLeft(double) * @see #turnLeftRadians(double) * @see #turnRight(double) * @see #turnRightRadians(double) * @see #turnGunLeft(double) * @see #turnGunLeftRadians(double) * @see #turnGunRight(double) * @see #turnGunRightRadians(double) * @see #setAdjustRadarForRobotTurn(boolean) * @see #setAdjustRadarForGunTurn(boolean) */ public void turnRadarRightRadians(double radians) { super.turnRadarRightRadians(radians); } /** * Returns the angle remaining in the gun's turn, in radians. *

* This call returns both positive and negative values. Positive values * means that the gun is currently turning to the right. Negative values * means that the gun is currently turning to the left. * * @return the angle remaining in the gun's turn, in radians * @see AdvancedRobot#getGunTurnRemaining() * @see AdvancedRobot#getTurnRemaining() getTurnRemaining() * @see #getTurnRemainingRadians() * @see AdvancedRobot#getRadarTurnRemaining() getRadarTurnRemaining() * @see #getRadarTurnRemainingRadians() */ public double getGunTurnRemainingRadians() { return super.getGunTurnRemainingRadians(); } /** * Returns the angle remaining in the radar's turn, in radians. *

* This call returns both positive and negative values. Positive values * means that the radar is currently turning to the right. Negative values * means that the radar is currently turning to the left. * * @return the angle remaining in the radar's turn, in radians * @see AdvancedRobot#getRadarTurnRemaining() * @see AdvancedRobot#getTurnRemaining() getTurnRemaining() * @see #getTurnRemainingRadians() * @see AdvancedRobot#getGunTurnRemaining() getGunTurnRemaining() * @see #getGunTurnRemainingRadians() */ public double getRadarTurnRemainingRadians() { return super.getRadarTurnRemainingRadians(); } /** * Returns the angle remaining in the robot's turn, in radians. *

* This call returns both positive and negative values. Positive values * means that the robot is currently turning to the right. Negative values * means that the robot is currently turning to the left. * * @return the angle remaining in the robot's turn, in radians * @see AdvancedRobot#getTurnRemaining() * @see AdvancedRobot#getGunTurnRemaining() getGunTurnRemaining() * @see #getGunTurnRemainingRadians() * @see AdvancedRobot#getRadarTurnRemaining() getRadarTurnRemaining() * @see #getRadarTurnRemainingRadians() */ public double getTurnRemainingRadians() { return super.getTurnRemainingRadians(); } /** * Do not call this method! *

* {@inheritDoc} */ public final IAdvancedEvents getAdvancedEventListener() { return this; // this robot is listening } } robocode/robocode/.settings/0000755000175000017500000000000011061320772015355 5ustar lambylambyrobocode/robocode/.settings/org.eclipse.jdt.core.prefs0000644000175000017500000000116611052373226022345 0ustar lambylamby#Sun Jul 06 13:24:58 CEST 2008 eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.5 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.source=1.5 robocode/robocode/.settings/org.eclipse.jdt.ui.prefs0000644000175000017500000000501410563463106022031 0ustar lambylamby#Sun Feb 11 00:41:01 CET 2007 cleanup.add_default_serial_version_id=true cleanup.add_generated_serial_version_id=false cleanup.add_missing_annotations=true cleanup.add_missing_deprecated_annotations=true cleanup.add_missing_nls_tags=false cleanup.add_missing_override_annotations=true cleanup.add_serial_version_id=false cleanup.always_use_blocks=true cleanup.always_use_parentheses_in_expressions=false cleanup.always_use_this_for_non_static_field_access=false cleanup.always_use_this_for_non_static_method_access=false cleanup.convert_to_enhanced_for_loop=true cleanup.format_source_code=false cleanup.make_local_variable_final=true cleanup.make_parameters_final=false cleanup.make_private_fields_final=true cleanup.make_variable_declarations_final=false cleanup.never_use_blocks=false cleanup.never_use_parentheses_in_expressions=true cleanup.organize_imports=true cleanup.qualify_static_field_accesses_with_declaring_class=false cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true cleanup.qualify_static_member_accesses_with_declaring_class=true cleanup.qualify_static_method_accesses_with_declaring_class=false cleanup.remove_private_constructors=true cleanup.remove_trailing_whitespaces=true cleanup.remove_trailing_whitespaces_all=true cleanup.remove_trailing_whitespaces_ignore_empty=false cleanup.remove_unnecessary_casts=true cleanup.remove_unnecessary_nls_tags=true cleanup.remove_unused_imports=true cleanup.remove_unused_local_variables=true cleanup.remove_unused_private_fields=true cleanup.remove_unused_private_members=true cleanup.remove_unused_private_methods=true cleanup.remove_unused_private_types=true cleanup.sort_members=false cleanup.sort_members_all=false cleanup.use_blocks=true cleanup.use_blocks_only_for_return_and_throw=false cleanup.use_parentheses_in_expressions=false cleanup.use_this_for_non_static_field_access=false cleanup.use_this_for_non_static_field_access_only_if_necessary=true cleanup.use_this_for_non_static_method_access=false cleanup.use_this_for_non_static_method_access_only_if_necessary=true cleanup_profile=_Robocode cleanup_settings_version=2 eclipse.preferences.version=1 org.eclipse.jdt.ui.ignorelowercasenames=true org.eclipse.jdt.ui.importorder=java;javax;org;com; org.eclipse.jdt.ui.ondemandthreshold=5 org.eclipse.jdt.ui.staticondemandthreshold=5 org.eclipse.jdt.ui.text.custom_code_templates= robocode/tools/0000755000175000017500000000000011052312542012777 5ustar lambylambyrobocode/tools/.project0000644000175000017500000000026411052312542014450 0ustar lambylamby tools robocode/tools/Jacobe/0000755000175000017500000000000011124141230014154 5ustar lambylambyrobocode/tools/Jacobe/build.xml0000644000175000017500000000213511101447336016011 0ustar lambylamby Apache Ant build script for code beautifying Robocode sources robocode/tools/Jacobe/robocode.cfg0000644000175000017500000001354611124141230016442 0ustar lambylamby// Jacobe configuration file for the Sun code conventions for Java // $Id: sun.cfg,v 1.94 2006/05/31 09:29:01 stappers Exp $ // reference: http://java.sun.com/docs/codeconv/ // (c) 2000-2006 Tiobe Software BV -- All rights reserved // support@jacobe.com, www.jacobe.com, Eindhoven, The Netherlands // INDENTATION // ----------- //--indent=4 --indenttab=1 --tablen=4 //--unindentjumplabel // LINE LENGTH // ----------- --wrap=120 // WRAPPING LINES // -------------- //--wrapinfixoplineterm=1 --wraplineterminfixop=1 --indentcontinuation=2 //--continuationindent=4 //--wraplinetermcomma=1 --wrapcommalineterm=1 --wraparrayinitopenbracelineterm=1 --wrapmethodcallopenparenlineterm=1 //--wrapassoplineterm=1 // COMMENTS // -------- --opencommentspace=1 //--opencommentlineterm=1 --indentcomment=1 //--commentstarspace=1 // JAVADOC // ------- // The rules below are only available in Jacobe Professional --javadocstartlineterm=1 --linetermendjavadoc=1 --javadocdescr --javadocdescrlineterm=2 --javadocauthor --javadocauthorlineterm=1 --javadocversion --javadocversionlineterm=2 --javadocparam --javadocparamorder --javadocparamlineterm=1 --javadocreturn --javadocreturnlineterm=1 --javadocthrows --javadocthrowsorder --javadocthrowslineterm=1 --javadocorder --javadoctagspacearg=1 // DECLARATIONS AND STATEMENTS // --------------------------- --colonlineterm=1 --spaceopenbrace=1 --closebracelineterm=1 --openbracespace=1 --openbracespaceclosebrace=0 --openbracelinetermclosebrace=0 --openparenspacecloseparen=0 --linetermopenbracket=0 --indentbraces=0 --indentblock=1 //--dimopenbracketspace=0 //--dimspaceclosebracket=0 //--indexopenbracketspace=0 //--indexspaceclosebracket=0 --openbracketspaceclosebracket=0 // DECLARATIONS // ------------ --decllineterm=1 --modifierslineterm=0 --modifiersspace=1 //--typespace=1 --classspace=1 --classlineterm=0 --classlinetermopenbrace=0 --classopenbracelineterm=1 --classlinetermclosebrace=1 --spaceextends=1 --extendsspace=1 --linetermextends=0 --extendslineterm=0 //--linetermimplements=0 //--implementslineterm=0 //--linetermthrows=0 --methodlinetermopenbrace=0 --methodopenbracelineterm=1 --methodlinetermclosebrace=1 //--arrayinitlinetermopenbrace=0 //--arrayinitopenbracelineterm=0 //--arrayinitlinetermclosebrace=0 //--arrayinitclosebracelineterm=0 //--arrayinitopenbracespace=0 //--arrayinitspaceclosebrace=0 --returntypelineterm=0 //--typelineterm=0 //--paramtypelineterm=0 //--fortypelineterm=0 //--declarraytoarraytype //--linetermclass=1 //--linetermconstructor=1 --closebracelinetermopenbrace=1 --importlineterm=0 --modifierlineterm=0 //--seplineterm=0 //--paramopenparenlineterm=0 //--paramlinetermcloseparen=0 //--paramlinetermopenparen=0 //--paramcloseparenlineterm=0 //--paramspaceopenparen=0 --enumcommalineterm=1 // SIMPLE STATEMENTS // ----------------- --statlineterm=1 --methodcallspaceopenparen=0 --methodcalllinetermopenparen=0 --dotlineterm=0 --linetermdot=0 --linetermsep=0 --lineterminfixop=0 --infixoplineterm=0 --prefixoplineterm=0 --linetermpostfixop=0 --linetermcomma=0 --commalineterm=0 --openparenlineterm=0 --linetermcloseparen=0 --assoplineterm=0 --linetermassop=0 // COMPOUND STATEMENTS // ------------------- --blocklinetermopenbrace=0 --blockopenbracelineterm=1 --blocklinetermclosebrace=1 --insertbraces --blockstatlinetermopenbrace=0 // IF STATEMENTS // ------------- --spaceelse=1 --closebracelinetermelse=0 //--semicolonlinetermelse=1 --elselinetermif=0 // FOR STATEMENTS // -------------- --forstatlineterm=0 // DO-WHILE STATEMENTS // ------------------- --closebracelinetermdowhile=0 --semicolonlinetermdowhile=1 // SWITCH STATEMENTS // ----------------- --blanklinescase=1 --indentcase=0 //--insertbracescasestats // TRY-CATCH STATEMENTS // -------------------- --spacecatch=1 --linetermcatch=0 --spacefinally=1 --linetermfinally=0 // WHITE SPACE // ----------- //--lineterm // BLANK LINES // ----------- //--blanklinescompilationunit=0 --methodblanklines=1 --declblanklinesstat=1 --statblanklinesdecl=0 --blanklinescomment=1 --sectionblanklines=2 --classblanklines=2 //--enumconstantblanklinesdecl=1 // SPACES // ------ //--keywordspace=1 --keywordspaceopenparen=1 --keywordlinetermopenparen=0 --methodnamespace=0 --spacecomma=0 --commaspace=1 --spacesemicolon=0 --semicolonspace=1 --spacecolon=0 --colonspace=1 --assignspace=1 --spaceassign=1 --dotspace=0 --spacedot=0 --prefixopspace=0 --infixopspace=1 --spaceinfixop=1 --spacepostfixop=0 --spaceopenbracket=0 --castspace=1 --castopenparenspace=0 --castspacecloseparen=0 //--castopenparenlineterm=0 //--castlinetermcloseparen=0 //--castlinetermopenparen=0 //--castcloseparenlineterm=0 //--castspaceopenparen=0 //--castcloseparenspace=0 //--statopenparenlineterm=0 //--statlinetermcloseparen=0 //--statcloseparenspace=0 //--statcloseparenlineterm=0 //--castcloseparenspacegroupopenparen=1 --statopenparenspace=0 --statspacecloseparen=0 --groupopenparenspace=0 --groupspacecloseparen=0 //--groupspaceopenparen=0 //--groupcloseparenspace=0 //--groupopenparenlineterm=0 //--grouplinetermcloseparen=0 //--grouplinetermopenparen=0 //--groupcloseparenlineterm=0 --methodopenparenspace=0 --methodspacecloseparen=0 //--methodopenparenlineterm=0 //--methodlinetermcloseparen=0 //--methodcloseparenspace=0 //--methodcloseparenlineterm=0 //--horspaceslineterm // ANNOTATIONS // ----------- //--annotationatspace=0 //--annotationatlineterm=0 //--annotationspaceopenparen=0 //--annotationlinetermopenparen=0 //--annotationopenparenspace=0 //--annotationopenparenlineterm=0 //--annotationspacecloseparen=0 //--annotationlinetermcloseparen=0 //--annotationcloseparenspace=0 //--annotationcloseparenlineterm=0 //--annotationspaceopenbrace=0 //--annotationlinetermopenbrace=0 //--annotationopenbracespace=0 //--annotationopenbracelineterm=0 //--annotationspaceclosebrace=0 //--annotationlinetermclosebrace=0 //--annotationclosebracespace=0 //--annotationclosebracelineterm=0 //--annotationspace=1 //--annotationlineterm=1 robocode/tools/Jacobe/ReadMe.txt0000644000175000017500000000425711052312542016070 0ustar lambylambyCode beautifier described by Flemming N. Larsen (AKA Fnl): The Jacobe Code Beautifier is used as code beautifier for Robocode. You can read about it and download it from here: http://www.tiobe.com/jacobe.htm Jacobe is quite good for Java as it follows the Java code conventions from Sun: http://java.sun.com/docs/codeconv/ Jacobe can be integrated with Eclipse by using the Eclipse plugin for Jacobe. The plugin can be downloaded from the same page used when downloading Jacobe under the "Plug-ins" section. You can install the Jacobe plugin into Eclipse simply by unpacking the Jacobe plugin to the root directory of Eclipse (the plugins directory must be "overwritten" with the Jacobe plugin). When the Jacobe plugin has been put into the root directory of Eclipse, you must restart Eclipse, if you had it running while putting the plugin into the Eclipse directory. Otherwise you'll not be able to use Jacobe yet. I attached the robocode.cfg file, which is used for beautifying the Robocode sources with Jacobe. You should put this file into the directory where you have installed Jacobe, i.e. just together the sun.cfg file. In Eclipse (when you have added your plugin, and can see the purple bug in the toolbar) you select "Preferences.." from the Window menu. On the Preferences window you expand the Java (in the tree) and click Jacobe. Browse and select your Jacobe executable. Browse and select the robocode.cfg file. All checkmarks should be cleared, except for "overwrite original files". Otherwise backup files are created. Now you are ready to code beautify following the Robocode Jacobe configuration. You can also code beautify the sources of Robocode by using the target named "jacobe" in the build.xml file provided in this directory. Here you'll need to download and install the Jacobe Ant Task: http://www.tiobe.com/downloads/jacobe-ant-task.zip You should copy the jacode.jar file inside the jacobe-ant-task.zip file into this folder, and also add the home folder where the Jacode executable is located into your PATH environment variable. You can read more about the Jacobe Ant task here: http://www.tiobe.com/downloads/jacobe_task_doc.htmrobocode/tools/Jacobe/jacobe.jar0000644000175000017500000000736411055335332016122 0ustar lambylambyPK]:4!com/tiobe/jacobe/JacobeTask.class}T]SE= fvl$jY> Dְ& ά3}]jĔ(; X0CtܾsvF /`B;)`"+a2SdyaZ3fm51{:tcQGA:XQԱC wS kX@ 14[Y0+[H˷]gTm~2_`ђmr۟he̼[ #jIzfBD[ |Z-Ku  u9΄TLg-W=YUQ_] }@miǐI,@;'YK!!TJ gc!˶w`-?N`KZܔӹor 1) t#xNJ YkoCp֪|*eכzٍ}Y@kv(BNeCya5m~ s4`uUzVAŸu1cZάֺ[LυkW#צR>(JQ/e瘽6D G"0N*5q*rY. AWYIQW ȭu ^& YUWPZU*%_l]ghm$hٶ ) t GZn5] [B="T F;#w.V 3P>7Zp IO#;. vs'2ΐ;Kd$.[$r6#MzCgR{Mok'F]k{D_?MI'{ߒ}3Ns=n?=ܟuB´ҝOp>̙Z= yzv|A\ J[bmkPK[XpPK]:4com/tiobe/jacobe/Jacobe.classVsUmwM-m iAPjMSI)MI EMRRM$}q|G}SPS3:Ψ}$MkC2~9w9g?:PA; {bL0OD a }DDBl{;(adꐈV!KX͞0{L P$4`T*a01&AQ9.{w{ rB*)-QAe"V' vz`$7am~/X lƺC=N6g՜3P6f6F[Z"Ɓw7 R*Ꞅf#ޯLEH* >o/ h׳ZO&ÎLK"g3 YU%Yʜ >{kF IE^26+ԓjMGGAn-loĿ!OOH4#ďJ74Vl`QPbeZ=2i#br?DkrR(' GzD9]%/uscøf,dar 4l)z|sX3v, 5Sk\Afh3v΄6A0[b7,.È?"!sKꑯ*&oэ﨎G?~ ~$ U8_vA02n?i+ְլ94 zY>t^ʮqYa>2 w ,K# +U*_2--h2xb[ X-[P!7ة2;.-ͦou񷨡[-ne`VA =̻l'ǜ\1s٫աGHB q1+FN?"7+ψA/N4ж84{ GT殃E m*aTf4 c7?N0"Q KatRk:h7yLlHPK%XXPK]:4META-INF/MANIFEST.MFMLK-. K-*ϳR03r.JM,IMuRH+OJKI-ɯsSE %%VP@\y9ȚA I,KM++ч(G(KB@!QT aPKԒSPK]:4[Xp!com/tiobe/jacobe/JacobeTask.classPK]:4~' .com/tiobe/jacobe/Jacobe.classPK]:4%XXN com/tiobe/jacobe/Jacobe$1.classPK]:4ԒS META-INF/MANIFEST.MFPK)