Authoritative Source:
It's up to us, really, as the Project Doco is subject to
improvement/updates just like everything else. The UDR Grammar document
was written for the first draft of the UDR, and I don't think I updated
it when I updated the Possible Die Codes document and set up the
Project - in fact, I'm sure I didn't.
So, of the two, the Possible Die Codes document is more up-to-date, so
that's the one *I'd* be using as Authoritative - and so the Grammar
document, which was used as a guide for the first Parser/Lexer, should
be updated so that it matches what's being done in the new Parser/Lexer.
So follow the Possible Die Codes and we'll update the Grammar - this
should resolve a lot of the issues @Ben raised - plus there's some
notes/thoughts below.
5d12!kt7s5+2d4!kt3s5:
I don't thinks this is legal. Target numbers (& therefore successes) should
only apply to final rolls, not sub rolls, and thus should be the last set of
die-code-elements, and so we should return this as an error (as we should do
with all "illegal rolls"). It's a bit of a contrived example (although a good
one, because it highlights the issue) because I can't think of *any* game
system where you'd want a roll like that - but please chip in people and tell
me I'm wrong.
A similar (legal) roll, without any ambiguity, would be:
({5d12!k}+{2d4!k})t3s5 = 5d12!k+2d4!kt3s5
Anything in the Die Boxes would/should apply to the entire roll - there's no
other way to treat it without going insane - and yes, that means that at the
moment we can't set up a Deadlands Classic Weapon Melee Roll (DLCWMR: eg
3d10!k+2d6!t5s5) because there's no way to specify that a Keep Flag should only
apply to one of the die-sets. - at the moment if you set up the Die Boxes to
Explode, Keep=5, Success=5, and then dropped 3d10 & 2d6 (or put in /roll
3d10+2d6) what you'd get would be:
(3d10!+2d6!)kt5s5
How do we fix this? I'm not sure, but a DLCWMR is the most complex roll I've
ever come across, so maybe we don't need to, as DLCMWRs should be coded into
the Character Sheet.
I think the best way to handle things (via dice code) is to "error" anything
that is ambiguous.
Happy to have a more detailed (group) discussion around this and any other
complex rolls people know about.
1st Issue:
Dice should have precedence over addition, multiplication, etc, so d5+5 =
(d5)+5, and if we want d(5+5) then that's what we need to write. I thought I'd
implied that in the Precedence section of the one of the docos, but I mustn't
have had. a "d" should go right after "{}" and "()" in precedence order.
We don't need and (extra) syntax because we already have it ie "()".
The second example also sort of "goes away" because of the statement above:
"Target numbers (& therefore successes) should only apply to final rolls... and
thus should be the last set of die-code-elements". 5d12!kt7s5+2 (without the
"|") should be interpreted as 5d12!kt7s(5+2) - if we want to add a modifier to
the roll it need to go *before* the "k", etc (or use "()"):
5d12+2!kt7s5 or 5d12!+2kt7s5
I think a good "rule" is to enforce all die rolls and modifiers come before all
keeps, crits, target numbers, etc - thoughts everyone?
2nd Issue:
If you bust the strength part of a DLCWMR then the whole roll is a bust (you're
not strong enough to do any damage - you've got to do some damage with the
strength part to get any damage from the weapon part - & you can't go bust on a
non-strength-part damage roll).
Do we need an extra die code for this? All rolls is Deadlands which we "k1"
also (have the potential to) bust - at least as I can recall (jump in guys and
let me know if I'm wrong). Wouldn't we be better off simple coding that into
the Ruleset?
However, if we do need a new code then let's use "b" by itself; we don't need
"bN" because N is a quick calculation based off of MdX ie N=ceil(M/2+0.5).
Open Qs:
As I said, the Grammar was to help me to the initial Parser/Lexer. I'm OK if we
don't update it, but I like we should (as it should form part of the final
doco). And I have no problem with it being a hybrid- or two-stage grammar (if
that's what's required).
On 02/09/2020 09:26, Ben Kolera wrote:
Heya,--
What's the authoritative source of what we want to do with the UDR? I
ask because the Grammar [1] and the Possible die codes [2] disagree.
Are we intending to keep the grammar up to date (the Grammar already
doesn't line up to develop) and correct as we go (like actually make
it proper ebnf, lol) or will the code and tests become the doco and
examples of the die codes that we support?
Possible_Die-Codes.md suggests this an example:
{4d8+3d12,5d20+3,5d10+1}>20
But if you look at the grammar the only things that can be part of
expressions are number literals, so the above case is not something
that is allowed by the grammar.
Taking a step back from all the documentation though, as users of our
two current games we want to be able to do:
3d6!+5d10!k (This lines up to a sabre damage roll with the strength
and weapon damage smooshed into one).
The current rewrite went down the route of treating DicePools as the
whole set of {NumDice,Sides,Exploding,Keep,Target,Raises} (it doesn't
do rerolls or crits yet) and it works out poorly when trying to add
these things together. I mean, what should the result of
5d12!kt7s5+2d4!kt3s5
be? Is it just adding the successes of both groups together? Is the
entire roll a success or a failure if one reaches its target and the
other fails? If you have a modifier in the modifier box in the UI,
does it apply to both groups or does it add extra successes to the
final result? It is really messy and suggests that this needs more
thought and precision.
I don't think that these have any clear answers in the context of our
game (and maybe not clear answers in general), so I'd prefer it if we
disallowed adding anything that has a target/raises from the grammar
but while still allowing the sabre roll that would be handy for
deadlands.
What I suggest is that the Target and Raises syntax can only apply at
the top level something like this (I've ignored functions and
Multiplication and Exponents here because I don't want to write out
the nested precedence, lol):
DieCode = DiceGroupExpr,[GlobalModifier],[Target],[Crit],[SortCode]
GlobalModifier=("+"|"-"), NumberLit
Target=("t"|"<"|">"),NumberExpr,[("s"|"r"),NumberExpr]
SortCode= "s", ("a" | "d")
DiceGroupExpr=DiceGroup,["+",DiceGroupExpr]
DiceGroup= DicePool | DicePools
DicePools = "{", { DicePool }, "}"
DicePool = [NumberExpr], "d", DieSides, [Exploding], [Keep], [Reroll]
<snip>
This seem to work in my head except for two issues:
1st Issue:
The global modifier is ambiguous! In spirit, it's supposed to handle
cases like these: "5d12!k+2t7s5" and "d100-60" but because we allow
arbitrary numeric expression in the diesides there's nothing in the
grammar that distinguishes "5d(5+5)" from "(5d5)+5". We need to
disambiguate this somehow. Some ideas:
- Always forcing dice pools into a grouping even if single pooled
(kinda ugly) "{5d5}+5"
- Putting some syntactic distinguisher before the global modifier
like "5d5|+5". Kinda looks weird with keep dice though "5d12!kt7s5|+2"
(is that clear that it'll add the +2 before doing the target number
calc? "5d12!k|+5t7s5" just looks weird so if we thought the ordering
is important we may need a better distinguisher than "|")
2nd Issue:
I want to add some syntax to the grammar that marks a pool with the
fact that it will bust if there are a majority of 1s in the pool.
However, this would have to go on the dicepools and with the proposed
grammar above that's still part of arithmetic so we need to figure out
what it means to do arithmetic on potentially busted pools is (5 +
bust = 5, or 5 + bust = 5?). I think that it's good to ground this in
deadlands. What happens if you bust a strength check on a weapon
damage roll? Do you still get the weapon damage or do you do a big fat
0 damage? Or do strength checks for hand to hand damage not bust? My
intuition is that a bust is an annihilator[3] (i.e X + bust = bust and
bust + X = bust, func(bust) = bust) that's akin to the expression
throwing an exception.
--- end issues ----
This is the problem with striving towards the kitchen sink! Trying to
figure out ways to make sure all of the features work precisely when
combined becomes harder. Being perfectionistic and wanting a kitchen
sink but being imprecise and doing funky things is a very sad state to
be in and I absolutely don't want the UDR ending up that way on my
watch. Precision is key with such a core piece of things, so we either
have something simple that covers our usecases in our games precisely
or we have to go through these thought exercises trying to hammer out
precisely what we mean and want in all these cases that we don't have
a concrete use case for.
---
Summarising, the proposed action points for this email are:
- Targets & Raises at top level only
- Need to distinguish the global modifier syntactically. Just going to
roll with a code terminating "|",("+","-"),NumberLit for now but we
can change that later if we want
- Crits go on the top level (they are basically a second target number)
- Busts go on the pool and (X <opr> bust = bust, bust <opr> X = bust
and func(bust) = bust).
Open Questions are:
- Are we planning to output a proper EBNF at the end of the UDR work
or is a test suite and the way that the parser is defined enough (the
nice thing about LPeg style parsers is that they read a lot like ebnf
anyway)? My vote would be that the parser & tests will be enough and
are better because they are machine checked. If we were generating a
parser from the ebnf this would be different, but we aren't so the
docs have the great risk of getting stale (the current ones are stale
and also contain a handful of errors).
I won't be doing any work on UDR today but when I get back to this
probably tomorrow or Friday I won't be blocked if folk haven't had the
time for a response yet so dw. We need to move in the direction of the
proposals anyway (unless we're cutting features, ofc!) so it feels
like the main things we'll need to discuss here are finer bikeshedding
type stuff anyway. I can just move as though those action points are
decided and I can adjust as we discuss the colour of the bikeshed. :)
Cheers,
Ben
[1]
https://github.com/Dulux-Oz/FGI/blob/master/Support_Files/Die-Code_EBNF_Grammar_Definition.md
[2]
https://github.com/Dulux-Oz/FGI/blob/master/Support_Files/Possible_Die-Codes.md
[3] https://en.wikipedia.org/wiki/Annihilator_(ring_theory)