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."); } } }
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); }
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; } } } } }
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); }
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")); }
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"); } } } } }
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); }
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); } }
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); //} }
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 }