frankkarsten

Optimal Mana Curve

Jul 24th, 2014
5,405
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. package optimalmanacurve;
  2.  
  3. import java.util.Arrays.*;
  4. import java.util.Random;
  5.  
  6.  
  7. public class OptimalManaCurve {
  8.  
  9.     public static void main(String[] args) {
  10.        
  11.         Deck deck=new Deck();
  12.         boolean[][][][][][][][] KeepOpeningHand = new boolean[8][8][8][8][8][8][8][8];
  13.         KeepOpeningHand=GiveLooseMulliganStrategy();
  14.         int NumberOfSimulationsPerDeck=2500;
  15.         double TotalManaSpent;
  16.         double MostManaSpent=1;
  17.         int OptimalOneDrops=0;
  18.         int OptimalTwoDrops=0;
  19.         int OptimalThreeDrops=0;
  20.         int OptimalFourDrops=0;
  21.         int OptimalFiveDrops=0;
  22.         int OptimalSixDrops=0;
  23.         int OptimalLands=0;
  24.         int NumberOfCardsInDeck=40;
  25.        
  26.         //Doing a grid search (increasing each card by 3) to quickly zoom in on, hopefully, the optimal configuration)
  27.  
  28.         for (int TripleOneDropCount=0; TripleOneDropCount<=10; TripleOneDropCount++){
  29.             for (int TripleTwoDropCount=0; TripleTwoDropCount<=10; TripleTwoDropCount++){
  30.                 for (int TripleThreeDropCount=0; TripleThreeDropCount<=7; TripleThreeDropCount++){
  31.                     for (int TripleFourDropCount=0; TripleFourDropCount<=4; TripleFourDropCount++){
  32.                         for (int TripleFiveDropCount=0; TripleFiveDropCount<=3; TripleFiveDropCount++){
  33.                             for (int TripleSixDropCount=0; TripleSixDropCount<=2; TripleSixDropCount++){
  34.                                     int LandCount=NumberOfCardsInDeck-3*TripleOneDropCount-3*TripleTwoDropCount-3*TripleThreeDropCount-3*TripleFourDropCount-3*TripleFiveDropCount-3*TripleSixDropCount;
  35.                                     if (LandCount>=13 && LandCount<=32) {
  36.                                         deck.SetDeck(3*TripleOneDropCount,3*TripleTwoDropCount,3*TripleThreeDropCount,3*TripleFourDropCount,3*TripleFiveDropCount,3*TripleSixDropCount,LandCount);
  37.                                         deck.PrintDeckBrief();
  38.                                         TotalManaSpent=AverageManaSpentForRandomHand(deck,7,KeepOpeningHand,NumberOfSimulationsPerDeck);
  39.                                         System.out.println(" "+TotalManaSpent);
  40.                                         if (TotalManaSpent>MostManaSpent){
  41.                                             MostManaSpent=TotalManaSpent;
  42.                                             OptimalOneDrops=3*TripleOneDropCount;
  43.                                             OptimalTwoDrops=3*TripleTwoDropCount;
  44.                                             OptimalThreeDrops=3*TripleThreeDropCount;
  45.                                             OptimalFourDrops=3*TripleFourDropCount;
  46.                                             OptimalFiveDrops=3*TripleFiveDropCount;
  47.                                             OptimalSixDrops=3*TripleSixDropCount;
  48.                                             OptimalLands=LandCount;
  49.                                         }
  50.                                     }
  51.                                 //Seven drops are no longer considered due to the curse of dimensionality
  52.                             }
  53.                         }
  54.                     }
  55.                 }
  56.             }
  57.         }
  58.        
  59.         System.out.println("----------------");
  60.         System.out.print("The optimal deck after the grid-enumeration at a small number of simulations per deck was:");
  61.         deck.SetDeck(OptimalOneDrops,OptimalTwoDrops,OptimalThreeDrops,OptimalFourDrops,OptimalFiveDrops,OptimalSixDrops,OptimalLands);
  62.         deck.PrintDeckBrief();
  63.         System.out.println();
  64.         System.out.println("The expected mana spent for this deck:"+MostManaSpent);
  65.         System.out.println("----------------");
  66.        
  67.         NumberOfSimulationsPerDeck=10000;
  68.         int NewOptimalOneDrops=OptimalOneDrops;
  69.         int NewOptimalTwoDrops=OptimalTwoDrops;
  70.         int NewOptimalThreeDrops=OptimalThreeDrops;
  71.         int NewOptimalFourDrops=OptimalFourDrops;
  72.         int NewOptimalFiveDrops=OptimalFiveDrops;
  73.         int NewOptimalSixDrops=OptimalSixDrops;
  74.         int NewOptimalLands=OptimalLands;
  75.         boolean ContinueLocalSearch=true;
  76.        
  77.         //Doing a local search, starting with the best deck from the previous step, all with a loose mulligan strategy under a reasonable number of simulations per deck
  78.        
  79.         do {
  80.             MostManaSpent=1;
  81.             for (int OneDropCount=Math.max(0,OptimalOneDrops-2); OneDropCount<=Math.min(NumberOfCardsInDeck,OptimalOneDrops+2); OneDropCount++){
  82.                 for (int TwoDropCount=Math.max(0,OptimalTwoDrops-2); TwoDropCount<=Math.min(NumberOfCardsInDeck,OptimalTwoDrops+2); TwoDropCount++){
  83.                     for (int ThreeDropCount=Math.max(0,OptimalThreeDrops-2); ThreeDropCount<=Math.min(NumberOfCardsInDeck,OptimalThreeDrops+2); ThreeDropCount++){
  84.                         for (int FourDropCount=Math.max(0,OptimalFourDrops-2); FourDropCount<=Math.min(NumberOfCardsInDeck,OptimalFourDrops+2); FourDropCount++){
  85.                             for (int FiveDropCount=Math.max(0,OptimalFiveDrops-2); FiveDropCount<=Math.min(NumberOfCardsInDeck,OptimalFiveDrops+2); FiveDropCount++){
  86.                                 for (int SixDropCount=Math.max(0,OptimalSixDrops-2); SixDropCount<=Math.min(NumberOfCardsInDeck,OptimalSixDrops+2); SixDropCount++){
  87.                                         int LandCount=NumberOfCardsInDeck-OneDropCount-TwoDropCount-ThreeDropCount-FourDropCount-FiveDropCount-SixDropCount;
  88.                                         if (LandCount>=Math.max(0,OptimalLands-2) && LandCount<=Math.min(NumberOfCardsInDeck,OptimalLands+2)) {
  89.                                             deck.SetDeck(OneDropCount,TwoDropCount,ThreeDropCount,FourDropCount,FiveDropCount,SixDropCount,LandCount);
  90.                                             deck.PrintDeckBrief();
  91.                                             TotalManaSpent=AverageManaSpentForRandomHand(deck,7,KeepOpeningHand,NumberOfSimulationsPerDeck);
  92.                                             System.out.println(" "+TotalManaSpent);
  93.                                             if (TotalManaSpent>MostManaSpent){
  94.                                                 MostManaSpent=TotalManaSpent;
  95.                                                 NewOptimalOneDrops=OneDropCount;
  96.                                                 NewOptimalTwoDrops=TwoDropCount;
  97.                                                 NewOptimalThreeDrops=ThreeDropCount;
  98.                                                 NewOptimalFourDrops=FourDropCount;
  99.                                                 NewOptimalFiveDrops=FiveDropCount;
  100.                                                 NewOptimalSixDrops=SixDropCount;
  101.                                                 OptimalLands=LandCount;
  102.                                             }
  103.                                         }
  104.                                     //Seven drops are no longer considered due to the curse of dimensionality
  105.                                 }
  106.                             }
  107.                         }
  108.                     }
  109.                 }
  110.             }
  111.             if (Math.abs(NewOptimalOneDrops-OptimalOneDrops)+Math.abs(NewOptimalTwoDrops-OptimalTwoDrops)+Math.abs(NewOptimalThreeDrops-OptimalThreeDrops)+Math.abs(NewOptimalFourDrops-OptimalFourDrops)+Math.abs(NewOptimalFiveDrops-OptimalFiveDrops)+Math.abs(NewOptimalSixDrops-OptimalSixDrops)+Math.abs(NewOptimalLands-OptimalLands)<=2) {ContinueLocalSearch=false;}
  112.             OptimalOneDrops=NewOptimalOneDrops;
  113.             OptimalTwoDrops=NewOptimalTwoDrops;
  114.             OptimalThreeDrops=NewOptimalThreeDrops;
  115.             OptimalFourDrops=NewOptimalFourDrops;
  116.             OptimalFiveDrops=NewOptimalFiveDrops;
  117.             OptimalSixDrops=NewOptimalSixDrops;
  118.             OptimalLands=NewOptimalLands;
  119.             System.out.println("----------------");
  120.             System.out.print("The optimal deck after the local search was:");
  121.             deck.SetDeck(OptimalOneDrops,OptimalTwoDrops,OptimalThreeDrops,OptimalFourDrops,OptimalFiveDrops,OptimalSixDrops,OptimalLands);
  122.             deck.PrintDeckBrief();
  123.             System.out.println();
  124.             System.out.println("The expected mana spent for this deck:"+MostManaSpent);
  125.             System.out.println("----------------");
  126.         } while (ContinueLocalSearch);
  127.        
  128.         NumberOfSimulationsPerDeck=200000;
  129.         ContinueLocalSearch=true;
  130.        
  131.         //Doing another local search, starting with the best deck from the previous step, but more fine-grained and with the optimal mulligan strategy
  132.        
  133.         do {
  134.             MostManaSpent=1;
  135.             for (int OneDropCount=Math.max(0,OptimalOneDrops-1); OneDropCount<=Math.min(NumberOfCardsInDeck,OptimalOneDrops+1); OneDropCount++){
  136.                 for (int TwoDropCount=Math.max(0,OptimalTwoDrops-1); TwoDropCount<=Math.min(NumberOfCardsInDeck,OptimalTwoDrops+1); TwoDropCount++){
  137.                     for (int ThreeDropCount=Math.max(0,OptimalThreeDrops-1); ThreeDropCount<=Math.min(NumberOfCardsInDeck,OptimalThreeDrops+1); ThreeDropCount++){
  138.                         for (int FourDropCount=Math.max(0,OptimalFourDrops-1); FourDropCount<=Math.min(NumberOfCardsInDeck,OptimalFourDrops+1); FourDropCount++){
  139.                             for (int FiveDropCount=Math.max(0,OptimalFiveDrops-1); FiveDropCount<=Math.min(NumberOfCardsInDeck,OptimalFiveDrops+1); FiveDropCount++){
  140.                                 for (int SixDropCount=Math.max(0,OptimalSixDrops-1); SixDropCount<=Math.min(NumberOfCardsInDeck,OptimalSixDrops+1); SixDropCount++){
  141.                                         int LandCount=NumberOfCardsInDeck-OneDropCount-TwoDropCount-ThreeDropCount-FourDropCount-FiveDropCount-SixDropCount;
  142.                                         if (LandCount>=Math.max(0,OptimalLands-1) && LandCount<=Math.min(NumberOfCardsInDeck,OptimalLands+1)) {
  143.                                             deck.SetDeck(OneDropCount,TwoDropCount,ThreeDropCount,FourDropCount,FiveDropCount,SixDropCount,LandCount);
  144.                                             //deck.PrintDeckBrief();
  145.                                             KeepOpeningHand=GiveOptimalMulliganStrategy(deck);
  146.                                             TotalManaSpent=AverageManaSpentForRandomHand(deck,7,KeepOpeningHand,NumberOfSimulationsPerDeck);
  147.                                             //System.out.println(" "+TotalManaSpent);
  148.                                             if (TotalManaSpent>MostManaSpent){
  149.                                                 MostManaSpent=TotalManaSpent;
  150.                                                 NewOptimalOneDrops=OneDropCount;
  151.                                                 NewOptimalTwoDrops=TwoDropCount;
  152.                                                 NewOptimalThreeDrops=ThreeDropCount;
  153.                                                 NewOptimalFourDrops=FourDropCount;
  154.                                                 NewOptimalFiveDrops=FiveDropCount;
  155.                                                 NewOptimalSixDrops=SixDropCount;
  156.                                                 NewOptimalLands=LandCount;
  157.                                             }
  158.                                         }
  159.                                     }
  160.                                 }
  161.                             }
  162.                         }
  163.                     }
  164.                 System.out.println();
  165.                 }
  166.             if (Math.abs(NewOptimalOneDrops-OptimalOneDrops)+Math.abs(NewOptimalTwoDrops-OptimalTwoDrops)+Math.abs(NewOptimalThreeDrops-OptimalThreeDrops)+Math.abs(NewOptimalFourDrops-OptimalFourDrops)+Math.abs(NewOptimalFiveDrops-OptimalFiveDrops)+Math.abs(NewOptimalSixDrops-OptimalSixDrops)+Math.abs(NewOptimalLands-OptimalLands)==0) {ContinueLocalSearch=false;}
  167.             OptimalOneDrops=NewOptimalOneDrops;
  168.             OptimalTwoDrops=NewOptimalTwoDrops;
  169.             OptimalThreeDrops=NewOptimalThreeDrops;
  170.             OptimalFourDrops=NewOptimalFourDrops;
  171.             OptimalFiveDrops=NewOptimalFiveDrops;
  172.             OptimalSixDrops=NewOptimalSixDrops;
  173.             OptimalLands=NewOptimalLands;
  174.  
  175.             System.out.println("----------------");
  176.             System.out.print("Found a better deck:");
  177.             deck.SetDeck(OptimalOneDrops,OptimalTwoDrops,OptimalThreeDrops,OptimalFourDrops,OptimalFiveDrops,OptimalSixDrops,OptimalLands);
  178.             deck.PrintDeckBrief();
  179.             System.out.println();
  180.             System.out.println("The expected mana spent for this deck:"+MostManaSpent);
  181.             System.out.println("----------------");
  182.            
  183.         } while (ContinueLocalSearch);
  184.    
  185.     System.out.println("----------------");
  186.     System.out.print("The final optimal deck:");
  187.     deck.SetDeck(OptimalOneDrops,OptimalTwoDrops,OptimalThreeDrops,OptimalFourDrops,OptimalFiveDrops,OptimalSixDrops,OptimalLands);
  188.     deck.PrintDeckBrief();
  189.     System.out.println();
  190.     System.out.println("The expected mana spent for this deck:"+MostManaSpent);
  191.     System.out.println("----------------");
  192.    
  193.     }//end of main
  194.  
  195.     public static boolean[][][][][][][][] GiveOptimalMulliganStrategy(Deck deck) {
  196.         boolean[][][][][][][][] KeepOpeningHand = new boolean[8][8][8][8][8][8][8][8];
  197.         OpeningHand openinghand=new OpeningHand();
  198.         int NumberOfSimulationsPerOpeningHandSize=1000;
  199.         int OriginalNr1Cost=deck.NumberOf1Cost;
  200.         int OriginalNr2Cost=deck.NumberOf2Cost;
  201.         int OriginalNr3Cost=deck.NumberOf3Cost;
  202.         int OriginalNr4Cost=deck.NumberOf4Cost;
  203.         int OriginalNr5Cost=deck.NumberOf5Cost;
  204.         int OriginalNr6Cost=deck.NumberOf6Cost;
  205.         int OriginalNrLands=deck.NumberOfLands;
  206.         double CutOffManaSpent = 1;
  207.         //Let's just keep every 2-card hand. That simplifies things.
  208.         for (int StartingCards=2; StartingCards<=7; StartingCards++){
  209.             //System.out.print(".");
  210.             for (int OneDropCount=0; OneDropCount<=StartingCards; OneDropCount++){
  211.                 for (int TwoDropCount=0; TwoDropCount+OneDropCount<=StartingCards; TwoDropCount++){
  212.                     for  (int ThreeDropCount=0; ThreeDropCount+TwoDropCount+OneDropCount<=StartingCards; ThreeDropCount++){
  213.                         for  (int FourDropCount=0; FourDropCount+ThreeDropCount+TwoDropCount+OneDropCount<=StartingCards; FourDropCount++){
  214.                             for  (int FiveDropCount=0; FiveDropCount+FourDropCount+ThreeDropCount+TwoDropCount+OneDropCount<=StartingCards; FiveDropCount++){
  215.                                 for  (int SixDropCount=0; SixDropCount+FiveDropCount+FourDropCount+ThreeDropCount+TwoDropCount+OneDropCount<=StartingCards; SixDropCount++){
  216.                                     int LandCount=StartingCards-OneDropCount-TwoDropCount-ThreeDropCount-FourDropCount-FiveDropCount-SixDropCount;
  217.                                     if (OneDropCount<=OriginalNr1Cost && TwoDropCount<=OriginalNr2Cost && ThreeDropCount<=OriginalNr3Cost && FourDropCount<=OriginalNr4Cost && FiveDropCount<=OriginalNr5Cost && SixDropCount<=OriginalNr6Cost && LandCount<=OriginalNrLands){
  218.                                         openinghand.SetHand(OneDropCount, TwoDropCount, ThreeDropCount, FourDropCount, FiveDropCount, SixDropCount, LandCount);
  219.                                         deck.SetDeck(OriginalNr1Cost,OriginalNr2Cost,OriginalNr3Cost,OriginalNr4Cost,OriginalNr5Cost,OriginalNr6Cost,OriginalNrLands);
  220.                                         double AvgManaSpent=AverageManaSpentForSpecificHand(deck,openinghand);
  221.                                         if (AvgManaSpent>CutOffManaSpent) { KeepOpeningHand[StartingCards][OneDropCount][TwoDropCount][ThreeDropCount][FourDropCount][FiveDropCount][SixDropCount][LandCount]=true;}
  222.                                         if (AvgManaSpent<=CutOffManaSpent) { KeepOpeningHand[StartingCards][OneDropCount][TwoDropCount][ThreeDropCount][FourDropCount][FiveDropCount][SixDropCount][LandCount]=false;}
  223.                                         if (StartingCards==2) {KeepOpeningHand[StartingCards][OneDropCount][TwoDropCount][ThreeDropCount][FourDropCount][FiveDropCount][SixDropCount][LandCount]=true;}
  224.                                     }
  225.                                 }
  226.                             }
  227.                         }
  228.                     }
  229.                 }
  230.             }
  231.             deck.SetDeck(OriginalNr1Cost,OriginalNr2Cost,OriginalNr3Cost,OriginalNr4Cost,OriginalNr5Cost,OriginalNr6Cost,OriginalNrLands);
  232.             if (StartingCards<7) {CutOffManaSpent=AverageManaSpentForRandomHand(deck,StartingCards,KeepOpeningHand,NumberOfSimulationsPerOpeningHandSize);}
  233.         }
  234.         return KeepOpeningHand;
  235.     }
  236.  
  237.     public static boolean[][][][][][][][] GiveLooseMulliganStrategy() {
  238.         boolean[][][][][][][][] KeepOpeningHand = new boolean[8][8][8][8][8][8][8][8];
  239.         for (int StartingCards=2; StartingCards<=7; StartingCards++){
  240.             for (int OneDropCount=0; OneDropCount<=StartingCards; OneDropCount++){
  241.                 for (int TwoDropCount=0; TwoDropCount+OneDropCount<=StartingCards; TwoDropCount++){
  242.                     for  (int ThreeDropCount=0; ThreeDropCount+TwoDropCount+OneDropCount<=StartingCards; ThreeDropCount++){
  243.                         for  (int FourDropCount=0; FourDropCount+ThreeDropCount+TwoDropCount+OneDropCount<=StartingCards; FourDropCount++){
  244.                             for  (int FiveDropCount=0; FiveDropCount+FourDropCount+ThreeDropCount+TwoDropCount+OneDropCount<=StartingCards; FiveDropCount++){
  245.                                 for  (int SixDropCount=0; SixDropCount+FiveDropCount+FourDropCount+ThreeDropCount+TwoDropCount+OneDropCount<=StartingCards; SixDropCount++){
  246.                                     int LandCount=StartingCards-OneDropCount-TwoDropCount-ThreeDropCount-FourDropCount-FiveDropCount-SixDropCount;
  247.                                     KeepOpeningHand[StartingCards][OneDropCount][TwoDropCount][ThreeDropCount][FourDropCount][FiveDropCount][SixDropCount][LandCount]=false;
  248.                                     //The simple idea is that we're keeping a hand if it contains between 2 and 5 lands and at least one spell of 3 mana or less. Also, keep any 2-card hand.
  249.                                     if (LandCount>=2 && LandCount<=5 && (OneDropCount+TwoDropCount+ThreeDropCount)>=1) {KeepOpeningHand[StartingCards][OneDropCount][TwoDropCount][ThreeDropCount][FourDropCount][FiveDropCount][SixDropCount][LandCount]=true;}
  250.                                     if (StartingCards<=2) {KeepOpeningHand[StartingCards][OneDropCount][TwoDropCount][ThreeDropCount][FourDropCount][FiveDropCount][SixDropCount][LandCount]=true;}
  251.                                 }
  252.                             }
  253.                         }
  254.                     }
  255.                 }
  256.             }
  257.         }
  258.         return KeepOpeningHand;
  259.     }
  260.    
  261.     public static double AverageManaSpentForSpecificHand(Deck deck, OpeningHand openinghand){
  262.         int NumberOfIterations=250;
  263.         Deck remainingdeck=new Deck();
  264.         double TotalManaSpent=0;
  265.         for (int IterationCounter=1; IterationCounter<=NumberOfIterations; IterationCounter++){
  266.             remainingdeck.SetDeck(deck.NumberOf1Cost-openinghand.NumberOf1Cost,deck.NumberOf2Cost-openinghand.NumberOf2Cost,deck.NumberOf3Cost-openinghand.NumberOf3Cost,deck.NumberOf4Cost-openinghand.NumberOf4Cost,deck.NumberOf5Cost-openinghand.NumberOf5Cost,deck.NumberOf6Cost-openinghand.NumberOf6Cost,deck.NumberOfLands-openinghand.NumberOfLands);
  267.             TotalManaSpent=TotalManaSpent+ManaSpent(remainingdeck,openinghand);
  268.         }
  269.         return (TotalManaSpent/(NumberOfIterations+0.0));
  270.     }//end of AverageManaSpentForSpecificHand
  271.  
  272.     public static double AverageManaSpentForRandomHand(Deck deck, int StartingCards, boolean[][][][][][][][] KeepOpeningHand, int NumberOfIterations){
  273.         Deck remainingdeck=new Deck();
  274.         double TotalManaSpent=0;
  275.         for (int IterationCounter=1; IterationCounter<=NumberOfIterations; IterationCounter++){
  276.             OpeningHand openinghand=GiveOpeningHandAfterMulls(deck, StartingCards, KeepOpeningHand);
  277.             remainingdeck.SetDeck(deck.NumberOf1Cost-openinghand.NumberOf1Cost,deck.NumberOf2Cost-openinghand.NumberOf2Cost,deck.NumberOf3Cost-openinghand.NumberOf3Cost,deck.NumberOf4Cost-openinghand.NumberOf4Cost,deck.NumberOf5Cost-openinghand.NumberOf5Cost,deck.NumberOf6Cost-openinghand.NumberOf6Cost,deck.NumberOfLands-openinghand.NumberOfLands);
  278.             TotalManaSpent=TotalManaSpent+ManaSpent(remainingdeck,openinghand);
  279.             if ( IterationCounter % 10000 == 0) {System.out.print(".");}
  280.         }
  281.         return TotalManaSpent/(NumberOfIterations+0.0);
  282.     }//end of AverageManaSpentForRandomHand
  283.    
  284.     static OpeningHand GiveOpeningHandAfterMulls (Deck deck, int StartingCards, boolean[][][][][][][][] KeepOpeningHand) {
  285.        
  286.         Deck remainingdeck=new Deck();
  287.         OpeningHand openinghand=new OpeningHand();
  288.         int TypeOfCardDrawn;
  289.         boolean KeepHand=false;
  290.        
  291.         for (int OpeningHandSize=7; OpeningHandSize>=1; OpeningHandSize--){
  292.             if (KeepHand==false && StartingCards>=OpeningHandSize){
  293.                 openinghand.ResetHand();
  294.                 remainingdeck.SetDeck(deck.NumberOf1Cost,deck.NumberOf2Cost,deck.NumberOf3Cost,deck.NumberOf4Cost,deck.NumberOf5Cost,deck.NumberOf6Cost,deck.NumberOfLands);
  295.                 for (int CardsDrawn=0; CardsDrawn<OpeningHandSize; CardsDrawn++){
  296.                     TypeOfCardDrawn=remainingdeck.DrawCard();
  297.                     if (TypeOfCardDrawn==1) {openinghand.NumberOf1Cost++;}
  298.                     if (TypeOfCardDrawn==2) {openinghand.NumberOf2Cost++;}
  299.                     if (TypeOfCardDrawn==3) {openinghand.NumberOf3Cost++;}
  300.                     if (TypeOfCardDrawn==4) {openinghand.NumberOf4Cost++;}
  301.                     if (TypeOfCardDrawn==5) {openinghand.NumberOf5Cost++;}
  302.                     if (TypeOfCardDrawn==6) {openinghand.NumberOf6Cost++;}
  303.                     if (TypeOfCardDrawn==9) {openinghand.NumberOfLands++;}
  304.                 }
  305.                 KeepHand=true;
  306.                 if (OpeningHandSize>1) {
  307.                     if (KeepOpeningHand[OpeningHandSize][openinghand.NumberOf1Cost][openinghand.NumberOf2Cost][openinghand.NumberOf3Cost][openinghand.NumberOf4Cost][openinghand.NumberOf5Cost][openinghand.NumberOf6Cost][openinghand.NumberOfLands]==false) {KeepHand=false;}
  308.                 }
  309.             }
  310.         }
  311.        
  312.         return openinghand;
  313.     }//end of GiveOpeningHandAfterMulls
  314.    
  315.     static int ManaSpent(Deck remainingdeck, OpeningHand openinghand) {
  316.        
  317.         int TotalManaSpent=0;
  318.         //Here we put in the speed of the format
  319.         int FinalTurn=7;
  320.        
  321.             int Turn=0;
  322.             int ManaLeft;
  323.             int TypeOfCardDrawn;
  324.    
  325.             int LandsInPlay=0;
  326.            
  327.             /*This is old code when the final turn was random, and we took the average of one turn slower, the expected game-over turn, and one turn faster, which all happen with equal probability  
  328.             OpeningHand openinghand=new OpeningHand();
  329.             openinghand.NumberOf1Cost=openinghandOrig.NumberOf1Cost;
  330.             openinghand.NumberOf2Cost=openinghandOrig.NumberOf2Cost;
  331.             openinghand.NumberOf3Cost=openinghandOrig.NumberOf3Cost;
  332.             openinghand.NumberOf4Cost=openinghandOrig.NumberOf4Cost;
  333.             openinghand.NumberOf5Cost=openinghandOrig.NumberOf5Cost;
  334.             openinghand.NumberOf6Cost=openinghandOrig.NumberOf6Cost;
  335.             openinghand.NumberOfLands=openinghandOrig.NumberOfLands;
  336.             Deck remainingdeck=new Deck();
  337.             remainingdeck.NumberOf1Cost=remainingdeckOrig.NumberOf1Cost;
  338.             remainingdeck.NumberOf2Cost=remainingdeckOrig.NumberOf2Cost;
  339.             remainingdeck.NumberOf3Cost=remainingdeckOrig.NumberOf3Cost;
  340.             remainingdeck.NumberOf4Cost=remainingdeckOrig.NumberOf4Cost;
  341.             remainingdeck.NumberOf5Cost=remainingdeckOrig.NumberOf5Cost;
  342.             remainingdeck.NumberOf6Cost=remainingdeckOrig.NumberOf6Cost;
  343.             remainingdeck.NumberOfLands=remainingdeckOrig.NumberOfLands;
  344.             */
  345.             int OneDropsInHand=openinghand.NumberOf1Cost;
  346.             int TwoDropsInHand=openinghand.NumberOf2Cost;
  347.             int ThreeDropsInHand=openinghand.NumberOf3Cost;
  348.             int FourDropsInHand=openinghand.NumberOf4Cost;
  349.             int FiveDropsInHand=openinghand.NumberOf5Cost;
  350.             int SixDropsInHand=openinghand.NumberOf6Cost;
  351.             int LandsInHand=openinghand.NumberOfLands;
  352.        
  353.            
  354.             do {
  355.                
  356.                 Turn++;
  357.                
  358.                 if (Turn==1) {
  359.                     if (LandsInHand>=1) {LandsInPlay++; LandsInHand--;}
  360.                     ManaLeft=LandsInPlay;
  361.                     if (OneDropsInHand>=1 && ManaLeft==1) {TotalManaSpent++; ManaLeft--; OneDropsInHand--;}
  362.                     //TotalManaSpent=TotalManaSpent+(LandsInPlay-ManaLeft)*0.5;
  363.                 } //end of the first turn
  364.                
  365.                 if (Turn>1) {
  366.  
  367.                     TypeOfCardDrawn=remainingdeck.DrawCard();
  368.                     if (TypeOfCardDrawn==1) {OneDropsInHand++;}
  369.                     if (TypeOfCardDrawn==2) {TwoDropsInHand++;}
  370.                     if (TypeOfCardDrawn==3) {ThreeDropsInHand++;}
  371.                     if (TypeOfCardDrawn==4) {FourDropsInHand++;}
  372.                     if (TypeOfCardDrawn==5) {FiveDropsInHand++;}
  373.                     if (TypeOfCardDrawn==6) {SixDropsInHand++;}                
  374.                     if (TypeOfCardDrawn==9) {LandsInHand++;}
  375.  
  376.                     if (LandsInHand>=1) {LandsInPlay++; LandsInHand--;}
  377.                     ManaLeft=LandsInPlay;
  378.                
  379.                     int CastableSixDrops=Math.min(SixDropsInHand, ManaLeft/6);
  380.                     if (CastableSixDrops>=1) {TotalManaSpent=TotalManaSpent+6*CastableSixDrops; ManaLeft=ManaLeft-6*CastableSixDrops; SixDropsInHand=SixDropsInHand-CastableSixDrops;}
  381.                
  382.                     int CastableFiveDrops=Math.min(FiveDropsInHand, ManaLeft/5);
  383.                     if (CastableFiveDrops>=1) {TotalManaSpent=TotalManaSpent+5*CastableFiveDrops; ManaLeft=ManaLeft-5*CastableFiveDrops; FiveDropsInHand=FiveDropsInHand-CastableFiveDrops;}
  384.                
  385.                     int CastableFourDrops=Math.min(FourDropsInHand, ManaLeft/4);
  386.                     if (CastableFourDrops>=1) {TotalManaSpent=TotalManaSpent+4*CastableFourDrops; ManaLeft=ManaLeft-4*CastableFourDrops; FourDropsInHand=FourDropsInHand-CastableFourDrops;}
  387.                
  388.                     int CastableThreeDrops=Math.min(ThreeDropsInHand, ManaLeft/3);
  389.                     if (CastableThreeDrops>=1) {TotalManaSpent=TotalManaSpent+3*CastableThreeDrops; ManaLeft=ManaLeft-3*CastableThreeDrops; ThreeDropsInHand=ThreeDropsInHand-CastableThreeDrops;}
  390.                
  391.                     int CastableTwoDrops=Math.min(TwoDropsInHand, ManaLeft/2);
  392.                     if (CastableTwoDrops>=1) {TotalManaSpent=TotalManaSpent+2*CastableTwoDrops; ManaLeft=ManaLeft-2*CastableTwoDrops; TwoDropsInHand=TwoDropsInHand-CastableTwoDrops;}
  393.                
  394.                     int CastableOneDrops=Math.min(OneDropsInHand, ManaLeft);
  395.                     if (CastableOneDrops>=1) {TotalManaSpent=TotalManaSpent+CastableOneDrops; ManaLeft=ManaLeft-CastableOneDrops; OneDropsInHand=OneDropsInHand-CastableOneDrops;}
  396.                    
  397.              
  398.                 } //end of a turn in which we drew a card and attacked
  399.             } while (Turn<FinalTurn);
  400.        
  401.         return TotalManaSpent;
  402.     }//end of TurnKill
  403.  
  404. }//end of OptimalAggroGoldfishDeck
  405.  
  406. class OpeningHand {
  407.     int NumberOf1Cost;
  408.     int NumberOf2Cost;
  409.     int NumberOf3Cost;
  410.     int NumberOf4Cost;
  411.     int NumberOf5Cost;
  412.     int NumberOf6Cost;
  413.     int NumberOfLands;
  414.    
  415.     void ResetHand(){
  416.         NumberOf1Cost=0;
  417.         NumberOf2Cost=0;
  418.         NumberOf3Cost=0;
  419.         NumberOf4Cost=0;
  420.         NumberOf5Cost=0;
  421.         NumberOf6Cost=0;
  422.         NumberOfLands=0;
  423.     }
  424.            
  425.     void SetHand (int Nr1Cost, int Nr2Cost, int Nr3Cost, int Nr4Cost, int Nr5Cost, int Nr6Cost, int NrLands) {
  426.         NumberOf1Cost=Nr1Cost;
  427.         NumberOf2Cost=Nr2Cost;
  428.         NumberOf3Cost=Nr3Cost;
  429.         NumberOf4Cost=Nr4Cost;
  430.         NumberOf5Cost=Nr5Cost;
  431.         NumberOf6Cost=Nr6Cost;
  432.         NumberOfLands=NrLands;
  433.     }
  434.  
  435. }//end of OpeningHand
  436.  
  437. class Deck {
  438.     int NumberOf1Cost;
  439.     int NumberOf2Cost;
  440.     int NumberOf3Cost;
  441.     int NumberOf4Cost;
  442.     int NumberOf5Cost;
  443.     int NumberOf6Cost;
  444.     int NumberOfLands;
  445.  
  446.     void PrintDeckBrief () {
  447.         if(NumberOf1Cost<10) {System.out.print("0");}
  448.         System.out.print(NumberOf1Cost+" ");
  449.         if(NumberOf2Cost<10) {System.out.print("0");}
  450.         System.out.print(NumberOf2Cost+" ");
  451.         if(NumberOf3Cost<10) {System.out.print("0");}
  452.         System.out.print(NumberOf3Cost+" ");
  453.         if(NumberOf4Cost<10) {System.out.print("0");}
  454.         System.out.print(NumberOf4Cost+" ");
  455.         if(NumberOf5Cost<10) {System.out.print("0");}
  456.         System.out.print(NumberOf5Cost+" ");
  457.         if(NumberOf6Cost<10) {System.out.print("0");}
  458.         System.out.print(NumberOf6Cost+" ");
  459.         if(NumberOfLands<10) {System.out.print("0");}
  460.         System.out.print(NumberOfLands);
  461.         System.out.print(" ");
  462.     }
  463.  
  464.     void SetDeck (int Nr1Cost, int Nr2Cost, int Nr3Cost, int Nr4Cost, int Nr5Cost, int Nr6Cost, int NrLands) {
  465.         NumberOf1Cost=Nr1Cost;
  466.         NumberOf2Cost=Nr2Cost;
  467.         NumberOf3Cost=Nr3Cost;
  468.         NumberOf4Cost=Nr4Cost;
  469.         NumberOf5Cost=Nr5Cost;
  470.         NumberOf6Cost=Nr6Cost;
  471.         NumberOfLands=NrLands;
  472.     }
  473.    
  474.     int NrOfCards(){
  475.         return NumberOf1Cost+NumberOf2Cost+NumberOf3Cost+NumberOf4Cost+NumberOf5Cost+NumberOf6Cost+NumberOfLands;
  476.     }
  477.    
  478.     int DrawCard (){
  479.             Random generator = new Random();
  480.             int RandomIntegerBetweenOneAndDeckSize=generator.nextInt( this.NrOfCards() )+1;
  481.             int CardType=0;
  482.             int OneCostCutoff=NumberOf1Cost;
  483.             int TwoCostCutoff=OneCostCutoff+NumberOf2Cost;
  484.             int ThreeCostCutoff=TwoCostCutoff+NumberOf3Cost;
  485.             int FourCostCutoff=ThreeCostCutoff+NumberOf4Cost;
  486.             int FiveCostCutoff=FourCostCutoff+NumberOf5Cost;
  487.             int SixCostCutoff=FiveCostCutoff+NumberOf6Cost;
  488.             int LandCutoff=SixCostCutoff+NumberOfLands;
  489.            
  490.             if (RandomIntegerBetweenOneAndDeckSize<=OneCostCutoff) {CardType=1; this.NumberOf1Cost--;}
  491.             if (RandomIntegerBetweenOneAndDeckSize>OneCostCutoff && RandomIntegerBetweenOneAndDeckSize<=TwoCostCutoff) {CardType=2; this.NumberOf2Cost--;}
  492.             if (RandomIntegerBetweenOneAndDeckSize>TwoCostCutoff && RandomIntegerBetweenOneAndDeckSize<=ThreeCostCutoff) {CardType=3; this.NumberOf3Cost--;}
  493.             if (RandomIntegerBetweenOneAndDeckSize>ThreeCostCutoff && RandomIntegerBetweenOneAndDeckSize<=FourCostCutoff) {CardType=4; this.NumberOf4Cost--;}
  494.             if (RandomIntegerBetweenOneAndDeckSize>FourCostCutoff && RandomIntegerBetweenOneAndDeckSize<=FiveCostCutoff) {CardType=5; this.NumberOf5Cost--;}
  495.             if (RandomIntegerBetweenOneAndDeckSize>FiveCostCutoff && RandomIntegerBetweenOneAndDeckSize<=SixCostCutoff) {CardType=6; this.NumberOf6Cost--;}
  496.             if (RandomIntegerBetweenOneAndDeckSize>SixCostCutoff && RandomIntegerBetweenOneAndDeckSize<=LandCutoff) {CardType=9; this.NumberOfLands--;}
  497.            
  498.             return CardType;
  499.     }
  500.    
  501. }//end of Deck
RAW Paste Data