Bubbling Beaker Awards (Award #24, May 03 2024)

That’s really very neat!

No, it’s a routine that prints text! It doesn’t return anything. (Okay, it returns true.)

But it is still a first-class text under I7’s rules.

Well OK, I know, I was leaning toward giving a simplified view of the world because in phrases such as

    let txt be "this is [some substituted text]".

despite what’s going on behind the scenes the text with substitution (by which I mean a double-quoted I7 construction like "this is [some substituted text]") doesn’t noticeably print anything, but it does syntactically look like a routine that returns a text. That’s how I find it conceptually easiest to understand how they behave in I7.

The associated ‘To say’ phrase producing the substitution itself (i.e the bit between square brackets)

To say some substituted text: say "semantically confusing".

has more the feel of a printing routine- which gives an oblique hint to some of the ‘under the hood mechanics’ of texts with substitutions.

At its lowest I6 level, (at least nowadays) a text with substitution(s) compiles variously depending on context to a sequence of one or more in-line printing statements or routines, or to a pointer to a word array whose second element is a routine that prints text, or to a function that returns either said pointer or a ‘standard’ text type (of which there are several flavours) expanded from the routine in the array it points to, or something like that, but I guess going too deeply into the weeds of these things is for most purposes making things more complicated than is helpful.

Much as classical mechanics isn’t really exactly right, but for most purposes it’s a more helpful way of thinking about the world than quantum mechanics.

1 Like

To I7, it’s just a mild-mannered unsubstituted text value…

xy is initially "[yourself]".

but beneath those glasses there lies… an I6 routine!

[ call_U2010;
    (say__p = 1);
    ParaContent();
    PrintShortName(selfobj);
    rtrue;
];

that runs whatever arbitrary code you might have included in a to say phrase you might have written, including printing text (optionally), and returns true.

But if you squint at let x be the substituted form of xy, which assigns a dynamically generated text value to x, and give your metaphors a healthy stir, that quack starts sounding at least a little duck-like to me.

2 Likes

heh, or

....
      let mylocaltextvariable be z;
....

after which, depending on the nature of z, mylocaltextvariable might end up as either a dynamically-created text or a pointer (indirectly) to the same routine as z (indirectly) points to…

1 Like

Regarding Bubbling Beaker Award® #2, although CrocMiam has not yet taken the floor, I will give a brief overview because this week’s award is coming up fast.

CrocMiam’s invention creates some variations on the I6 routines called LIST_OF_TY_Sort() and ListCompareEntries(), which are found in the Lists.i6t template file. The normal versions of these routines are designed to use a property as the basis of the sort, while his variations are designed to make use of a routine as the basis. The routine that will be used for sorting is generated from an author-created to decide which number... phrase, which must be given a parenthesized name, as in:

To decide which number is the name length of (O - thing) (this is name length):
	decide on the number of characters in the printed name of O.

The phrases for sorting found his original post are quite narrow in range, to match the specific problem that was posted. A slightly more generalized version would be:

To sort (L - a list of things) in/into (ph - phrase thing -> number) order:
	(- LIST_OF_TY_SortBy({-lvalue-by-reference:L}, 1, {ph}); -).

To sort (L - a list of things) in/into reverse (ph - phrase thing -> number) order:
	(- LIST_OF_TY_SortBy({-lvalue-by-reference:L}, -1, {ph}); -).

It is important that the kind matches up between the different places in the code specifying the “arguments” for phrases – in the preceding examples they are all the thing kind. (The phrases can be generalized further, if desired, but I’ll leave that aside.)

Of note is the fact that the declarations for the sorting phrases make use of a syntax which causes them to operate “by reference” instead of “by value.” This ensures that the sorting will be done on the list that is supplied as an argument, instead of a sorting a copy of the list that just gets thrown away after the sort has been completed.

EDIT: I would also add that Zed came up with something similar for sorting according to author-defined phrases at Sorting scenes - #6 by Zed.

2 Likes

Thank you, I couldn’t find the time to write.

Another thing of note is the technique for calling an I7 phrase from I6.

The I7 phrase is passed to I6 with the {ph} syntax but ph is not directly a reference to the function. It’s an array: [info about kinds; a reference to the actual function; text containing the name of the I7 phrase]. For instance, the phrase:

To decide which number is attack points of (m - monster) (this is attack points):
    […]

would give:

Array DK5_phrase_monster____number --> [ PHRASE_TY; 2; NUMBER_TY; ];
Array closure_data_U21 --> [ DK5_phrase_monster____number; call_U1966; "attack points"; ];
[ call_U1966 t_0;
    // …
];

ph is closure_data_U21 and ph-->1 is call_U1966, the function we’re interested in.

To call it: (ph-->1)(arg1, arg2, …)

4 Likes

This week’s prize, Bubbling Beaker Award® #3, is presented to @Draconis (Daniel Stelzer). As with last week’s award, the winner is not a mad scientist, though he contributes to mad science discussions with suspicious regularity. His award-winning post creates an alternate list writer routine designed to more flexible than the built-in one. His invention was inspired by a method used by zarf in Hadean Lands but adds innovations of its own.

Draconis, you gave a pretty good overview of your invention already on the original post, but is there anything that you would like to say by way of acceptance speech (or perhaps as opening arguments for the defense)?

5 Likes

Hi Otis, to assist the terminally indolent / cerebrally challenged please can you include a link to the winning post? EDIT: I’ve found it, I think

1 Like

Oops, sorry – I keep the top post updated with links to each winning post, but it makes sense to include them in the discussion starters down below, too. I’ll edit them in.

4 Likes

Sure thing! I am honored to receive this suspiciously bubbling beaker!

So, Inform has a very elaborate system for printing lists of objects. This is accessed through a phrase with a truly staggering number of options:

To list the contents of (something - an object), with newlines, indented, as a sentence, including contents, including all contents, giving inventory information, giving brief inventory information, using the definite article, listing marked items only, prefacing with is/are, not listing concealed items, suppressing all articles and/or with extra indentation:

Why are all these options necessary? Well, in Inform, descriptions like “angry male people in the Gymnasium” are values in their own right, which we can pass around to phrases as much as we like! So it’s very easy for an author to specify what things should be in their list.

The hard part is specifying what should be printed for each item in the list. That’s why we need options like “suppressing all articles” and “using the definite article”. This is also the difficult part for printing lists of anything that’s not an object.

The solution to this problem came from the Hadean Lands source, where zarf used a text for this! His list-writer sticks the current item into a global variable called “substitution-variable”, and the text you pass into the list-writer can thus reference “[the color of the substitution-variable]” or whatever you like.

Previously, I’d been writing my own little mini-list-writer code every time I needed a customized list. For example, I have a “to (direction)” phrase to handle the difference between “to the north” and “upward” (or, in this particular case, “to starboard” and “forward”!). If I want to say “You can go…” followed by a list of viable directions, using this phrase, I need to write my own loop that prints all the commas in the right places and everything. Or, I have a kind of value called “position”, which has a property called “name” (to handle the fact that “above” already has a meaning to I7). If I want to print a list of positions using their names, again, I need to handle all the commas and “ands” myself.

But with this text trick, suddenly that’s no longer needed!

First, a hack that I’ve used before to access activity parameters. In I6, variables don’t have types. In I7, they do. But in I7, you can pass kind names to phrases! So:

To decide which K is the (name of kind of value K) being listed: (- listing_parameter -).
To set the (name of kind of value K) being listed to (V - K): (- listing_parameter = {V}; -).

So now we have a variable, the “thing being listed” (or “direction being listed” or “position being listed” or “number being listed” or…), which can take on any type we want it to. Sorry, type-checker.

Then, we take in a description and a text:

To print a list of (T - text) for (D - description of values of kind K), prefacing with is/are and/or disjunctive:

Note that “description of values of kind K”. Inform’s type-checker knows that “viable directions” is a description of directions, and “positions accepted by the noun” is a description of positions. So there’s no need for the author to specify that explicitly: Inform tells our phrase what its type-checker knows already!

There are two main things we can do with descriptions, and we’re going to do both:

let N be the number of D;

Find out how many there are, and…

repeat with V running through D:
	set the K being listed to V;
	say T;

…repeat through them!

The rest is just a bunch of details to get commas in the right places and handle nested lists (instead of clobbering the listing-parameter variable, we push it onto the stack, and pull it back when we’re done). But we can now say:

print a list of “[to the direction being listed]” for viable directions
print a list of “[name of the position being listed]” for positions accepted by the noun

Or anything else, for that matter! Using texts referencing a global variable like this really is a game-changer!

6 Likes

Oh yeah, and an extension version is coming as soon as I’ve stress-tested it a bit more!

1 Like

This week’s prize, Bubbling Beaker Award® #4, is presented to @evc003 (Eric Conrad), who hasn’t visited the forum in some time. His award-winning post has a practical bent: It demonstrates a method for setting up asymmetrical map connections at compile-time using the relatively-undocumented mapping <direction> relations. It may not sound like much, but it drew a comment of “Ooh, nice.” from none other than zarf. (Note that there may be tweaks needed in 10.1.2 or future releases. See discussion at https://intfiction.org/t/mapped-above-mapped-below)

7 Likes

It occurs to me that, although the compiler source code was a black box at the time this week’s award-winner was posted, now the source code is open for inspection.

I still don’t know my way around it very well, but I know that @Zed and @Draconis have spent some time reviewing it. Can either of you two shed some light on the dividing line between “simple” and “complex” declarations on which evc003’s technique depends? That would be a good supplement to the discussion on the original post itself.

4 Likes

Some time ago I did some experimenting and observed the following:

Making one-way connections

As noted above, phrases including ‘nowhere’ can be used to override the compiler’s innate tendency to assume two-way connections.

Also, an explicitly stated alternate destination for an assumed reverse mapping direction will take precedence over the assumption:
For example after: The Lawn is east of the Potting shed and west of the Herbaceous Border. East is the Lake. the Lawn remains west of the Herbaceous Border, but there is no corresponding eastward connection- east of the Lawn is the Lake.

Furthermore, the compiler only creates two-way connections for what the documentation calls ‘simple sentences’ Unfortunately, this cryptic comment leaves it a little vague where the boundary between ‘complicated’ and ‘simple’ lies. The example given in the documentation is:
The Attic is a dark room above the Parlour. rather than the simple The Attic is above the Parlour, but actually even The Attic is a room above the Parlour appears ‘complicated’ enough to create a one-way connection. A dark room above the Parlour called the Attic contains a brass lamp. also creates a one-way connection.

(Note that the Parlour must have been already declared for the compiler to accept this- otherwise the following complaint is made:

The sentence ‘The Attic is a room above the Parlour’ appears to say two things are the same - I am reading ‘Attic’ and ‘room above the Parlour’ as two different things

Also, The Attic is a room above or The Attic is a room above it both provoke a similar complaint even with prior declaration of the Parlour)

Conversely, the apparently equally complicated The Parlour is a room. Above is a room called the Attic or Above the Parlour is a room called the Attic or A dark room called the Attic is above the Parlour or even Above is a dark room called the Attic all lead to a two-way connection.

The simplest approach to creating explicit one way connections is therefore probably to use the exact forms:

The <name-of-a-new room> is a <optional-list-of-adjectives> room <direction> of/from/-- <name-of-a-previously-declared-room> OR

A <optional-list-of-adjectives> room <direction> of/from/-- <name-of-a-previously-declared-room> called <name-of-a-new-room> contains <list-of-objects>

remembered through the archetypes:

  'The Attic is a dark room above the Parlour.' OR
  'A dark room above the Parlour called the Attic contains a brass lamp.'
4 Likes

This week’s prize, Bubbling Beaker Award® #5 is presented to @Zed, the mad scientist par excellence. His award-winning post demonstrates use of an anonymous relation set up as a property of an enumerated value as a method of handling color mixing rules. (NOTE: Due to a bug in Inform 6M62, his code causes an interpreter crash on startup if compiled for Glulx using 6M62. It will work if compiled to Z-Machine using 6M62, and works for either VM using 10.1 because the bug has been fixed.)

What makes this invention special is that it is a working implementation that approximates some of the functionality of ternary relations, a feature that many Inform users have wished for in the past. For this reason, by vote of his fellow mad scientists, this is the first award to be granted the coveted distinction of being Peer Revued™.

Congratulations, Zed! You are formally invited for show-and-tell.

12 Likes

Thank you. I’m tickled pink to have been Peer Revued™. But I must confess that I have misgivings that this one was mad enough! Like I said there, something like this technique may be what’s “meant to” be idiomatic Inform!

WI 4.16:

Relations are really the central organising idea of Inform [emphasis added]

WI 13.14-13.15 and WI 22.1 make clear that the relation of K to L syntax is a kind-of-value constructor, and one can have values of that kind, and variables that hold values of that kind. And, so, why not properties?

Only problem is: it didn’t actually work. Or so I thought. I only compile to Z-code on rare occasion to test something in particular. Until you told me it worked on the Z-machine with 9.3/6M62, Otis, I had no idea.

It’s easy to point to when I found out that relations as properties worked in 10.1 (on glulx) 'cause I posted about it (in one of the several threads over the years in which someone was yearning for a ternary relation).

(A different example of using a constructed KoV as a property can be seen in an answer to Dynamic relations: what’s the idom? where I made an enumerated kind of value with a thing-based rulebook as a property.)

6 Likes

I guess that link answers the question I posed in the original award-winning thread ‘Can forms of relation other than various to various be usefully used as properties?’ :wink:

1 Like

Well, at least partially. I can’t (so far) find a working syntax that explicitly creates for example a various-to-one color to color relation as a property.

Two things:

  1. The fact that it works on Z-Machine for 6M62 is pure luck – an oddity of some low-level logic being right enough for the wrong reasons due to an integer overflow that results in a fortuitous value. (Details available by PM, if you care, but the root cause is already fixed in 10.1.)

  2. As far as whether it was “mad enough,” I can reveal only that a comment by one of the revue-ing peers deemed it “insane genius,” so I think you’re on firm ground.

I had missed that you did basically the same thing 16 months ago. Better late than never!

3 Likes