Some questions about dice

I’m playing around with 6L38 trying to create a generic die kind:


Chapter - Defining Dice

Color is a kind of value. The colors are red, orange, yellow, green, blue, purple, white, gray, brown, and black.

Sidedness is a kind of value. 1-sided specifies a sidedness.

A die is a kind of thing. The plural of die is dice. A die has a color. The color of a die is usually white. A die has a sidedness. The sidedness of a die is usually 6-sided. A die has a number called current face. Understand the sidedness property as describing a die. Understand the color property as describing a die.

To decide which number is the face count of (X - a die):
decide on the sidedness of X divided by 1-sided.

The description of a die is usually “An ordinary die with [face count of the item described] sides[if the item described is not enclosed by the player], currently showing [current face][end if].”

Chapter - Rules for Dice

Before printing the name of a die (this is the prefix die with side count in name rule):
say " [sidedness] ".

To randomly set the current face of (X - a die):
now the current face of X is a random number between 1 and the face count of X.

When play begins (this is the initialize all dice at startup rule):
repeat with subject running through dice:
randomly set the current face of subject.

Carry out dropping a die (called X) (this is the throwing a die randomizes its face rule):
randomly set the current face of X.

After dropping a die (this is the report throwing a die rule):
say “It lands with the [current face of the noun] side on top.”

Chapter - The Basics

Place is a room.

The player carries two dice.

The player carries a red die.

test me with “throw dice / showme red / x 6-sided”[/code]

So far, so good, but I’m having trouble with the following ideas:

  1. How can I declare a die with a non-default number of sides? “The player carries a yellow 8-sided die.” results in a generic thing, not a die. “The player carries a die with sidedness 8-sided.” produces a white 6-sided die. I’ve found it’s possible to create named dice with non-default sidedness (“The player carries a die called an X. The sidedness of X is 8-sided.”), but this isn’t really the desired functionality.

  2. I would like the player to be able to differentiate identical dice via the current face, e.g. “>GET DIE SHOWING 4”. A rule like ‘Understand “showing [number]” as a die when the number understood is the current face of the item described.’ compiles but doesn’t seem to function – the parser goes into disambiguation for all dice regardless of the value of current face.

  3. Assuming it’s possible to get the above working, I would also like to be able to have the parser recognize phrases like “6-sided” or “6 sided” or “six-sided” or “six sided” or maybe even “with 6 sides” to disambiguate dice, so the player could type “>GET SIX-SIDED DICE SHOWING 3” to pick up multiple dice with those features from a set.

Anyone have any tips?

For the first part, you need a sentence verb:

The verb to conform to means the sidedness property.

The player carries a yellow die which conforms to 8-sided.

Thank you, zarf. That clears it right up. I’ve been rereading WWI for 6L38 but didn’t think to look in chapter 15.

Is there anything equally obvious I’ve missed that would be relevant to questions #2 or #3?

Look at the source for Reliques of Tolti Aph (inform full example) for a Graham Nelson example, although I don’t think the actual dice are physical.

Thank you, HanonO - Professor Nelson’s example is wonderfully compact and useful, and I’m glad to have read it. However, as you note, it does not involve “physical” instantiation of the dice within the world model, so it doesn’t serve the same purpose as I need here.

So I think I got everything I wanted working by digging into the DM4:

[code]Include (-
[ ParseDieByFace j;
j = NextWord();
if (j ~= ‘die’ or ‘dice’)
return GPR_FAIL;
if (j == ‘dice’)
parser_action = ##PluralFound;
if (NextWord() ~= ’showing’)
return GPR_FAIL;
return GPR_FAIL;
if (~~(self ofclass (+ die +) && self.(+ current face +) == parsed_number))
return GPR_FAIL;
return 3;

The Understand token dice by face translates into I6 as “ParseDieByFace”.

Understand “[dice by face]” as a die.[/code]

which seems to handle very nicely for both singular and plural cases, with or without additional property-based adjectives:

Now my question is: Is there a way to accomplish the same thing in pure I7?

It really seemed to me that something along the lines of:

Understand "showing [number]" as a die when the current face of the item described is the number understood.

but, although this compiles, it doesn’t work. Looking at the generated code, I see a corresponding I6 function:

[ Cond_Token_161 ; if ((((GProperty(OBJECT_TY, self,p15_current_face) == parsed_number)))) return GPR_PREPOSITION; return GPR_FAIL; ];

and I see that it attempts to use this function in a routine used for the parse_name property of the die kind:

[ Parse_Name_GV93 original_wn ! first word of text parsed group_wn ! first word matched against A/B/C/... disjunction try_from_wn ! position to try matching from n ! number of words matched f ! flag: sufficiently good match found to justify success w ! for use by individual grammar lines rv ! for use by individual grammar lines g ! temporary: success flag for parsing visibles ss ! temporary: saves 'self' in distinguishing visibles spn ! temporary: saves 'parsed_number' in parsing visibles pass ! pass counter (1 to 3) pass1_n ! value of n recorded during pass 1 pass2_n ! value of n recorded during pass 2 ; #ifdef DEBUG; if (parser_trace >= 3) print "Parse_name called^"; #endif; original_wn = wn; for (pass = 1: pass <= 3: pass++) { wn = original_wn; try_from_wn = wn; f = false; n = 0; while (true) { ! On pass 1 only, advance wn past name property words ! (but do not do this for ##TheSame, when wn is undefined) if ((parser_action ~= ##TheSame) && (pass == 1)) { while (WordInProperty(NextWordStopped(), self, name)) f = true; wn--; try_from_wn = wn; } if (pass == 1 or 2) { if (parser_action==##TheSame) { #ifdef DEBUG; if (parser_trace >= 4) print "p1, p2 = ", parser_one, ", ", parser_two, "^"; #endif; ss = self; ! Distinguishing property p60_sidedness if (parser_one.p60_sidedness ~= parser_two.p60_sidedness) return -2; ! Distinguishing property p61_color if (parser_one.p61_color ~= parser_two.p61_color) return -2; self = ss; return 0; } ! Match any number of visible property values try_from_wn = wn; g = true; while (g) { g = false; ! Parsing property p60_sidedness wn = try_from_wn; spn = parsed_number; ss = etype; if ((Kind_GPR_53() == GPR_NUMBER) && (self.p60_sidedness == parsed_number)) { try_from_wn = wn; g = true; f = true; } parsed_number = spn; etype = ss; ! Parsing property p61_color wn = try_from_wn; spn = parsed_number; ss = etype; if ((Instance_GPR_52(self.p61_color) == GPR_NUMBER)) { try_from_wn = wn; g = true; f = true; } parsed_number = spn; etype = ss; } ! try_from_wn is now advanced past any visible property values wn = try_from_wn; } if ((parser_action ~= ##TheSame) && (pass == 1)) { while (WordInProperty(NextWordStopped(), self, name)) f = true; wn--; try_from_wn = wn; } if (Cond_Token_161() == GPR_FAIL) jump Fail_1; if (NextWordStopped() ~= 'showing') jump Fail_1; w = ParseTokenStopped(GPR_TT, DECIMAL_TOKEN); if (w ~= GPR_NUMBER) jump Fail_1; rv = GPR_NUMBER; try_from_wn = wn; f = true; continue; .Fail_1; wn = try_from_wn; break; } ! End of endless loop while (WordInProperty(NextWordStopped(), self, name)) n++; if ((f) || (n>0)) n = n + try_from_wn - original_wn; if (pass == 1) pass1_n = n; if (pass == 2) pass2_n = n; } ! End of pass loop #ifdef DEBUG; if (parser_trace >= 3) print "Pass 1: ", pass1_n, " Pass 2: ", pass2_n, " Pass 3: ", n, "^"; #endif; if (pass1_n > n) n = pass1_n; if (pass2_n > n) n = pass2_n; wn = original_wn + n; if (n == 0) return -1; DetectPluralWord(original_wn, n); return n; ];

but it just doesn’t work, and I’m not sure why. It almost looks like the key tests in the parse_name routine are out of order, i.e. looking at the section:

if (Cond_Token_161() == GPR_FAIL) jump Fail_1; if (NextWordStopped() ~= 'showing') jump Fail_1; w = ParseTokenStopped(GPR_TT, DECIMAL_TOKEN); if (w ~= GPR_NUMBER) jump Fail_1; rv = GPR_NUMBER;

Why is Cond_Token_161 called before checking that NextWord() returns ‘showing’?

I note that the section on “Understand … when …” does point out that things like “the number understood” are not yet defined, so it makes sense that this wouldn’t necessarily work. And the ordering of Cond_Token_* test in the generated code makes sense if the idea is to first attempt to disqualify the “when …” condition before trying to match the associated grammar.

I’d still like to figure out an I7-friendly way to do something like this but I’m running out of ideas for creative abuse.

I have an as yet unreleased I7 dice extension that might help here. Let me know if it might be useful.