package games.strategy.triplea.delegate;
import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import games.strategy.engine.data.GameData;
import games.strategy.engine.data.PlayerID;
import games.strategy.engine.message.IRemote;
import games.strategy.triplea.MapSupport;
import games.strategy.triplea.attachments.ICondition;
import games.strategy.triplea.attachments.PlayerAttachment;
import games.strategy.triplea.attachments.TriggerAttachment;
import games.strategy.util.CompositeMatchAnd;
import games.strategy.util.CompositeMatchOr;
import games.strategy.util.Match;
import games.strategy.util.Util;
/**
* Logic for activating tech rolls. This delegate requires the
* TechnologyDelegate to run correctly.
*/
@MapSupport
public class TechActivationDelegate extends BaseTripleADelegate {
private boolean m_needToInitialize = true;
/** Creates new TechActivationDelegate. */
public TechActivationDelegate() {}
/**
* Called before the delegate will run. In this class, this does all the
* work.
*/
@Override
public void start() {
super.start();
final GameData data = getData();
if (!m_needToInitialize) {
return;
}
// Activate techs
final Map<PlayerID, Collection<TechAdvance>> techMap = DelegateFinder.techDelegate(data).getAdvances();
final Collection<TechAdvance> advances = techMap.get(m_player);
if ((advances != null) && (advances.size() > 0)) {
// Start event
m_bridge.getHistoryWriter().startEvent(m_player.getName() + " activating " + advancesAsString(advances));
for (final TechAdvance advance : advances) {
// advance.perform(m_bridge.getPlayerID(), m_bridge, m_data);
TechTracker.addAdvance(m_player, m_bridge, advance);
}
}
// empty
techMap.put(m_player, null);
if (games.strategy.triplea.Properties.getTriggers(data)) {
// First set up a match for what we want to have fire as a default in this delegate. List out as a composite match
// OR.
// use 'null, null' because this is the Default firing location for any trigger that does NOT have 'when' set.
final Match<TriggerAttachment> techActivationDelegateTriggerMatch = new CompositeMatchAnd<>(
TriggerAttachment.availableUses, TriggerAttachment.whenOrDefaultMatch(null, null),
new CompositeMatchOr<TriggerAttachment>(TriggerAttachment.unitPropertyMatch(), TriggerAttachment.techMatch(),
TriggerAttachment.supportMatch()));
// get all possible triggers based on this match.
final HashSet<TriggerAttachment> toFirePossible = TriggerAttachment.collectForAllTriggersMatching(
new HashSet<>(Collections.singleton(m_player)), techActivationDelegateTriggerMatch, m_bridge);
if (!toFirePossible.isEmpty()) {
// get all conditions possibly needed by these triggers, and then test them.
final HashMap<ICondition, Boolean> testedConditions =
TriggerAttachment.collectTestsForAllTriggers(toFirePossible, m_bridge);
// get all triggers that are satisfied based on the tested conditions.
final Set<TriggerAttachment> toFireTestedAndSatisfied = new HashSet<>(
Match.getMatches(toFirePossible, TriggerAttachment.isSatisfiedMatch(testedConditions)));
// now list out individual types to fire, once for each of the matches above.
TriggerAttachment.triggerUnitPropertyChange(toFireTestedAndSatisfied, m_bridge, null, null, true, true, true,
true);
TriggerAttachment.triggerTechChange(toFireTestedAndSatisfied, m_bridge, null, null, true, true, true, true);
TriggerAttachment.triggerSupportChange(toFireTestedAndSatisfied, m_bridge, null, null, true, true, true, true);
}
}
shareTechnology();
m_needToInitialize = false;
}
@Override
public void end() {
super.end();
m_needToInitialize = true;
}
@Override
public boolean delegateCurrentlyRequiresUserInput() {
return false;
}
private void shareTechnology() {
final PlayerAttachment pa = PlayerAttachment.get(m_player);
if (pa == null) {
return;
}
final Collection<PlayerID> shareWith = pa.getShareTechnology();
if (shareWith == null || shareWith.isEmpty()) {
return;
}
final GameData data = getData();
final Collection<TechAdvance> currentAdvances = TechTracker.getCurrentTechAdvances(m_player, data);
for (final PlayerID p : shareWith) {
final Collection<TechAdvance> availableTechs = TechnologyDelegate.getAvailableTechs(p, data);
final Collection<TechAdvance> toGive = Util.intersection(currentAdvances, availableTechs);
if (!toGive.isEmpty()) {
// Start event
m_bridge.getHistoryWriter()
.startEvent(m_player.getName() + " giving technology to " + p.getName() + ": " + advancesAsString(toGive));
for (final TechAdvance advance : toGive) {
TechTracker.addAdvance(p, m_bridge, advance);
}
}
}
}
@Override
public Serializable saveState() {
final TechActivationExtendedDelegateState state = new TechActivationExtendedDelegateState();
state.superState = super.saveState();
state.m_needToInitialize = m_needToInitialize;
return state;
}
@Override
public void loadState(final Serializable state) {
final TechActivationExtendedDelegateState s = (TechActivationExtendedDelegateState) state;
super.loadState(s.superState);
m_needToInitialize = s.m_needToInitialize;
}
// Return string representing all advances in collection
private static String advancesAsString(final Collection<TechAdvance> advances) {
final Iterator<TechAdvance> iter = advances.iterator();
int count = advances.size();
final StringBuilder text = new StringBuilder();
while (iter.hasNext()) {
final TechAdvance advance = iter.next();
text.append(advance.getName());
count--;
if (count > 1) {
text.append(", ");
}
if (count == 1) {
text.append(" and ");
}
}
return text.toString();
}
@Override
public Class<? extends IRemote> getRemoteType() {
return null;
}
}
class TechActivationExtendedDelegateState implements Serializable {
private static final long serialVersionUID = 1742776261442260882L;
Serializable superState;
public boolean m_needToInitialize;
}