Risk Simulation Help
BlitzMax Forums/BlitzMax Beginners Area/Risk Simulation Help
| ||
Hello all! I've been working on a simulation for a game of risk in order to determine probabilities of victory as the armies stack up. I've encountered a problem however. For some reason, the numbers are not being as random as they should be. Below, a = attack victories, and d = defense victories. The problem is that every other result, the attacker gets a 100% chance of victory no matter the odds. So, at attackarmies = 3 and defensearmies = 6 I got attacker wins 100% of the time, but at attackarmies = 4 defensearmies = 3 the defense has a 21% chance of victory. I think it may have something to do with the random number generator I have set. Help please?a = 0 d = 0 Repeat attackarmies = 12 defencearmies = 6 Repeat attack1 = (Rnd(1)*5 + 1) attack2 = (Rnd(1)*5 + 1) attack3 = (Rnd(1)*5 + 1) defence1 = (Rnd(1)*5 + 1) defence2 = (Rnd(1)*5 + 1) If attack1 >= attack2 If attack1 >= attack3 attackhigh = attack1 If attack2 >= attack3 attackmed = attack2 Else attackmed = attack3 EndIf Else attackhigh = attack3 If attack1 >= attack2 attackmed = attack1 Else attackmed = attack2 EndIf EndIf Else If attack2 >= attack3 attackhigh = attack2 If attack1 >= attack3 attackmed = attack1 Else attackmed = attack3 EndIf Else attackhigh = attack3 If attack1 >= attack2 attackmed = attack1 Else attackmed = attack2 EndIf EndIf EndIf If defence1 >= defence2 defencehigh = defence1 defencelow = defence2 Else defencehigh = defence2 defencelow = defence1 EndIf If defencehigh >= attackhigh attackarmies = attackarmies-1 Else defencearmies = defencearmies-1 EndIf If defencelow >= attackmed attackarmies = attackarmies - 1 Else defencearmies = defencearmies-1 EndIf Until defencearmies < 2 Or attackarmies < 3 Repeat If defencearmies < 2 defence1 = (Rnd(1)*5 + 1) defencelow = defence1 defencehigh = defence1 Else defence1 = (Rnd(1)*5 + 1) defence2 = (Rnd(1)*5 + 1) If defence1 >= defence2 defencehigh = defence1 defencelow = defence2 Else defencehigh = defence2 defencelow = defence1 EndIf EndIf If attackarmies = 2 attack1 = (Rnd(1)*5 + 1) attack2 = (Rnd(1)*5 + 1) If attack1 >= attack2 attackhigh = attack1 attackmed = attack2 Else attackhigh = attack2 attackmed = attack1 EndIf EndIf If attackarmies = 1 attack1 = (Rnd(1)*5 + 1) attackhigh = attack1 attackmed = attack1 EndIf If attackarmies >= 3 attack1 = (Rnd(1)*5 + 1) attack2 = (Rnd(1)*5 + 1) attack3 = (Rnd(1)*5 + 1) If attack1 >= attack2 If attack1 >= attack3 attackhigh = attack1 If attack2 >= attack3 attackmed = attack2 Else attackmed = attack3 EndIf Else attackhigh = attack3 If attack1 >= attack2 attackmed = attack1 Else attackmed = attack2 EndIf EndIf Else If attack2 >= attack3 attackhigh = attack2 If attack1 >= attack3 attackmed = attack1 Else attackmed = attack3 EndIf Else attackhigh = attack3 If attack1 >= attack2 attackmed = attack1 Else attackmed = attack2 EndIf EndIf EndIf EndIf If defencehigh >= attackhigh attackarmies = attackarmies-1 Else defencearmies = defencearmies-1 EndIf If defencelow >= attackmed attackarmies = attackarmies - 1 Else defencearmies = defencearmies-1 EndIf Until attackarmies Or defencearmies = 0 If attackarmies = 0 d = d+1 EndIf If defencearmies = 0 a = a+1 EndIf Until a + d =10000 Print "a = " + a Print "d = " + d Print "end" WaitKey() |
| ||
As somebody with little people in the family, can I ask is there a particular reason you are using such a socially unacceptable and offensive user name? Or are you just a jerk? You can't claim you don't know it is offensive, as you are in the USA, so you know this is the same as using the N word or other vulgar and cruel words to describe those different than you. |
| ||
I know some people like that and none of them have ever been offended. You are right that I should have recognized that some people would be though. I simply made it that out of force of habit, as I've never encountered a site where it was taken. I really need to break that habit. Sorry. |
| ||
apology accepted. |
| ||
First off, if you're trying to simulate a dice roll, your rand function never returns a six. Secondly you really should seed the random value or every run of the code will always give the same results. Here's a little tester that does both those things;SuperStrict SeedRnd( MilliSecs() ) Local results:Int[6] Local r:Int Print "your random:" For Local i:Int = 0 To 100000 r = (Rnd(1)*5 + 1) results[r-1] :+ 1 Next For Local i:Int = 0 To 5 Print (i + 1) + "'s = " + results[i] results[i] = 0 Next Print "~nalt random:" For Local i:Int = 0 To 100000 r = (Rnd(1)*6 + 1) results[r-1] :+ 1 Next For Local i:Int = 0 To 5 Print (i + 1) + "'s = " + results[i] Next Finally I know nothing about Risk, but the problems are probably in your convoluted logic somewhere. Here's a much simpler way of sorting values into Low/Med/High using arrays, Constant values and Sort() SuperStrict SeedRnd( MilliSecs() ) Const LOW:Int = 0 Const MED:Int = 1 Const HIGH:Int = 2 Local attack:Int[3] For Local i:Int = 0 To 2 attack[i] = RollDice() Next attack.Sort() Print attack[ LOW ] Print attack[ MED ] Print attack[ HIGH ] Function RollDice:Int() Local result:Int = (Rnd(1)*6 + 1) Assert( 0 < result And result < 7 ) Return result End Function Hope that helps! |
| ||
Thanks, but could you tell me what the second code is actually saying? This is really the first code I've ever written and am unfamiliar with many of the codes. |
| ||
I'm sorry I can't go over everything in too fine a detail. Try reading the excellent tutorial here: http://www.truplo.com/blitzmaxbeginnersguide/ Remember you can select keywords in the IDE and press F1 twice to see their documentation. I'll add some comments, maybe that will help a little.. SuperStrict 'Really strict code formatting enforcement catches lots of silly errors SeedRnd( MilliSecs() ) ' Seed the rand function so it spits out different results each time the program runs ' CONST-ant values never change during the execution of you program and are safer than trying to remember things like "is LOW zero? or is it one??" Const LOW:Int = 0 Const MED:Int = 1 Const HIGH:Int = 2 Local attack:Int[3] ' using an array to hold three attack values For Local i:Int = 0 To 2 attack[i] = RollDice() ' set the three attach values Next attack.Sort() ' sort the values in numerical order ' output the attack values (which will be sorted, and between 1 and 6 inclusive) Print attack[ LOW ] Print attack[ MED ] Print attack[ HIGH ] ' I turned the Rand(...) call into a function in its own right Function RollDice:Int() Local result:Int = (Rnd(1)*6 + 1) ' in a debug build an Assert tests the code condition ' and stops app execution if the test condition fails ' Here we are just proving that the rollDice function always outputs ' a value we are expecting. ' A bit silly and pointless, but you never know, and asserts can ' be very, very useful in other, situations like this Assert( 0 < result And result < 7 ) Return result End Function |