Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package hatebears;
- import java.util.Random;
- import java.util.Arrays.*;
- public class Hatebears {
- public static void main(String[] args) {
- Deck Hatedeck=new Deck();
- //CardType 1 is a Leyline of Sanctity
- //CardType 2 is a Nourishing Shoal
- //CardType 3 is a Bassara Tower Archer
- //CardType 4 is a Forest
- double BestWinProb=0;
- for (int NrLeyline=10; NrLeyline<=20; NrLeyline++){
- for (int NrShoal=15; NrShoal<=25; NrShoal++){
- for (int NrArcher=10; NrArcher<=20; NrArcher++){
- int NrForest=60-NrLeyline-NrShoal-NrArcher;
- if (NrForest>0){
- Hatedeck.SetDeck(NrLeyline,NrShoal,NrArcher,NrForest,0);
- double ProbabilityVsChancellor=ProbabilityForRandomHand(Hatedeck,7,100000,true);
- double ProbabilityVsRipple=ProbabilityForRandomHand(Hatedeck,7,100000,false);
- double Probability=0.5*ProbabilityVsChancellor+0.5*ProbabilityVsRipple;
- if (Probability>BestWinProb){
- System.out.print("A new best deck! For a deck with "+NrLeyline+" Leylines, "+NrShoal+" Shoals, "+NrArcher+" Archers, and "+NrForest+" Forests: win probability is ");
- System.out.println(Math.round(Probability*10000)/100.0+". Vs Chancellor: "+ProbabilityVsChancellor+". Vs Ripple: "+ProbabilityVsRipple);
- BestWinProb=Probability;
- }
- }
- }
- }
- }
- }//end of main
- public static double ProbabilityForRandomHand(Deck deck, int StartingCards, int NumberOfIterations, boolean PlayVsChancellor){
- double NumberOfGamesWithfavorableOutcome=0;
- double NumberOfGames=0;
- Deck remainingdeck=new Deck();
- for (int IterationCounter=1; IterationCounter<=NumberOfIterations; IterationCounter++){
- remainingdeck.SetDeck(deck.NumberOfCardType1,deck.NumberOfCardType2,deck.NumberOfCardType3,deck.NumberOfCardType4,deck.NumberOfCardType5);
- int Outcome=0;
- if (!PlayVsChancellor) {Outcome=SimulateGameVsFlame(remainingdeck);}
- if (PlayVsChancellor) {Outcome=SimulateGameVsChancellor(remainingdeck);}
- if (Outcome==0) {NumberOfGamesWithfavorableOutcome++; NumberOfGames++;}
- if (Outcome==1) {NumberOfGames++;}
- }
- return NumberOfGamesWithfavorableOutcome/(NumberOfGames+0.0);
- }//end of AverageKillTurnForRandomHand
- static int SimulateGameVsFlame(Deck HateDeck) {
- int TypeOfCardDrawn=1;
- int Outcome=1; //1 corresponds to a loss; 0 corresponds to a win
- int NrShoal=0;
- int NrArcher=0;
- int NrForest=0;
- int NrLeyline=0;
- int ForestInPlay=0;
- int ArcherInPlay=0;
- int HatePlayerLife=20;
- for (int CardsDrawn=0; CardsDrawn<7; CardsDrawn++){
- TypeOfCardDrawn=HateDeck.DrawCard();
- if (TypeOfCardDrawn==1) {NrLeyline++;}
- if (TypeOfCardDrawn==2) {NrShoal++;}
- if (TypeOfCardDrawn==3) {NrArcher++;}
- if (TypeOfCardDrawn==4) {NrForest++;}
- }
- boolean WeHaveLeyline=false;
- if (NrLeyline>=1) {WeHaveLeyline=true;}
- Random generator = new Random();
- boolean OnThePlay=generator.nextBoolean(); //This refers to whether the Hate player is on the play or not
- Deck FlameDeck=new Deck();
- FlameDeck.SetDeck(31,29,0,0,0);
- int NrFlames=0;
- int NrSSG=0;
- int ApesInPlay=0;
- int FlamePlayerLife=20;
- //CardType 1 is a SSG
- //CardType 2 is a SurgFlame
- //CardType 3-5 are not used
- for (int CardsDrawn=0; CardsDrawn<7; CardsDrawn++){
- TypeOfCardDrawn=FlameDeck.DrawCard();
- if (TypeOfCardDrawn==1) {NrSSG++;}
- if (TypeOfCardDrawn==2) {NrFlames++;}
- }
- boolean FlamePlayerWon=false;
- boolean HatePlayerWon=false;
- if (WeHaveLeyline) {
- if (!OnThePlay) {
- for (int Turn=1; Turn<=53; Turn++){
- if (!FlamePlayerWon && !HatePlayerWon){
- //FlamePlayerTurn
- int NrTrades=Math.min(ApesInPlay, ArcherInPlay);
- ArcherInPlay=ArcherInPlay-NrTrades;
- ApesInPlay=ApesInPlay-NrTrades;
- HatePlayerLife=HatePlayerLife-2*ApesInPlay;
- if (HatePlayerLife<=0) {FlamePlayerWon=true;}
- if (Turn>1){
- TypeOfCardDrawn=FlameDeck.DrawCard();
- if (TypeOfCardDrawn==1) {NrSSG++;}
- }
- if (NrSSG>=4) {ApesInPlay++; NrSSG=NrSSG-4;}
- //HatePlayerTurn
- NrTrades=Math.min(ApesInPlay, ArcherInPlay);
- ArcherInPlay=ArcherInPlay-NrTrades;
- ApesInPlay=ApesInPlay-NrTrades;
- FlamePlayerLife=FlamePlayerLife-2*ArcherInPlay;
- if (FlamePlayerLife<=0) {HatePlayerWon=true;}
- TypeOfCardDrawn=HateDeck.DrawCard();
- if (TypeOfCardDrawn==2) {NrShoal++;}
- if (TypeOfCardDrawn==3) {NrArcher++;}
- if (TypeOfCardDrawn==4) {NrForest++;}
- if (NrForest>=1) {ForestInPlay++; NrForest--;}
- ArcherInPlay=ArcherInPlay+Math.min(ForestInPlay/2, NrArcher);
- NrArcher=NrArcher-Math.min(ForestInPlay/2, NrArcher);
- if (NrShoal>=2) {HatePlayerLife=HatePlayerLife+2; NrShoal=NrShoal-2;}
- }
- }
- if (HatePlayerWon) {Outcome=0;} else {Outcome=1;}
- //In case neither player's life total was reduced to 0 after all those turns (because everything traded) then the hate player, who was on the draw, loses to decking
- }
- if (OnThePlay) {
- for (int Turn=1; Turn<=53; Turn++){
- if (!FlamePlayerWon && !HatePlayerWon){
- //HatePlayerTurn
- int NrTrades=Math.min(ApesInPlay, ArcherInPlay);
- ArcherInPlay=ArcherInPlay-NrTrades;
- ApesInPlay=ApesInPlay-NrTrades;
- FlamePlayerLife=FlamePlayerLife-2*ArcherInPlay;
- if (FlamePlayerLife<=0) {HatePlayerWon=true;}
- if (Turn>1){
- TypeOfCardDrawn=HateDeck.DrawCard();
- if (TypeOfCardDrawn==2) {NrShoal++;}
- if (TypeOfCardDrawn==3) {NrArcher++;}
- if (TypeOfCardDrawn==4) {NrForest++;}
- }
- if (NrForest>=1) {ForestInPlay++; NrForest--;}
- ArcherInPlay=ArcherInPlay+Math.min(ForestInPlay/2, NrArcher);
- NrArcher=NrArcher-Math.min(ForestInPlay/2, NrArcher);
- if (NrShoal>=2) {HatePlayerLife=HatePlayerLife+2; NrShoal=NrShoal-2;}
- //FlamePlayerTurn
- NrTrades=Math.min(ApesInPlay, ArcherInPlay);
- ArcherInPlay=ArcherInPlay-NrTrades;
- ApesInPlay=ApesInPlay-NrTrades;
- HatePlayerLife=HatePlayerLife-2*ApesInPlay;
- if (HatePlayerLife<=0) {FlamePlayerWon=true;}
- TypeOfCardDrawn=FlameDeck.DrawCard();
- if (TypeOfCardDrawn==1) {NrSSG++;}
- if (NrSSG>=4) {ApesInPlay++; NrSSG=NrSSG-4;}
- }
- }
- if (FlamePlayerWon) {Outcome=1;} else {Outcome=0;}
- //In case neither player's life total was reduced to 0 after all those turns (because everything traded) then the Flame player, who was on the draw, loses to decking
- }
- }
- if (!WeHaveLeyline) {
- //We'll assume for convenience that the Flame player never hardcasts Simian Spirit Guide. This need not be optimal but it's a close approximation.
- if (!OnThePlay) {
- for (int Turn=1; Turn<=53; Turn++){
- if (!FlamePlayerWon && !HatePlayerWon){
- if (NrShoal>=2) {HatePlayerLife=HatePlayerLife+2; NrShoal=NrShoal-2;}
- //FlamePlayerTurn
- if (Turn>1){
- if (FlameDeck.NrOfCards()>0) {TypeOfCardDrawn=FlameDeck.DrawCard();} else {TypeOfCardDrawn=1;} //SSGs are rippled to the bottom
- if (TypeOfCardDrawn==1) {NrSSG++;}
- if (TypeOfCardDrawn==2) {NrFlames++;}
- }
- int CastableFlames=Math.min(NrSSG/2,NrFlames);
- int TotDMG=0;
- NrSSG=NrSSG-2*CastableFlames;
- NrFlames=NrFlames-CastableFlames;
- if (CastableFlames>0){
- do {
- CastableFlames--; TotDMG=TotDMG+2;
- for (int i=1; i<=4; i++){
- if (FlameDeck.NrOfCards()>0){TypeOfCardDrawn=FlameDeck.DrawCard();}
- if (TypeOfCardDrawn==2) {CastableFlames++;}
- }
- } while (CastableFlames>0 && TotDMG<20);
- }
- HatePlayerLife=HatePlayerLife-TotDMG;
- if (HatePlayerLife<=0) {FlamePlayerWon=true;}
- //HatePlayerTurn
- FlamePlayerLife=FlamePlayerLife-2*ArcherInPlay;
- if (FlamePlayerLife<=0) {HatePlayerWon=true;}
- TypeOfCardDrawn=HateDeck.DrawCard();
- if (TypeOfCardDrawn==2) {NrShoal++;}
- if (TypeOfCardDrawn==3) {NrArcher++;}
- if (TypeOfCardDrawn==4) {NrForest++;}
- if (NrForest>=1) {ForestInPlay++; NrForest--;}
- ArcherInPlay=ArcherInPlay+Math.min(ForestInPlay/2, NrArcher);
- NrArcher=NrArcher-Math.min(ForestInPlay/2, NrArcher);
- //System.out.println("Turn "+Turn+": HatePlayerLife "+HatePlayerLife+", FlamePlayerLife "+FlamePlayerLife);
- }
- }
- if (FlamePlayerWon){Outcome=1;} else if (HatePlayerWon){Outcome=0;}
- }
- if (OnThePlay) {
- for (int Turn=1; Turn<=53; Turn++){
- if (!FlamePlayerWon && !HatePlayerWon){
- if (NrShoal>=2) {HatePlayerLife=HatePlayerLife+2; NrShoal=NrShoal-2;}
- //HatePlayerTurn
- FlamePlayerLife=FlamePlayerLife-2*ArcherInPlay;
- if (FlamePlayerLife<=0) {HatePlayerWon=true;}
- if (Turn>1){
- TypeOfCardDrawn=HateDeck.DrawCard();
- if (TypeOfCardDrawn==2) {NrShoal++;}
- if (TypeOfCardDrawn==3) {NrArcher++;}
- if (TypeOfCardDrawn==4) {NrForest++;}
- }
- if (NrForest>=1) {ForestInPlay++; NrForest--;}
- ArcherInPlay=ArcherInPlay+Math.min(ForestInPlay/2, NrArcher);
- NrArcher=NrArcher-Math.min(ForestInPlay/2, NrArcher);
- //FlamePlayerTurn
- if (FlameDeck.NrOfCards()>0) {TypeOfCardDrawn=FlameDeck.DrawCard();} else {TypeOfCardDrawn=1;} //SSGs are rippled to the bottom
- if (TypeOfCardDrawn==1) {NrSSG++;}
- if (TypeOfCardDrawn==2) {NrFlames++;}
- int CastableFlames=Math.min(NrSSG/2,NrFlames);
- int TotDMG=0;
- NrSSG=NrSSG-2*CastableFlames;
- NrFlames=NrFlames-CastableFlames;
- if (CastableFlames>0){
- do {
- CastableFlames--; TotDMG=TotDMG+2;
- for (int i=1; i<=4; i++){
- if (FlameDeck.NrOfCards()>0){TypeOfCardDrawn=FlameDeck.DrawCard();}
- if (TypeOfCardDrawn==2) {CastableFlames++;}
- //We'll assume for convenience that the other cards remain exiled rather than going to the bottom, but this shouldn't realistially matter
- }
- } while (CastableFlames>0 && TotDMG<20);
- }
- HatePlayerLife=HatePlayerLife-TotDMG;
- if (HatePlayerLife<=0) {FlamePlayerWon=true;}
- }
- }
- if (HatePlayerWon){Outcome=0;} else if (FlamePlayerWon){Outcome=1;}
- }
- }
- return Outcome;
- }
- static int SimulateGameVsChancellor(Deck fulldeck) {
- int TypeOfCardDrawn;
- int Outcome=1; //1 corresponds to a loss; 0 corresponds to a win
- int NrShoal=0;
- int NrArcher=0;
- int NrForest=0;
- int ForestInPlay=0;
- int ArcherInPlay=0;
- for (int CardsDrawn=0; CardsDrawn<7; CardsDrawn++){
- TypeOfCardDrawn=fulldeck.DrawCard();
- if (TypeOfCardDrawn==2) {NrShoal++;}
- if (TypeOfCardDrawn==3) {NrArcher++;}
- if (TypeOfCardDrawn==4) {NrForest++;}
- }
- boolean WeCanGain2=false;
- if (NrShoal>=2) {
- WeCanGain2=true;
- }
- else if (NrShoal==1 && NrArcher>=1){
- NrArcher--;
- WeCanGain2=true;
- }
- if (WeCanGain2) {
- Random generator = new Random();
- boolean OnThePlay=generator.nextBoolean();
- if (OnThePlay) {Outcome=0;} //If we survive the Chancellors then we'll eventually deck our opponent
- if (!OnThePlay) {
- int OppLife=20+3*7;
- for (int Turn=1; Turn<=53; Turn++){
- OppLife=OppLife-2*ArcherInPlay;
- TypeOfCardDrawn=fulldeck.DrawCard();
- if (TypeOfCardDrawn==3) {NrArcher++;}
- if (TypeOfCardDrawn==4) {NrForest++;}
- if (NrForest>=1) {ForestInPlay++; NrForest--;}
- ArcherInPlay=ArcherInPlay+Math.min(ForestInPlay/2, NrArcher);
- NrArcher=NrArcher-Math.min(ForestInPlay/2, NrArcher);
- }
- if (OppLife<0) {Outcome=0;}
- }
- }
- //In other cases (we weren't able to gain 2 in response, or our deck had so few Archers that we got decked) Outcome remains at 1, i.e., a loss
- return Outcome;
- }//end of SimulateGame
- }
- class OpeningHand {
- int NumberOfLands;
- int NumberOfCardType2;
- int NumberOfCardType3;
- int NumberOfCardType4;
- int NumberOfSpells;
- int NrOfCards(){
- return NumberOfLands+NumberOfCardType2+NumberOfCardType3+NumberOfCardType4+NumberOfSpells;
- }
- void SetHand (int Nr1, int Nr2, int Nr3, int Nr4, int Nr5) {
- NumberOfLands=Nr1;
- NumberOfCardType2=Nr2;
- NumberOfCardType3=Nr3;
- NumberOfCardType4=Nr4;
- NumberOfSpells=Nr5;
- }
- }//end of OpeningHand
- class Deck {
- int NumberOfCardType1;
- int NumberOfCardType2;
- int NumberOfCardType3;
- int NumberOfCardType4;
- int NumberOfCardType5;
- void SetDeck (int Nr1, int Nr2, int Nr3, int Nr4, int Nr5) {
- NumberOfCardType1=Nr1;
- NumberOfCardType2=Nr2;
- NumberOfCardType3=Nr3;
- NumberOfCardType4=Nr4;
- NumberOfCardType5=Nr5;
- }
- int NrOfCards(){
- return NumberOfCardType1+NumberOfCardType2+NumberOfCardType3+NumberOfCardType4+NumberOfCardType5;
- }
- int DrawCard (){
- Random generator = new Random();
- int CardType=0;
- int RandomIntegerBetweenOneAndDeckSize=generator.nextInt( this.NrOfCards() )+1;
- int OneCutoff=NumberOfCardType1;
- int TwoCutoff=OneCutoff+NumberOfCardType2;
- int ThreeCutoff=TwoCutoff+NumberOfCardType3;
- int FourCutoff=ThreeCutoff+NumberOfCardType4;
- int FiveCutoff=FourCutoff+NumberOfCardType5;
- if (RandomIntegerBetweenOneAndDeckSize<=OneCutoff) {CardType=1; this.NumberOfCardType1--;}
- if (RandomIntegerBetweenOneAndDeckSize>OneCutoff && RandomIntegerBetweenOneAndDeckSize<=TwoCutoff) {CardType=2; this.NumberOfCardType2--;}
- if (RandomIntegerBetweenOneAndDeckSize>TwoCutoff && RandomIntegerBetweenOneAndDeckSize<=ThreeCutoff) {CardType=3; this.NumberOfCardType3--;}
- if (RandomIntegerBetweenOneAndDeckSize>ThreeCutoff && RandomIntegerBetweenOneAndDeckSize<=FourCutoff) {CardType=4; this.NumberOfCardType4--;}
- if (RandomIntegerBetweenOneAndDeckSize>FourCutoff && RandomIntegerBetweenOneAndDeckSize<=FiveCutoff) {CardType=5; this.NumberOfCardType5--;}
- return CardType;
- }
- }//end of Deck
Add Comment
Please, Sign In to add comment