public static void Main(string[] args) { string game; int iterations; int maxCost; RewardType rewardType; double const_C; double epsilon = 1; double const_D; int restarts; uint seed; bool stopOnResult; string level; if (args.Length != 3) { throw new ArgumentException("Need three arguments: game method level"); } //textWriter = File.WriteAllText("Log.txt"); //File.Delete("Log.txt"); textWriter = File.AppendText("Log.txt"); string[] gameSettings = args[0].Split(':'); string[] commands = args[1].Split(':'); level = args[2]; string configurationString = "\n\n\n********************************\n********************************\nBEGIN TASK:\nGame: " + gameSettings[0]; switch (gameSettings[0]) { case "sokoban": if (!bool.TryParse(gameSettings[1], out useNormalizedPosition)) { PrintInputError("useNormalizedPosition requires a bool value"); return; } if (!bool.TryParse(gameSettings[2], out useTunnelMacro)) { PrintInputError("useTunnelMacro requires a bool value"); return; } if (!bool.TryParse(gameSettings[3], out useGoalMacro)) { PrintInputError("useGoalMacro requires a bool value"); return; } if (!bool.TryParse(gameSettings[4], out useGoalCut)) { PrintInputError("useGoalCut requires a bool value"); return; } configurationString += "\nUse Normalized Position: " + useNormalizedPosition + "\nUse Tunnel Macro: " + useTunnelMacro + "\nUse Goal Macro: " + useGoalMacro + (useGoalMacro ? "\nUse Goal Cut: " + useGoalCut : "\nGoal Cut ignored with Goal Macro disabled") + "\n"; switch (commands[0]) { case "mcts": if (!int.TryParse(commands[1], out iterations)) { PrintInputError("iterations requires an integer value"); return; } if (!double.TryParse(commands[2], out const_C)) { PrintInputError("Const_C requires a double value"); return; } if (!double.TryParse(commands[3], out const_D)) { PrintInputError("Const_D requires a double value"); return; } if (!RewardType.TryParse(commands[4], out rewardType)) { PrintInputError("reward type requires an valid RewardType"); return; } if (!bool.TryParse(commands[5], out stopOnResult)) { PrintInputError("stop on result requires a boolean value"); return; } if (!uint.TryParse(commands[6], out seed)) { PrintInputError("seed requires an unsigned integer value"); return; } if (!bool.TryParse(commands[7], out ucb1Tuned)) { PrintInputError("UCB1 tuned requires a boolean value"); return; } if (!bool.TryParse(commands[8], out rave)) { PrintInputError("rave requires a boolean value"); return; } if (!int.TryParse(commands[9], out raveThreshold)) { PrintInputError("Rave threshold requires an integer value"); return; } if (!bool.TryParse(commands[10], out nodeRecycling)) { PrintInputError("node recycling requires a boolean value"); return; } if (!int.TryParse(commands[11], out memoryBudget)) { PrintInputError("Memory budget requires an integer value"); return; } if (!bool.TryParse(commands[12], out avoidCycles)) { PrintInputError("Avoid Cycles requires a boolean value"); return; } if (!bool.TryParse(commands[13], out useNodeElimination)) { PrintInputError("Use Node Elimination requires a boolean value"); return; } if (!SimulationType.TryParse(commands[14], out simulationType)) { PrintInputError("Use Node Elimination requires a boolean value"); return; } string simulationString = ""; switch (simulationType) { case SimulationType.EpsilonGreedy: if (!double.TryParse(commands[15], out epsilon)) { PrintInputError("epsilon requires a double value"); return; } simulationString += "\nSimulation: EpsilonGreedy - epsilon: " + epsilon; break; case SimulationType.IDAstar: if (!int.TryParse(commands[15], out maxNodes)) { PrintInputError("maxCost requires an integer value"); return; } if (!int.TryParse(commands[16], out tableSize)) { PrintInputError("maxTableSize requires an integer value"); return; } simulationString += "\nSimulation: IDA* - maxNodes: " + maxNodes + "; tableSize: " + tableSize; break; } if (nodeRecycling && (memoryBudget <= 0 || memoryBudget >= iterations)) { PrintInputError("Memory budget value not compatible with node recycling"); return; } configurationString += "\nSP-MCTS \nMethod: MCTS \niterations: " + iterations + "\nUCT constant: " + const_C + "\nSP_UCT constant: " + const_D + "\nReward Type: " + rewardType + "\nUCB1Tuned: " + ucb1Tuned + "\nRAVE: " + rave + "\nRAVE Threshold: " + raveThreshold + "\nNode Recycling: " + nodeRecycling + "\nMemory Budget: " + (nodeRecycling?"" + memoryBudget:"Ignored with node recycling disabled") + "\nAvoid Cycles: " + avoidCycles + "\nNode Elimination:" + useNodeElimination + "\nStop on Result: " + stopOnResult + "\nlevel path: " + level + "\nseed: " + seed + simulationString + "\n********************************\n********************************\n"; Log(configurationString); MultiThreadSokobanTest(const_C, const_D, iterations, 1, level, seed, true, rewardType, stopOnResult, epsilon, true, 1); break; case "ida": if (!int.TryParse(commands[1], out maxCost)) { PrintInputError("maxCost requires an integer value"); return; } if (!RewardType.TryParse(commands[2], out rewardType)) { PrintInputError("reward type requires an valid RewardType"); return; } if (!int.TryParse(commands[3], out int maxTableSize)) { PrintInputError("maxTableSize requires an integer value"); return; } configurationString += "\nMethod: IDA* \nMaximum cost: " + maxCost + "\nReward Type: " + rewardType + "\nlevel: " + level + "\n********************************\n********************************\n"; Log(configurationString); SokobanIDAStarTest(level, maxCost, rewardType, maxTableSize, useNormalizedPosition, useTunnelMacro, useGoalMacro, useGoalCut); break; case "random": if (!int.TryParse(commands[1], out iterations)) { PrintInputError("seed requires an unsigned integer value"); return; } if (!int.TryParse(commands[2], out int maxDepth)) { PrintInputError("seed requires an unsigned integer value"); return; } if (!uint.TryParse(commands[3], out seed)) { PrintInputError("seed requires an unsigned integer value"); return; } configurationString += "\nMethod: random \niterations: " + iterations + "\nMax Iteration Depth: " + maxDepth + "\nseed: " + seed + "\nlevel: " + level + "\n********************************\n********************************\n"; Log(configurationString); SokobanRandom(level, maxDepth, iterations, seed); break; } break; case "samegame": switch (commands[0]) { case "mcts": if (!int.TryParse(commands[1], out iterations)) { PrintInputError("iterations requires an integer value"); return; } if (!double.TryParse(commands[2], out const_C)) { PrintInputError("const_C requires a double value"); return; } if (!double.TryParse(commands[3], out const_D)) { PrintInputError("const_d requires adouble value"); return; } if (!int.TryParse(commands[4], out restarts)) { PrintInputError("restarts requires an integer value"); return; } if (!uint.TryParse(commands[5], out seed)) { PrintInputError("seed requires an unsigned integer value"); return; } if (!bool.TryParse(commands[6], out bool ucb1Tuned)) { PrintInputError("seed requires an unsigned integer value"); return; } if (!bool.TryParse(commands[7], out bool rave)) { PrintInputError("seed requires an unsigned integer value"); return; } if (!int.TryParse(commands[8], out raveThreshold)) { PrintInputError("Rave threshold requires an integer value"); return; } if (!bool.TryParse(commands[9], out bool nodeRecycling)) { PrintInputError("seed requires an unsigned integer value"); return; } if (!int.TryParse(commands[10], out int memoryBudget)) { PrintInputError("restarts requires an integer value"); return; } if (!bool.TryParse(commands[11], out useNodeElimination)) { PrintInputError("Use Node Elimination requires a boolean value"); return; } if (nodeRecycling && (memoryBudget <= 0 || memoryBudget >= iterations)) { PrintInputError("Memory budget value not compatible with node recycling"); return; } Log("\n********************\nBEGIN TASK:\nGame:" + gameSettings[0] + "\nMethod: MCTS \niterations: " + iterations + "\nUCT constant: " + const_C + "\nSP_UCT constant: " + const_D + "\nrestarts: " + restarts + "\nSeed: " + seed + "\nUCB1Tuned: " + ucb1Tuned + "\nRAVE: " + rave + "\nRAVE threshold: " + raveThreshold + "\nNode Recycling: " + nodeRecycling + "\nMemory Budget: " + (nodeRecycling ? "" + memoryBudget : "Ignored with node recycling disabled") + "\nNode Elimination: " + useNodeElimination + "\nlevel: " + level + "\n********************"); MultiThreadSamegameTest(const_C, const_D, iterations, restarts, level, 1, seed, ucb1Tuned, rave, nodeRecycling, memoryBudget); break; case "ida": if (!int.TryParse(commands[1], out maxCost)) { PrintInputError("maxCost requires an integer value"); return; } if (!int.TryParse(commands[2], out int tableSize)) { PrintInputError("maxTableSize requires an integer value"); return; } SamegameIDAStarTest(level, maxCost, tableSize); break; } break; default: PrintInputError("Wrong game name: Accepted names are 'sokoban' and 'samegame'"); break; } }