/*
* EU2Scenario.java
*
* Created on June 23, 2006, 6:57 PM
*/
package eug.specific.eu2;
import eug.parser.EUGFileIO;
import eug.shared.GenericList;
import eug.shared.GenericObject;
import eug.shared.Scenario;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
/**
*
* @author Michael Myers
*/
public class EU2Scenario extends Scenario {
// private String scenarioFilePath;
static String eu2FolderPath = "c:/program files/strategy first/europa universalis 2/";
static String modPath = "AGCEEP/";
// private String scenarioName;
public String[] provName;
public String[] provReligion;
public String[] provCulture;
public int[] provIncome;
private int[] provTerrain;
public int[] provMine;
public String[] provGoods;
public String[] goods;
/** Caches requested countries for better performance. */
private Map<String, EU2Country> countryCache;
// private int lastID;
private static final int NUM_PROVINCES = 2020;
public EU2Scenario(GenericObject r, String filePath) {
this(r, filePath, true);
}
/** Creates a new instance of EU2Scenario */
public EU2Scenario(GenericObject r, String filePath, boolean includeEvents) {
// scenarioFilePath = filePath;
//mac game setup:
if (new File(eu2FolderPath+"Europa Universalis 2 Data Files/config/text.csv").exists()) {
eu2FolderPath+="Europa Universalis 2 Data Files";
//PC game setup:
} else if (new File(eu2FolderPath+"config/text.csv").exists()) {
} else {
JOptionPane.showMessageDialog(null, "Could not locate the EU2 game files.");
System.exit(1);
}
root=r;
scenarioName = r.getChild("header").getString("name");
// lastID = 0;
initDisplayNames();
initProvs();
// Note: initGoods() MUST come after initDisplayNames() !!
initGoods();
if (includeEvents)
loadEvents();
/*
* The following methods are used to find commonly-used objects
* for quick access later
*/
setProvVector();
setCountryVector();
// root.getChild("header").getList("selectable").sort(); // just for fun
// System.out.println(countries.size()+" countries.");
}
private void initDisplayNames() {
/* Changed in EUGFile 1.02.01 to eliminate dependency on ostermillerutils. */
/*
* TODO: make multi-platform
*/
final File f = new File(eu2FolderPath+modPath+"config/text.csv");
String cL;
String line;
String[] arr;
displayNames = new HashMap<String, String>();
/*
* Reading the displayNames from the EU2 file containing them
*/
try {
final BufferedReader reader = new BufferedReader(new FileReader(f));
// final CSVParser parser =
// new CSVParser(new BufferedReader(new FileReader(f)), ';');
// parser.setCommentStart("#");
while ((line = reader.readLine()) != null) {
// name = parser.nextValue();
//
// if (name == null)
// break;
if (line.charAt(0) == '#')
continue;
// try {
arr = line.split(";", -1);
displayNames.put(arr[0].toLowerCase(), arr[1]); //displayNames.put(name.toLowerCase(), parser.nextValue());
// } catch (Exception ex) {
// System.out.println("DEBUG: "+line);
// if (arr != null)
// System.out.println("DEBUG: "+java.util.Arrays.deepToString(arr));
// }
//displayNames.put(name.toLowerCase(), parser.nextValue());
// parser.getLine();
}
reader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void initProvs() {
/* Changed in EUGFile 1.02.01 to eliminate dependency on ostermillerutils. */
try {
final BufferedReader br =
new BufferedReader(new FileReader(eu2FolderPath+modPath+"db/province.csv"));
String currLine;
// final CSVParser p = new CSVParser(br, ';');
// p.setCommentStart("#");
// final LabeledCSVParser reader = new LabeledCSVParser(p);
provTerrain = new int[NUM_PROVINCES];
provName = new String[NUM_PROVINCES];
provReligion = new String[NUM_PROVINCES];
provCulture = new String[NUM_PROVINCES];
provIncome = new int[NUM_PROVINCES];
provMine = new int[NUM_PROVINCES];
provGoods = new String[NUM_PROVINCES];
for (int i = 0; i < NUM_PROVINCES; i++) {
provName[i] = "";
provReligion[i] = "";
provCulture[i] = "";
provIncome[i] = -1;
provTerrain[i] = -1;
provMine[i] = 0;
provGoods[i] = "";
}
int id = -1;
br.readLine(); // eat first line
while ((currLine = br.readLine()) != null) {
if (currLine.charAt(0) == '#' || currLine.charAt(0) == ';')
continue;
String[] args = currLine.split(";");
try {
String sid = args[0]; //reader.getValueByLabel("Id");
if (sid.length() != 0) {
id = Integer.parseInt(sid);
if (id > 0) {
provName[id] = args[1]; //reader.getValueByLabel("Name");
provReligion[id] = args[3]; //reader.getValueByLabel("Religion");
provCulture[id] = args[4]; //reader.getValueByLabel("Culture");
provIncome[id] = Integer.parseInt(args[12]); //Integer.parseInt(reader.getValueByLabel("Income"));
provTerrain[id] = Integer.parseInt(args[13]); //Integer.parseInt(reader.getValueByLabel("Terrain"));
// NOTE: Entries 14, 15, and 16 (ToT-SPA;ToT-POR;HRE;) were added in 1.09, so
// these next two may be problematic for those without access to the patch.
provMine[id] = Integer.parseInt(args[18]); //Integer.parseInt(reader.getValueByLabel("MineValue"));
provGoods[id] = getDisplayName(args[19]); //getDisplayName(reader.getValueByLabel("Goods"));
}
}
} catch (Exception e) {
System.err.print("Error with "+id+": ");
e.printStackTrace();
}
}
br.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void initGoods() {
try {
final BufferedReader br = new BufferedReader(new FileReader(eu2FolderPath+modPath+"db/goods.csv"));
br.readLine(); // eat first line
String currentLine;
goods = new String[25];
int i = 0;
while ((currentLine = br.readLine()) != null)
goods[i++] = getDisplayName(currentLine.split(";")[0]);
br.close();
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
}
private void loadEvents() {
System.out.println("Loading event files...\n");
for (eug.shared.ObjectVariable var : root.values) {
if (var.varname.equals("event"))
EventDatabase.loadEvents(var.getValue(), this);
}
System.out.println("\n --- Done ---");
System.out.println("Loaded "+EventDatabase.database.size()+" events.\n");
}
public EU2Country getCountry(String tag) {
tag = tag.toUpperCase().substring(0,3); // in case
if (countryCache.containsKey(tag))
return countryCache.get(tag);
for (GenericObject ctry : countries) {
if (ctry.getString("tag").equals(tag)) {
final EU2Country country = new EU2Country(ctry, this);
countryCache.put(tag, country);
return country;
}
}
return null;
}
public void removeCountry(EU2Country ctry) {
root.removeChild(ctry.go);
countries.remove(ctry.go);
countryCache.remove(ctry.getTag());
// These may not exist
root.getChild("header").getList("selectable").delete(ctry.getTag());
root.getChild("header").removeChild(ctry.getTag());
final GenericObject globaldata = root.getChild("globaldata");
List<GenericObject> toRemove = new java.util.ArrayList<GenericObject>();
GenericList participant;
for (GenericObject alliance : globaldata.getChildren("alliance")) {
participant = alliance.getList("participant");
if (participant.contains(ctry.getTag())) {
if (participant.size() == 2)
toRemove.add(alliance);
else
participant.delete(ctry.getTag());
}
}
GenericObject score;
for (GenericObject war : globaldata.getChildren("war")) {
participant = war.getChild("attackers").getList("participant");
if (participant.contains(ctry.getTag())) {
if (participant.size() == 1)
toRemove.add(war);
else
participant.delete(ctry.getTag());
}
participant = war.getChild("defenders").getList("participant");
if (participant.contains(ctry.getTag())) {
if (participant.size() == 1)
toRemove.add(war);
else
participant.delete(ctry.getTag());
}
score = war.getChild("attackerscore");
score.removeChild(ctry.getTag());
for (GenericObject s : score.children)
s.removeVariable(ctry.getTag());
score = war.getChild("defenderscore");
score.removeChild(ctry.getTag());
for (GenericObject s : score.children)
s.removeVariable(ctry.getTag());
}
for (GenericObject o : toRemove)
globaldata.removeChild(o);
}
public EU2Country getCountry(int pos) {
final String tag = countries.get(pos).getString("tag");
if (countryCache.containsKey(tag))
return countryCache.get(tag);
final EU2Country ctry = new EU2Country(countries.get(pos), this);
countryCache.put(tag, ctry);
return ctry;
}
public Province getProvince(int id) {
String sid = String.valueOf(id);
for (GenericObject prov : provinces) {
if (prov.getString("id").equals(sid))
return new Province(prov, this);
}
System.err.println("Province " + sid + " cannot be found");
return null;
}
public boolean provCanHaveOwner(int id) {
return provTerrain[id] < 5;
}
private void setCountryVector() {
countries = new Vector<GenericObject>();
for (GenericObject obj : root.children) {
if (obj.name.equals("country")) {
countries.add(obj);
}
}
Collections.sort(countries, new Comparator<GenericObject>() {
public int compare(GenericObject o1, GenericObject o2) {
return getDisplayName((o1.getString("tag"))).compareTo(getDisplayName(o2.getString("tag")));
}
});
countryCache = new HashMap<String,EU2Country>(countries.size());
}
private void setProvVector() {
provinces = new Vector<GenericObject>();
for (GenericObject obj : root.children) {
if (obj.name.equals("province")) {
provinces.add(obj);
}
}
}
public double getTotalPopulation() {
double pop = 0.0;
for (int i = 0; i < countries.size(); i++)
pop += getCountry(i).getTotalPopulation();
return pop;
}
public double getTotalLandForces() {
double mil = 0.0;
for (int i = 0; i < countries.size(); i++)
mil += getCountry(i).numLandTroops();
return mil;
}
public double getTotalSeaForces() {
double mil = 0.0;
for (int i = 0; i < countries.size(); i++)
mil += getCountry(i).numShips();
return mil;
}
public static EU2Scenario openEU2Scenario() {
JFileChooser fc = new JFileChooser(eu2FolderPath);
// ExtensionFileFiler filter = new ExtensionFileFiler();
// filter.addExtension("eug");
// filter.setDescription("Europa Universalis 2 scenarios");
// fc.setFileFilter(filter);
int res = fc.showOpenDialog(null);
if (res != JFileChooser.APPROVE_OPTION){
return null;
}
GenericObject root = EUGFileIO.load(fc.getSelectedFile());
return new EU2Scenario(root, fc.getSelectedFile().getPath());
}
public static EU2Scenario openEU2Scenario(String filename) {
GenericObject root = EUGFileIO.load(filename);
return new EU2Scenario(root, filename);
}
public static EU2Scenario openEU2Scenario(String filename, boolean includeEvents) {
GenericObject root = EUGFileIO.load(filename);
return new EU2Scenario(root, filename, includeEvents);
}
public String getScenarioName() {
return scenarioName;
}
public GenericList getSelectable() {
return root.getChild("header").getList("selectable");
}
void changeCountryTag(String oldTag, String newTag) {
// Normalize tags, just in case
oldTag = oldTag.toUpperCase();
newTag = newTag.toUpperCase();
// Make sure the tag change makes sense
if (oldTag.equals(newTag))
return;
countryCache.put(newTag, countryCache.get(oldTag));
countryCache.remove(oldTag);
// Change selectable
GenericList selectable = root.getChild("header").getList("selectable");
selectable.delete(oldTag);
selectable.add(newTag, false);
// If the old country was one of the ones shown in scenario setup,
// change it.
GenericObject shield = root.getChild("header").getChild(oldTag);
if (shield != null)
shield.name = newTag;
// Change the tag in alliances (this also includes RM's and vassalizations)
for (GenericObject alliance : root.getChild("globaldata").getChildren("alliance")) {
alliance.getList("participant").replace(oldTag, newTag);
}
// This is the most involved part: Change the tag in all wars and all warscores.
GenericObject score;
for (GenericObject war : root.getChild("globaldata").getChildren("war")) {
war.getChild("attackers").getList("participant").replace(oldTag, newTag);
war.getChild("defenders").getList("participant").replace(oldTag, newTag);
score = war.getChild("attackerscore");
if (score.containsChild(oldTag))
score.getChild(oldTag).name = newTag;
for (GenericObject s : score.children)
if (s.containsChild(oldTag))
s.getChild(oldTag).name = newTag;
score = war.getChild("defenderscore");
if (score.containsChild(oldTag))
score.getChild(oldTag).name = newTag;
for (GenericObject s : score.children)
if (s.containsChild(oldTag))
s.getChild(oldTag).name = newTag;
}
}
public static void main(String[] args) {
EU2Scenario scenario = openEU2Scenario();
System.out.println("Forces:");
System.out.format("%12s %12s %14s\n", "Land", "Naval", "Population");
System.out.format("%8.3f %8.3f %10.3f\n", scenario.getTotalLandForces(), scenario.getTotalSeaForces(), scenario.getTotalPopulation());
}
}