source: branches/Robocode.TrunkInt/HeuristicLab.Problems.Robocode/3.3/Interpreter.cs @ 9947

Last change on this file since 9947 was 9947, checked in by jkarder, 7 years ago

#2069:

  • modified the RobocodeProblem to extract all robots in robocode directory
  • modified the battle runner to take a number of enemies that should be battled
File size: 6.3 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2013 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Diagnostics;
24using System.Globalization;
25using System.IO;
26using System.Linq;
27using System.Reflection;
28using HeuristicLab.Core;
29using HeuristicLab.Data;
30using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
31
32namespace HeuristicLab.Problems.Robocode {
33  public static class Interpreter {
34    public static double EvaluateTankProgram(ISymbolicExpressionTree tree, string path, ICheckedItemList<StringValue> enemies, string robotName = null, bool showUI = false, int nrOfRounds = 3) {
35      if (robotName == null)
36        robotName = GenerateRobotName();
37
38      string interpretedProgram = InterpretProgramTree(tree.Root, robotName);
39      string battleRunnerPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
40      string roboCodeLibPath = Path.Combine(path, "libs");
41      string robocodeJar = Path.Combine(roboCodeLibPath, "robocode.jar");
42      string robocodeCoreJar = GetFileName(roboCodeLibPath, "robocode.core*");
43      string picocontainerJar = GetFileName(roboCodeLibPath, "picocontainer*");
44      string robotsPath = Path.Combine(path, "robots", "Evaluation");
45      string srcRobotPath = Path.Combine(robotsPath, robotName + ".java");
46
47      File.WriteAllText(srcRobotPath, interpretedProgram, System.Text.Encoding.Default);
48
49      ProcessStartInfo javaCompileInfo = new ProcessStartInfo();
50      javaCompileInfo.FileName = "cmd.exe";
51      javaCompileInfo.Arguments = "/C javac -cp " + robocodeJar + "; " + srcRobotPath;
52      javaCompileInfo.RedirectStandardOutput = true;
53      javaCompileInfo.RedirectStandardError = true;
54      javaCompileInfo.UseShellExecute = false;
55      javaCompileInfo.CreateNoWindow = true;
56
57      Process javaCompile = new Process();
58      javaCompile.StartInfo = javaCompileInfo;
59      javaCompile.Start();
60
61      string cmdOutput = javaCompile.StandardOutput.ReadToEnd();
62      cmdOutput += javaCompile.StandardError.ReadToEnd();
63
64      javaCompile.WaitForExit();
65      if (javaCompile.ExitCode != 0) {
66        DeleteRobotFiles(path, robotName);
67        throw new Exception("Compile Error: " + cmdOutput);
68      }
69
70      //parallel execution of multiple robocode instances can sometimes lead to a damaged robot.database
71      try { File.Delete(path + @"\robots\robot.database"); }
72      catch { }
73
74      ProcessStartInfo evaluateCodeInfo = new ProcessStartInfo();
75
76      evaluateCodeInfo.FileName = "cmd.exe";
77      evaluateCodeInfo.Arguments = "/C java -cp " + battleRunnerPath + ";" + robocodeCoreJar + ";" + robocodeJar +
78                                  ";" + picocontainerJar + ";" + " BattleRunner Evaluation." + robotName + "* " + path;
79
80      if (showUI) {
81        evaluateCodeInfo.Arguments += " true " + nrOfRounds;
82      } else {
83        evaluateCodeInfo.Arguments += " false " + nrOfRounds;
84      }
85
86      foreach (var enemy in enemies)
87        evaluateCodeInfo.Arguments += enemy.Value + "* ";
88
89      evaluateCodeInfo.RedirectStandardOutput = true;
90      evaluateCodeInfo.RedirectStandardError = true;
91      evaluateCodeInfo.UseShellExecute = false;
92      evaluateCodeInfo.CreateNoWindow = true;
93
94      Process evaluateCode = new Process();
95      evaluateCode.StartInfo = evaluateCodeInfo;
96      evaluateCode.Start();
97      evaluateCode.WaitForExit();
98
99      if (evaluateCode.ExitCode != 0) {
100        DeleteRobotFiles(path, robotName);
101        throw new Exception("Error running Robocode: " + evaluateCode.StandardError.ReadToEnd());
102      }
103
104      string scoreString = "";
105      double evaluation = -1.0;
106      try {
107        scoreString = evaluateCode.StandardOutput.ReadToEnd().Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).Last();
108        evaluation = Double.Parse(scoreString, CultureInfo.InvariantCulture);
109      }
110      catch (Exception ex) {
111        throw new Exception("Error parsing score string: " + ex.ToString());
112      }
113      finally {
114        DeleteRobotFiles(path, robotName);
115      }
116
117      return evaluation;
118    }
119
120    private static void DeleteRobotFiles(string path, string outputname) {
121      try {
122        File.Delete(path + @"\robots\Evaluation\" + outputname + ".java");
123        File.Delete(path + @"\robots\Evaluation\" + outputname + ".class");
124      }
125      catch { }
126    }
127
128    private static string GetFileName(string path, string pattern) {
129      string fileName = string.Empty;
130      try {
131        fileName = Directory.GetFiles(path, pattern).First();
132      }
133      catch {
134        throw new Exception("Error finding required RoboCode files.");
135      }
136      return fileName;
137    }
138
139    private static string GenerateRobotName() {
140      // Robocode class names are 32 char max and
141      // Java class names have to start with a letter
142      string outputname = Guid.NewGuid().ToString();
143      outputname = outputname.Remove(8, 1);
144      outputname = outputname.Remove(12, 1);
145      outputname = outputname.Remove(16, 1);
146      outputname = outputname.Remove(20, 1);
147      outputname = outputname.Remove(0, 1);
148      outputname = outputname.Insert(0, "R");
149      return outputname;
150    }
151
152    public static string InterpretProgramTree(ISymbolicExpressionTreeNode node, string robotName) {
153      var tankNode = node;
154      while (!(tankNode.Symbol is Tank))
155        tankNode = tankNode.GetSubtree(0);
156
157      string result = ((CodeNode)tankNode.Symbol).Interpret(tankNode, tankNode.Subtrees);
158      result = result.Replace("class output", "class " + robotName);
159      return result;
160    }
161  }
162}
Note: See TracBrowser for help on using the repository browser.