public override void implement(VoteOption option)
        {
            base.implement(option);

            society.crisisWarLong        = null;
            society.crisisWarShort       = null;
            society.lastEvidenceResponse = society.map.turn;

            if (option.index == AGENT_TO_KNIGHT)
            {
                Unit_Investigator inv = (Unit_Investigator)option.unit;
                inv.changeState(Unit_Investigator.unitState.knight);
                if (inv.person.isWatched())
                {
                    World.self.prefabStore.popMsgAgent(option.unit, option.unit, option.unit.getName() + " has been assigned the role of Knight, by the nobles of " + option.unit.society.getName() +
                                                       " in response to external threats. Knights are combat specialists, who grant bonuses to nearby military units' damage (both attacking and defending).");
                }
            }
            if (option.index == AGENT_TO_BASIC)
            {
                Unit_Investigator inv = (Unit_Investigator)option.unit;
                inv.changeState(Unit_Investigator.unitState.basic);
                if (inv.person.isWatched())
                {
                    World.self.prefabStore.popMsgAgent(option.unit, option.unit, option.unit.getName() + " has been assigned the role of Agent, by the nobles of " + option.unit.society.getName() +
                                                       " in response to external threats. Standard agents are general-purpose units. They can investigate your agents' evidence, and can assist in wars. They can be promoted "
                                                       + " to specalists by vote.");
                }
            }
        }
示例#2
0
        public override void castInner(Map map, Unit u)
        {
            Unit_Investigator inv = (Unit_Investigator)u;

            inv.victim = null;

            foreach (Unit u2 in u.location.units)
            {
                if (u2 != u && u2.person != null)
                {
                    inv.victim = u2;
                }
            }

            if (inv.victim != null)
            {
                inv.victimUses = map.param.ability_unit_falseAccusationCharges;

                u.location.map.world.prefabStore.popImgMsg(u.getName() + " gathers personal items of " + inv.victim.getName() + ", and can now falsely accuse them to nobles (" + inv.victimUses + " uses until they will need more fake evidence).",
                                                           u.location.map.world.wordStore.lookup("ABILITY_UNIT_PRODUCE_FALSE_EVIDENCE"));
            }
            else
            {
                map.world.prefabStore.popMsg("No unit here has a unique character leading them");
            }
        }
        public override double computeUtility(Person p, VoteOption option, List <ReasonMsg> msgs)
        {
            double u = option.getBaseUtility(p);


            if (option.index == NO_RESPONSE)
            {
                msgs.Add(new ReasonMsg("Neutral Option", 0));
            }

            if (option.index == AGENT_TO_KNIGHT)
            {
                double localU = Unit_Investigator.getSwitchUtility(p, (Unit_Investigator)option.unit, Unit_Investigator.unitState.knight);
                localU *= p.map.param.utility_swapAgentRolesMult;
                msgs.Add(new ReasonMsg("Balance of agent skills vs balance of threats", localU));
                u += localU;
            }
            if (option.index == AGENT_TO_BASIC)
            {
                double localU = Unit_Investigator.getSwitchUtility(p, (Unit_Investigator)option.unit, Unit_Investigator.unitState.basic);
                localU *= p.map.param.utility_swapAgentRolesMult;
                msgs.Add(new ReasonMsg("Balance of agent skills vs balance of threats", localU));
                u += localU;
            }

            return(u);
        }
示例#4
0
        public override void implement(VoteOption option)
        {
            base.implement(option);

            society.lastNobleCrisis = society.map.turn;
            society.crisisNobles    = false;
            foreach (Evidence ev in foundEvidence)
            {
                society.handledEvidence.Add(ev);
            }

            if (option.index == WITCH_HUNT)
            {
                society.crisisWitchHunt = true;
            }
            if (option.index == AGENT_TO_INQUISITOR)
            {
                Unit_Investigator inv = (Unit_Investigator)option.unit;
                inv.changeState(Unit_Investigator.unitState.inquisitor);
                World.self.prefabStore.popMsgAgent(option.unit, option.unit, option.unit.getName() + " has been assigned the role of Inquisitor, by the nobles of " + option.unit.society.getName() +
                                                   " in response to external threats. Inquisitors are experts at combatting your finding enthralled, enshadowed, broken or corrupt nobles.");
            }
            if (option.index == AGENT_TO_BASIC)
            {
                Unit_Investigator inv = (Unit_Investigator)option.unit;
                inv.changeState(Unit_Investigator.unitState.basic);
                if (inv.person.isWatched())
                {
                    World.self.prefabStore.popMsgAgent(option.unit, option.unit, option.unit.getName() + " has been assigned the role of Agent, by the nobles of " + option.unit.society.getName() +
                                                       " in response to external threats. Standard agents are general-purpose units. They can investigate your agents' evidence, and can assist in wars. They can be promoted "
                                                       + " to specalists by vote.");
                }
            }
        }
        public override void castInner(Map map, Unit other)
        {
            map.overmind.availableEnthrallments -= 1;

            string addMsg = "\n\nYou have " + map.overmind.availableEnthrallments + " enthrallment uses remaining.You will regain one every " +
                            map.param.overmind_enthrallmentUseRegainPeriod + " turns if you are below maximum.";

            map.world.prefabStore.popImgMsg(
                "You take " + other.getName() + " under your control. You may vote through them, convince others using their goodwill towards them, and use abilities relating to noble enthralled. " + addMsg,
                map.world.wordStore.lookup("ABILITY_ENTHRALL_AGENT"));

            other.person.state = Person.personState.enthralledAgent;
            Evidence ev = new Evidence(map.turn);

            ev.pointsTo = other;
            ev.weight   = 0.66;
            other.location.evidence.Add(ev);

            other.automated = false;

            other.task        = null;
            other.movesTaken += 1;
            map.overmind.computeEnthralled();
            map.hasEnthralledAnAgent = true;

            if (other is Unit_Investigator)
            {
                Unit_Investigator inv = (Unit_Investigator)other;
                inv.state = Unit_Investigator.unitState.basic;
            }

            AchievementManager.unlockAchievement(SteamManager.achievement_key.FIRST_AGENT);
        }
        public void turnTick()
        {
            if (map.turn % 10 == 0)
            {
                HashSet <Province> investigatedProvinces = new HashSet <Province>();
                int nInvestigators = 0;
                foreach (Unit u in map.units)
                {
                    if (u is Unit_Investigator && u.isEnthralled() == false)
                    {
                        if (u.parentLocation != null)
                        {
                            investigatedProvinces.Add(u.parentLocation.province);
                        }
                        nInvestigators += 1;
                    }
                }
                HashSet <Province> inhabitedProvinces = new HashSet <Province>();
                foreach (Location l in map.locations)
                {
                    if (l.soc is Society && l.settlement != null && l.settlement.isHuman)
                    {
                        inhabitedProvinces.Add(l.province);
                    }
                }
                if (investigatedProvinces.Count < inhabitedProvinces.Count)
                {
                    foreach (Province p in inhabitedProvinces)
                    {
                        if (investigatedProvinces.Contains(p))
                        {
                            continue;
                        }

                        int      c      = 0;
                        Location chosen = null;
                        foreach (Location loc in p.locations)
                        {
                            if (loc.soc is Society && loc.settlement != null && loc.settlement.isHuman)
                            {
                                c += 1;
                                if (Eleven.random.Next(c) == 0)
                                {
                                    chosen = loc;
                                }
                            }
                        }
                        if (chosen != null)
                        {
                            Unit_Investigator u = new Unit_Investigator(chosen, (Society)chosen.soc);
                            u.person      = new Person((Society)chosen.soc);
                            u.person.unit = u;
                            u.person.traits.Clear();//Can't see traits, best to have them removed
                            map.units.Add(u);
                            u.parentLocation = chosen;
                        }
                    }
                }
            }
        }
示例#7
0
        public override bool castable(Map map, Unit u)
        {
            if (u.location.person() == null)
            {
                return(false);
            }
            if (u is Unit_Investigator == false)
            {
                return(false);
            }
            Unit_Investigator u2 = (Unit_Investigator)u;

            if (u2.victimUses <= 0)
            {
                return(false);
            }
            return(u2.victim != null && u2.victim.person != null);
        }
        public bool shouldBePaladin(Map map)
        {
            if (location.soc != this.society)
            {
                return(false);
            }
            if (map.simplified)
            {
                return(false);
            }
            //if (map.automatic) { return false; }

            int nPaladins = 0;

            foreach (Unit u in map.units)
            {
                if (u is Unit_Investigator)
                {
                    Unit_Investigator inv = (Unit_Investigator)u;
                    if (inv.state == unitState.paladin)
                    {
                        nPaladins += 1;
                    }
                }
            }
            if (nPaladins >= map.unitManager.getTargetPaladins())
            {
                return(false);
            }

            foreach (Unit u in huntableSuspects)
            {
                if (map.units.Contains(u))
                {
                    return(true);
                }
            }
            return(false);
        }
示例#9
0
        public override void castInner(Map map, Unit u)
        {
            Unit_Investigator inv = (Unit_Investigator)u;

            double effect       = 0;
            Person p            = u.location.person();
            double liking       = p.getRelation(u.person).getLiking();      //0 to 100
            double infiltration = u.location.settlement.infiltration * 100; //Also 0 to 100

            effect = (liking + infiltration + 100) * map.param.ability_unit_falseAccusationEffect;
            if (effect < 0)
            {
                effect = 0;
            }
            effect /= 100;
            if (effect > 1)
            {
                effect = 1;
            }

            p.getRelation(inv.victim.person).suspicion += effect;
            if (p.getRelation(inv.victim.person).suspicion > 1)
            {
                p.getRelation(inv.victim.person).suspicion = 1;
            }


            string add = "";

            inv.victimUses -= 1;
            if (inv.victimUses <= 0)
            {
                add += "\nThey have used all the false evidence they produced, and now must collect more from their victim to continue.";
            }

            u.location.map.world.prefabStore.popImgMsg(u.getName() + " accuses " + inv.victim.getName() + " of being in league with shadow, presenting false evidence to " + p.getFullName()
                                                       + "\nTheir suspicion rises by " + (int)(100 * effect) + "% (after applying infiltration and liking bonuses), and is now " + (int)(100 * p.getRelation(inv.victim.person).suspicion) + "%." + add,
                                                       u.location.map.world.wordStore.lookup("ABILITY_UNIT_FALSE_ACCUSE"));
        }
示例#10
0
        public override void implement(VoteOption option)
        {
            base.implement(option);

            society.crisisPlague         = null;
            society.crisisPlagueLong     = null;
            society.lastEvidenceResponse = society.map.turn;

            if (option.index == AGENT_TO_MEDIC)
            {
                Unit_Investigator inv = (Unit_Investigator)option.unit;
                inv.changeState(Unit_Investigator.unitState.medic);
                if (inv.person.isWatched())
                {
                    World.self.prefabStore.popMsgAgent(option.unit, option.unit, option.unit.getName() + " has been assigned the role of Apothecarian, by the nobles of " + option.unit.society.getName() +
                                                       " in response to external threats. Apothecarians excell in treating plagues, but cannot do anything else.");
                }
            }
            if (option.index == AGENT_TO_BASIC)
            {
                Unit_Investigator inv = (Unit_Investigator)option.unit;
                inv.changeState(Unit_Investigator.unitState.basic);
                if (inv.person.isWatched())
                {
                    World.self.prefabStore.popMsgAgent(option.unit, option.unit, option.unit.getName() + " has been assigned the role of Agent, by the nobles of " + option.unit.society.getName() +
                                                       " in response to external threats. Standard agents are general-purpose units. They can investigate your agents' evidence, and can assist in wars. They can be promoted "
                                                       + " to specalists by vote.");
                }
            }
            if (option.index == QUARANTINE)
            {
                foreach (Location loc in society.map.locations)
                {
                    if (loc.soc == society)
                    {
                        bool hasDisease = false;
                        foreach (Property pr in loc.properties)
                        {
                            if (pr.proto.isDisease)
                            {
                                hasDisease = true; break;
                            }
                        }
                        if (hasDisease)
                        {
                            Property.addProperty(loc.map, loc, "Quarantine");
                        }
                    }
                }
            }
            if (option.index == TREATMENT)
            {
                foreach (Location loc in society.map.locations)
                {
                    if (loc.soc == society)
                    {
                        bool hasDisease = false;
                        foreach (Property pr in loc.properties)
                        {
                            if (pr.proto.isDisease)
                            {
                                hasDisease = true; break;
                            }
                        }
                        if (hasDisease)
                        {
                            Property.addProperty(loc.map, loc, "Medical Aid");
                        }
                    }
                }
            }
        }
示例#11
0
        public override void turnTick(Unit unit)
        {
            if (unit.location.evidence.Count > 0)
            {
                unit.task = new Task_Investigate();
                return;
            }
            if (unit is Unit_Investigator)
            {
                Unit_Investigator inv      = (Unit_Investigator)unit;
                bool unsharedEvidence      = false;
                bool unsharedEvidenceToAny = false;
                foreach (Evidence ev in inv.evidenceCarried)
                {
                    if (ev.turnSubmitted == 0)
                    {
                        unsharedEvidenceToAny = true;
                    }
                    if (unit.location.soc is Society localSoc)
                    {
                        if (localSoc.isDarkEmpire)
                        {
                            break;
                        }
                        if (localSoc.evidenceSubmitted.Contains(ev) == false)
                        {
                            unsharedEvidence = true;
                        }
                    }
                }
                if (unsharedEvidence)
                {
                    inv.task = new Task_ShareSuspicions();
                    return;
                }
                else if (unsharedEvidenceToAny)
                {
                    //We're clearly not at home, or the previous condition would have triggered
                    inv.task = new Task_GoToSocialGroup(inv.society);
                    return;
                }
            }
            List <Location> neighbours = unit.location.getNeighbours();

            int      c      = 0;
            Location chosen = null;

            foreach (Location loc in neighbours)
            {
                if (loc.soc != null && loc.soc.hostileTo(unit))
                {
                    continue;
                }
                if (loc.soc is Society soc && soc.isDarkEmpire)
                {
                    continue;
                }
                if (loc.evidence.Count > 0)
                {
                    chosen = loc;
                    break;
                }
                if (visitBuffer.Contains(loc) == false)
                {
                    c += 1;
                    if (Eleven.random.Next(c) == 0)
                    {
                        chosen = loc;
                    }
                }
            }
            if (chosen != null)
            {
                visitBuffer.AddLast(chosen);
            }
            else
            {
                int q = Eleven.random.Next(neighbours.Count);
                chosen = neighbours[q];
            }
            unit.location.map.adjacentMoveTo(unit, chosen);
            if (visitBuffer.Count > bufferSize)
            {
                visitBuffer.RemoveFirst();
            }

            //Start investigating the evidence you just moved to
            if (unit.location.evidence.Count > 0)
            {
                unit.task = new Task_Investigate();
                return;
            }

            //See if you want to warn this new person about anything
            if (unit.location.person() != null && (unit.location.person().society.isDarkEmpire == false))
            {
                Person noble = unit.location.person();
                foreach (RelObj rel in unit.person.relations.Values)
                {
                    ////Goes negative if they suspect more than we do, reaches 1.0 if we suspect 1.0 and they suspect 0.0
                    // if ((rel.suspicion - noble.getRelation(rel.them).suspicion) > Eleven.random.NextDouble())
                    if ((rel.suspicion > noble.getRelation(rel.them).suspicion *1.1))
                    {
                        unit.task = new Task_ShareSuspicions();
                        return;
                    }
                }

                if (noble.state == Person.personState.enthralled || noble.state == Person.personState.broken)
                {
                    bool alreadyInv = false;
                    foreach (Unit u2 in unit.location.units)
                    {
                        if (u2 is Unit_Investigator && u2.task is Task_InvestigateNoble)
                        {
                            alreadyInv = true;
                            break;
                        }
                    }
                    if ((!alreadyInv) && unit.location.map.turn - noble.investigationLastTurn > unit.location.map.param.unit_investigateNobleCooldown)
                    {
                        //unit.location.map.world.prefabStore.popMsg(unit.getName() + " is beginning an investigation regarding " + noble.getFullName() + ", as they suspected they were under the influence of dark powers." +
                        //    " If their investigation ends, " +  noble.getFullName() + " will gain " + ((int)(unit.location.map.param.unit_investigateNobleEvidenceGain * 100))
                        //    + "% evidence. This task can be disrupted to prevent the evidence being generated, or the evidence can be given away to other friendly nobles.");

                        unit.location.map.world.prefabStore.popMsgAgent(unit, unit, unit.getName() + " has detected something is wrong with the nobles in " + noble.society.getName() + ", and is "
                                                                        + "investigating to see if the shadow has influence. If this task completes they will warn nobles that there may exist enthralled or broken nobles in their midst," +
                                                                        " although who the enshadowed noble is will not yet be known.");


                        noble.investigationLastTurn = unit.location.map.turn;

                        unit.task = new Task_InvestigateNobleBasic();
                        return;
                    }
                }
            }

            wanderTimer += 1;
            if (wanderTimer > wanderDur)
            {
                if (unit.parentLocation != null)
                {
                    unit.task = new Task_GoToLocation(unit.parentLocation);
                }
                else
                {
                    //Done wandering, go home to ensure you don't wander too far for too long
                    unit.task = new Task_GoToSocialGroup(unit.society);
                }
            }
        }
        public override double computeUtility(Person p, VoteOption option, List <ReasonMsg> msgs)
        {
            double u = option.getBaseUtility(p);

            double concernLevel = p.threat_agents.threat;                   //curr 0 to 200

            concernLevel += (100 * p.awareness) + (100 * p.map.worldPanic); //0 to 400
            concernLevel /= 4;
            concernLevel  = Math.Min(concernLevel, (p.map.worldPanic * 100) + 20);

            concernLevel *= (1 - p.shadow);
            if (p.state == Person.personState.enthralled || p.state == Person.personState.broken)
            {
                concernLevel = 0;
            }

            //Define the range at which this manner of response is appropriate
            double responseLevelMin = 0;
            double responseLevelMax = 0;

            if (option.index == DEFEND_PROVINCE)
            {
                responseLevelMin = 10;
                responseLevelMax = 40;

                int evidenceFound = 0;
                foreach (Evidence ev in foundEvidence)
                {
                    if (ev.locationFound.province.index == option.province)
                    {
                        evidenceFound += 1;
                    }
                }

                double localU = World.staticMap.param.utility_defendEvidenceProvince * evidenceFound * (1 - p.shadow);
                msgs.Add(new ReasonMsg("Amount of evidence found in " + society.map.provinces[option.province].name + " province", localU));
                u += localU;

                localU = 0;
                foreach (Person person in society.people)
                {
                    if (person.getLocation() != null && person.getLocation().province.index == option.province)
                    {
                        localU += p.getRelation(person.index).getLiking() * World.staticMap.param.utility_agentDefendProvinceLikingMult;
                    }
                }
                string add = "";
                msgs.Add(new ReasonMsg("Liking for nobles in province" + add, localU));
                u += localU;

                if (p.getLocation().province.index != option.province)
                {
                    localU = p.getSelfInterest() * p.threat_agents.threat * World.staticMap.param.utility_selfInterestFromThreat;
                    if (localU != 0)
                    {
                        msgs.Add(new ReasonMsg("Does not help me personally", localU));
                        u += localU;
                    }
                }
                else
                {
                    localU = -1 * p.getSelfInterest() * p.threat_agents.threat * World.staticMap.param.utility_selfInterestFromThreat;
                    if (localU != 0)
                    {
                        msgs.Add(new ReasonMsg("Helps me personally", localU));
                        u += localU;
                    }
                }
            }
            if (option.index == NATIONWIDE_SECURITY)
            {
                responseLevelMin = 10;
                responseLevelMax = 40;

                double localU = World.staticMap.param.utility_evidenceResonseBaseline * (concernLevel / 100);
                msgs.Add(new ReasonMsg("Base Desirability", localU));
                u += localU;

                localU = p.getSelfInterest() * p.threat_agents.threat * World.staticMap.param.utility_selfInterestFromThreat / 2;
                if (localU != 0)
                {
                    msgs.Add(new ReasonMsg("Doesn't maximise my provinces' defences", localU));
                    u += localU;
                }
            }
            if (option.index == NO_RESPONSE)
            {
                responseLevelMin = 0;
                responseLevelMax = 10;

                if (p.getGreatestThreat() != null && p.getGreatestThreat() != p.threat_agents)
                {
                    double localU = World.staticMap.param.utility_greatestThreatDelta * 0.5;
                    msgs.Add(new ReasonMsg("Not our greatest threat", localU));
                    u += localU;
                }
                else
                {
                    double localU = -World.staticMap.param.utility_greatestThreatDelta;
                    msgs.Add(new ReasonMsg("Dark Agents are our greatest threat", localU));
                    u += localU;
                }
            }

            if (option.index == EXPELL_ALL_FOREIGN_AGENTS)
            {
                responseLevelMin = 75;
                responseLevelMax = 100;

                double n = 0;
                foreach (Unit unit in society.map.units)
                {
                    if (unit.society == society)
                    {
                        continue;
                    }
                    if (society.enemies.Contains(unit) == false)
                    {
                        n += 1;
                    }
                }
                if (n > 0)
                {
                    msgs.Add(new ReasonMsg("So many potential enemies!", concernLevel));
                    u += concernLevel;
                }
            }
            if (option.index == LOCKDOWN_PROVINCE)
            {
                responseLevelMin = 40;
                responseLevelMax = 100;

                int evidenceFound = 0;
                foreach (Evidence ev in foundEvidence)
                {
                    if (ev.locationFound.province.index == option.province)
                    {
                        evidenceFound += 1;
                    }
                }

                double localU = World.staticMap.param.utility_defendEvidenceProvince * evidenceFound * (1 - p.shadow);
                msgs.Add(new ReasonMsg("Amount of evidence found in " + society.map.provinces[option.province].name + " province", localU));
                u += localU;

                localU = 0;
                foreach (Person person in society.people)
                {
                    if (person.getLocation() != null && person.getLocation().province.index == option.province)
                    {
                        localU += p.getRelation(person.index).getLiking() * World.staticMap.param.utility_agentDefendProvinceLikingMult;
                    }
                }
                string add = "" + (int)(localU);
                msgs.Add(new ReasonMsg("Liking for nobles in province" + add, localU));
                u += localU;

                if (p.getLocation().province.index != option.province)
                {
                    localU = p.getSelfInterest() * p.threat_agents.threat * World.staticMap.param.utility_selfInterestFromThreat;
                    if (localU != 0)
                    {
                        msgs.Add(new ReasonMsg("Does not help me personally", localU));
                        u += localU;
                    }
                }
                else
                {
                    localU = -1 * p.getSelfInterest() * p.threat_agents.threat * World.staticMap.param.utility_selfInterestFromThreat;
                    if (localU != 0)
                    {
                        msgs.Add(new ReasonMsg("Helps me personally", localU));
                        u += localU;
                    }
                }
            }
            if (option.index == AGENT_TO_INVESTIGATOR)
            {
                responseLevelMin = 0;
                responseLevelMax = 100;
                Unit_Investigator inv = (Unit_Investigator)option.unit;

                double localU = Unit_Investigator.getSwitchUtility(p, (Unit_Investigator)option.unit, Unit_Investigator.unitState.investigator);
                localU *= p.map.param.utility_swapAgentRolesMult;
                msgs.Add(new ReasonMsg("Balance of agent skills vs balance of threats", localU));
                u += localU;
                bool hasSuspicions = false;
                foreach (RelObj rel in inv.person.relations.Values)
                {
                    if (inv.location.map.persons[rel.them] == null)
                    {
                        continue;
                    }
                    if (rel.suspicion > 0 && inv.location.map.persons[rel.them].unit != null && inv.location.map.units.Contains(inv.location.map.persons[rel.them].unit))
                    {
                        hasSuspicions = true;
                    }
                }
                if (hasSuspicions)
                {
                    localU = 12;
                    msgs.Add(new ReasonMsg("Has a suspect", localU));
                    u += localU;
                }
            }
            if (option.index == AGENT_TO_BASIC)
            {
                responseLevelMin = 0;
                responseLevelMax = 100;

                double localU = Unit_Investigator.getSwitchUtility(p, (Unit_Investigator)option.unit, Unit_Investigator.unitState.basic);
                localU *= p.map.param.utility_swapAgentRolesMult;
                msgs.Add(new ReasonMsg("Balance of agent skills vs balance of threats", localU));
                u += localU;
            }

            if (concernLevel > responseLevelMax)
            {
                double delta = responseLevelMax - concernLevel;
                delta *= society.map.param.utility_extremeismScaling;
                double localU = delta;
                msgs.Add(new ReasonMsg("Too weak response for current concern level (" + (int)(concernLevel) + "%)", localU));
                u += localU;
            }
            if (concernLevel < responseLevelMin)
            {
                double delta = concernLevel - responseLevelMin;
                delta *= society.map.param.utility_extremeismScaling;
                double localU = delta;
                msgs.Add(new ReasonMsg("Too extreme for current concern level (" + (int)(concernLevel) + "%)", localU));
                u += localU;
            }
            return(u);
        }
        private VoteIssue checkForCrises()
        {
            if (map.simplified)
            {
                return(null);
            }

            if (society.crisisWitchHunt)
            {
                VoteIssue_WitchHunt issue = new VoteIssue_WitchHunt(society, this);

                VoteOption opt;

                foreach (Person p in society.people)
                {
                    opt        = new VoteOption();
                    opt.person = p;
                    issue.options.Add(opt);
                }

                return(issue);
            }

            VoteIssue replyIssue = null;
            int       c          = 0;

            if (society.lastEvidenceSubmission > society.lastEvidenceResponse && (society.isDarkEmpire == false))
            {
                List <Evidence> unprocessedEvidence = new List <Evidence>();
                foreach (Evidence ev in society.evidenceSubmitted)
                {
                    if (society.handledEvidence.Contains(ev))
                    {
                        continue;
                    }
                    unprocessedEvidence.Add(ev);
                }


                VoteIssue_Crisis_EvidenceDiscovered issue = new VoteIssue_Crisis_EvidenceDiscovered(society, this, unprocessedEvidence);

                //Every province (even those unaffected) can have its security increased (egotism influenced)
                HashSet <Province> provinces        = new HashSet <Province>();
                HashSet <Province> securedProvinces = new HashSet <Province>();
                bool hasRaisedSecurity = false;
                foreach (Location loc in map.locations)
                {
                    if (loc.soc == this.society)
                    {
                        provinces.Add(loc.province);

                        foreach (Property pr in loc.properties)
                        {
                            if (pr.proto is Pr_MajorSecurityBoost || pr.proto is Pr_MinorSecurityBoost || pr.proto is Pr_Lockdown)
                            {
                                hasRaisedSecurity = true;
                                securedProvinces.Add(loc.province);
                            }
                        }
                    }
                }
                VoteOption opt;

                opt       = new VoteOption();
                opt.index = VoteIssue_Crisis_EvidenceDiscovered.NO_RESPONSE;
                issue.options.Add(opt);

                bool existEnemies = false;
                foreach (Unit u in map.units)
                {
                    if (society.enemies.Contains(u) == false && u.society != society)
                    {
                        existEnemies = true;
                    }
                }
                if (existEnemies)
                {
                    opt       = new VoteOption();
                    opt.index = VoteIssue_Crisis_EvidenceDiscovered.EXPELL_ALL_FOREIGN_AGENTS;
                    issue.options.Add(opt);
                }

                if (!hasRaisedSecurity)
                {
                    opt       = new VoteOption();
                    opt.index = VoteIssue_Crisis_EvidenceDiscovered.NATIONWIDE_SECURITY;
                    issue.options.Add(opt);
                }

                foreach (Province prv in provinces)
                {
                    if (securedProvinces.Contains(prv) == false)
                    {
                        opt          = new VoteOption();
                        opt.province = prv.index;
                        opt.index    = VoteIssue_Crisis_EvidenceDiscovered.DEFEND_PROVINCE;
                        issue.options.Add(opt);

                        opt          = new VoteOption();
                        opt.province = prv.index;
                        opt.index    = VoteIssue_Crisis_EvidenceDiscovered.LOCKDOWN_PROVINCE;
                        issue.options.Add(opt);
                    }
                }
                foreach (Unit unit in map.units)
                {
                    if (unit is Unit_Investigator && unit.society == society)
                    {
                        Unit_Investigator inv = (Unit_Investigator)unit;
                        if (inv.canPromote() == false)
                        {
                            continue;
                        }
                        if (inv.state == Unit_Investigator.unitState.investigator || inv.state == Unit_Investigator.unitState.paladin)
                        {
                            //Already in offensive anti-agent state, no need to intefere
                        }
                        else if (inv.state == Unit_Investigator.unitState.basic) //Could upgrade to investigator if they've got a target
                        {
                            opt           = new VoteOption();
                            opt.unit      = unit;
                            opt.agentRole = Unit_Investigator.unitState.investigator;
                            opt.index     = VoteIssue_Crisis_EvidenceDiscovered.AGENT_TO_INVESTIGATOR;
                            issue.options.Add(opt);
                        }
                        else
                        {
                            opt           = new VoteOption();
                            opt.unit      = unit;
                            opt.agentRole = Unit_Investigator.unitState.basic;
                            opt.index     = VoteIssue_Crisis_EvidenceDiscovered.AGENT_TO_BASIC;
                            issue.options.Add(opt);
                        }
                    }
                }



                //bool hostilityPossible = false;
                //foreach (Evidence ev in unprocessedEvidence)
                //{
                //    World.log("Evidence. Discovered by " + ev.discoveredBy.getName() + " points to " + ev.pointsTo.getName() + " discSoc " + ev.discoveredBy.society.getName() + " us " + society.getName());
                //    if (ev.discoveredBy != null && ev.pointsTo != null && ev.discoveredBy.society == society)
                //    {
                //        if (ev.discoveredBy.hostileTo(ev.pointsTo)) { continue; }
                //        hostilityPossible = true;
                //    }
                //}

                //Decide if this is the crisis you're gonna deal with right now
                c += 1;
                if (Eleven.random.Next(c) == 0)
                {
                    replyIssue = issue;
                }
            }


            bool nobleCrisis = society.crisisNobles;

            if (
                this.awareness >= map.param.awarenessCanCallNobleCrisis &&
                map.turn - society.lastNobleCrisis >= map.param.awarenessMinNobleCrisisPeriod &&
                map.worldPanic >= map.param.panic_canCallNobleCrisis &&
                (this.society.isDarkEmpire == false) &&
                this.state != personState.broken &&
                this.state != personState.enthralled)
            {
                foreach (Person p in society.people)
                {
                    if (p == this)
                    {
                        continue;
                    }
                    if (this.getRelation(p.index).suspicion > 0.5)
                    {
                        nobleCrisis = true;
                    }
                }
            }
            if (nobleCrisis)
            {
                World.log("Noble crisis initiated");
                List <Evidence> unprocessedEvidence = new List <Evidence>();
                foreach (Evidence ev in society.evidenceSubmitted)
                {
                    if (society.handledEvidence.Contains(ev))
                    {
                        continue;
                    }
                    unprocessedEvidence.Add(ev);
                }


                VoteIssue_Crisis_EnshadowedNobles issue = new VoteIssue_Crisis_EnshadowedNobles(society, this, unprocessedEvidence);

                VoteOption opt;

                opt       = new VoteOption();
                opt.index = VoteIssue_Crisis_EnshadowedNobles.NO_RESPONSE;
                issue.options.Add(opt);

                opt       = new VoteOption();
                opt.index = VoteIssue_Crisis_EnshadowedNobles.WITCH_HUNT;
                issue.options.Add(opt);

                foreach (Unit unit in map.units)
                {
                    if (unit is Unit_Investigator && unit.society == society)
                    {
                        Unit_Investigator inv = (Unit_Investigator)unit;
                        if (inv.canPromote() == false)
                        {
                            continue;
                        }
                        if (inv.state == Unit_Investigator.unitState.investigator || inv.state == Unit_Investigator.unitState.paladin)
                        {
                            //Already in offensive anti-agent state, no need to intefere
                        }
                        else if (inv.state == Unit_Investigator.unitState.basic)//Could upgrade to investigator if they've got a target
                        {
                            opt           = new VoteOption();
                            opt.unit      = unit;
                            opt.agentRole = Unit_Investigator.unitState.investigator;
                            opt.index     = VoteIssue_Crisis_EnshadowedNobles.AGENT_TO_INQUISITOR;
                            issue.options.Add(opt);
                        }
                        else
                        {
                            opt           = new VoteOption();
                            opt.unit      = unit;
                            opt.agentRole = Unit_Investigator.unitState.basic;
                            opt.index     = VoteIssue_Crisis_EnshadowedNobles.AGENT_TO_BASIC;
                            issue.options.Add(opt);
                        }
                    }
                }

                c += 1;
                if (Eleven.random.Next(c) == 0)
                {
                    replyIssue = issue;
                }
            }
            if (society.crisisWarShort != null)
            {
                VoteIssue_Crisis_WarThreatens issue = new VoteIssue_Crisis_WarThreatens(society, this, society.crisisWarShort, society.crisisWarLong);
                VoteOption opt;

                opt       = new VoteOption();
                opt.index = VoteIssue_Crisis_WarThreatens.NO_RESPONSE;
                issue.options.Add(opt);

                foreach (Unit unit in map.units)
                {
                    if (unit is Unit_Investigator && unit.society == society)
                    {
                        Unit_Investigator inv = (Unit_Investigator)unit;
                        if (inv.canPromote() == false)
                        {
                            continue;
                        }
                        if (inv.state == Unit_Investigator.unitState.knight || inv.state == Unit_Investigator.unitState.paladin)
                        {
                            //Already doing something useful, ignore these
                        }
                        else if (inv.state == Unit_Investigator.unitState.basic)//Could upgrade to knight
                        {
                            opt           = new VoteOption();
                            opt.unit      = unit;
                            opt.agentRole = Unit_Investigator.unitState.knight;
                            opt.index     = VoteIssue_Crisis_WarThreatens.AGENT_TO_KNIGHT;
                            issue.options.Add(opt);
                        }
                        else
                        {
                            opt           = new VoteOption();
                            opt.unit      = unit;
                            opt.agentRole = Unit_Investigator.unitState.basic;
                            opt.index     = VoteIssue_Crisis_WarThreatens.AGENT_TO_BASIC;
                            issue.options.Add(opt);
                        }
                    }
                }


                //Decide if this is the crisis you're gonna deal with right now
                if (issue.options.Count > 1)
                {
                    c += 1;
                    if (Eleven.random.Next(c) == 0)
                    {
                        replyIssue = issue;
                    }
                }
            }

            if (society.crisisPlague != null)
            {
                VoteIssue_Crisis_Plague issue = new VoteIssue_Crisis_Plague(society, this, society.crisisPlague, society.crisisPlagueLong);
                VoteOption opt;

                opt       = new VoteOption();
                opt.index = VoteIssue_Crisis_Plague.NO_RESPONSE;
                issue.options.Add(opt);

                opt       = new VoteOption();
                opt.index = VoteIssue_Crisis_Plague.QUARANTINE;
                issue.options.Add(opt);

                opt       = new VoteOption();
                opt.index = VoteIssue_Crisis_Plague.TREATMENT;
                issue.options.Add(opt);

                foreach (Unit unit in map.units)
                {
                    if (unit is Unit_Investigator && unit.society == society)
                    {
                        Unit_Investigator inv = (Unit_Investigator)unit;
                        if (inv.canPromote() == false)
                        {
                            continue;
                        }
                        if (inv.state == Unit_Investigator.unitState.medic || inv.state == Unit_Investigator.unitState.paladin)
                        {
                            //Already doing something useful, ignore these
                        }
                        else if (inv.state == Unit_Investigator.unitState.basic)//Could upgrade to medic
                        {
                            opt           = new VoteOption();
                            opt.unit      = unit;
                            opt.agentRole = Unit_Investigator.unitState.medic;
                            opt.index     = VoteIssue_Crisis_Plague.AGENT_TO_MEDIC;
                            issue.options.Add(opt);
                        }
                        else
                        {
                            opt           = new VoteOption();
                            opt.unit      = unit;
                            opt.agentRole = Unit_Investigator.unitState.basic;
                            opt.index     = VoteIssue_Crisis_Plague.AGENT_TO_BASIC;
                            issue.options.Add(opt);
                        }
                    }
                }


                //Decide if this is the crisis you're gonna deal with right now
                if (issue.options.Count > 1)
                {
                    c += 1;
                    if (Eleven.random.Next(c) == 0)
                    {
                        replyIssue = issue;
                    }
                }
            }
            return(replyIssue);
        }
示例#14
0
        public override double computeUtility(Person p, VoteOption option, List <ReasonMsg> msgs)
        {
            double u = option.getBaseUtility(p);

            double concernLevel = p.threat_enshadowedNobles.threat;         //curr 0 to 200

            concernLevel += (100 * p.awareness) + (100 * p.map.worldPanic); //0 to 400
            concernLevel /= 4;
            concernLevel  = Math.Min(concernLevel, (p.map.worldPanic * 100) + 20);

            concernLevel *= (1 - p.shadow);
            if (p.state == Person.personState.enthralled || p.state == Person.personState.broken)
            {
                concernLevel = 0;
            }

            //Define the range at which this manner of response is appropriate
            double responseLevelMin = 0;
            double responseLevelMax = 0;

            if (option.index == NO_RESPONSE)
            {
                responseLevelMin = 0;
                responseLevelMax = 10;

                if (p.getGreatestThreat() != null && p.getGreatestThreat() != p.threat_enshadowedNobles)
                {
                    double localU = World.staticMap.param.utility_greatestThreatDelta * 0.5;
                    msgs.Add(new ReasonMsg("Not our greatest threat", localU));
                    u += localU;
                }
                else
                {
                    double localU = -World.staticMap.param.utility_greatestThreatDelta;
                    msgs.Add(new ReasonMsg("Enshadowed nobles are our greatest threat", localU));
                    u += localU;
                }
            }

            if (option.index == WITCH_HUNT)
            {
                responseLevelMin = 80;
                responseLevelMax = 100;

                double localU = -World.staticMap.param.utility_killSuspectRelucatance;
                msgs.Add(new ReasonMsg("Base Reluctance to Execute Noble", localU));
                u += localU;


                bool isWarlike   = false;
                bool isHonorable = false;
                bool isPacifist  = false;
                foreach (Trait t in p.traits)
                {
                    if (t is Trait_Political_Warlike)
                    {
                        isWarlike = true; break;
                    }
                    if (t is Trait_Political_Honorable)
                    {
                        isHonorable = true; break;
                    }
                    if (t is Trait_Political_Pacifist)
                    {
                        isPacifist = true; break;
                    }
                }
                if (isHonorable)
                {
                    localU = p.map.param.utility_honorableHatesWitchHunt;
                    msgs.Add(new ReasonMsg("Honorable Politician opposes executions without trials", localU));
                    u += localU;
                }
                if (isWarlike)
                {
                    localU = p.map.param.utility_warlikeLikesWitchHunt;
                    msgs.Add(new ReasonMsg("Warlike Politician supports violence", localU));
                    u += localU;
                }
                if (isPacifist)
                {
                    localU = -p.map.param.utility_warlikeLikesWitchHunt;
                    msgs.Add(new ReasonMsg("Pacifist Politician supports violence", localU));
                    u += localU;
                }

                double maxSuspicion = 0;
                foreach (Person p2 in p.society.people)
                {
                    maxSuspicion = Math.Max(maxSuspicion, p.getRelation(p2.index).suspicion);
                }
                localU = maxSuspicion;
                if (localU != 0)
                {
                    msgs.Add(new ReasonMsg("Suspicion towards other nobles", localU));
                    u += localU;
                }
            }

            if (option.index == AGENT_TO_INQUISITOR)
            {
                responseLevelMin = 0;
                responseLevelMax = 100;
                Unit_Investigator inv = (Unit_Investigator)option.unit;

                double localU = Unit_Investigator.getSwitchUtility(p, (Unit_Investigator)option.unit, Unit_Investigator.unitState.inquisitor);
                localU *= p.map.param.utility_swapAgentRolesMult;
                msgs.Add(new ReasonMsg("Balance of agent skills vs balance of threats", localU));
                u += localU;

                bool isCorrupt = false;
                foreach (Trait t in p.traits)
                {
                    if (t is Trait_Political_Corrupt)
                    {
                        isCorrupt = true; break;
                    }
                }
                if (isCorrupt)
                {
                    localU = p.map.param.utility_corruptHatesInquisitor;
                    msgs.Add(new ReasonMsg("Inquisitor may expose my political corruption", localU));
                    u += localU;
                }
            }
            if (option.index == AGENT_TO_BASIC)
            {
                responseLevelMin = 0;
                responseLevelMax = 100;

                double localU = Unit_Investigator.getSwitchUtility(p, (Unit_Investigator)option.unit, Unit_Investigator.unitState.basic);
                localU *= p.map.param.utility_swapAgentRolesMult;
                msgs.Add(new ReasonMsg("Balance of agent skills vs balance of threats", localU));
                u += localU;
            }

            if (concernLevel > responseLevelMax)
            {
                double delta = responseLevelMax - concernLevel;
                delta *= society.map.param.utility_extremeismScaling;
                double localU = delta;
                msgs.Add(new ReasonMsg("Too weak response for current concern level (" + (int)(concernLevel) + "%)", localU));
                u += localU;
            }
            if (concernLevel < responseLevelMin)
            {
                double delta = concernLevel - responseLevelMin;
                delta *= society.map.param.utility_extremeismScaling;
                double localU = delta;
                msgs.Add(new ReasonMsg("Too extreme for current concern level (" + (int)(concernLevel) + "%)", localU));
                u += localU;
            }
            return(u);
        }
        public void checkInvestigators()
        {
            HashSet <Province> investigatedProvinces = new HashSet <Province>();
            int nInvestigators = 0;

            foreach (Unit u in map.units)
            {
                if (u is Unit_Investigator && u.isEnthralled() == false)
                {
                    if (u.parentLocation != null)
                    {
                        investigatedProvinces.Add(u.parentLocation.province);
                    }
                    nInvestigators += 1;
                }
            }
            HashSet <Province> inhabitedProvinces = new HashSet <Province>();

            foreach (Location l in map.locations)
            {
                if (l.soc is Society && l.settlement != null && l.settlement.isHuman)
                {
                    inhabitedProvinces.Add(l.province);
                }
            }
            if (investigatedProvinces.Count < inhabitedProvinces.Count * map.param.unit_investigatorsPerProvince)
            {
                int      c      = 0;
                Location chosen = null;
                foreach (Province p in inhabitedProvinces)
                {
                    if (investigatedProvinces.Contains(p))
                    {
                        continue;
                    }

                    foreach (int locI in p.locations)
                    {
                        Location loc = map.locations[locI];
                        if (loc.soc is Society soc && loc.settlement != null && loc.settlement.isHuman)
                        {
                            if (soc.isDarkEmpire == false)
                            {
                                c += 1;
                                if (Eleven.random.Next(c) == 0)
                                {
                                    chosen = loc;
                                }
                            }
                        }
                    }
                }
                //Allow doubling up if you exceed cap
                if (chosen == null)
                {
                    foreach (Province p in inhabitedProvinces)
                    {
                        foreach (int locI in p.locations)
                        {
                            Location loc = map.locations[locI];
                            if (loc.soc is Society && loc.settlement != null && loc.settlement.isHuman)
                            {
                                c += 1;
                                if (Eleven.random.Next(c) == 0)
                                {
                                    chosen = loc;
                                }
                            }
                        }
                    }
                }
                if (chosen != null)
                {
                    Unit_Investigator u = new Unit_Investigator(chosen, (Society)chosen.soc);
                    u.person      = new Person((Society)chosen.soc);
                    u.person.unit = u;
                    u.person.traits.Clear();//Can't see traits, best to have them removed
                    map.units.Add(u);
                    u.parentLocation = chosen;
                }
            }
        }
        public static void takeCommand(Map map, string command)
        {
            World.log("cheat command registered: " + command);


            try
            {
                if (command == "power")
                {
                    map.overmind.power = 100;
                }
                if (command == "testsave")
                {
                    map.world.save("testSave.sv");
                }
                if (command == "testload")
                {
                    map.world.load("testSave.sv");
                }
                if (command == "shadow")
                {
                    GraphicalMap.selectedHex.location.person().shadow = 1;
                }
                if (command == "aware")
                {
                    GraphicalMap.selectedHex.location.person().awareness = 1;
                }
                if (command == "testproperty")
                {
                    Property.addProperty(map, GraphicalMap.selectedHex.location, "Military Aid");
                    World.staticMap.world.ui.checkData();
                }
                if (command == "playback")
                {
                    World.staticMap.world.ui.addBlocker(World.staticMap.world.prefabStore.getPlayback(World.staticMap.world, World.staticMap).gameObject);
                }
                if (command == "uivoting")
                {
                    World.staticMap.world.ui.uiVoting.populate((Society)GraphicalMap.selectedHex.location.soc, GraphicalMap.selectedHex.location.person());
                    World.staticMap.world.ui.setToVoting();
                }
                if (command == "100")
                {
                    World.staticMap.world.b100Turns();
                }
                if (command == "enthrall")
                {
                    if (GraphicalMap.selectedHex.location.person() == null)
                    {
                        int    c      = 0;
                        Person choice = null;
                        foreach (Person p in ((Society)GraphicalMap.selectedHex.location.soc).people)
                        {
                            if (p.getLocation() == GraphicalMap.selectedHex.location)
                            {
                                c += 1;
                                if (Eleven.random.Next(c) == 0)
                                {
                                    choice = p;
                                }
                            }
                        }
                        choice.state            = Person.personState.enthralled;
                        map.overmind.enthralled = choice;
                    }
                    else
                    {
                        map.overmind.enthralled       = GraphicalMap.selectedHex.location.person();
                        map.overmind.enthralled.state = Person.personState.enthralled;
                    }
                }
                if (command == "love")
                {
                    foreach (Person p in map.overmind.enthralled.society.people)
                    {
                        p.getRelation(map.overmind.enthralled).addLiking(100, "Cheat love", map.turn);
                    }
                }
                if (command == "insanity")
                {
                    GraphicalMap.selectedHex.location.person().goInsane();
                }
                if (command == "hot")
                {
                    for (int i = 0; i < map.tempMap.Length; i++)
                    {
                        for (int j = 0; j < map.tempMap[0].Length; j++)
                        {
                            map.tempMap[i][j] += 0.1f;
                            if (map.tempMap[i][j] > 1)
                            {
                                map.tempMap[i][j] = 1;
                            }
                        }
                    }
                    map.assignTerrainFromClimate();
                    map.world.ui.checkData();
                }
                if (command == "cold")
                {
                    for (int i = 0; i < map.tempMap.Length; i++)
                    {
                        for (int j = 0; j < map.tempMap[0].Length; j++)
                        {
                            map.tempMap[i][j] -= 0.1f;
                            if (map.tempMap[i][j] < 0)
                            {
                                map.tempMap[i][j] = 0;
                            }
                        }
                    }
                    map.assignTerrainFromClimate();
                    map.world.ui.checkData();
                }
                if (command == "min sanity")
                {
                    GraphicalMap.selectedHex.location.person().sanity = 0.01;
                }
                if (command == "die")
                {
                    GraphicalMap.selectedHex.location.person().die("Killed by console");
                }
                if (command == "evidence")
                {
                    GraphicalMap.selectedHex.location.person().evidence = 1;
                }
                if (command == "10 evidence")
                {
                    GraphicalMap.selectedHex.location.person().evidence += 0.1;
                    if (GraphicalMap.selectedHex.location.person().evidence > 1)
                    {
                        GraphicalMap.selectedHex.location.person().evidence = 1;
                    }
                }
                if (command == "refresh")
                {
                    World.staticMap.overmind.hasTakenAction = false;
                }
                if (command == "unit")
                {
                    Unit u = new Unit_Investigator(GraphicalMap.selectedHex.location, (Society)GraphicalMap.selectedHex.location.soc);
                    map.units.Add(u);
                    GraphicalMap.selectedHex.location.units.Add(u);
                }
                if (command == "victory")
                {
                    World.staticMap.overmind.victory();
                }
                if (command == "placeevidence")
                {
                    GraphicalMap.selectedHex.location.evidence.Add(new Evidence(map.turn));
                    World.log("Placing evidence");
                }
                if (command == "vote")
                {
                    Society soc = map.overmind.enthralled.society;
                    if (soc.voteSession != null)
                    {
                        soc.voteSession.assignVoters();
                        World.log("Attempting to build blocker");
                        map.world.ui.addBlocker(map.world.prefabStore.getScrollSet(soc.voteSession, soc.voteSession.issue.options).gameObject);
                    }
                }
                map.world.ui.checkData();
            }
            catch (Exception e)
            {
                World.log(e.Message);
            }
        }
示例#17
0
        public override double computeUtility(Person p, VoteOption option, List <ReasonMsg> msgs)
        {
            double u = option.getBaseUtility(p);


            if (option.index == NO_RESPONSE)
            {
                msgs.Add(new ReasonMsg("Neutral Option", 0));
            }

            if (option.index == AGENT_TO_MEDIC)
            {
                double localU = Unit_Investigator.getSwitchUtility(p, (Unit_Investigator)option.unit, Unit_Investigator.unitState.medic);
                localU *= p.map.param.utility_swapAgentRolesMult;
                msgs.Add(new ReasonMsg("Balance of agent skills vs balance of threats", localU));
                u += localU;
            }
            if (option.index == AGENT_TO_BASIC)
            {
                double localU = Unit_Investigator.getSwitchUtility(p, (Unit_Investigator)option.unit, Unit_Investigator.unitState.basic);
                localU *= p.map.param.utility_swapAgentRolesMult;
                msgs.Add(new ReasonMsg("Balance of agent skills vs balance of threats", localU));
                u += localU;
            }
            if (option.index == QUARANTINE)
            {
                //First part is your personal utility. How much am I, personally, affected?
                double localU      = p.threat_plague.threat;
                bool   amNeighbour = false;
                bool   hasDisease  = false;
                foreach (Property p2 in p.getLocation().properties)
                {
                    if (p2.proto.isDisease)
                    {
                        hasDisease = true; break;
                    }
                }
                if (hasDisease)
                {
                    //This option doesn't help me. It's already here. If I'm corrupt, I'll naturally be angry at not being given help
                    localU = p.getSelfInterest() * p.threat_plague.threat * World.staticMap.param.utility_selfInterestFromThreat;
                    if (localU != 0)
                    {
                        msgs.Add(new ReasonMsg("Does not help me personally", localU));
                        u += localU;
                    }
                }
                else
                {
                    //I do not have the disease. Best to vote to keep it that way.
                    foreach (Location l2 in p.getLocation().getNeighbours())
                    {
                        foreach (Property p2 in l2.properties)
                        {
                            if (p2.proto.isDisease)
                            {
                                amNeighbour = true; break;
                            }
                        }
                    }
                    if (amNeighbour)
                    {
                        localU *= 1.5;
                    }
                    else
                    {
                        localU *= 0.66;
                    }
                    localU *= p.getSelfInterest() * -1 * World.staticMap.param.utility_selfInterestFromThreat; //Note this param is negative as it is petulance
                    if (localU != 0)
                    {
                        msgs.Add(new ReasonMsg("Desire to keep self safe from disease", localU));
                        u += localU;
                    }
                }

                //Second part is the benefit to the nation
                int    nNeighbours = 0;
                double nSocLocs    = 0;
                foreach (Location l2 in p.map.locations)
                {
                    if (l2.soc == p.society)
                    {
                        nSocLocs += 1;
                    }
                    else
                    {
                        continue;
                    }

                    hasDisease = false;
                    foreach (Property p2 in l2.properties)
                    {
                        if (p2.proto.isDisease)
                        {
                            hasDisease = true; break;
                        }
                    }
                    if (hasDisease)
                    {
                        foreach (Location l3 in l2.getNeighbours())
                        {
                            if (l3.soc != p.society)
                            {
                                continue;
                            }
                            bool l3HasDisease = false;
                            foreach (Property p2 in l3.properties)
                            {
                                if (p2.proto.isDisease)
                                {
                                    l3HasDisease = true; break;
                                }
                            }
                            if (!l3HasDisease)
                            {
                                //Location 3 doesn not have the disease, but l2 does. Therefore it is a spread vector
                                //Since we're taking a risk for each link, we can double-count L3s.
                                nNeighbours += 1;
                            }
                        }
                    }
                }
                localU = nNeighbours;
                if (nSocLocs > 0)
                {
                    localU /= nSocLocs;
                }                                        //Normalise for society size
                localU *= p.threat_plague.threat;
                localU *= p.map.param.utility_plagueResponseMultPerRiskItem;
                localU *= Math.Max(0, Math.Min(1, 1 - p.getSelfInterest()));//Clamp that between [0,1]
                if (localU != 0)
                {
                    msgs.Add(new ReasonMsg("Benefit to nation: Number of locations at risk", localU));
                    u += localU;
                }
            }
            if (option.index == TREATMENT)
            {
                //First part is your personal utility. How much am I, personally, affected?
                double localU     = p.threat_plague.threat;
                bool   hasDisease = false;
                foreach (Property p2 in p.getLocation().properties)
                {
                    if (p2.proto.isDisease)
                    {
                        hasDisease = true; break;
                    }
                }
                if (hasDisease)
                {
                    //I have the disease. Gotta invest in that sweet cure
                    localU *= p.getSelfInterest() * -1 * World.staticMap.param.utility_selfInterestFromThreat;//Note this param is negative as it is petulance
                    if (localU != 0)
                    {
                        msgs.Add(new ReasonMsg("Desire to save self from disease", localU));
                        u += localU;
                    }
                }
                else
                {
                    //This option doesn't help me. It's already here. If I'm corrupt, I'll naturally be angry at not being given help
                    localU = p.getSelfInterest() * p.threat_plague.threat * World.staticMap.param.utility_selfInterestFromThreat;
                    if (localU != 0)
                    {
                        msgs.Add(new ReasonMsg("Does not help me personally", localU));
                        u += localU;
                    }
                }

                //Second part is the benefit to the nation
                int    nDiseased = 0;
                double nSocLocs  = 0;
                foreach (Location l2 in p.map.locations)
                {
                    if (l2.soc == p.society)
                    {
                        nSocLocs += 1;
                    }
                    else
                    {
                        continue;
                    }

                    foreach (Property p2 in l2.properties)
                    {
                        if (p2.proto.isDisease)
                        {
                            nDiseased += 1; break;
                        }
                    }
                }
                localU = nDiseased;
                if (nSocLocs > 0)
                {
                    localU /= nSocLocs;
                }                                        //Normalise for society size
                localU *= p.threat_plague.threat;
                localU *= p.map.param.utility_plagueResponseMultPerRiskItem;
                localU *= Math.Max(0, Math.Min(1, 1 - p.getSelfInterest()));//Clamp that between [0,1]
                if (localU != 0)
                {
                    msgs.Add(new ReasonMsg("Benefit to nation: Number of locations infected", localU));
                    u += localU;
                }
            }

            return(u);
        }
        public override void implement(VoteOption option)
        {
            base.implement(option);

            society.lastEvidenceResponse = society.map.turn;
            foreach (Evidence ev in foundEvidence)
            {
                society.handledEvidence.Add(ev);
            }

            if (option.index == DEFEND_PROVINCE)
            {
                World.log(society.getName() + " implements crisis legislation, increasing security to " + society.map.provinces[option.province].name);
                foreach (Location loc in society.map.locations)
                {
                    if (loc.province.index == option.province && loc.soc == society)
                    {
                        Property.addProperty(society.map, loc, "Major Security Boost");
                    }
                }
                society.map.addMessage(society.getName() + " raises " + society.map.provinces[option.province].name + " security level", MsgEvent.LEVEL_ORANGE, false, society.map.provinces[option.province].coreHex);
            }
            if (option.index == NATIONWIDE_SECURITY)
            {
                World.log(society.getName() + " implements crisis legislation, increasing security nationwide");
                foreach (Location loc in society.map.locations)
                {
                    if (loc.province.index == option.province && loc.soc == society)
                    {
                        Property.addProperty(society.map, loc, "Minor Security Boost");
                    }
                }
                society.map.addMessage(society.getName() + " raises its security level nationwide", MsgEvent.LEVEL_ORANGE, false, society.getCapitalHex());
            }
            if (option.index == NO_RESPONSE)
            {
                World.log(society.getName() + " implements crisis legislation, does nothing");
            }
            if (option.index == EXPELL_ALL_FOREIGN_AGENTS)
            {
                bool agentsExpelled = false;
                foreach (Unit u in society.map.units)
                {
                    if (u.society != society && society.enemies.Contains(u) == false)
                    {
                        society.enemies.Add(u);
                        if (u.isEnthralled())
                        {
                            agentsExpelled = true;
                        }
                    }
                }
                if (agentsExpelled)
                {
                    society.map.world.prefabStore.popMsg(society.getName() + " expells all foreign agents, in response to evidence discovered." +
                                                         " All your existing agents will now be attacked on sight if they enter or are in its lands. New agents will still be acceptable.");
                }
                World.log(society.getName() + " implements crisis legislation, expelling all foreign agents");
                society.map.addMessage(society.getName() + " outlaws all foreign agents", MsgEvent.LEVEL_RED, false, society.getCapitalHex());
            }
            if (option.index == INVESTIGATOR_HOSTILITY)
            {
                foreach (Evidence ev in foundEvidence)
                {
                    if (ev.discoveredBy.society == society && ev.discoveredBy != null && ev.pointsTo != null && (ev.discoveredBy.hostileTo(ev.pointsTo) == false))
                    {
                        ev.discoveredBy.hostility.Add(ev.pointsTo);
                        society.map.addMessage(ev.discoveredBy.getName() + " permitted to attack " + ev.pointsTo.getName(), MsgEvent.LEVEL_RED, !ev.pointsTo.isEnthralled());
                        if (ev.pointsTo.isEnthralled())
                        {
                            society.map.world.prefabStore.popMsg("The nobles of " + society.getName() + " have given permission their agent, " + ev.discoveredBy.getName()
                                                                 + " to attack " + ev.pointsTo.getName() + " on sight, if they encounter them during investigations.");
                        }
                    }
                }
            }
            if (option.index == LOCKDOWN_PROVINCE)
            {
                World.log(society.getName() + " implements crisis legislation, fully locking down " + society.map.provinces[option.province].name);
                Unit enthralledVic = null;
                foreach (Location loc in society.map.locations)
                {
                    if (loc.province.index == option.province && loc.soc == society)
                    {
                        Property.addProperty(society.map, loc, "Lockdown");
                        foreach (Unit u in loc.units)
                        {
                            if (u.isEnthralled())
                            {
                                enthralledVic = u;
                            }
                        }
                    }
                }
                society.map.addMessage(society.getName() + " locks down " + society.map.provinces[option.province].name, MsgEvent.LEVEL_ORANGE, false, society.map.provinces[option.province].coreHex);
                if (enthralledVic != null)
                {
                    society.map.world.prefabStore.popMsg(society.getName() + " has imposed a complete lockdown in the province " + society.map.provinces[option.province].name +
                                                         " which impacts your agent " + enthralledVic.getName() + "'s ability to operate until the lockdown is over.");
                }
            }

            if (option.index == AGENT_TO_INVESTIGATOR)
            {
                Unit_Investigator inv = (Unit_Investigator)option.unit;
                inv.changeState(Unit_Investigator.unitState.investigator);
                World.self.prefabStore.popMsgAgent(option.unit, option.unit, option.unit.getName() + " has been assigned the role of Investigator, by the nobles of " + option.unit.society.getName() +
                                                   " in response to external threats. Investigators are experts at combatting your agents. They can recognise evidence and spot your agents if they are in the same location.");
            }
            if (option.index == AGENT_TO_BASIC)
            {
                Unit_Investigator inv = (Unit_Investigator)option.unit;
                inv.changeState(Unit_Investigator.unitState.basic);
                if (inv.person.isWatched())
                {
                    World.self.prefabStore.popMsgAgent(option.unit, option.unit, option.unit.getName() + " has been assigned the role of Agent, by the nobles of " + option.unit.society.getName() +
                                                       " in response to external threats. Standard agents are general-purpose units. They can investigate your agents' evidence, and can assist in wars. They can be promoted "
                                                       + " to specalists by vote.");
                }
            }
        }
        public static void takeCommand(Map map, string command)
        {
            World.log("cheat command registered: " + command);


            //try
            {
                if (command == "power")
                {
                    map.overmind.power = 1024;
                    map.overmind.availableEnthrallments = 128;
                }
                if (command == "testsave")
                {
                    map.world.save("testSave.sv");
                    //map.world.prefabStore.popAutosave();
                }
                if (command == "testload")
                {
                    //map.world.load("testSave.sv");
                }
                if (command == "silence")
                {
                    World.self.displayMessages = !World.self.displayMessages;
                }
                if (command == "shadow")
                {
                    GraphicalMap.selectedHex.location.person().shadow = 1;
                }
                if (command == "music")
                {
                    map.world.ui.uiMusic.playTest();
                }
                if (command == "aware")
                {
                    GraphicalMap.selectedHex.location.person().awareness = 1;
                }
                if (command == "testproperty")
                {
                    Property.addProperty(map, GraphicalMap.selectedHex.location, "Military Aid");
                    World.staticMap.world.ui.checkData();
                }
                if (command == "playback")
                {
                    World.staticMap.world.ui.addBlocker(World.staticMap.world.prefabStore.getPlayback(World.staticMap.world, World.staticMap).gameObject);
                }
                if (command == "uivoting")
                {
                    World.staticMap.world.ui.uiVoting.populate((Society)GraphicalMap.selectedHex.location.soc, GraphicalMap.selectedHex.location.person());
                    World.staticMap.world.ui.setToVoting();
                }
                if (command == "100")
                {
                    World.staticMap.world.b100Turns();
                }
                if (command == "enthrall")
                {
                    if (GraphicalMap.selectedHex.location.person() == null)
                    {
                        int    c      = 0;
                        Person choice = null;
                        foreach (Person p in ((Society)GraphicalMap.selectedHex.location.soc).people)
                        {
                            if (p.getLocation() == GraphicalMap.selectedHex.location)
                            {
                                c += 1;
                                if (Eleven.random.Next(c) == 0)
                                {
                                    choice = p;
                                }
                            }
                        }
                        choice.state            = Person.personState.enthralled;
                        map.overmind.enthralled = choice;
                    }
                    else
                    {
                        map.overmind.enthralled       = GraphicalMap.selectedHex.location.person();
                        map.overmind.enthralled.state = Person.personState.enthralled;
                    }
                }
                if (command == "love")
                {
                    foreach (Person p in map.overmind.enthralled.society.people)
                    {
                        p.getRelation(map.overmind.enthralled).addLiking(100, "Cheat love", map.turn);
                    }
                }
                if (command == "hate")
                {
                    foreach (Person p in map.overmind.enthralled.society.people)
                    {
                        p.getRelation(map.overmind.enthralled).addLiking(-100, "Cheat hate", map.turn);
                    }
                }
                if (command == "resetSteamAchievements")
                {
                    SteamManager.reset_all_achievements();
                    World.staticMap.world.prefabStore.popMsg("All steam achievements reset");
                }
                if (command == "thetruth")
                {
                    foreach (Unit u in map.units)
                    {
                        if (u is Unit_Seeker seeker)
                        {
                            seeker.knowsTruth = true;
                        }
                    }
                }
                if (command == "insanity")
                {
                    GraphicalMap.selectedHex.location.person().goInsane();
                }
                if (command == "ruin")
                {
                    GraphicalMap.selectedHex.location.settlement.fallIntoRuin();
                }
                if (command == "redDeath")
                {
                    Property.addProperty(GraphicalMap.map, GraphicalMap.selectedHex.location, "Red Death");
                }
                if (command == "rotting" || command == "rotting sickness")
                {
                    Property.addProperty(GraphicalMap.map, GraphicalMap.selectedHex.location, "Rotting Sickness");
                }
                if (command == "fogSource")
                {
                    Property.addProperty(GraphicalMap.map, GraphicalMap.selectedHex.location, "Well of Fog");
                }
                if (command == "hot")
                {
                    for (int i = 0; i < map.tempMap.Length; i++)
                    {
                        for (int j = 0; j < map.tempMap[0].Length; j++)
                        {
                            map.tempMap[i][j] += 0.1f;
                            if (map.tempMap[i][j] > 1)
                            {
                                map.tempMap[i][j] = 1;
                            }
                        }
                    }
                    map.assignTerrainFromClimate();
                    map.world.ui.checkData();
                }
                if (command == "cold")
                {
                    //for (int i = 0; i < map.tempMap.Length; i++)
                    //{
                    //    for (int j = 0; j < map.tempMap[0].Length; j++)
                    //    {
                    //        map.tempMap[i][j] -= 0.1f;
                    //        if (map.tempMap[i][j] < 0) { map.tempMap[i][j] = 0; }
                    //    }
                    //}
                    foreach (Hex[] row in map.grid)
                    {
                        foreach (Hex h in row)
                        {
                            h.transientTempDelta -= 0.1f;
                        }
                    }
                    map.assignTerrainFromClimate();
                    map.world.ui.checkData();
                }
                if (command == "globalcooling")
                {
                    World.cheat_globalCooling = !World.cheat_globalCooling;
                }
                if (command == "min sanity")
                {
                    GraphicalMap.selectedHex.location.person().sanity = 0.01;
                }
                if (command == "die")
                {
                    GraphicalMap.selectedHex.location.person().die("Killed by console", true);
                }
                if (command == "inquisitor")
                {
                    Unit_Investigator inv = (Unit_Investigator)GraphicalMap.selectedSelectable;
                    inv.changeState(Unit_Investigator.unitState.inquisitor);
                }
                if (command == "civilWar")
                {
                    List <Person> rebels = new List <Person>();
                    Society       soc    = (Society)GraphicalMap.selectedHex.location.soc;
                    int           c      = 0;
                    foreach (Person p in soc.people)
                    {
                        if (p.title_land == null)
                        {
                            continue;
                        }
                        if (p.getLocation().province != soc.getCapital().province)
                        {
                            rebels.Add(p);
                        }
                    }
                    soc.triggerCivilWar(rebels);
                }
                if (command == "evidence")
                {
                    GraphicalMap.selectedHex.location.person().evidence = 1;
                }
                if (command == "disrupt")
                {
                    GraphicalMap.selectedHex.location.person().action = new Act_Disrupted();
                }
                if (command == "10 evidence")
                {
                    GraphicalMap.selectedHex.location.person().evidence += 0.1;
                    if (GraphicalMap.selectedHex.location.person().evidence > 1)
                    {
                        GraphicalMap.selectedHex.location.person().evidence = 1;
                    }
                }
                if (command == "refresh")
                {
                    World.staticMap.overmind.hasTakenAction = false;
                }
                if (command == "nextAge")
                {
                    World.staticMap.overmind.progressToNextAge();
                }
                if (command == "unit")
                {
                    Unit u = new Unit_Investigator(GraphicalMap.selectedHex.location, (Society)GraphicalMap.selectedHex.location.soc);
                    map.units.Add(u);
                    GraphicalMap.selectedHex.location.units.Add(u);
                }
                if (command == "victory")
                {
                    World.staticMap.overmind.victory();
                }
                if (command == "defeat")
                {
                    World.staticMap.overmind.defeat();
                }
                if (command == "course")
                {
                    World.staticMap.world.prefabStore.popEndgameCyclic();
                }
                if (command == "worm")
                {
                    SG_WormHive add = new SG_WormHive(map, GraphicalMap.selectedHex.location);
                    map.socialGroups.Add(add);
                }
                if (command == "placeevidence")
                {
                    GraphicalMap.selectedHex.location.evidence.Add(new Evidence(map.turn));
                    World.log("Placing evidence");
                }
                if (command == "vote")
                {
                    Society soc = map.overmind.enthralled.society;
                    if (soc.voteSession != null)
                    {
                        soc.voteSession.assignVoters();
                        World.log("Attempting to build blocker");
                        map.world.ui.addBlocker(map.world.prefabStore.getScrollSet(soc.voteSession, soc.voteSession.issue.options).gameObject);
                    }
                }
                if (command == "infiltrate")
                {
                    GraphicalMap.selectedHex.location.settlement.infiltration = 1;
                    World.log("Infiltrate");
                }
                if (command == "infiltratehalf")
                {
                    GraphicalMap.selectedHex.location.settlement.infiltration = 0.5;
                    World.log("Infiltrate half");
                }
                map.world.ui.checkData();
            }
            //catch(Exception e)
            //{
            //    World.log(e.Message);
            //}
        }
示例#20
0
        public override void turnTick(Unit unit)
        {
            dur += 1;
            if (dur >= unit.location.map.param.unit_shareSuspicionTime)
            {
                if (unit.person != null && unit.location.person() != null && unit.location.person().state != Person.personState.broken)
                {
                    foreach (RelObj rel in unit.person.relations.Values)
                    {
                        double them = unit.location.person().getRelation(rel.them).suspicion;
                        double me   = rel.suspicion;
                        double gain = (me - them) * 1;

                        RelObj toInv     = unit.location.person().getRelation(unit.person);
                        double relLiking = toInv.getLiking();
                        relLiking += 50;
                        if (relLiking < 0)
                        {
                            relLiking = 0;
                        }
                        relLiking /= 100;
                        if (relLiking > 1)
                        {
                            relLiking = 1;
                        }                                    //0 to 1

                        gain *= relLiking;

                        if (me > them)
                        {
                            Person themP = World.staticMap.persons[rel.them];
                            unit.location.map.addMessage(unit.getName() + " warns " + unit.location.person().getFullName() + " about " + themP.getFullName(), MsgEvent.LEVEL_ORANGE, false, unit.location.hex);
                            unit.location.person().getRelation(rel.them).suspicion += gain;
                        }
                    }
                }


                if (unit is Unit_Investigator && unit.location.soc != null && unit.location.soc is Society)
                {
                    Unit_Investigator inv = (Unit_Investigator)unit;
                    Society           soc = (Society)inv.location.soc;
                    bool submitted        = false;
                    foreach (Evidence ev in inv.evidenceCarried)
                    {
                        if (soc.evidenceSubmitted.Contains(ev) == false)
                        {
                            submitted = true;
                            soc.evidenceSubmitted.Add(ev);
                            soc.lastEvidenceSubmission = unit.location.map.turn;
                            ev.turnSubmitted           = unit.location.map.turn;

                            unit.location.addAgentDreadAroundThisLocation();
                            //double deltaFear = World.staticMap.param.threat_evidencePresented;
                            //if (soc.isDarkEmpire == false)
                            //{
                            //    soc.dread_agents_evidenceFound += deltaFear;
                            //}
                        }
                    }
                    if (submitted)
                    {
                        unit.location.map.addMessage(unit.getName() + " presents evidence to " + soc.getName(), MsgEvent.LEVEL_ORANGE, false, unit.location.hex);
                    }
                }
                unit.task = null;
            }
        }
        public override void turnTick(Unit unit)
        {
            //Enthralled can't just eat clues
            if (unit.isEnthralled())
            {
                unit.task = null;
                return;
            }

            if (unit.location.evidence.Count > 0)
            {
                Evidence massiveEvidence = null;
                foreach (Evidence ev in unit.location.evidence)
                {
                    if (ev.instaDiscover)
                    {
                        massiveEvidence = ev; break;
                    }
                }
                if (massiveEvidence != null)
                {
                    discoverMassiveEvidence(massiveEvidence, unit);
                    return;
                }

                dur += 1;
                if (dur >= unit.location.map.param.unit_investigateTime)
                {
                    Evidence ev = unit.location.evidence[0];
                    if (ev.pointsTo != null)
                    {
                        if (unit.person != null && ev.pointsTo.person != null)
                        {
                            unit.person.getRelation(ev.pointsTo.person).suspicion = System.Math.Min(1, unit.person.getRelation(ev.pointsTo.person).suspicion + ev.weight);
                        }
                        else
                        {
                            //Can't use suspicion system, go straight to murder
                            //Makes sense since they're probably non-human terrors
                            unit.hostility.Add(ev.pointsTo);
                        }

                        unit.location.map.addMessage(unit.getName() + " has found evidence from " + ev.pointsTo.getName(), MsgEvent.LEVEL_ORANGE, false, unit.location.hex);
                    }
                    else if (ev.pointsToPerson != null)
                    {
                        if (unit.person != null && ev.pointsToPerson != null)
                        {
                            unit.person.getRelation(ev.pointsToPerson).suspicion = System.Math.Min(1, unit.person.getRelation(ev.pointsToPerson).suspicion + ev.weight);
                        }

                        unit.location.map.addMessage(unit.getName() + " has found evidence from " + ev.pointsToPerson.getFullName(), MsgEvent.LEVEL_ORANGE, false, unit.location.hex);
                    }


                    if (unit is Unit_Investigator)
                    {
                        Unit_Investigator inv = (Unit_Investigator)unit;
                        inv.evidenceCarried.Add(ev);
                        ev.discoveredBy = inv;
                    }
                    ev.locationFound = unit.location;
                    unit.location.evidence.Remove(ev);
                    unit.task = null;

                    unit.location.map.overmind.panicFromCluesDiscovered += unit.location.map.param.panic_fromClueFound;
                    if (unit.location.map.overmind.panicFromCluesDiscovered > 1)
                    {
                        unit.location.map.overmind.panicFromCluesDiscovered = 1;
                    }


                    //If we're already at maximum suspicion we can now begin pursuing them
                    if (unit is Unit_Investigator)
                    {
                        Unit_Investigator inv = (Unit_Investigator)unit;
                        if (inv.state == Unit_Investigator.unitState.investigator)
                        {
                            if (ev.pointsTo != null && ev.pointsTo.person != null && inv.person.getRelation(ev.pointsTo.person).suspicion >= 1)
                            {
                                Task_HuntEnthralled_InvState task = new Task_HuntEnthralled_InvState(inv, ev.pointsTo);
                                inv.task = task;
                                unit.location.map.world.prefabStore.popMsgAgent(inv, ev.pointsTo,
                                                                                inv.getName() + " has found evidence left by " + ev.pointsTo.getName() + ", and because they are an investigator who is 100% suspicious of " + ev.pointsTo.getName()
                                                                                + ", is able to use these clues to determine the location of " + ev.pointsTo.getName() + ", and will begin to chase them for " + task.turnsLeft + " turns.");
                            }
                        }
                    }

                    if (unit.task == null)
                    {
                        if (unit.location.person() != null)
                        {
                            Person noble = unit.location.person();
                            foreach (RelObj rel in unit.person.relations.Values)
                            {
                                ////Goes negative if they suspect more than we do, reaches 1.0 if we suspect 1.0 and they suspect 0.0
                                // if ((rel.suspicion - noble.getRelation(rel.them).suspicion) > Eleven.random.NextDouble())
                                if ((rel.suspicion > noble.getRelation(rel.them).suspicion * 1.1))
                                {
                                    unit.task = new Task_ShareSuspicions();
                                    return;
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                //Evidence gone. Probably eaten by someone else. Return to idle to retask next turn
                unit.task = null;
            }
        }
 public Task_HuntEnthralled_PaladinState(Unit_Investigator inv, Unit prey)
 {
     this.target = prey;
     this.inv    = inv;
     turnsLeft   = World.staticMap.param.unit_paladin_trackDuration;
 }
        public static double getSwitchUtility(Person person, Unit_Investigator swappable, unitState hypo)
        {
            double value = 0;

            double worstMilitaryFear = 0;

            foreach (ThreatItem item in person.threatEvaluations)
            {
                if (item.group != null)
                {
                    if (item.threat > worstMilitaryFear)
                    {
                        worstMilitaryFear = item.threat;
                    }
                }
            }
            double[] weights           = new double[] { person.threat_agents.threat, worstMilitaryFear, person.threat_plague.threat, person.threat_agents.threat };
            double[] currentAllocation = new double[4];
            double[] futureAllocation  = new double[4];

            if (weights[0] < 50)
            {
                weights[0] = 50;//Try to keep at least some people watching the criminal situation
            }

            int specialisationWeight = 3;

            foreach (Unit u in person.map.units)
            {
                if (u.society == person.society && u is Unit_Investigator)
                {
                    Unit_Investigator existing = (Unit_Investigator)u;
                    if (existing.state == unitState.basic)
                    {
                        //Basic covers all jobs
                        for (int i = 0; i < currentAllocation.Length; i++)
                        {
                            currentAllocation[i] += 1;
                            if (u != swappable)
                            {
                                futureAllocation[i] += 1;
                            }
                        }
                    }
                    else if (existing.state == unitState.investigator || existing.state == unitState.paladin)
                    {
                        currentAllocation[0] += specialisationWeight;
                        if (u != swappable)
                        {
                            futureAllocation[0] += specialisationWeight;
                        }
                    }
                    else if (existing.state == unitState.knight)
                    {
                        currentAllocation[1] += specialisationWeight;
                        if (u != swappable)
                        {
                            futureAllocation[1] += specialisationWeight;
                        }
                    }
                    else if (existing.state == unitState.medic)
                    {
                        currentAllocation[2] += specialisationWeight;
                        if (u != swappable)
                        {
                            futureAllocation[2] += specialisationWeight;
                        }
                    }
                    else if (existing.state == unitState.inquisitor)
                    {
                        currentAllocation[3] += specialisationWeight;
                        if (u != swappable)
                        {
                            futureAllocation[3] += specialisationWeight;
                        }
                    }
                }
            }
            //What would the future state look like if this agent swapped?
            if (hypo == unitState.basic)
            {
                for (int i = 0; i < currentAllocation.Length; i++)
                {
                    futureAllocation[i] += 1;
                }
            }
            else if (hypo == unitState.paladin || hypo == unitState.investigator)
            {
                futureAllocation[0] += specialisationWeight;
            }
            else if (hypo == unitState.knight)
            {
                futureAllocation[1] += specialisationWeight;
            }
            else if (hypo == unitState.medic)
            {
                futureAllocation[2] += specialisationWeight;
            }
            else if (hypo == unitState.inquisitor)
            {
                futureAllocation[3] += specialisationWeight;
            }

            double normA = 0;
            double normB = 0;
            double normC = 0;

            for (int i = 0; i < currentAllocation.Length; i++)
            {
                normA += currentAllocation[i];
                normB += weights[i];
                normC += futureAllocation[i];
            }
            for (int i = 0; i < currentAllocation.Length; i++)
            {
                if (normA != 0)
                {
                    currentAllocation[i] /= normA;
                }
                if (normB != 0)
                {
                    weights[i] /= normB;
                }
                if (normC != 0)
                {
                    futureAllocation[i] /= normC;
                }
            }

            //We now want to ask if swapping gets us closer to ideal distribution
            //Squared Euclidean metric
            double presentDistance = 0;
            double futureDistance  = 0;

            //string msgCur = "";
            //string msgFuture = "";
            //string msgWeights = "";
            for (int i = 0; i < futureAllocation.Length; i++)
            {
                //msgFuture += Eleven.toFixedLen(futureAllocation[i], 4) + " ";
                //msgCur += Eleven.toFixedLen(currentAllocation[i], 4) + " ";
                //msgWeights += Eleven.toFixedLen(weights[i], 4) + " ";
                //World.log("Swap hypothesis " + i + " " + currentAllocation[i] + " " + futureAllocation[i]);
                presentDistance += (currentAllocation[i] - weights[i]) * (currentAllocation[i] - weights[i]);
                futureDistance  += (futureAllocation[i] - weights[i]) * (futureAllocation[i] - weights[i]);
            }
            //World.log("Threat weights: " + msgWeights);
            //World.log("Hypotheatical : " + msgFuture + " dist " + Eleven.toFixedLen(futureDistance, 5));
            //World.log("Current       : " + msgCur + " dist " + Eleven.toFixedLen(presentDistance,5));

            return(presentDistance - futureDistance);//We want to minimise the distance. If swapping moves us closer then futureDist is smaller than present dist, so this becomes positive
        }