/// <summary> /// Run the simulations and save result to ViewState and JS script block /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void btnRunSimulations_OnClick(object sender, EventArgs e) { var deck = new Deck(); List<int> position = Request.Form["robotPosition"].Split(',').Select(int.Parse).ToList(); var cards = Request.Form["cards"].Split(',').Select(x => GetCardPriority(deck, x)); var robot = new Robot { Position = new Coordinate {X = position[0], Y = position[1]}, Facing = (Orientation)Enum.Parse(typeof(Orientation), Request.Form["robotOrientation"]) }; foreach (var priority in cards) { robot.DealCard(priority); } var map = MapParser.JsonToMap(LoadMapJson("~/Maps/ScottRallyMap.rrdl")); var game = new Game(new Map {Squares = map}, new List<Robot> {robot}); game.Initialize(); List<List<CardExecutionResult>> results = Simulator.Simulate(robot); List<List<CardExecutionResult>> productiveResults = results.Where(result => result.Last().Position.X != -1).ToList(); ViewState["PosX"] = position[0]; ViewState["PosY"] = position[1]; ViewState["Facing"] = Request.Form["robotOrientation"]; ViewState["Cards"] = Request.Form["cards"]; ClientScript.RegisterClientScriptBlock(GetType(), "results", "results = " + JsonConvert.SerializeObject(productiveResults, Formatting.Indented), true); }
public void Convey(Robot robot) { // Convey the robot a single square Coordinate target = robot.Position; if (Exit == Orientation.Bottom) target.Y += 1; else if (Exit == Orientation.Top) target.Y -= 1; else if (Exit == Orientation.Left) target.X -= 1; else target.X += 1; ITile targetTile = robot.Game.Board.GetTile(target); if (targetTile == null || targetTile is Pit) { // Robot conveyed off the board or into a pit robot.Position = new Coordinate {X = -1, Y = -1}; return; } var conveyer = targetTile as Conveyer; if (conveyer != null) { Rotation rotation = conveyer.ConveyerRotation(Utilities.GetOppositeOrientation(Exit)); if (rotation == Rotation.Clockwise) robot.RotateRight(); else if (rotation == Rotation.CounterClockwise) robot.RotateLeft(); } robot.Position = target; }
public void Rotate(Robot robot) { if (Direction == Rotation.Clockwise) robot.RotateRight(); else robot.RotateLeft(); }
protected void btnRunSimulations_OnClick(object sender, EventArgs e) { List<int> position = Request.Form["robotPosition"].Split(',').Select(int.Parse).ToList(); var cards = Request.Form["cards"].Split(',').Select(int.Parse); var robot = new Robot { Position = new Coordinate {X = position[0], Y = position[1]}, Facing = (Orientation)Enum.Parse(typeof(Orientation), Request.Form["robotOrientation"]) }; foreach (var c in cards) { robot.DealCard(c); } var game = new Game { Board = { Squares = Maps.GetMap(Maps.MapLayouts.ScottRallyMap) }, Robots = new List<Robot> { robot } }; game.Initialize(); List<List<CardExecutionResult>> results = Simulator.RunSimulations(robot); List<List<CardExecutionResult>> productiveResults = results.Where(result => result.Last().Position.X != -1).ToList(); ViewState["PosX"] = position[0]; ViewState["PosY"] = position[1]; ViewState["Facing"] = Request.Form["robotOrientation"]; ViewState["Cards"] = Request.Form["cards"]; ClientScript.RegisterClientScriptBlock(GetType(), "results", "results = " + JsonConvert.SerializeObject(productiveResults, Formatting.Indented), true); }
public static string RunSimulations(string body) { JToken json = JToken.Parse(body); var deck = new Deck(); IEnumerable<int> cards = json["cards"].ToString().Split(',').Select(x => GetCardPriority(deck, x)); List<int> robotPosition = json["robotPosition"].ToString().Split(',').Select(int.Parse).ToList(); string robotOrientation = json["robotOrientation"].ToString(); var robot = new Robot { Position = new Coordinate { X = robotPosition[0], Y = robotPosition[1] }, Facing = (Orientation)Enum.Parse(typeof(Orientation), robotOrientation) }; foreach (var priority in cards) { robot.DealCard(priority); } var map = MapParser.JsonToMap(LoadMapJson(ActiveMap)); var game = new Game(new Map { Squares = map }, new List<Robot> { robot }); game.Initialize(); List<List<CardExecutionResult>> results = Simulator.Simulate(robot); List<List<CardExecutionResult>> productiveResults = results.Where(result => result.Last().Position.X != -1).ToList(); return JsonConvert.SerializeObject(productiveResults, Formatting.Indented); }
public void Push(Robot robot, int register) { if (!Registers.Contains(register)) return; Coordinate target = robot.Position; var floorTile = robot.Game.Board.Tile<Floor>(robot.Position); if (floorTile == null) return; foreach (var edge in floorTile.Edges) { if (edge.Item2 == this) { if (edge.Item1 == Orientation.Top) target.Y += 1; else if (edge.Item1 == Orientation.Bottom) target.Y -= 1; else if (edge.Item1 == Orientation.Left) target.X += 1; else target.X -= 1; if (floorTile.GetEdge(Utilities.GetOppositeOrientation(edge.Item1)) != null) { // There is an opposite edge. I'm not exactly sur ewhat is supposed to happen. Most likely just not move return; } ITile targetTile = robot.Game.Board.Tile(target); if (targetTile == null || targetTile is Pit) { // pushed to death; robot.Position = Coordinate.OutOfBounds; return; } var targetFloor = (Floor) targetTile; if (targetFloor.GetEdge(edge.Item1) != null) { // blocked from entering! return; } robot.Position = target; return; } } }
/// <summary> /// Runs simulations on moves based on the cards the robot currently has assigned. /// Robot is expected to be initialized and part of an existing Game. /// The robot will not be in the same state after simulation is executed. /// </summary> /// <param name="robot">Robot to run simulations for</param> /// <returns>List of results</returns> public static List<List<CardExecutionResult>> Simulate(Robot robot) { var results = new List<List<CardExecutionResult>>(); List<List<ProgramCardType>> permutations = CalculateMovePermutations(robot); Coordinate position = robot.Position; Orientation facing = robot.Facing; foreach (var permutation in permutations) { robot.Position = position; robot.Facing = facing; robot.Damage = 0; robot.PickUpCards(); var deck = new Deck(); var permutationResult = new List<CardExecutionResult>(); for (int i = 0 ; i < permutation.Count; ++i) { var card = deck.GetCard(permutation[i]); robot.DealCard(card.Priority, i + 1); } robot.Game.StartTurn(false /* Deal Cards */); int previousDamage = 0; while (true) { int registersLeft = robot.Game.ExecuteNextRegister(); permutationResult.Add(new CardExecutionResult { Card = permutation[permutationResult.Count], Position = robot.Position, Facing = robot.Facing, Damage = robot.Damage - previousDamage }); previousDamage = robot.Damage; if (registersLeft == 0) break; } robot.Game.EndTurn(); results.Add(permutationResult); } return results; }
/// <summary> /// Calculate all possible move permutations given a robots set of cards /// </summary> /// <param name="robot">Robot</param> /// <returns>List of permutations</returns> internal static List<List<ProgramCardType>> CalculateMovePermutations(Robot robot) { var permutations = new List<List<ProgramCardType>>(); // This is the list of cards that can be placed. Locked registers are not included in this list // and should be appended to the end of each list if necessary IEnumerable<ProgramCardType> cards = robot.CardsToPlace().Select(ProgramCard.GetCardTypeByPriority); var root = new PermutationNode(); BuildCardPermutationTree(root, cards); BuildCardPermutationList(permutations, root); return permutations; }
public void Simulator_CalculateMovePermutations_6UniqueCards() { // Arrange var robot = new Robot(); robot.DealCard(10); // UTurn robot.DealCard(70); // RotateLeft robot.DealCard(80); // RotateRight robot.DealCard(430); // BackUp robot.DealCard(490); // Move1 robot.DealCard(790); // Move3 // Act var moves = Simulator.CalculateMovePermutations(robot); // Assert Assert.AreEqual(720, moves.Count); }
public void Simulator_CalculateMovePermutations_7Cards_2TypeRepeatedTwice() { // Arrange var robot = new Robot(); robot.DealCard(10); // UTurn robot.DealCard(20); // UTurn robot.DealCard(70); // RotateLeft robot.DealCard(80); // RotateRight robot.DealCard(430); // BackUp robot.DealCard(490); // Move1 robot.DealCard(500); // Move1 // Act var moves = Simulator.CalculateMovePermutations(robot); // Assert Assert.AreEqual(690, moves.Count); }
public void Simulator_PermutationCounts_7Cards_2TypeRepeatedTwice() { // Arrange var robot = new Robot(); robot.DealCard(10); // UTurn robot.DealCard(20); // UTurn robot.DealCard(70); // RotateLeft robot.DealCard(80); // RotateRight robot.DealCard(430); // BackUp robot.DealCard(490); // Move1 robot.DealCard(500); // Move1 // Act int permutations = PermutationCounts(robot); // Assert Assert.AreEqual(630, permutations); }
public void Simulator_RunSimulations_7Cards2TypeRepeatedTwice() { // Arrange var robot = new Robot(); robot.DealCard(10); // UTurn robot.DealCard(20); // UTurn robot.DealCard(70); // RotateLeft robot.DealCard(80); // RotateRight robot.DealCard(430); // BackUp robot.DealCard(490); // Move1 robot.DealCard(500); // Move1 var game = new Game(new Map {Squares = Maps.GetMap(Maps.MapLayouts.ScottRallyMap)}, new List<Robot> {robot}); game.Initialize(); // Act List<List<CardExecutionResult>> results = Simulator.Simulate(robot); // Assert Assert.AreEqual(690, results.Count); }
protected void Convey(Robot robot) { Coordinate target = TargetCoordinate(robot.Position); ITile targetTile = robot.Game.Board.Tile(target); if (targetTile == null || targetTile is Pit) { // Robot conveyed off the board or into a pit robot.Position = Coordinate.OutOfBounds; return; } var conveyer = targetTile as Conveyer; if (conveyer != null) { Rotation rotation = conveyer.ConveyerRotation(Utilities.GetOppositeOrientation(Exit)); if (rotation == Rotation.Clockwise) robot.Facing = Utilities.ClockwiseRotation(robot.Facing); else if (rotation == Rotation.CounterClockwise) robot.Facing = Utilities.CounterclockwiseRotation(robot.Facing); } robot.Position = target; }
private static int PermutationCounts(Robot robot) { // BUG: This math does not match our function for calculating permutations. FWIW, I trust the code more than this math. // Calculate the number of unique permutations possible with the cards to place. // For example, if we need to place the following cards // (2) Rotate Left, (1) Rotate Right, (1) Move 1, (1) Move 2 and (2) Move 3 // Given there are 7 cards to place and the number of cards we need is 5 // we are calculating P(n,r) where n = 7 and r = 5. // Also, given Rotate Left is repeated twice we have x1 = 2 and x2 = 2 for the // Move 3 repetitions. // Permutations = P(n,r) / (x1!x2!) // Permutations = P(7,5) / (2!2!) // Permutations = (7! / (7 - 5)!) / (2!2!) // Permutations = (5040 / 2) / (4) // Permutations = 2520 / 4 // Permutations = 630 List<int> cardsToPlace = robot.CardsToPlace().ToList(); List<ProgramCardType> cardTypesToPlace = cardsToPlace.Select(ProgramCard.GetCardByPriority).ToList(); int n = cardTypesToPlace.Count(); int r = Math.Min(n, Constants.RobotRegisters); List<Tuple<ProgramCardType, int>> cardDuplicateCounts = Permutations.GetDuplicateItemCounts(cardTypesToPlace).ToList(); double dividend = (Permutations.Factorial(n) / Permutations.Factorial(n - r)); double divisor = cardDuplicateCounts.Aggregate<Tuple<ProgramCardType, int>, double>(1, (current, dupe) => current * Permutations.Factorial(dupe.Item2)); return (int)(dividend / divisor); }