While your solution works if you extends the Faction to hold the Relations it has the problem of each relation being specified twice.
First you specify that the relation from Humans to Elfs is neutral, and then you also specify that the relation from Elfs to Humans is also neutral, this leads room for a problem where the relations are different depending on the point of view (unless that's what you're going for, it would mean some interesting game mechanics).
One way to fix this in the way you've implemented this is check both relations and return the "worst" one;
public enum Faction {
/*
* Position 1 = Humans
* Position 2 = Elves
* Position 3 = Dwarves
* Position 4 = Orcs
* Position 5 = Undead
* Position 6 = Trolls
* ....
*/
Human(Relations.Friendly/*Humans*/, Relations.Neutral/*Elves*/, Relations.Neutral/*Dwarves*/, Relations.Neutral/*Orcs*/, Relations.Hostile/*Undead*/, Relations.Hostile/*Trolls*/),
Elf(Relations.Neutral, Relations.Friendly, Relations.Neutral, Relations.Neutral, Relations.Hostile, Relations.Hostile),
Dwarf(Relations.Neutral, Relations.Neutral, Relations.Friendly, Relations.Neutral, Relations.Hostile, Relations.Hostile),
Orc(Relations.Neutral, Relations.Neutral, Relations.Neutral, Relations.Friendly, Relations.Hostile, Relations.Friendly),
Undead(Relations.Hostile, Relations.Hostile, Relations.Hostile, Relations.Hostile, Relations.Friendly, Relations.Hostile),
Troll(Relations.Hostile, Relations.Hostile, Relations.Hostile,Relations.Friendly, Relations.Hostile, Relations.Friendly);
public final Relations[] relations;
Faction(Relations... relations) {
this.relations = relations;
}
}
public enum Relations {
Hostile,
Neutral,
Friendly
}
public class FactionHandler {
public Relations getRelations(Faction faction1, Faction faction2) {
Relations relations1to2 = faction1.relations[faction2.ordinal()];
Relations relations2to1 = faction2.relations[faction1.ordinal()];
return relations1to2.ordinal() < relations2to1.ordinal() ? relations1to2 : relations2to1;
}
public boolean checkIfHostile(Faction faction1, Faction faction2) {
return getRelations(faction1, faction2) == Relations.Hostile;
}
}
If you want to avoid having that problem, and if you relations can change during the game you might want to store the Relations in a Map keyed on the Faction,Faction pair.
A simplified version of this (without error handling for you forgetting to set a Relation for a specific pair) could look like this;
public enum Faction {
Humans,
Elves,
Dwarves,
Orcs,
Undead,
Trolls
}
public enum Relations {
Hostile,
Neutral,
Friendly
}
public class FactionPair {
private final Faction factionA;
private final Faction factionB;
public FactionPair(Faction factionA, Faction factionB) {
// This makes sure that if you do
// new FactionPair(Humans, Orcs)
// or
// new FactionPair(Orcs, Humans)
// they both end up the same.
this.factionA = factionA.ordinal() < factionB.ordinal() ? factionA : factionB;
this.factionB = factionA.ordinal() < factionB.ordinal() ? factionB : factionA;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof FactionPair) {
FactionPair other = (FactionPair)obj;
return other.factionA.equals(factionA) && other.factionB.equals(factionB);
}
else
return false;
}
@Override
public int hashCode() {
return factionA.hashCode() ^ factionB.hashCode();
}
}
public class FactionHandler {
private final Map<FactionPair, Relations> map = new HashMap<FactionPair, Relations>();
public void setRelations(Faction factionA, Faction factionB, Relations relations) {
map.put(new FactionPair(factionA, factionB), relations);
}
public void isHostile(Faction factionA, Faction factionB) {
return map.get(new FactionPair(factionA, factionB));
}
}
You would then set your relations like this;
FactionHandler factionHandler = new FactionHandler();
factionHandler.setRelations(Faction.Humans, Factions.Orcs, Relations.Hostile);
bool areOrsHostileTowardsHumans = factionHandler.isHostile(Factions.Orcs, Factions.Humans);