vroman
|
 |
« on: October 01, 2006, 03:32:26 am » |
|
Im writing an article for Starcity concerning Ubastax mulligans. For data I programmed random starting hands and calculated how much mana would be available on the first turn. by no means do I claim to be virtuoso programmer, and thus my system is probably very clunky. I wrote and ran it on the venerable TI83 calculator, as my C++ is incredibly rusty and I didnt want to go to the trouble of finding decent compiler/editor on the internet. its possible something equivalent to this already exists out there, but again, I wasnt interested in hunting around for someone else's solution. writing the program was not too challenging, but tolarian academy's contributions was something of a sticky wicket, and some arbitrary decisions had to be made. for example: [academy, mana crypt, null rod, 4xwelder] this hand technically produces 4 mana, but only if I am willing to cast null rod. to incorporate the tendency for non-mana cards to improve academy's function, I would have to program in the converted cost of every single non-mana artifact. realistically, I DO pump academy in this way almost whenever possible, most notably with chalice. for this reason I compromised and programmed in dropping chalice@0 as a boost to academy, but left all other cards out of the equation. Academy also complicated things by not being able to cast solring/vault by itself, and that lotus might not stick around to pump. The other tricky issue was how to simulate mulligans. If I simulate 100 seven card hands, some number of them are going to produce zero mana. these should not be part of the average, because obviously I would mulligan those hands, and I would not start my turn 1 with zero mana. Instead I should simulate 100 six card hands, and then every time I get a zero mana 7-card hand, I add the avg result of all 6-card hands to my running total, not zero. For 1 mana hands its somewhat different, since there are plenty of keepable 1 mana hands (ie {mtn, welder, chalice, bazaar, duplicant, uba, smoky} or {chalice, strip, waste, waste, rishadan, crucible, null rod}) but I definitely tend to muligan 1 mana hands w no decent plays. thus for 1 mana hands, I substitute the mulligan constant, weighted by the percentage of the time I would mulligan those hands in real life. I assume for the sake of this experiment that I keep all hands that produce 2+ mana, though in reality this is not the case. so my procedure was: simulate 100 five card hands, with average turn 1 mana Z simulate 100 six card hands, where zero mana hands count for Z, and 1 mana hands count for (Z+1)/2, generating average Y simulate 100 seven card hands, where zero mana hands count for Y, and 1 mana hands count for .75Y+.25, generating total average X. The end result of the experiment, with these arbitrary mulligan and academy rules, is that ubastax generates on average 3.69 mana on the first turn.
keep in mind, the program is solely interested in the amount of mana generated on the first turn, not the total amount of mana in the hand. thus: {mtn, mtn, waste, rishadan, b-ring, strip, crucible} gets the exact same score as: {waste, welder, smoky, uba, duplicant, tangle, crucible} no regard is given to overall quality, only the exact amount of mana it produces on the first turn.
first some notes. I built my deck via a 60x1 matrix, w coded numbers: 0=spells/bazaars 1=single mana land 2=workshop 3=black lotus 4=mox 5=sol ring 6=mana vault 7=mana crypt 8=tolarian academy 9=chalice of the void so there are twelve '1's, four '2's, one '3', five '4's, etc.
so heres the program, with my annotations.
:prgmCLRVARS this is a subprogram that stores zero to all variables :7->H H=hand size. variable allows me to simulate mulligans, or after-draw scenarios :60->D D=cards in library. I sometimes made this smaller while de-bugging :100->I I=iterations. how many hands to generate before producing an average. 100 iterations takes approximately 6 minutes for the TI83 to run. perhaps it has to do w my obtuse programming methods :2.85->O O=mulligan substitution constant. this is the end result of running the program w one fewer card in hand, and is what is added to the total, if the hand generates mana below the mulligan threshold. if the simulation is not being run w mulligan possibilities, this line should be deleted. :.5->P P=percentage times mulligan w a 1 mana hand. assuming I will always keep a hand of 2+ mana, but only sometimes keep 1 mana hands, this variable weights 'O' proportionally. again, if no mulligans are being considered, this line should be deleted. :Fill(0,[ B ]) its not necessary to record the hand results in matrix, if all you want is the end avg, but for de-bugging purposes, I liked to be able to see how many instances of each mana result were being generated. this line clears the results matrix, but should be deleted if not in use. :For(G,1,I) this generates 'I' hands. :0->A A=tolarian academy flag. all these flags need to be reset at the beginning of each hand :0->L L=land flag. :0->M M=mana this hand generates :0->Q Q=total amount of mana produced by academy+artifacts. used to compare in hands where there is academy and other lands. :0->S S=mox/manacrypt flag. this tells the program whether sol ring/vault can be used to pump academy. :0->T T=total number of academy pumpers. :0->V V=chalice flag. this flag keeps the program from letting more than one chalice@0 pump academy. :0->W W=workshop flag :Fill(0,[C]) clear the hand matrix :For(B,1,H) begin loop to generate hand :iPart(rand*D)+1->X randomly pick a card :If B>1 :Then :For(E,1,B-1) :While X=[C](E,2) :iPart(randXD)+1->X :End :End :End if this is not the first card, check to make sure this card has not already been picked. :X->[C](B,2) store the card number to compare against future picks :[ A ](X,1)->C extract the code number from the deck list :If C=1 :Then :If L=1 :0->C :1->L :End if the card is single-mana-land, and the land flag has not been tripped, trip the land flag, otherwise, ignore this card. :If C=2 :Then :1->L :1->W :End if the card is workshop, trip both land flag and workshop flag :If C=3 :Then :M+3->M :T+1->T :End if its black lotus, increase mana production by 3, and academy pumps by 1 :If C=4 :Then :M+1->M :T+1->T :1->S :End if its mox, increase mana by 1, academy pumps by 1, and trip mox/crypt flag :If C=7 :Then :M+2->M :T+1->T :1->S :End if its crypt, increase mana by 2, academy pumps by 1, and trip mox/crypt flag :If C=8 :1->A if its academy, trip academy flag :If C=9 :Then :If V=1 :Then :0->C :Else :T+1->T :End :1->V :End if its chalice, and the chalice flag has not been tripped, trip the chalice flag. otherwise ignore this card. :C->[C](B,1) :End input the card in the hand matrix, and go back to beginning of loop :For(B,1,H) start another loop to check more information about hand :[C](B,1)->C extract card code from hand matrix :If C=1 and W=1 :0->[C](B,1) if its single-mana-land, and the workshop flag is tripped, ignore this card. :If C=5 and (M>0 or L=1) :Then :M+1->M :If S=1 :T+1->T :End this block checks whether sol ring is castable. if so, it adds mana. then pumps academy if mox/crypt flag is tripped. :If C=6 and (M>0 or L=1) :Then :M+2->M :If S=1 :T+1->T :End this block checks whether mana vault is castable. if so, mana is increased by 2, then academy is pumped if mox/crypt flag is tripped. :End end of the hand check loop :If W=1 :0->L if we have workshop, ignore single-mana-lands :If A=1 :M+T->Q if we have academy, then calculate how much total mana we have if academy is used. :If L=1 :Then :If Q>M+1 :Then :Q->M :Else :M+1->M :End :End single-mana-land is compared to academy's production (automatically zero if no academy) :If W=1 :Then :If Q>M+3 :Then :Q->M :Else :M+3->M :End :End workshop is compared to academy's production :If A=1 and L=0 and W=0 :Q->M if we have academy, and no other lands, store academy production in mana variable :If M=0 :O->M if this is a mulligan hand, substitute mulligan constant. delete this line if not using mulligans. :If M=1 :O*P+(1-P)->M if this is sometimes mulligan hand, substitute weighted mulligan constant. delete this line if not using mulligans. :If M>0 :[ B ](iPart(M),1)+1->[ B ](iPart(M),1) record mana result in matrix. delete these lines if not recording results. :N+M->N add to overall mana production from all hands :End :Disp N/I final ouput is average mana produced in this number of hands.
|