Esempio n. 1
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);
        }
Esempio n. 2
0
        /// <summary>
        /// Calculates an action according to a simple default policy. Used mainly
        /// in MCTS playouts.
        /// </summary>
        public static UctAction DefaultPolicyAction(GameInstance state)
        {
            var mobId = state.CurrentMob;

            if (mobId == null)
            {
                throw new InvalidOperationException("Requesting mob action when there is no current mob.");
            }

            Debug.Assert(state.State.MobInstances[mobId.Value].Hp > 0, "Current mob is dead");

            var mob = state.CachedMob(mobId.Value);

            if (mob.MobInstance.Ap == 0)
            {
                return(UctAction.EndTurnAction());
            }

            var abilityIds = new List <int>();

            foreach (var possibleAbilityId in mob.MobInfo.Abilities)
            {
                if (GameInvariants.IsAbilityUsableNoTarget(state, mobId.Value, possibleAbilityId))
                {
                    abilityIds.Add(possibleAbilityId);
                }
            }

            int moveTargetId = MobInstance.InvalidId;

            var actions = new List <UctAction>();

            foreach (var possibleTargetId in state.MobManager.Mobs)
            {
                var possibleTarget = state.CachedMob(possibleTargetId);

                moveTargetId = possibleTargetId;

                if (!GameInvariants.IsTargetable(state, mob, possibleTarget))
                {
                    continue;
                }

                if (abilityIds.Count == 0)
                {
                    continue;
                }

                foreach (var abilityId in abilityIds)
                {
                    if (GameInvariants.IsAbilityUsableApRangeCheck(state, mob, possibleTarget, abilityId))
                    {
                        actions.Add(UctAction.AbilityUseAction(abilityId, mob.MobId, possibleTargetId));
                    }
                }
            }

            if (actions.Count > 0)
            {
                return(MaxAbilityRatio(state, actions));
            }

            if (moveTargetId != MobInstance.InvalidId)
            {
                return(PickMoveTowardsEnemyAction(state, state.CachedMob(mobId.Value),
                                                  state.CachedMob(moveTargetId)));
            }
            else
            {
                Utils.Log(LogSeverity.Error, nameof(ActionGenerator), "No targets, game should be over");

                throw new InvalidOperationException("No targets, game should be over.");
            }
        }