Skip to content

Commit

Permalink
Fix for noted types for Volo's journal (#6665)
Browse files Browse the repository at this point in the history
  • Loading branch information
neoFuzz authored Dec 6, 2024
1 parent 95e5b7a commit 6c1f4c7
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 23 deletions.
20 changes: 9 additions & 11 deletions forge-ai/src/main/java/forge/ai/ComputerUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -2544,35 +2544,33 @@ public static String chooseSomeType(Player ai, String kindOfType, SpellAbility s

if (logic.equals("MostProminentOnBattlefield")) {
chosen = ComputerUtilCard.getMostProminentType(game.getCardsIn(ZoneType.Battlefield), valid);
}
else if (logic.equals("MostProminentComputerControls")) {
} else if (logic.equals("MostProminentComputerControls")) {
chosen = ComputerUtilCard.getMostProminentType(ai.getCardsIn(ZoneType.Battlefield), valid);
}
else if (logic.equals("MostProminentComputerControlsOrOwns")) {
} else if (logic.equals("MostProminentComputerControlsOrOwns")) {
CardCollectionView list = ai.getCardsIn(Arrays.asList(ZoneType.Battlefield, ZoneType.Hand));
if (list.isEmpty()) {
list = ai.getCardsIn(Arrays.asList(ZoneType.Library));
}
chosen = ComputerUtilCard.getMostProminentType(list, valid);
}
else if (logic.equals("MostProminentOppControls")) {
} else if (logic.equals("MostProminentOppControls")) {
CardCollection list = ai.getOpponents().getCardsIn(ZoneType.Battlefield);
chosen = ComputerUtilCard.getMostProminentType(list, valid);
if (!CardType.isACreatureType(chosen) || invalidTypes.contains(chosen)) {
list = CardLists.filterControlledBy(game.getCardsInGame(), ai.getOpponents());
chosen = ComputerUtilCard.getMostProminentType(list, valid);
}
}
else if (logic.startsWith("MostProminentInComputerDeck")) {
} else if (logic.startsWith("MostProminentInComputerDeck")) {
boolean includeTokens = !logic.endsWith("NonToken");
chosen = ComputerUtilCard.getMostProminentType(ai.getAllCards(), valid, includeTokens);
}
else if (logic.equals("MostProminentInComputerGraveyard")) {
} else if (logic.equals("MostProminentInComputerGraveyard")) {
chosen = ComputerUtilCard.getMostProminentType(ai.getCardsIn(ZoneType.Graveyard), valid);
}
}

if (!CardType.isACreatureType(chosen) || invalidTypes.contains(chosen)) {
chosen = "Sliver";
chosen = validTypes.size() == 1 ? (String) validTypes.toArray()[0] :
ComputerUtilCard.getMostProminentType(ai.getAllCards(), validTypes, false);
//chosen = "Sliver";
}

} else if (kindOfType.equals("Basic Land")) {
Expand Down
8 changes: 5 additions & 3 deletions forge-ai/src/main/java/forge/ai/ComputerUtilCard.java
Original file line number Diff line number Diff line change
Expand Up @@ -875,12 +875,14 @@ public static String getMostProminentType(final CardCollectionView list, final C
int max = 0;
String maxType = "";

// Iterate through typesInDeck and consider only valid types
for (final Entry<String, Integer> entry : typesInDeck.entrySet()) {
final String type = entry.getKey();

if (max < entry.getValue()) {
max = entry.getValue();
maxType = type;
// consider the types that are in the valid list
if ((valid.isEmpty() || valid.contains(type)) && max < entry.getValue()) {
max = entry.getValue();
maxType = type;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ protected String getStackDescription(SpellAbility sa) {
public void resolve(SpellAbility sa) {
final Card card = sa.getHostCard();
final String type = sa.getParam("Type");
final List<String> invalidTypes = sa.hasParam("InvalidTypes") ? Arrays.asList(sa.getParam("InvalidTypes").split(",")) : new ArrayList<>();
final List<String> invalidTypes = getInvalidTypes(sa);
final List<String> validTypes = new ArrayList<>();
final List<Player> tgtPlayers = getTargetPlayers(sa);
final boolean secret = sa.hasParam("Secretly");
Expand Down Expand Up @@ -154,4 +154,10 @@ public void resolve(SpellAbility sa) {
throw new InvalidParameterException(sa.getHostCard() + "'s ability resulted in no types to choose from");
}
}

private static List<String> getInvalidTypes(SpellAbility sa) {
return sa.hasParam("InvalidTypes") ?
Arrays.asList(sa.getParam("InvalidTypes").split(",")) :
new ArrayList<>();
}
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
package forge.ai.simulation;

import java.util.List;

import org.testng.AssertJUnit;
import org.testng.annotations.Test;

import com.google.common.collect.Lists;

import forge.ai.ComputerUtilAbility;
import forge.card.CardStateName;
import forge.card.MagicColor;
import forge.game.Game;
import forge.game.ability.ApiType;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView;
import forge.game.card.CounterEnumType;
import forge.game.keyword.Keyword;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
import org.testng.AssertJUnit;
import org.testng.annotations.Test;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class GameSimulationTest extends SimulationTest {

Expand Down Expand Up @@ -154,7 +155,7 @@ public void testEnchantedAbilities() {
@Test
public void testEtbTriggers() {
Game game = initAndCreateGame();
Player p0 = game.getPlayers().get(0);
Player p0 = game.getPlayers().get(0);
Player p = game.getPlayers().get(1);
addCard("Black Knight", p);
addCards("Swamp", 5, p);
Expand Down Expand Up @@ -1391,7 +1392,7 @@ public void testDeathsShadow() {
p.setLife(-1, null);
game.getAction().checkStateEffects(true);
assert (deathsShadow.getNetPower() == 13); // on negative life, should
// always be 13/13
// always be 13/13
}

@Test
Expand Down Expand Up @@ -2548,4 +2549,72 @@ public void testBasicSpellFizzling() {
// spell should fizzle so no card was drawn
AssertJUnit.assertEquals(0, game.getPlayers().get(0).getCardsIn(ZoneType.Hand).size());
}

/**
* blah
*/
@Test
public void testVoloJournal() {
Game game = initAndCreateGame();
Player p0 = game.getPlayers().get(0);
Player p = game.getPlayers().get(1);

addCards("Island", 7, p);
addCards("Mountain", 2, p);
addCards("Forest", 2, p);

Card c = addCardToZone("Volo, Itinerant Scholar", p, ZoneType.Hand);
Card[] cards = {
addCardToZone("Cathartic Adept", p, ZoneType.Hand),
addCardToZone("Cathartic Adept", p, ZoneType.Hand),
addCardToZone("Drowner Initiate", p, ZoneType.Hand),
addCardToZone("Atog", p, ZoneType.Hand),
addCardToZone("Atog", p, ZoneType.Hand)
};

game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
game.getAction().checkStateEffects(true);

SpellAbility playVoloSA = c.getFirstSpellAbility();
playVoloSA.setActivatingPlayer(p);

GameSimulator sim = createSimulator(game, p);
sim.simulateSpellAbility(playVoloSA);
Game simGame = sim.getSimulatedGameState();

for (Card card : cards) {
SpellAbility a1 = card.getSpellAbilities().get(0);
a1.setActivatingPlayer(p);
sim.simulateSpellAbility(a1);
}

Player simP = simGame.getPlayer(p.getId());
CardCollectionView btlf = simP.getCardsIn(ZoneType.Battlefield);
List<String> words = List.of(new String[]{"Human", "Wizard", "Atog", "Merfolk"});

for (Card card : btlf) {
if (card.getName().equals("Volo's Journal")) {
// All words are present in the iterable
AssertJUnit.assertTrue(areWordsInIterable(words, card.getNotedTypes()));
}
}
}

protected boolean areWordsInIterable(List<String> words, Iterable<String> iterable) {
// Create a frequency map for the words in the iterable
Map<String, Integer> frequencyMap = new HashMap<>();
for (String item : iterable) {
frequencyMap.put(item, frequencyMap.getOrDefault(item, 0) + 1);
}

// Check if each word in the list appears exactly once
for (String word : words) {
if (frequencyMap.getOrDefault(word, 0) != 1) {
return false; // If the word doesn't appear exactly once, return false
}
}

return true; // All words appear exactly once
}

}

0 comments on commit 6c1f4c7

Please sign in to comment.