package com.galvarez.ttw.model;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import com.artemis.ComponentMapper;
import com.artemis.Entity;
import com.artemis.annotations.Wire;
import com.artemis.systems.VoidEntitySystem;
import com.badlogic.gdx.utils.ObjectFloatMap;
import com.galvarez.ttw.model.DiplomaticSystem.State;
import com.galvarez.ttw.model.components.ArmyCommand;
import com.galvarez.ttw.model.components.Diplomacy;
import com.galvarez.ttw.model.components.Discoveries;
import com.galvarez.ttw.model.components.InfluenceSource;
import com.galvarez.ttw.model.components.Policies;
import com.galvarez.ttw.model.map.Terrain;
@Wire
public final class EffectsSystem extends VoidEntitySystem {
private ComponentMapper<Policies> policies;
private ComponentMapper<ArmyCommand> armies;
private ComponentMapper<Discoveries> discoveries;
private ComponentMapper<Diplomacy> diplomacies;
private ComponentMapper<InfluenceSource> influences;
private final class TerrainEffect implements Effect<Number> {
private final Terrain terrain;
public TerrainEffect(Terrain t) {
this.terrain = t;
}
@Override
public void apply(Number value, Entity empire, boolean revert) {
InfluenceSource source = influences.get(empire);
int delta = value.intValue();
Integer current = source.modifiers.terrainBonus.get(terrain);
if (revert)
source.modifiers.terrainBonus.put(terrain, current == null ? 0 : current - delta);
else
source.modifiers.terrainBonus.put(terrain, current == null ? delta : current + delta);
}
@Override
public void addFactionsScores(ObjectFloatMap<Faction> scores, Number value) {
float delta = value.intValue();
scores.getAndIncrement(Faction.MILITARY, 0, delta / 2f);
scores.getAndIncrement(Faction.ECONOMIC, 0, delta);
}
@Override
public String toString(Number value) {
int i = value.intValue();
return terrain.getDesc() + (i > 0 ? ": +" : " ") + i;
}
}
private final class StabilityEffect implements Effect<Number> {
@Override
public void apply(Number value, Entity empire, boolean revert) {
Policies p = policies.get(empire);
if (revert) {
p.stabilityGrowth -= value.intValue();
p.stabilityMax -= value.intValue();
} else {
p.stabilityGrowth += value.intValue();
p.stabilityMax += value.intValue();
}
}
@Override
public void addFactionsScores(ObjectFloatMap<Faction> scores, Number value) {
float delta = value.intValue();
scores.getAndIncrement(Faction.ECONOMIC, 0, delta / 2f);
scores.getAndIncrement(Faction.CULTURAL, 0, delta);
}
@Override
public String toString(Number value) {
int i = value.intValue();
return (i > 0 ? "stability: +" : "stability: ") + i;
}
}
private final class MilitaryEffect implements Effect<Number> {
@Override
public void apply(Number value, Entity empire, boolean revert) {
ArmyCommand army = armies.get(empire);
int delta = 2 * value.intValue();
if (revert)
army.militaryPower -= delta;
else
army.militaryPower += delta;
}
@Override
public void addFactionsScores(ObjectFloatMap<Faction> scores, Number value) {
float delta = value.intValue();
scores.getAndIncrement(Faction.MILITARY, 0, delta * 3f);
scores.getAndIncrement(Faction.CULTURAL, 0, -delta * 3f);
}
@Override
public String toString(Number value) {
int delta = 2 * value.intValue();
return (delta > 0 ? "military power: +" : "military power: ") + delta;
}
}
private final class DiplomacyEffect implements Effect<String> {
@Override
public void apply(String value, Entity empire, boolean revert) {
// cannot revert that one
Diplomacy diplomacy = diplomacies.get(empire);
diplomacy.knownStates.add(State.valueOf(value));
}
@Override
public void addFactionsScores(ObjectFloatMap<Faction> scores, String value) {
scores.getAndIncrement(Faction.MILITARY, 0, 3f);
scores.getAndIncrement(Faction.ECONOMIC, 0, 1f);
scores.getAndIncrement(Faction.CULTURAL, 0, 0.5f);
}
@Override
public String toString(String value) {
return "diplomacy: " + value;
}
}
private final class DiscoveryEffect implements Effect<Number> {
@Override
public void apply(Number value, Entity empire, boolean revert) {
Discoveries d = discoveries.get(empire);
if (revert)
d.progressPerTurn -= value.intValue();
else
d.progressPerTurn += value.intValue();
}
@Override
public void addFactionsScores(ObjectFloatMap<Faction> scores, Number value) {
float delta = value.intValue();
scores.getAndIncrement(Faction.CULTURAL, 0, delta * 2);
}
@Override
public String toString(Number value) {
int i = value.intValue();
return (i > 0 ? "discovery: +" : "discovery: ") + i;
}
}
private final class GrowthEffect implements Effect<Number> {
@Override
public void apply(Number value, Entity empire, boolean revert) {
InfluenceSource source = influences.get(empire);
if (revert)
source.growth -= value.intValue();
else
source.growth += value.intValue();
}
@Override
public void addFactionsScores(ObjectFloatMap<Faction> scores, Number value) {
float delta = value.intValue();
scores.getAndIncrement(Faction.ECONOMIC, 0, delta * 2);
scores.getAndIncrement(Faction.CULTURAL, 0, delta / 2);
}
@Override
public String toString(Number value) {
int i = value.intValue();
return (i > 0 ? "growth: +" : "growth: ") + (i / 10f) + "%/turn";
}
}
private final class HealthEffect implements Effect<Number> {
@Override
public void apply(Number value, Entity empire, boolean revert) {
InfluenceSource source = influences.get(empire);
if (revert)
source.health -= value.intValue();
else
source.health += value.intValue();
}
@Override
public void addFactionsScores(ObjectFloatMap<Faction> scores, Number value) {
float delta = value.intValue();
scores.getAndIncrement(Faction.ECONOMIC, 0, delta * 2);
scores.getAndIncrement(Faction.CULTURAL, 0, delta / 2);
}
@Override
public String toString(Number value) {
int i = value.intValue();
return (i > 0 ? "health: +" : "health: ") + i;
}
}
private interface Effect<V> {
void apply(V value, Entity empire, boolean revert);
void addFactionsScores(ObjectFloatMap<Faction> scores, V value);
String toString(V value);
}
private final Map<String, Effect<?>> effects = new HashMap<>();
{
effects.put("stability", new StabilityEffect());
effects.put("discovery", new DiscoveryEffect());
effects.put("growth", new GrowthEffect());
effects.put("health", new HealthEffect());
effects.put("diplomacy", new DiplomacyEffect());
effects.put("militaryPower", new MilitaryEffect());
for (Terrain t : Terrain.values())
effects.put(t.name(), new TerrainEffect(t));
}
public EffectsSystem() {
}
@Override
protected void processSystem() {
// nothing to do, called by other systems to add and remove effects
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public void apply(Map<String, Object> effectsMap, Entity empire, boolean revert) {
for (Entry<String, Object> e : effectsMap.entrySet()) {
Effect effect = effects.get(e.getKey());
effect.apply(e.getValue(), empire, revert);
}
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public List<String> toString(Map<String, Object> effectsMap) {
List<String> list = new ArrayList<>();
for (Entry<String, Object> e : effectsMap.entrySet()) {
Effect effect = effects.get(e.getKey());
list.add(effect.toString(e.getValue()));
}
return list;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public ObjectFloatMap<Faction> getFactionsScores(Map<String, Object> effectsMap) {
ObjectFloatMap<Faction> scores = new ObjectFloatMap<>(Faction.values().length);
for (Entry<String, Object> effect : effectsMap.entrySet()) {
Effect e = effects.get(effect.getKey());
e.addFactionsScores(scores, effect.getValue());
}
return scores;
}
}