Refactor code to make it easier to show rewards for planar conquest games

This commit is contained in:
drdev
2014-12-06 23:52:54 +00:00
parent ce3b8e6c76
commit f7fbdc05dd
10 changed files with 452 additions and 285 deletions

View File

@@ -1,8 +1,17 @@
package forge.interfaces;
import java.util.List;
import forge.assets.FSkinProp;
import forge.item.PaperCard;
public interface IWinLoseView<T extends IButton> {
T getBtnContinue();
T getBtnRestart();
T getBtnQuit();
void hide();
void showRewards(Runnable runnable);
void showCards(String title, List<PaperCard> cards);
void showMessage(String message, String title, FSkinProp icon);
}

View File

@@ -17,11 +17,31 @@
*/
package forge.planarconquest;
import java.util.ArrayList;
import java.util.List;
import com.google.common.base.Predicate;
import com.google.common.eventbus.Subscribe;
import forge.FThreads;
import forge.card.CardRarity;
import forge.card.CardRules;
import forge.card.CardRulesPredicates;
import forge.deck.CardPool;
import forge.deck.Deck;
import forge.game.GameView;
import forge.game.event.GameEvent;
import forge.interfaces.IButton;
import forge.interfaces.IWinLoseView;
import forge.item.PaperCard;
import forge.model.FModel;
import forge.planarconquest.ConquestPlaneData.RegionData;
import forge.planarconquest.ConquestPreferences.CQPref;
import forge.player.GamePlayerUtil;
import forge.util.Aggregates;
import forge.util.Lang;
import forge.util.gui.SGuiChoose;
import forge.util.gui.SOptionPane;
import forge.util.storage.IStorage;
public class ConquestController {
@@ -64,4 +84,299 @@ public class ConquestController {
public void receiveGameEvent(GameEvent ev) { // Receives events only during planar conquest games
}
public void endDay(final IVCommandCenter commandCenter) {
FThreads.invokeInBackgroundThread(new Runnable() {
@Override
public void run() {
//prompt user if any commander hasn't taken an action
final List<ConquestCommander> commanders = model.getCurrentPlaneData().getCommanders();
for (ConquestCommander commander : commanders) {
if (commander.getCurrentDayAction() == null) {
if (!SOptionPane.showConfirmDialog(commander.getName() + " has not taken an action today. End day anyway?", "Action Not Taken", "End Day", "Cancel")) {
return;
}
}
}
//perform all commander actions
for (ConquestCommander commander : commanders) {
switch (commander.getCurrentDayAction()) {
case Attack1:
playGame(commander, 0, false);
break;
case Attack2:
playGame(commander, 1, false);
break;
case Attack3:
playGame(commander, 2, false);
break;
case Defend:
playGame(commander, Aggregates.randomInt(0, 2), true); //defend against random opponent
break;
case Recruit:
if (!recruit(commander)) { return; }
break;
case Study:
if (!study(commander)) { return; }
break;
case Undeploy:
model.getCurrentPlaneData().getRegionData(commander.getDeployedRegion()).setDeployedCommander(null);
break;
default: //remaining actions don't need to do anything more
break;
}
}
//increment day and reset actions, then update UI for new day
FThreads.invokeInEdtLater(new Runnable() {
@Override
public void run() {
model.incrementDay();
for (ConquestCommander commander : commanders) {
commander.setCurrentDayAction(null);
}
commandCenter.updateCurrentDay();
}
});
}
});
}
private void playGame(ConquestCommander commander, int opponentIndex, boolean isHumanDefending) {
RegionData regionData = model.getCurrentPlaneData().getRegionData(commander.getDeployedRegion());
ConquestCommander opponent = regionData.getOpponent(opponentIndex);
//TODO
}
private boolean recruit(ConquestCommander commander) {
boolean bonusCard = Aggregates.randomInt(1, 100) <= FModel.getConquestPreferences().getPrefInt(CQPref.RECRUIT_BONUS_CARD_ODDS);
return awardNewCards(commander.getDeployedRegion().getCardPool().getAllCards(),
commander.getName() + " recruited", "new creature", null, null,
CardRulesPredicates.Presets.IS_CREATURE, bonusCard ? 2 : 1);
}
private boolean study(ConquestCommander commander) {
boolean bonusCard = Aggregates.randomInt(1, 100) <= FModel.getConquestPreferences().getPrefInt(CQPref.STUDY_BONUS_CARD_ODDS);
return awardNewCards(commander.getDeployedRegion().getCardPool().getAllCards(),
commander.getName() + " unlocked", "new spell", null, null,
CardRulesPredicates.Presets.IS_NON_CREATURE_SPELL, bonusCard ? 2 : 1);
}
public void showGameRewards(final GameView game, final IWinLoseView<? extends IButton> view) {
view.getBtnRestart().setVisible(false);
view.getBtnContinue().setVisible(false);
if (game.isMatchWonBy(GamePlayerUtil.getGuiPlayer())) { //TODO: Should this be smarter
view.getBtnQuit().setText("Great!");
//give controller a chance to run remaining logic on a separate thread
view.showRewards(new Runnable() {
@Override
public void run() {
awardWinStreakBonus(view);
awardBooster(view);
}
});
}
else {
view.getBtnQuit().setText("OK");
}
}
public void onGameFinished(final GameView game) {
if (game.isMatchWonBy(GamePlayerUtil.getGuiPlayer())) {
model.addWin();
}
else {
model.addLoss();
}
FModel.getConquest().save();
FModel.getConquestPreferences().save();
}
private void awardWinStreakBonus(final IWinLoseView<? extends IButton> view) {
int currentStreak = model.getCurrentPlaneData().getWinStreakCurrent() + 1;
int mod = currentStreak % 10;
int count = (currentStreak - 1) / 10 + 1; //so on 13th win you get 2 commons, etc.
CardRarity rarity = null;
String typeWon = "";
switch (mod) {
case 3:
rarity = CardRarity.Common;
count = 1;
typeWon = "common";
break;
case 5:
rarity = CardRarity.Uncommon;
count = 1;
typeWon = "uncommon";
break;
case 7:
rarity = CardRarity.Rare;
count = 1;
typeWon = "rare";
break;
case 0: //0 is multiple of 10 win
rarity = CardRarity.MythicRare;
count = 1;
typeWon = "mythic rare";
break;
default:
return;
}
awardNewCards(model.getCurrentPlane().getCardPool().getAllCards(), currentStreak + " game win streak - unlocked", typeWon, rarity, view, null, count);
}
private boolean awardNewCards(Iterable<PaperCard> cardPool, String messagePrefix, String messageSuffix, CardRarity rarity, final IWinLoseView<? extends IButton> view, Predicate<CardRules> pred, int count) {
List<PaperCard> commons = new ArrayList<PaperCard>();
List<PaperCard> uncommons = new ArrayList<PaperCard>();
List<PaperCard> rares = new ArrayList<PaperCard>();
List<PaperCard> mythics = new ArrayList<PaperCard>();
int newCardCount = 0;
for (PaperCard c : cardPool) {
if ((pred == null || pred.apply(c.getRules())) && !model.getCollection().contains(c)) {
switch (c.getRarity()) {
case Common:
commons.add(c);
break;
case Uncommon:
uncommons.add(c);
break;
case Rare:
rares.add(c);
break;
case MythicRare:
mythics.add(c);
break;
default:
break;
}
}
}
newCardCount = commons.size() + uncommons.size() + rares.size() + mythics.size();
if (newCardCount == 0) {
return false;
}
ConquestPreferences prefs = FModel.getConquestPreferences();
int rareThreshold = prefs.getPrefInt(CQPref.BOOSTER_RARES);
int uncommonThreshold = rareThreshold + prefs.getPrefInt(CQPref.BOOSTER_UNCOMMONS);
int cardsPerPack = uncommonThreshold + prefs.getPrefInt(CQPref.BOOSTER_COMMONS);
List<PaperCard> rewardPool = null;
if (rarity != null) {
switch (rarity) {
case Common:
rewardPool = commons;
if (rewardPool.isEmpty()) {
rewardPool = uncommons;
messageSuffix = messageSuffix.replace("common", "uncommon");
if (rewardPool.isEmpty()) {
rewardPool = rares;
messageSuffix = messageSuffix.replace("uncommon", "rare");
if (rewardPool.isEmpty()) {
rewardPool = mythics;
messageSuffix = messageSuffix.replace("rare", "mythic rare");
}
}
}
break;
case Uncommon:
rewardPool = uncommons;
if (rewardPool.isEmpty()) {
rewardPool = commons;
messageSuffix = messageSuffix.replace("uncommon", "common");
if (rewardPool.isEmpty()) {
rewardPool = rares;
messageSuffix = messageSuffix.replace("common", "rare");
if (rewardPool.isEmpty()) {
rewardPool = mythics;
messageSuffix = messageSuffix.replace("rare", "mythic rare");
}
}
}
break;
case Rare:
rewardPool = rares;
if (rewardPool.isEmpty()) {
rewardPool = uncommons;
messageSuffix = messageSuffix.replace("rare", "uncommon");
if (rewardPool.isEmpty()) {
rewardPool = commons;
messageSuffix = messageSuffix.replace("uncommon", "common");
if (rewardPool.isEmpty()) {
rewardPool = mythics;
messageSuffix = messageSuffix.replace("common", "mythic rare");
}
}
}
break;
case MythicRare:
rewardPool = mythics;
if (rewardPool.isEmpty()) {
rewardPool = rares;
messageSuffix = messageSuffix.replace("mythic rare", "rare");
if (rewardPool.isEmpty()) {
rewardPool = uncommons;
messageSuffix = messageSuffix.replace("rare", "uncommon");
if (rewardPool.isEmpty()) {
rewardPool = commons;
messageSuffix = messageSuffix.replace("uncommon", "common");
}
}
}
break;
default:
return false;
}
newCardCount = rewardPool.size();
}
List<PaperCard> rewards = new ArrayList<PaperCard>();
for (int i = 0; i < count; i++) {
//determine which rarity card to get based on pack ratios if no rarity passed in
if (rarity == null) {
int value = Aggregates.randomInt(1, cardsPerPack);
if (value <= rareThreshold) {
if (mythics.size() > 0 && Aggregates.randomInt(1, 8) == 1) {
rewardPool = mythics;
}
else {
rewardPool = rares;
}
}
else if (value <= uncommonThreshold) {
rewardPool = uncommons;
}
else {
rewardPool = commons;
}
if (rewardPool.isEmpty()) { continue; } //if no cards in selected pool, determine random pool again
}
int index = Aggregates.randomInt(0, rewardPool.size() - 1);
rewards.add(rewardPool.remove(index));
if (--newCardCount == 0) {
break; //break out if no new cards remain
}
}
model.getCollection().add(rewards);
String message = messagePrefix + " " + Lang.nounWithAmount(rewards.size(), messageSuffix);
if (view == null) {
SGuiChoose.reveal(message, rewards);
}
else {
view.showCards(message, rewards);
}
return true;
}
private void awardBooster(final IWinLoseView<? extends IButton> view) {
//TODO
}
}

View File

@@ -17,29 +17,14 @@
*/
package forge.planarconquest;
import forge.FThreads;
import forge.card.CardRules;
import forge.card.CardRulesPredicates;
import forge.deck.CardPool;
import forge.deck.Deck;
import forge.item.PaperCard;
import forge.model.FModel;
import forge.planarconquest.ConquestPlane.Region;
import forge.planarconquest.ConquestPlaneData.RegionData;
import forge.planarconquest.ConquestPreferences.CQPref;
import forge.properties.ForgeConstants;
import forge.util.Aggregates;
import forge.util.Lang;
import forge.util.gui.SGuiChoose;
import forge.util.gui.SOptionPane;
import java.io.File;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import com.google.common.base.Predicate;
public final class ConquestData {
/** Holds the latest version of the Conquest Data. */
@@ -93,154 +78,8 @@ public final class ConquestData {
public int getDay() {
return day;
}
public void endDay(final IVCommandCenter base) {
FThreads.invokeInBackgroundThread(new Runnable() {
@Override
public void run() {
//prompt user if any commander hasn't taken an action
final List<ConquestCommander> commanders = getCurrentPlaneData().getCommanders();
for (ConquestCommander commander : commanders) {
if (commander.getCurrentDayAction() == null) {
if (!SOptionPane.showConfirmDialog(commander.getName() + " has not taken an action today. End day anyway?", "Action Not Taken", "End Day", "Cancel")) {
return;
}
}
}
//perform all commander actions
for (ConquestCommander commander : commanders) {
switch (commander.getCurrentDayAction()) {
case Attack1:
playGame(commander, 0, false);
break;
case Attack2:
playGame(commander, 1, false);
break;
case Attack3:
playGame(commander, 2, false);
break;
case Defend:
playGame(commander, Aggregates.randomInt(0, 2), true); //defend against random opponent
break;
case Recruit:
if (!recruit(commander)) { return; }
break;
case Study:
if (!study(commander)) { return; }
break;
case Undeploy:
getCurrentPlaneData().getRegionData(commander.getDeployedRegion()).setDeployedCommander(null);
break;
default: //remaining actions don't need to do anything more
break;
}
}
//increment day and reset actions, then update UI for new day
FThreads.invokeInEdtLater(new Runnable() {
@Override
public void run() {
day++;
for (ConquestCommander commander : commanders) {
commander.setCurrentDayAction(null);
}
base.updateCurrentDay();
}
});
}
});
}
private void playGame(ConquestCommander commander, int opponentIndex, boolean isHumanDefending) {
RegionData regionData = getCurrentPlaneData().getRegionData(commander.getDeployedRegion());
ConquestCommander opponent = regionData.getOpponent(opponentIndex);
//TODO
}
private boolean recruit(ConquestCommander commander) {
boolean bonusCard = Aggregates.randomInt(1, 100) <= FModel.getConquestPreferences().getPrefInt(CQPref.RECRUIT_BONUS_CARD_ODDS);
return rewardNewCards(commander.getDeployedRegion().getCardPool().getAllCards(),
commander.getName() + " recruited", "new creature",
CardRulesPredicates.Presets.IS_CREATURE, bonusCard ? 2 : 1);
}
private boolean study(ConquestCommander commander) {
boolean bonusCard = Aggregates.randomInt(1, 100) <= FModel.getConquestPreferences().getPrefInt(CQPref.STUDY_BONUS_CARD_ODDS);
return rewardNewCards(commander.getDeployedRegion().getCardPool().getAllCards(),
commander.getName() + " unlocked", "new spell",
CardRulesPredicates.Presets.IS_NON_CREATURE_SPELL, bonusCard ? 2 : 1);
}
private boolean rewardNewCards(Iterable<PaperCard> cardPool, String messagePrefix, String messageSuffix, Predicate<CardRules> pred, int count) {
List<PaperCard> commons = new ArrayList<PaperCard>();
List<PaperCard> uncommons = new ArrayList<PaperCard>();
List<PaperCard> rares = new ArrayList<PaperCard>();
List<PaperCard> mythics = new ArrayList<PaperCard>();
int newCardCount = 0;
for (PaperCard c : cardPool) {
if (pred.apply(c.getRules()) && !collection.contains(c)) {
switch (c.getRarity()) {
case Common:
commons.add(c);
break;
case Uncommon:
uncommons.add(c);
break;
case Rare:
rares.add(c);
break;
case MythicRare:
mythics.add(c);
break;
default:
break;
}
}
}
newCardCount = commons.size() + uncommons.size() + rares.size() + mythics.size();
if (newCardCount == 0) {
return false;
}
ConquestPreferences prefs = FModel.getConquestPreferences();
int rareThreshold = prefs.getPrefInt(CQPref.BOOSTER_RARES);
int uncommonThreshold = rareThreshold + prefs.getPrefInt(CQPref.BOOSTER_UNCOMMONS);
int cardsPerPack = uncommonThreshold + prefs.getPrefInt(CQPref.BOOSTER_COMMONS);
List<PaperCard> rewardPool;
List<PaperCard> rewards = new ArrayList<PaperCard>();
for (int i = 0; i < count; i++) {
//determine which rarity card to get based on pack ratios
int value = Aggregates.randomInt(1, cardsPerPack);
if (value <= rareThreshold) {
if (mythics.size() > 0 && Aggregates.randomInt(1, 8) == 1) {
rewardPool = mythics;
}
else {
rewardPool = rares;
}
}
else if (value <= uncommonThreshold) {
rewardPool = uncommons;
}
else {
rewardPool = commons;
}
if (rewardPool.isEmpty()) { continue; } //if no cards in selected pool, determine random pool again
int index = Aggregates.randomInt(0, rewardPool.size() - 1);
rewards.add(rewardPool.remove(index));
if (--newCardCount == 0) {
break; //break out if no new cards remain
}
}
collection.add(rewards);
String message = messagePrefix + " " + Lang.nounWithAmount(rewards.size(), messageSuffix);
SGuiChoose.reveal(message, rewards);
return true;
public void incrementDay() {
day++;
}
public ConquestPlane getStartingPlane() {

View File

@@ -12,6 +12,8 @@ public class ConquestPlaneData {
private final Map<Region, RegionData> regionDataLookup = new HashMap<Region, RegionData>();
private int wins, losses;
private int winStreakBest = 0;
private int winStreakCurrent = 0;
public List<ConquestCommander> getCommanders() {
return commanders;
@@ -19,6 +21,10 @@ public class ConquestPlaneData {
public void addWin() {
wins++;
winStreakCurrent++;
if (winStreakCurrent > winStreakBest) {
winStreakBest = winStreakCurrent;
}
}
public void addLoss() {
@@ -33,6 +39,14 @@ public class ConquestPlaneData {
return losses;
}
public int getWinStreakBest() {
return winStreakBest;
}
public int getWinStreakCurrent() {
return winStreakCurrent;
}
public RegionData getRegionData(Region region) {
RegionData regionData = regionDataLookup.get(region);
if (regionData == null) {

View File

@@ -34,22 +34,24 @@ import java.util.Comparator;
import java.util.List;
import java.util.Map.Entry;
public abstract class QuestWinLoseController {
public class QuestWinLoseController {
private final GameView lastGame;
private final IWinLoseView<? extends IButton> view;
private final transient boolean wonMatch;
private final transient boolean isAnte;
private final transient QuestController qData;
private final transient QuestEvent qEvent;
public QuestWinLoseController(final GameView game0) {
public QuestWinLoseController(final GameView game0, final IWinLoseView<? extends IButton> view0) {
lastGame = game0;
view = view0;
qData = FModel.getQuest();
qEvent = qData.getCurrentEvent();
wonMatch = lastGame.isMatchWonBy(GamePlayerUtil.getQuestPlayer());
isAnte = FModel.getPreferences().getPrefBoolean(FPref.UI_ANTE);
}
public void showRewards(final IWinLoseView<? extends IButton> view) {
public void showRewards() {
view.getBtnRestart().setVisible(false);
final QuestController qc = FModel.getQuest();
@@ -83,7 +85,7 @@ public abstract class QuestWinLoseController {
}
//give controller a chance to run remaining logic on a separate thread
showRewards(new Runnable() {
view.showRewards(new Runnable() {
@Override
public void run() {
if (isAnte) {
@@ -158,10 +160,10 @@ public abstract class QuestWinLoseController {
private void anteReport(final List<PaperCard> cardsWon, List<PaperCard> cardsLost, boolean hasWon) {
// Generate Swing components and attach.
if (cardsWon != null && !cardsWon.isEmpty()) {
showCards("Spoils! Cards won from ante.", cardsWon);
view.showCards("Spoils! Cards won from ante.", cardsWon);
}
if (cardsLost != null && !cardsLost.isEmpty()) {
showCards("Looted! Cards lost to ante.", cardsLost);
view.showCards("Looted! Cards lost to ante.", cardsLost);
}
}
@@ -375,7 +377,7 @@ public abstract class QuestWinLoseController {
sb.append(String.format("%s %d credits in total.", congrats, credTotal));
qData.getAssets().addCredits(credTotal);
showMessage(sb.toString(), "Gameplay Results", FSkinProp.ICO_QUEST_GOLD);
view.showMessage(sb.toString(), "Gameplay Results", FSkinProp.ICO_QUEST_GOLD);
}
/**
@@ -390,7 +392,7 @@ public abstract class QuestWinLoseController {
final List<PaperCard> cardsWon = new ArrayList<PaperCard>();
cardsWon.add(c);
showCards(message, cardsWon);
view.showCards(message, cardsWon);
}
/**
@@ -458,12 +460,12 @@ public abstract class QuestWinLoseController {
}
if (addDraftToken) {
showMessage("For achieving a 25 win streak, you have been awarded a draft token!\nUse these tokens to generate new tournaments.", "Bonus Draft Token Reward", FSkinProp.ICO_QUEST_COIN);
view.showMessage("For achieving a 25 win streak, you have been awarded a draft token!\nUse these tokens to generate new tournaments.", "Bonus Draft Token Reward", FSkinProp.ICO_QUEST_COIN);
qData.getAchievements().addDraftToken();
}
if (cardsWon.size() > 0) {
showCards("You have achieved a " + (currentStreak == 0 ? "50" : currentStreak) + " win streak and won " + cardsWon.size() + " " + typeWon + " card" + ((cardsWon.size() != 1) ? "s" : "") + "!", cardsWon);
view.showCards("You have achieved a " + (currentStreak == 0 ? "50" : currentStreak) + " win streak and won " + cardsWon.size() + " " + typeWon + " card" + ((cardsWon.size() != 1) ? "s" : "") + "!", cardsWon);
}
}
@@ -476,7 +478,7 @@ public abstract class QuestWinLoseController {
*/
private void awardJackpot() {
final List<PaperCard> cardsWon = qData.getCards().addRandomRare(10);
showCards("You just won 10 random rares!", cardsWon);
view.showCards("You just won 10 random rares!", cardsWon);
}
/**
@@ -569,7 +571,7 @@ public abstract class QuestWinLoseController {
return c2.getRarity().compareTo(c1.getRarity());
}
});
showCards(title, cardsWon);
view.showCards(title, cardsWon);
}
}
@@ -589,7 +591,7 @@ public abstract class QuestWinLoseController {
qData.getAssets().addCredits(questRewardCredits);
showMessage(sb.toString(), "Challenge Rewards for \"" + ((QuestEventChallenge) qEvent).getTitle() + "\"", FSkinProp.ICO_QUEST_BOX);
view.showMessage(sb.toString(), "Challenge Rewards for \"" + ((QuestEventChallenge) qEvent).getTitle() + "\"", FSkinProp.ICO_QUEST_BOX);
awardSpecialReward(null);
}
@@ -627,7 +629,7 @@ public abstract class QuestWinLoseController {
}
if (!boosterCards.isEmpty()) {
qData.getCards().addAllCards(boosterCards);
showCards("Extra " + ii.getName() + "!", boosterCards);
view.showCards("Extra " + ii.getName() + "!", boosterCards);
}
}
else if (ii instanceof IQuestRewardCard) {
@@ -642,14 +644,14 @@ public abstract class QuestWinLoseController {
if (message == null) {
message = "Cards Won";
}
showCards(message, cardsWon);
view.showCards(message, cardsWon);
qData.getCards().addAllCards(cardsWon);
}
}
private void penalizeLoss() {
final int x = FModel.getQuestPreferences().getPrefInt(QPref.PENALTY_LOSS);
showMessage("You lose! You have lost " + x + " credits.", "Gameplay Results", FSkinProp.ICO_QUEST_HEART);
view.showMessage("You lose! You have lost " + x + " credits.", "Gameplay Results", FSkinProp.ICO_QUEST_HEART);
}
/**
@@ -725,8 +727,4 @@ public abstract class QuestWinLoseController {
return credits;
}
protected abstract void showRewards(Runnable runnable);
protected abstract void showCards(String title, List<PaperCard> cards);
protected abstract void showMessage(String message, String title, FSkinProp icon);
}