'The next lines are only needed for manual testing
DIM DiceToRoll
AS DiceRoller_Type
'Feel free to change options as wanted for your program
'DiceToRoll.NumberOfDice = 2
'DiceToRoll.DiceSides = 10
'DiceToRoll.DiceReroll = "=1"
'DiceToRoll.DiceOpenRoll = "=10"
'DiceToRoll.DiceMod = 2
'DiceToRoll.DiceKeepHigh = 1
'DiceToRoll.DiceKeepLow = 1
'DiceToRoll.Set = 10
'DiceToRoll.SetMod = 1
'DiceToRoll.SetReRoll = "<6"
'DiceToRoll.SetOpenRoll = ">10"
'DiceToRoll.TotalMod = 27
'DiceToRoll.SetKeepHigh = 9
PRINT RollEm$
("10skh9r2;2d10o20;t2;b2")
PRINT "PRESS <ANY KEY> TO CONTINUE"
ClearDice
DiceToRoll.Set = 6
DiceToRoll.NumberOfDice = 4
DiceToRoll.DiceSides = 6
DiceToRoll.DiceKeepHigh = 3
Brief = 0
PRINT "NON-BRIEF OUTPUT:" PRINT "'6s; 4d6 kh3' -- Roll 6 sets of 4 six-sided dice, keep the three highest" PRINT "PRESS <ANY KEY> TO CONTINUE"
Brief = 1
PRINT "SEMI-BRIEF OUTPUT:" PRINT "'6s; 4d6 kh3' -- Roll 6 sets of 4 six-sided dice, keep the three highest" PRINT "PRESS <ANY KEY> TO CONTINUE"
Brief = 2
PRINT "MOST BRIEF OUTPUT:" PRINT "'6s; 4d6 kh3' -- Roll 6 sets of 4 six-sided dice, keep the three highest" PRINT "PRESS <ANY KEY> TO CONTINUE"
'PRINT "Stripping number"; m$
DiceToRoll.Set = 0
DiceToRoll.SetMod = 0
DiceToRoll.SetReRoll = ""
DiceToRoll.NumberOfDice = 0
DiceToRoll.DiceSides = 0
DiceToRoll.DiceMod = 0
DiceToRoll.DiceReroll = ""
DiceToRoll.DiceOpenRoll = ""
DiceToRoll.DiceKeepHigh = 0
DiceToRoll.DiceKeepLow = 0
DiceToRoll.DiceDiscardHigh = 0
DiceToRoll.DiceDiscardLow = 0
DiceToRoll.TotalMod = 0
IF DiceToRoll.DiceKeepHigh
OR DiceToRoll.DiceKeepLow
THEN IF DiceToRoll.DiceDiscardHigh
OR DiceToRoll.DiceDiscardLow
THEN DiceRoll$
= "Error - Can not keep and discard at the same time.":
EXIT FUNCTION
SetCount = 0
FOR j
= 1 TO DiceToRoll.Set
ReRollSet:
SetTotal = 0
rollcount = -1
FOR i
= 1 TO DiceToRoll.NumberOfDice
ReRollDice:
roll
= INT(RND(1) * DiceToRoll.DiceSides
) + 1
IF ParseDiceOption
(roll
, DiceToRoll.DiceReroll
) THEN DiceOK = 0
IF ParseDiceOption
(roll
, DiceToRoll.DiceOpenRoll
) THEN DiceOK = 0
DiceTotal = DiceTotal + roll + DiceToRoll.DiceMod
rollcount = rollcount + 1
REDIM _PRESERVE rolls
(rollcount
) AS LONG 'make certain we dont get out of bound errors for crazy reroll scenarios rolls(rollcount) = roll + DiceToRoll.DiceMod
rollcount = rollcount + 1
REDIM _PRESERVE rolls
(rollcount
) AS LONG 'make certain we dont get out of bound errors for crazy reroll scenarios rolls(rollcount) = roll + DiceToRoll.DiceMod
DiceTotal = DiceTotal + roll + DiceToRoll.DiceMod
IF i
< DiceToRoll.NumberOfDice
THEN 'more dice to roll in this set
IF rollcount
> 0 THEN Sort rolls
() 'No need to try and sort only 1 dice.
IF DiceToRoll.DiceKeepHigh
OR DiceToRoll.DiceKeepLow
THEN IF DiceToRoll.DiceKeepHigh
THEN FOR i
= DiceToRoll.DiceKeepHigh
- 1 TO 0 STEP -1 IF i
< rollcount
THEN keep
(rollcount
- i
) = -1 IF DiceToRoll.DiceKeepLow
THEN FOR i
= 0 TO DiceToRoll.DiceKeepLow
- 1 IF i
< rollcount
THEN keep
(i
) = -1 ELSEIF DiceToRoll.DiceDiscardHigh
OR DiceToRoll.DiceDiscardLow
THEN keep(i) = -1
IF DiceToRoll.DiceDiscardHigh
THEN FOR i
= DiceToRoll.DiceDiscardHigh
- 1 TO 0 STEP -1 IF i
< rollcount
THEN keep
(rollcount
- i
) = 0 IF DiceToRoll.DiceDiscardLow
THEN FOR i
= 0 TO DiceToRoll.DiceDiscardLow
- 1 IF i
< rollcount
THEN keep
(i
) = 0 keep(i) = -1
KeepTotal = 0
kept = 0
kept = kept + 1
KeepTotal = KeepTotal + rolls(i)
IF ParseDiceOption
(KeepTotal
, DiceToRoll.SetReRoll
) THEN
IF ParseDiceOption
(KeepTotal
, DiceToRoll.SetOpenRoll
) THEN SetTotal = SetTotal + KeepTotal + DiceToRoll.SetMod
SetCount = SetCount + 1
SetRolls(SetCount) = SetTotal
GrandTotal = GrandTotal + SetTotal
SetTotal = SetTotal + KeepTotal + DiceToRoll.SetMod
SetCount = SetCount + 1
SetRolls(SetCount) = SetTotal
GrandTotal = GrandTotal + SetTotal
GrandTotal = GrandTotal + DiceToRoll.TotalMod
Sort SetRolls()
IF DiceToRoll.SetKeepHigh
OR DiceToRoll.SetKeepLow
THEN IF DiceToRoll.SetKeepHigh
THEN FOR i
= DiceToRoll.SetKeepHigh
- 1 TO 0 STEP -1 IF i
< SetCount
THEN keep
(SetCount
- i
) = -1 FOR i
= 0 TO DiceToRoll.SetKeepLow
- 1 IF i
< SetCount
THEN keep
(i
) = -1 ELSEIF DiceToRoll.SetDiscardHigh
OR DiceToRoll.SetDiscardLow
THEN keep(i) = -1
IF DiceToRoll.SetDiscardHigh
THEN FOR i
= DiceToRoll.SetDiscardHigh
- 1 TO 0 STEP -1 IF i
< SetCount
THEN keep
(SetCount
- i
) = 0 IF DiceToRoll.SetDiscardLow
THEN FOR i
= 0 TO DiceToRoll.SetDiscardLow
- 1 IF i
< SetCount
THEN keep
(i
) = 0 keep(i) = -1
KeepTotal = 0
keep = 0
keep = keep + 1
KeepTotal = KeepTotal + SetRolls(i)
KeepTotal = KeepTotal + DiceToRoll.TotalMod
temp$
= MID$(temp$
, f
+ 1)
'The dice sorting routine, optimized to use _MEM and a comb sort algorithm.
'It's more than fast enough for our needs here I think. ;)
gap = rollcount
gap = 10 * gap \ 13
i = 0
swapped = 0
o = m.OFFSET + i * 4
o1 = m.OFFSET + (i + gap) * 4
swapped = -1
i = i + 1
FOR i
= 1 TO LEN(text1$
) 'check for invalid characters CASE "0" TO "9", "+", "-", "D", "K", "H", "L", "S", "T", ";", "=", "<", ">", ",", "R", "O", "B" text$ = text$ + m$ 'add valid characters to make text$
CASE " " 'do nothing to a space 'invalid
'IF DiagRollEM THEN PRINT "Verified: "; text$
IF text$
= "" THEN EXIT SUB 'can't do nothing with an empty string ClearDice
semicolon
= INSTR(text$
, ";") l$
= LEFT$(text$
, semicolon
- 1) text$
= MID$(text$
, semicolon
+ 1) l$ = text$
'IF DiagRollEM THEN PRINT "PROCESSING: "; l$
found = 0
IF found
<> 1 THEN EXIT SUB 'we should only find ONE element each pass, and there should always be one. IF not, somebody screwed up.
IF DiagRollEm
THEN PRINT "Number of Sets = "; DiceToRoll.Set
pass = 0
pass = pass + 1
'IF DiagRollEM THEN PRINT "SUBPROC "; m$
IF v
> 0 THEN DiceToRoll.SetMod
= v
IF v
> 0 THEN DiceToRoll.SetMod
= -v
IF v
> 0 THEN DiceToRoll.SetKeepHigh
= v
IF DiagRollEm
THEN PRINT "Keep the Highest"; v;
" Sets" IF v
> 0 THEN DiceToRoll.SetKeepLow
= v
IF v
> 0 THEN DiceToRoll.SetDiscardHigh
= v
IF DiagRollEm
THEN PRINT "Discard the Highest"; v;
" Sets" IF v
> 0 THEN DiceToRoll.SetDiscardLow
= v
IF DiagRollEm
THEN PRINT "Discard the Lowest"; v;
" Sets" CASE "R", "O" 'reroll or open roll finished = 0: t$ = "": innerpass = 0
innerpass = innerpass + 1
IF v
<> 0 THEN 'it's an o/r followed by a number CASE ELSE 'a character not a number, or =<>, finished = -1
StripNumber m$
DiceToRoll.SetReRoll = t$
IF DiagRollEm
THEN PRINT "Reroll Sets "; DiceToRoll.SetReRoll
DiceToRoll.SetOpenRoll = t$
IF DiagRollEm
THEN PRINT "Openroll Sets "; DiceToRoll.SetOpenRoll
StripNumber m$
CASE "K", "D", "R", "O", "+", "-" 'see if it's another command without a comma
IF v
< 1 THEN DiceToRoll.NumberOfDice
= 1 ELSE DiceToRoll.NumberOfDice
= v
IF DiagRollEm
THEN PRINT "Number of Dice To Roll = "; DiceToRoll.NumberOfDice
IF v
> 0 THEN DiceToRoll.DiceSides
= v
StripNumber m$
IF DiagRollEm
THEN PRINT "Dice Sides = "; DiceToRoll.DiceSides
pass = 0
pass = pass + 1
'IF DiagRollEM THEN PRINT "SUBPROC "; m$
IF v
> 0 THEN DiceToRoll.DiceMod
= v
IF v
> 0 THEN DiceToRoll.DiceMod
= -v
IF v
> 0 THEN DiceToRoll.DiceKeepHigh
= v
IF v
> 0 THEN DiceToRoll.DiceKeepLow
= v
IF v
> 0 THEN DiceToRollDiceDiscardHigh
= v
IF v
> 0 THEN DiceToRoll.DiceDiscardLow
= v
CASE "R", "O" 'reroll or open roll finished = 0: t$ = "": innerpass = 0
innerpass = innerpass + 1
IF v
<> 0 THEN 'it's an o/r followed by a number CASE ELSE 'a character not a number, or =<>, finished = -1
StripNumber m$
DiceToRoll.DiceReroll = t$
DiceToRoll.DiceOpenRoll = t$
IF DiagRollEm
THEN PRINT "DO: "; DiceToRoll.DiceOpenRoll
StripNumber m$
CASE "K", "D", "R", "O", "+", "-" 'see if it's another command without a comma
DiceToRoll.TotalMod
= VAL(MID$(l$
, 2)) IF DiagRollEm
THEN PRINT "Dice Total Modifier = "; DiceToRoll.TotalMod
IF DiagRollEm
THEN PRINT "Roll Information Displayed: ";
RollEm$ = DiceRoll$