mirror of
https://github.com/correl/mage.git
synced 2024-11-25 11:09:53 +00:00
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:
parent
d1f6bd1301
commit
761663c63c
4 changed files with 87 additions and 73 deletions
|
@ -1,6 +1,5 @@
|
||||||
package mage.client.dialog;
|
package mage.client.dialog;
|
||||||
|
|
||||||
import mage.Mana;
|
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
import mage.cards.FrameStyle;
|
import mage.cards.FrameStyle;
|
||||||
import mage.cards.decks.Deck;
|
import mage.cards.decks.Deck;
|
||||||
|
@ -10,6 +9,7 @@ import mage.client.constants.Constants.DeckEditorMode;
|
||||||
import mage.client.util.gui.FastSearchUtil;
|
import mage.client.util.gui.FastSearchUtil;
|
||||||
import mage.constants.Rarity;
|
import mage.constants.Rarity;
|
||||||
import mage.util.RandomUtil;
|
import mage.util.RandomUtil;
|
||||||
|
import mage.util.DeckBuildUtils;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
import org.mage.card.arcane.ManaSymbols;
|
import org.mage.card.arcane.ManaSymbols;
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@ import javax.swing.*;
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
|
||||||
|
@ -471,57 +470,13 @@ public class AddLandDialog extends MageDialog {
|
||||||
}//GEN-LAST:event_btnSetFastSearchActionPerformed
|
}//GEN-LAST:event_btnSetFastSearchActionPerformed
|
||||||
|
|
||||||
private void autoAddLands() {
|
private void autoAddLands() {
|
||||||
int red = 0;
|
int deckSize = ((Number) spnDeckSize.getValue()).intValue();
|
||||||
int green = 0;
|
int[] lands = DeckBuildUtils.landCountSuggestion(deckSize, deck.getCards());
|
||||||
int black = 0;
|
spnPlains.setValue(lands[0]);
|
||||||
int blue = 0;
|
spnIsland.setValue(lands[1]);
|
||||||
int white = 0;
|
spnSwamp.setValue(lands[2]);
|
||||||
Set<Card> cards = deck.getCards();
|
spnMountain.setValue(lands[3]);
|
||||||
int land_number = ((Number) spnDeckSize.getValue()).intValue() - cards.size();
|
spnForest.setValue(lands[4]);
|
||||||
if (land_number < 0) {
|
|
||||||
land_number = 0;
|
|
||||||
}
|
|
||||||
for (Card cd : cards) {
|
|
||||||
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 = red + green + black + blue + white;
|
|
||||||
|
|
||||||
int redcards = 0;
|
|
||||||
int greencards = 0;
|
|
||||||
int blackcards = 0;
|
|
||||||
int bluecards = 0;
|
|
||||||
int whitecards = 0;
|
|
||||||
if (total > 0) {
|
|
||||||
redcards = Math.round(land_number * ((float) red / (float) total));
|
|
||||||
total -= red;
|
|
||||||
land_number -= redcards;
|
|
||||||
|
|
||||||
greencards = Math.round(land_number * ((float) green / (float) total));
|
|
||||||
total -= green;
|
|
||||||
land_number -= greencards;
|
|
||||||
|
|
||||||
blackcards = Math.round(land_number * ((float) black / (float) total));
|
|
||||||
total -= black;
|
|
||||||
land_number -= blackcards;
|
|
||||||
|
|
||||||
bluecards = Math.round(land_number * ((float) blue / (float) total));
|
|
||||||
total -= blue;
|
|
||||||
land_number -= bluecards;
|
|
||||||
|
|
||||||
whitecards = land_number;
|
|
||||||
}
|
|
||||||
|
|
||||||
spnMountain.setValue(redcards);
|
|
||||||
spnForest.setValue(greencards);
|
|
||||||
spnSwamp.setValue(blackcards);
|
|
||||||
spnIsland.setValue(bluecards);
|
|
||||||
spnPlains.setValue(whitecards);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
|
|
|
@ -2,6 +2,8 @@ package mage.server.tournament;
|
||||||
|
|
||||||
import mage.MageException;
|
import mage.MageException;
|
||||||
import mage.cards.decks.Deck;
|
import mage.cards.decks.Deck;
|
||||||
|
import mage.cards.decks.DeckValidator;
|
||||||
|
import mage.cards.decks.DeckValidatorFactory;
|
||||||
import mage.constants.TableState;
|
import mage.constants.TableState;
|
||||||
import mage.constants.TournamentPlayerState;
|
import mage.constants.TournamentPlayerState;
|
||||||
import mage.game.GameException;
|
import mage.game.GameException;
|
||||||
|
@ -333,7 +335,9 @@ public class TournamentController {
|
||||||
if (userPlayerMap.containsKey(userId)) {
|
if (userPlayerMap.containsKey(userId)) {
|
||||||
TournamentPlayer tournamentPlayer = tournament.getPlayer(userPlayerMap.get(userId));
|
TournamentPlayer tournamentPlayer = tournament.getPlayer(userPlayerMap.get(userId));
|
||||||
if (tournamentPlayer.getDeck() != null) {
|
if (tournamentPlayer.getDeck() != null) {
|
||||||
tournament.autoSubmit(userPlayerMap.get(userId), tournamentPlayer.generateDeck());
|
DeckValidator deckValidator = DeckValidatorFactory.instance.createDeckValidator(tournament.getOptions().getMatchOptions().getDeckType());
|
||||||
|
int deckMinSize = deckValidator != null ? deckValidator.getDeckMinSize() : 40;
|
||||||
|
tournament.autoSubmit(userPlayerMap.get(userId), tournamentPlayer.generateDeck(deckMinSize));
|
||||||
} else {
|
} else {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
managerFactory.userManager().getUser(userId).ifPresent(user
|
managerFactory.userManager().getUser(userId).ifPresent(user
|
||||||
|
|
|
@ -6,8 +6,8 @@ import mage.game.result.ResultProtos.TourneyPlayerProto;
|
||||||
import mage.game.result.ResultProtos.TourneyQuitStatus;
|
import mage.game.result.ResultProtos.TourneyQuitStatus;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.players.PlayerType;
|
import mage.players.PlayerType;
|
||||||
|
import mage.util.DeckBuildUtils;
|
||||||
import mage.util.TournamentUtil;
|
import mage.util.TournamentUtil;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -91,7 +91,7 @@ public class TournamentPlayer {
|
||||||
public boolean updateDeck(Deck deck) {
|
public boolean updateDeck(Deck deck) {
|
||||||
// Check if the cards included in the deck are the same as in the original deck
|
// Check if the cards included in the deck are the same as in the original deck
|
||||||
boolean validDeck = (getDeck().getDeckCompleteHashCode() == deck.getDeckCompleteHashCode());
|
boolean validDeck = (getDeck().getDeckCompleteHashCode() == deck.getDeckCompleteHashCode());
|
||||||
if (validDeck == false) {
|
if (!validDeck) {
|
||||||
// Clear the deck so the player cheating looses the game
|
// Clear the deck so the player cheating looses the game
|
||||||
deck.getCards().clear();
|
deck.getCards().clear();
|
||||||
deck.getSideboard().clear();
|
deck.getSideboard().clear();
|
||||||
|
@ -100,26 +100,22 @@ public class TournamentPlayer {
|
||||||
return validDeck;
|
return validDeck;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Deck generateDeck() {
|
public Deck generateDeck(int minDeckSize) {
|
||||||
// user passed to submit deck in time
|
/*
|
||||||
// all all cards to deck
|
If user fails to submit deck on time, submit deck as is if meets minimum size,
|
||||||
deck.getCards().addAll(deck.getSideboard());
|
else add basic lands per suggested land counts
|
||||||
deck.getSideboard().clear();
|
*/
|
||||||
// add lands to deck
|
if (deck.getCards().size() < minDeckSize) {
|
||||||
int landsPerType = 7;
|
int[] lands = DeckBuildUtils.landCountSuggestion(minDeckSize, deck.getCards());
|
||||||
if (deck.getCards().size() >= 90) {
|
Set<String> landSets = TournamentUtil.getLandSetCodeForDeckSets(deck.getExpansionSetCodes());
|
||||||
landsPerType = 14;
|
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.doneConstructing = true;
|
||||||
this.setState(TournamentPlayerState.WAITING);
|
this.setState(TournamentPlayerState.WAITING);
|
||||||
|
|
||||||
return deck;
|
return deck;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
59
Mage/src/main/java/mage/util/DeckBuildUtils.java
Normal file
59
Mage/src/main/java/mage/util/DeckBuildUtils.java
Normal 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() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue