- Added scheme: Choose Your Champion and supporting AI logic.

- Added a basic board state evaluation that returns the player from a list with the best rating. Could probably be improved with better weightings.
This commit is contained in:
moomarc
2013-07-19 14:51:49 +00:00
parent 355ab88ba9
commit 6a6050dea2
6 changed files with 75 additions and 2 deletions

1
.gitattributes vendored
View File

@@ -1811,6 +1811,7 @@ res/cardsfolder/c/choking_fumes.txt svneol=native#text/plain
res/cardsfolder/c/choking_sands.txt svneol=native#text/plain res/cardsfolder/c/choking_sands.txt svneol=native#text/plain
res/cardsfolder/c/choking_tethers.txt svneol=native#text/plain res/cardsfolder/c/choking_tethers.txt svneol=native#text/plain
res/cardsfolder/c/choking_vines.txt -text res/cardsfolder/c/choking_vines.txt -text
res/cardsfolder/c/choose_your_champion.txt -text
res/cardsfolder/c/chord_of_calling.txt -text res/cardsfolder/c/chord_of_calling.txt -text
res/cardsfolder/c/chorus_of_might.txt -text res/cardsfolder/c/chorus_of_might.txt -text
res/cardsfolder/c/chorus_of_woe.txt svneol=native#text/plain res/cardsfolder/c/chorus_of_woe.txt svneol=native#text/plain

View File

@@ -0,0 +1,10 @@
Name:Choose Your Champion
ManaCost:no cost
Types:Scheme
T:Mode$ SetInMotion | ValidCard$ Card.Self | Execute$ ChooseChampion | TriggerZones$ Command | TriggerDescription$ When you set this scheme in motion, target opponent chooses a player. Until your next turn, only you and the chosen player can cast spells and attack with creatures.
SVar:ChooseChampion:AB$ ChoosePlayer | Cost$ 0 | ValidTgts$ Opponent | Choices$ Player | AILogic$ BestAllyBoardPosition | SubAbility$ PrepChamps
SVar:PrepChamps:DB$ Effect | RememberObjects$ ChosenPlayer,You | Name$ Choose Your Champion Scheme | Duration$ UntilYourNextTurn | StaticAbilities$ RestrictAttackers,RestrictCasting
SVar:RestrictAttackers:Mode$ Continuous | Affected$ Creature.nonRememberedPlayerCtrl | AddHiddenKeyword$ CARDNAME can't attack. | EffectZone$ Command | Description$ Until your next turn, only you and the chosen player can attack with creatures.
SVar:RestrictCasting:Mode$ CantBeCast | ValidCard$ Card | Caster$ Player.IsNotRemembered | EffectZone$ Command | Description$ Until your next turn, only you and the chosen player can cast spells.
SVar:Picture:http://www.cardforge.org/fpics/lq_schemes/choose_your_champion.jpg
Oracle:When you set this scheme in motion, target opponent chooses a player. Until your next turn, only you and the chosen player can cast spells and attack with creatures.

View File

@@ -5386,6 +5386,17 @@ public class Card extends GameEntity implements Comparable<Card> {
} }
} }
} }
} else if (property.startsWith("nonRememberedPlayerCtrl")) {
if (source.getRemembered().isEmpty()) {
final Card newCard = game.getCardState(source);
if (newCard.getRemembered().contains(this.getController())) {
return false;
}
}
if (source.getRemembered().contains(this.getController())) {
return false;
}
} else if (property.equals("TargetedPlayerCtrl")) { } else if (property.equals("TargetedPlayerCtrl")) {
for (final SpellAbility sa : source.getCharacteristics().getSpellAbility()) { for (final SpellAbility sa : source.getCharacteristics().getSpellAbility()) {
final SpellAbility saTargeting = sa.getSATargetingPlayer(); final SpellAbility saTargeting = sa.getSATargetingPlayer();

View File

@@ -4,6 +4,7 @@ import java.util.List;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.game.ai.ComputerUtilCard;
import forge.game.player.Player; import forge.game.player.Player;
public class ChoosePlayerAi extends SpellAbilityAi { public class ChoosePlayerAi extends SpellAbilityAi {
@@ -45,6 +46,16 @@ public class ChoosePlayerAi extends SpellAbilityAi {
} }
} else if ("Pump".equals(sa.getParam("AILogic"))) { } else if ("Pump".equals(sa.getParam("AILogic"))) {
chosen = choices.contains(ai) ? ai : choices.get(0); chosen = choices.contains(ai) ? ai : choices.get(0);
} else if ("BestAllyBoardPosition".equals(sa.getParam("AILogic"))) {
List<Player> prefChoices = choices;
prefChoices.removeAll(ai.getOpponents());
if (!prefChoices.isEmpty()) {
chosen = ComputerUtilCard.evaluateBoardPosition(prefChoices);
}
if (chosen == null) {
System.out.println("No good curse choices. Picking first available: " + choices.get(0));
chosen = choices.get(0);
}
} else { } else {
System.out.println("Default player choice logic."); System.out.println("Default player choice logic.");
chosen = choices.contains(ai) ? ai : choices.get(0); chosen = choices.contains(ai) ? ai : choices.get(0);

View File

@@ -169,10 +169,12 @@ public class EffectEffect extends SpellAbilityEffect {
// Set Remembered // Set Remembered
if (effectRemembered != null) { if (effectRemembered != null) {
for (final Object o : AbilityUtils.getDefinedObjects(hostCard, effectRemembered, sa)) { for (final String rem : effectRemembered.split(",")) {
for (final Object o : AbilityUtils.getDefinedObjects(hostCard, rem, sa)) {
eff.addRemembered(o); eff.addRemembered(o);
} }
} }
}
// Set Imprinted // Set Imprinted
if (effectImprinted != null) { if (effectImprinted != null) {

View File

@@ -8,6 +8,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import org.apache.commons.lang3.tuple.MutablePair; import org.apache.commons.lang3.tuple.MutablePair;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
@@ -31,6 +32,7 @@ import forge.deck.Deck;
import forge.deck.DeckSection; import forge.deck.DeckSection;
import forge.game.combat.Combat; import forge.game.combat.Combat;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.zone.ZoneType;
import forge.item.PaperCard; import forge.item.PaperCard;
import forge.util.Aggregates; import forge.util.Aggregates;
@@ -820,4 +822,40 @@ public class ComputerUtilCard {
} }
}; };
/**
* <p>
* evaluateBoardPosition.
* </p>
*
* @param listToEvaluate
* a list of players to evaluate.
* @return a Player.
*/
public static Player evaluateBoardPosition(final List<Player> listToEvaluate) {
Player bestBoardPosition = listToEvaluate.get(0);
int bestBoardRating = 0;
for (final Player p : listToEvaluate) {
int pRating = p.getLife() * 3;
pRating += p.getLandsInPlay().size() * 2;
for (final Card c : p.getCardsIn(ZoneType.Battlefield)) {
pRating += ComputerUtilCard.evaluateCreature(c) / 3;
}
if (p.getCardsIn(ZoneType.Library).size() < 3) {
pRating /= 5;
}
System.out.println("Board position evaluation for " + p + ": " + pRating);
if (pRating > bestBoardRating) {
bestBoardRating = pRating;
bestBoardPosition = p;
}
}
return bestBoardPosition;
}
} }