public override double computeUtility(Person voter, VoteOption option, List <ReasonMsg> msgs) { double u = option.getBaseUtility(voter); Person p = option.person; double benefitU = voter.getRelation(p).getLiking() * voter.map.param.utility_singleUseCure; msgs.Add(new ReasonMsg("Benefit to " + p.getFullName(), benefitU)); u += benefitU; bool hasDisease = false; foreach (Property pr in voter.getLocation().properties) { if (pr.proto.isDisease) { hasDisease = true; break; } } if (hasDisease && p != voter) { //We're considering giving this cure to another //This option doesn't help me. If I'm corrupt, I'll naturally be angry at not being given help double localU = voter.getSelfInterest() * voter.threat_plague.threat * World.staticMap.param.utility_selfInterestFromThreat * 1.5; if (localU != 0) { msgs.Add(new ReasonMsg("Does not help me personally", localU)); u += localU; } } return(u); }
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 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); }