private void ConstructPortals() { PortalCells = new Dictionary <GridPoint, string>(); Portals = new Dictionary <string, IList <GridPoint> >(); var emptyCells = MazeCells .Where(kvp => DonutMazeCellType.Empty.Equals(kvp.Value.Type)); foreach (var emptyCell in emptyCells) { var point = emptyCell.Key; var movementDirections = new List <MovementDirection>() { MovementDirection.Down, MovementDirection.Left, MovementDirection.Right, MovementDirection.Up }; foreach (var direction in movementDirections) { // Assumption: One point can only be associated with at // most one portal. var neighbor1 = point.Move(direction, 1); if (!MazeCells.ContainsKey(neighbor1) || !DonutMazeCellType.Portal.Equals(MazeCells[neighbor1].Type)) { continue; } var neighbor2 = point.Move(direction, 2); if (!MazeCells.ContainsKey(neighbor2) || !DonutMazeCellType.Portal.Equals(MazeCells[neighbor2].Type)) { throw new Exception("Only one neighboring portal cell found"); } var portalId = string.Empty; if (MovementDirection.Right.Equals(direction) || MovementDirection.Up.Equals(direction)) { portalId = MazeCells[neighbor1].PortalLetter + MazeCells[neighbor2].PortalLetter; } else { portalId = MazeCells[neighbor2].PortalLetter + MazeCells[neighbor1].PortalLetter; } PortalCells.Add(point, portalId); if (!Portals.ContainsKey(portalId)) { Portals.Add(portalId, new List <GridPoint>()); } Portals[portalId].Add(point); } } EntrancePoint = new GridPoint3D(Portals[EntrancePortalId][0], 0); ExitPoint = new GridPoint3D(Portals[ExitPortalId][0], 0); }
public bool GetIsOnSide(GridPoint3D point, MovementDirection side) { // Note - because "up" increases Y, whereas the top is at 0 and // increasing y goes down, // we need to invert the meaning of Up and Down here return(side switch { MovementDirection.Left => point.X == 0, MovementDirection.Right => point.X == Width - 1, MovementDirection.Down => point.Y == 0, MovementDirection.Up => point.Y == Height - 1, _ => throw new Exception($"Invalid side {side}"), });
public string GetCellString(GridPoint3D point) { if (BugCells.Contains(point)) { return("#"); } if (GetIsPointOffMap(point)) { return(" "); } if (IsRecursive && CenterPointXY.Equals(point.XYPoint)) { return("?"); } return("."); }
public BigInteger GetBiodiversityRating(int layer) { BigInteger result = 0; BigInteger cellPointValue = 1; for (int y = 0; y < Height; y++) { for (int x = 0; x < Width; x++) { var point = new GridPoint3D(x, y, layer); if (BugCells.Contains(point)) { result += cellPointValue; } cellPointValue *= 2; } } return(result); }
public bool GetIsOnOuterWall(GridPoint3D point) { if (point.X >= OuterWallLeft && point.X <= OuterWallRight && ( point.Y == OuterWallTop || point.Y == OuterWallBottom)) { return(true); } if (point.Y >= OuterWallTop && point.Y <= OuterWallBottom && ( point.X == OuterWallLeft || point.X == OuterWallRight)) { return(true); } return(false); }
public static ErisMapState CreateMap( IList <string> mapDefinition, bool isRecursive) { int height = mapDefinition.Count; int width = mapDefinition.Max(row => row.Length); var bugCells = new HashSet <GridPoint3D>(); for (int y = 0; y < mapDefinition.Count; y++) { var rowDefinition = mapDefinition[y]; for (int x = 0; x < rowDefinition.Length; x++) { var cellDefinition = rowDefinition[x]; var point = new GridPoint3D(x, y, 0); CellType cellType = cellDefinition switch { '.' => CellType.Empty, '#' => CellType.Bug, _ => CellType.Empty, }; if (CellType.Bug.Equals(cellType)) { bugCells.Add(point); } } } var result = new ErisMapState( bugCells: bugCells, width: width, height: height, minZ: 0, maxZ: 0, isRecursive: isRecursive); return(result); }
public IList <GridPoint3D> GetNeighbors(GridPoint3D point) { var result = new List <GridPoint3D>(); var directions = new List <MovementDirection>() { MovementDirection.Left, MovementDirection.Right, MovementDirection.Up, MovementDirection.Down }; foreach (var direction in directions) { var neighbor = point.Move(direction, 1); if (!IsRecursive) { result.Add(neighbor); } else // Recursive map { // Check if the neighbor is the middle point if (neighbor.XYPoint.Equals(CenterPointXY)) { // Get the outer cells adjacent to this one in the // inner layer // Handle y is inverted (up actually decreases y), // the inner layer side is actually the same as the // vertical movement direction var innerLayerSide = direction; if (MovementDirection.Left.Equals(direction) || MovementDirection.Right.Equals(direction)) { innerLayerSide = MovementDirectionHelper.GetOppositeDirection(direction); } int[] edgeValues; var coordinateOrder = string.Empty; switch (innerLayerSide) { case MovementDirection.Left: edgeValues = new int[4] { 0, point.Z + 1, 0, Height - 1 }; coordinateOrder = "XZY"; break; case MovementDirection.Right: edgeValues = new int[4] { Width - 1, point.Z + 1, 0, Height - 1 }; coordinateOrder = "XZY"; break; case MovementDirection.Up: edgeValues = new int[4] { 0, point.Z + 1, 0, Width - 1 }; coordinateOrder = "YZX"; break; case MovementDirection.Down: edgeValues = new int[4] { Height - 1, point.Z + 1, 0, Width - 1 }; coordinateOrder = "YZX"; break; default: throw new Exception($"Invalid side {direction}"); } var neighborsOnInnerLayer = GridHelper3D.GetPointsAlongEdge( edgeValues: edgeValues, coordinateOrder: coordinateOrder); result.AddRange(neighborsOnInnerLayer); } // Check if the neighbor is off the map else if (GetIsPointOffMap(neighbor)) { // Get the adjacent cell to the center in the outer layer var outerLayerCenterCell = new GridPoint3D(CenterPointXY, point.Z - 1); neighbor = outerLayerCenterCell.Move(direction, 1); result.Add(neighbor); } else { result.Add(neighbor); } } } return(result); }
public void UpdateVelocity(Tuple <int, int, int> acceleration) { Velocity = Velocity.Move(acceleration); }
public Moon(GridPoint3D position, GridPoint3D velocity) { Position = position.Move(new Tuple <int, int, int>(0, 0, 0)); Velocity = velocity.Move(new Tuple <int, int, int>(0, 0, 0)); }
public Moon(int x, int y, int z, int vX, int vY, int vZ) { Position = new GridPoint3D(x, y, z); Velocity = new GridPoint3D(vX, vY, vZ); }
public void Set(TCell cell, GridPoint3D point) { GridCoord3D coord = new GridCoord3D(Size, point.X, point.Y, point.Z); Set(cell, coord); }
public Moon(int x, int y, int z) { Position = new GridPoint3D(x, y, z); Velocity = new GridPoint3D(); }
public Moon() { Position = new GridPoint3D(); Velocity = new GridPoint3D(); }
public IList <GridPoint3D> GetEmptyNeighbors(GridPoint3D currentPosition) { var result = new List <GridPoint3D>(); var movementDirections = new List <MovementDirection>() { MovementDirection.Down, MovementDirection.Left, MovementDirection.Right, MovementDirection.Up }; foreach (var movementDirection in movementDirections) { var neighborPoint = currentPosition.Move(movementDirection, 1); if (!MazeCells.ContainsKey(neighborPoint.XYPoint)) { continue; } var type = MazeCells[neighborPoint.XYPoint].Type; if (DonutMazeCellType.Wall.Equals(type)) { continue; } if (DonutMazeCellType.Empty.Equals(type)) { result.Add(neighborPoint); } else if (DonutMazeCellType.Portal.Equals(type)) { // Assumption: One point can be associated with at most // one portal var portalId = PortalCells[currentPosition.XYPoint]; if (EntrancePortalId.Equals(portalId) || ExitPortalId.Equals(portalId)) { continue; } bool isOnOuterEdge = GetIsOnOuterWall(currentPosition); // If this is a recursive maze, then outer portals only // work for z > 1 if (IsRecursive && isOnOuterEdge && currentPosition.Z == 0) { continue; } var connectedPoint = Portals[portalId] .Where(p => !p .Equals(currentPosition.XYPoint)) .FirstOrDefault(); if (connectedPoint == null) { throw new Exception("Portal found with no connected point"); } // Handle recursive maze - if this is an inner portal, then // we are going in a level, so increment z // If this is an outer portal, then we are going out a // level, so decrease z int connectedPointZ = currentPosition.Z; if (IsRecursive) { if (isOnOuterEdge) { connectedPointZ--; } else if (GetIsOnInnerWall(currentPosition)) { connectedPointZ++; } } // The connected point is stored in the maze at z=0, so // move it to the appropriate z index result.Add(new GridPoint3D(connectedPoint, connectedPointZ)); } else { throw new Exception($"Invalid cell type {type}"); } } return(result); }
private void AssertPoint(GridPoint3D point, int x, int y, int z) { Assert.AreEqual(x, point.X); Assert.AreEqual(y, point.Y); Assert.AreEqual(z, point.Z); }
public Moon(GridPoint3D position) { Position = position.Move(new Tuple <int, int, int>(0, 0, 0)); Velocity = new GridPoint3D(); }
public TCell Get(GridPoint3D point) { GridCoord3D coord = new GridCoord3D(Size, point); return(Get(coord)); }