public override bool CommunicateInfo(Vector2Int crossingCoords, LevelBoard.Directions dirIn, LevelBoard.Directions dirOut) { base.CommunicateInfo(crossingCoords, dirIn, dirOut); var connected = false; // If the Slime has come from a Crossing if (this.CrossingLog.Count > 0) { var last = this.CrossingLog.Peek(); // Get last visited Crossing // If the last visited Crossing is not the present Crossing if (last.Key != crossingCoords) { // Add this Crossing as the last one's child connected = this.RegisterCrossingConnection(last.Key, last.Value, crossingCoords, dirIn); } else if (this.DeadEnds && !this.PathBlocked) { this.RegisterDeadEnd(crossingCoords, LevelBoard.InvertDirection(dirIn)); connected = true; } this.PathBlocked = false; } // Save this Crossing as its most recently visited, and Direction from which it left this.CrossingLog.Push(new KeyValuePair <Vector2Int, LevelBoard.Directions>(crossingCoords, dirOut)); return(connected); }
public void Initialize(LevelBoard board, List <Piece> pieces, List <Tile> tiles, WinCondition winCondition, Dictionary <string, Resource> resources) { this.Board = board; this.Pieces = pieces; this.Tiles = tiles; this.WinCondition = winCondition; this.ResourcesAvailable = resources; this.Agents = new List <Agent>(); foreach (var piece in pieces) { this.Board.PlacePiece(piece, piece.Coords); } this.Agents = this.Board.GetAllAgents(); foreach (var tile in tiles) { this.Board.PlaceTile(tile, tile.Coords); } this.PiecesObj = this.transform.GetChild(0).gameObject; this.TilesObj = this.transform.GetChild(1).gameObject; }
protected Dictionary <LevelBoard.Directions, Piece> CheckAdjacentSolderTiles(Agent agent) { Dictionary <LevelBoard.Directions, Piece> adjacents = new Dictionary <LevelBoard.Directions, Piece>(); // For each cardinal direction for (var i = 0; i < 4; i++) { var dir = (LevelBoard.Directions)(i * 2); // Create Direction // Get coordinates of adjacent Space in that Direction var coords = LevelBoard.GetAdjacentCoords(agent.Coords, dir); // Get Tile at that Space var tile = agent.TileAt(coords); // If there's a Solder Tile there if (tile != null && tile.Type == Tile.Types.Solder) { // Get Piece at that Space var piece = agent.PieceAt(coords); // Add adjacency adjacents.Add(dir, piece); } } return(adjacents); }
public override void RollBackInfo(Vector2Int crossingCoords, LevelBoard.Directions dirIn, LevelBoard.Directions dirOut, bool connected) { // Pop last Log entry this.CrossingLog.Pop(); // If the Slime had come from a Crossing and a connection was made if (this.CrossingLog.Count > 0 && connected) { var last = this.CrossingLog.Peek(); // Get last visited Crossing // If the last visited Crossing is not the present Crossing if (last.Key != crossingCoords) { // Disconnect the Crossings this.UnregisterCrossingConnection(last.Key, last.Value, crossingCoords, dirIn); } else if (this.DeadEnds) { this.UnregisterDeadEnd(crossingCoords, LevelBoard.InvertDirection(dirIn)); } } base.RollBackInfo(crossingCoords, dirIn, dirOut, connected); }
protected virtual Dictionary <LevelBoard.Directions, CircuitComponent> CheckAdjacentSolderTiles(Agent agent) { Dictionary <LevelBoard.Directions, CircuitComponent> adjacents = new Dictionary <LevelBoard.Directions, CircuitComponent>(); for (var i = 0; i < 4; i++) { var dir = (LevelBoard.Directions)(i * 2); var coords = LevelBoard.GetAdjacentCoords(agent.Coords, dir); var tile = agent.TileAt(coords); // If there's a Solder Tile there if (tile != null && tile.Type == Tile.Types.Solder) { var piece = agent.PieceAt(coords); if (piece == null) { adjacents.Add(dir, null); } else if (piece is CircuitComponent component && component.Stats.Food < component.Stats.MaxFood) { adjacents.Add(dir, component); } } } return(adjacents); }
override public Action Available(Agent agent) { var adjacents = CheckAdjacentSolderTiles(agent); var start = ((int)agent.Orientation) / 2; for (var i = 0; i < 4; i++) { var dir = (LevelBoard.Directions)(((start + i + 3) % 4) * 2); if (adjacents.TryGetValue(dir, out var component)) { var tcoords = LevelBoard.GetAdjacentCoords(agent.Coords, dir); if (tcoords.sqrMagnitude > 1000f) { continue; } if (component == null) { return(new ElectricMovement(dir, tcoords)); } else { return(new Charge(component)); } } } return(null); }
public static GameObject Instantiate(Transform parent, string prefabName, Vector2Int coords) { var position = LevelBoard.WorldCoords(coords); var rotation = Quaternion.identity; return(GameObject.Instantiate((GameObject)Resources.Load("Prefabs/Board Items/" + prefabName), position, rotation, parent)); }
public virtual void RollBackInfo(Vector2Int crossingCoords, LevelBoard.Directions dirIn, LevelBoard.Directions dirOut, bool connected) { // Unregister path by which the present Crossing was reached this.UnregisterExploredPath(crossingCoords, LevelBoard.InvertDirection(dirIn)); // Unregister path chosen to exit present Crossing this.UnregisterExploredPath(crossingCoords, dirOut); }
public virtual bool CommunicateInfo(Vector2Int crossingCoords, LevelBoard.Directions dirIn, LevelBoard.Directions dirOut) { // Register path chosen to exit present Crossing this.RegisterExploredPath(crossingCoords, dirOut); // Register path by which the present Crossing was reached this.RegisterExploredPath(crossingCoords, LevelBoard.InvertDirection(dirIn)); return(true); }
private static GameObject Instantiate(Puzzle puzzle, string prefabName, Vector2Int coords) { var position = LevelBoard.WorldCoords(coords); var rotation = Quaternion.identity; var parent = puzzle.transform.GetChild(0); return(GameObject.Instantiate((GameObject)Resources.Load("Prefabs/Board Items/" + prefabName), position, rotation, parent)); }
// Reactivates the Agent public void Reactivate(Vector2Int coords) { this.Reveal(); this.PlacePiece(this, coords); this.transform.position = LevelBoard.WorldCoords(coords); this.Active = true; }
public override bool Undo(Agent agent) { var oppositeDir = (LevelBoard.Directions)(((int)this.Direction + 4) % 8); var origCoords = LevelBoard.GetAdjacentCoords(this.MoveCoords, oppositeDir); agent.Move(origCoords, 1000f); agent.Rotate(this.OrigOrientation, 1f); agent.MoveInBoard(origCoords); agent.RotateInBoard(this.OrigOrientation); return(base.Undo(agent)); }
private void SaveSmartInfo(Agent agent) { // If this is a Crossing if (this.Crossing && agent is SmartElectricSlime smart) { // Save the Direction the Slime reached the Crossing from this.OrigOrientation = smart.Orientation; // Save Direction Slime entered component by/left crossing from this.WentTo = LevelBoard.GetDirection(smart.Coords, this.ComponentCoords); this.RegisteredConnection = smart.CommunicateInfo(this.ChargeCoords, this.OrigOrientation, this.WentTo); } }
override public Action Available(Agent agent) { List<Vector2Int> pathToTarget = agent.PathToNearest(this.TargetCharacteristics, 3); if(pathToTarget != null) { var dir = LevelBoard.GetDirection(pathToTarget[0], pathToTarget[1]); var target = agent.PieceAt(pathToTarget[pathToTarget.Count - 1]); return new SeekTarget(pathToTarget[1], dir, target); } return null; }
public void RemoveCrossingConnection(Vector2Int startCoords, LevelBoard.Directions dirOut, Vector2Int endCoords, LevelBoard.Directions dirIn) { if (this.Crossings.TryGetValue(startCoords, out var start) && this.Crossings.TryGetValue(endCoords, out var end)) { start.RemoveConnection(dirOut); var invDir = LevelBoard.InvertDirection(dirIn); end.RemoveConnection(invDir); Debug.Log("Removed connection between " + startCoords + " through " + dirOut + " to " + endCoords); Debug.Log("Removed connection between " + endCoords + " through " + invDir + " to " + startCoords); } }
public static Puzzle CreateEmpty(int width, int height) { GameObject puzzleObj = GameObject.Instantiate(Resources.Load <GameObject>("Prefabs/Puzzle")); puzzleObj.name = "Puzzle"; Puzzle puzzle = puzzleObj.GetComponent <Puzzle>(); GameObject boardObj = GameObject.Instantiate(Resources.Load <GameObject>("Prefabs/Board")); boardObj.name = "Board"; boardObj.transform.parent = puzzleObj.transform; LevelBoard board = boardObj.GetComponent <LevelBoard>(); board.Initialize(width, height); puzzle.Initialize(board); return(puzzle); }
override public Action Available(Agent agent) { // If the Agent is a Component if (agent is CircuitComponent component) { // If the Component is connected and has surplus charge if (component.Connections.Count > 0 && component.Stats.Food > 0) { ElectricSlime charge = null; // If there are Slimes stored if (component.Charges.Count > 0) { charge = component.Charges[component.Charges.Count - 1]; // Get the next Slime to be discharged // Find the approapriate connection to discharge it to var componentExitCoords = component.Coords + component.Footprint[component.Footprint.Length - 1]; LevelBoard.Directions inDir = LevelBoard.GetDirection(charge.Coords, component.Coords); var coords = component.RouteEnergy(inDir); // If an approapriate connection was found if (coords.x != -1) { return(new Discharge(charge, coords)); // Return the potential Action } } // If there are no Slimes stored else { var coords = component.RouteEnergy(LevelBoard.Directions.North); if (coords.x != -1) { return(new Discharge(charge, coords)); } } } } return(null); }
public bool AddCrossingConnection(Vector2Int startCoords, LevelBoard.Directions dirOut, Vector2Int endCoords, LevelBoard.Directions dirIn) { if (this.Crossings.TryGetValue(startCoords, out var start) && this.Crossings.TryGetValue(endCoords, out var end)) { var first = start.AddConnection(dirOut, end); var invDir = LevelBoard.InvertDirection(dirIn); var second = end.AddConnection(invDir, start); //if(first) Debug.Log("Added connection between " + startCoords + " through " + dirOut + " to " + endCoords); //if(second) Debug.Log("Added connection between " + endCoords + " through " + invDir + " to " + startCoords); return(first || second); } return(false); }
virtual public bool Move(Vector2Int targetCoords, float minSpeed = 0f) { var targetPosition = LevelBoard.WorldCoords(targetCoords); var speed = Mathf.Max(minSpeed, this.Stats.Speed); var maxVelocity = speed / 100f; var currentPosition = this.transform.position; // If the distance to the Target Position exceeds what can be traveled in one Step if (Vector3.Distance(currentPosition, targetPosition) > maxVelocity) { var dX = targetPosition.x - currentPosition.x; // Distance to travel (North - South) var dZ = targetPosition.z - currentPosition.z; // Distance to travel (West - East) var norm = (new Vector3(dX, 0, dZ)).normalized; // Normalize the distance vector; var rate = Time.deltaTime / EXPECTED_DELTA; if (minSpeed == 1f) { rate = 1f; } this.transform.position += norm * ((float)(maxVelocity * rate)); // Apply movement return(false); } // If the Agent is within a one Step distance of the Target Position else { this.transform.position = targetPosition; // Set their position to the Target Position return(true); } }
public override bool Confirm(Agent agent) { if (agent is CircuitComponent component) { if (component.IsFree(this.TargetCoords)) { if (component.Charges.Count == 0) { var componentFootprint = component.GetFootprint(); LevelBoard.Directions ori = LevelBoard.GetDirection(componentFootprint[componentFootprint.Length - 1], this.TargetCoords); var piece = component.CreatePiece(new Piece.Characteristics(component.GetChargeType()), this.TargetCoords, ori, component.Turn + 1); this.Charge = (ElectricSlime)piece; this.NewCharge = true; } else { component.ReleaseCharge(this.Charge, this.TargetCoords); var outDir = LevelBoard.GetDirection(agent.Coords, this.TargetCoords); this.Charge.RotateInBoard(outDir); this.Charge.Rotate(outDir, 1f); } this.Charge.Hide(); return(true); } } return(false); }
public override Action Available(Agent agent) { var adjacents = this.CheckAdjacentSolderTiles(agent); #region Crossing Attributes var crossing = false; Dictionary <LevelBoard.Directions, int> utilities = null; var slime = (SmarterElectricSlime)agent; // If this is a Crossing if (adjacents.Count > 2) { crossing = true; slime.UpdateCrossing(slime.Coords, new List <LevelBoard.Directions>(adjacents.Keys)); utilities = slime.GetUtilities(slime.Coords); } #endregion var start = ((int)(agent.Orientation)) / 2; var maxUtility = float.MinValue; var bestChoice = LevelBoard.Directions.None; var isMove = true; // For each cardinal Direction for (var i = 0; i < 4; i++) { // Make the Direction var dir = (LevelBoard.Directions)(((start + i + 3) * 2) % 8); // If there is an adjacent Solder Tile if (adjacents.TryGetValue(dir, out var piece)) { var utility = (4 - i) * 0.25f; // If this is a Crossing get the Directions utility if (crossing && utilities.ContainsKey(dir)) { utility += utilities[dir]; } if (dir == LevelBoard.InvertDirection(agent.Orientation)) { if (utility > 0) { utility *= 0.5f; } else { utility *= 2f; } } // If there's a Piece that is not a Component // Or a Component that is at capacity, check the next Direction if ((piece != null && !(piece is CircuitComponent)) || (piece is CircuitComponent component && component.Stats.Food >= component.Stats.MaxFood)) { if (utility > maxUtility) { slime.PathBlocked = true; } continue; } // If the utility is better going this way if (utility > maxUtility) { maxUtility = utility; bestChoice = dir; isMove = piece == null; } } } // If the best choice is not to stay in place if (bestChoice != LevelBoard.Directions.None) { if (isMove) { return(new SmarterElectricMovement(bestChoice, LevelBoard.GetAdjacentCoords(agent.Coords, bestChoice), crossing)); } else { return(new Charge((CircuitComponent)adjacents[bestChoice], crossing)); } } return(null); }
override public Action Available(Agent agent) { var adjacents = CheckAdjacentSolderTiles(agent); #region Crossing Attributes var crossing = false; List <LevelBoard.Directions> unexplored = null; if (adjacents.Count > 2) { crossing = true; var slime = (SmartElectricSlime)agent; slime.UpdateCrossing(slime.Coords, new List <LevelBoard.Directions>(adjacents.Keys)); unexplored = slime.GetUnexploredPaths(slime.Coords); } #endregion var start = ((int)(agent.Orientation)) / 2; var maxUtility = 0; var bestChoice = LevelBoard.Directions.None; var isMove = true; // For each cardinal Direction for (var i = 0; i < 4; i++) { // Make the Direction var dir = (LevelBoard.Directions)(((start + i + 3) * 2) % 8); // If there is an adjacent Solder Tile if (adjacents.TryGetValue(dir, out var piece)) { var utility = 1; // If there's a Piece that is not a Component // Or a Component that is at capacity, check the next Direction if ((piece != null && !(piece is CircuitComponent)) || (piece is CircuitComponent component && component.Stats.Food >= component.Stats.MaxFood)) { continue; } // If this Direction has not been explored if (crossing && unexplored.Contains(dir)) { utility += 1; } // If the utility is better going this way if (utility > maxUtility) { maxUtility = utility; bestChoice = dir; isMove = piece == null; } } } // If the best choice is not to stay in place if (bestChoice != LevelBoard.Directions.None) { if (isMove) { return(new SmartElectricMovement(bestChoice, LevelBoard.GetAdjacentCoords(agent.Coords, bestChoice), crossing)); } else { return(new Charge((CircuitComponent)adjacents[bestChoice], crossing)); } } return(null); }
public bool RotatePieceRight(Piece piece) { LevelBoard.Directions newDir = LevelBoard.GetNextDirection(piece.Orientation, 2); return(this.RotatePiece(piece, newDir)); }
public Vector2Int RouteEnergy(Vector2Int entryPoint) { LevelBoard.Directions entryDir = LevelBoard.GetDirection(entryPoint, this.Coords); return(this.RouteEnergy(entryDir)); }
public List <Piece> PiecesInSight(float range) { float toExplore = range; List <Piece> pieces = new List <Piece>(); Queue <Vector2Int> queue = new Queue <Vector2Int>(); queue.Enqueue(this.Coords); Dictionary <Vector2Int, LevelBoard.Directions> toExpand = new Dictionary <Vector2Int, LevelBoard.Directions> { { this.Coords, LevelBoard.Directions.None } }; Queue <Vector2Int> nextQueue; Dictionary <Vector2Int, LevelBoard.Directions> toExpandNext; while (toExplore > 0f) { nextQueue = new Queue <Vector2Int>(); toExpandNext = new Dictionary <Vector2Int, LevelBoard.Directions>(); while (queue.Count > 0) { Vector2Int coords = queue.Dequeue(); if (!toExpand.TryGetValue(coords, out LevelBoard.Directions originDir)) { continue; } toExpand.Remove(coords); int dirId = (int)originDir; Vector2Int adjCoords; Piece found; switch (originDir) { case LevelBoard.Directions.None: for (int i = 0; i < 8; i++) { LevelBoard.Directions checkDir = (LevelBoard.Directions)(i % 8); adjCoords = LevelBoard.GetAdjacentCoords(coords, checkDir); // Out of Bounds if (adjCoords.x == -1) { continue; } found = this.Puzzle.GetPiece(adjCoords); // No Piece in the space if (found == null) { if (i % 2 == 0 && toExplore - 1 >= 0f || i % 2 == 1 && toExplore - 1 >= 0.5f) { nextQueue.Enqueue(adjCoords); // Queue position to be checked toExpandNext.Add(adjCoords, checkDir); // List direction it was reached from } continue; } pieces.Add(found); // Add Piece to the list } break; case LevelBoard.Directions.East: case LevelBoard.Directions.South: case LevelBoard.Directions.West: case LevelBoard.Directions.North: for (int i = dirId - 1; i <= dirId + 1; i++) { LevelBoard.Directions checkDir = (LevelBoard.Directions)(i % 8); if (checkDir == LevelBoard.Directions.None) { checkDir = LevelBoard.Directions.SouthEast; } // Get adjacent space coordinates adjCoords = LevelBoard.GetAdjacentCoords(coords, checkDir); // Out of Bounds if (adjCoords.x == -1) { continue; } if (toExplore - 1 >= 0f) { nextQueue.Enqueue(adjCoords); // Queue position to be checked toExpandNext.Add(adjCoords, checkDir); // List direction it was reached from } found = this.Puzzle.GetPiece(adjCoords); // No Piece in the space if (found == null) { continue; } pieces.Add(found); // Add Piece to the list } break; case LevelBoard.Directions.SouthEast: case LevelBoard.Directions.SouthWest: case LevelBoard.Directions.NorthEast: case LevelBoard.Directions.NorthWest: adjCoords = LevelBoard.GetAdjacentCoords(coords, originDir); // Out of Bounds if (adjCoords.x == -1) { continue; } if (toExplore - 1 >= 0.5f) { nextQueue.Enqueue(adjCoords); // Queue position to be checked toExpandNext.Add(adjCoords, originDir); // List direction it was reached from } found = this.Puzzle.GetPiece(adjCoords); // No Piece in the space if (found == null) { continue; } pieces.Add(found); // Add Piece to the list break; } } queue = nextQueue; toExpand = toExpandNext; toExplore--; } return(pieces); }
public Vector2Int Discretize(Vector3 position) { return(LevelBoard.Discretize(position)); }
public Vector3 WorldCoords(Vector2Int position) { return(LevelBoard.WorldCoords(position)); }
public void Initialize(LevelBoard board) { Initialize(board, new List <Piece>(), new List <Tile>(), new WinCondition(WinCondition.Conditions.GLED_On_RLED_Off), new Dictionary <string, Resource>()); }
public BoardData(LevelBoard board) { this.Width = board.Width; this.Height = board.Height; }