Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Rule ordering by grouping

127 views
Skip to first unread message

Andrew Plotkin

unread,
Oct 6, 2006, 1:04:53 AM10/6/06
to
Ok, here's my new thought: when I write a bunch of rules for action --
write them all at once, I mean -- they're probably related. So I can
put a precedence ordering on them. (Assume this for the moment.)

Or maybe the library has a bunch of rules for an action -- that's
likely -- and the precedence is all set up for those.

Now I want to add a rule. Most likely, I want to treat the whole group
of already-written actions as that -- a group. I'm probably adding a
rule before, after, or instead of that entire action (group of rules).
I should be *able* to insert my new rule in the middle of the group,
but that's the unusual case.

This is the general pattern of programming, after all: you have
related chunks of code, that have to know about each other's guts, and
then you have unrelated (or more distantly related) code, which wants
to handle that chunk "from the outside" -- as an opaque chunk. That's
the whole data-encapsulation programming movement (and the teeny wee
offshoot that we call object orientation).

But, of course, what's a tidy encapsulation model in most programming
work gets a bit blurry in IF programming. There can always be an
exception.

So we need a notion of "a group of rules". Great -- I7 already has
this, although it doesn't apply any significance to it: a group of
rules is called a chapter. Or a section, volume, book, whatever: we
have the notion of (hierarchical) groups of rule declarations, divided
by the way the author organizes his code. And that's natural. We
organize related code together. At least *I* do.

And then we simply make declarations like

Chapter 3 takes precedence over Volume 1.
The Darkness Extension by J. Blindbat Chroma takes precedence over
my game rules.
Chapter 3 Section 4 takes precedence over the Darkness Extension.

Is strict hierarchy good enough? It's not good enough for IF classes/
kinds (according to me, yeah, I know) so it's probably not good enough
for rules. The library might have "touching rules" as a group, but
you'd want to be able to add a new touching rule. Shoving my rule into
the library source code is not sexy.

But we can take the source-code hierarchy (book, chapter, section --
library, extensions, etc) as a *starting point*. Say there are "kinds
of rules", just as there kinds of objects back in my properties post.
Sets of rules. The default definition of a set is "whatever's in this
chapter of my source", or "whatever's in the Standard Library", or
"whatever's in the Darkness Extension" -- but we can customize
particular rules (or particular sets of rules!) into and out of
particular sets. And the syntax for this is going to look exactly like
the syntax for objects:

The Gondwanaland Rule is a Chapter 3 rule.
(implicitly: rule for deciding whether the Gondwanaland Rule is a
member of Chapter 3: decide yes.)

These sets overlap -- Chapter 3 contains six sections, and we have the
natural implicit rules

Rule for deciding whether Chapter-3-Section-1 rule is in Chapter 3:
decide yes.

And so on. And just like with objects, we can *override* these
assumptions where necessary. The touching rules start out as a section
in the standard library, but we can throw new rules (or whole new
sections) into that group, by making implicit (or, indeed, explicit)
metarules about that set-property.

Now, we're making rules about rules; we have to put some clamps on, or
we'll just shove the problem up a level. Obviously, rules about rule
membership have to be decidable at compile-time. They have to be
decidable before the rules about *objects*, because they will be
*controlling* the rules about objects. Probably they have to be
unconditional. (Saying that rule X is in chapter Y *sometimes* is
asking for headaches. Or maybe that makes sense for simple,
compile-time conditionals? That would cover what us old-school C
programmers think of as compile-time switches, you know, #define
NO_SCORE to rearrange the library in this particular way...)

But I think this gives us the right tool. All along I've been groping
for a way to not just divide actions into phases, but *talk about*
dividing actions into phases. Okay:

The deciding group takes precedence over the reaching group.
The reaching group takes precedence over the touching group.

The compiler is trying to put all these conflicting rules in a strict
ordered list, but now its job is simplified: it only needs to sort
within these three bins (deciding, reaching, touching). Which is what
we've been trying to express all along. Plus, adding a new phase is as
simple as adding a new precedence declaration of this sort -- or
perhaps two, if you want to go between two existing phases. Go crazy,
define as many as you want.

(Conflicts between metarules still need to be resolved, yes. What if
I, the game author, decide that the touching rules should take
precedence over the reaching rules? Well, hell, let's set up a
meta-meta-rule: "The game metarules take precedence over the standard
library metarules." Georg Cantor would tear his hair out, but I bet
that in practice, each layer of meta-logic will be much simpler than
the one below, and you will never need any meta-meta-meta-rules. The
compiler can just treat the whole mess as a dependency tree -- we
already know that it has to be able to figure out dependencies like
this.)

Possible down-sides: there is no way to say "run the reaching rules
for this action". But then, is that something you want to do? We've
neatly sidestepped the necessity of having any code say "run the
deciding rules; run the reaching rules; run the touching rules". It
all simply appears as an outcome of the compiler's rule-ordering
process.

(Of course you *can* model your code that way: you can define new
properties P1, P2, P3, and then have your action code say "P1; P2;
P3". Those are your phases, and instead of defining action rules, you
define P1 rules, P2 rules, and P3 rules. But I don't think the action
model in standard library should be built that way.)

(In case you're wondering about the actual ordering algorithm, I
imagine it as some kind of ranked-pairs system. I half-wrote a working
model of this a few years ago, although I was still thinking in simple
hierarchies at the time.)

--Z

--
"And Aholibamah bare Jeush, and Jaalam, and Korah: these were the borogoves..."
*
If the Bush administration hasn't subjected you to searches without a warrant,
it's for one reason: they don't feel like it. Not because you're an American.

vaporware

unread,
Oct 6, 2006, 1:43:39 AM10/6/06
to
Andrew Plotkin wrote:
> So we need a notion of "a group of rules". Great -- I7 already has
> this, although it doesn't apply any significance to it: a group of
> rules is called a chapter. Or a section, volume, book, whatever: we
> have the notion of (hierarchical) groups of rule declarations, divided
> by the way the author organizes his code. And that's natural. We
> organize related code together. At least *I* do.

I7 does have a significant notion for groups of rules: the rulebook.
Much of what you've proposed here can be done today with rulebooks, and
for any features that aren't currently possible, it seems that it'd be
sensible to base them on rulebooks instead of branching off in a new
direction.

vw

Andrew Plotkin

unread,
Oct 6, 2006, 1:44:51 PM10/6/06
to

I7's rulebooks (along with activities and phrases) are what I'm
calling "properties" -- something which you can invoke, which can be
implemented by any number of (possibly overlapping) rules. My post was
addressing the question of how to order the rules *within* a rulebook.
Obviously I am not satisfied with the answer of putting in
sub-rulebooks. :)

--Z

--
"And Aholibamah bare Jeush, and Jaalam, and Korah: these were the borogoves..."
*

It used to be that "conservatives" were in favor of smaller government,
fiscal responsibility, and tighter constraints on the Man's ability to
monitor you, arrest you, and control your life.

Kevin Forchione

unread,
Oct 6, 2006, 4:49:48 PM10/6/06
to
"vaporware" <jmc...@gmail.com> wrote in message
news:1160113419.5...@e3g2000cwe.googlegroups.com...

Surely Andrew is fully aware of the I7 rulebook. So I wonder what he finds
unpaletable about the rulebook concept.

--Kevin


Andrew Plotkin

unread,
Oct 6, 2006, 7:26:34 PM10/6/06
to
Here, Kevin Forchione <ke...@lysseus.com> wrote:
>
> Surely Andrew is fully aware of the I7 rulebook. So I wonder what he finds
> unpaletable about the rulebook concept.

(Not the rulebook concept, but the idea of using rulebooks as the
fundamental mechanism for ordering rules *within* a rulebook.)

It's heavyweight and it's... definite. You can't look at a bunch of
rules in a rulebook and say, well, how about I divide these up into
two groups and then add a third in the middle. Or if you do, it's by
inventing two new subrulebooks and then moving *every* existing rule
into one of them. Similarly, to rearrange "phases" which are set up
this way, you aren't just making statements about order; you have to
define a rule out of one rulebook and into another. And there isn't
such a thing as two *overlapping* rulebooks -- whereas it makes sense
to have two groups of rules whose order winds up (for whatever reason)
interspersed.

The nice thing about source-organization groups is that you're already
using them. If you have a lot of rules, they're probably divided into
groups already -- and the related rules are probably grouped together.
My point is that related rules are probably going to be *ordered*
together as well, because an unrelated rule will want to handle them
as an opaque mass.

--Z

--
"And Aholibamah bare Jeush, and Jaalam, and Korah: these were the borogoves..."
*

Andrew Plotkin

unread,
Oct 10, 2006, 11:30:13 AM10/10/06
to
I am starting to chase down the final details of how I want my rule
system to behave, but this isn't explaining that. This post was
inspired by a problem which started to show up in I7 once people
started using extensions: everything you define is in one global
namespace. This has led to a couple of rounds of (e.g.) Emily names a
global variable "height" in an extension, someone writes a game with
"height" as a property, he wants to use that extension, conflict, the
extension is updated to use "confugliated-private-height" instead.

This model is workable as long as extension writers are very careful.
But that's not ideal. Also note that there could be a conflict with an
extension's *public* names -- the ones which ought to be short and
readable because the game is expected to use them. That would require
the game to be rewritten to accomodate the extension.

I'd like to apply source organization groups (sections, chapters,
volumes, books -- in a normal programming language I'd say "lexical
scope") to solve this problem.

(As usual, I will use I7 syntax and propose I7-like extensions to it.
But the principle is applicable to any language that has a lexical
hierarchy.)

Say you can declare a section (or chapter, etc) to be "private":

Section 3 - Oddities - private

Height is a number that varies.

This means that anything you declare in this section -- in this
example, "height" -- is not visible in the global namespace. That
applies to objects, properties, kinds, rules, variables, and so on.
(This would not affect objects' visibility in the *game*; it's purely
a way to keep source code tidy.)

It is my guiding principle of IF programming that any restriction will
someday need to be overridden. So we need a way to refer to these
private declarations. I propose two. First, for a single ad-hoc
reference:

if X is less than height (see Oddities), ...

Section names themselves can collide, so you might need to specify the
chapter title as well as the section title:

if X is less than height (see Outdoors, Oddities), ...

I'm not using "Chapter 1, section 4" because those tend to be
renumbered a lot during a game's development. Although I guess it
should be legal.

Second, you'd want to be able to suck in the entire private namespace
of a section, if you wanted to do wholesale mucking around with its
guts:

See also Oddities.

Or

See also Outdoors, Oddities.

This would import all the declarations into whichever section or
chapter the "see also" declaration occurs in. You might also want to
say

See also Outdoors, Oddities, height.

This lets us organize an extension this way: (indenting added for clarity)

--------------
Frogs by Zarf

Chapter - Public Stuff

See also Frog Privates.

A frog is a kind of animal.
Instead of touching a frog:
say "Frog got [count] warts."

Section - Frog Privates - private.

Count is a number which varies.
--------------

The extension can use "count" freely, but a game which includes it
will only see the "frog" declaration. Unless it explicitly asks for
"count (see Frog Privates)". The game could then use "count" to refer
to something completely different.

I can also imagine a game saying

Section - Extension Sandbox - private
Include Frogs by Zarf.

This would seclude the entire extension in a namespace, so that the
rest of the game could use "frog" for some other purpose. To refer to
the extension's "frog" kind, the game would say

Kermit is a frog (see Extension Sandbox)

Or even

Kermit is a frog (see Frogs)

since an extension is itself a group.

It need hardly be said (he said ironically) that if you never declare
anything "private", you get the current I7 model. So this mechanism
has the "ignore it if you don't need it" property.

--Z

--
"And Aholibamah bare Jeush, and Jaalam, and Korah: these were the borogoves..."
*

Andrew Plotkin

unread,
Oct 10, 2006, 2:29:33 PM10/10/06
to
Here, Andrew Plotkin <erky...@eblong.com> wrote:
>
> It need hardly be said (he said ironically) that if you never declare
> anything "private", you get the current I7 model. So this mechanism
> has the "ignore it if you don't need it" property.

And while I'm in that area, I forgot to mention the existing scoping
mechanism -- I7 already prefers declarations from the same section
when you use a fuzzy match. My idea extends that: private
declarations are entirely excluded (not just dispreferred). I think
that's a useful idea.

Note that I7's fuzzy matching only applies to objects, not variables
or anything else. You can't say

The frog wart count is a number which varies.
The count is five.

Maybe that should be legal, or maybe it would cause mass confusion --
hard to say without trying it. (My worry about confusion is that
almost any common word would wind up fuzzily matching *some*
declaration in the game or library.)

steve....@gmail.com

unread,
Oct 10, 2006, 4:11:33 PM10/10/06
to
Sounds like the same old problem: rule precedence. (The word
"precedence" is perfect, because "precedence" means both the things at
issue: "relative order" and "relative importance.")

The problem with rule-based systems is that there's never a good
structure for rule precedence. The execution, by definition, is decided
by a dumb core resolution algorithm, which the programmer barely gets
to fiddle with in the best of scenarios.

The going solution? Let's invent a more sophisticated grouping
mechanism which, by coincidence, the more we work on, the more sounds
like OO class/inheritance hierarchy, a structure which was already very
good at organizing the execution in the first place. -- But at a huge
hit to performance and expressiveness. At its best, RO is OO, but OO
out-of-control, with cement boots and/or its tongue ripped out.

This roundabout might have been worthwhile, if it eventually opens your
eyes to the strength of true OO (quite opposed to the bullshit OO
familiar to users of I6, which I believe instilled the very frustration
which drives this fascination with rule-based systems).

Neil Cerutti

unread,
Oct 10, 2006, 4:40:27 PM10/10/06
to
On 2006-10-10, steve....@gmail.com <steve....@gmail.com> wrote:
> Sounds like the same old problem: rule precedence. (The word
> "precedence" is perfect, because "precedence" means both the
> things at issue: "relative order" and "relative importance.")

You should try reading more of the message than just the
"Subject:" Usenet is full of message bodies. They are neat!

> The problem with rule-based systems is that there's never a good
> structure for rule precedence. The execution, by definition, is decided
> by a dumb core resolution algorithm, which the programmer barely gets
> to fiddle with in the best of scenarios.
>
> The going solution? Let's invent a more sophisticated grouping
> mechanism which, by coincidence, the more we work on, the more sounds
> like OO class/inheritance hierarchy, a structure which was already very
> good at organizing the execution in the first place. -- But at a huge
> hit to performance and expressiveness. At its best, RO is OO, but OO
> out-of-control, with cement boots and/or its tongue ripped out.
>
> This roundabout might have been worthwhile, if it eventually opens your
> eyes to the strength of true OO (quite opposed to the bullshit OO
> familiar to users of I6, which I believe instilled the very frustration
> which drives this fascination with rule-based systems).

I take it back. Sometimes it'a good to ignore the body of the
message.

Inform 7's lack of namespaces is orthogonal to its rule
precedence system.

--
Neil Cerutti

steve....@gmail.com

unread,
Oct 10, 2006, 5:30:48 PM10/10/06
to
Neil Cerutti wrote:
> Inform 7's lack of namespaces is orthogonal to its rule
> precedence system.

That's a consequence of bad design; that's the problem, which you would
know if you were actually paying attention to the discussion. Razatazz
me later, or start a new thread; this is actually relevant.

It's not only about namespaces, and it *is* only about rule precedence,
which is to say, it's about a good model for rule precedence. Namespace
might have a minor role, but what is that concept in abstract?
Namespace, lexical range, is another way of characterizing a hierarchy.
Which is why it's best to return to the OO model, which characterizes
hierarchy very well (on multiple axes), including namespace.

Neil Cerutti

unread,
Oct 10, 2006, 10:50:54 PM10/10/06
to

A class or object makes a for a too-restrictive namespace. Many
OO languages allow you to use a class as a namespace if you want
to, but when that isn't sufficient, the literal concept of
"namespaces" (C++) or modules (most other OO systems) is added.

I agree with Andrew that name conflicts are a nuisance in Inform
7. But that problem can be solved without making Inform 7 objects
into namespaces.

--
Neil Cerutti

steve....@gmail.com

unread,
Oct 11, 2006, 4:38:26 AM10/11/06
to
Neil Cerutti wrote:

> A class or object makes a for a too-restrictive namespace.

Maybe so, but it's a lot better than no namespace at all. (And careful
not to get too hung up on the "object" metaphor: it just means a
conceptual range of code. And especially careful not to fuzz "class or
object," as the distinction is relevant to the point: objects make a
more restrictive namespace than classes.)

> I agree with Andrew that name conflicts are a nuisance in Inform
> 7. But that problem can be solved without making Inform 7 objects
> into namespaces.

This isn't really about I7, whose main problem in this regard is its
lack of a central library. I'm not suggesting that you make I7 objects
into namespaces. (I don't know what that means.) I7 lacks any decent
hierarchical organization -- it lacks a multi-axis hierarchial
structure which would determine, among other things, lexical range.

This is about the ideal RO system, which would provide such
organization, which involves (as Andrew seems to have argued) modeling
rules the way OO programming sets up its hierarchy: e.g., mixable
degrees of specificity, if you like.

All I'm saying is that it becomes a question, at what point in apeing
OO should RO actually become OO. Or, if you can figure out what's left
in RO that's worth saving, you've answered the question.

Neil Cerutti

unread,
Oct 12, 2006, 7:30:41 AM10/12/06
to
On 2006-10-11, steve....@gmail.com <steve....@gmail.com> wrote:
> Neil Cerutti wrote:
>> A class or object makes a for a too-restrictive namespace.
>
> Maybe so, but it's a lot better than no namespace at all. (And
> careful not to get too hung up on the "object" metaphor: it
> just means a conceptual range of code. And especially careful
> not to fuzz "class or object," as the distinction is relevant
> to the point: objects make a more restrictive namespace than
> classes.)
>
>> I agree with Andrew that name conflicts are a nuisance in Inform
>> 7. But that problem can be solved without making Inform 7 objects
>> into namespaces.
>
> This isn't really about I7, whose main problem in this regard is its
> lack of a central library. I'm not suggesting that you make I7 objects
> into namespaces. (I don't know what that means.)

My CS jargon is probably more like pidjin-speak. I meant the
property that most OO languages have that a class scope functions
as a namespace, and names from within it must be qualified from
without.

> I7 lacks any decent hierarchical organization -- it lacks a
> multi-axis hierarchial structure which would determine, among
> other things, lexical range.

Andrew proposes taking advantage of the organization it does
have: Chapters, sections, et al.

> This is about the ideal RO system, which would provide such
> organization, which involves (as Andrew seems to have argued)
> modeling rules the way OO programming sets up its hierarchy:
> e.g., mixable degrees of specificity, if you like.
>
> All I'm saying is that it becomes a question, at what point in
> apeing OO should RO actually become OO. Or, if you can figure
> out what's left in RO that's worth saving, you've answered the
> question.

You still haven't specified in what way OO is related to lexical
scoping. An OO system without lexical scoping is possible: see
I7. I'm no sure if any other system has tried such a thing.

--
Neil Cerutti

Michael Martin

unread,
Oct 12, 2006, 6:53:17 PM10/12/06
to
I would generally consider this feeding a troll, but as there's some
relevant thoughts relating to Proper Full-Scale Programming Langauges
For I7 that I haven't seen come up yet...

steve....@gmail.com wrote:
> > A class or object makes a for a too-restrictive namespace.
>
> Maybe so, but it's a lot better than no namespace at all.

As pointed out in the first post, sections *are* namespaces. I more
than twelve objects in my current WIP in I7 with character-exact names,
and both the Index and the testing ensure that these are, in fact,
different things.

They are, however, too restrictive, because it means that you *must*
group code in certain ways in order for it to resolve properly. The
lack isn't lack of namespaces. The lack is a lack of *qualified
names*.

> (And careful
> not to get too hung up on the "object" metaphor: it just means a
> conceptual range of code. And especially careful not to fuzz "class or
> object," as the distinction is relevant to the point: objects make a
> more restrictive namespace than classes.)

The Z-Machine doesn't particularly "do" dynamically created objects at
all. The idea of a class is, as a result, almost entirely only present
at the source level, except for (vary rare!) is-a tests. There isn't
really, ANAICT, any equivalent or any need for C++-style vtables.

(Not, I hasten to add, that this is the only way to do OO! After all,
the *** programming error: no such property named foo in object bar ***
messages Inform produces imply the Smalltalk or Python approach to
method calls.)

(And anyway, lexical scoping is a red herring because lexical scoping
in the manner of LISP or ML is *alone* sufficiently powerful to capture
everything OO can do, which thus includes doing explicit namespace
separation.)

> This isn't really about I7, whose main problem in this regard is its
> lack of a central library.

This is, I humbly submit, a feature. I'm aware that you're using TADS
3 as the measure of all things IF here -- I7's approach to what the
standard library should do is really quite explicitly The Opposite.
The most recent release, for example, as a *feature*, removed a
half-dozen or so actions from the basic library. Removed them.

And yes, this is a feature. A game that needs it can put any one of
them back in with three sentences, which can actually be scattered
throughout the source code almost wholly at will, and the library is
less cluttered.

> I7 lacks any decent
> hierarchical organization -- it lacks a multi-axis hierarchial
> structure which would determine, among other things, lexical range.

You'll have to define multi-axis if you're talking about source code
structure, because I only see one axis (nesting depth) in nearly all
languages.

If you're talking about the semantics of objects, though, this is
flatly untrue. It just generally doesn't use inheritance hierarchies
to do this. Where TADS3 has "DarkRoom" and "FloorlessRoom" as
subclasses of Room, the I7 library lets a room be "lit or unlit" and it
would be trivial to also distinguish them as "floorless or floored".
(The sentence there being "A room can be floorless or floored.") Three
or four additional sentences to describe defaults and the necessary
behavior of a FloorlessRoom would grant you the rest of the capability.

This also means multiple inheritance is unnecessary for the production
of a dark floorless room. You'd just define the room as "The mineshaft
is a dark floorless room west of the mine entrance" or what have you.

> All I'm saying is that it becomes a question, at what point in apeing
> OO should RO actually become OO. Or, if you can figure out what's left
> in RO that's worth saving, you've answered the question.

You're assuming by default that everyone agrees that OO is the optimum
way of controlling program complexity, and this is, to say the least,
not a universal viewpoint. And I7 isn't even *trying* to aim for it,
any more than, say, Haskell or SML is.

In fact, SML -- which defines its functions by, in effect,
pattern-matching on its arguments -- is the closest match to I7 rule
semantics I've found, and it's the one that guides my I7 designs. (The
OCaml dialect makes this a command "match x with" which is similar, and
could be rendered in I7 as "The following is a rulebook with rules to
check in this order.") Complexity in the ML family of languages, of
which SML is a part, is done primarily through what it calls
"structures" and "functors", which other languages either don't have or
call very different things.

There aren't really a lot of surprises in structures if you've used any
modular language (which includes any OO language), and the ML systems
I've used have tended to handle structures kind of clunkily from a UI
standpoint. Functors, however, have no direct equivalent anywhere
else, and I'll have to give "what would an I7 functor look like" some
thought before continuing down that road.

--Michael

Andrew Plotkin

unread,
Oct 12, 2006, 11:40:22 PM10/12/06
to
This grouping idea (sorry, no quotes from previous post, because it'd
basically be the whole thing) assumes a particular view of what it
means to "decide the precedence of a bunch of rules". To wit: arrange
the rules in a linear order.

Well, that sounds obvious, doesn't it? But I'm trying to specify the
system precisely now. So... a rule looks like

if C: instead of X, do CODE

Where X is the name of an activity (phrase, rulebook, etc). Actually
we can simplify this even more; we can treat this as equivalent to:

(rule for activity X): if C then CODE else X.

I don't think I want the author to *write* code like this, because
it's nicer to have the rule condition pulled out as a primary feature
of the rule. (I will say why later!) But this is what it will compile
as.

As usual, "before" and "after" rules look like:

if C: instead of X, do { X; CODE }
if C: instead of X, do { CODE; X }

Or equivalently:

(rule for activity X): if C then { X; CODE } else X.
(rule for activity X): if C then { CODE; X } else X.

So we have the sneaky question, what the heck does "X" mean in these
bits of CODE? Obviously it isn't "run activity X from the beginning".
(That would cause an infinite recursion.) My current theory is that
you put all the rules into an ordered list, and then for each rule,
"X" means "run the next rule in the list." (With the same parameters.)

Yes, this looks very much like what I7 calls "continue the action".
Except that I7 doesn't let you "continue the activity" or "continue
the phrase".

You may wonder why it took me two years to decide on an ordered list
of rules. Well, I haven't really settled on it -- but it's the
underlying model of this particular precedence system, which is the
least bad idea I've come up with, so I may be stuck with it. However,
there are some common IF patterns which seem rather non-linear. So
this post will try to account for them. If I succeed, I'll be fairly
confident that this model makes sense.

Patterns to think about:

* Skipping parts of an action sequence. Perhaps we want to disable the
"can't open what's locked" rule in certain circumstances. Or disable
all of the "reaching" rules. This corresponds to leaping over one or
more steps in the list.

* Boxes. This is my code name for the annoying situation you get when
you start with the previous case -- overriding the "can't open what's
locked" rule for a certain kind of closed box -- and then go through
two or three more cycles of, oh, I've thought of another special case.
This class uses rule B to decide whether it's locked, instead of
checking the "locked" property. But this subclass uses rule C instead.
But in some cases, the subclass falls back to rule B, or maybe to the
original rule A.

* One action behaves like another, in some circumstances (perhaps as a
default). This example came up on the newsgroup recently: "read"
should normally be a synonym for "examine", but for a few objects it
does something different. We'd like the common case to really be
synonymous -- it should be easy to make it execute exactly the same
code as "examine".

* Trying an action silently. You want to run through an activity, but
skip certain steps (the ones which print messages). It would be nice
to think that we're skipping the steps *at the end*, but really there
can be sub-sequences of rules with printing components anywhere in the
action. ("If the box is locked, say 'You can't get it open' and
fail.") If we treat that as a rule containing two sub-rules -- which
seems natural -- then our simple linear list has become a list of
lists. (So the notion of "next rule" gets confusing.)

* Changing the default message printed as the result of an action.
This is very common, of course, but it looks strangely like the same
problem as trying an action silently. Hm.

* While we're at it: changing default *failure* messages. Again, each
possible failure is a little branch hanging off the general action
list of rules. In I6, you go in and whack an entry in LibraryMessages,
but this seems crude.

* Also while we're at it: changing the default *behavior* of an
action, *without* changing the message. (You might customize the
"open" action of a box to update its internal state in some crazy way
-- more complicated than just setting an "open" property.) Note that
I've now mentioned what I7 calls the "report", "check", and "carry
out" phases; useful concepts, even if I'm not happy with how I7
handles them.

* Implicit take. This is the acid test; an action completely contained
within another action.

(Next up: solutions to a couple of these problems...)

--Z

--
"And Aholibamah bare Jeush, and Jaalam, and Korah: these were the borogoves..."
*

"Bush has kept America safe from terrorism since 9/11." Too bad his
job was to keep America safe *on* 9/11.

Andrew Plotkin

unread,
Oct 12, 2006, 11:42:49 PM10/12/06
to
I will start with the easiest case, or rather the case that easily
yields to the trick I've thought of.

* Skipping parts of an action sequence.

The "can't open what's locked" rule looks something like this:

Before opening something: fail with "[The noun] is locked", if noun
is locked.

We'd like to skip this rule if the Chime of Opening is ringing.
(Perhaps a more likely case, for games without silly example magic
items, is that we're going to handle locked boxes in a later rule, so
we want to suppress this rule.)

My clever trick is that this isn't an ordering question at all. We
want to disable *this rule*, which means modifying it in place. That
is, we're not really doing anything to the "opening" activity; we're
doing something to the "can't open what's locked" rule.

So, we should be able to express this as:

Instead of the condition of the can't open what's locked rule:
decide no, if the chime is ringing.

The basis of the trick is that in the basic implementation of the
rule:

(rule R:) if C: instead of X, do CODE

C is *itself* an activity -- not activity X, but activity
condition-of-R. In this example, C is the activity implemented as "if
noun is locked":

(rule condition-of-R:) { if noun is locked, decide yes; else decide
no. }

This has the form of a boolean property, you'll note. By modifying
this activity, we get the compiler to generate something like:

(rule for activity X):
if (chime is ringing), flag = false;
else flag = (noun is locked);
if flag then CODE else X.

(And there is also an activity code-of-R. So we could equally well
write:

Instead of the code of the can't open what's locked rule:
continue the activity, if the chime is ringing.

The fact that we have two formulations is redundant here, but will be
useful when we move beyond simple rule suppression.)

(Note that I am *not* talking about modifying the "locked" property
itself. That would be a different approach; I dealt with that in my
first properties post. This example is modifying one rule which, in
its default state, checks the "locked" property.)

Yes, I am relying on massive compiler optimization here. The rule
system will contain *zillions* of activities. Most of them will be
defined by a single rule and invoked from just one place. Such simple
activities should be compiled as simple functions, if not inlined away
entirely.

I nearly wrote: every activity is defined by at least one rule, and
every rule defines two activities (the code and the condition). Then I
realized the logical problem there. Don't sweat it, though. Most of
these activities are created implicitly by the compiler, and the
compiler knows when to stop dorking around and get on with the job.
(For a start, most of the implicit rules have the condition "decide
yes".) If you're perverse, you could redefine the "condition of the
condition of the condition of the whatever rule"... that's legal, but
it doesn't do anything useful.

Whew. Where was I? Oh, right -- suppressing one rule. And the next
thing was suppressing a bunch of rules; say, all the reaching rules.
(The ones that apply to verbs that involve touching the noun -- touch
and take, but not examine or listen to.) Say you become a Jedi at some
point in the game; Jedi can of course push and pull things that are
out of reach.

There are likely to be many reaching check rules. (Or are there?
Assume for the sake of example that there are.) We could modify each
of them:

Instead of the condition of rule R1: decide no, if the player is a
Jedi.
Instead of the condition of rule R2: decide no, if the player is a
Jedi.
...etc...

This is of course tedious and wrong. We want to suppress the entire...
group... of reaching rules. Group? Aha, we say: there probably *is* a
group of rules called the reaching rules. That's how they got sorted
into the action rulebook; someone said "Consider the reaching rules
after the deciding rules; consider the reaching rules before the
action rules." (Or something like that. I know, the details of actions
are still vague. Sorry.)

More importantly, how does the system decide *whether* to invoke
reaching rules? Why, it probably set them up like this:

Section - Reaching Rules
(Reaching rule 1): CODE, if the action is a reaching action.
(Reaching rule 2): CODE, if the action is a reaching action.
...

Where "reaching actions" is, guess what, a group of actions. That is,
a boolean property on actions. Which means we could say:

Instead of the condition of a reaching rule R:
decide no, if the player is a Jedi.

Or, equivalently but probably more efficiently:

Rule for deciding whether an action is a reaching action:
decide no, if the player is a Jedi.

* Boxes.

No, really -- I want to skip from one rule in a rulebook to a
different rule. None of this messing around with conditionals.

Again, the library has:

Before opening something: fail with "[The noun] is locked", if noun
is locked.

We decide the cool way to customize this rule is to mess with the
"locked" property. (Which is, of course, a boolean property of
objects.)

(R1:) Rule for deciding if something is locked: decide no.
(R2:) Rule for deciding if a safe is locked: decide yes.
(R3:) Rule for deciding if a fire door is locked:
if the building is burning, decide no;
else decide yes.
(R4:) Rule for deciding if the biometric door is locked:
if the player has the alien blood, decide no;
else decide yes.

(Recall that there is an implicit rule:

Rule for deciding if something is locked when its value has been
explicitly set:
if it has been explicitly set locked, decide yes;
else decide no.

That covers the fact that we set the safe to be unlocked in the "dial
safe" action. But we're not going to set any doors to be
locked/unlocked.)

These rules are all fine. Until we decide that the biometric door
should be a biometric *fire* door. (In other words, it should fall
open when the building catches fire.)

There are a few ways we could approach this. We could change the
"else" line of R4 -- copy and paste in the code from R3. That's ugly.

Or, we could make R4 a before rule:

Before deciding if the biometric door is locked:
if the player has the alien blood, decide no.

Lacking an "else" line, the rule would fall through to the rest of the
activity, and R3 would execute.

(Note that the form

Rule for deciding if the biometric door is locked:
if the player has the alien blood, decide no;
else continue the activity.

is exactly the same as the before-rule form. See the beginning of the
previous post!)

*However*, there might be an R3.5 that we want to skip. I don't know,
it's late and my example-inventor neuron is tired.

Anyway, the very dumb idea that all this is pointing at is to have a
more-specified form for "continue the activity". You should be able to
say, "continue the activity at rule R." (Where R is another rule in
the same activity/rulebook.)

(R4:) Rule for deciding if the biometric door is locked:
if the player has the alien blood, decide no;
else continue the activity at R3.

Since R3 has a lower precedence than R4, we're jumping ahead in the
list. But because of the underlying model, we're also invoking the
"locked" property that would have existed if R4 had never been
declared! See my original discussion of what "X" (the activity) means
in any rule's context.

We could also say "continue the activity at R5", where R5 is a
*higher* precedence rule. Or, indeed, "at R4". That's a loop, which
might be desirable for, I dunno, the usual reasons people write loops.

All of this behaves a bit counterintuitively when it comes to after
rules. The highest-precedence after rule runs *last* -- it has the
strongest claim to be after everything else! (This follows directly
from my formulation of after rules.) You can still skip ahead in the
list of afters (or jump back, for looping) but the precedence goes the
other way around.

* One action behaves like another, in some circumstances.

The easy way to do this is the way I6 and I7 handle it -- provide a
way to trigger an entirely new action.

Instead of reading something which is not a book:
Carry out the examining activity with the noun.

This isn't "continuing the action" within the current rulebook
execution; it's calling a new one (and that's all, since this is an
instead-of rule.) As long as this is a high-precedence rule, we'll get
the right result.

But imagine (work at it) a tangle of several of these declarations;
some on reading, some on examining. We'd like to skip over the tangle
when invoking the new action -- invoke only the "basic" examine
action.

I suppose the answer is a line like

Carry out the examining activity with the noun, at rule R3.

But that really starts to be spaghetti code, doesn't it? We'd like to
lean on the fact that this is a *group of rules* -- a high-precedence
group. And this group collectively wants to be able to invoke the form
of the activity that existed if the group had never been declared!
Very much like the previous example, you see; but with several rules
rather than one.

I haven't figured this one out yet.

(Man, that really broke the rhythm of this post.)

Maybe I'm stuck on the idea of invoking an entirely new action. This
whole scenario only makes sense for a group of *high-precedence* rules
-- the ones at the beginning of the rulebook list, that is -- so maybe
I should stick with "continuing the activity".

Well, I'll sleep on that. More later. (But I'm out of town starting
this weekend, and my net access will be intermittent, so don't expect
any huge updates for a while.)

Neil Cerutti

unread,
Oct 13, 2006, 8:19:20 AM10/13/06
to
On 2006-10-12, Michael Martin <mcma...@gmail.com> wrote:
> I would generally consider this feeding a troll, but as there's
> some relevant thoughts relating to Proper Full-Scale
> Programming Langauges For I7 that I haven't seen come up yet...

Thanks for chiming it. It cleared up some fuzzy thinking I was
having in all the excitement.

> As pointed out in the first post, sections *are* namespaces. I
> more than twelve objects in my current WIP in I7 with
> character-exact names, and both the Index and the testing
> ensure that these are, in fact, different things.
>
> They are, however, too restrictive, because it means that you
> *must* group code in certain ways in order for it to resolve
> properly. The lack isn't lack of namespaces. The lack is a
> lack of *qualified names*.

OK, much better. And I think Andrew's solution is very clever,
and is also in the spirit of I7 syntax.

> There aren't really a lot of surprises in structures if you've
> used any modular language (which includes any OO language), and
> the ML systems I've used have tended to handle structures kind
> of clunkily from a UI standpoint. Functors, however, have no
> direct equivalent anywhere else, and I'll have to give "what
> would an I7 functor look like" some thought before continuing
> down that road.

would it have to have functions first?

I'm not clear on the concept. The only 'functors' I've used is
the C++ version, which is just an object whose instances can be
called like functions.

--
Neil Cerutti

Andrew Plotkin

unread,
Oct 13, 2006, 11:18:00 AM10/13/06
to
Here, Neil Cerutti <hor...@yahoo.com> wrote:
> On 2006-10-12, Michael Martin <mcma...@gmail.com> wrote:
>
> > There aren't really a lot of surprises in structures if you've
> > used any modular language (which includes any OO language), and
> > the ML systems I've used have tended to handle structures kind
> > of clunkily from a UI standpoint. Functors, however, have no
> > direct equivalent anywhere else, and I'll have to give "what
> > would an I7 functor look like" some thought before continuing
> > down that road.
>
> would it have to have functions first?

I7 has several function-like mechanisms.

> I'm not clear on the concept. The only 'functors' I've used is
> the C++ version, which is just an object whose instances can be
> called like functions.

Functors in ML are functions that accept and return types. You use
them to generate new types (classes) on the fly. Same idea as
class templates or parametrized types in C++/Java.

I confess that I've never felt a need to do that when writing IF. :)

--Z

--
"And Aholibamah bare Jeush, and Jaalam, and Korah: these were the borogoves..."
*

If the Bush administration hasn't shipped you to Syria for interrogation, it's
for one reason: they don't feel like it. Not because of the Eighth Amendment.

Neil Cerutti

unread,
Oct 13, 2006, 1:05:14 PM10/13/06
to
On 2006-10-13, Andrew Plotkin <erky...@eblong.com> wrote:
> Here, Neil Cerutti <hor...@yahoo.com> wrote:
>> would it have to have functions first?
>
> I7 has several function-like mechanisms.

I was thinking of them as "function-lite" mechanisms. ;)

--
Neil Cerutti
You've got to take the sour with the bitter. --Samuel Goldwyn

Andrew Plotkin

unread,
Oct 13, 2006, 1:09:00 PM10/13/06
to
Here, Neil Cerutti <hor...@yahoo.com> wrote:
> On 2006-10-13, Andrew Plotkin <erky...@eblong.com> wrote:
> > Here, Neil Cerutti <hor...@yahoo.com> wrote:
> >> would it have to have functions first?
> >
> > I7 has several function-like mechanisms.
>
> I was thinking of them as "function-lite" mechanisms. ;)

Well, I7 phrases are functions with some polymorphism thrown in. A
phrase with one rule compiles directly as an I6 function; it can do
everything a function can do. (Except that you can't usefully get a
reference *to* the function.)

--Z

--
"And Aholibamah bare Jeush, and Jaalam, and Korah: these were the borogoves..."
*

Bush's biggest lie is his claim that it's okay to disagree with him. As soon as
you *actually* disagree with him, he sadly explains that you're undermining
America, that you're giving comfort to the enemy. That you need to be silent.

Andrew Plotkin

unread,
Oct 13, 2006, 4:00:10 PM10/13/06
to
Here, Andrew Plotkin <erky...@eblong.com> wrote:
>
> I haven't figured this one out yet.
>
> (Man, that really broke the rhythm of this post.)

Having thought a little more, I find I was confusing myself with the
image of a rulebook as a list of rules *in the game program*. (Which
is what I7 generates.)

What I've been talking about is a compiler which *has* such a list,
internally; but it uses that list to generate a series of functions
which implement the activity. Something like this (ignoring inlining
optimizations):

[ func_R1;
if (C1()) return "One.";
else return func_R2();
]

[ func_R2;
if (C2()) return "Two.";
else return func_R3();
]

[ func_R3;
return "Base case.";
]

There isn't a utility loop buried somewhere that chunks down an array
of rules. Each function is a valid representation of the whole
activity *taking account of some of the rules*. (The first function
takes account of all of them.) Okay, this is not an important
distinction to the game author, but it makes it easier to see how the
system will have to do certain things -- like skipping rules.

So, back a few posts ago, I said "the ordering system will work by
something like ranked-pairs." Let me dig into that a little.

Precedence declarations all boil down to rules for a "precedes"
property:

Rule for deciding whether rule R1 precedes rule R2: ...

Or maybe, to invoke groups of rules rather than specific ones:

Rule for deciding whether a reaching rule precedes a deciding rule: ...

The "precedes" property has special significance to the compiler. Not
just that it defines the precedence of other rules, but that it is an
ordering. That is, it's a property of two arguments, which usually
returns one of two values -- call them "<" or ">". It's antisymmetric
(you can say "A precedes B" or "B follows A", equivalently). It can
also return a "don't-care" value. (The rules

(R1:) decide "one" if X==1.
(R2:) decide "two" if X==2.

...don't need to have their precedence sorted, because they exist
under mutually contradictory conditions.) (But that's distinct from
the case where A and B are the *same* rule.) Or, of course, the
property can return "beats the hell out of me" -- the case where
nothing in the system specifies a precedence.

I'm going to assume that the compiler can get a result out of this
property for any pair of rules (in the same activity). (But really,
executing one Inform game action is an activity -- so most of the
rules of the standard library are going to pile up there.) This is the
same property resolution system that's used for object kinds, object
properties, etc, etc. General group-ordering rules should cover the
majority of the cases, and inferred precedences (from logical
comparison of rule conditions) will cover some. And there will be some
don't-cares[*] The rest are hellifiknows.

So then we just have the problem of taking this N^2 heap of
information and making a list. This is kind of what a ranked-pairs
(Condorcet) election does, which is why that came to mind. It's
ickier, though, because Condorcet uses a greedy algorithm to get
itself started: pick the two candidates for whom the candidates show
the strongest opinion, as measured by number of ballots that rank
them, and write their names on the blackboard. We don't have a ballot
count in that sense. But we can still pick *a* pair of rules and write
them up. Then pick another, compare it to both, and fit it into the
list. And so on.

We're going to run into two problems: underspecified preferences
(hellifiknows), and overspecified preferences (contradictions).

For hellifiknows, we delay the decision until we have more information
-- that is, until more of the list is resolved. (If we never get
enough info, it's time to break and ask the game author for help.)

For contradictions, well, we *do* have a way to compare precedence
"strength": a specific declaration ("X follows A") is stronger than a
group declaration ("Consonants precede vowels".) This may help.

You'll note I'm pretty much pulling this stuff out of my ass. I have
not done research on ordering procedures -- a topic about which, I
imagine, much has been said. I'll get to it.

--Z

(* Footnote: the problem of detecting don't-cares is no doubt going to
turn into a headache. It's essentially the problem of finding a good
database index key: what condition, in all the crazy conditions stuck
on these rules, distributes the rules into the most non-overlapping
bins? As with databases, the first-cut solution will no doubt be for
the program to give the compiler hints. Try "action" and "noun" first,
wink wink.)

--Z

--
"And Aholibamah bare Jeush, and Jaalam, and Korah: these were the borogoves..."
*

9/11 did change everything. Since 9/12, the biggest threat to American
society has been the American president. I'd call that a change.

Michael Martin

unread,
Oct 13, 2006, 7:00:02 PM10/13/06
to
Andrew Plotkin wrote:
> Functors in ML are functions that accept and return types. You use
> them to generate new types (classes) on the fly. Same idea as
> class templates or parametrized types in C++/Java.

Yeah. I tend to think of ML structures more as *modules* than types,
though, so my thoughts (still hazy and undefined, especially by the
standards of these threads) was moving some kind of way of interacting
with (or parameterizing) extensions.

> I confess that I've never felt a need to do that when writing IF. :)

The other part of the problem is Why This Would Be Handy, yes. :)

--Michael

steve....@gmail.com

unread,
Oct 13, 2006, 8:40:45 PM10/13/06
to

Michael Martin wrote:
> I would generally consider this feeding a troll

I don't understand why you think you would like to insult me. The
feeling isn't mutual.

> > > A class or object makes a for a too-restrictive namespace.
> >
> > Maybe so, but it's a lot better than no namespace at all.
>
> As pointed out in the first post, sections *are* namespaces.

They could be interpreted as namespaces, with some work. (Whether it's
actually doable I don't know.) In any case this is not namespace in the
conventional sense, and sections are not functional namespaces at
present.

> The
> lack isn't lack of namespaces. The lack is a lack of *qualified
> names*.

That's a separate issue. I personally think it's really dumb that you
cannot provide programmatic object names when you want. TADS 3 allows
you to leave off the name, but it doesn't deny you the capability. When
a programming language denies capabilities, it's a good sign that it
was designed for the designer, not the user. But that has nothing to do
with namespaces, which itself has relatively little to do with the
initial point.

> The Z-Machine doesn't particularly "do" dynamically created objects at
> all.

Relevance? You think we're talking about the Z-Machine?

> (And anyway, lexical scoping is a red herring because lexical scoping
> in the manner of LISP or ML is *alone* sufficiently powerful to capture
> everything OO can do, which thus includes doing explicit namespace
> separation.)

Relevance? Obviously we're not talking about LISP or ML.

> > This isn't really about I7, whose main problem in this regard is its
> > lack of a central library.
>
> This is, I humbly submit, a feature. I'm aware that you're using TADS
> 3 as the measure of all things IF here

No, and I'd appreciate if you quit condescending. In fact, I find this
"oh, I'm quite aware of <you being wrong>" garbage-rhetoric quite rude
and irresponsible.

The problem of extension collision, which is one of the things we
actually *were* talking about, is somewhat alleviated by having a well
worked out library. Anyone could easily have predicted this problem for
I7.

> > I7 lacks any decent
> > hierarchical organization -- it lacks a multi-axis hierarchial
> > structure which would determine, among other things, lexical range.
>
> You'll have to define multi-axis if you're talking about source code
> structure, because I only see one axis (nesting depth) in nearly all
> languages.

Well, the suggestion that Andrew made was to immitate two axes of OO,
class mixing in relation to class hierarchy. (Andrew used the word
'group' rather than class, but the idea is the same.) There's more
going on in OO than this, but that should get you thinking.

> If you're talking about the semantics of objects, though, this is
> flatly untrue. It just generally doesn't use inheritance hierarchies
> to do this. Where TADS3 has "DarkRoom" and "FloorlessRoom" as
> subclasses of Room, the I7 library lets a room be "lit or unlit" and it
> would be trivial to also distinguish them as "floorless or floored".
> (The sentence there being "A room can be floorless or floored.") Three
> or four additional sentences to describe defaults and the necessary
> behavior of a FloorlessRoom would grant you the rest of the capability.

You're thinking too much about declaring objects. In this respect, I7
is doing a lame but passable job at being itself OO.

> You're assuming by default that everyone agrees that OO is the optimum
> way of controlling program complexity, and this is, to say the least,
> not a universal viewpoint.

Obviously I'm not assuming that, as it is obviously untrue. You're
being obviously condescending and a dick. Troll baiting indeed. You're
just being an ass and not taking the discussion seriously. Why don't
you go do some reading and figure out what I am actually saying, and
respond to that.

Jim Aikin

unread,
Oct 13, 2006, 11:44:11 PM10/13/06
to
I've dipped lightly into this thread, with some trepidation. The parts of it
I can understand seem very intriguing, and possibly very helpful in the
development of a new IF language (which I think is what you're envisioning,
more or less).

I'd like to pose a question, if I can do so without sounding like a
troll....

Background: I'm just a poor dumb author. (Well, perhaps not quite dumb; I
did score 800 on the math SAT, but that was more than 40 years ago.) I want
to write interactive stories, not bury my nose in a manual for months on
end. So my evaluation of any new IF language, or any proposed changes in an
existing language, is going to be heavily weighted toward a consideration of
how, or whether, the new features will make my life easier and more
pleasant.

Don't get me wrong -- powerful features are important. I'm not planning to
switch to Quest anytime soon. But two points may be worth bearing in mind.
First, the existing features of the existing major IF languages will
probably work perfectly swell for 95% of the situations one may want to
incorporate in a story. And second, the other 5% of situations one may want
to incorporate tend to be one-offs. They tend to be demanded by a particular
scenario and will quite likely resist the rigors of conceptual
generalization.

I find that I can do almost anything that I need to do in Inform 6 ... but
sometimes it's a hack, and once in a while I give up because it's just too
big a headache. So my question is ... well, I guess maybe it's two related
questions.

First, what concrete advantages do you envision your concepts offering to
the author, in terms of implementation, workflow, etc.?

Second, how do you envision presenting this conceptual framework to the
author in terms of source code syntax and the documents with which one would
learn said syntax?

This is perhaps an IF version of a principle that I've heard mentioned in
the field of synthesizer design: You design the user interface FIRST. Once
you understand how the musician will interact with the box, you know what
features to put under the hood.

This principle breaks down at various points, of course. It could not have
been applied in the design of the Yamaha DX7, which was one of the most
successful synths of all time, because the technology under the hood was
entirely new. Nonetheless, I think it's probably a principle that's worth
keeping in mind. Them's mah 2 cents, anyhow.

--Jim Aikin


Michael Martin

unread,
Oct 14, 2006, 4:58:59 AM10/14/06
to
Too many points veering off-thread here, but a few are both relevant
and interesting and deserve a response.

steve....@gmail.com wrote:
> They could be interpreted as namespaces, with some work. (Whether it's
> actually doable I don't know.) In any case this is not namespace in the
> conventional sense, and sections are not functional namespaces at
> present.

My I7-based work in progress has 10 or so objects with non-unique
identifiers, so it's quite practical, and if you've organized the
source sensibly, it's also entirely invisible (barring two compiler
bugs which have been already been duly reported and contradict what the
manual implies the compiler should be doing).

[snip, and reorganized to sort by response:]
> [Lack of qualified names is] a separate issue. ... But that has nothing to do


> with namespaces, which itself has relatively little to do with the
> initial point.

I'm using "qualified name" here in the sense the Java Language Spec
uses it, viz, something like "Packagename.Classname.fieldname" instead
of just "fieldname". Java doesn't have an explicit namespace mechanism
the way C++ does, but you can use static inner classes to get the same
effect, and even in C++ namespace selection and member selection use
the same :: syntax. So I'd say it's actually quite related.

> Relevance? You think we're talking about the Z-Machine?

We're talking about a variant language based on I7, which primarily
targets the Z-Machine and inherits to greater or lesser degrees various
assumptions the Z-Machine makes. In most I6 and I7 programs, all
objects are allocated and pre-initialized at program start, and once
the program has started, objects are neither created nor destroyed.
Both languages operate from this assumption.

> The problem of extension collision, which is one of the things we
> actually *were* talking about, is somewhat alleviated by having a well
> worked out library. Anyone could easily have predicted this problem for
> I7.

I consider the greatest and most significant difference between I7 and
T3 to be the intent of their standard libraries. I7 is intending to be
minimal, to be extended as needed possibly with a number of third-party
modules. T3 is intending to cover all of the reasonably expectable
bases commonly found in vaguely realistic IF worlds, and then keep the
abstract superclasses around for extension by the user later to cover
the truly exotic cases. There are tradeoffs involved both ways, and
the extension collision problem is, as you note, always only "somewhat"
alleviated.

> Well, the suggestion that Andrew made was to immitate two axes of OO,
> class mixing in relation to class hierarchy.

This pretty much shows our fundamental disagreement. You're seeing
this as class mixing or as simulating OO, because it's doing things
that have direct OO analogues. I'm not, because as far as I'm
concerned, *everything* has an OO analogue, and a procedural analogue,
and a functional analogue. That an OO system has a mechanism that does
something similar is not, to me, evidence that the OO system is being
imitated.

This last bit is totally off-thread, but you've pointed near an
interesting assymetry in I7's default behaviors here, so I'll cover
that here.

> I personally think it's really dumb that you
> cannot provide programmatic object names when you want. TADS 3 allows
> you to leave off the name, but it doesn't deny you the capability.

I7 is more blurring the capability than eliminating it, and it's
similar to the way it handles map connections. As a result, I'd
suggest a different solution for I7, one closer to how it handles
connections. From my experience with I7 and TADS 3, the real
difference here is twofold:

(1) Unlike most programming languages, I7 allows spaces inside its
identifiers, so the identifier for a green apple can be "green apple".
(2) Unlike TADS 3 (and Inform 6 -- I have no experience with other
systems other than flipping through Cloak of Darkness once), I7
includes the words of the identifier as part of the "name" property --
that is, the game will let the player refer to the object that way.
Obviously, this is only feasible because (1) is true.

So, this is perfectly legal I7:

greenApple13 is in the Kitchen. The printed name of greenApple13 is
"green apple". Understand "green" or "apple" as greenApple13.

This will end up looking like an object defined in I7 as "A green apple
is in the Kitchen" but still have a traditional-looking identifier.
However, the player will be allowed to type > EAT GREENAPPLE13, and
there seems at present to be no way to stop this. The most logical
solution would be a command structure of the form:

Understand "greenApple13" as nothing at all.

This corresponds to the way you do one-way doors in I7:

Down from the Chute is the Cellar. Up from the Cellar is nowhere.

But this moves well beyond the scope of this discussion.

--Michael

Michael Martin

unread,
Oct 14, 2006, 5:12:28 AM10/14/06
to
Andrew Plotkin wrote:
> Possible down-sides: there is no way to say "run the reaching rules
> for this action". But then, is that something you want to do?

Wouldn't a check on "if object X is reachable by actor Y" end up
meaning "run the reaching rules", including all those special-case
things like "Rule for deciding if the player can reach an object: if
the player has eaten the Energy Sphere of Omnipresence, decide yes"?

We definitely need to be able to do that, because I could easily want
to do something like this:

The description of the golden coin is "This coin must be hideously
valuable. It sits[if the golden coin is reachable] here, daring you to
walk off with it[otherwise] out of reach, taunting you with its
unavailablility[end if]."

(Well, by "could easily" I here mean "just realized that I'd like to do
it in one of the games I have sketched out but not implemented.)

--Michael

steve....@gmail.com

unread,
Oct 15, 2006, 3:54:58 PM10/15/06
to

Michael Martin wrote:
> > [Sections] could be interpreted as namespaces, with some work. (Whether it's

> > actually doable I don't know.) In any case this is not namespace in the
> > conventional sense, and sections are not functional namespaces at
> > present.
>
> My I7-based work in progress has 10 or so objects with non-unique
> identifiers, so it's quite practical, and if you've organized the
> source sensibly, it's also entirely invisible (barring two compiler
> bugs which have been already been duly reported and contradict what the
> manual implies the compiler should be doing).

As Andrew has explained, this is a hack, and one that doesn't work for
his idea.

> > [Lack of qualified names is] a separate issue. ... But that has nothing to do
> > with namespaces, which itself has relatively little to do with the
> > initial point.
>
> I'm using "qualified name" here in the sense the Java Language Spec
> uses it, viz, something like "Packagename.Classname.fieldname" instead
> of just "fieldname". Java doesn't have an explicit namespace mechanism
> the way C++ does, but you can use static inner classes to get the same
> effect, and even in C++ namespace selection and member selection use
> the same :: syntax. So I'd say it's actually quite related.

You're really not making much sense. We're talking about reorganizing
the way rules hiererchically interrelate, how groups of rules, of
varying specificity, can be integrated. We're *not* fixating on
namespace -- how we refer is a minor concern. Further, the fact that
game objects do not carry programmatic names has little to do with the
internal reference mechanisms available.

> > Relevance? You think we're talking about the Z-Machine?
>
> We're talking about a variant language based on I7, which primarily
> targets the Z-Machine and inherits to greater or lesser degrees various
> assumptions the Z-Machine makes. In most I6 and I7 programs, all
> objects are allocated and pre-initialized at program start, and once
> the program has started, objects are neither created nor destroyed.
> Both languages operate from this assumption.

I don't think Andrew was talking about the Z-Machine, but maybe you can
ask him. My interest in this thread has nothing to do with the
Z-Machine, which I consider the single dumbest thing about Inform.

> > The problem of extension collision, which is one of the things we
> > actually *were* talking about, is somewhat alleviated by having a well
> > worked out library. Anyone could easily have predicted this problem for
> > I7.
>
> I consider the greatest and most significant difference between I7 and
> T3 to be the intent of their standard libraries. I7 is intending to be
> minimal, to be extended as needed possibly with a number of third-party
> modules. T3 is intending to cover all of the reasonably expectable
> bases commonly found in vaguely realistic IF worlds, and then keep the
> abstract superclasses around for extension by the user later to cover
> the truly exotic cases. There are tradeoffs involved both ways, and
> the extension collision problem is, as you note, always only "somewhat"
> alleviated.

Great description. Recent discussion on the TADS 3 development list has
focused my attention on name collision. But outside the limited field
of the generation of keywords, a well-worked-out library effectively
eliminates the problem of collision.

> > Well, the suggestion that Andrew made was to immitate two axes of OO,
> > class mixing in relation to class hierarchy.
>
> This pretty much shows our fundamental disagreement. You're seeing
> this as class mixing or as simulating OO, because it's doing things
> that have direct OO analogues. I'm not, because as far as I'm
> concerned, *everything* has an OO analogue, and a procedural analogue,
> and a functional analogue. That an OO system has a mechanism that does
> something similar is not, to me, evidence that the OO system is being
> imitated.

This is a pretty flat and empty point, if you just say that "everything
has an OO analogue." It's like the deflating argument that Graham has
tried a couple times, that "everything can be theoretically reduced to
a Turing machine, so <blah>." Lost in this deflation is our capability
to think productively about the significance of the analogies.

Andrew Plotkin

unread,
Oct 16, 2006, 12:45:40 PM10/16/06
to
Here, Michael Martin <mcma...@gmail.com> wrote:
> Andrew Plotkin wrote:
> > Possible down-sides: there is no way to say "run the reaching rules
> > for this action". But then, is that something you want to do?
>
> Wouldn't a check on "if object X is reachable by actor Y" end up
> meaning "run the reaching rules", including all those special-case
> things like "Rule for deciding if the player can reach an object: if
> the player has eaten the Energy Sphere of Omnipresence, decide yes"?

Not necessarily. The way I'm thinking of setting this up, those rules
are a subset of the action rules. They're not a subroutine which
are called by an *entry* in the action rules.

(The rationale behind this is, again, easier rearrangement.)



> We definitely need to be able to do that, because I could easily want
> to do something like this:
>
> The description of the golden coin is "This coin must be hideously
> valuable. It sits[if the golden coin is reachable] here, daring you to
> walk off with it[otherwise] out of reach, taunting you with its
> unavailablility[end if]."

This is an interesting point. But it's actually beyond the scope of
what I'm considering right now. You want to run an action silently
*and without consequences*, just to see if it succeeds or fails. Rules
are not, in general, set up to allow this! They can look like "If
the wire is live, say 'ZAP' and set your hand on fire."

The desire to check rules for success without running them is in line
with Nate Cull's notion of NPC planning. I think something like that
is necessary, but I don't have a clear idea of how to do it.
Hopefully, if it can be done, it can be done in a direct way --
referring to the rules as a group, because *any* group of rules can be
referred to.

--Z

--
"And Aholibamah bare Jeush, and Jaalam, and Korah: these were the borogoves..."
*

Andrew Plotkin

unread,
Oct 16, 2006, 1:07:31 PM10/16/06
to
Here, Jim Aikin <rai...@musicwords.net> wrote:
>
> I'd like to pose a question, if I can do so without sounding like a
> troll....

Sure. Only my answer is going to be brief, because I'm away from home
this week and my net time is limited. Expect me to be a few days
behind on this newsgroup for the next week.



> First, what concrete advantages do you envision your concepts offering to
> the author, in terms of implementation, workflow, etc.?

Some of the answer is "what Inform 7 already offers, but better." If
you prefer Inform 6 now, this may not mean anything to you. On the
other hand, I may be able to improve on I7 in a way that *is*
meaningful to you.

The rest of the answer is "a simple consistent syntax, a simple -- or
at least unified -- set of mechanisms underneath." And the whole system
will be written in that language; including the standard library, and
deep IF mechanisms (scope, reaching, action order) which I7 handles by
hardwiring the compiler.

That, I hope, gets at your second question:

> Second, how do you envision presenting this conceptual framework to
> the author in terms of source code syntax and the documents with
> which one would learn said syntax?

I envision writing a complete specification of the syntax and the
underlying mechanisms.

> This is perhaps an IF version of a principle that I've heard
> mentioned in the field of synthesizer design: You design the user
> interface FIRST. Once you understand how the musician will interact
> with the box, you know what features to put under the hood.

That doesn't make sense to me, because features *are* interface.
Features are a categorized list of what the musician will want to do.

I envision writing a complete specification of the system *after* I
understand how it will work. And after I write it, yes. (While I'm
writing it, the spec will exist, but not in a form that anybody else
will be able to read. Not worth it -- it's certain to change in the
writing.)

But that's a long way off, really.

--Z

--
"And Aholibamah bare Jeush, and Jaalam, and Korah: these were the borogoves..."
*

ka...@henchmonkey.org

unread,
Oct 16, 2006, 8:25:04 PM10/16/06
to
Andrew Plotkin <erky...@eblong.com> wrote:
>> We definitely need to be able to do that, because I could easily want
>> to do something like this:
>>
>> The description of the golden coin is "This coin must be hideously
>> valuable. It sits[if the golden coin is reachable] here, daring you to
>> walk off with it[otherwise] out of reach, taunting you with its
>> unavailablility[end if]."
>
> This is an interesting point. But it's actually beyond the scope of
> what I'm considering right now. You want to run an action silently
> *and without consequences*, just to see if it succeeds or fails. Rules
> are not, in general, set up to allow this! They can look like "If
> the wire is live, say 'ZAP' and set your hand on fire."
>
> The desire to check rules for success without running them is in line
> with Nate Cull's notion of NPC planning. I think something like that
> is necessary, but I don't have a clear idea of how to do it.
> Hopefully, if it can be done, it can be done in a direct way --
> referring to the rules as a group, because *any* group of rules can be
> referred to.

This actually ties in with vague ideas I've had about an
event/message-based IF system. In this plan, all of the rules would run
as usual, and then send a message to the actor, and any other objects in
scope that are interested. The player-object would process this message
and then display output to the player. NPC objects would process the
message and either respond (via another message that the player-object
would translate to actual output), or adjust their internal state
(NPC.add_knowledge(book, in, bookshelf), say), or just silently ignore.
In this kind of setup, it's fairly easy to set the rules-running engine
to work silently: it just doesn't emit messages, or emits them with a
special JUST_TESTING flag, or something.

But hey, if I want to develop this, I should at least think it through
as far as you have with your rules system. :-)

katre

0 new messages