public Problem() : base() { DirectoryValue robocodeDir = new DirectoryValue { Value = @"robocode" }; var robotList = EnemyCollection.ReloadEnemies(robocodeDir.Value); robotList.RobocodePath = robocodeDir.Value; Parameters.Add(new FixedValueParameter <DirectoryValue>(RobocodePathParamaterName, "Path of the Robocode installation.", robocodeDir)); Parameters.Add(new FixedValueParameter <IntValue>(NrOfRoundsParameterName, "Number of rounds a robot has to fight against each opponent.", new IntValue(3))); Parameters.Add(new ValueParameter <EnemyCollection>(EnemiesParameterName, "The enemies that should be battled.", robotList)); Encoding = new SymbolicExpressionTreeEncoding(new Grammar(), 1000, 10); Encoding.FunctionArguments = 0; Encoding.FunctionDefinitions = 0; RegisterEventHandlers(); }
public static EnemyCollection ReloadEnemies(string robocodeDir) { EnemyCollection robotList = new EnemyCollection(); try { var robotsDir = new DirectoryInfo(Path.Combine(robocodeDir, "robots")); var robotFiles = robotsDir.GetFiles("*", SearchOption.AllDirectories) .Where(x => x.Extension == ".class" || x.Extension == ".jar"); var robotSet = new Dictionary <string, StringValue>(); foreach (var robot in robotFiles) { string robotName = Path.Combine(robot.DirectoryName, Path.GetFileNameWithoutExtension(robot.FullName)); robotName = robotName.Remove(0, robotsDir.FullName.Length); string[] nameParts = robotName.Split(new[] { Path.DirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries); robotName = string.Join(".", nameParts); robotSet[robot.FullName] = new StringValue(robotName); } robotList.AddRange(robotSet.Values); foreach (var robot in robotList) { robotList.SetItemCheckedState(robot, false); } } catch { } //select one robot so that if a user tries out the Robocode problem it works with the default settings if (robotList.Exists(x => x.Value == sampleRobotToSelect)) { StringValue sampleRobot = robotList.Single(x => x.Value == sampleRobotToSelect); robotList.SetItemCheckedState(sampleRobot, true); } return(robotList); }
protected EnemyCollection(EnemyCollection original, Cloner cloner) : base(original, cloner) { RobocodePath = original.RobocodePath; }
// TODO performance: it would probably be useful to implement the BattleRunner in such a way that we don't have to restart the java process each time, e.g. using console IO to load & run robots public static double EvaluateTankProgram(ISymbolicExpressionTree tree, string path, EnemyCollection enemies, string robotName = null, bool showUI = false, int nrOfRounds = 3) { if (robotName == null) { robotName = GenerateRobotName(); } string interpretedProgram = InterpretProgramTree(tree.Root, robotName); string battleRunnerPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "robocode"); string roboCodeLibPath = Path.Combine(path, "libs"); string robocodeJar = Path.Combine(roboCodeLibPath, "robocode.jar"); string robocodeCoreJar = GetFileName(roboCodeLibPath, "robocode.core*"); string picocontainerJar = GetFileName(roboCodeLibPath, "picocontainer*"); string robotsPath = Path.Combine(path, "robots", "Evaluation"); string srcRobotPath = Path.Combine(robotsPath, robotName + ".java"); File.WriteAllText(srcRobotPath, interpretedProgram, System.Text.Encoding.Default); // compile java source to class file ProcessStartInfo javaCompileInfo = new ProcessStartInfo(); javaCompileInfo.FileName = "cmd.exe"; javaCompileInfo.Arguments = "/C javac -cp " + robocodeJar + "; " + srcRobotPath; javaCompileInfo.RedirectStandardOutput = true; javaCompileInfo.RedirectStandardError = true; javaCompileInfo.UseShellExecute = false; javaCompileInfo.CreateNoWindow = true; // it's ok to compile multiple robocode programs concurrently using (Process javaCompile = new Process()) { javaCompile.StartInfo = javaCompileInfo; javaCompile.Start(); string cmdOutput = javaCompile.StandardOutput.ReadToEnd(); cmdOutput += javaCompile.StandardError.ReadToEnd(); javaCompile.WaitForExit(); if (javaCompile.ExitCode != 0) { DeleteRobotFiles(path, robotName); throw new Exception("Compile Error: " + cmdOutput); } } ProcessStartInfo evaluateCodeInfo = new ProcessStartInfo(); // execute a battle with numberOfRounds against a number of enemies // TODO: seems there is a bug when selecting multiple enemies evaluateCodeInfo.FileName = "cmd.exe"; var classpath = string.Join(";", new[] { battleRunnerPath, robocodeCoreJar, robocodeJar, picocontainerJar }); var enemyRobotNames = string.Join(" ", enemies.CheckedItems.Select(i => i.Value)); evaluateCodeInfo.Arguments = string.Format("/C java -cp {0} BattleRunner Evaluation.{1} {2} {3} {4} {5}", classpath, robotName, path, showUI, nrOfRounds, enemyRobotNames); evaluateCodeInfo.RedirectStandardOutput = true; evaluateCodeInfo.RedirectStandardError = true; evaluateCodeInfo.UseShellExecute = false; evaluateCodeInfo.CreateNoWindow = true; // the robocode framework writes state to a file therefore parallel evaluation of multiple robocode programs is not possible yet. double evaluation; lock (syncRoot) { using (Process evaluateCode = new Process()) { evaluateCode.StartInfo = evaluateCodeInfo; evaluateCode.Start(); evaluateCode.WaitForExit(); if (evaluateCode.ExitCode != 0) { DeleteRobotFiles(path, robotName); throw new Exception("Error running Robocode: " + evaluateCode.StandardError.ReadToEnd() + Environment.NewLine + evaluateCode.StandardOutput.ReadToEnd()); } try { string scoreString = evaluateCode.StandardOutput.ReadToEnd() .Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries) .Last(); evaluation = Double.Parse(scoreString, CultureInfo.InvariantCulture); } catch (Exception ex) { throw new Exception("Error parsing score string: " + ex); } finally { DeleteRobotFiles(path, robotName); } } } return(evaluation); }