Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Weighted Map: MekHQ-side Changes #2549

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 26 additions & 28 deletions MekHQ/src/mekhq/campaign/mission/AtBContract.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,37 +21,24 @@
*/
package mekhq.campaign.mission;

import java.io.PrintWriter;
import java.io.Serializable;
import java.text.ParseException;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Objects;
import java.util.UUID;

import megamek.client.ui.swing.util.PlayerColour;
import megamek.common.icons.Camouflage;
import mekhq.campaign.againstTheBot.enums.AtBLanceRole;
import mekhq.campaign.finances.Money;
import mekhq.campaign.market.enums.UnitMarketType;
import mekhq.campaign.mission.enums.MissionStatus;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import megamek.client.generator.RandomSkillsGenerator;
import megamek.client.generator.RandomUnitGenerator;
import megamek.client.ui.swing.util.PlayerColour;
import megamek.common.Compute;
import megamek.common.Entity;
import megamek.common.MechFileParser;
import megamek.common.MechSummary;
import megamek.common.UnitType;
import megamek.common.icons.Camouflage;
import megamek.common.loaders.EntityLoadingException;
import megamek.common.util.WeightedMap;
import mekhq.MekHQ;
import mekhq.MekHqXmlUtil;
import mekhq.campaign.Campaign;
import mekhq.campaign.againstTheBot.enums.AtBLanceRole;
import mekhq.campaign.finances.Money;
import mekhq.campaign.market.enums.UnitMarketType;
import mekhq.campaign.mission.atb.AtBScenarioFactory;
import mekhq.campaign.mission.enums.MissionStatus;
import mekhq.campaign.personnel.Person;
import mekhq.campaign.personnel.SkillType;
import mekhq.campaign.rating.IUnitRating;
Expand All @@ -62,6 +49,17 @@
import mekhq.campaign.universe.Faction;
import mekhq.campaign.universe.Factions;
import mekhq.campaign.universe.RandomFactionGenerator;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.io.PrintWriter;
import java.io.Serializable;
import java.text.ParseException;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Objects;
import java.util.UUID;

/**
* Contract class for use with Against the Bot rules
Expand Down Expand Up @@ -167,7 +165,7 @@ public class AtBContract extends Contract implements Serializable {
protected int battleTypeMod;
/* Only applies to next week */
protected int nextWeekBattleTypeMod;

private StratconCampaignState stratconCampaignState;

protected AtBContract() {
Expand Down Expand Up @@ -556,18 +554,18 @@ else if (roll >= 13) {
}

/**
* Changes the enemy to a randomly selected faction that's an enemy of
* Changes the enemy to a randomly selected faction that's an enemy of
* the current employer
*/
private void updateEnemy(LocalDate today) {
String enemyCode = RandomFactionGenerator.getInstance().getEnemy(
Factions.getInstance().getFaction(employerCode), false, true);
setEnemyCode(enemyCode);

Faction enemyFaction = Factions.getInstance().getFaction(enemyCode);
setEnemyBotName(enemyFaction.getFullName(today.getYear()));
}

public int getRepairLocation(int dragoonRating) {
int retval = Unit.SITE_BAY;
if ((missionType == MT_GUERRILLAWARFARE) ||
Expand Down Expand Up @@ -1210,7 +1208,7 @@ protected void writeToXmlBegin(PrintWriter pw1, int indent) {
MekHqXmlUtil.saveFormattedDate(specialEventScenarioDate));
MekHqXmlUtil.writeSimpleXmlTag(pw1, indent + 1, "specialEventScenarioType", specialEventScenarioType);
}

if(stratconCampaignState != null) {
stratconCampaignState.Serialize(pw1);
}
Expand Down Expand Up @@ -1522,23 +1520,23 @@ public void useBonusPart() {
public int getBattleTypeMod() {
return battleTypeMod + nextWeekBattleTypeMod;
}

public StratconCampaignState getStratconCampaignState() {
return stratconCampaignState;
}

public void setStratconCampaignState(StratconCampaignState state) {
stratconCampaignState = state;
}

@Override
public void acceptContract(Campaign campaign) {
if (campaign.getCampaignOptions().getUseStratCon()) {
StratconContractInitializer.initializeCampaignState(this, campaign,
StratconContractInitializer.initializeCampaignState(this, campaign,
StratconContractDefinition.getContractDefinition(getMissionType()));
}
}

public AtBContract(Contract c, Campaign campaign) {
this(c.getName());

Expand Down
52 changes: 25 additions & 27 deletions MekHQ/src/mekhq/campaign/personnel/SpecialAbility.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,35 +20,14 @@
*/
package mekhq.campaign.personnel;

import java.io.FileInputStream;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import javax.xml.parsers.DocumentBuilder;

import megamek.common.Mounted;
import megamek.common.annotations.Nullable;
import megamek.common.util.WeightedMap;
import mekhq.campaign.CampaignOptions;
import mekhq.campaign.personnel.enums.PersonnelRole;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import megamek.common.EquipmentType;
import megamek.common.Mounted;
import megamek.common.TechConstants;
import megamek.common.WeaponType;
import megamek.common.annotations.Nullable;
import megamek.common.options.IOption;
import megamek.common.options.PilotOptions;
import megamek.common.util.weightedMaps.WeightedIntMap;
import megamek.common.weapons.InfantryAttack;
import megamek.common.weapons.autocannons.ACWeapon;
import megamek.common.weapons.autocannons.LBXACWeapon;
Expand All @@ -60,6 +39,25 @@
import mekhq.MekHqXmlUtil;
import mekhq.Utilities;
import mekhq.Version;
import mekhq.campaign.CampaignOptions;
import mekhq.campaign.personnel.enums.PersonnelRole;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Vector;

/**
* This object will serve as a wrapper for a specific pilot special ability. In the actual
Expand Down Expand Up @@ -586,7 +584,7 @@ public static SpecialAbility getOption(String name) {
*/
public static @Nullable String chooseWeaponSpecialization(final Person person, final int techLevel,
final int year, final boolean clusterOnly) {
final WeightedMap<EquipmentType> weapons = new WeightedMap<>();
final WeightedIntMap<EquipmentType> weapons = new WeightedIntMap<>();
// First try to generate based on the person's unit
if ((person.getUnit() != null) && (person.getUnit().getEntity() != null)) {
for (final Mounted mounted : person.getUnit().getEntity().getEquipment()) {
Expand Down Expand Up @@ -618,7 +616,7 @@ public static SpecialAbility getOption(String name) {
private static void addValidWeaponryToMap(final EquipmentType equipmentType,
final Person person, final int techLevel,
final int year, final boolean clusterOnly,
final WeightedMap<EquipmentType> weapons) {
final WeightedIntMap<EquipmentType> weapons) {
// Ensure it is a weapon eligible for the SPA in question, and the tech level is IS for
// IS personnel and Clan for Clan personnel
if (!isWeaponEligibleForSPA(equipmentType, person.getPrimaryRole(), clusterOnly)
Expand Down Expand Up @@ -701,7 +699,7 @@ public String getAllPrereqDesc() {
toReturn += getDisplayName(prereq) + "<br>";
}
for (SkillPrereq skPr : prereqSkills) {
toReturn += skPr.toString() + "<br>";
toReturn += skPr + "<br>";
}
for (String pr : prereqMisc.keySet()) {
toReturn += pr + ": " + prereqMisc.get(pr) + "<br/>";
Expand Down
8 changes: 4 additions & 4 deletions MekHQ/src/mekhq/campaign/personnel/enums/Marriage.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

import megamek.common.util.EncodeControl;
import megamek.common.util.StringUtil;
import megamek.common.util.WeightedMap;
import megamek.common.util.weightedMaps.WeightedIntMap;
import mekhq.MekHQ;
import mekhq.campaign.Campaign;
import mekhq.campaign.event.PersonChangedEvent;
Expand Down Expand Up @@ -82,7 +82,7 @@ public void marry(final Campaign campaign, final Person origin, final Person spo
Marriage surnameStyle = this;

if (surnameStyle == WEIGHTED) {
WeightedMap<Marriage> map = createWeightedSurnameMap(campaign);
WeightedIntMap<Marriage> map = createWeightedSurnameMap(campaign);
surnameStyle = map.randomItem();
}

Expand Down Expand Up @@ -213,8 +213,8 @@ public void marry(final Campaign campaign, final Person origin, final Person spo
}


private WeightedMap<Marriage> createWeightedSurnameMap(final Campaign campaign) {
final WeightedMap<Marriage> map = new WeightedMap<>();
private WeightedIntMap<Marriage> createWeightedSurnameMap(final Campaign campaign) {
final WeightedIntMap<Marriage> map = new WeightedIntMap<>();
final int[] weights = campaign.getCampaignOptions().getMarriageSurnameWeights();
final Marriage[] styles = Marriage.values();
for (int i = 0; i < (styles.length - 1); i++) {
Expand Down
48 changes: 26 additions & 22 deletions MekHQ/src/mekhq/campaign/universe/RandomFactionGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,25 @@
*/
package mekhq.campaign.universe;

import java.time.LocalDate;
import java.time.Month;
import java.util.*;
import java.util.stream.Collectors;

import megamek.common.util.WeightedMap;

import megamek.common.Compute;
import megamek.common.annotations.Nullable;
import megamek.common.event.Subscribe;
import megamek.common.util.weightedMaps.WeightedIntMap;
import mekhq.MekHQ;
import mekhq.Utilities;
import mekhq.campaign.Campaign;
import mekhq.campaign.event.OptionsChangedEvent;

import java.time.LocalDate;
import java.time.Month;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;

/**
* @author Neoancient
*
Expand Down Expand Up @@ -173,8 +177,8 @@ public Set<String> getCurrentFactions() {
*
* @return Map used to select employer
*/
protected WeightedMap<Faction> buildEmployerMap() {
WeightedMap<Faction> retVal = new WeightedMap<>();
protected WeightedIntMap<Faction> buildEmployerMap() {
WeightedIntMap<Faction> retVal = new WeightedIntMap<>();
for (Faction f : borderTracker.getFactionsInRegion()) {

if (f.isClan() || FactionHints.isEmptyFaction(f)) {
Expand Down Expand Up @@ -208,7 +212,7 @@ protected WeightedMap<Faction> buildEmployerMap() {
* @return A faction to use as the employer for a contract.
*/
public String getEmployer() {
WeightedMap<Faction> employers = buildEmployerMap();
WeightedIntMap<Faction> employers = buildEmployerMap();
Faction f = employers.randomItem();
if (null != f) {
return f.getShortName();
Expand Down Expand Up @@ -242,7 +246,7 @@ public String getEnemy(String employer, boolean useRebels) {
public String getEnemy(Faction employer, boolean useRebels) {
return getEnemy(employer, useRebels, false);
}

/**
* Selects an enemy faction for the given employer, weighted by length of shared border and
* diplomatic relations. Factions at war or designated as rivals are twice as likely (cumulative)
Expand All @@ -269,44 +273,44 @@ public String getEnemy(Faction employer, boolean useRebels, boolean useMercs) {
}
if (null != employer) {
employerName = employer.getShortName();
WeightedMap<Faction> enemyMap = buildEnemyMap(employer);
WeightedIntMap<Faction> enemyMap = buildEnemyMap(employer);

if (useMercs) {
appendMercsToEnemyMap(enemyMap);
}

enemy = enemyMap.randomItem();
}
if (null != enemy) {
return enemy.getShortName();
}

MekHQ.getLogger().error("Could not find enemy for " + employerName); //$NON-NLS-1$

// Fallback; there are always pirates.
return "PIR";
}

/**
* Appends MERC faction to the given enemy map, with approximately a 10% probability
*/
protected void appendMercsToEnemyMap(WeightedMap<Faction> enemyMap) {
protected void appendMercsToEnemyMap(WeightedIntMap<Faction> enemyMap) {
int mercWeight = 0;
for (int key : enemyMap.keySet()) {
mercWeight += key;
}
enemyMap.add((int) Math.max(1, (mercWeight / 10)), Factions.getInstance().getFaction("MERC"));

enemyMap.add(Math.max(1, (mercWeight / 10)), Factions.getInstance().getFaction("MERC"));
}

/**
* Builds a map of potential enemies keyed to cumulative weight
*
* @param employer The employer faction
* @return The weight map of potential enemies
*/
protected WeightedMap<Faction> buildEnemyMap(Faction employer) {
WeightedMap<Faction> enemyMap = new WeightedMap<>();
protected WeightedIntMap<Faction> buildEnemyMap(Faction employer) {
WeightedIntMap<Faction> enemyMap = new WeightedIntMap<>();
for (Faction enemy : borderTracker.getFactionsInRegion()) {
if (FactionHints.isEmptyFaction(enemy)
|| enemy.getShortName().equals("CLAN")) {
Expand Down