mirror of
https://github.com/magefree/mage.git
synced 2026-01-26 21:29:17 -08:00
Merge origin/master
This commit is contained in:
commit
42112622d3
21 changed files with 463 additions and 115 deletions
|
|
@ -193,6 +193,7 @@ public class DeckGenerator {
|
|||
Random random = new Random();
|
||||
int count = 0;
|
||||
int reservesAdded = 0;
|
||||
boolean added;
|
||||
if (retrievedCount > 0 && retrievedCount >= spellCount) {
|
||||
int tries = 0;
|
||||
while (count < spellCount) {
|
||||
|
|
@ -208,9 +209,10 @@ public class DeckGenerator {
|
|||
count++;
|
||||
}
|
||||
} else {
|
||||
if (reservesAdded < genPool.getDeckSize() / 2) {
|
||||
genPool.tryAddReserve(card, cardCMC);
|
||||
reservesAdded++;
|
||||
if (reservesAdded < (genPool.getDeckSize() / 2)) {
|
||||
added = genPool.tryAddReserve(card, cardCMC);
|
||||
if(added)
|
||||
reservesAdded++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,8 @@ import java.awt.*;
|
|||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.util.UUID;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -53,10 +54,12 @@ public class DeckGeneratorDialog {
|
|||
private static JComboBox cbDeckSize;
|
||||
private static JButton btnGenerate, btnCancel;
|
||||
private static JCheckBox cArtifacts, cSingleton, cNonBasicLands;
|
||||
private static SimpleDateFormat dateFormat;
|
||||
|
||||
public DeckGeneratorDialog()
|
||||
{
|
||||
initDialog();
|
||||
dateFormat = new SimpleDateFormat("dd-MM-yyyy-hh-mm-ss-SSS");
|
||||
}
|
||||
|
||||
private void initDialog() {
|
||||
|
|
@ -172,14 +175,17 @@ public class DeckGeneratorDialog {
|
|||
for (ActionListener al: btnCancel.getActionListeners()) {
|
||||
btnCancel.removeActionListener(al);
|
||||
}
|
||||
//deck = null;
|
||||
}
|
||||
|
||||
public String saveDeck(Deck deck) {
|
||||
try {
|
||||
File tmp = File.createTempFile("tempDeck" + UUID.randomUUID().toString(), ".dck");
|
||||
// Random directory through the system property to avoid random numeric string attached to temp files.
|
||||
String tempDir = System.getProperty("java.io.tmpdir");
|
||||
// Generated deck has a nice unique name which corresponds to the timestamp at which it was created.
|
||||
String deckName = "Generated-Deck-" + dateFormat.format( new Date());
|
||||
File tmp = new File(tempDir + File.separator + deckName + ".dck");
|
||||
tmp.createNewFile();
|
||||
deck.setName("Generated-Deck-" + UUID.randomUUID());
|
||||
deck.setName(deckName);
|
||||
Sets.saveDeck(tmp.getAbsolutePath(), deck.getDeckCardLists());
|
||||
DeckGeneratorDialog.cleanUp();
|
||||
return tmp.getAbsolutePath();
|
||||
|
|
|
|||
|
|
@ -176,13 +176,15 @@ public class DeckGeneratorPool
|
|||
* @param card the card to add
|
||||
* @param cardCMC the converted mana cost of the card
|
||||
*/
|
||||
public void tryAddReserve(Card card, int cardCMC) {
|
||||
public boolean tryAddReserve(Card card, int cardCMC) {
|
||||
// Only cards with CMC < 7 and don't already exist in the deck
|
||||
// can be added to our reserve pool as not to overwhelm the curve
|
||||
// with high CMC cards and duplicates.
|
||||
if(cardCMC < 7 && getCardCount(card.getName()) == 0) {
|
||||
this.reserveSpells.add(card);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -386,13 +388,13 @@ public class DeckGeneratorPool
|
|||
List<Card> spellsToAdd = new ArrayList<>(spellsNeeded);
|
||||
|
||||
// Initial reservoir
|
||||
for(int i = 0; i < spellsNeeded-1; i++)
|
||||
for(int i = 0; i < spellsNeeded; i++)
|
||||
spellsToAdd.add(reserveSpells.get(i));
|
||||
|
||||
for(int j = spellsNeeded+1; j < reserveSpells.size()-1; j++) {
|
||||
int index = random.nextInt(j);
|
||||
Card randomCard = reserveSpells.get(index);
|
||||
if (index < j && isValidSpellCard(randomCard)) {
|
||||
for(int i = spellsNeeded+1; i < reserveSpells.size()-1; i++) {
|
||||
int j = random.nextInt(i);
|
||||
Card randomCard = reserveSpells.get(j);
|
||||
if (isValidSpellCard(randomCard) && j < spellsToAdd.size()) {
|
||||
spellsToAdd.set(j, randomCard);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -138,16 +138,10 @@ public class SimulatedPlayer2 extends ComputerPlayer {
|
|||
options = optimizeOptions(game, options, ability);
|
||||
if (options.isEmpty()) {
|
||||
allActions.add(ability);
|
||||
// simulateAction(game, previousActions, ability);
|
||||
} else {
|
||||
// ExecutorService simulationExecutor = Executors.newFixedThreadPool(4);
|
||||
for (Ability option : options) {
|
||||
allActions.add(option);
|
||||
// SimulationWorker worker = new SimulationWorker(game, this, previousActions, option);
|
||||
// simulationExecutor.submit(worker);
|
||||
}
|
||||
// simulationExecutor.shutdown();
|
||||
// while(!simulationExecutor.isTerminated()) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
|
|
@ -20,12 +20,11 @@
|
|||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.player.ai;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -40,9 +39,9 @@ import mage.game.permanent.Permanent;
|
|||
public class Attackers extends TreeMap<Integer, List<Permanent>> {
|
||||
|
||||
public List<Permanent> getAttackers() {
|
||||
List<Permanent> attackers = new ArrayList<Permanent>();
|
||||
for (List<Permanent> l: this.values()) {
|
||||
for (Permanent permanent: l) {
|
||||
List<Permanent> attackers = new ArrayList<>();
|
||||
for (List<Permanent> l : this.values()) {
|
||||
for (Permanent permanent : l) {
|
||||
attackers.add(permanent);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,9 +47,8 @@ public class DeployToTheFront extends CardImpl {
|
|||
super(ownerId, 6, "Deploy to the Front", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{5}{W}{W}");
|
||||
this.expansionSetCode = "C14";
|
||||
|
||||
|
||||
// Put X 1/1 white Soldier creature tokens onto the battlefield, where X is the number of creatures on the battlefield.
|
||||
Effect effect = new CreateTokenEffect(new SoldierToken("C14"), new PermanentsOnBattlefieldCount(new FilterCreaturePermanent("the number of creatures on the battlefield")));
|
||||
Effect effect = new CreateTokenEffect(new SoldierToken(), new PermanentsOnBattlefieldCount(new FilterCreaturePermanent("the number of creatures on the battlefield")));
|
||||
effect.setText("Put X 1/1 white Soldier creature tokens onto the battlefield, where X is the number of creatures on the battlefield");
|
||||
this.getSpellAbility().addEffect(effect);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,6 @@ public class FirstResponse extends CardImpl {
|
|||
super(ownerId, 12, "First Response", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}");
|
||||
this.expansionSetCode = "M15";
|
||||
|
||||
|
||||
// At the beginning of each upkeep, if you lost life last turn, put a 1/1 white Soldier creature token onto the battlefield.
|
||||
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new FirstResponseEffect(), TargetController.ANY, false), new PlayerLostLifeWatcher());
|
||||
|
||||
|
|
@ -88,7 +87,7 @@ class FirstResponseEffect extends OneShotEffect {
|
|||
PlayerLostLifeWatcher watcher = (PlayerLostLifeWatcher) game.getState().getWatchers().get("PlayerLostLifeWatcher");
|
||||
if (watcher != null) {
|
||||
if (watcher.getLiveLostLastTurn(source.getControllerId()) > 0) {
|
||||
return new CreateTokenEffect(new SoldierToken("M15")).apply(game, source);
|
||||
return new CreateTokenEffect(new SoldierToken()).apply(game, source);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ class WheelOfSunAndMoonEffect extends ReplacementEffectImpl {
|
|||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == EventType.ZONE_CHANGE;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
||||
|
|
@ -110,8 +110,8 @@ class WheelOfSunAndMoonEffect extends ReplacementEffectImpl {
|
|||
Card card = game.getCard(event.getTargetId());
|
||||
if (card != null) {
|
||||
Permanent enchantment = game.getPermanent(source.getSourceId());
|
||||
if (enchantment != null && enchantment.getAttachedTo() != null &&
|
||||
card.getOwnerId().equals(enchantment.getAttachedTo())) {
|
||||
if (enchantment != null && enchantment.getAttachedTo() != null
|
||||
&& card.getOwnerId().equals(enchantment.getAttachedTo())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -128,7 +128,7 @@ class WheelOfSunAndMoonEffect extends ReplacementEffectImpl {
|
|||
if (card != null) {
|
||||
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
||||
Cards cards = new CardsImpl(card);
|
||||
controller.revealCards(sourceObject.getName(), cards, game);
|
||||
controller.revealCards(sourceObject.getIdName(), cards, game);
|
||||
controller.moveCardToLibraryWithInfo(card, source.getSourceId(), game, zEvent.getFromZone(), false, true);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,6 @@ public class SigilOfSleep extends CardImpl {
|
|||
this.expansionSetCode = "UDS";
|
||||
this.subtype.add("Aura");
|
||||
|
||||
|
||||
// Enchant creature
|
||||
TargetPermanent auraTarget = new TargetCreaturePermanent();
|
||||
this.getSpellAbility().addTarget(auraTarget);
|
||||
|
|
@ -67,7 +66,7 @@ public class SigilOfSleep extends CardImpl {
|
|||
// Whenever enchanted creature deals damage to a player, return target creature that player controls to its owner's hand.
|
||||
Effect effect = new ReturnToHandTargetEffect();
|
||||
effect.setText("return target creature that player controls to its owner's hand");
|
||||
ability = new DealsDamageToAPlayerAttachedTriggeredAbility(effect, "enchanted", false, true);
|
||||
ability = new DealsDamageToAPlayerAttachedTriggeredAbility(effect, "enchanted", false, true, false);
|
||||
this.addAbility(ability);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package org.mage.test.AI.basic;
|
||||
|
||||
import org.mage.test.serverside.base.CardTestPlayerBaseAI;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class CombatTest extends CardTestPlayerBaseAI {
|
||||
|
||||
/*
|
||||
* Combat is not integrated yet in the CardTestPlayerBaseAI
|
||||
*
|
||||
* TODO: Modify CardTestPlayerBaseAI to use the AI combat acting
|
||||
*
|
||||
* Tests to create:
|
||||
* AI is not attacking if opponent has a creature that can't block
|
||||
* AI is not blocking also if able if the damage the attacker will do will kill the AI
|
||||
* AI is not able to block with two or more creatures one attacking creature to kill it. Even if none of the AI creatures will die
|
||||
* AI attacks with a flyer even if opponent has a bigger flyer that kills AI
|
||||
*/
|
||||
}
|
||||
|
|
@ -29,6 +29,8 @@ package org.mage.test.AI.basic;
|
|||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.Filter;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBaseAI;
|
||||
|
||||
|
|
@ -88,8 +90,10 @@ public class TargetsAreChosenTest extends CardTestPlayerBaseAI {
|
|||
// Destroy two target artifacts.
|
||||
addCard(Zone.HAND, playerA, "Rack and Ruin"); // {2}{R}
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Mox Emerald", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Juggernaut");
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Mox Emerald", 4);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Juggernaut", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Composite Golem", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mox Emerald", 1);
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
|
@ -99,4 +103,123 @@ public class TargetsAreChosenTest extends CardTestPlayerBaseAI {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Target only opponent creatures to tap
|
||||
*/
|
||||
@Test
|
||||
public void testFrostBreath1() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
|
||||
// Tap up to two target creatures. Those creatures don't untap during their controller's next untap step.
|
||||
addCard(Zone.HAND, playerA, "Frost Breath"); // {2}{U}
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Juggernaut", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Composite Golem", 1);
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, "Frost Breath", 1);
|
||||
assertTapped("Silvercoat Lion", true);
|
||||
assertTapped("Pillarfield Ox", true);
|
||||
assertTapped("Juggernaut", false);
|
||||
assertTapped("Composite Golem", false);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Target only opponent creatures also if more targets are possible
|
||||
*/
|
||||
@Test
|
||||
public void testFrostBreath2() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
|
||||
// Tap up to two target creatures. Those creatures don't untap during their controller's next untap step.
|
||||
addCard(Zone.HAND, playerA, "Frost Breath"); // {2}{U}
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Juggernaut", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Composite Golem", 1);
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, "Frost Breath", 1);
|
||||
assertTapped("Pillarfield Ox", true);
|
||||
assertTapped("Juggernaut", false);
|
||||
assertTapped("Composite Golem", false);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Spell is not cast if only own creatures can be targeted
|
||||
*/
|
||||
@Test
|
||||
public void testFrostBreath3() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
|
||||
// Tap up to two target creatures. Those creatures don't untap during their controller's next untap step.
|
||||
addCard(Zone.HAND, playerA, "Frost Breath"); // {2}{U}
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Juggernaut", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Composite Golem", 1);
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, "Frost Breath", 0);
|
||||
assertTapped("Juggernaut", false);
|
||||
assertTapped("Composite Golem", false);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testNefashu() {
|
||||
// Whenever Nefashu attacks, up to five target creatures each get -1/-1 until end of turn.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Nefashu"); // 5/3
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Bellows Lizard", 5);
|
||||
// Whenever a creature an opponent controls dies, put a +1/+1 counter on Malakir Cullblade.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Malakir Cullblade", 5);
|
||||
|
||||
attack(3, playerA, "Nefashu");
|
||||
setStopAt(3, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerB, "Bellows Lizard", 5);
|
||||
assertPowerToughness(playerA, "Malakir Cullblade", 6, 6, Filter.ComparisonScope.All);
|
||||
assertTapped("Nefashu", true);
|
||||
|
||||
assertLife(playerB, 15);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that AI counters creatire spell
|
||||
*/
|
||||
@Test
|
||||
@Ignore // counter spells don't seem to be cast by AI
|
||||
public void testRewind() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
|
||||
// Counter target spell. Untap up to four lands.
|
||||
addCard(Zone.HAND, playerA, "Rewind"); // {2}{U}{U}
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Plains", 4);
|
||||
// Renown 1 (When this creature deals combat damage to a player, if it isn't renowned, put a +1/+1 counter on it and it becomes renowned.)
|
||||
// {W}{W}: Tap target creature.
|
||||
addCard(Zone.HAND, playerB, "Kytheon's Irregulars", 1);
|
||||
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Kytheon's Irregulars");
|
||||
setStopAt(2, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerB, "Kytheon's Irregulars", 0);
|
||||
assertGraveyardCount(playerB, "Kytheon's Irregulars", 1);
|
||||
assertGraveyardCount(playerA, "Rewind", 1);
|
||||
|
||||
assertTappedCount("Island", true, 0);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,16 @@
|
|||
package org.mage.test.utils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.mana.ManaCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.mana.*;
|
||||
import mage.abilities.mana.BasicManaAbility;
|
||||
import mage.abilities.mana.BlackManaAbility;
|
||||
import mage.abilities.mana.ManaAbility;
|
||||
import mage.abilities.mana.RedManaAbility;
|
||||
import mage.abilities.mana.WhiteManaAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.repository.CardRepository;
|
||||
import mage.util.ManaUtil;
|
||||
|
|
@ -11,10 +18,6 @@ import org.junit.Assert;
|
|||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author noxx
|
||||
*/
|
||||
|
|
@ -47,7 +50,7 @@ public class ManaUtilTest extends CardTestPlayerBase {
|
|||
testManaToPayVsLand("{2}", "Cavern of Souls", 2, 2); // can't auto choose to pay
|
||||
|
||||
testManaToPayVsLand("{2}", "Eldrazi Temple", 2, 2); // can't auto choose to pay
|
||||
|
||||
|
||||
// hybrid mana
|
||||
testManaToPayVsLand("{W/R}{W/R}{W/R}", "Sacred Foundry", 2, 1); // auto choose for hybrid mana: choose any
|
||||
testManaToPayVsLand("{R}{W/R}", "Sacred Foundry", 2, RedManaAbility.class); // auto choose for hybrid mana: we should choose {R}
|
||||
|
|
@ -79,18 +82,20 @@ public class ManaUtilTest extends CardTestPlayerBase {
|
|||
Assert.assertEquals("{R}{R}", ManaUtil.condenseManaCostString("{R}{R}"));
|
||||
Assert.assertEquals("{U}", ManaUtil.condenseManaCostString("{U}"));
|
||||
Assert.assertEquals("{2}", ManaUtil.condenseManaCostString("{2}"));
|
||||
Assert.assertEquals("", ManaUtil.condenseManaCostString(""));
|
||||
Assert.assertEquals("", ManaUtil.condenseManaCostString("{}"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Common way to test ManaUtil.tryToAutoPay
|
||||
*
|
||||
* We get all mana abilities, then try to auto pay and compare to expected1 and expected2 params.
|
||||
* We get all mana abilities, then try to auto pay and compare to expected1
|
||||
* and expected2 params.
|
||||
*
|
||||
* @param manaToPay Mana that should be paid using land.
|
||||
* @param landName Land to use as mana producer.
|
||||
* @param expected1 The amount of mana abilities the land should have.
|
||||
* @param expected2 The amount of mana abilities that ManaUtil.tryToAutoPay should be returned after optimization.
|
||||
* @param expected2 The amount of mana abilities that ManaUtil.tryToAutoPay
|
||||
* should be returned after optimization.
|
||||
*/
|
||||
private void testManaToPayVsLand(String manaToPay, String landName, int expected1, int expected2) {
|
||||
ManaCost unpaid = new ManaCostsImpl(manaToPay);
|
||||
|
|
@ -100,19 +105,20 @@ public class ManaUtilTest extends CardTestPlayerBase {
|
|||
HashMap<UUID, ManaAbility> useableAbilities = getManaAbilities(card);
|
||||
Assert.assertEquals(expected1, useableAbilities.size());
|
||||
|
||||
useableAbilities = ManaUtil.tryToAutoPay(unpaid, (LinkedHashMap<UUID, ManaAbility>)useableAbilities);
|
||||
useableAbilities = ManaUtil.tryToAutoPay(unpaid, (LinkedHashMap<UUID, ManaAbility>) useableAbilities);
|
||||
Assert.assertEquals(expected2, useableAbilities.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Another way to test ManaUtil.tryToAutoPay
|
||||
* Here we also check what ability was auto chosen
|
||||
* Another way to test ManaUtil.tryToAutoPay Here we also check what ability
|
||||
* was auto chosen
|
||||
*
|
||||
* N.B. This method can be used ONLY if we have one ability left that auto choose mode!
|
||||
* That's why we assert the following:
|
||||
* Assert.assertEquals(1, useableAbilities.size());
|
||||
* N.B. This method can be used ONLY if we have one ability left that auto
|
||||
* choose mode! That's why we assert the following: Assert.assertEquals(1,
|
||||
* useableAbilities.size());
|
||||
*
|
||||
* We get all mana abilities, then try to auto pay and compare to expected1 and expected2 params.
|
||||
* We get all mana abilities, then try to auto pay and compare to expected1
|
||||
* and expected2 params.
|
||||
*
|
||||
* @param manaToPay Mana that should be paid using land.
|
||||
* @param landName Land to use as mana producer.
|
||||
|
|
@ -127,7 +133,7 @@ public class ManaUtilTest extends CardTestPlayerBase {
|
|||
HashMap<UUID, ManaAbility> useableAbilities = getManaAbilities(card);
|
||||
Assert.assertEquals(expected1, useableAbilities.size());
|
||||
|
||||
useableAbilities = ManaUtil.tryToAutoPay(unpaid, (LinkedHashMap<UUID, ManaAbility>)useableAbilities);
|
||||
useableAbilities = ManaUtil.tryToAutoPay(unpaid, (LinkedHashMap<UUID, ManaAbility>) useableAbilities);
|
||||
Assert.assertEquals(1, useableAbilities.size());
|
||||
ManaAbility ability = useableAbilities.values().iterator().next();
|
||||
Assert.assertTrue("Wrong mana ability has been chosen", expectedChosen.isInstance(ability));
|
||||
|
|
@ -141,13 +147,13 @@ public class ManaUtilTest extends CardTestPlayerBase {
|
|||
*/
|
||||
private HashMap<UUID, ManaAbility> getManaAbilities(Card card) {
|
||||
HashMap<UUID, ManaAbility> useableAbilities = new LinkedHashMap<>();
|
||||
for (Ability ability: card.getAbilities()) {
|
||||
for (Ability ability : card.getAbilities()) {
|
||||
if (ability instanceof ManaAbility) {
|
||||
ability.newId(); // we need to assign id manually as we are not in game
|
||||
useableAbilities.put(ability.getId(), (ManaAbility)ability);
|
||||
useableAbilities.put(ability.getId(), (ManaAbility) ability);
|
||||
}
|
||||
}
|
||||
return useableAbilities;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,9 @@
|
|||
*/
|
||||
package mage.game.permanent.token;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import mage.MageInt;
|
||||
import mage.constants.CardType;
|
||||
|
|
@ -38,9 +40,15 @@ import mage.constants.CardType;
|
|||
*/
|
||||
public class BeastToken extends Token {
|
||||
|
||||
final static private List<String> tokenImageSets = new ArrayList<>();
|
||||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("C14", "LRW", "M15", "M14", "DDL", "M13", "M12"));
|
||||
}
|
||||
|
||||
public BeastToken() {
|
||||
super("Beast", "3/3 green Beast creature token");
|
||||
availableImageSetCodes.addAll(Arrays.asList("C14", "LRW", "M15", "M14", "DDL", "M13", "M12"));
|
||||
availableImageSetCodes = tokenImageSets;
|
||||
cardType.add(CardType.CREATURE);
|
||||
color.setGreen(true);
|
||||
subtype.add("Beast");
|
||||
|
|
@ -59,4 +67,13 @@ public class BeastToken extends Token {
|
|||
this.setTokenType(2);
|
||||
}
|
||||
}
|
||||
|
||||
public BeastToken(final BeastToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeastToken copy() {
|
||||
return new BeastToken(this); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,9 @@
|
|||
*/
|
||||
package mage.game.permanent.token;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import mage.MageInt;
|
||||
import mage.constants.CardType;
|
||||
|
||||
|
|
@ -37,9 +39,15 @@ import mage.constants.CardType;
|
|||
*/
|
||||
public class ElfToken extends Token {
|
||||
|
||||
final static private List<String> tokenImageSets = new ArrayList<>();
|
||||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("C14", "SHM", "EVG", "LRW", "ORI"));
|
||||
}
|
||||
|
||||
public ElfToken() {
|
||||
super("Elf Warrior", "1/1 green Elf Warrior creature token");
|
||||
availableImageSetCodes.addAll(Arrays.asList("C14", "SHM", "EVG", "LRW", "ORI"));
|
||||
availableImageSetCodes = tokenImageSets;
|
||||
cardType.add(CardType.CREATURE);
|
||||
color.setGreen(true);
|
||||
subtype.add("Elf");
|
||||
|
|
@ -55,4 +63,13 @@ public class ElfToken extends Token {
|
|||
this.setTokenType(1);
|
||||
}
|
||||
}
|
||||
|
||||
public ElfToken(final ElfToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElfToken copy() {
|
||||
return new ElfToken(this); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ public class GoblinToken extends Token {
|
|||
|
||||
public GoblinToken() {
|
||||
super("Goblin", "1/1 red Goblin creature token");
|
||||
availableImageSetCodes.addAll(Arrays.asList("SOM", "M10", "C14", "KTK", "EVG", "DTK", "ORI"));
|
||||
availableImageSetCodes.addAll(Arrays.asList("SOM", "M10", "C14", "KTK", "EVG", "DTK", "ORI", "DDG"));
|
||||
|
||||
cardType.add(CardType.CREATURE);
|
||||
subtype.add("Goblin");
|
||||
|
|
|
|||
|
|
@ -1,33 +1,36 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.game.permanent.token;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import mage.MageInt;
|
||||
import mage.constants.CardType;
|
||||
|
||||
|
|
@ -37,18 +40,38 @@ import mage.constants.CardType;
|
|||
*/
|
||||
public class SoldierToken extends Token {
|
||||
|
||||
public SoldierToken() {
|
||||
this("10E");
|
||||
final static private List<String> tokenImageSets = new ArrayList<>();
|
||||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("10E", "M15", "C14", "ORI", "ALA", "DDF", "THS", "M12", "M13", "MM2", "MMA", "RTR", "SOM"));
|
||||
}
|
||||
public SoldierToken(String setCode) {
|
||||
|
||||
public SoldierToken() {
|
||||
super("Soldier", "1/1 white Soldier creature token");
|
||||
this.setOriginalExpansionSetCode(setCode);
|
||||
availableImageSetCodes = tokenImageSets;
|
||||
|
||||
cardType.add(CardType.CREATURE);
|
||||
color.setWhite(true);
|
||||
subtype.add("Soldier");
|
||||
power = new MageInt(1);
|
||||
toughness = new MageInt(1);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExpansionSetCodeForImage(String code) {
|
||||
super.setExpansionSetCodeForImage(code);
|
||||
if (getOriginalExpansionSetCode().equals("THS")) {
|
||||
this.setTokenType(new Random().nextInt(2) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
public SoldierToken(final SoldierToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SoldierToken copy() {
|
||||
return new SoldierToken(this); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@
|
|||
*/
|
||||
package mage.game.permanent.token;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import mage.MageInt;
|
||||
import mage.constants.CardType;
|
||||
|
||||
|
|
@ -36,12 +39,15 @@ import mage.constants.CardType;
|
|||
*/
|
||||
public class SquirrelToken extends Token {
|
||||
|
||||
public SquirrelToken() {
|
||||
this("CNS");
|
||||
final static private List<String> tokenImageSets = new ArrayList<>();
|
||||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("CNS"));
|
||||
}
|
||||
public SquirrelToken(String setCode) {
|
||||
|
||||
public SquirrelToken() {
|
||||
super("Squirrel", "1/1 green Squirrel creature token");
|
||||
setOriginalExpansionSetCode(setCode);
|
||||
availableImageSetCodes = tokenImageSets;
|
||||
cardType.add(CardType.CREATURE);
|
||||
subtype.add("Squirrel");
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,9 @@
|
|||
*/
|
||||
package mage.game.permanent.token;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
|
|
@ -39,9 +41,15 @@ import mage.constants.CardType;
|
|||
*/
|
||||
public class ThopterColorlessToken extends Token {
|
||||
|
||||
final static private List<String> tokenImageSets = new ArrayList<>();
|
||||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("EXO", "ORI"));
|
||||
}
|
||||
|
||||
public ThopterColorlessToken() {
|
||||
super("Thopter", "1/1 colorless Thopter artifact creature token with flying");
|
||||
availableImageSetCodes.addAll(Arrays.asList("EXO", "ORI"));
|
||||
availableImageSetCodes = tokenImageSets;
|
||||
cardType.add(CardType.ARTIFACT);
|
||||
cardType.add(CardType.CREATURE);
|
||||
subtype.add("Thopter");
|
||||
|
|
@ -58,4 +66,14 @@ public class ThopterColorlessToken extends Token {
|
|||
this.setTokenType(new Random().nextInt(2) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
public ThopterColorlessToken(final ThopterColorlessToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThopterColorlessToken copy() {
|
||||
return new ThopterColorlessToken(this); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ public class Token extends MageObjectImpl {
|
|||
this.originalCardNumber = token.originalCardNumber;
|
||||
this.originalExpansionSetCode = token.originalExpansionSetCode;
|
||||
this.copySourceCard = token.copySourceCard; // will never be changed
|
||||
this.availableImageSetCodes = token.availableImageSetCodes;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
|
|
@ -216,6 +217,10 @@ public class Token extends MageObjectImpl {
|
|||
} else {
|
||||
setOriginalExpansionSetCode(availableImageSetCodes.get(new Random().nextInt(availableImageSetCodes.size())));
|
||||
}
|
||||
} else {
|
||||
if (getOriginalExpansionSetCode() == null || getOriginalExpansionSetCode().isEmpty()) {
|
||||
setOriginalExpansionSetCode(code);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,9 @@
|
|||
*/
|
||||
package mage.game.permanent.token;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import mage.MageInt;
|
||||
import mage.constants.CardType;
|
||||
|
|
@ -38,9 +40,15 @@ import mage.constants.CardType;
|
|||
*/
|
||||
public class ZombieToken extends Token {
|
||||
|
||||
final static private List<String> tokenImageSets = new ArrayList<>();
|
||||
|
||||
static {
|
||||
tokenImageSets.addAll(Arrays.asList("10E", "M10", "M11", "M12", "M13", "M14", "M15", "MBS", "ALA", "ISD", "C14", "CNS", "MMA", "BNG", "KTK", "DTK", "ORI"));
|
||||
}
|
||||
|
||||
public ZombieToken() {
|
||||
super("Zombie", "2/2 black Zombie creature token");
|
||||
availableImageSetCodes.addAll(Arrays.asList("10E", "M10", "M11", "M12", "M13", "M14", "M15", "MBS", "ALA", "ISD", "C14", "CNS", "MMA", "BNG", "KTK", "DTK", "ORI"));
|
||||
availableImageSetCodes = tokenImageSets;
|
||||
cardType.add(CardType.CREATURE);
|
||||
color.setBlack(true);
|
||||
subtype.add("Zombie");
|
||||
|
|
@ -56,4 +64,12 @@ public class ZombieToken extends Token {
|
|||
}
|
||||
}
|
||||
|
||||
public ZombieToken(final ZombieToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZombieToken copy() {
|
||||
return new ZombieToken(this); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -376,26 +376,94 @@ public abstract class TargetImpl implements Target {
|
|||
return targets.size() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all possible different target combinations
|
||||
*
|
||||
* @param source
|
||||
* @param game
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<? extends TargetImpl> getTargetOptions(Ability source, Game game) {
|
||||
List<TargetImpl> options = new ArrayList<>();
|
||||
Set<UUID> possibleTargets = possibleTargets(source.getSourceId(), source.getControllerId(), game);
|
||||
List<UUID> possibleTargets = new ArrayList<>();
|
||||
possibleTargets.addAll(possibleTargets(source.getSourceId(), source.getControllerId(), game));
|
||||
possibleTargets.removeAll(getTargets());
|
||||
Iterator<UUID> it = possibleTargets.iterator();
|
||||
while (it.hasNext()) {
|
||||
UUID targetId = it.next();
|
||||
|
||||
// get the length of the array
|
||||
// e.g. for {'A','B','C','D'} => N = 4
|
||||
int N = possibleTargets.size();
|
||||
// not enough targets, return no option
|
||||
if (N < getNumberOfTargets()) {
|
||||
return options;
|
||||
}
|
||||
// not target but that's allowed, return one empty option
|
||||
if (N == 0) {
|
||||
TargetImpl target = this.copy();
|
||||
target.clearChosen();
|
||||
target.addTarget(targetId, source, game, true);
|
||||
if (!target.isChosen()) {
|
||||
Iterator<UUID> it2 = possibleTargets.iterator();
|
||||
while (it2.hasNext() && !target.isChosen()) {
|
||||
UUID nextTargetId = it2.next();
|
||||
target.addTarget(nextTargetId, source, game, true);
|
||||
}
|
||||
options.add(target);
|
||||
return options;
|
||||
}
|
||||
int maxK = getMaxNumberOfTargets() - getTargets().size();
|
||||
if (maxK > 5) { // Prevent endless iteration with targets set to INTEGER.maxvalue
|
||||
maxK = 5;
|
||||
if (N > 10) { // not more than 252 combinations
|
||||
maxK = 4;
|
||||
}
|
||||
if (target.isChosen()) {
|
||||
options.add(target);
|
||||
if (N > 20) { // not more than 4845 combinations
|
||||
maxK = 3;
|
||||
}
|
||||
}
|
||||
if (N < maxK) { // less possible targets than the maximum allowed so reduce the max
|
||||
maxK = N;
|
||||
}
|
||||
int minK = getNumberOfTargets();
|
||||
if (getNumberOfTargets() == 0) { // add option without targets if possible
|
||||
TargetImpl target = this.copy();
|
||||
options.add(target);
|
||||
minK = 1;
|
||||
}
|
||||
for (int K = minK; K <= maxK; K++) {
|
||||
// get the combination by index
|
||||
// e.g. 01 --> AB , 23 --> CD
|
||||
int combination[] = new int[K];
|
||||
|
||||
// position of current index
|
||||
// if (r = 1) r*
|
||||
// index ==> 0 | 1 | 2
|
||||
// element ==> A | B | C
|
||||
int r = 0;
|
||||
int index = 0;
|
||||
|
||||
while (r >= 0) {
|
||||
// possible indexes for 1st position "r=0" are "0,1,2" --> "A,B,C"
|
||||
// possible indexes for 2nd position "r=1" are "1,2,3" --> "B,C,D"
|
||||
|
||||
// for r = 0 ==> index < (4+ (0 - 2)) = 2
|
||||
if (index <= (N + (r - K))) {
|
||||
combination[r] = index;
|
||||
|
||||
// if we are at the last position print and increase the index
|
||||
if (r == K - 1) {
|
||||
//add the new target option
|
||||
TargetImpl target = this.copy();
|
||||
for (int i = 0; i < combination.length; i++) {
|
||||
target.addTarget(possibleTargets.get(combination[i]), source, game, true);
|
||||
}
|
||||
options.add(target);
|
||||
index++;
|
||||
} else {
|
||||
// select index for next position
|
||||
index = combination[r] + 1;
|
||||
r++;
|
||||
}
|
||||
} else {
|
||||
r--;
|
||||
if (r > 0) {
|
||||
index = combination[r] + 1;
|
||||
} else {
|
||||
index = combination[0] + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return options;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue