[Home]AlexChurchill/GeneratorMaths

ec2-3-81-28-94.compute-1.amazonaws.com | ToothyWiki | AlexChurchill | RecentChanges | Login | Webcomic

A generic include for generators, used by AlexChurchill/MagicCardGenerator and ChrisHowlett/BetaExaltedStatsGenerator, possibly others. Those are the interesting pages, and you probably want to be there.

BNF: AlexChurchill/GeneratorMaths should run some self-tests.

Maths


// Numbers are dynamically created when needed. All references to succ##num or predec##num must use deep assign unless guaranteed to be heading towards zero.
// Must initialise numbers at least as far as any hard-coded numbers in the generator: mediumpositiveinteger goes up to 7, so I must define succ_7 and predec_-_7
// ChrisHowlett/BetaExaltedStatsGenerator goes up to 9...

option ::= spaces = 0
bnf ::= preliminaryinit "1 + 2 = " <plus_op1::=1> <plus_op2::=2> _plus <numtodisplay::=plus_output> displaynum test2
test2 ::= "
5 - 2 = " <minus_op1::=5> <minus_op2::=2> _minus <numtodisplay::=minus_output> displaynum test3
test3 ::=  "
4 + (-3) = " <plus_op1::=4> <plus_op2::=-_3> _plus <numtodisplay::=plus_output> displaynum test4
test4 ::= "
5 - (-2) = " <minus_op1::=5> <minus_op2::=-_2> _minus <numtodisplay::=minus_output> displaynum test5
test5 ::= "
9 + 8 = " <plus_op1::=9> <plus_op2::=8> _plus <numtodisplay::=plus_output> displaynum test6
test6 ::= "
2 * 4 = " <mult_op1::=2> <mult_op2::=4> _mult <numtodisplay::=mult_output> displaynum test7
test7 ::= "
3 * 0 = " <mult_op1::=3> <mult_op2::=0> _mult <numtodisplay::=mult_output> displaynum test8
test8 ::= "
0 * 6 = " <mult_op1::=0> <mult_op2::=6> _mult <numtodisplay::=mult_output> displaynum test9
test9 ::= "
3 * -4 = " <mult_op1::=3> <mult_op2::=-_4> _mult <numtodisplay::=mult_output> displaynum test10
test10 ::= "
-3 * 7 = " <mult_op1::=-_3> <mult_op2::=7> _mult <numtodisplay::=mult_output> displaynum test11
test11 ::= "
-2 * -5 = " <mult_op1::=-_2> <mult_op2::=-_5> _mult <numtodisplay::=mult_output> displaynum test12
test12 ::= "
Rolling 3d6 six times, the results are: STR " roll3d6 ", INT " roll3d6 ", WIS " roll3d6 ", DEX " roll3d6 ", CON " roll3d6 ", CHA " roll3d6 test13
test13 ::= "
Rolling 4d6 keep high 3 six times, the results are: STR " roll4d6kh3 ", INT " roll4d6kh3 ", WIS " roll4d6kh3 ", DEX " roll4d6kh3 ", CON " roll4d6kh3 ", CHA " roll4d6kh3

preliminaryinit ::= initnumbers initspecialcasenumbers
initnumbers ::= <unitsdigit::=0> <tensdigit::=nothing> <currhalf::=0> <parity##0::=0> <currnum::=0> <prevnum::=-_1> storenewnum storenewnum storenewnum storenewnum storenewnum storenewnum storenewnum storenewnum storenewnum storenewnum

nothing ::= nothing2
nothing2 ::= ""
storenewnum ::= incinitialisednumbers <<nextnum::=bothdigits>> storenum <succ##currnum::=getnextpositivenum> <predec##-##currnum::=getnextnegativenum>
bothdigits ::= tensdigit unitsdigit
incinitialisednumbers ::= <unitsdigit::=digitsucc##unitsdigit> <initnewnum##unitsdigit::=nothing> <initnewnum##0::=inctensdigit> initnewnum##unitsdigit
inctensdigit ::= <tensdigit::=digitsucc##tensdigit>
// The below is what gets evaluated-on-demand when numbers are requested beyond what's currently initialised.
// By the time storenewnum is done, the requested number has been moved to "prevnum"
getnextpositivenum ::= storenewnum prevnum
getnextnegativenum ::= storenewnum <prevnegnum::=-##prevnum> prevnegnum

// storenum mustn't store any ways to reach numbers that haven't been fully initialised. Setting succ##currnum::=nextnum is forbidden, because nextnum isn't fully initialised by this run through storenum. We can store links like predec##nextnum::=currnum, however.
storenum ::= <succ##prevnum::=currnum> <predec##nextnum::=currnum> <succ##-##nextnum::=-##currnum> <predec##-##prevnum::=-##currnum> <sign##currnum::=positive> <sign##-##currnum::=negative> <abs##-##currnum::=currnum> <abs##currnum::=currnum> <thisparity::=parity##currnum> storehalfandparity##thisparity <-##-##currnum::=currnum> <prevnum::=currnum> <currnum::=nextnum>
storehalfandparity_0 ::= <parity##nextnum::=1> <parity##-##nextnum::=1> <half##currnum::=currhalf> <half##-##currnum::=-##currhalf>
storehalfandparity_1 ::= <parity##nextnum::=0> <parity##-##nextnum::=0> <half##currnum::=currhalf> <half##-##currnum::=-##currhalf> <currhalf::=succ##currhalf>

// special cases that don't get set up correctly by the above
initspecialcasenumbers ::= <sign_0::=0> <succ_-_1::=0> <predec_0::=-_1> <half_-_1::=0>

digitsucc_nothing2 ::= 1
digitsucc_0 ::= 1
digitsucc_1 ::= 2
digitsucc_2 ::= 3
digitsucc_3 ::= 4
digitsucc_4 ::= 5
digitsucc_5 ::= 6
digitsucc_6 ::= 7
digitsucc_7 ::= 8
digitsucc_8 ::= 9
digitsucc_9 ::= 0

// Z = X + Y handles cases Y=0 (return X), Y<0 (return X-abs(Y)), and Y>0 (set Z=X, and then repeat Z++, Y-- until Y==0).
_plus ::= <tmp::=sign##plus_op2> __plus##tmp
__plus_0 ::= <plus_output::=plus_op1>
__plus_negative ::= <minus_op1::=plus_op1> <minus_op2::=abs##plus_op2> __minus_positive <plus_output::=minus_output>
__plus_positive ::= <plus_output::=plus_op1> __plus_loop
__plus_loop ::= <<plus_output::=succ##plus_output>> <plus_op2::=predec##plus_op2> <tmp##plus_op2::=__plus_loop> <tmp##0::=nothing> tmp##plus_op2

// Similarly, Z = X - Y handles cases Y=0 (return X), Y<0 (return X+abs(Y)), and Y>0 (set Z=X, and then repeat Z--, Y-- until Y==0).
_minus ::= <tmp::=sign##minus_op2> __minus##tmp
__minus_0 ::= <minus_output::=minus_op1>
__minus_negative ::= <plus_op1::=minus_op1> <plus_op2::=abs##minus_op2> __plus_positive <minus_output::=plus_output>
__minus_positive ::= <minus_output::=minus_op1> __minus_loop
__minus_loop ::= <<minus_output::=predec##minus_output>> <minus_op2::=predec##minus_op2> <tmp##minus_op2::=__minus_loop> <tmp##0::=nothing> tmp##minus_op2

// Similarly again, Z = X * Y handles cases Y=0 or X=0 (return 0), Y<0 (return -X*abs(Y)), and Y>0 (set Z = 0, then repeat Z+=X, Y-- until Y==0)
_mult ::= <tmp::=sign##mult_op1> __multchk1##tmp
__multchk1_0 ::= <multiply_output::=0>
__multchk1_positive ::= <tmp::=sign##mult_op2> __multchk2##tmp
__multchk1_negative ::= <tmp::=sign##mult_op2> __multchk2##tmp
__multchk2_0 ::= <mult_output::=0>
__multchk2_negative ::= <mult_op2::=abs##mult_op2> _mult <<mult_output::=-##mult_output>>
__multchk2_positive ::= <mult_output::=0> __mult_loop
__mult_loop ::= <plus_op1::=mult_output> <plus_op2::=mult_op1> _plus <mult_output::=plus_output> <mult_op2::=predec##mult_op2> <tmp##mult_op2::=__mult_loop> <tmp##0::=nothing> tmp##mult_op2

displaynum ::= <tmp::=sign##numtodisplay> displaynum##tmp
displaynum_0 ::= 0
displaynum_positive ::= numtodisplay
displaynum_negative ::= "-" abs##numtodisplay

// For X > Y, we calculate X-Y, and return true if the result is positive
_greaterthan ::= <minus_op1::=gt_op1> <minus_op2::=gt_op2> _minus <tmp::=sign##minus_output> <gt_output::=_greaterthanresult##tmp>
_greaterthanresult_0 ::= 0
_greaterthanresult_positive ::= true
_greaterthanresult_negative ::= false

// max(X,Y) is X if X>Y or X==Y, Y if X<Y
// this could probably be more efficiently rephrased to use _minus directly, rather than going via _greaterthan
_max ::= <gt_op1::=max_op1> <gt_op2::=max_op2> _greaterthan _maxresult##gt_output
_maxresult_0 ::= <max_output::=gt_op1>
_maxresult_true ::= <max_output::=gt_op1>
_maxresult_false ::= <max_output::=gt_op2>

// Dice
roll3d6 ::= <plus_op1::=rolld6> <plus_op2::=rolld6> _plus <plus_op1::=rolld6> <plus_op2::=plus_output> _plus plus_output
rolld6 ::= 1 | 2 | 3 | 4 | 5 | 6
roll4d6kh3 ::= <die1::=rolld6> <die2::=rolld6> <die3::=rolld6> <die4::=rolld6> <plus_op1::=die1> <plus_op2::=die2> _plus <plus_op1::=die3> <plus_op2::=plus_output> _plus <plus_op1::=die4> <plus_op2::=plus_output> _plus <fourdice::=plus_output> <max_op1::=-##die1> <max_op2::=-##die2> _max <max_op1::=-##die3> <max_op2::=max_output> _max <max_op1::=-##die4> <max_op2::=max_output> _max <plus_op1::=fourdice> <plus_op2::=max_output> _plus plus_output

ec2-3-81-28-94.compute-1.amazonaws.com | ToothyWiki | AlexChurchill | RecentChanges | Login | Webcomic
Edit this page | View other revisions | Recently used referrers
Last edited September 21, 2017 9:57 pm (viewing revision 32, which is the newest) (diff)
Search: