Exemplo n.º 1
0
        /// <summary>
        /// Calculates the furthest walkable point ot the given target mob.
        /// </summary>
        public AxialCoord?FurthestPointToTarget(CachedMob mob, CachedMob target)
        {
            var path = PrecomputedPathTo(mob.MobInstance.Coord, target.MobInstance.Coord);

            if (path.Count == 0 && mob.MobInstance.Coord.Distance(target.MobInstance.Coord) == 1)
            {
                return(null);
            }

            AxialCoord?furthestPoint = null;

            foreach (var coord in path)
            {
                int distance   = Distance(mob.MobInstance.Coord, coord);
                var mobAtCoord = Game.State.AtCoord(coord, true);

                if (distance <= mob.MobInstance.Ap)
                {
                    if (mobAtCoord == null)
                    {
                        furthestPoint = coord;
                    }
                }
                else
                {
                    break;
                }
            }

            return(furthestPoint);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Generates possible direct ability use actions.
        /// </summary>
        public static bool GenerateDirectAbilityUse(GameInstance state,
                                                    CachedMob mob,
                                                    List <UctAction> result)
        {
            bool foundAbilityUse = false;
            var  mobInfo         = mob.MobInfo;
            var  mobId           = mob.MobId;

            foreach (var abilityId in mobInfo.Abilities)
            {
                if (!GameInvariants.IsAbilityUsableNoTarget(state, mobId, abilityId))
                {
                    continue;
                }

                foreach (var targetId in state.MobManager.Mobs)
                {
                    if (GameInvariants.IsAbilityUsable(state, mob, state.CachedMob(targetId), abilityId))
                    {
                        foundAbilityUse = true;

                        var action = UctAction.AbilityUseAction(abilityId, mobId, targetId);
                        GameInvariants.AssertValidAction(state, action);

                        result.Add(action);
                    }
                }
            }

            return(foundAbilityUse);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Generates a number of defensive move actions based on a heatmap.
        /// </summary>
        public static void GenerateDefensiveMoveActions(GameInstance state, CachedMob mob, List <UctAction> result)
        {
            var heatmap = Heatmap.BuildHeatmap(state, null, false);
            var coords  = new List <AxialCoord>();

            var mobInstance = mob.MobInstance;
            var mobId       = mob.MobId;

            foreach (var coord in heatmap.Map.AllCoords)
            {
                if (heatmap.Map[coord] != heatmap.MinValue)
                {
                    continue;
                }
                if (state.Map[coord] == HexType.Wall)
                {
                    continue;
                }
                if (state.State.AtCoord(coord, true).HasValue)
                {
                    continue;
                }

                bool canMoveTo = state.Pathfinder.Distance(mobInstance.Coord, coord) <= mobInstance.Ap;

                if (!canMoveTo)
                {
                    continue;
                }

                coords.Add(coord);
            }

            coords.Shuffle();

            int maximumMoveActions = Math.Max(0, 3 - result.Count);

            for (int i = 0; i < Math.Min(coords.Count, maximumMoveActions); i++)
            {
                var action = UctAction.DefensiveMoveAction(mobId, coords[i]);
                GameInvariants.AssertValidAction(state, action);

                result.Add(action);
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Calculates a move towards an enemy, or ends a turn if no such move is possible.
        /// </summary>
        private static UctAction PickMoveTowardsEnemyAction(GameInstance game, CachedMob mob,
                                                            CachedMob possibleTarget)
        {
            foreach (var targetId in game.MobManager.Mobs)
            {
                var target = game.CachedMob(targetId);

                if (!GameInvariants.IsTargetableNoSource(game, mob, target))
                {
                    continue;
                }

                var action = FastMoveTowardsEnemy(game, mob, target);

                if (action.Type == UctActionType.Move)
                {
                    return(action);
                }
            }

            return(UctAction.EndTurnAction());
        }
Exemplo n.º 5
0
        public string BuildMessage(UctAction action, CachedMob mob, CachedMob target, AbilityInfo abilityInfo, int?moveCost)
        {
            if (action.Type == UctActionType.Null)
            {
                return(" ");
            }

            string str;

            switch (action.Type)
            {
            case UctActionType.AbilityUse:
                str = $"Did {abilityInfo.Dmg} damage for {abilityInfo.Cost} AP.";
                break;

            case UctActionType.AttackMove:
                str = $"Moved towards enemy for {moveCost} AP and did {abilityInfo.Dmg} damage for {abilityInfo.Cost} AP.";
                break;

            case UctActionType.Move:
                str = $"Moved from {mob.MobInstance.Coord} to {action.Coord} for {moveCost} AP.";
                break;

            case UctActionType.DefensiveMove:
                str = $"Is trying to hide at {action.Coord} for {moveCost} AP.";
                break;

            case UctActionType.EndTurn:
                throw new InvalidOperationException("End turn shouldn't be logged.");

            case UctActionType.Null:
                throw new InvalidOperationException("Null action should never be logged.");

            default:
                throw new ArgumentException($"Invalid action type ${action.Type}", nameof(action));
            }

            return($"{string.Format("{0,3}", _actionIndex)}. {str}");
        }
Exemplo n.º 6
0
        public void Log(TeamColor currentTeam, UctAction action, CachedMob mob, CachedMob target,
                        AbilityInfo abilityInfo, int?moveCost)
        {
            GameManager.CurrentSynchronizationContext.Post(_ => {
                var entry = new HistoryLogEntry(ActionCount++,
                                                currentTeam,
                                                action,
                                                mob,
                                                target,
                                                abilityInfo,
                                                moveCost,
                                                _assetManager);

                _log.Add(entry);
                _childrenPlaceholder.AddChild(entry);

                if (_log.Count > MaxHistorySize)
                {
                    _log.RemoveAt(0);
                    _childrenPlaceholder.Children.RemoveAt(0);
                }
            }, null);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Returns an action that moves towards an enemy as fast as possible.
        /// </summary>
        public static UctAction FastMoveTowardsEnemy(GameInstance state, CachedMob mob, CachedMob target)
        {
            var pathfinder = state.Pathfinder;

            var moveTarget = pathfinder.FurthestPointToTarget(mob, target);

            if (moveTarget != null && pathfinder.Distance(mob.MobInstance.Coord, moveTarget.Value) <=
                mob.MobInstance.Ap)
            {
                return(UctAction.MoveAction(mob.MobId, moveTarget.Value));
            }
            else if (moveTarget == null)
            {
                // Intentionally doing nothing
                return(UctAction.EndTurnAction());
            }
            else
            {
                Utils.Log(LogSeverity.Debug, nameof(AiRuleBasedController),
                          $"Move failed since target is too close, source {mob.MobInstance.Coord}, target {target.MobInstance.Coord}");
                return(UctAction.EndTurnAction());
            }
        }
Exemplo n.º 8
0
        /// <summary>
        /// Generates possible attack move actions.
        /// </summary>
        public static void GenerateAttackMoveActions(GameInstance state, CachedMob mob, List <UctAction> result)
        {
            var mobInfo     = mob.MobInfo;
            var mobInstance = mob.MobInstance;

            foreach (var enemyId in state.MobManager.Mobs)
            {
                var target = state.CachedMob(enemyId);

                if (!GameInvariants.IsTargetableNoSource(state, mob, target))
                {
                    continue;
                }

                AxialCoord myCoord         = mobInstance.Coord;
                AxialCoord?closestCoord    = null;
                int?       distance        = null;
                int?       chosenAbilityId = null;

                foreach (var coord in state.Map.EmptyCoords)
                {
                    if (!state.Map.IsVisible(coord, target.MobInstance.Coord))
                    {
                        continue;
                    }

                    var possibleMoveAction = GameInvariants.CanMoveTo(state, mob, coord);

                    if (possibleMoveAction.Type == UctActionType.Null)
                    {
                        continue;
                    }
                    Debug.Assert(possibleMoveAction.Type == UctActionType.Move);

                    foreach (var abilityId in mobInfo.Abilities)
                    {
                        if (!GameInvariants.IsAbilityUsableFrom(state, mob, coord, target, abilityId))
                        {
                            continue;
                        }

                        int myDistance = state.Pathfinder.Distance(myCoord, coord);

                        if (!closestCoord.HasValue)
                        {
                            chosenAbilityId = abilityId;
                            closestCoord    = coord;
                            distance        = myDistance;
                        }
                        else if (distance.Value > myDistance)
                        {
                            chosenAbilityId = abilityId;
                            closestCoord    = coord;
                            distance        = myDistance;
                        }
                    }
                }

                if (closestCoord.HasValue)
                {
                    if (Constants.AttackMoveEnabled)
                    {
                        var action = UctAction.AttackMoveAction(mob.MobId,
                                                                closestCoord.Value,
                                                                chosenAbilityId.Value,
                                                                target.MobId);

                        var after = ActionEvaluator.F(state, action.ToPureMove());
                        GameInvariants.AssertValidAbilityUseAction(after, action.ToPureAbilityUse());

                        GameInvariants.AssertValidAction(state, action);

                        result.Add(action);
                    }
                    else
                    {
                        var action = UctAction.MoveAction(mob.MobId, closestCoord.Value);
                        GameInvariants.AssertValidAction(state, action);

                        result.Add(action);
                    }
                }
            }
        }
Exemplo n.º 9
0
        public HistoryLogEntry(int actionIndex, TeamColor currentTeam, UctAction action, CachedMob mob, CachedMob target,
                               AbilityInfo abilityInfo,
                               int?moveCost,
                               AssetManager assetManager)
        {
            _actionIndex  = actionIndex;
            _assetManager = assetManager;
            Renderer      = this;
            CurrentTeam   = currentTeam;

            Message = BuildMessage(action, mob, target, abilityInfo, moveCost);
        }