package magic.model.choice;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import magic.exception.UndoClickedException;
import magic.model.IUIGameController;
import magic.model.MagicGame;
import magic.model.MagicPermanent;
import magic.model.MagicPermanentList;
import magic.model.MagicPermanentState;
import magic.model.MagicPlayer;
import magic.model.MagicRandom;
import magic.model.MagicSource;
import magic.model.event.MagicEvent;
public class MagicDeclareBlockersChoice extends MagicChoice {
// translatable UI text (prefix with _S).
private static final String _S1 = "Declare blockers.";
private static final String _S_BLOCKER_MESSAGE = "Click on a creature to declare as blocker or remove from combat.|Press {f} to continue.";
private static final String _S_ATTACKER_MESSAGE = "Click on an attacking creature to declare as blocker.";
private static final String _S_CONTINUE_MESSAGE = "Press {f} to continue.";
private static final MagicDeclareBlockersChoice INSTANCE=new MagicDeclareBlockersChoice();
private MagicDeclareBlockersChoice() {
super(_S1);
}
@Override
Collection<Object> getArtificialOptions(final MagicGame game,final MagicEvent event) {
final MagicDeclareBlockersResultBuilder builder = new MagicDeclareBlockersResultBuilder(game, event.getPlayer(), game.getFastBlocker());
return builder.getResults();
}
/** Builds result and does cleanup for blockers. */
private static void buildResult(final MagicCombatCreatureBuilder builder, final MagicDeclareBlockersResult result) {
for (final MagicCombatCreature attacker : builder.getAttackers()) {
final MagicPermanentList blockers=attacker.permanent.getBlockingCreatures();
if (!blockers.isEmpty()) {
final List<MagicCombatCreature> creatures=new ArrayList<MagicCombatCreature>();
creatures.add(attacker);
for (final MagicPermanent blocker : blockers) {
for (final MagicCombatCreature candidateBlocker : attacker.candidateBlockers) {
if (candidateBlocker.permanent==blocker) {
creatures.add(candidateBlocker);
break;
}
}
blocker.clearState(MagicPermanentState.Blocking);
blocker.setBlockedCreature(MagicPermanent.NONE);
}
attacker.permanent.removeBlockingCreatures();
result.add(creatures.toArray(new MagicCombatCreature[0]));
}
}
}
@Override
public Object[] getPlayerChoiceResults(final IUIGameController controller, final MagicGame game, final MagicEvent event) throws UndoClickedException {
final MagicPlayer player = event.getPlayer();
final MagicSource source = event.getSource();
final MagicDeclareBlockersResult result=new MagicDeclareBlockersResult(0,0);
final MagicCombatCreatureBuilder builder=new MagicCombatCreatureBuilder(game,player.getOpponent(),player);
builder.buildBlockers();
if (!builder.buildBlockableAttackers()&&game.canSkipDeclareBlockersSingleChoice()) {
return new Object[]{result};
}
try {
while (true) {
// Choose blocker.
final Set<MagicPermanent> candidateBlockers=builder.getCandidateBlockers();
controller.focusViewers(-1);
if (candidateBlockers.isEmpty()) {
controller.showMessage(source,_S_CONTINUE_MESSAGE);
} else {
controller.setValidChoices(new HashSet<Object>(candidateBlockers),true);
controller.showMessage(source,_S_BLOCKER_MESSAGE);
}
controller.enableForwardButton();
controller.waitForInput();
controller.clearValidChoices();
if (controller.isActionClicked()) {
break;
}
final MagicPermanent blocker = controller.getChoiceClicked();
// Remove blocker from combat.
if (blocker.isBlocking()) {
final MagicPermanent attacker=blocker.getBlockedCreature();
attacker.removeBlockingCreature(blocker);
if (attacker.getBlockingCreatures().isEmpty()) {
attacker.clearState(MagicPermanentState.Blocked);
}
blocker.setBlockedCreature(MagicPermanent.NONE);
blocker.clearState(MagicPermanentState.Blocking);
// Block an attacker.
} else {
controller.setSourceCardDefinition(blocker);
controller.setValidChoices(new HashSet<Object>(builder.getBlockableAttackers(blocker)),true);
controller.showMessage(blocker,_S_ATTACKER_MESSAGE);
controller.disableActionButton(false);
controller.waitForInput();
controller.setSourceCardDefinition(MagicSource.NONE);
controller.clearValidChoices();
final MagicPermanent attacker = controller.getChoiceClicked();
attacker.addBlockingCreature(blocker);
blocker.setState(MagicPermanentState.Blocking);
blocker.setBlockedCreature(attacker);
}
controller.updateGameView();
}
} finally {
// Cleanup
buildResult(builder,result);
}
game.snapshot();
return new Object[]{result};
}
@Override
public Object[] getSimulationChoiceResult(final MagicGame game, final MagicEvent event) {
final MagicPlayer player = event.getPlayer();
final MagicDeclareBlockersResult result=new MagicDeclareBlockersResult(0,0);
final MagicCombatCreatureBuilder builder=new MagicCombatCreatureBuilder(game,player.getOpponent(),player);
//check if any of the defending creatures can block
if (!builder.buildBlockers()) {
return new Object[]{result};
}
//check if non of the attackers can be blocked
if (!builder.buildBlockableAttackers()) {
return new Object[]{result};
}
final Set<MagicPermanent> blockers = builder.getCandidateBlockers();
for (final MagicPermanent blocker : blockers) {
final MagicPermanent[] attackers = builder.getBlockableAttackers(blocker).toArray(new MagicPermanent[0]);
//choose one of the attackers or don't block
final int idx = MagicRandom.nextRNGInt(attackers.length + 1);
if (idx < attackers.length) {
final MagicPermanent attacker = attackers[idx];
attacker.addBlockingCreature(blocker);
blocker.setState(MagicPermanentState.Blocking);
blocker.setBlockedCreature(attacker);
}
}
buildResult(builder,result);
return new Object[]{result};
}
public static MagicDeclareBlockersChoice getInstance() {
return INSTANCE;
}
}