Example #1
0
        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);
        }
Example #2
0
        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;
        }
Example #3
0
        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);
        }
Example #4
0
        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);
        }
Example #7
0
        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));
        }
Example #8
0
        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);
        }
Example #9
0
        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);
        }
Example #10
0
        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));
        }
Example #11
0
        // Reactivates the Agent
        public void Reactivate(Vector2Int coords)
        {
            this.Reveal();

            this.PlacePiece(this, coords);

            this.transform.position = LevelBoard.WorldCoords(coords);

            this.Active = true;
        }
Example #12
0
        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));
        }
Example #13
0
        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);
            }
        }
Example #14
0
        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;
        }
Example #15
0
        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);
            }
        }
Example #16
0
        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);
        }
Example #17
0
        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);
        }
Example #18
0
        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);
        }
Example #19
0
        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);
            }
        }
Example #20
0
        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);
        }
Example #21
0
        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);
        }
Example #22
0
        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);
        }
Example #23
0
 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));
        }
Example #25
0
        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);
        }
Example #26
0
 public Vector2Int Discretize(Vector3 position)
 {
     return(LevelBoard.Discretize(position));
 }
Example #27
0
 public Vector3 WorldCoords(Vector2Int position)
 {
     return(LevelBoard.WorldCoords(position));
 }
Example #28
0
 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>());
 }
Example #29
0
 public BoardData(LevelBoard board)
 {
     this.Width  = board.Width;
     this.Height = board.Height;
 }