예제 #1
0
        protected override ActorAction SelectAction(RogueGame game, List <Percept> percepts)
        {
            HashSet <Point> fov         = (m_MemLOSSensor.Sensor as LOSSensor).FOV;
            List <Percept>  mapPercepts = FilterSameMap(game, percepts);

            //////////////////////////////////////////////////////////////
            // 1 move closer to an enemy, nearest & visible enemies first
            // 2 eat corpses.
            // 3 use exits (if ability)
            // 4 move close to nearest undead master (if not master)
            // 5 move to highest adjacent undead master scent (if not master)
            // 6 move to highest living scent
            // 7 **DISABLED** assault breakables (if ability)
            // 8 randomly push objects around (if ability OR skill STRONG)
            // 9 explore (if ability)
            // 10 wander
            //////////////////////////////////////////////////////////////

            // get data.
            if (m_Actor.Model.Abilities.ZombieAI_Explore)
            {
                // exploration.
                m_Exploration.Update(m_Actor.Location);
            }

            // 1 move closer to an enemy, nearest & visible enemies first
            #region
            List <Percept> enemies = FilterEnemies(game, mapPercepts);
            if (enemies != null)
            {
                // try visible enemies first, the closer the best.
                List <Percept> visibleEnemies = Filter(game, enemies, (p) => p.Turn == m_Actor.Location.Map.LocalTime.TurnCounter);
                if (visibleEnemies != null)
                {
                    Percept     bestEnemyPercept = null;
                    ActorAction bestBumpAction   = null;
                    float       closest          = int.MaxValue;

                    foreach (Percept enemyP in visibleEnemies)
                    {
                        float distance = game.Rules.GridDistance(m_Actor.Location.Position, enemyP.Location.Position);
                        if (distance < closest)
                        {
                            ActorAction bumpAction = BehaviorStupidBumpToward(game, enemyP.Location.Position, true, true);
                            if (bumpAction != null)
                            {
                                closest          = distance;
                                bestEnemyPercept = enemyP;
                                bestBumpAction   = bumpAction;
                            }
                        }
                    }

                    if (bestBumpAction != null)
                    {
                        m_Actor.Activity    = Activity.CHASING;
                        m_Actor.TargetActor = bestEnemyPercept.Percepted as Actor;
                        return(bestBumpAction);
                    }
                }

                // then try rest, the closer the best.
                List <Percept> oldEnemies = Filter(game, enemies, (p) => p.Turn != m_Actor.Location.Map.LocalTime.TurnCounter);
                if (oldEnemies != null)
                {
                    Percept     bestEnemyPercept = null;
                    ActorAction bestBumpAction   = null;
                    float       closest          = int.MaxValue;

                    foreach (Percept enemyP in oldEnemies)
                    {
                        float distance = game.Rules.GridDistance(m_Actor.Location.Position, enemyP.Location.Position);
                        if (distance < closest)
                        {
                            ActorAction bumpAction = BehaviorStupidBumpToward(game, enemyP.Location.Position, true, true);
                            if (bumpAction != null)
                            {
                                closest          = distance;
                                bestEnemyPercept = enemyP;
                                bestBumpAction   = bumpAction;
                            }
                        }
                    }

                    if (bestBumpAction != null)
                    {
                        m_Actor.Activity    = Activity.CHASING;
                        m_Actor.TargetActor = bestEnemyPercept.Percepted as Actor;
                        return(bestBumpAction);
                    }
                }
            }
            #endregion

            // 2 eat corpses.
            List <Percept> corpses = FilterCorpses(game, mapPercepts);
            if (corpses != null)
            {
                ActorAction eatCorpses = BehaviorGoEatCorpse(game, corpses);
                if (eatCorpses != null)
                {
                    m_Actor.Activity = Activity.IDLE;
                    return(eatCorpses);
                }
            }

            // 3 use exit (if ability)
            #region
            // move before following scents so the AI is more likely to move into basements etc...
            if (m_Actor.Model.Abilities.AI_CanUseAIExits && game.Rules.RollChance(USE_EXIT_CHANCE))
            {
                ActorAction useExit = BehaviorUseExit(game, UseExitFlags.ATTACK_BLOCKING_ENEMIES | UseExitFlags.BREAK_BLOCKING_OBJECTS | UseExitFlags.DONT_BACKTRACK);
                if (useExit != null)
                {
                    // memory is obsolete, clear it.
                    m_MemLOSSensor.Clear();
                    m_Actor.Activity = Activity.IDLE;
                    return(useExit);
                }
            }
            #endregion

            // 4 move close to nearest undead master (if not master)
            #region
            if (!m_Actor.Model.Abilities.IsUndeadMaster)
            {
                Percept nearestMaster = FilterNearest(game, FilterActors(game, mapPercepts, (a) => a.Model.Abilities.IsUndeadMaster));
                if (nearestMaster != null)
                {
                    ActorAction bumpAction = BehaviorStupidBumpToward(game, RandomPositionNear(game.Rules, m_Actor.Location.Map, nearestMaster.Location.Position, 3), true, true);
                    if (bumpAction != null)
                    {
                        // MAASTEERRR!
                        m_Actor.Activity    = Activity.FOLLOWING;
                        m_Actor.TargetActor = nearestMaster.Percepted as Actor;
                        return(bumpAction);
                    }
                }
            }
            #endregion

            // 5 move to highest undead master scent (if not master)
            #region
            if (!m_Actor.Model.Abilities.IsUndeadMaster)
            {
                ActorAction trackMasterAction = BehaviorTrackScent(game, m_MasterSmellSensor.Scents);
                if (trackMasterAction != null)
                {
                    m_Actor.Activity = Activity.TRACKING;
                    return(trackMasterAction);
                }
            }
            #endregion

            // 6 move to highest living scent
            #region
            ActorAction trackLivingAction = BehaviorTrackScent(game, m_LivingSmellSensor.Scents);
            if (trackLivingAction != null)
            {
                m_Actor.Activity = Activity.TRACKING;
                return(trackLivingAction);
            }
            #endregion

            // 7 **DISABLED** assault breakables (if ability)
#if false
            #region
            if (m_Actor.Model.Abilities.ZombieAI_AssaultBreakables)
            {
                ActorAction assaultAction = BehaviorAssaultBreakables(game, fov);
                if (assaultAction != null)
                {
                    m_Actor.Activity = Activity.IDLE;
                    return(assaultAction);
                }
            }
            #endregion
#endif

            // 8 randomly push objects around (if ability OR skill STRONG)
            #region
            if (game.Rules.HasActorPushAbility(m_Actor) && game.Rules.RollChance(PUSH_OBJECT_CHANCE))
            {
#if false
                special ZM case disabled
        protected override ActorAction SelectAction(RogueGame game, List <Percept> percepts)
        {
            List <Percept> mapPercepts = FilterSameMap(game, percepts);

            ///////////////////////
            // 1. Follow order
            // 2. Normal behavior.
            ///////////////////////

            // 1. Follow order
            #region
            if (this.Order != null)
            {
                ActorAction orderAction = ExecuteOrder(game, this.Order, mapPercepts);
                if (orderAction == null)
                {
                    SetOrder(null);
                }
                else
                {
                    m_Actor.Activity = Activity.FOLLOWING_ORDER;
                    return(orderAction);
                }
            }
            #endregion

            // 2. Normal behavior.
            #region
            //////////////////////////////////////////////////////////////////////
            // BEHAVIOR
            // - FLAGS
            // "courageous" : has leader, see leader, he is fighting and actor not tired.
            // - RULES
            // 0 run away from primed explosives.
            // 1 throw grenades at enemies.
            // 2 equip weapon/armor
            // 3 fire at nearest (always if has leader, half of the time if not)  - check directives
            // 4 fight or flee, shout
            // 5 use medicine
            // 6 rest if tired
            // 7 charge enemy if courageous
            // 8 eat when hungry (also eat corpses)
            // 9 sleep when almost sleepy and safe.
            // 10 drop light/tracker with no batteries
            // 11 equip light/tracker/scent spray
            // 12 make room for food items if needed.
            // 13 get nearby item/trade (not if seeing enemy) - check directives.
            // 14 if hungry and no food, charge at people for food (option, not follower or law enforcer)
            // 15 use stench killer.
            // 16 close door behind me.
            // 17 use entertainment
            // 18 follow leader.
            // 19 take lead (if leadership)
            // 20 if hungry, tear down barricades & push objects.
            // 21 go revive corpse.
            // 22 use exit.
            // 23 build trap or fortification.
            // 24 tell friend about latest raid.
            // 25 tell friend about latest friendly soldier.
            // 26 tell friend about latest enemy.
            // 27 tell friend about latest items.
            // 28 (law enforcer) watch for murderers.
            // 29 (leader) don't leave followers behind.
            // 30 explore.
            // 31 wander.
            //////////////////////////////////////////////////////////////////////

            // don't run by default.
            m_Actor.IsRunning = false;

            // get data.
            List <Percept> enemies          = FilterEnemies(game, mapPercepts);
            bool           hasEnemies       = enemies != null && enemies.Count > 0;
            bool           checkOurLeader   = m_Actor.HasLeader && !DontFollowLeader;
            bool           seeLeader        = checkOurLeader && m_LOSSensor.FOV.Contains(m_Actor.Leader.Location.Position);
            bool           isLeaderFighting = checkOurLeader && IsAdjacentToEnemy(game, m_Actor.Leader);
            bool           isCourageous     = checkOurLeader && seeLeader && isLeaderFighting && !game.Rules.IsActorTired(m_Actor);

            // safety counter.
            if (hasEnemies)
            {
                m_SafeTurns = 0;
            }
            else
            {
                ++m_SafeTurns;
            }

            // exploration.
            m_Exploration.Update(m_Actor.Location);

            // clear taboo tiles : periodically or when changing maps.
            if (m_Actor.Location.Map.LocalTime.TurnCounter % WorldTime.TURNS_PER_HOUR == 0 ||
                (PrevLocation != null && PrevLocation.Map != m_Actor.Location.Map))
            {
                ClearTabooTiles();
            }
            // clear trades.
            if (m_Actor.Location.Map.LocalTime.TurnCounter % WorldTime.TURNS_PER_DAY == 0)
            {
                ClearTabooTrades();
            }

            // last enemy saw.
            if (hasEnemies)
            {
                m_LastEnemySaw = enemies[game.Rules.Roll(0, enemies.Count)];
            }

            // 0 run away from primed explosives.
            #region
            ActorAction runFromExplosives = BehaviorFleeFromExplosives(game, FilterStacks(game, mapPercepts));
            if (runFromExplosives != null)
            {
                m_Actor.Activity = Activity.FLEEING_FROM_EXPLOSIVE;
                return(runFromExplosives);
            }
            #endregion

            // 1 throw grenades at enemies.
            #region
            // if directive off, unequip.
            if (!this.Directives.CanThrowGrenades)
            {
                // unequip grenade?
                ItemGrenade eqGrenade = m_Actor.GetEquippedWeapon() as ItemGrenade;
                if (eqGrenade != null)
                {
                    ActionUnequipItem unequipGre = new ActionUnequipItem(m_Actor, game, eqGrenade);
                    if (unequipGre.IsLegal())
                    {
                        m_Actor.Activity = Activity.IDLE;
                        return(unequipGre);
                    }
                }
            }
            // throw?
            if (hasEnemies)
            {
                ActorAction throwAction = BehaviorThrowGrenade(game, m_LOSSensor.FOV, enemies);
                if (throwAction != null)
                {
                    return(throwAction);
                }
            }
            #endregion

            // 2 equip weapon/armor
            #region
            ActorAction equipWpnAction = BehaviorEquipWeapon(game);
            if (equipWpnAction != null)
            {
                m_Actor.Activity = Activity.IDLE;
                return(equipWpnAction);
            }
            ActorAction equipArmAction = BehaviorEquipBodyArmor(game);
            if (equipArmAction != null)
            {
                m_Actor.Activity = Activity.IDLE;
                return(equipArmAction);
            }
            #endregion

            // 3 fire at nearest enemy
            #region
            if (hasEnemies && this.Directives.CanFireWeapons && m_Actor.GetEquippedWeapon() is ItemRangedWeapon)
            {
                List <Percept> fireTargets = FilterFireTargets(game, enemies);
                if (fireTargets != null)
                {
                    Percept nearestTarget = FilterNearest(game, fireTargets);
                    Actor   target        = nearestTarget.Percepted as Actor;

                    // flee contact from someone SLOWER with no ranged weapon.
                    if (game.Rules.GridDistance(nearestTarget.Location.Position, m_Actor.Location.Position) == 1 &&
                        !HasEquipedRangedWeapon(target) &&
                        HasSpeedAdvantage(game, m_Actor, target))
                    {
                        // flee!
                        ActorAction fleeAction = BehaviorWalkAwayFrom(game, nearestTarget);
                        if (fleeAction != null)
                        {
                            RunIfPossible(game.Rules);
                            m_Actor.Activity = Activity.FLEEING;
                            return(fleeAction);
                        }
                    }

                    // fire ze missiles!
                    ActorAction fireAction = BehaviorRangedAttack(game, nearestTarget);
                    if (fireAction != null)
                    {
                        m_Actor.Activity    = Activity.FIGHTING;
                        m_Actor.TargetActor = target;
                        return(fireAction);
                    }
                }
            }
            #endregion

            // 4 fight or flee, shout
            #region
            if (hasEnemies)
            {
                // shout?
                if (game.Rules.RollChance(50))
                {
                    List <Percept> friends = FilterNonEnemies(game, mapPercepts);
                    if (friends != null)
                    {
                        ActorAction shoutAction = BehaviorWarnFriends(game, friends, FilterNearest(game, enemies).Percepted as Actor);
                        if (shoutAction != null)
                        {
                            m_Actor.Activity = Activity.IDLE;
                            return(shoutAction);
                        }
                    }
                }
                // fight or flee.
                ActorAction fightOrFlee = BehaviorFightOrFlee(game, enemies, seeLeader, isLeaderFighting, Directives.Courage, m_Emotes);
                if (fightOrFlee != null)
                {
                    return(fightOrFlee);
                }
            }
            #endregion

            // 5 use medicine
            #region
            ActorAction useMedAction = BehaviorUseMedecine(game, 2, 1, 2, 4, 2);
            if (useMedAction != null)
            {
                m_Actor.Activity = Activity.IDLE;
                return(useMedAction);
            }
            #endregion

            // 6 rest if tired
            #region
            ActorAction restAction = BehaviorRestIfTired(game);
            if (restAction != null)
            {
                m_Actor.Activity = Activity.IDLE;
                return(new ActionWait(m_Actor, game));
            }
            #endregion

            // 7 charge enemy if courageous
            #region
            if (hasEnemies && isCourageous)
            {
                Percept     nearestEnemy = FilterNearest(game, enemies);
                ActorAction chargeAction = BehaviorChargeEnemy(game, nearestEnemy);
                if (chargeAction != null)
                {
                    m_Actor.Activity    = Activity.FIGHTING;
                    m_Actor.TargetActor = nearestEnemy.Percepted as Actor;
                    return(chargeAction);
                }
            }
            #endregion

            // 8 eat when hungry (also eat corpses)
            #region
            if (game.Rules.IsActorHungry(m_Actor))
            {
                ActorAction eatAction = BehaviorEat(game);
                if (eatAction != null)
                {
                    m_Actor.Activity = Activity.IDLE;
                    return(eatAction);
                }
                if (game.Rules.IsActorStarving(m_Actor) || game.Rules.IsActorInsane(m_Actor))
                {
                    eatAction = BehaviorGoEatCorpse(game, FilterCorpses(game, mapPercepts));
                    if (eatAction != null)
                    {
                        m_Actor.Activity = Activity.IDLE;
                        return(eatAction);
                    }
                }
            }
            #endregion

            // 9 sleep when almost sleepy and safe.
            #region
            if (m_SafeTurns >= MIN_TURNS_SAFE_TO_SLEEP && this.Directives.CanSleep &&
                WouldLikeToSleep(game, m_Actor) && IsInside(m_Actor) && game.Rules.CanActorSleep(m_Actor))
            {
                // secure sleep.
                ActorAction secureSleepAction = BehaviorSecurePerimeter(game, m_LOSSensor.FOV);
                if (secureSleepAction != null)
                {
                    m_Actor.Activity = Activity.IDLE;
                    return(secureSleepAction);
                }

                // sleep.
                ActorAction sleepAction = BehaviorSleep(game, m_LOSSensor.FOV);
                if (sleepAction != null)
                {
                    if (sleepAction is ActionSleep)
                    {
                        m_Actor.Activity = Activity.SLEEPING;
                    }
                    return(sleepAction);
                }
            }
            #endregion

            // 10 drop useless light/tracker/spray
            #region
            ActorAction dropUseless = BehaviorDropUselessItem(game);
            if (dropUseless != null)
            {
                m_Actor.Activity = Activity.IDLE;
                return(dropUseless);
            }
            #endregion

            // 11 equip light/tracker/spray.
            #region
            // tracker : if has leader or is a leader.
            bool needCellPhone = m_Actor.HasLeader || m_Actor.CountFollowers > 0;
            // then light.
            bool needLight = NeedsLight(game);
            // finally spray.
            bool needSpray = IsGoodStenchKillerSpot(game, m_Actor.Location.Map, m_Actor.Location.Position);
            // if tracker/light/spray useless, unequip it.
            if (!needCellPhone && !needLight && !needSpray)
            {
                ActorAction unequipUselessLeftItem = BehaviorUnequipLeftItem(game);
                if (unequipUselessLeftItem != null)
                {
                    m_Actor.Activity = Activity.IDLE;
                    return(unequipUselessLeftItem);
                }
            }
            // tracker?
            if (needCellPhone)
            {
                ActorAction eqTrackerAction = BehaviorEquipCellPhone(game);
                if (eqTrackerAction != null)
                {
                    m_Actor.Activity = Activity.IDLE;
                    return(eqTrackerAction);
                }
            }
            // ...or light?
            else if (needLight)
            {
                ActorAction eqLightAction = BehaviorEquipLight(game);
                if (eqLightAction != null)
                {
                    m_Actor.Activity = Activity.IDLE;
                    return(eqLightAction);
                }
            }
            // ... scent spray?
            else if (needSpray)
            {
                ActorAction eqScentSpray = BehaviorEquipStenchKiller(game);
                if (eqScentSpray != null)
                {
                    m_Actor.Activity = Activity.IDLE;
                    return(eqScentSpray);
                }
            }
            #endregion

            // 12 make room for food items if needed.
            // &&
            // 13 get nearby item/trade (not if seeing enemy)
            // ignore not currently visible items & blocked items.
            #region
            if (!hasEnemies && this.Directives.CanTakeItems)
            {
                Map map = m_Actor.Location.Map;

                #region Get nearby item
                // list visible items.
                List <Percept> interestingStacks = FilterOut(game, FilterStacks(game, mapPercepts),
                                                             (p) => (p.Turn != map.LocalTime.TurnCounter) ||
                                                             IsOccupiedByOther(map, p.Location.Position) ||
                                                             IsTileTaboo(p.Location.Position) ||
                                                             !HasAnyInterestingItem(game, p.Percepted as Inventory));

                // if some items...
                if (interestingStacks != null)
                {
                    // update last percept saw.
                    Percept nearestStack = FilterNearest(game, interestingStacks);
                    m_LastItemsSaw = nearestStack;

                    // 12: make room for food if needed.
                    ActorAction makeRoomForFood = BehaviorMakeRoomForFood(game, interestingStacks);
                    if (makeRoomForFood != null)
                    {
                        m_Actor.Activity = Activity.IDLE;
                        return(makeRoomForFood);
                    }

                    // 13: try to grab.
                    ActorAction grabAction = BehaviorGrabFromStack(game, nearestStack.Location.Position, nearestStack.Percepted as Inventory);
                    if (grabAction != null)
                    {
                        m_Actor.Activity = Activity.IDLE;
                        return(grabAction);
                    }
                    // we can't grab the item. mark the tile as taboo.
                    MarkTileAsTaboo(nearestStack.Location.Position);
                    // emote
                    game.DoEmote(m_Actor, "Mmmh. Looks like I can't reach what I want.");
                }
                #endregion

                #region Trade
                if (Directives.CanTrade)
                {
                    // get actors we want to trade with.
                    List <Percept> tradingActors = FilterOut(game, FilterNonEnemies(game, mapPercepts),
                                                             (p) =>
                    {
                        if (p.Turn != map.LocalTime.TurnCounter)
                        {
                            return(true);
                        }
                        Actor other = p.Percepted as Actor;
                        // dont bother player or someone we can't trade with or already did trade.
                        if (other.IsPlayer)
                        {
                            return(true);
                        }
                        if (!game.Rules.CanActorInitiateTradeWith(m_Actor, other))
                        {
                            return(true);
                        }
                        if (IsActorTabooTrade(other))
                        {
                            return(true);
                        }
                        // dont bother if no interesting items.
                        if (!HasAnyInterestingItem(game, other.Inventory))
                        {
                            return(true);
                        }
                        if (!((other.Controller as BaseAI).HasAnyInterestingItem(game, m_Actor.Inventory)))
                        {
                            return(true);
                        }
                        // don't reject.
                        return(false);
                    });
                    // trade with nearest.
                    if (tradingActors != null)
                    {
                        Actor tradeTarget = FilterNearest(game, tradingActors).Percepted as Actor;
                        if (game.Rules.IsAdjacent(m_Actor.Location, tradeTarget.Location))
                        {
                            ActorAction tradeAction = new ActionTrade(m_Actor, game, tradeTarget);
                            if (tradeAction.IsLegal())
                            {
                                // remember we tried to trade.
                                MarkActorAsRecentTrade(tradeTarget);
                                // say, so we make sure we spend a turn and won't loop.
                                game.DoSay(m_Actor, tradeTarget, String.Format("Hey {0}, let's make a deal!", tradeTarget.Name), RogueGame.Sayflags.NONE);
                                return(tradeAction);
                            }
                        }
                        else
                        {
                            ActorAction bump = BehaviorIntelligentBumpToward(game, tradeTarget.Location.Position);
                            if (bump != null)
                            {
                                m_Actor.Activity    = Activity.FOLLOWING;
                                m_Actor.TargetActor = tradeTarget;
                                return(bump);
                            }
                        }
                    }
                }
                #endregion
            }
            #endregion

            // 14 if hungry and no food, charge at people for food (option, not follower or law enforcer)
            #region
            if (RogueGame.Options.IsAggressiveHungryCiviliansOn &&
                mapPercepts != null && !m_Actor.HasLeader && !m_Actor.Model.Abilities.IsLawEnforcer &&
                game.Rules.IsActorHungry(m_Actor) && HasNoFoodItems(m_Actor))
            {
                Percept targetForFood = FilterNearest(game, FilterActors(game, mapPercepts,
                                                                         (a) =>
                {
                    // reject self, dead and leader/follower.
                    if (a == m_Actor)
                    {
                        return(false);
                    }
                    if (a.IsDead)
                    {
                        return(false);
                    }
                    if (a.Inventory == null || a.Inventory.IsEmpty)
                    {
                        return(false);
                    }
                    if (a.Leader == m_Actor || m_Actor.Leader == a)
                    {
                        return(false);
                    }

                    // actor has food or is standing on food.
                    if (a.Inventory.HasItemOfType(typeof(ItemFood)))
                    {
                        return(true);
                    }
                    Inventory groundInv = a.Location.Map.GetItemsAt(a.Location.Position);
                    if (groundInv == null || groundInv.IsEmpty)
                    {
                        return(false);
                    }
                    return(groundInv.HasItemOfType(typeof(ItemFood)));
                }));

                if (targetForFood != null)
                {
                    ActorAction chargeAction = BehaviorChargeEnemy(game, targetForFood);
                    if (chargeAction != null)
                    {
                        // randomly emote.
                        if (game.Rules.RollChance(HUNGRY_CHARGE_EMOTE_CHANCE))
                        {
                            game.DoSay(m_Actor, targetForFood.Percepted as Actor, "HEY! YOU! SHARE SOME FOOD!", RogueGame.Sayflags.IS_FREE_ACTION);
                        }

                        // chaaarge!
                        m_Actor.Activity    = Activity.FIGHTING;
                        m_Actor.TargetActor = targetForFood.Percepted as Actor;
                        return(chargeAction);
                    }
                }
            }
            #endregion

            // 15 use stench killer.
            #region
            if (game.Rules.RollChance(USE_STENCH_KILLER_CHANCE))
            {
                ActorAction sprayAction = BehaviorUseStenchKiller(game);
                if (sprayAction != null)
                {
                    m_Actor.Activity = Activity.IDLE;
                    return(sprayAction);
                }
            }
            #endregion

            // 16 close door behind me.
            #region
            ActorAction closeBehindMe = BehaviorCloseDoorBehindMe(game, PrevLocation);
            if (closeBehindMe != null)
            {
                m_Actor.Activity = Activity.IDLE;
                return(closeBehindMe);
            }
            #endregion

            // 17 use entertainment
            #region
            if (m_Actor.Model.Abilities.HasSanity)
            {
                if (m_Actor.Sanity < 0.75f * game.Rules.ActorMaxSanity(m_Actor))
                {
                    ActorAction entAction = BehaviorUseEntertainment(game);
                    if (entAction != null)
                    {
                        m_Actor.Activity = Activity.IDLE;
                        return(entAction);
                    }
                }
                ActorAction dropEnt = BehaviorDropBoringEntertainment(game);
                if (dropEnt != null)
                {
                    m_Actor.Activity = Activity.IDLE;
                    return(dropEnt);
                }
            }
            #endregion

            // 18 follow leader
            #region
            if (checkOurLeader)
            {
                Point       lastKnownLeaderPosition = m_Actor.Leader.Location.Position;
                bool        isLeaderVisible         = m_LOSSensor.FOV.Contains(m_Actor.Leader.Location.Position);
                int         maxDist      = m_Actor.Leader.IsPlayer ? FOLLOW_PLAYERLEADER_MAXDIST : FOLLOW_NPCLEADER_MAXDIST;
                ActorAction followAction = BehaviorFollowActor(game, m_Actor.Leader, lastKnownLeaderPosition, isLeaderVisible, maxDist);
                if (followAction != null)
                {
                    m_Actor.Activity    = Activity.FOLLOWING;
                    m_Actor.TargetActor = m_Actor.Leader;
                    return(followAction);
                }
            }
            #endregion

            // 19 take lead (if leadership)
            #region
            bool hasLeadership = m_Actor.Sheet.SkillTable.GetSkillLevel((int)Skills.IDs.LEADERSHIP) >= 1;
            if (hasLeadership)
            {
                bool canLead = !checkOurLeader && m_Actor.CountFollowers < game.Rules.ActorMaxFollowers(m_Actor);
                if (canLead)
                {
                    Percept nearestFriend = FilterNearest(game, FilterNonEnemies(game, mapPercepts));
                    if (nearestFriend != null)
                    {
                        ActorAction leadAction = BehaviorLeadActor(game, nearestFriend);
                        if (leadAction != null)
                        {
                            m_Actor.Activity    = Activity.IDLE;
                            m_Actor.TargetActor = nearestFriend.Percepted as Actor;
                            return(leadAction);
                        }
                    }
                }
            }
            #endregion

            // 20 if hungry, tear down barricades & push objects.
            #region
            if (game.Rules.IsActorHungry(m_Actor))
            {
                ActorAction attackBarricadeAction = BehaviorAttackBarricade(game);
                if (attackBarricadeAction != null)
                {
                    // emote.
                    game.DoEmote(m_Actor, "Open damn it! I know there is food there!");

                    // go!
                    m_Actor.Activity = Activity.IDLE;
                    return(attackBarricadeAction);
                }
                if (game.Rules.RollChance(HUNGRY_PUSH_OBJECTS_CHANCE))
                {
                    ActorAction pushAction = BehaviorPushNonWalkableObject(game);
                    if (pushAction != null)
                    {
                        // emote.
                        game.DoEmote(m_Actor, "Where is all the damn food?!");

                        // go!
                        m_Actor.Activity = Activity.IDLE;
                        return(pushAction);
                    }
                }
            }
            #endregion

            // 21 go revive corpse.
            ActorAction revive = BehaviorGoReviveCorpse(game, FilterCorpses(game, mapPercepts));
            if (revive != null)
            {
                m_Actor.Activity = Activity.IDLE;
                return(revive);
            }

            // 22 use exit.
            #region
            if (game.Rules.RollChance(USE_EXIT_CHANCE))
            {
                ActorAction useExit = BehaviorUseExit(game, UseExitFlags.DONT_BACKTRACK);
                if (useExit != null)
                {
                    m_Actor.Activity = Activity.IDLE;
                    return(useExit);
                }
            }
            #endregion

            // 23 build trap or fortification.
            #region
            if (game.Rules.RollChance(BUILD_TRAP_CHANCE))
            {
                ActorAction trapAction = BehaviorBuildTrap(game);
                if (trapAction != null)
                {
                    m_Actor.Activity = Activity.IDLE;
                    return(trapAction);
                }
            }
            // large fortification.
            if (game.Rules.RollChance(BUILD_LARGE_FORT_CHANCE))
            {
                ActorAction buildAction = BehaviorBuildLargeFortification(game, START_FORT_LINE_CHANCE);
                if (buildAction != null)
                {
                    m_Actor.Activity = Activity.IDLE;
                    return(buildAction);
                }
            }
            // small fortification.
            if (game.Rules.RollChance(BUILD_SMALL_FORT_CHANCE))
            {
                ActorAction buildAction = BehaviorBuildSmallFortification(game);
                if (buildAction != null)
                {
                    m_Actor.Activity = Activity.IDLE;
                    return(buildAction);
                }
            }
            #endregion

            // 24 tell friend about latest raid.
            #region
            // tell?
            if (m_LastRaidHeard != null && game.Rules.RollChance(TELL_FRIEND_ABOUT_RAID_CHANCE))
            {
                ActorAction tellAction = BehaviorTellFriendAboutPercept(game, m_LastRaidHeard);
                if (tellAction != null)
                {
                    m_Actor.Activity = Activity.IDLE;
                    return(tellAction);
                }
            }
            #endregion

            // 25 tell friend about latest soldier.
            #region
            // update percept.
            Percept seeingSoldier = FilterFirst(game, mapPercepts,
                                                (p) =>
            {
                Actor other = p.Percepted as Actor;
                if (other == null || other == m_Actor)
                {
                    return(false);
                }
                return(IsSoldier(other));
            });
            if (seeingSoldier != null)
            {
                m_LastSoldierSaw = seeingSoldier;
            }
            // tell?
            if (game.Rules.RollChance(TELL_FRIEND_ABOUT_SOLDIER_CHANCE) && m_LastSoldierSaw != null)
            {
                ActorAction tellAction = BehaviorTellFriendAboutPercept(game, m_LastSoldierSaw);
                if (tellAction != null)
                {
                    m_Actor.Activity = Activity.IDLE;
                    return(tellAction);
                }
            }
            #endregion

            // 26 tell friend about latest enemy.
            #region
            if (game.Rules.RollChance(TELL_FRIEND_ABOUT_ENEMY_CHANCE) && m_LastEnemySaw != null)
            {
                ActorAction tellAction = BehaviorTellFriendAboutPercept(game, m_LastEnemySaw);
                if (tellAction != null)
                {
                    m_Actor.Activity = Activity.IDLE;
                    return(tellAction);
                }
            }
            #endregion

            // 27 tell friend about latest items.
            #region
            if (game.Rules.RollChance(TELL_FRIEND_ABOUT_ITEMS_CHANCE) && m_LastItemsSaw != null)
            {
                ActorAction tellAction = BehaviorTellFriendAboutPercept(game, m_LastItemsSaw);
                if (tellAction != null)
                {
                    m_Actor.Activity = Activity.IDLE;
                    return(tellAction);
                }
            }
            #endregion

            // 28 (law enforcer) watch for murderers.
            #region
            if (m_Actor.Model.Abilities.IsLawEnforcer && mapPercepts != null && game.Rules.RollChance(LAW_ENFORCE_CHANCE))
            {
                Actor       target;
                ActorAction lawAction = BehaviorEnforceLaw(game, mapPercepts, out target);
                if (lawAction != null)
                {
                    m_Actor.TargetActor = target;
                    return(lawAction);
                }
            }
            #endregion

            // 29 (leader) don't leave followers behind.
            #region
            if (m_Actor.CountFollowers > 0)
            {
                Actor       target;
                ActorAction stickTogether = BehaviorDontLeaveFollowersBehind(game, 2, out target);
                if (stickTogether != null)
                {
                    // emote?
                    if (game.Rules.RollChance(DONT_LEAVE_BEHIND_EMOTE_CHANCE))
                    {
                        if (target.IsSleeping)
                        {
                            game.DoEmote(m_Actor, String.Format("patiently waits for {0} to wake up.", target.Name));
                        }
                        else
                        {
                            if (m_LOSSensor.FOV.Contains(target.Location.Position))
                            {
                                game.DoEmote(m_Actor, String.Format("Come on {0}! Hurry up!", target.Name));
                            }
                            else
                            {
                                game.DoEmote(m_Actor, String.Format("Where the hell is {0}?", target.Name));
                            }
                        }
                    }

                    // go!
                    m_Actor.Activity = Activity.IDLE;
                    return(stickTogether);
                }
            }
            #endregion

            // 30 explore
            #region
            ActorAction exploreAction = BehaviorExplore(game, m_Exploration);
            if (exploreAction != null)
            {
                m_Actor.Activity = Activity.IDLE;
                return(exploreAction);
            }
            #endregion

            // 31 wander.
            #region
            m_Actor.Activity = Activity.IDLE;
            return(BehaviorWander(game));

            #endregion

            #endregion
        }
예제 #3
0
        protected override ActorAction SelectAction(RogueGame game, List <Percept> percepts)
        {
            HashSet <Point> FOV         = m_LOSSensor.FOV;
            List <Percept>  mapPercepts = FilterSameMap(game, percepts);

            // 1. Follow order
            #region
            if (this.Order != null)
            {
                ActorAction orderAction = ExecuteOrder(game, this.Order, mapPercepts);
                if (orderAction == null)
                {
                    SetOrder(null);
                }
                else
                {
                    m_Actor.Activity = Activity.FOLLOWING_ORDER;
                    return(orderAction);
                }
            }
            #endregion

            //////////////////////////////////////////////////////////////////////
            // partial copy of Civilian AI 8) but always courageous and gets into fights.
            // BEHAVIOR
            // - FLAGS
            // "courageous" : always if not tired.
            // - RULES
            // 1 equip weapon/armor
            // 2 fire at nearest.
            // 3 shout, fight or flee.
            // 4 use medecine
            // 5 rest if tired
            // 6 charge enemy if courageous
            // 7 eat when hungry (also eat corpses)
            // 8 sleep.
            // 9 drop light/tracker with no batteries
            // 10 equip light/tracker
            // 11 get nearby item (not if seeing enemy)
            // 12 steal item from someone.
            // 13 tear down barricade
            // 14 follow leader
            // 15 take lead (if leadership)
            // 16 (leader) don't leave follower behind.
            // 17 explore
            // 18 wander
            //////////////////////////////////////////////////////////////////////

            // don't run by default.
            m_Actor.IsRunning = false;

            // get data.
            List <Percept> allEnemies        = FilterEnemies(game, mapPercepts);
            List <Percept> currentEnemies    = FilterCurrent(game, allEnemies);
            bool           hasCurrentEnemies = currentEnemies != null;
            bool           hasAnyEnemies     = allEnemies != null;
            bool           checkOurLeader    = m_Actor.HasLeader && !DontFollowLeader;
            bool           seeLeader         = checkOurLeader && FOV.Contains(m_Actor.Leader.Location.Position);
            bool           isLeaderFighting  = checkOurLeader && IsAdjacentToEnemy(game, m_Actor.Leader);
            bool           isCourageous      = !game.Rules.IsActorTired(m_Actor);

            // exploration.
            m_Exploration.Update(m_Actor.Location);

            // 1 equip weapon/armor
            #region
            ActorAction equipWpnAction = BehaviorEquipWeapon(game);
            if (equipWpnAction != null)
            {
                m_Actor.Activity = Activity.IDLE;
                return(equipWpnAction);
            }
            ActorAction equipArmAction = BehaviorEquipBodyArmor(game);
            if (equipArmAction != null)
            {
                m_Actor.Activity = Activity.IDLE;
                return(equipArmAction);
            }
            #endregion

            // 2 fire at nearest enemy (always if has leader, half of the time if not)
            #region
            if (hasCurrentEnemies && (checkOurLeader || game.Rules.RollChance(50)))
            {
                List <Percept> fireTargets = FilterFireTargets(game, currentEnemies);
                if (fireTargets != null)
                {
                    Percept     nearestTarget = FilterNearest(game, fireTargets);
                    ActorAction fireAction    = BehaviorRangedAttack(game, nearestTarget);
                    if (fireAction != null)
                    {
                        m_Actor.Activity    = Activity.FIGHTING;
                        m_Actor.TargetActor = nearestTarget.Percepted as Actor;
                        return(fireAction);
                    }
                }
            }
            #endregion

            // 3 shout, fight or flee
            #region
            if (hasCurrentEnemies)
            {
                // shout?
                if (game.Rules.RollChance(50))
                {
                    List <Percept> friends = FilterNonEnemies(game, mapPercepts);
                    if (friends != null)
                    {
                        ActorAction shoutAction = BehaviorWarnFriends(game, friends, FilterNearest(game, currentEnemies).Percepted as Actor);
                        if (shoutAction != null)
                        {
                            m_Actor.Activity = Activity.IDLE;
                            return(shoutAction);
                        }
                    }
                }
                // fight or flee.
                ActorAction fightOrFlee = BehaviorFightOrFlee(game, currentEnemies, seeLeader, isLeaderFighting, ActorCourage.COURAGEOUS, FIGHT_EMOTES);
                if (fightOrFlee != null)
                {
                    return(fightOrFlee);
                }
            }
            #endregion

            // 4 use medecine
            #region
            ActorAction useMedAction = BehaviorUseMedecine(game, 2, 1, 2, 4, 2);
            if (useMedAction != null)
            {
                m_Actor.Activity = Activity.IDLE;
                return(useMedAction);
            }
            #endregion

            // 5 rest if tired
            #region
            ActorAction restAction = BehaviorRestIfTired(game);
            if (restAction != null)
            {
                m_Actor.Activity = Activity.IDLE;
                return(new ActionWait(m_Actor, game));
            }
            #endregion

            // 6 charge enemy if courageous
            #region
            if (hasCurrentEnemies && isCourageous)
            {
                Percept     nearestEnemy = FilterNearest(game, currentEnemies);
                ActorAction chargeAction = BehaviorChargeEnemy(game, nearestEnemy);
                if (chargeAction != null)
                {
                    m_Actor.Activity    = Activity.FIGHTING;
                    m_Actor.TargetActor = nearestEnemy.Percepted as Actor;
                    return(chargeAction);
                }
            }
            #endregion

            // 7 eat when hungry (also eat corpses)
            #region
            if (game.Rules.IsActorHungry(m_Actor))
            {
                ActorAction eatAction = BehaviorEat(game);
                if (eatAction != null)
                {
                    m_Actor.Activity = Activity.IDLE;
                    return(eatAction);
                }
                if (game.Rules.IsActorStarving(m_Actor) || game.Rules.IsActorInsane(m_Actor))
                {
                    eatAction = BehaviorGoEatCorpse(game, FilterCorpses(game, mapPercepts));
                    if (eatAction != null)
                    {
                        m_Actor.Activity = Activity.IDLE;
                        return(eatAction);
                    }
                }
            }
            #endregion

            // 8 sleep.
            #region
            if (!hasAnyEnemies && WouldLikeToSleep(game, m_Actor) && IsInside(m_Actor) && game.Rules.CanActorSleep(m_Actor))
            {
                // secure sleep?
                ActorAction secureSleepAction = BehaviorSecurePerimeter(game, m_LOSSensor.FOV);
                if (secureSleepAction != null)
                {
                    m_Actor.Activity = Activity.IDLE;
                    return(secureSleepAction);
                }

                // sleep.
                ActorAction sleepAction = BehaviorSleep(game, m_LOSSensor.FOV);
                if (sleepAction != null)
                {
                    if (sleepAction is ActionSleep)
                    {
                        m_Actor.Activity = Activity.SLEEPING;
                    }
                    return(sleepAction);
                }
            }
            #endregion

            // 9 drop light/tracker with no batteries
            #region
            ActorAction dropOutOfBatteries = BehaviorDropUselessItem(game);
            if (dropOutOfBatteries != null)
            {
                m_Actor.Activity = Activity.IDLE;
                return(dropOutOfBatteries);
            }
            #endregion

            // 10 equip light/tracker
            #region
            // tracker : if has leader or is a leader.
            bool needCellPhone = checkOurLeader || m_Actor.CountFollowers > 0;
            // then light.
            bool needLight = NeedsLight(game);
            // if tracker or light useless, unequip it.
            if (!needCellPhone && !needLight)
            {
                ActorAction unequipUselessLeftItem = BehaviorUnequipLeftItem(game);
                if (unequipUselessLeftItem != null)
                {
                    m_Actor.Activity = Activity.IDLE;
                    return(unequipUselessLeftItem);
                }
            }
            // tracker?
            if (needCellPhone)
            {
                ActorAction eqTrackerAction = BehaviorEquipCellPhone(game);
                if (eqTrackerAction != null)
                {
                    m_Actor.Activity = Activity.IDLE;
                    return(eqTrackerAction);
                }
            }
            // ...or light?
            else if (needLight)
            {
                ActorAction eqLightAction = BehaviorEquipLight(game);
                if (eqLightAction != null)
                {
                    m_Actor.Activity = Activity.IDLE;
                    return(eqLightAction);
                }
            }
            #endregion

            // 11 get nearby item (not if seeing enemy)
            // ignore not currently visible items & blocked items.
            #region
            if (!hasCurrentEnemies)
            {
                Map            map    = m_Actor.Location.Map;
                List <Percept> stacks = FilterOut(game, FilterStacks(game, mapPercepts),
                                                  (p) => (p.Turn != map.LocalTime.TurnCounter) || IsOccupiedByOther(map, p.Location.Position));
                if (stacks != null)
                {
                    Percept     nearestStack = FilterNearest(game, stacks);
                    ActorAction grabAction   = BehaviorGrabFromStack(game, nearestStack.Location.Position, nearestStack.Percepted as Inventory);
                    if (grabAction != null)
                    {
                        m_Actor.Activity = Activity.IDLE;
                        return(grabAction);
                    }
                }
            }
            #endregion

            // 12 steal item from someone.
            #region
            if (!hasCurrentEnemies)
            {
                Map            map          = m_Actor.Location.Map;
                List <Percept> mayStealFrom = FilterActors(game, FilterCurrent(game, mapPercepts),
                                                           (a) =>
                {
                    if (a.Inventory == null || a.Inventory.CountItems == 0 || IsFriendOf(game, a))
                    {
                        return(false);
                    }
                    if (game.Rules.RollChance(game.Rules.ActorUnsuspicousChance(m_Actor, a)))
                    {
                        // emote.
                        game.DoEmote(a, String.Format("moves unnoticed by {0}.", m_Actor.Name));
                        // unnoticed.
                        return(false);
                    }
                    return(HasAnyInterestingItem(game, a.Inventory));
                });
                if (mayStealFrom != null)
                {
                    // get data.
                    Percept nearest = FilterNearest(game, mayStealFrom);
                    Actor   victim  = nearest.Percepted as Actor;
                    Item    wantIt  = FirstInterestingItem(game, victim.Inventory);

                    // make an enemy of him.
                    game.DoMakeAggression(m_Actor, victim);

                    // declare my evil intentions.
                    m_Actor.Activity    = Activity.CHASING;
                    m_Actor.TargetActor = victim;
                    return(new ActionSay(m_Actor, game, victim,
                                         String.Format("Hey! That's some nice {0} you have here!", wantIt.Model.SingleName), RogueGame.Sayflags.IS_IMPORTANT));
                }
            }
            #endregion

            // 13 tear down barricade
            ActorAction attackBarricadeAction = BehaviorAttackBarricade(game);
            if (attackBarricadeAction != null)
            {
                m_Actor.Activity = Activity.IDLE;
                return(attackBarricadeAction);
            }

            // 14 follow leader
            if (checkOurLeader)
            {
                Point       lastKnownLeaderPosition = m_Actor.Leader.Location.Position;
                bool        isLeaderVisible         = FOV.Contains(m_Actor.Leader.Location.Position);
                int         maxDist      = m_Actor.Leader.IsPlayer ? FOLLOW_PLAYERLEADER_MAXDIST : FOLLOW_NPCLEADER_MAXDIST;
                ActorAction followAction = BehaviorFollowActor(game, m_Actor.Leader, lastKnownLeaderPosition, isLeaderVisible, maxDist);
                if (followAction != null)
                {
                    m_Actor.Activity    = Activity.FOLLOWING;
                    m_Actor.TargetActor = m_Actor.Leader;
                    return(followAction);
                }
            }

            // 15 take lead (if leadership)
            bool isLeader = m_Actor.Sheet.SkillTable.GetSkillLevel((int)Skills.IDs.LEADERSHIP) >= 1;
            bool canLead  = !checkOurLeader && isLeader && m_Actor.CountFollowers < game.Rules.ActorMaxFollowers(m_Actor);
            if (canLead)
            {
                Percept nearestFriend = FilterNearest(game, FilterNonEnemies(game, mapPercepts));
                if (nearestFriend != null)
                {
                    ActorAction leadAction = BehaviorLeadActor(game, nearestFriend);
                    if (leadAction != null)
                    {
                        m_Actor.Activity    = Activity.IDLE;
                        m_Actor.TargetActor = nearestFriend.Percepted as Actor;
                        return(leadAction);
                    }
                }
            }

            // 16 (leader) don't leave followers behind.
            #region
            if (m_Actor.CountFollowers > 0)
            {
                Actor       target;
                ActorAction stickTogether = BehaviorDontLeaveFollowersBehind(game, 3, out target);
                if (stickTogether != null)
                {
                    // emote?
                    if (game.Rules.RollChance(DONT_LEAVE_BEHIND_EMOTE_CHANCE))
                    {
                        if (target.IsSleeping)
                        {
                            game.DoEmote(m_Actor, String.Format("patiently waits for {0} to wake up.", target.Name));
                        }
                        else
                        {
                            if (m_LOSSensor.FOV.Contains(target.Location.Position))
                            {
                                game.DoEmote(m_Actor, String.Format("Hey {0}! F*****g move!", target.Name));
                            }
                            else
                            {
                                game.DoEmote(m_Actor, String.Format("Where is that {0} retard?", target.Name));
                            }
                        }
                    }

                    // go!
                    m_Actor.Activity = Activity.IDLE;
                    return(stickTogether);
                }
            }
            #endregion

            // 17 explore
            ActorAction exploreAction = BehaviorExplore(game, m_Exploration);
            if (exploreAction != null)
            {
                m_Actor.Activity = Activity.IDLE;
                return(exploreAction);
            }

            // 18 wander
            m_Actor.Activity = Activity.IDLE;
            return(BehaviorWander(game));
        }
        protected override ActorAction SelectAction(RogueGame game, List <Percept> percepts)
        {
            List <Percept> mapPercepts = FilterSameMap(game, percepts);

            // alpha10
            // don't run by default.
            m_Actor.IsRunning = false;

            // 0. Equip best item
            ActorAction bestEquip = BehaviorEquipBestItems(game, false, true);

            if (bestEquip != null)
            {
                return(bestEquip);
            }
            // end alpha10

            // 1. Follow order
            #region
            if (this.Order != null)
            {
                ActorAction orderAction = ExecuteOrder(game, this.Order, mapPercepts, m_Exploration);
                if (orderAction == null)
                {
                    SetOrder(null);
                }
                else
                {
                    m_Actor.Activity = Activity.FOLLOWING_ORDER;
                    return(orderAction);
                }
            }
            #endregion

            /////////////////////////////////////
            // 0 run away from primed explosives.
            // 1 throw grenades at enemies.
            // alpha10 OBSOLETE 2 equip weapon/armor.
            // 3 shout, fire/hit at nearest enemy.
            // 4 rest if tired
            // alpha10 obsolete and redundant with rule 3! 5 charge enemy.
            // 6 use med.
            // 7 sleep.
            // 8 chase old enemy.
            // 9 build fortification.
            // 10 hang around leader.
            // 11 (leader) don't leave followers behind.
            // 12 explore.
            // 13 wander.
            ////////////////////////////////////

            // get data.
            List <Percept> allEnemies        = FilterEnemies(game, mapPercepts);
            List <Percept> currentEnemies    = FilterCurrent(game, allEnemies);
            bool           checkOurLeader    = m_Actor.HasLeader && !DontFollowLeader;
            bool           hasCurrentEnemies = (currentEnemies != null);
            bool           hasAnyEnemies     = (allEnemies != null);

            // exploration.
            m_Exploration.Update(m_Actor.Location);

            // 0 run away from primed explosives.
            #region
            ActorAction runFromExplosives = BehaviorFleeFromExplosives(game, FilterStacks(game, mapPercepts));
            if (runFromExplosives != null)
            {
                m_Actor.Activity = Activity.FLEEING_FROM_EXPLOSIVE;
                return(runFromExplosives);
            }
            #endregion

            // 1 throw grenades at enemies.
            #region
            if (hasCurrentEnemies)
            {
                ActorAction throwAction = BehaviorThrowGrenade(game, m_LOSSensor.FOV, currentEnemies);
                if (throwAction != null)
                {
                    return(throwAction);
                }
            }
            #endregion

            // alpha10 obsolete
            // 2 equip weapon/armor
            //#region
            //ActorAction equipWpnAction = BehaviorEquipWeapon(game);
            //if (equipWpnAction != null)
            //{
            //    m_Actor.Activity = Activity.IDLE;
            //    return equipWpnAction;
            //}
            //ActorAction equipArmAction = BehaviorEquipBestBodyArmor(game);
            //if (equipArmAction != null)
            //{
            //    m_Actor.Activity = Activity.IDLE;
            //    return equipArmAction;
            //}
            //#endregion

            // 3 shout, fire/hit at nearest enemy.
            #region
            if (hasCurrentEnemies)
            {
                // shout?
                if (game.Rules.RollChance(50))
                {
                    List <Percept> friends = FilterNonEnemies(game, mapPercepts);
                    if (friends != null)
                    {
                        ActorAction shoutAction = BehaviorWarnFriends(game, friends, FilterNearest(game, currentEnemies).Percepted as Actor);
                        if (shoutAction != null)
                        {
                            m_Actor.Activity = Activity.IDLE;
                            return(shoutAction);
                        }
                    }
                }

                // fire?
                List <Percept> fireTargets = FilterFireTargets(game, currentEnemies);
                if (fireTargets != null)
                {
                    Percept     nearestTarget = FilterNearest(game, fireTargets);
                    ActorAction fireAction    = BehaviorRangedAttack(game, nearestTarget);
                    if (fireAction != null)
                    {
                        m_Actor.Activity    = Activity.FIGHTING;
                        m_Actor.TargetActor = nearestTarget.Percepted as Actor;
                        return(fireAction);
                    }
                }

                // fight or flee?
                RouteFinder.SpecialActions allowedChargeActions = RouteFinder.SpecialActions.JUMP | RouteFinder.SpecialActions.DOORS; // alpha10
                ActorAction fightOrFlee = BehaviorFightOrFlee(game, currentEnemies, true, true, ActorCourage.COURAGEOUS, FIGHT_EMOTES, allowedChargeActions);
                if (fightOrFlee != null)
                {
                    return(fightOrFlee);
                }
            }
            #endregion

            // 4 rest if tired
            #region
            ActorAction restAction = BehaviorRestIfTired(game);
            if (restAction != null)
            {
                m_Actor.Activity = Activity.IDLE;
                return(restAction);
            }
            #endregion

            // alpha10 obsolete and redundant with rule 3!
            //// 5 charge enemy
            //#region
            //if (hasAnyEnemies)
            //{
            //    Percept nearestEnemy = FilterNearest(game, allEnemies);
            //    ActorAction chargeAction = BehaviorChargeEnemy(game, nearestEnemy, false, false);
            //    if (chargeAction != null)
            //    {
            //        m_Actor.Activity = Activity.FIGHTING;
            //        m_Actor.TargetActor = nearestEnemy.Percepted as Actor;
            //        return chargeAction;
            //    }
            //}
            //#endregion

            // 6 use medicine
            #region
            ActorAction useMedAction = BehaviorUseMedecine(game, 2, 1, 2, 4, 2);
            if (useMedAction != null)
            {
                m_Actor.Activity = Activity.IDLE;
                return(useMedAction);
            }
            #endregion

            // 7 sleep.
            #region
            if (!hasAnyEnemies && WouldLikeToSleep(game, m_Actor) && IsInside(m_Actor) && game.Rules.CanActorSleep(m_Actor))
            {
                // secure sleep?
                ActorAction secureSleepAction = BehaviorSecurePerimeter(game, m_LOSSensor.FOV);
                if (secureSleepAction != null)
                {
                    m_Actor.Activity = Activity.IDLE;
                    return(secureSleepAction);
                }

                // sleep.
                ActorAction sleepAction = BehaviorSleep(game, m_LOSSensor.FOV);
                if (sleepAction != null)
                {
                    if (sleepAction is ActionSleep)
                    {
                        m_Actor.Activity = Activity.SLEEPING;
                    }
                    return(sleepAction);
                }
            }
            #endregion

            // 8 chase old enemy
            #region
            List <Percept> oldEnemies = Filter(game, allEnemies, (p) => p.Turn != m_Actor.Location.Map.LocalTime.TurnCounter);
            if (oldEnemies != null)
            {
                Percept chasePercept = FilterNearest(game, oldEnemies);

                // cheat a bit for good chasing behavior.
                if (m_Actor.Location == chasePercept.Location)
                {
                    // memorized location reached, chase now the actor directly (cheat so they appear more intelligent)
                    Actor chasedActor = chasePercept.Percepted as Actor;
                    chasePercept = new Percept(chasedActor, m_Actor.Location.Map.LocalTime.TurnCounter, chasedActor.Location);
                }

                // chase.
                ActorAction chargeAction = BehaviorChargeEnemy(game, chasePercept, false, false);
                if (chargeAction != null)
                {
                    m_Actor.Activity    = Activity.FIGHTING;
                    m_Actor.TargetActor = chasePercept.Percepted as Actor;
                    return(chargeAction);
                }
            }
            #endregion

            // 9 build fortification
            #region
            // large fortification.
            if (game.Rules.RollChance(BUILD_LARGE_FORT_CHANCE))
            {
                ActorAction buildAction = BehaviorBuildLargeFortification(game, START_FORT_LINE_CHANCE);
                if (buildAction != null)
                {
                    m_Actor.Activity = Activity.IDLE;
                    return(buildAction);
                }
            }
            // small fortification.
            if (game.Rules.RollChance(BUILD_SMALL_FORT_CHANCE))
            {
                ActorAction buildAction = BehaviorBuildSmallFortification(game);
                if (buildAction != null)
                {
                    m_Actor.Activity = Activity.IDLE;
                    return(buildAction);
                }
            }
            #endregion

            // 10 hang around leader.
            #region
            if (checkOurLeader)
            {
                Point       lastKnownLeaderPosition = m_Actor.Leader.Location.Position;
                ActorAction followAction            = BehaviorHangAroundActor(game, m_Actor.Leader, lastKnownLeaderPosition, FOLLOW_LEADER_MIN_DIST, FOLLOW_LEADER_MAX_DIST);
                if (followAction != null)
                {
                    m_Actor.Activity    = Activity.FOLLOWING;
                    m_Actor.TargetActor = m_Actor.Leader;
                    return(followAction);
                }
            }
            #endregion

            // 11 (leader) don't leave followers behind.
            #region
            if (m_Actor.CountFollowers > 0)
            {
                Actor       target;
                ActorAction stickTogether = BehaviorDontLeaveFollowersBehind(game, 4, out target);
                if (stickTogether != null)
                {
                    // emote?
                    if (game.Rules.RollChance(DONT_LEAVE_BEHIND_EMOTE_CHANCE))
                    {
                        if (target.IsSleeping)
                        {
                            game.DoEmote(m_Actor, String.Format("patiently waits for {0} to wake up.", target.Name));
                        }
                        else
                        {
                            if (m_LOSSensor.FOV.Contains(target.Location.Position))
                            {
                                game.DoEmote(m_Actor, String.Format("{0}! Don't lag behind!", target.Name));
                            }
                            else
                            {
                                game.DoEmote(m_Actor, String.Format("Where the hell is {0}?", target.Name));
                            }
                        }
                    }

                    // go!
                    m_Actor.Activity = Activity.IDLE;
                    return(stickTogether);
                }
            }
            #endregion

            // 12 explore
            #region
            ActorAction exploreAction = BehaviorExplore(game, m_Exploration);
            if (exploreAction != null)
            {
                m_Actor.Activity = Activity.IDLE;
                return(exploreAction);
            }
            #endregion

            // 13 wander
            #region
            m_Actor.Activity = Activity.IDLE;
            return(BehaviorWander(game, m_Exploration));

            #endregion
        }
예제 #5
0
        protected override ActorAction SelectAction(RogueGame game, List <Percept> percepts)
        {
            HashSet <Point> FOV         = m_LOSSensor.FOV;
            List <Percept>  mapPercepts = FilterSameMap(game, percepts);

            // alpha10
            // don't run by default.
            m_Actor.IsRunning = false;

            // 0. Equip best item
            ActorAction bestEquip = BehaviorEquipBestItems(game, true, true);

            if (bestEquip != null)
            {
                return(bestEquip);
            }
            // end alpha10

            // 1. Follow order
            #region
            if (this.Order != null)
            {
                ActorAction orderAction = ExecuteOrder(game, this.Order, mapPercepts, m_Exploration);
                if (orderAction == null)
                {
                    SetOrder(null);
                }
                else
                {
                    m_Actor.Activity = Activity.FOLLOWING_ORDER;
                    return(orderAction);
                }
            }
            #endregion

            //////////////////////////////////////////////////////////////////////
            // partial copy of Civilian AI 8) but always courageous and gets into fights.
            // BEHAVIOR
            // - FLAGS
            // "courageous" : always if not tired.
            // - RULES
            // alpha10 OBSOLETE 1 equip weapon/armor
            // 2 fire at nearest.
            // 3 shout, fight or flee.
            // 4 use medecine
            // 5 rest if tired
            // // alpa10 obsolete and redundant with rule 3!! 6 charge enemy if courageous
            // 7 eat when hungry (also eat corpses)
            // 8 sleep.
            // 9 drop light/tracker with no batteries
            // alpa10 OBSOLETE 10 equip light/tracker
            // 11 get nearby item (not if seeing enemy)
            // 12 steal item from someone.
            // 13 tear down barricade
            // 14 follow leader
            // 15 take lead (if leadership)
            // 16 (leader) don't leave follower behind.
            // 17 explore
            // 18 wander
            //////////////////////////////////////////////////////////////////////

            // get data.
            List <Percept> allEnemies        = FilterEnemies(game, mapPercepts);
            List <Percept> currentEnemies    = FilterCurrent(game, allEnemies);
            bool           hasCurrentEnemies = currentEnemies != null;
            bool           hasAnyEnemies     = allEnemies != null;
            bool           checkOurLeader    = m_Actor.HasLeader && !DontFollowLeader;
            bool           seeLeader         = checkOurLeader && FOV.Contains(m_Actor.Leader.Location.Position);
            bool           isLeaderFighting  = checkOurLeader && IsAdjacentToEnemy(game, m_Actor.Leader);
            bool           isCourageous      = !game.Rules.IsActorTired(m_Actor);

            // exploration.
            m_Exploration.Update(m_Actor.Location);

            // alpha10 needed due to uggraded get item behavior
            // clear taboo tiles : periodically or when changing maps.
            if (m_Actor.Location.Map.LocalTime.TurnCounter % WorldTime.TURNS_PER_HOUR == 0 ||
                (PrevLocation != null && PrevLocation.Map != m_Actor.Location.Map))
            {
                ClearTabooTiles();
            }

            // 1 equip weapon/armor
            // alpha10 obsolete
            //#region
            //ActorAction equipWpnAction = BehaviorEquipWeapon(game);
            //if (equipWpnAction != null)
            //{
            //    m_Actor.Activity = Activity.IDLE;
            //    return equipWpnAction;
            //}
            //ActorAction equipArmAction = BehaviorEquipBestBodyArmor(game);
            //if (equipArmAction != null)
            //{
            //    m_Actor.Activity = Activity.IDLE;
            //    return equipArmAction;
            //}
            //#endregion

            // 2 fire at nearest enemy (always if has leader, half of the time if not)
            #region
            if (hasCurrentEnemies && (checkOurLeader || game.Rules.RollChance(50)))
            {
                List <Percept> fireTargets = FilterFireTargets(game, currentEnemies);
                if (fireTargets != null)
                {
                    Percept     nearestTarget = FilterNearest(game, fireTargets);
                    ActorAction fireAction    = BehaviorRangedAttack(game, nearestTarget);
                    if (fireAction != null)
                    {
                        m_Actor.Activity    = Activity.FIGHTING;
                        m_Actor.TargetActor = nearestTarget.Percepted as Actor;
                        return(fireAction);
                    }
                }
            }
            #endregion

            // 3 shout, fight or flee
            #region
            if (hasCurrentEnemies)
            {
                // shout?
                if (game.Rules.RollChance(50))
                {
                    List <Percept> friends = FilterNonEnemies(game, mapPercepts);
                    if (friends != null)
                    {
                        ActorAction shoutAction = BehaviorWarnFriends(game, friends, FilterNearest(game, currentEnemies).Percepted as Actor);
                        if (shoutAction != null)
                        {
                            m_Actor.Activity = Activity.IDLE;
                            return(shoutAction);
                        }
                    }
                }

                // fight or flee.
                RouteFinder.SpecialActions allowedChargeActions = RouteFinder.SpecialActions.JUMP | RouteFinder.SpecialActions.DOORS; // alpha10
                // gangs are allowed to make a mess :)
                allowedChargeActions |= RouteFinder.SpecialActions.BREAK | RouteFinder.SpecialActions.PUSH;
                ActorAction fightOrFlee = BehaviorFightOrFlee(game, currentEnemies, seeLeader, isLeaderFighting, ActorCourage.COURAGEOUS, FIGHT_EMOTES, allowedChargeActions);
                if (fightOrFlee != null)
                {
                    return(fightOrFlee);
                }
            }
            #endregion

            // 4 use medecine
            #region
            ActorAction useMedAction = BehaviorUseMedecine(game, 2, 1, 2, 4, 2);
            if (useMedAction != null)
            {
                m_Actor.Activity = Activity.IDLE;
                return(useMedAction);
            }
            #endregion

            // 5 rest if tired
            #region
            ActorAction restAction = BehaviorRestIfTired(game);
            if (restAction != null)
            {
                m_Actor.Activity = Activity.IDLE;
                return(new ActionWait(m_Actor, game));
            }
            #endregion

            // alpa10 obsolete and redundant with rule 3!!
            //// 6 charge enemy if courageous
            //#region
            //if (hasCurrentEnemies && isCourageous)
            //{
            //    Percept nearestEnemy = FilterNearest(game, currentEnemies);
            //    // alpha10 Gangs can make a mess :)
            //    ActorAction chargeAction = BehaviorChargeEnemy(game, nearestEnemy, true, true);
            //    if (chargeAction != null)
            //    {
            //        m_Actor.Activity = Activity.FIGHTING;
            //        m_Actor.TargetActor = nearestEnemy.Percepted as Actor;
            //        return chargeAction;
            //    }
            //}
            //#endregion

            // 7 eat when hungry (also eat corpses)
            #region
            if (game.Rules.IsActorHungry(m_Actor))
            {
                ActorAction eatAction = BehaviorEat(game);
                if (eatAction != null)
                {
                    m_Actor.Activity = Activity.IDLE;
                    return(eatAction);
                }
                if (game.Rules.IsActorStarving(m_Actor) || game.Rules.IsActorInsane(m_Actor))
                {
                    eatAction = BehaviorGoEatCorpse(game, FilterCorpses(game, mapPercepts));
                    if (eatAction != null)
                    {
                        m_Actor.Activity = Activity.IDLE;
                        return(eatAction);
                    }
                }
            }
            #endregion

            // 8 sleep.
            #region
            if (!hasAnyEnemies && WouldLikeToSleep(game, m_Actor) && IsInside(m_Actor) && game.Rules.CanActorSleep(m_Actor))
            {
                // secure sleep?
                ActorAction secureSleepAction = BehaviorSecurePerimeter(game, m_LOSSensor.FOV);
                if (secureSleepAction != null)
                {
                    m_Actor.Activity = Activity.IDLE;
                    return(secureSleepAction);
                }

                // sleep.
                ActorAction sleepAction = BehaviorSleep(game, m_LOSSensor.FOV);
                if (sleepAction != null)
                {
                    if (sleepAction is ActionSleep)
                    {
                        m_Actor.Activity = Activity.SLEEPING;
                    }
                    return(sleepAction);
                }
            }
            #endregion

            // 9 drop light/tracker with no batteries
            #region
            ActorAction dropOutOfBatteries = BehaviorDropUselessItem(game);
            if (dropOutOfBatteries != null)
            {
                m_Actor.Activity = Activity.IDLE;
                return(dropOutOfBatteries);
            }
            #endregion

            // 10 equip light/tracker
            // alpha10 obsolete
            //#region
            //// tracker : if has leader or is a leader.
            //bool needCellPhone = checkOurLeader || m_Actor.CountFollowers > 0;
            //// then light.
            //bool needLight = NeedsLight(game);
            //// if tracker or light useless, unequip it.
            //if (!needCellPhone && !needLight)
            //{
            //    ActorAction unequipUselessLeftItem = BehaviorUnequipLeftItem(game);
            //    if (unequipUselessLeftItem != null)
            //    {
            //        m_Actor.Activity = Activity.IDLE;
            //        return unequipUselessLeftItem;
            //    }
            //}
            //// tracker?
            //if (needCellPhone)
            //{
            //    ActorAction eqTrackerAction = BehaviorEquipCellPhone(game);
            //    if (eqTrackerAction != null)
            //    {
            //        m_Actor.Activity = Activity.IDLE;
            //        return eqTrackerAction;
            //    }
            //}
            //// ...or light?
            //else if (needLight)
            //{
            //    ActorAction eqLightAction = BehaviorEquipLight(game);
            //    if (eqLightAction != null)
            //    {
            //        m_Actor.Activity = Activity.IDLE;
            //        return eqLightAction;
            //    }

            //}
            //#endregion

            // 11 get nearby item (not if seeing enemy)
            // ignore not currently visible items & blocked items.
            // alpha10 upgraded rule to use the same new core behavior as CivilianAI with custom params
            #region
            if (!hasCurrentEnemies)
            {
                // alpha10 new common behaviour code, also used by CivilianAI, but Gangs can break and push
                ActorAction getItemAction = BehaviorGoGetInterestingItems(game, mapPercepts,
                                                                          true, true, CANT_GET_ITEM_EMOTE, false, ref m_DummyPerceptLastItemsSaw);

                if (getItemAction != null)
                {
                    return(getItemAction);
                }

                /* prev gang code, much simpler, grabbed any item it could
                 * Map map = m_Actor.Location.Map;
                 * List<Percept> stacks = FilterOut(game, FilterStacks(game, mapPercepts),
                 *  (p) => (p.Turn != map.LocalTime.TurnCounter) || IsOccupiedByOther(map, p.Location.Position));
                 * if (stacks != null)
                 * {
                 *  Percept nearestStack = FilterNearest(game, stacks);
                 *  ActorAction grabAction = BehaviorGrabFromStack(game, nearestStack.Location.Position, nearestStack.Percepted as Inventory);
                 *  if (grabAction != null)
                 *  {
                 *      m_Actor.Activity = Activity.IDLE;
                 *      return grabAction;
                 *  }
                 * }
                 */
            }
            #endregion

            // 12 steal item from someone.
            #region
            if (!hasCurrentEnemies)
            {
                Map            map          = m_Actor.Location.Map;
                List <Percept> mayStealFrom = FilterActors(game, FilterCurrent(game, mapPercepts),
                                                           (a) =>
                {
                    if (a.Inventory == null || a.Inventory.CountItems == 0 || IsFriendOf(game, a))
                    {
                        return(false);
                    }
                    if (game.Rules.RollChance(game.Rules.ActorUnsuspicousChance(m_Actor, a)))
                    {
                        // emote.
                        game.DoEmote(a, String.Format("moves unnoticed by {0}.", m_Actor.Name));
                        // unnoticed.
                        return(false);
                    }
                    return(HasAnyInterestingItem(game, a.Inventory, ItemSource.ANOTHER_ACTOR));
                });

                if (mayStealFrom != null)
                {
                    // alpha10 make sure to consider only reachable victims
                    RouteFinder.SpecialActions allowedActions;
                    allowedActions = RouteFinder.SpecialActions.ADJ_TO_DEST_IS_GOAL | RouteFinder.SpecialActions.JUMP | RouteFinder.SpecialActions.DOORS;
                    // gangs can break & push stuff
                    allowedActions |= RouteFinder.SpecialActions.BREAK | RouteFinder.SpecialActions.PUSH;
                    FilterOutUnreachablePercepts(game, ref mayStealFrom, allowedActions);

                    if (mayStealFrom.Count > 0)
                    {
                        // get data.
                        Percept nearest = FilterNearest(game, mayStealFrom);
                        Actor   victim  = nearest.Percepted as Actor;
                        Item    wantIt  = FirstInterestingItem(game, victim.Inventory, ItemSource.ANOTHER_ACTOR);

                        // make an enemy of him.
                        game.DoMakeAggression(m_Actor, victim);

                        // declare my evil intentions.
                        m_Actor.Activity    = Activity.CHASING;
                        m_Actor.TargetActor = victim;
                        return(new ActionSay(m_Actor, game, victim,
                                             String.Format("Hey! That's some nice {0} you have here!", wantIt.Model.SingleName), RogueGame.Sayflags.IS_IMPORTANT | RogueGame.Sayflags.IS_DANGER));
                    }
                }
            }
            #endregion

            // 13 tear down barricade
            ActorAction attackBarricadeAction = BehaviorAttackBarricade(game);
            if (attackBarricadeAction != null)
            {
                m_Actor.Activity = Activity.IDLE;
                return(attackBarricadeAction);
            }

            // 14 follow leader
            if (checkOurLeader)
            {
                Point       lastKnownLeaderPosition = m_Actor.Leader.Location.Position;
                bool        isLeaderVisible         = FOV.Contains(m_Actor.Leader.Location.Position);
                int         maxDist      = m_Actor.Leader.IsPlayer ? FOLLOW_PLAYERLEADER_MAXDIST : FOLLOW_NPCLEADER_MAXDIST;
                ActorAction followAction = BehaviorFollowActor(game, m_Actor.Leader, lastKnownLeaderPosition, isLeaderVisible, maxDist);
                if (followAction != null)
                {
                    m_Actor.Activity    = Activity.FOLLOWING;
                    m_Actor.TargetActor = m_Actor.Leader;
                    return(followAction);
                }
            }

            // 15 take lead (if leadership)
            bool isLeader = m_Actor.Sheet.SkillTable.GetSkillLevel((int)Skills.IDs.LEADERSHIP) >= 1;
            bool canLead  = !checkOurLeader && isLeader && m_Actor.CountFollowers < game.Rules.ActorMaxFollowers(m_Actor);
            if (canLead)
            {
                Percept nearestFriend = FilterNearest(game, FilterNonEnemies(game, mapPercepts));
                if (nearestFriend != null)
                {
                    ActorAction leadAction = BehaviorLeadActor(game, nearestFriend);
                    if (leadAction != null)
                    {
                        m_Actor.Activity    = Activity.IDLE;
                        m_Actor.TargetActor = nearestFriend.Percepted as Actor;
                        return(leadAction);
                    }
                }
            }

            // 16 (leader) don't leave followers behind.
            #region
            if (m_Actor.CountFollowers > 0)
            {
                Actor       target;
                ActorAction stickTogether = BehaviorDontLeaveFollowersBehind(game, 3, out target);
                if (stickTogether != null)
                {
                    // emote?
                    if (game.Rules.RollChance(DONT_LEAVE_BEHIND_EMOTE_CHANCE))
                    {
                        if (target.IsSleeping)
                        {
                            game.DoEmote(m_Actor, String.Format("patiently waits for {0} to wake up.", target.Name));
                        }
                        else
                        {
                            if (m_LOSSensor.FOV.Contains(target.Location.Position))
                            {
                                game.DoEmote(m_Actor, String.Format("Hey {0}! F*****g move!", target.Name));
                            }
                            else
                            {
                                game.DoEmote(m_Actor, String.Format("Where is that {0} retard?", target.Name));
                            }
                        }
                    }

                    // go!
                    m_Actor.Activity = Activity.IDLE;
                    return(stickTogether);
                }
            }
            #endregion

            // 17 explore
            ActorAction exploreAction = BehaviorExplore(game, m_Exploration);
            if (exploreAction != null)
            {
                m_Actor.Activity = Activity.IDLE;
                return(exploreAction);
            }

            // 18 wander
            m_Actor.Activity = Activity.IDLE;
            return(BehaviorWander(game, m_Exploration));
        }