Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package rats;
- import java.util.Arrays.*;
- import java.util.Random;
- public class Rats{
- //We use stochastic dynamic programming to find an optimal mulligan strategy for every deck
- public static void main(String[] args) {
- Deck deck=new Deck();
- boolean[][][] KeepOpeningHand = new boolean[8][8][8];
- int NumberOfSimulationsPerDeck=1000000;
- double FastestTurn=50;
- double KillTurn;
- for (int RatCount=20; RatCount<=50; RatCount++){
- deck.SetDeck(RatCount,60-RatCount);
- KeepOpeningHand=GiveOptimalMulliganStrategy(deck);
- KillTurn=AverageKillTurnForRandomHand(deck,7,KeepOpeningHand,NumberOfSimulationsPerDeck);
- System.out.println("With "+RatCount+" Rats and "+(60-RatCount)+" Swamps, you win in expectation on turn "+KillTurn);
- }
- }//end of main
- public static boolean[][][] GiveOptimalMulliganStrategy(Deck deck) {
- boolean[][][] KeepOpeningHand = new boolean[8][8][8];
- OpeningHand openinghand=new OpeningHand();
- int NumberOfSimulationsPerOpeningHandSize=100000;
- int OriginalNrRats=deck.NumberOfRats;
- int OriginalNrLands=deck.NumberOfLands;
- double CutOffTurn = AverageKillTurnForRandomHand(deck,1,KeepOpeningHand,NumberOfSimulationsPerOpeningHandSize);
- for (int StartingCards=2; StartingCards<=7; StartingCards++){
- for (int RatCount=0; RatCount<=StartingCards; RatCount++){
- int LandCount=StartingCards-RatCount;
- //We assume that RatCount<=OriginalNrRats and LandCount<=OriginalNrLands but that should always be the case for our decks
- openinghand.SetHand(RatCount, LandCount);
- deck.SetDeck(OriginalNrRats,OriginalNrLands);
- double AvgKillTurn=AverageKillTurnForSpecificHand(deck,openinghand);
- if (AvgKillTurn<=CutOffTurn) { KeepOpeningHand[StartingCards][RatCount][LandCount]=true;}
- if (AvgKillTurn>CutOffTurn) { KeepOpeningHand[StartingCards][RatCount][LandCount]=false;}
- }
- deck.SetDeck(OriginalNrRats,OriginalNrLands);
- if (StartingCards<7) {CutOffTurn=AverageKillTurnForRandomHand(deck,StartingCards,KeepOpeningHand,NumberOfSimulationsPerOpeningHandSize);}
- }
- return KeepOpeningHand;
- }
- public static double AverageKillTurnForSpecificHand(Deck deck, OpeningHand openinghand){
- int NumberOfIterations=100000;
- Deck remainingdeck=new Deck();
- double AverageKillTurn=0;
- for (int IterationCounter=1; IterationCounter<=NumberOfIterations; IterationCounter++){
- remainingdeck.SetDeck(deck.NumberOfRats-openinghand.NumberOfRats,deck.NumberOfLands-openinghand.NumberOfLands);
- AverageKillTurn=AverageKillTurn+TurnKill(remainingdeck,openinghand);
- }
- return (AverageKillTurn/(NumberOfIterations+0.0));
- }//end of AverageKillTurnForSpecificHand
- public static double AverageKillTurnForRandomHand(Deck deck, int StartingCards, boolean[][][] KeepOpeningHand, int NumberOfIterations){
- Deck remainingdeck=new Deck();
- double AverageKillTurn=0;
- for (int IterationCounter=1; IterationCounter<=NumberOfIterations; IterationCounter++){
- OpeningHand openinghand=GiveOpeningHandAfterMulls(deck, StartingCards, KeepOpeningHand);
- remainingdeck.SetDeck(deck.NumberOfRats-openinghand.NumberOfRats,deck.NumberOfLands-openinghand.NumberOfLands);
- AverageKillTurn=AverageKillTurn+TurnKill(remainingdeck,openinghand);
- }
- return AverageKillTurn/(NumberOfIterations+0.0);
- }//end of AverageKillTurnForRandomHand
- static OpeningHand GiveOpeningHandAfterMulls (Deck deck, int StartingCards, boolean[][][] KeepOpeningHand) {
- Deck remainingdeck=new Deck();
- OpeningHand openinghand=new OpeningHand();
- int TypeOfCardDrawn;
- boolean KeepHand=false;
- for (int OpeningHandSize=7; OpeningHandSize>=1; OpeningHandSize--){
- if (KeepHand==false && StartingCards>=OpeningHandSize){
- openinghand.ResetHand();
- remainingdeck.SetDeck(deck.NumberOfRats,deck.NumberOfLands);
- for (int CardsDrawn=0; CardsDrawn<OpeningHandSize; CardsDrawn++){
- TypeOfCardDrawn=remainingdeck.DrawCard();
- if (TypeOfCardDrawn==1) {openinghand.NumberOfRats++;}
- if (TypeOfCardDrawn==2) {openinghand.NumberOfLands++;}
- }
- KeepHand=true;
- if (OpeningHandSize>1) {
- if (KeepOpeningHand[OpeningHandSize][openinghand.NumberOfRats][openinghand.NumberOfLands]==false) {KeepHand=false;}
- }
- }
- }
- return openinghand;
- }//end of GiveOpeningHandAfterMulls
- static int TurnKill(Deck remainingdeck, OpeningHand openinghand) {
- int Turn=0;
- int OppLife=20;
- int ManaLeft;
- int TypeOfCardDrawn;
- int RatsInPlay=0;
- int NonSickRats=0;
- int SwampsInPlay=0;
- int TotalPower=0;
- int RatsInHand=openinghand.NumberOfRats;
- int SwampsInHand=openinghand.NumberOfLands;
- do {
- if (Turn>1) {
- TypeOfCardDrawn=remainingdeck.DrawCard();
- if (TypeOfCardDrawn==1) {RatsInHand++;}
- if (TypeOfCardDrawn==2) {SwampsInHand++;}
- }
- //Play a land
- if (SwampsInHand>=1) {SwampsInPlay++; SwampsInHand--;}
- ManaLeft=SwampsInPlay;
- NonSickRats=RatsInPlay;
- //Play Rats
- if (RatsInHand>=3 && ManaLeft>=6) {RatsInPlay=RatsInPlay+3; RatsInHand=RatsInHand-3; ManaLeft=ManaLeft-6;}
- if (RatsInHand>=2 && ManaLeft>=4) {RatsInPlay=RatsInPlay+2; RatsInHand=RatsInHand-2; ManaLeft=ManaLeft-4;}
- if (RatsInHand>=1 && ManaLeft>=2) {RatsInPlay=RatsInPlay+1; RatsInHand=RatsInHand-1; ManaLeft=ManaLeft-2;}
- //Attack
- TotalPower=NonSickRats*(2+RatsInPlay-1);
- OppLife=OppLife-TotalPower;
- Turn++;
- } while (OppLife>0 &&Turn<=50);
- return Turn;
- }//end of TurnKill
- }//end of OptimalAggroGoldfishDeck
- class OpeningHand {
- int NumberOfRats;
- int NumberOfLands;
- void ResetHand(){
- NumberOfRats=0;
- NumberOfLands=0;
- }
- void SetHand (int NrRats, int NrLands) {
- NumberOfRats=NrRats;
- NumberOfLands=NrLands;
- }
- }//end of OpeningHand
- class Deck {
- int NumberOfRats;
- int NumberOfLands;
- void SetDeck (int NrRats, int NrLands) {
- NumberOfRats=NrRats;
- NumberOfLands=NrLands;
- }
- int NrOfCards(){
- return NumberOfRats+NumberOfLands;
- }
- int DrawCard (){
- Random generator = new Random();
- int RandomIntegerBetweenOneAndDeckSize=generator.nextInt( this.NrOfCards() )+1;
- int CardType=0;
- if (RandomIntegerBetweenOneAndDeckSize<=NumberOfRats) {CardType=1; this.NumberOfRats--;}
- if (RandomIntegerBetweenOneAndDeckSize>NumberOfRats) {CardType=2; this.NumberOfLands--;}
- return CardType;
- }
- }//end of Deck
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement