Feature improvement: automatic deck submissions now add lands sensibly (#10159)

* Make automatic deck submissions use sensible land suggestions

* Cover edge case of no colored mana symbols among cards in deck

* Add comments

* Get minimum deck size from deck validator
This commit is contained in:
xenohedron 2023-04-28 10:59:24 -04:00 committed by GitHub
parent d1f6bd1301
commit 761663c63c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 87 additions and 73 deletions

View file

@ -6,8 +6,8 @@ import mage.game.result.ResultProtos.TourneyPlayerProto;
import mage.game.result.ResultProtos.TourneyQuitStatus;
import mage.players.Player;
import mage.players.PlayerType;
import mage.util.DeckBuildUtils;
import mage.util.TournamentUtil;
import java.util.Set;
/**
@ -91,7 +91,7 @@ public class TournamentPlayer {
public boolean updateDeck(Deck deck) {
// Check if the cards included in the deck are the same as in the original deck
boolean validDeck = (getDeck().getDeckCompleteHashCode() == deck.getDeckCompleteHashCode());
if (validDeck == false) {
if (!validDeck) {
// Clear the deck so the player cheating looses the game
deck.getCards().clear();
deck.getSideboard().clear();
@ -100,26 +100,22 @@ public class TournamentPlayer {
return validDeck;
}
public Deck generateDeck() {
// user passed to submit deck in time
// all all cards to deck
deck.getCards().addAll(deck.getSideboard());
deck.getSideboard().clear();
// add lands to deck
int landsPerType = 7;
if (deck.getCards().size() >= 90) {
landsPerType = 14;
public Deck generateDeck(int minDeckSize) {
/*
If user fails to submit deck on time, submit deck as is if meets minimum size,
else add basic lands per suggested land counts
*/
if (deck.getCards().size() < minDeckSize) {
int[] lands = DeckBuildUtils.landCountSuggestion(minDeckSize, deck.getCards());
Set<String> landSets = TournamentUtil.getLandSetCodeForDeckSets(deck.getExpansionSetCodes());
deck.getCards().addAll(TournamentUtil.getLands("Plains", lands[0], landSets));
deck.getCards().addAll(TournamentUtil.getLands("Island", lands[1], landSets));
deck.getCards().addAll(TournamentUtil.getLands("Swamp", lands[2], landSets));
deck.getCards().addAll(TournamentUtil.getLands("Mountain", lands[3], landSets));
deck.getCards().addAll(TournamentUtil.getLands("Forest", lands[4], landSets));
}
Set<String> landSets = TournamentUtil.getLandSetCodeForDeckSets(deck.getExpansionSetCodes());
deck.getCards().addAll(TournamentUtil.getLands("Mountain", landsPerType, landSets));
deck.getCards().addAll(TournamentUtil.getLands("Plains", landsPerType, landSets));
deck.getCards().addAll(TournamentUtil.getLands("Swamp", landsPerType, landSets));
deck.getCards().addAll(TournamentUtil.getLands("Forest", landsPerType, landSets));
deck.getCards().addAll(TournamentUtil.getLands("Island", landsPerType, landSets));
this.doneConstructing = true;
this.setState(TournamentPlayerState.WAITING);
return deck;
}

View file

@ -0,0 +1,59 @@
package mage.util;
import mage.cards.Card;
import java.util.Set;
public final class DeckBuildUtils {
public static int[] landCountSuggestion(int deckSize, Set<Card> deckList) {
/*
Returns the number of basic lands suggested to complete a deck
as an array of five ints: plains, islands, swamps, mountains, forests
Total number of lands always sufficient to reach deckSize
*/
int plains = 0, islands = 0, swamps = 0, mountains = 0, forests = 0;
int landsNeeded = deckSize - deckList.size();
if (landsNeeded > 0) {
int white = 0, blue = 0, black = 0, red = 0, green = 0;
// Rudimentary algorithm that simply counts number of cards with each mana symbol
for (Card cd : deckList) {
for (String s : cd.getManaCostSymbols()) {
if (s.contains("W")) white++;
if (s.contains("U")) blue++;
if (s.contains("B")) black++;
if (s.contains("R")) red++;
if (s.contains("G")) green++;
}
}
int total = white + blue + black + red + green;
// If no colored mana symbols, distribute evenly
if (total == 0) {
total = 5; white = 1; blue = 1; black = 1; red = 1;
}
plains = Math.round(landsNeeded * ((float) white / (float) total));
total -= white;
landsNeeded -= plains;
islands = Math.round(landsNeeded * ((float) blue / (float) total));
total -= blue;
landsNeeded -= islands;
swamps = Math.round(landsNeeded * ((float) black / (float) total));
total -= black;
landsNeeded -= swamps;
mountains = Math.round(landsNeeded * ((float) red / (float) total));
landsNeeded -= mountains;
forests = landsNeeded;
}
return new int[] {plains, islands, swamps, mountains, forests};
}
// Hide constructor - not to be instantiated
private DeckBuildUtils() {
}
}