Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 13013 was 13013, checked in by gkronber, 9 years ago

#2069: reviewing and minor changes

File size: 6.5 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2015 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.Encodings.SymbolicExpressionTreeEncoding;
29
30namespace HeuristicLab.Problems.GeneticProgramming.Robocode {
31  public static class Interpreter {
32    public static double EvaluateTankProgram(ISymbolicExpressionTree tree, string path, EnemyCollection enemies, string robotName = null, bool showUI = false, int nrOfRounds = 3) {
33      if (robotName == null)
34        robotName = GenerateRobotName();
35
36      string interpretedProgram = InterpretProgramTree(tree.Root, robotName);
37      string battleRunnerPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
38      string roboCodeLibPath = Path.Combine(path, "libs");
39      string robocodeJar = Path.Combine(roboCodeLibPath, "robocode.jar");
40      string robocodeCoreJar = GetFileName(roboCodeLibPath, "robocode.core*");
41      string picocontainerJar = GetFileName(roboCodeLibPath, "picocontainer*");
42      string robotsPath = Path.Combine(path, "robots", "Evaluation");
43      string srcRobotPath = Path.Combine(robotsPath, robotName + ".java");
44
45      File.WriteAllText(srcRobotPath, interpretedProgram, System.Text.Encoding.Default);
46
47      // compile java source to class file
48      ProcessStartInfo javaCompileInfo = new ProcessStartInfo();
49      javaCompileInfo.FileName = "cmd.exe";
50      javaCompileInfo.Arguments = "/C javac -cp " + robocodeJar + "; " + srcRobotPath;
51      javaCompileInfo.RedirectStandardOutput = true;
52      javaCompileInfo.RedirectStandardError = true;
53      javaCompileInfo.UseShellExecute = false;
54      javaCompileInfo.CreateNoWindow = true;
55
56      using (Process javaCompile = new Process()) {
57        javaCompile.StartInfo = javaCompileInfo;
58        javaCompile.Start();
59
60        string cmdOutput = javaCompile.StandardOutput.ReadToEnd();
61        cmdOutput += javaCompile.StandardError.ReadToEnd();
62
63        javaCompile.WaitForExit();
64        if (javaCompile.ExitCode != 0) {
65          DeleteRobotFiles(path, robotName);
66          throw new Exception("Compile Error: " + cmdOutput);
67        }
68      }
69
70      //parallel execution of multiple robocode instances can sometimes lead to a damaged robot.database
71      var robotsDbFileName = Path.Combine(path, "robots", "robot.database");
72      if (File.Exists(robotsDbFileName))
73        File.Delete(robotsDbFileName);
74
75      ProcessStartInfo evaluateCodeInfo = new ProcessStartInfo();
76
77      // execute a battle with numberOfRounds against a number of enemies
78      // TODO: seems there is a bug when selecting multiple enemies
79      evaluateCodeInfo.FileName = "cmd.exe";
80      var classpath = string.Join(";", new[] { battleRunnerPath, robocodeCoreJar, robocodeJar, picocontainerJar });
81      var enemyRobotNames = string.Join(" ", enemies.CheckedItems.Select(i => i.Value));
82      evaluateCodeInfo.Arguments = string.Format("/C java -cp {0} BattleRunner Evaluation.{1} {2} {3} {4} {5}", classpath, robotName, path, showUI, nrOfRounds, enemyRobotNames);
83
84      evaluateCodeInfo.RedirectStandardOutput = true;
85      evaluateCodeInfo.RedirectStandardError = true;
86      evaluateCodeInfo.UseShellExecute = false;
87      evaluateCodeInfo.CreateNoWindow = true;
88
89      double evaluation;
90      using (Process evaluateCode = new Process()) {
91        evaluateCode.StartInfo = evaluateCodeInfo;
92        evaluateCode.Start();
93        evaluateCode.WaitForExit();
94
95        if (evaluateCode.ExitCode != 0) {
96          DeleteRobotFiles(path, robotName);
97          throw new Exception("Error running Robocode: " + evaluateCode.StandardError.ReadToEnd() + Environment.NewLine +
98                              evaluateCode.StandardOutput.ReadToEnd());
99        }
100
101        try {
102          string scoreString =
103            evaluateCode.StandardOutput.ReadToEnd()
104              .Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)
105              .Last();
106          evaluation = Double.Parse(scoreString, CultureInfo.InvariantCulture);
107        }
108        catch (Exception ex) {
109          throw new Exception("Error parsing score string: " + ex);
110        }
111        finally {
112          DeleteRobotFiles(path, robotName);
113        }
114      }
115
116      return evaluation;
117    }
118
119    private static void DeleteRobotFiles(string path, string outputname) {
120      File.Delete(path + @"\robots\Evaluation\" + outputname + ".java");
121      File.Delete(path + @"\robots\Evaluation\" + outputname + ".class");
122    }
123
124    private static string GetFileName(string path, string pattern) {
125      string fileName = string.Empty;
126      try {
127        fileName = Directory.GetFiles(path, pattern).First();
128      }
129      catch {
130        throw new Exception("Error finding required Robocode files.");
131      }
132      return fileName;
133    }
134
135    private static string GenerateRobotName() {
136      // Robocode class names are 32 char max and
137      // Java class names have to start with a letter
138      string outputname = Guid.NewGuid().ToString();
139      outputname = outputname.Remove(8, 1);
140      outputname = outputname.Remove(12, 1);
141      outputname = outputname.Remove(16, 1);
142      outputname = outputname.Remove(20, 1);
143      outputname = outputname.Remove(0, 1);
144      outputname = outputname.Insert(0, "R");
145      return outputname;
146    }
147
148    public static string InterpretProgramTree(ISymbolicExpressionTreeNode node, string robotName) {
149      var tankNode = node;
150      while (!(tankNode.Symbol is Tank))
151        tankNode = tankNode.GetSubtree(0);
152
153      string result = ((CodeNode)tankNode.Symbol).Interpret(tankNode, tankNode.Subtrees);
154      result = result.Replace("class output", "class " + robotName);
155      return result;
156    }
157  }
158}
Note: See TracBrowser for help on using the repository browser.