Example #1
0
 /// <summary>
 /// Finds the shortest path from the given start to the given goal.
 /// Does not include the "start" pos in the list.
 /// Returns "null" if a path wasn't found.
 /// IMPORTANT: The returned list is reused for other calls to this method,
 ///     so treat it as a temp variable!
 /// </summary>
 /// <param name="heuristicCalc">
 /// The heuristic/path length calculator,
 ///     or "null" if the default one (manhattan distance) should be used.
 /// </param>
 public List <Vector2i> FindPath(Vector2i start, Pathfinding.Goal <Vector2i> goal,
                                 Pathfinding.PathFinder <Vector2i> .CostCalculator heuristicCalc = null)
 {
     return(FindPath(start, goal, tempPath, heuristicCalc) ?
            tempPath :
            null);
 }
Example #2
0
        public override IEnumerable TakeTurn()
        {
            //If the tile no longer supports building a bed, stop the job.
            if (!TheMap.Value.Tiles[Tile].IsBuildableOn() ||
                TheMap.Value.AnyUnitsAt(Tile, u => u.BlocksStructures))
            {
                EndJob(false, Localization.Get("CANT_BUILD_ON_TILE"));
                yield break;
            }

            //If we're not currently building, path to the tile to build from.
            if (!IsCurrentlyBuilding)
            {
                var movementStatus = new TryMoveToPos_Status();
                var goal           = new Pathfinding.Goal <Vector2i>(Tile);
                foreach (object o in TryMoveToPos(goal, movementStatus))
                {
                    yield return(o);
                }

                switch (movementStatus.CurrentState)
                {
                case TryMoveToPos_States.Finished:
                    //Start building.
                    IsCurrentlyBuilding = true;
                    TurnsLeft           = Consts.TurnsToBuildStructure(Owner.Value.Strength,
                                                                       Owner.Value.AdultMultiplier);
                    break;

                case TryMoveToPos_States.EnRoute:
                    //End the turn.
                    yield break;

                case TryMoveToPos_States.NoPath:
                    //Cancel the job.
                    EndJob(false, Localization.Get("NO_PATH_JOB"));
                    yield break;
                }
            }

            //Build.
            if (TurnsLeft > 0)
            {
                TurnsLeft -= 1;
                yield break;
            }

            //Create the bed.
            var bed = new Bed(TheMap, OwnerGroupId, Tile);

            TheMap.Value.AddUnit(bed);

            EndJob(true);
        }
Example #3
0
        /// <summary>
        /// Gets the first applicable job from the given set.
        /// Returns null if none were applicable.
        /// </summary>
        public Job ChooseApplicable(HashSet <Job> jobs)
        {
            foreach (Job j in jobs)
            {
                switch (j.ThisType)
                {
                case Job.Types.MoveToPos: {
                    var jMove = (Job_MoveToPos)j;

                    //Edge-case: the PlayerChar is already there, and doesn't have to do anything.
                    if (Owner.Pos.Value == jMove.TargetPos.Value)
                    {
                        return(j);
                    }

                    //This job is doable if the PlayerChar is not too far away
                    //    and can actually path to the object.
                    int maxDist = MoveToPos_MaxDist;
                    if (maxDist != 0)
                    {
                        var goal = new Pathfinding.Goal <Vector2i>(jMove.TargetPos);
                        var path = Owner.FindPath(goal, AvoidEnemiesWhenPathing);
                        if (path != null && path.Count < maxDist)
                        {
                            return(j);
                        }
                    }
                } break;

                case Job.Types.Mine:
                    if (AcceptJob_Mining)
                    {
                        return(j);
                    }
                    break;

                case Job.Types.BuildBed:
                    if (AcceptJob_Build)
                    {
                        return(j);
                    }
                    break;

                default: throw new NotImplementedException(j.ThisType.ToString());
                }
            }

            return(null);
        }
Example #4
0
        /// <summary>
        /// Outputs the shortest path from the given start to the given goal
        ///     into the "outPath" list.
        /// Does not include the "start" pos in the list.
        /// Returns whether a path was actually found.
        /// </summary>
        /// <param name="heuristicCalc">
        /// The heuristic/path length calculator,
        ///     or "null" if the default one (manhattan distance) should be used.
        /// </param>
        public bool FindPath(Vector2i start, Pathfinding.Goal <Vector2i> goal,
                             List <Vector2i> outPath,
                             Pathfinding.PathFinder <Vector2i> .CostCalculator heuristicCalc = null)
        {
            if (heuristicCalc == null)
            {
                pathing.CalcCosts = Graph.AStarEdgeCalc;
            }
            else
            {
                pathing.CalcCosts = heuristicCalc;
            }

            return(pathing.FindPath(start, goal, float.PositiveInfinity, false, outPath));
        }
Example #5
0
        /// <summary>
        /// The heuristic function for doing A* pathfinding for this unit.
        /// Note that to reduce garbage, this heuristic may reuse global variables,
        ///		which means only one Unit can have a heuristic at any time.
        /// </summary>
        protected void AStarEdgeCalc(Pathfinding.Goal <Vector2i> goal,
                                     Pathfinding.Edge <Vector2i> edge,
                                     out float edgeLength, out float heuristic)
        {
            Graph.AStarEdgeCalc(goal, edge, out edgeLength, out heuristic);

            //Subtract enemy distances squared from the heuristic.
            foreach (Unit enemy in _temp_enemies)
            {
                float distSqr = enemy.Pos.Value.DistanceSqr(Pos);
                float distT   = distSqr * One_Over_MaxEnemyDistance;
                distT = Math.Max(0.0f, Math.Min(1.0f, distT));

                heuristic += Units.Consts.EnemyDistanceHeuristicMax * distT;
            }
        }
Example #6
0
        /// <summary>
        /// A coroutine that attempts to make the owning PlayerChar move to the given position.
        /// </summary>
        /// <param name="nMoves">
        /// The maximum number of moves to take,
        /// or -1 to take as many as he is allowed in one turn.
        /// </param>
        /// <param name="nActualMoves">
        /// The number of actual moves the PlayerChar took by the end of this.
        /// He will stop early if he reaches the goal.
        /// </param>
        /// <param name="outStatus">
        /// As this method runs, it outputs information into this structure.
        /// </param>
        protected System.Collections.IEnumerable TryMoveToPos(Pathfinding.Goal <Vector2i> goal,
                                                              TryMoveToPos_Status outStatus,
                                                              int nMoves = -1)
        {
            outStatus.NActualMoves = 0;
            outStatus.CurrentState = TryMoveToPos_States.EnRoute;

            //Try to find the best path.
            List <Vector2i> path = Owner.Value.FindPath(goal, Owner.Value.Career.AvoidEnemiesWhenPathing);

            if (path == null)
            {
                outStatus.CurrentState = TryMoveToPos_States.NoPath;
                yield break;
            }

            //Move along the path.
            if (nMoves == -1)
            {
                nMoves = PlayerConsts.MovesPerTurn;
            }
            nMoves = Math.Min(nMoves, path.Count);
            for (int i = 0; i < nMoves; ++i)
            {
                Owner.Value.Pos.Value   = path[i];
                outStatus.NActualMoves += 1;

                //If we're at the end of the path, exit.
                if (goal.IsValidEnd(Owner.Value.Pos))
                {
                    outStatus.CurrentState = TryMoveToPos_States.Finished;
                    yield break;
                }

                yield return(null);
            }

            //We didn't make it to the end of the path.
            outStatus.CurrentState = TryMoveToPos_States.EnRoute;
        }
Example #7
0
        /// <summary>
        /// Does the basic edge length/heuristic calculation
        /// that all units will likely use for their pathing.
        /// </summary>
        public static void AStarEdgeCalc(Pathfinding.Goal <Vector2i> goal,
                                         Pathfinding.Edge <Vector2i> edge,
                                         out float edgeLength, out float heuristic)
        {
            //For performance (and because they'll generally be adjacent),
            //    use manhattan distance between nodes.
            edgeLength = Math.Abs(edge.Start.x - edge.End.x) + Math.Abs(edge.Start.y - edge.End.y);


            heuristic = 0.0f;

            //Manhattan distance to the goal.
            if (goal.SpecificGoal.HasValue)
            {
                Vector2i specificGoal = goal.SpecificGoal.Value;
                float    dist         = Math.Abs(edge.End.x - specificGoal.x) +
                                        Math.Abs(edge.End.y - specificGoal.y);

                //Square it to make it more important.
                heuristic += dist * dist;
            }
        }
Example #8
0
        public override IEnumerable TakeTurn()
        {
            //If the unit's energy and health is high enough, end the job.
            if (Owner.Value.Health.Value >= Consts.Max_Health &&
                Owner.Value.Energy.Value >= Consts.MaxEnergy(Owner.Value.Strength))
            {
                EndJob(true);
            }
            //Otherwise, if we're not sleeping yet, path to a bed.
            else if (!BedID.HasValue)
            {
                //Get all friendly beds.
                friendlyBedPoses.Clear();
                foreach (Bed b in TheMap.Value.GetUnits(Unit.Types.Bed).Cast <Bed>())
                {
                    if (b.MyGroup == Owner.Value.MyGroup || b.MyGroup.IsAllyTo(Owner.Value.MyGroup))
                    {
                        friendlyBedPoses.Add(b.Pos);
                    }
                }

                //If there are no friendly beds, cancel the job.
                if (friendlyBedPoses.Count == 0)
                {
                    EndJob(false, Localization.Get("NO_BED"));
                    yield break;
                }

                //Either move towards a specific bed, or towards any friendly bed.
                var goal = new Pathfinding.Goal <Vector2i>();
                if (TargetBedID.Value.HasValue)
                {
                    goal.SpecificGoal = TheMap.Value.GetUnit(TargetBedID.Value.Value).Pos.Value;
                }
                else
                {
                    goal.GeneralGoal = friendlyBedPoses.Contains;
                }

                //Move to the goal.
                TryMoveToPos_Status moveStatus = new TryMoveToPos_Status();
                foreach (object o in TryMoveToPos(goal, moveStatus))
                {
                    yield return(o);
                }
                switch (moveStatus.CurrentState)
                {
                case TryMoveToPos_States.Finished:
                    //Start sleeping.
                    StartSleeping((Bed)TheMap.Value.FirstUnitAt(Owner.Value.Pos, u => u is Bed));
                    break;

                case TryMoveToPos_States.EnRoute:
                    //End the turn.
                    yield break;

                case TryMoveToPos_States.NoPath:
                    //Cancel the job.
                    EndJob(false, Localization.Get("NO_PATH_JOB"));
                    break;

                default: throw new NotImplementedException(moveStatus.CurrentState.ToString());
                }
            }
        }
Example #9
0
 /// <summary>
 /// Finds the shortest path from this Unit to the given goal.
 /// Does not include this Unit's own position in the list.
 /// Returns "null" if a path wasn't found.
 /// IMPORTANT: The returned list is reused for other calls to this method,
 ///     so treat it as a temp variable!
 /// </summary>
 public List <Vector2i> FindPath(Pathfinding.Goal <Vector2i> goal, bool avoidEnemies)
 {
     return(TheMap.FindPath(Pos, goal, MakeHeuristic(avoidEnemies)));
 }