using System; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using System.Xml; using HeuristicLab.Core; using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding; namespace HeuristicLab.Problems.Robocode { public class Interpreter { private struct TankStats { public int moves, shots; public TankStats(int moves, int shots) { this.moves = moves; this.shots = shots; } } static string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; public static string BuildTankProgram(ISymbolicExpressionTree tree) { XmlDocument solutionCandidateRoot = new XmlDocument(); solutionCandidateRoot.Load("../tank.xml"); TankStats tankStats = EvaluateTankProgram(tree.Root, solutionCandidateRoot.FirstChild, null); return solutionCandidateRoot.InnerText; } public static double EvaluateTankProgram(ISymbolicExpressionTree tree, XmlNode solutionCandidateRoot, string path) { //TankStats tankStats = EvaluateTankProgram(tree.Root, solutionCandidateRoot, null); //Evaluator.tankStatLog += "\r\n" + tankStats.shots + " / " + tankStats.moves; string interpretedProgram = InterpretProgramTree(tree.Root); Random random = new Random(); string formattedPath = path.Replace("/", "\\"); string outputname = ""; string output = ""; bool noError = true; do { try { outputname = new string(Enumerable.Repeat(chars, 8).Select(s => s[random.Next(s.Length)]).ToArray()); output = /*solutionCandidateRoot.InnerText*/interpretedProgram.Replace("class output", "class " + outputname); File.WriteAllText(path + "/robots/Evaluation/" + outputname + ".java", output, System.Text.Encoding.Default); noError = true; } catch (Exception e) { noError = false; } } while (!noError); //string path = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); //path.Replace("\\", "\\\\"); //path.Replace(" ", "\\ "); #region Compile code file ProcessStartInfo javaCompileInfo = new ProcessStartInfo(); javaCompileInfo.FileName = "cmd.exe"; javaCompileInfo.Arguments = "/C javac -cp " + formattedPath + "\\libs\\robocode.jar " + formattedPath + "\\robots\\Evaluation\\" + outputname + ".java"; javaCompileInfo.RedirectStandardOutput = true; javaCompileInfo.RedirectStandardError = true; javaCompileInfo.UseShellExecute = false; javaCompileInfo.CreateNoWindow = true; Process javaCompile = new Process(); javaCompile.StartInfo = javaCompileInfo; javaCompile.Start(); /*Evaluator.tankStatLog = "=====================================================\r\n"; Evaluator.tankStatLog += "Tree Compilation Output: \r\n"; Evaluator.tankStatLog += "=====================================================\r\n";*/ string cmdOutput = javaCompile.StandardOutput.ReadToEnd(); cmdOutput += javaCompile.StandardError.ReadToEnd(); //Evaluator.tankStatLog += cmdOutput; //Console.WriteLine(cmdOutput); //Console.ReadLine(); /*Evaluator.tankStatLog = "=====================================================\r\n"; Evaluator.tankStatLog += "End of Tree Compilation Output: \r\n"; Evaluator.tankStatLog += "=====================================================\r\n";*/ javaCompile.WaitForExit(); if (javaCompile.ExitCode != 0) { return -1000.0; } #endregion try { File.Delete(path + "/robots/robot.database"); } catch (Exception e) { } #region evaluate code ProcessStartInfo evaluateCodeInfo = new ProcessStartInfo(); evaluateCodeInfo.FileName = "cmd.exe"; //javaCompileInfo.Arguments = "/C javac -cp C:\\robocode\\libs\\robocode.jar \"" + path + "\\Spaced Up\\output.java\""; evaluateCodeInfo.Arguments = "/C java -classpath " + formattedPath + "\\libs;" + formattedPath + "\\libs\\robocode.core-1.8.1.0.jar;" + formattedPath + "\\libs\\robocode.jar;" + formattedPath + "\\libs\\picocontainer-2.14.2.jar BattleRunner Evaluation." + outputname + "* false"; //Console.WriteLine(javaCompileInfo.Arguments); evaluateCodeInfo.RedirectStandardOutput = true; evaluateCodeInfo.RedirectStandardError = true; evaluateCodeInfo.UseShellExecute = false; evaluateCodeInfo.CreateNoWindow = true; Process evaluateCode = new Process(); evaluateCode.StartInfo = evaluateCodeInfo; evaluateCode.Start(); StringBuilder q = new StringBuilder(); string scoreString = ""; evaluateCode.WaitForExit(); try { scoreString = evaluateCode.StandardOutput.ReadToEnd().Split( new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries).Last(); q.Append("Output: " + scoreString + "\r\n"); q.Append("Error: " + evaluateCode.StandardError.ReadToEnd() + "\r\n"); cmdOutput += q.ToString(); }catch { return -1000.0; } #endregion double evaluation = -900; try { File.Delete(path + "/robots/Evaluation/" + outputname + ".java"); File.Delete(path + "/robots/Evaluation/" + outputname + ".class"); evaluation = Double.Parse(scoreString); } catch (Exception e) { evaluation = -900; } Random rand = new Random(); evaluation += rand.NextDouble() / 100; /*Evaluator.tankStatLog = "=====================================================\r\n"; Evaluator.tankStatLog += "START OF TREE - Score: " + evaluation + " (" + tankStats.shots + "/" + tankStats.moves + ")" + "\r\n" + " Compilation Output: " + cmdOutput + "\r\n"; Evaluator.tankStatLog += "=====================================================\r\n"; Evaluator.tankStatLog += solutionCandidateRoot.InnerText + "\r\n"; Evaluator.tankStatLog += "=====================================================\r\n"; Evaluator.tankStatLog += "END OF TREE\r\n"; Evaluator.tankStatLog += "=====================================================\r\n"; File.AppendAllText("../TankLog.txt", Evaluator.tankStatLog);*/ return evaluation; } public static double EvaluateTankProgram(ISymbolicExpressionTree tree, ScopeList coevolutionIndividuals, XmlNode solutionCandidateRoot, string path) { Random random = new Random(); string formattedPath = path.Replace("/", "\\"); // Interpret and compile main tree //XmlNode mainTreeNode = solutionCandidateRoot.Clone(); //EvaluateTankProgram(tree.Root, mainTreeNode, null); string interpretedMainTree = InterpretProgramTree(tree.Root); string mainTreeName = writeTreeToFile(interpretedMainTree, path, random); compileCodefile(/*mainTreeName,*/ mainTreeName, formattedPath); // Interpret and compile coevolutionIndividuals String[] coevolutionIndividualsNames = new String[coevolutionIndividuals.Count]; for (int i = 0; i < coevolutionIndividuals.Count; i++) { //XmlNode individualTreeNode = solutionCandidateRoot.Clone(); //EvaluateTankProgram(((ISymbolicExpressionTree)coevolutionIndividuals[i].Variables.ToArray()[0].Value).Root, individualTreeNode, null); string interpretedIndividual = InterpretProgramTree(((ISymbolicExpressionTree)coevolutionIndividuals[i].Variables.ToArray()[0].Value).Root); coevolutionIndividualsNames[i] = writeTreeToFile(/*individualTreeNode,*/ interpretedIndividual, path, random); compileCodefile(coevolutionIndividualsNames[i], formattedPath); } // Force Robocode to update its robot database by deleting the existing one try { File.Delete(path + "/robots/robot.database"); } catch (Exception e) { } // Run evaluator double evaluation = runEvaluator(mainTreeName, coevolutionIndividualsNames, formattedPath); try { File.Delete(path + "/robots/Evaluation/" + mainTreeName + ".java"); File.Delete(path + "/robots/Evaluation/" + mainTreeName + ".class"); foreach (string s in coevolutionIndividualsNames) { File.Delete(path + "/robots/Evaluation/" + s + ".java"); File.Delete(path + "/robots/Evaluation/" + s + ".class"); } } catch (Exception e) { } Random rand = new Random(); evaluation += rand.NextDouble() / 100; return evaluation; } private static string writeTreeToFile(/*XmlNode node,*/ string interpretedTree, string path, Random random) { string outputName = ""; string outputString = ""; bool noError = true; do { try { outputName = new string(Enumerable.Repeat(chars, 8).Select(s => s[random.Next(s.Length)]).ToArray()); outputString = /*node.InnerText*/interpretedTree.Replace("class output", "class " + outputName); File.WriteAllText(path + "/robots/Evaluation/" + outputName + ".java", outputString, System.Text.Encoding.Default); noError = true; } catch (Exception e) { noError = false; } } while (!noError); return outputName; } private static bool compileCodefile(string filename, string formattedPath) { ProcessStartInfo javaCompileInfo = new ProcessStartInfo(); javaCompileInfo.FileName = "cmd.exe"; javaCompileInfo.Arguments = "/C javac -cp " + formattedPath + "\\libs\\robocode.jar " + formattedPath + "\\robots\\Evaluation\\" + filename + ".java"; javaCompileInfo.RedirectStandardOutput = true; javaCompileInfo.RedirectStandardError = true; javaCompileInfo.UseShellExecute = false; javaCompileInfo.CreateNoWindow = true; Process javaCompile = new Process(); javaCompile.StartInfo = javaCompileInfo; javaCompile.Start(); string cmdOutput = javaCompile.StandardOutput.ReadToEnd(); cmdOutput += javaCompile.StandardError.ReadToEnd(); javaCompile.WaitForExit(); if (cmdOutput.Equals("")) return true; return false; } private static double runEvaluator(string mainTreeFilename, string[] coevolutionIndividualsNames, string formattedPath) { ProcessStartInfo evaluateCodeInfo = new ProcessStartInfo(); evaluateCodeInfo.FileName = "cmd.exe"; //javaCompileInfo.Arguments = "/C javac -cp C:\\robocode\\libs\\robocode.jar \"" + path + "\\Spaced Up\\output.java\""; evaluateCodeInfo.Arguments = "/C java -classpath " + formattedPath + "\\libs;" + formattedPath + "\\libs\\robocode.core-1.8.1.0.jar;" + formattedPath + "\\libs\\robocode.jar;" + formattedPath + "\\libs\\picocontainer-2.14.2.jar BattleRunner Evaluation." + mainTreeFilename + "* "; if (coevolutionIndividualsNames != null) { foreach (string s in coevolutionIndividualsNames) evaluateCodeInfo.Arguments += "Evaluation." + s + "* "; } else evaluateCodeInfo.Arguments += "false"; //Console.WriteLine(javaCompileInfo.Arguments); evaluateCodeInfo.RedirectStandardOutput = true; evaluateCodeInfo.RedirectStandardError = true; evaluateCodeInfo.UseShellExecute = false; evaluateCodeInfo.CreateNoWindow = true; Process evaluateCode = new Process(); evaluateCode.StartInfo = evaluateCodeInfo; evaluateCode.Start(); StringBuilder q = new StringBuilder(); string scoreString = ""; while (!evaluateCode.HasExited) { scoreString = evaluateCode.StandardOutput.ReadToEnd().Split( new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries).Last(); q.Append("Output: " + scoreString + "\r\n"); q.Append("Error: " + evaluateCode.StandardError.ReadToEnd() + "\r\n"); } string cmdOutput = q.ToString(); try { double evaluation = Double.Parse(scoreString); return evaluation; } catch (Exception e) { } return -900; } private static TankStats EvaluateTankProgram(ISymbolicExpressionTreeNode node, XmlNode docNode, string method) { TankStats tankStats = new TankStats(0, 0); //string log = "Doing node: \r\n"; /*if (node.Symbol is ProgramRootSymbol || node.Symbol is StartSymbol) tankStats = EvaluateTankProgram(node.GetSubtree(0), ref docNode, null); else*/ if (node.Symbol is Constant) docNode[method]["code"].InnerText += " " + ((ConstantTreeNode)node).Value + " "; else if (node.Symbol is ShotPower) docNode[method]["code"].InnerText += " " + ((ShotPowerTreeNode)node).Value + " "; else if (node.Symbol is LogicalValue) docNode[method]["code"].InnerText += " " + ((BooleanTreeNode)node).Value.ToString().ToLower() + " "; else if (node.Symbol is Block) { docNode[method]["code"].InnerText += "{\r\n"; foreach (ISymbolicExpressionTreeNode n in node.Subtrees) EvaluateTankProgram(n, docNode, method); docNode[method]["code"].InnerText += "}\r\n"; } else if (node.Symbol is IfStatement) { docNode[method]["code"].InnerText += "if("; EvaluateTankProgram(node.GetSubtree(0), docNode, method); docNode[method]["code"].InnerText += ")\r\n"; EvaluateTankProgram(node.GetSubtree(1), docNode, method); if (node.SubtreeCount == 3) EvaluateTankProgram(node.GetSubtree(2), docNode, method); } else if (node.Symbol is ElseStatement) { docNode[method]["code"].InnerText += "else\r\n"; if (node.SubtreeCount == 1) EvaluateTankProgram(node.GetSubtree(0), docNode, method); } else if (node.Symbol is WhileLoop) { docNode[method]["code"].InnerText += "While("; EvaluateTankProgram(node.GetSubtree(0), docNode, method); docNode[method]["code"].InnerText += ")\r\n"; EvaluateTankProgram(node.GetSubtree(1), docNode, method); } else if (node.Symbol is Ahead) { docNode[method]["code"].InnerText += "setAhead("; EvaluateTankProgram(node.GetSubtree(0), docNode, method); docNode[method]["code"].InnerText += ");\r\n"; tankStats.moves = 1; } else if (node.Symbol is Back) { docNode[method]["code"].InnerText += "setBack("; EvaluateTankProgram(node.GetSubtree(0), docNode, method); docNode[method]["code"].InnerText += ");\r\n"; tankStats.moves = 1; } else if (node.Symbol is SetAdjustGunForRobotTurn) { docNode[method]["code"].InnerText += "setAdjustGunForRobotTurn("; EvaluateTankProgram(node.GetSubtree(0), docNode, method); docNode[method]["code"].InnerText += ");\r\n"; tankStats.moves = 1; } else if (node.Symbol is SetAdjustRadarForGunTurn) { docNode[method]["code"].InnerText += "setAdjustRadarForGunTurn("; EvaluateTankProgram(node.GetSubtree(0), docNode, method); docNode[method]["code"].InnerText += ");\r\n"; tankStats.moves = 1; } else if (node.Symbol is SetAdjustRadarForRobotTurn) { docNode[method]["code"].InnerText += "setAdjustRadarForRobotTurn("; EvaluateTankProgram(node.GetSubtree(0), docNode, method); docNode[method]["code"].InnerText += ");\r\n"; tankStats.moves = 1; } else if (node.Symbol is TurnGunLeft) { docNode[method]["code"].InnerText += "setTurnGunLeft("; EvaluateTankProgram(node.GetSubtree(0), docNode, method); docNode[method]["code"].InnerText += ");\r\n"; tankStats.moves = 1; } else if (node.Symbol is TurnGunRight) { docNode[method]["code"].InnerText += "setTurnGunRight("; EvaluateTankProgram(node.GetSubtree(0), docNode, method); docNode[method]["code"].InnerText += ");\r\n"; tankStats.moves = 1; } else if (node.Symbol is TurnLeft) { docNode[method]["code"].InnerText += "setTurnLeft("; EvaluateTankProgram(node.GetSubtree(0), docNode, method); docNode[method]["code"].InnerText += ");\r\n"; tankStats.moves = 1; } else if (node.Symbol is TurnRadarLeft) { docNode[method]["code"].InnerText += "setTurnRadarLeft("; EvaluateTankProgram(node.GetSubtree(0), docNode, method); docNode[method]["code"].InnerText += ");\r\n"; tankStats.moves = 1; } else if (node.Symbol is TurnRadarRight) { docNode[method]["code"].InnerText += "setTurnRadarRight("; EvaluateTankProgram(node.GetSubtree(0), docNode, method); docNode[method]["code"].InnerText += ");\r\n"; tankStats.moves = 1; } else if (node.Symbol is TurnRight) { docNode[method]["code"].InnerText += "setTurnRight("; EvaluateTankProgram(node.GetSubtree(0), docNode, method); docNode[method]["code"].InnerText += ");\r\n"; tankStats.moves = 1; } else if (node.Symbol is Fire) { docNode[method]["code"].InnerText += "setFire("; EvaluateTankProgram(node.GetSubtree(0), docNode, method); docNode[method]["code"].InnerText += ");\r\n"; tankStats.shots = 1; } else if (node.Symbol is Run || node.Symbol is OnBulletHit || node.Symbol is OnBulletMissed || node.Symbol is OnHitByBullet || node.Symbol is OnHitRobot || node.Symbol is OnHitWall || node.Symbol is OnScannedRobot) { tankStats = new TankStats(); foreach (SymbolicExpressionTreeNode n in node.Subtrees) { string methodName = node.Symbol.GetType().ToString().Split('.').Last(); try { var tempStats = EvaluateTankProgram(n, docNode, methodName); tankStats.moves += tempStats.moves; tankStats.shots += tempStats.shots; } catch (Exception e) { //log += "NULL EXCEPTION ON:::::::: -" + methodName + "-\r\n"; //foreach (XmlNode f in docNode[methodName]) // log += f.Name + "\r\n"; } } } else if (node.Symbol is Tank) { foreach (SymbolicExpressionTreeNode n in node.Subtrees) { try { var tempStats = EvaluateTankProgram(n, docNode, method); tankStats.moves += tempStats.moves; tankStats.shots += tempStats.shots; } catch (Exception e) { } } } else tankStats = EvaluateTankProgram(node.GetSubtree(0), docNode, null); //log += tankStats.shots + " / " + tankStats.moves + "\r\n"; //File.AppendAllText("../TankLog.txt", log); return tankStats; } public static string InterpretProgramTree(ISymbolicExpressionTreeNode node) { var tankNode = node; while (!(tankNode.Symbol is Tank)) tankNode = tankNode.GetSubtree(0); return ((CodeNode)tankNode.Symbol).Interpret(tankNode, tankNode.Subtrees); } } }