void CheckObjectif(ref SokobanGameState gs) { foreach (var item in gs.Grid) { if (item.state == State.Objective) { foreach (var bloc in gs.caisses) { if (bloc.position == item.position) { item.state = State.ObjectiveAccomplish; break; } } } if (item.state == State.ObjectiveAccomplish) { var test = false; foreach (var bloc in gs.caisses) { if (item.position == bloc.position) { test = true; break; } } if (!test) { item.state = State.Objective; } } } }
public bool IsAvailable(SokobanGameState gameState) { var pos = gameState.playerPosition + direction; var t = gameState.Grid[pos.x, pos.y]; switch (t.state) { case State.Walkable: return(true); case State.Objective: return(true); case State.Unwalkable: return(false); case State.ObjectiveAccomplish: return(false); case State.Caisse: var nextPos = pos + direction; var nextTile = gameState.Grid[nextPos.x, nextPos.y]; if (nextTile.state == State.Objective || nextTile.state == State.Walkable) { return(true); } return(false); default: return(false); } }
public bool Perform(ref SokobanGameState gameState) { // Move var nextPos = gameState.playerPosition + this.direction; var nextTile = gameState.Grid[nextPos.x, nextPos.y]; var res = false; switch (nextTile.state) { case State.Caisse: if (IsWalkableState(TestNextTileAfterBloc(nextPos, ref gameState))) { for (int i = 0; i < gameState.caisses.Count; i++) { if (gameState.caisses[i].position == nextPos) { gameState.Grid[gameState.playerPosition.x, gameState.playerPosition.y].state = State.Walkable; gameState.caisses[i].Move(direction); var caisse = gameState.caisses[i]; if (gameState.Grid[caisse.position.x, caisse.position.y].state == State.Objective) { gameState.Grid[caisse.position.x, caisse.position.y].state = State.ObjectiveAccomplish; res = true; } if (gameState.Grid[caisse.position.x, caisse.position.y].state == State.Walkable) { gameState.Grid[gameState.caisses[i].position.x, gameState.caisses[i].position.y].state = State.Caisse; } gameState.playerPosition = nextPos; gameState.Grid[nextPos.x, nextPos.y].state = State.Player; var blocPos = gameState.caisses[i].position; if (gameState.CheckFinish()) { Debug.Log("FINISH"); } } } } break; case State.Walkable: var currentState = gameState.Grid[gameState.playerPosition.x, gameState.playerPosition.y].state; gameState.Grid[gameState.playerPosition.x, gameState.playerPosition.y].state = currentState == State.Objective ? State.Objective : State.Walkable; gameState.playerPosition += direction; gameState.Grid[gameState.playerPosition.x, gameState.playerPosition.y].state = State.Player; break; case State.Unwalkable: break; case State.Objective: var state = gameState.Grid[gameState.playerPosition.x, gameState.playerPosition.y].state; gameState.Grid[gameState.playerPosition.x, gameState.playerPosition.y].state = state == State.Objective ? State.Objective : State.Walkable; gameState.playerPosition += direction; break; case State.ObjectiveAccomplish: if (IsWalkableState(TestNextTileAfterBloc(nextPos, ref gameState))) { for (int i = 0; i < gameState.caisses.Count; i++) { if (gameState.caisses[i].position == nextPos) { gameState.Grid[gameState.playerPosition.x, gameState.playerPosition.y].state = State.Walkable; gameState.caisses[i].Move(direction); var caisse = gameState.caisses[i]; if (gameState.Grid[caisse.position.x, caisse.position.y].state == State.Objective) { gameState.Grid[caisse.position.x, caisse.position.y].state = State.ObjectiveAccomplish; res = true; } if (gameState.Grid[caisse.position.x, caisse.position.y].state == State.Walkable) { gameState.Grid[gameState.caisses[i].position.x, gameState.caisses[i].position.y].state = State.Caisse; } gameState.playerPosition = nextPos; gameState.Grid[nextPos.x, nextPos.y].state = State.Player; var blocPos = gameState.caisses[i].position; if (gameState.CheckFinish()) { Debug.Log("FINISH"); } } } } break; } return(res); }
State TestNextTileAfterBloc(Vector2Int pos, ref SokobanGameState gameState) { return(gameState.Grid[pos.x + this.direction.x, pos.y + this.direction.y].state); }
private static void ManualSokoban() { string level = " #####\n # ####\n # # #\n ## .#\n### ###.#\n# $ # #.#\n# $$# ###\n#@ #\n#####"; //string level = "####\n# .#\n# ###\n#*@ #\n# $ #\n# ###\n####"; Log("Level:\n" + level); MersenneTwister rng = new MersenneTwister(1 + threadIndex); ISPSimulationStrategy simulationStrategy = new SokobanRandomStrategy(); SokobanGameState s = new SokobanGameState(level, RewardType.NegativeBM, simulationStrategy); SokobanGameState backupState = (SokobanGameState)s.Clone(); bool quit = false; IPuzzleMove move = null; Console.WriteLine(s.PrettyPrint()); while (!quit) { ConsoleKeyInfo input = Console.ReadKey(); List <IPuzzleMove> moves = s.GetMoves(); switch (input.Key) { case ConsoleKey.UpArrow: if (moves.Contains(new SokobanGameMove("u"))) { move = new SokobanGameMove("u"); } else { move = new SokobanGameMove("U"); } break; case ConsoleKey.DownArrow: if (moves.Contains(new SokobanGameMove("d"))) { move = new SokobanGameMove("d"); } else { move = new SokobanGameMove("D"); } break; case ConsoleKey.LeftArrow: if (moves.Contains(new SokobanGameMove("l"))) { move = new SokobanGameMove("l"); } else { move = new SokobanGameMove("L"); } break; case ConsoleKey.RightArrow: if (moves.Contains(new SokobanGameMove("r"))) { move = new SokobanGameMove("r"); } else { move = new SokobanGameMove("R"); } break; case ConsoleKey.R: s = (SokobanGameState)backupState.Clone(); move = null; break; case ConsoleKey.Q: move = null; quit = true; break; } if (move != null) { Console.WriteLine("Move: " + move); s.DoMove(move); } Console.WriteLine(s.PrettyPrint()); Console.WriteLine("Score: " + s.GetScore() + " | isTerminal: " + s.isTerminal()); } }
private static int[] SokobanTest(double const_C, double const_D, int iterations, int restarts, string[] levels, uint seed, bool abstractSokoban, RewardType rewardType, bool stopOnResult, double epsilonValue, bool log) { uint threadIndex = GetThreadIndex(); RNG.Seed(seed + threadIndex); MersenneTwister rng = new MersenneTwister(seed + threadIndex); int currentLevelIndex = GetTaskIndex(threadIndex); ISPSimulationStrategy simulationStrategy; simulationStrategy = new SokobanEGreedyStrategy(epsilonValue, rng); IPuzzleState[] states = new IPuzzleState[levels.Length]; //SokobanMCTSStrategy player; //Debug.WriteLine("Solved random: "+randomSolved+"/"+levels.Length); // Debug.WriteLine(restart); int solvedLevels = 0; int[] rolloutsCount = new int[states.Length]; Stopwatch stopwatch = new Stopwatch(); long stateInitializationTime; long solvingTime; int totalRollouts = 0; int totalNodes = 0; List <int> visitsList = new List <int>(); List <int> raveVisitsList = new List <int>(); double totalDepth = 0; int totalNodesEliminated = 0; int totalNodesNotExpanded = 0; for (int i = 0; i < states.Length; i++) { RNG.Seed(seed + threadIndex); rng = new MersenneTwister(seed + threadIndex); if (simulationType == SimulationType.EpsilonGreedy) { simulationStrategy = new SokobanEGreedyStrategy(epsilonValue, rng); } else { simulationStrategy = new SokobanIDAstarStrategy(maxNodes, tableSize, 200, 0.2); } if (i % SinglePlayerMCTSMain.threadIndex != threadIndex) { continue; } stopwatch.Restart(); if (abstractSokoban) { states[i] = new AbstractSokobanState(levels[i], rewardType, useNormalizedPosition, useGoalMacro, useTunnelMacro, useGoalCut, simulationStrategy, rng); } else { states[i] = new SokobanGameState(levels[i], rewardType, simulationStrategy); } stopwatch.Stop(); stateInitializationTime = stopwatch.ElapsedMilliseconds; List <IPuzzleMove> moveList = new List <IPuzzleMove>(); //player = new SokobanMCTSStrategy(rng, iterations, 600, null, const_C, const_D, stopOnResult); //SP_MCTSAlgorithm mcts = new SP_MCTSAlgorithm(new SP_UCTTreeNodeCreator(const_C, const_D, rng), stopOnResult); OptMCTSAlgorithm mcts = new OptMCTSAlgorithm(new Opt_SP_UCTTreeNodeCreator(const_C, const_D, rng, ucb1Tuned, rave, raveThreshold, nodeRecycling), iterations, memoryBudget, stopOnResult, avoidCycles, useNodeElimination); string moves = ""; stopwatch.Restart(); moveList = mcts.Solve(states[i], iterations); stopwatch.Stop(); solvingTime = stopwatch.ElapsedMilliseconds; //moveList = player.GetSolution(states[i]); int pushCount = 0; foreach (IPuzzleMove m in moveList) { if (abstractSokoban) { //Debug.WriteLine("Move: " + m); //Debug.WriteLine(states[i]); SokobanPushMove push = (SokobanPushMove)m; foreach (IPuzzleMove basicMove in push.MoveList) { moves += basicMove; if (basicMove.move > 3)//the move is a push move { pushCount++; } } } else { moves += m; if (m.move > 3)//the move is a push move { pushCount++; } } states[i].DoMove(m); } if (states[i].EndState()) { solvedLevels++; totalRollouts += mcts.IterationsForFirstSolution; } else { totalRollouts += mcts.IterationsExecuted; } totalDepth += mcts.maxDepth; totalNodesEliminated += mcts.nodesEliminated; totalNodesNotExpanded += mcts.nodesNotExpanded; rolloutsCount[i] = mcts.IterationsExecuted; scores[i] = rolloutsCount[i]; solved[i] = states[i].EndState(); if (log) { Log("Level " + (i + 1) + "\titerations: " + mcts.IterationsExecuted + "\titerations for first solution: " + mcts.IterationsForFirstSolution + "\ttotal solutions: " + mcts.SolutionCount + "\tbest solution length (moves/pushes): " + moves.Count() + "/" + pushCount + "\tInit Time: " + TimeFormat(stateInitializationTime) + " - Solving Time: " + TimeFormat(solvingTime) + "\tTree depth: " + mcts.maxDepth + "\tNodes: " + mcts.NodeCount + "\tNodes Eliminated: " + mcts.nodesEliminated + "\tNodes Not Expanded: " + mcts.nodesNotExpanded + "\tBest solution: " + moves); } totalNodes += mcts.NodeCount; visitsList.AddRange(mcts.visits); raveVisitsList.AddRange(mcts.raveVisits); Console.Write("\r "); Console.Write("\rSolved " + solvedLevels + "/" + (i + 1)); } visitsList.Sort((x, y) => (x.CompareTo(y))); raveVisitsList.Sort((x, y) => (x.CompareTo(y))); double avgVisits = 0; foreach (int v in visitsList) { avgVisits += v; } double avgRaveVisits = 0; foreach (int v in raveVisitsList) { avgRaveVisits += v; } avgVisits /= visitsList.Count; avgRaveVisits /= raveVisitsList.Count; Log("Solved " + solvedLevels + "/" + levels.Length); Log("Total iterations: " + totalRollouts); Log("Total nodes: " + totalNodes); Log("Nodes eliminated: " + totalNodesEliminated); Log("Nodes Not Expanded: " + totalNodesNotExpanded); Log("avg nodes:" + ((double)totalNodes) / states.Length); Log("avg visits: " + avgVisits); Log("avg raveVisits: " + avgRaveVisits); Log("median visits: " + (visitsList.Count % 2 == 0 ? visitsList[visitsList.Count / 2] : (visitsList[visitsList.Count / 2] + visitsList[1 + visitsList.Count / 2]) / 2)); Log("median raveVisits: " + (raveVisitsList.Count % 2 == 0 ? raveVisitsList[raveVisitsList.Count / 2] : (raveVisitsList[raveVisitsList.Count / 2] + raveVisitsList[1 + raveVisitsList.Count / 2]) / 2)); Log("avg depth: " + totalDepth / states.Length); return(rolloutsCount); }