[squeak-dev] Dice rolling improvement
Stéphane Rollandin
lecteur at zogotounga.net
Wed Apr 15 16:44:25 UTC 2020
Hello,
I implemented an improved version of Random>>#roll: (attached)
It has two more operators, > and <, that can be used to discard
respectively a number of lowest or highest throw results. This is used
to skew the random distribution to the left or to the right.
The idea is illustrated here:
https://www.gmdice.com/blogs/dnd/dice-probability-explained
So for example,
Random roll: '3d6>2'
will roll three d6 and discard two of them, keeping only the best result.
Similarly:
Random roll: '3d6<1'
rolls three d6 and discards the lowest result.
For consistency, the algorithm takes offsets into account:
Random roll: '3d6>2+10'
adds 10 to the two best throws, while
Random roll: '3d6+10>2'
will keep 10 and the best throw among the three d6.
What do you think? Should I submit the code to the inbox?
Stef
-------------- next part --------------
'From Squeak5.3 of 3 March 2020 [latest update: #19431] on 15 April 2020 at 6:21:53 pm'!
!Random methodsFor: 'die rolling' stamp: 'spfa 4/15/2020 18:20'!
roll: diceString
"Roll some dice, DnD-style, according to this mini-grammar:
dice := epxr {pm dice}
pm := '+' | '-' | '<' | '>'
expr := num | num dD | dD numP | num dD numP
dD := 'd' | 'D'
num := digit+
numP := num | '%'"
| stream op results |
stream := diceString readStream.
results := Bag new.
op := #+.
[ | res range dice token s |
token := self diceToken: stream.
token isNumber
ifTrue: [dice := token.
res := token.
token := self diceToken: stream]
ifFalse: [token == $d
ifTrue: [dice := 1]
ifFalse: [self error: 'unknown token' , token]].
token == $d
ifTrue: [token := self diceToken: stream.
token isNumber
ifTrue: [range := token.
token := self diceToken: stream]
ifFalse: [token == $%
ifTrue: [range := 100.
token := self diceToken: stream]
ifFalse: [range := 6]].
res := nil.
s := op == #- ifTrue: [-1] ifFalse: [1].
dice timesRepeat: [
results add: (self nextInt: range) * s]].
res ifNotNil: [
op caseOf: {
[#+] -> [results add: res].
[#-] -> [results add: res negated].
[#>] -> [res timesRepeat: [results remove: results min]].
[#<] -> [res timesRepeat: [results remove: results max]]}].
token ifNil: [^ (results ifEmpty: [^0]) sum].
('+-><' includes: token)
ifFalse: [self error: 'unknown token ' , token].
op := token asSymbol
] repeat! !
More information about the Squeak-dev
mailing list
|