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

IF engine features request?

12 views
Skip to first unread message

Albert

unread,
Aug 30, 1999, 3:00:00 AM8/30/99
to
I'm in the process of creating my own IF engine, coded in C++ and
OOD. Right now I'm reworking the parser (but before I do that I have
to make my own custom stream class, but I expect to finish that by
the end of this week), but I'd like to know any unique features you'd
like to see that aren't easily done in either TADS, Inform, or any
other popular IF engine. I've heard someone mention the ability to
call a function to determine which room an exit leads to, but I couldn't
think of anywhere else this could be applied.

--

Albert (TheCheeseMan) (Baud Bard)
http://home.earthlink.net/~thecheezeman
http://conceptual.virtualave.net
ICQ: 14617788

"I don't know why I did it,
I don't know why I enjoyed it,
and I don't know why I'll do it again."
- Bart Simpson

Jonadab the Unsightly One

unread,
Aug 31, 1999, 3:00:00 AM8/31/99
to
artfulbobATmindspringDOTcom (Albert) wrote:

> I'm in the process of creating my own IF engine, coded in C++ and
> OOD. Right now I'm reworking the parser (but before I do that I have
> to make my own custom stream class, but I expect to finish that by
> the end of this week), but I'd like to know any unique features you'd
> like to see that aren't easily done in either TADS, Inform, or any
> other popular IF engine. I've heard someone mention the ability to
> call a function to determine which room an exit leads to, but I couldn't
> think of anywhere else this could be applied.

That's a very useful feature, but it would by no means be unique.
Any good IF language can do that.

Here are some features that Inform does NOT do that you
could consider:

Automatic typo correction.

Automatic scanning of the text an object produces to determine
whether it matches what the player typed. To be really
effective this should work even on text produced by one
of the object's routines.

Automatic detection and scoring of creative solutions the
author didn't think about.

Non-player characters that the author designates as "friend"
or "foe" and automatically act in an attempt to either
help the player or prevent him from obtaining any of
the game goals. Why should the player have to specifically
program a theif or pirate to steal valuables? Any foe
should automatically pick up anything in reach that the
player could use to get points. A friend character
should do the same thing, but should bring them to the
player. If the author defines weapon objects, the
NPCs could automatically fight, also.

"His eye twitches involuntarily." -- Calvin
"Can't we play something else?" -- Hobbes

BrenBarn

unread,
Aug 31, 1999, 3:00:00 AM8/31/99
to
>I'm in the process of creating my own IF engine, coded in C++ and
>OOD. Right now I'm reworking the parser (but before I do that I have
>to make my own custom stream class, but I expect to finish that by
>the end of this week), but I'd like to know any unique features you'd
>like to see that aren't easily done in either TADS, Inform, or any
>other popular IF engine.
I don't know how TADS is with this, but I do know that in Inform,
debugging from within the run-time product (using Infix) is very tough. I would
suggest:
1) Give the user to set a command (I'll call it "source on/off") that
toggles whether debugging commands affect the source document or just the
current instance of the game. (For example, if I type ";give apple edible",
the apple becomes edible only for this particular instance of the game. If I
type "Source on" first, then the source code is altered so that the apple is
initially defined as having "edible". 2) Also, the user should be able to
give a debugging command (I'll call it "sourceback"), check to see that it
works, and then retroactively make it affect the source. (For example, I
should be able to type either "Source on" and then ";give apple edible", or
";give apple edible" and then "Sourceback", and acheive the same effect.)
Ideally, I could type "Sourceback X", where X is a number, to apply the last X
debugging commands to the source.
3) Allow the user to trace, step by step, the sequence of commands in a
routine. The user should be able to "step through" each statement in a routine
individually, and this should work for both global and local routines.
4) In conjunction with the above, allow the user to edit routines at
run-time. (For example, if there is a problem with a certain routine inside a
certain object, I can use #3 above to debug the problem, then use #4 to
reprogram the routine, and then use #2 to lock those changes into the source.
I fear I may have given you more than you were looking for. But thanks
for giving me the opportunity to spout off (as if I needed one :-).

From,
Brendan B. B. (Bren...@aol.com)
(Name in header has spam-blocker, use the address above instead.)

"Do not follow where the path may lead;
go, instead, where there is no path, and leave a trail."
--Author Unknown

Graham Nelson

unread,
Aug 31, 1999, 3:00:00 AM8/31/99
to
In article <37cb6ea7...@news.bright.net>, Jonadab the Unsightly One

<URL:mailto:jon...@bright.net> wrote:
> Here are some features that Inform does NOT do that you
> could consider:
...

> Automatic scanning of the text an object produces to determine
> whether it matches what the player typed. To be really
> effective this should work even on text produced by one
> of the object's routines.

This is an exercise in the manual. It isn't as tricky as it
looks! -- Though it is still a bit tricky.

--
Graham Nelson | gra...@gnelson.demon.co.uk | Oxford, United Kingdom


Paul Alexander Mikell

unread,
Aug 31, 1999, 3:00:00 AM8/31/99
to

Albert wrote:

> I'm in the process of creating my own IF engine, coded in C++ and
> OOD. Right now I'm reworking the parser (but before I do that I have
> to make my own custom stream class, but I expect to finish that by
> the end of this week), but I'd like to know any unique features you'd
> like to see that aren't easily done in either TADS, Inform, or any

> other popular IF engine. I've heard someone mention the ability to
> call a function to determine which room an exit leads to, but I couldn't
> think of anywhere else this could be applied.

A re-entrant parser would make it much easier to code autonomous NPCs. An
NPC's daemon routine could contain a line of code such as:

self.parse("take everything from the table except except the mcguffin
then go north");

instead of having to build lists of objects and call action routines
directly (not trivial for the above example). It would also enable NPCs to
give orders to other NPCs eg:

captain, tell the robot to open the airlock

Another feature for the parser would be to allow it to handle commands given
to multiple actors, possibly including the player eg:

robot and me, pull rope


wo...@one.net

unread,
Aug 31, 1999, 3:00:00 AM8/31/99
to

Hi Jesse,

jwe...@pacific.mps.ohio-state.edu (Jesse Welton) wrote:

>That particular feature is a special use of what should be a general
>feature, that objects' members can be arbitrary functions (methods).
>Ideally, methods which require no parameters should be called
>identically to the way direct data members are accessed.
>
>Here are some features I would like to have:
>
>* Anonymous, first-class functions with lexical scope, as in Scheme.
> This aids in such things as defining flexible high-level interfaces
> to game functionality. (Eg, write a general sort routine which takes
> a comparison function as an argument; it's convenient to be able to
> use a function written in-line with the call to the sorter.)
>
>* Flexible and powerful operations on collections, as in Smalltalk.
> This allows the concise expression of operations to be performed on
> all objects satisfying a given criterion. I don't want to have to
> write C-style for loops everywhere.
>
>* If you provide a way to call functions/methods with variable numbers
> of arguments, also provide a way to apply a function/method to an
> arbitrary collection of arguments, as in Scheme's apply function.
>
>* Automatic memory management.
>
>* Programmatic formation of code tokens: Take the suffix 'Check' and
> add it to the root 'Take' to get 'TakeCheck', then convert this to a
> symbol/compiler token <TakeCheck>, which may then be used to call an
> object's TakeCheck method. This way, a verb may define a whole
> family of checking and action methods by specifying a single root
> for that verb and applying general verb-check generators.
>
>* As few compiler assumptions about how I'll use the system as
> possible. For example, TADS limits its flexibility by automatically
> setting up objects' contents lists and not allowing this member to
> be overridden with a method, which would be a useful thing to do in
> certain implementations of items with multiple kinds of contents.
>
>Hmmm... Nothing else off the top of my head, but that should be
>enough keep you busy. :)

Python supports most of these, and PAWS has a Get() function to call
either properties or an argumentless method with common
syntax--including the ability to automatically return None if an
object doesn't have the requested property/method.

Respectfully,

Wolf

"The world is my home, it's just that some rooms are draftier than
others". -- Wolf

Albert

unread,
Aug 31, 1999, 3:00:00 AM8/31/99
to
jon...@bright.net (Jonadab the Unsightly One) wrote in
<37cb6ea7...@news.bright.net>:

>artfulbobATmindspringDOTcom (Albert) wrote:
>
>> I'm in the process of creating my own IF engine, coded in C++ and
>> OOD. Right now I'm reworking the parser (but before I do that I have
>> to make my own custom stream class, but I expect to finish that by
>> the end of this week), but I'd like to know any unique features you'd
>> like to see that aren't easily done in either TADS, Inform, or any
>> other popular IF engine. I've heard someone mention the ability to
>> call a function to determine which room an exit leads to, but I couldn't
>> think of anywhere else this could be applied.
>

>That's a very useful feature, but it would by no means be unique.
>Any good IF language can do that.
>

>Here are some features that Inform does NOT do that you
>could consider:
>

>Automatic typo correction.

Something I was considering was being able to create synonyms
from within a game, allowing you to do things like:
retrieve=put and the game would automatically recognize retrieve
as the put command. This could probably be extended to include
commonly misspelled commands. Otherwise, I suppose I could do
a lexicographical (sp?) comparison...

>Automatic scanning of the text an object produces to determine
> whether it matches what the player typed. To be really
> effective this should work even on text produced by one
> of the object's routines.

I don't follow your train of thought here.

>Automatic detection and scoring of creative solutions the
> author didn't think about.

Hmmm, this could be hard. My best guess is to keep track of the
different things a player does. If the expected is not done and
yet a problem is somehow solved, add points. The more actions
the player takes, the more points are given.

>Non-player characters that the author designates as "friend"
> or "foe" and automatically act in an attempt to either
> help the player or prevent him from obtaining any of
> the game goals. Why should the player have to specifically
> program a theif or pirate to steal valuables? Any foe
> should automatically pick up anything in reach that the
> player could use to get points. A friend character
> should do the same thing, but should bring them to the
> player. If the author defines weapon objects, the
> NPCs could automatically fight, also.

In other words, AI. This would be very difficult, but I could
do mudprog like things that simulate such intelligence.

>
>
>"His eye twitches involuntarily." -- Calvin
>"Can't we play something else?" -- Hobbes

Thanks for the suggestions :)

Evin C Robertson

unread,
Sep 1, 1999, 3:00:00 AM9/1/99
to
Jonadab wrote:
> Here are some features that Inform does NOT do that you
> could consider:
>
> Automatic typo correction.

Nitfol (my z-machine interpreter) optionally provides typo corrections.
It'll fix a single one-letter
transposition/deletion/insertion/substitution per word in input. So
while this isn't strictly part of Inform, you can play Inform games with
typo correction if you wish.

BrenBarn requested:


> 3) Allow the user to trace, step by step, the sequence of commands in a
> routine. The user should be able to "step through" each statement in a
> routine individually, and this should work for both global and local
> routines.

Nitfol also provides this for Inform games (when the game is compiled with -k).


Jonadab the Unsightly One

unread,
Sep 1, 1999, 3:00:00 AM9/1/99
to
Graham Nelson <gra...@gnelson.demon.co.uk> wrote:

> Jonadab the Unsightly One wrote:
>
> > Automatic scanning of the text an object produces to determine
> > whether it matches what the player typed. To be really
> > effective this should work even on text produced by one
> > of the object's routines.
>

> This is an exercise in the manual. It isn't as tricky as it
> looks! -- Though it is still a bit tricky.

To get it to work with text produced by embedded routines, I
cannot immagine but what the VM would have to have some
restrictions that the z-machine lacks. Unless perhaps it
were to only work on text that the object's routines have
actually printed so far that game, as opposed to text they
might theoretically print in the future. That restriction
would make it possible. Then you just have to store
records of text produced by each object...

Jonadab the Unsightly One

unread,
Sep 1, 1999, 3:00:00 AM9/1/99
to
jwe...@pacific.mps.ohio-state.edu (Jesse Welton) wrote:

> That particular feature is a special use of what should be a general
> feature, that objects' members can be arbitrary functions (methods).

Exactly. Well, most of them can, anyway. Most of the exceptions in
Inform generally have a parallel property that is supposed to be
a function if it exists. For example, name can't be a function
(AFAIK), but parse_name is the functional equivalent. I don't mind
that, as it retains the spirit of what you said, albeit not the
letter of it. (The reason for the dichotomy in this case is
that there are times when it's handy to have BOTH...)

> Ideally, methods which require no parameters should be called
> identically to the way direct data members are accessed.

Inform doesn't do this DIRECTLY, but PrintOrRun() and ValueOrRun()
are library-provided workarounds to allow you to do essentially
just that, and they're VERY handy. So yeah, I'd agree with your
statement. Being able to get the value if it's a value or the
return value if it's a function without caring which it is can
be extraordinarily useful.

> Here are some features I would like to have:
>

> * Flexible and powerful operations on collections, as in Smalltalk.
> This allows the concise expression of operations to be performed on
> all objects satisfying a given criterion. I don't want to have to
> write C-style for loops everywhere.

objectloops allow a certain amount of that, particularly with
objectloop (i ofclass foo), but I can immagine some extensions
such as, for example objectloop (i has light) or perhaps
objectloop (i suchthat [generic condition]) even.
That's syntax sugar, but it might be handy. Then again,
it might encourage overuse, and it should be noted that
both of the above would have to check the condition for
every object in the game (unlike, say, objectloop (x in y),
which doesn't have to do that, even if it's implemented
the "safe" way).

> * Programmatic formation of code tokens: Take the suffix 'Check' and
> add it to the root 'Take' to get 'TakeCheck', then convert this to a
> symbol/compiler token <TakeCheck>, which may then be used to call an
> object's TakeCheck method. This way, a verb may define a whole
> family of checking and action methods by specifying a single root
> for that verb and applying general verb-check generators.

You completely lost me here.

Jesse Welton

unread,
Sep 1, 1999, 3:00:00 AM9/1/99
to
In article <ant3108150b0M+4%@gnelson.demon.co.uk>,

Graham Nelson <gra...@gnelson.demon.co.uk> wrote:
>In article <37cb6ea7...@news.bright.net>, Jonadab the Unsightly One
><URL:mailto:jon...@bright.net> wrote:
>> Here are some features that Inform does NOT do that you
>> could consider:
>...

>> Automatic scanning of the text an object produces to determine
>> whether it matches what the player typed. To be really
>> effective this should work even on text produced by one
>> of the object's routines.
>
>This is an exercise in the manual. It isn't as tricky as it
>looks! -- Though it is still a bit tricky.

Perhaps I'm missing the point, but is this something one would
actually want to do? It seems like it would be an invitation for
parsing bugs. If the player is wandering through the desert, and a
location's description runs, "There is sand all around you for miles,
your throat is getting seriously parched, and your skin is starting to
burn in the sun," I definitely wouldn't want 'sand', 'throat', or
'skin' to refer to that location object. "X skin" repeats all that
about the sand and your throat? I should hope not!

Or do I misunderstand how this is supposed to work?

-Jesse

Jesse Welton

unread,
Sep 1, 1999, 3:00:00 AM9/1/99
to
In article <37ccabcf...@news.bright.net>,

Jonadab the Unsightly One <jon...@bright.net> wrote:
>jwe...@pacific.mps.ohio-state.edu (Jesse Welton) wrote:
>
>> That particular feature is a special use of what should be a general
>> feature, that objects' members can be arbitrary functions (methods).
>
>Exactly. Well, most of them can, anyway. [nibble]

There are exceptions in TADS, too, mostly being confined to the
vocabulary pseudoproperties (they don't really exist as such at
runtime), but also the contents member, which is overwritten by the
compiler.

>> Ideally, methods which require no parameters should be called
>> identically to the way direct data members are accessed.
>
>Inform doesn't do this DIRECTLY, but PrintOrRun() and ValueOrRun()
>are library-provided workarounds to allow you to do essentially
>just that, and they're VERY handy.

Sounds like it works, but it's not ideal, since you have to explicitly
put those function calls in. Besides the syntactical overhead, that
means you can't use a method where some bit of library code expects a
data member and hasn't been explicitly generalized. TADS handles this
at the language level, and it's one of the things that makes TADS a
winner, for me.

>> Here are some features I would like to have:
>>
>> * Flexible and powerful operations on collections, as in Smalltalk.
>> This allows the concise expression of operations to be performed on
>> all objects satisfying a given criterion. I don't want to have to
>> write C-style for loops everywhere.
>
>objectloops allow a certain amount of that, particularly with
>objectloop (i ofclass foo), but I can immagine some extensions
>such as, for example objectloop (i has light) or perhaps
>objectloop (i suchthat [generic condition]) even.
>That's syntax sugar, but it might be handy. Then again,
>it might encourage overuse, and it should be noted that
>both of the above would have to check the condition for
>every object in the game (unlike, say, objectloop (x in y),
>which doesn't have to do that, even if it's implemented
>the "safe" way).

You could avoid having to check every object in the game by defining a
recursiveContents method on containers that returns a collection of
their contents (and their contents' contents, and...). (You could
give it an argument, too, that would determine passibility at each
level, so only the visible/reachable/whatever contents are returned.)
This collection can the be operated on by general collection methods
for selection, iteration, and so on. To do something with all visible
light sources, you'd have something like this: (Smalltalk syntax on)

((player location recursiveContentsPassing: #visible)
select: [:each | each isLightSource])
do: [:each | "whatever you want to to with each lightsource"].

You can then use the exact same code to process all stinky objects
within smelling range, all angry bees that can see you, all the whiny
fusspots you can hear, etc.

>> * Programmatic formation of code tokens: [nibble]


>
>You completely lost me here.

I'm not very familiar with the Inform parser, but in TADS each verb
has several associated methods that are called on objects for
verification, processing, and so on. They form a family with a common
base, which is defined by the verb object, as in:

take: deepverb
doAction = 'Take'
;

This tells the compiler that the parser is to call (in the direct
object) the verification method verDoTake to determine if it is
logical/possible to take an object, and the method doTake to actually
carry out the action. I happen to like this system, and would like to
be able to expand on it with my own family of methods, to tidy up
certain aspects of it. To do that, I would really like to be able to
generate the symbols/method pointers I want to add automatically,
rather than having to enter each one manually for each verb.

Clearer?

-Jesse

BrenBarn

unread,
Sep 1, 1999, 3:00:00 AM9/1/99
to
>I'm not very familiar with the Inform parser, but in TADS each verb
>has several associated methods that are called on objects for
>verification, processing, and so on. They form a family with a common
>base, which is defined by the verb object, as in:
>
>take: deepverb
> doAction = 'Take'
>;
>
>This tells the compiler that the parser is to call (in the direct
>object) the verification method verDoTake to determine if it is
>logical/possible to take an object, and the method doTake to actually
>carry out the action. I happen to like this system, and would like to
>be able to expand on it with my own family of methods, to tidy up
>certain aspects of it.
Inform implements all this, except that: A) Both the "verDo" and the "Do"
may be functionally combined in one routine (called "before" in Inform). If
you want to ADD to the normal verb processes (rather than replace them), you
can put the "Do" in a different routine called "after"; B) All the "verDo" and
"Do" methods for a single object are defined as parts of a single routine
rather than as separate routines. (This doesn't seem, from my understanding,
to be functionally different.)

>To do that, I would really like to be able to
>generate the symbols/method pointers I want to add automatically,
>rather than having to enter each one manually for each verb.
>
>Clearer?
>

This I don't understand (although you did make the rest of it clearer).
What do you mean by "generate the symbols/method pointers I want to add
automatically"? (I fear I may not be very well versed in programming jargon.)

Jesse Welton

unread,
Sep 1, 1999, 3:00:00 AM9/1/99
to
In article <19990901110754...@ng-ff1.aol.com>,

BrenBarn <bren...@aol.comRemove> wrote:
>>I'm not very familiar with the Inform parser, but in TADS each verb
>>has several associated methods that are called on objects for
>>verification, processing, and so on. They form a family with a common
>>base, which is defined by the verb object, as in:
>>
>>take: deepverb
>> doAction = 'Take'
>>;
>>
>>This tells the compiler that the parser is to call (in the direct
>>object) the verification method verDoTake to determine if it is
>>logical/possible to take an object, and the method doTake to actually
>>carry out the action. I happen to like this system, and would like to
>>be able to expand on it with my own family of methods, to tidy up
>>certain aspects of it.
> Inform implements all this, except that: A) Both the "verDo" and the "Do"
>may be functionally combined in one routine (called "before" in Inform). If
>you want to ADD to the normal verb processes (rather than replace them), you
>can put the "Do" in a different routine called "after"; B) All the "verDo" and
>"Do" methods for a single object are defined as parts of a single routine
>rather than as separate routines. (This doesn't seem, from my understanding,
>to be functionally different.)

Hmm... It may not be functionally different, but I think there are
good reasons to separate it into separate methods with different
purposes. The "verDo" methods perform checks on things like whether
the object is in reach, whether the action is currently sensible (eg,
don't open an open door), etc, in part to aid disambiguation. The
"do" methods actually carry out the action if it gets past the checks.
If I want to change the default response to picking something up, I
don't want to have to include all the default checking code as well.
That should already be taken care of.

Correct me if I'm wrong, but doesn't Inform separate out some of that
functionality by using different parsing routines for held objects,
reachable objects, visible objects, etc? Or do I completely
misunderstand the parser templates I've seen here and there?

>>To do that, I would really like to be able to
>>generate the symbols/method pointers I want to add automatically,
>>rather than having to enter each one manually for each verb.
>>
>>Clearer?
>>
> This I don't understand (although you did make the rest of it clearer).
>What do you mean by "generate the symbols/method pointers I want to add
>automatically"? (I fear I may not be very well versed in programming jargon.)

I mean the compiler automatically generates "verDoTake" and "doTake"
from "Take", and I want to add my own parser-assistance methods, like
"prefDoTake" to determine if the object is a preferred object for the
verb (in this case, take). Presently, in TADS, what I would like to
do separately as object validation and preferred object selection is
rolled into one "verDo" method. The parser knows the "verDo" method
already, but to do what I want, I also need my program to know the
"prefDo" method associated with a given verb. I can give each verb a
prefDoMethod data member that holds the apropriate method pointer, but
then I have to define that member separately for each verb, which gets
tedious (especially since there's actually a family of these to create
for different situation). I'd rather have my program be able to
generate the method pointers on its own from the verb's method-name
root word, either at compile-time or run-time.

Now, this example is specific to a particular change I would like to
make to the parser, but such a facility could and should be more
general than that. Basically, what I want too be able to do is to
convert a string into something I can apply to an object like a
method.

Clear yet?

Here's another example: Consider a game-defined debugging command,
"call <method> in <object>". The verb action is to take the string
the parser receives for <method>, and use the facility I'm talking
about to look that string up in a symbol table, returning the
corresponding method pointer, then to apply the returned method to the
object specified in the command.

-Jesse

BrenBarn

unread,
Sep 1, 1999, 3:00:00 AM9/1/99
to
>Hmm... It may not be functionally different, but I think there are
>good reasons to separate it into separate methods with different
>purposes. The "verDo" methods perform checks on things like whether
>the object is in reach, whether the action is currently sensible (eg,
>don't open an open door), etc, in part to aid disambiguation. The
>"do" methods actually carry out the action if it gets past the checks.
>If I want to change the default response to picking something up, I
>don't want to have to include all the default checking code as well.
>That should already be taken care of.
In Inform, the details of whether an object is in reach (and other
virtually universal considerations) are handled automatically by the parser
itself. If you want to add to or detract from these restrictions, you can do
so with your own code.

>Correct me if I'm wrong, but doesn't Inform separate out some of that
>functionality by using different parsing routines for held objects,
>reachable objects, visible objects, etc? Or do I completely
>misunderstand the parser templates I've seen here and there?

Here I'm getting in over my head. I do know that Inform uses different
processes to determine whether an object is visible than it does to determine
whether the object is reachable (physically). For example, an apple in a
closed glass box is visible but not reachable. As far as held objects go, any
object held by the player is always reachable. (But if you are holding a
closed box with an apple inside, the apple will not be reachable until you open
the box.)

I'm beginning to understand (I think). From my (limited) understanding of
TADS, the "verDo" is not automatically CREATED, it's just automatically used if
it IS created. (In other words, all objects that don't define a "verDo" will
use the default one, and all objects that do define a "verDo" will use that
one, overriding the default.) I'm not exactly sure about object preferences.
In Inform, as I mentioned earlier, the basic details are handled "behind
the scenes". Object preference (i.e., making the verb "eat" prefer an edible
object over an inedible one as a direct object, which I assume is what you
mean) is done with the verb grammar (which is, I believe, a construct which
does not exist in TADS in any similar form). In short, the verb decides which
objects it prefers, rather than the objects deciding which verb(s) prefer(s)
them. (The latter is what you seem to be suggesting with your "prefDoTake"
idea.)
I personally prefer that the verb decide which objects it prefers, rather
than the reverse. For example, rather than having all edible objects define
themselves as "preferred" by the "eat" action, the "eat" action itself simply
defines a preference for edible objects. I am not, however, entirely pleased
with the WAY Inform achieves this goal; I believe that the "preference" should
be given in levels, right on down to the point where the simple command "Eat"
will automatically choose an appropriate object.
As far as the "call <method> in <object>" idea, Inform's built-in
debugging suite (called Infix) provides such a function. You can type ";
apple.DoADance()" while running the game, and the DoADance method of the apple
will be executed.

wo...@one.net

unread,
Sep 2, 1999, 3:00:00 AM9/2/99
to

Hi Paul,

>A re-entrant parser would make it much easier to code autonomous NPCs. An
>NPC's daemon routine could contain a line of code such as:
>
> self.parse("take everything from the table except except the mcguffin
>then go north");
>
>instead of having to build lists of objects and call action routines
>directly (not trivial for the above example). It would also enable NPCs to
>give orders to other NPCs eg:

This is a really neat trick! I never even thought about it, but it
wouldn't be hard... :)

Jesse Welton

unread,
Sep 2, 1999, 3:00:00 AM9/2/99
to
In article <19990901182442...@ng-fy1.aol.com>,

BrenBarn <bren...@aol.comRemove> wrote:
> In Inform, the details of whether an object is in reach (and other
>virtually universal considerations) are handled automatically by the parser
>itself. If you want to add to or detract from these restrictions, you can do
>so with your own code.

I don't think this is the right way to do things, because as you said,
such considerations are *virtually* universal. Exceptions run rampant
in IF, and it's much easier to deal with them if the exceptional
behavior goes into the exceptional objects themselves than making a
special case in the code that handles the general case. Or so I find.

> I'm beginning to understand (I think). From my (limited)
>understanding of TADS, the "verDo" is not automatically CREATED, it's
>just automatically used if it IS created. (In other words, all
>objects that don't define a "verDo" will use the default one, and all
>objects that do define a "verDo" will use that one, overriding the
>default.) I'm not exactly sure about object preferences.

Right, you still have to create the apropriate handler methods in the
objects, but you don't have to tediously tell the compiler what their
names are, because it automatically generates their names. I'd like
to be able to generate my own names in the same way.

> In Inform, [...] the verb decides which


>objects it prefers, rather than the objects deciding which verb(s) prefer(s)
>them. (The latter is what you seem to be suggesting with your "prefDoTake"
>idea.)

Exactly right.

> I personally prefer that the verb decide which objects it prefers, rather

>than the reverse. [Example, "eat".]

I think perhaps "push" would be a better example. Certainly there are
various classes of objects which the library will know should be
preferred, like buttons and levers. But whereas I'm unlikely to think
of any new classes of objects preferred for eating, it's not hard to
come up with new defaults for pushing. One might have a puzzle
involving pushing alphabet blocks around, pushing on various colored
bricks in a given wall, or pushing midgets out of the way. When I add
these things, I don't want to fuss with the parser code when I could
simply give that class of objects a property "prefPush = &preferred".

> As far as the "call <method> in <object>" idea, Inform's built-in
>debugging suite (called Infix) provides such a function. You can type ";
>apple.DoADance()" while running the game, and the DoADance method of the apple
>will be executed.

I feel like we're getting farther and farther off the point here.
That was just another example I came up with to illustrate possible
uses of a general feature. The fact that Inform handles these
particular things in different ways isn't entirely relevant to the
point. If the language or library provides a heap of features to
handle particular cases, but doesn't provide a way for me to add my
own, I'll eventually want to do something it doesn't have a special
case for, or want to do it differently. What I'm saying is that I'd
like language features which allow me to add my own functionality, at
a similar abstraction level to what the system provides by default, in
this case the ability to programmatically generate references to
methods whose names I can construct.

-Jesse

Andrew Plotkin

unread,
Sep 2, 1999, 3:00:00 AM9/2/99
to
wo...@one.net wrote:
>
>>A re-entrant parser would make it much easier to code autonomous NPCs. An
>>NPC's daemon routine could contain a line of code such as:
>>
>> self.parse("take everything from the table except except the mcguffin
>>then go north");
>>
>>instead of having to build lists of objects and call action routines
>>directly (not trivial for the above example). It would also enable NPCs to
>>give orders to other NPCs eg:
>
> This is a really neat trick! I never even thought about it, but it
> wouldn't be hard... :)

It's also subject to the most astonishingly intractable bugs. I'd avoid it
like hot death.

Invent a new literal format if you like:
<<Take Except(AllFrom(table), macguffin); Go n_obj>>;

One of the things I like about SML (and I'm told Haskell is similar) is
that it's very easy to create data structures in place like this.

But leave the natural-language parsing for beings that can correct their
errors.

--Z

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

Mike Roberts

unread,
Sep 2, 1999, 3:00:00 AM9/2/99
to
Paul Alexander Mikell wrote in message
<37CC4457...@pmikell.freeserve.co.uk>...

>A re-entrant parser would make it much easier to code autonomous NPCs. An
>NPC's daemon routine could contain a line of code such as:
>
> self.parse("take everything from the table except except the mcguffin
>then go north");
>
>instead of having to build lists of objects and call action routines
>directly (not trivial for the above example).

It would be hard for the program to answer questions about the command
("which mcguffin do you mean..."), though. That's an advantage of referring
directly to objects by reference rather than by player-visible name.

--Mike


Jonadab the Unsightly One

unread,
Sep 2, 1999, 3:00:00 AM9/2/99
to
jwe...@pacific.mps.ohio-state.edu (Jesse Welton) wrote:

> >>take: deepverb
> >> doAction = 'Take'
> >>;

> > Inform implements all this, except that: A) Both the "verDo" and the "Do"
> >may be functionally combined in one routine (called "before" in Inform). If
> >you want to ADD to the normal verb processes (rather than replace them), you
> >can put the "Do" in a different routine called "after"; B) All the "verDo" and
> >"Do" methods for a single object are defined as parts of a single routine
> >rather than as separate routines. (This doesn't seem, from my understanding,
> >to be functionally different.)
>

> Hmm... It may not be functionally different, but I think there are
> good reasons to separate it into separate methods with different
> purposes. The "verDo" methods perform checks on things like whether
> the object is in reach, whether the action is currently sensible (eg,
> don't open an open door), etc, in part to aid disambiguation. The
> "do" methods actually carry out the action if it gets past the checks.

Ah. I see. What you want is to have a before routine, an
override routine, and an after routine. That could easily
be implemented with very minor changes to the Inform library
(I think one property would have to be declared and one line
added to one routine). These changes could be made in
the game file (using the Replace directive) if you don't like
editing your library files.

> If I want to change the default response to picking something up, I
> don't want to have to include all the default checking code as well.
> That should already be taken care of.

Now I'm thoroughly lost. What default checking code? The parser?
No, you wouldn't have to replace the parser to change the default
response. (Actually, if all you want to do is change the printed
message you can do that with the after routine.)

> Correct me if I'm wrong, but doesn't Inform separate out some of that
> functionality by using different parsing routines for held objects,
> reachable objects, visible objects, etc?

No, now you're completely losing me.

> I mean the compiler automatically generates "verDoTake" and "doTake"
> from "Take", and I want to add my own parser-assistance methods, like
> "prefDoTake" to determine if the object is a preferred object for the
> verb (in this case, take).

Ah. Now we're dealing with disambiguation, which is another
matter entirely. ChooseObjects could be made to call a
routine residing in a particular property of the object in
question to determine how to weight it. I think that's the
sort of thing you're after here.

> Presently, in TADS, what I would like to
> do separately as object validation and preferred object selection is
> rolled into one "verDo" method. The parser knows the "verDo" method
> already, but to do what I want, I also need my program to know the
> "prefDo" method associated with a given verb.

This is where the beauty of Inform's system comes out. The Take
action already has a constant (##Take), and you can switch on
that in any property routine. So you could declare a property
and use it for exactly this. All you then have to do is cause
it to be called from the appropriate point in the library.
(Naturally, you only call it for any given object if the object
provides it; otherwise you have default behavior.)

> Here's another example: Consider a game-defined debugging command,
> "call <method> in <object>". The verb action is to take the string
> the parser receives for <method>, and use the facility I'm talking
> about to look that string up in a symbol table, returning the
> corresponding method pointer, then to apply the returned method to the
> object specified in the command.

I could code that in Inform, but the library already provides it.

Jonadab the Unsightly One

unread,
Sep 2, 1999, 3:00:00 AM9/2/99
to
jwe...@pacific.mps.ohio-state.edu (Jesse Welton) wrote:

> > In Inform, [...] the verb decides which
> >objects it prefers, rather than the objects deciding which verb(s) prefer(s)
> >them. (The latter is what you seem to be suggesting with your "prefDoTake"
> >idea.)
>
> Exactly right.
>
> > I personally prefer that the verb decide which objects it prefers, rather
> >than the reverse. [Example, "eat".]
>
> I think perhaps "push" would be a better example. Certainly there are
> various classes of objects which the library will know should be
> preferred, like buttons and levers. But whereas I'm unlikely to think
> of any new classes of objects preferred for eating, it's not hard to
> come up with new defaults for pushing. One might have a puzzle
> involving pushing alphabet blocks around, pushing on various colored
> bricks in a given wall, or pushing midgets out of the way. When I add
> these things, I don't want to fuss with the parser code when I could
> simply give that class of objects a property "prefPush = &preferred".

Ah. Yes, definitely what you want could be done in Inform by having
ChooseObjects check the object for a VerbPreferences property (or
whatever you'd like to call it), and then you can have something
like this:

class AlphabetBlock
with VerbPreferences [ switch (action)
{ ##Push: return 50;
default: rfalse;
} ],
! insert other stuff here
name 'block' 'alphabet',
list_together "alphabet blocks";

> > As far as the "call <method> in <object>" idea, Inform's built-in
> >debugging suite (called Infix) provides such a function. You can type ";
> >apple.DoADance()" while running the game, and the DoADance method of the apple
> >will be executed.
>
> I feel like we're getting farther and farther off the point here.
> That was just another example I came up with to illustrate possible
> uses of a general feature.

And the fact that it has been coded in Inform (and in fact would
not be difficult to code; I could have done it) indicates that
the feature is provided, or an equivalent feature.

> The fact that Inform handles these
> particular things in different ways isn't entirely relevant to the
> point. If the language or library provides a heap of features to
> handle particular cases, but doesn't provide a way for me to add my
> own, I'll eventually want to do something it doesn't have a special
> case for, or want to do it differently.

Absolutely. That's why you're allowed to replace library functions.

> What I'm saying is that I'd
> like language features which allow me to add my own functionality, at
> a similar abstraction level to what the system provides by default, in
> this case the ability to programmatically generate references to
> methods whose names I can construct.

Sounds to me like you want to be able to edit the library,
or at least replace parser functions. Can't you do that in
TADS? I thought this functionality had been added? (I
admit I'm not very "current" with TADS...)

Jonadab the Unsightly One

unread,
Sep 2, 1999, 3:00:00 AM9/2/99
to
jwe...@pacific.mps.ohio-state.edu (Jesse Welton) wrote:

> >> Automatic scanning of the text an object produces to determine
> >> whether it matches what the player typed. To be really
> >> effective this should work even on text produced by one
> >> of the object's routines.
> >
> >This is an exercise in the manual. It isn't as tricky as it
> >looks! -- Though it is still a bit tricky.
>
> Perhaps I'm missing the point, but is this something one would
> actually want to do? It seems like it would be an invitation for
> parsing bugs. If the player is wandering through the desert, and a
> location's description runs, "There is sand all around you for miles,
> your throat is getting seriously parched, and your skin is starting to
> burn in the sun," I definitely wouldn't want 'sand', 'throat', or
> 'skin' to refer to that location object. "X skin" repeats all that
> about the sand and your throat? I should hope not!
>
> Or do I misunderstand how this is supposed to work?

Actually, for location objects it would say, "That's not something
you need to refer to in the course of this game." (Or "That's just
scenery", or whatever you make that library message say.) But of
course it wouldn't do this if the text could also be matched by
another object.

Jonadab the Unsightly One

unread,
Sep 2, 1999, 3:00:00 AM9/2/99
to
jwe...@pacific.mps.ohio-state.edu (Jesse Welton) wrote:

> >> That particular feature is a special use of what should be a general
> >> feature, that objects' members can be arbitrary functions (methods).
> >
> >Exactly. Well, most of them can, anyway. [nibble]
>
> There are exceptions in TADS, too, mostly being confined to the
> vocabulary pseudoproperties (they don't really exist as such at
> runtime), but also the contents member, which is overwritten by the
> compiler.

Right. If you allowed functions to determine the object tree
you'd have all manner of nasty side-effects. Such kludges as
found_in have wicked enough side-effects, without allowing
child and sibling calls to be intercepted by an object's routine.
That way lies madness. If you want to change the object tree,
it's much safer to just move the objects.

> >> Ideally, methods which require no parameters should be called
> >> identically to the way direct data members are accessed.
> >
> >Inform doesn't do this DIRECTLY, but PrintOrRun() and ValueOrRun()
> >are library-provided workarounds to allow you to do essentially
> >just that, and they're VERY handy.
>
> Sounds like it works, but it's not ideal, since you have to explicitly
> put those function calls in. Besides the syntactical overhead, that
> means you can't use a method where some bit of library code expects a
> data member and hasn't been explicitly generalized.

In anything like a recent version of the library, they've pretty
much all been generalised, except the ones I noted (like name
and parse_name). User-added routines (such as FooSub) have to
be coded this way, but it's generally not a problem.

> >> Here are some features I would like to have:
> >>
> >> * Flexible and powerful operations on collections, as in Smalltalk.
> >> This allows the concise expression of operations to be performed on
> >> all objects satisfying a given criterion. I don't want to have to
> >> write C-style for loops everywhere.
> >
> >objectloops allow a certain amount of that, particularly with
> >objectloop (i ofclass foo), but I can immagine some extensions
> >such as, for example objectloop (i has light) or perhaps
> >objectloop (i suchthat [generic condition]) even.
> >That's syntax sugar, but it might be handy. Then again,
> >it might encourage overuse, and it should be noted that
> >both of the above would have to check the condition for
> >every object in the game (unlike, say, objectloop (x in y),
> >which doesn't have to do that, even if it's implemented
> >the "safe" way).
>
> You could avoid having to check every object in the game by defining a
> recursiveContents method on containers that returns a collection of
> their contents (and their contents' contents, and...).

That only solves the issue for the objectloop (x in y) and
objectloop (x near y) cases, which already are optimised,
if I am not mistaken. I don't know whether
objectloop (x ofclass Foo) is optimised or not; it theoretically
could be. But a case like objectloop (x has light) is not
optimiseable. There is no recourse but to check every object
in the game.

> You can then use the exact same code to process all stinky objects
> within smelling range, all angry bees that can see you, all the whiny
> fusspots you can hear, etc.

Right, but it will NOT process all stinky objects in the game,
all angry bees in the game, or all whiny fusspots in the game.
For that you have to check every object in the game, not just
every object in scope.

> >> * Programmatic formation of code tokens: [nibble]
> >
> >You completely lost me here.
>

> I'm not very familiar with the Inform parser, but in TADS each verb
> has several associated methods that are called on objects for
> verification, processing, and so on. They form a family with a common
> base, which is defined by the verb object, as in:
>

> take: deepverb
> doAction = 'Take'
> ;
>

> This tells the compiler that the parser is to call (in the direct
> object) the verification method verDoTake to determine if it is
> logical/possible to take an object, and the method doTake to actually
> carry out the action.

Oh. Grammar. Inform does exactly the same thing in a completely
different way:

Verb "take" * noun -> Take;

Tells the library that the action should be set to ##Take when
the preroutines are called and that if the preroutines
don't return true the routine TakeSub should be called.

Grammar, I might add, is Inform's big strength. Past
threads have concluded, if I am not mistaken, that it's
if anything more flexible than the system TADS uses.

> I happen to like this system, and would like to
> be able to expand on it with my own family of methods, to tidy up

> certain aspects of it. To do that, I would really like to be able to


> generate the symbols/method pointers I want to add automatically,
> rather than having to enter each one manually for each verb.
>
> Clearer?

Oh, yes, and in Inform you could do exactly that by declaring
a property and replacing the library routine that calls
the various preroutines, adding a call to your new property
if the object provides it. If I understand you correctly.

Jim Aikin

unread,
Sep 2, 1999, 3:00:00 AM9/2/99
to
Paul Alexander Mikell wrote:

> A re-entrant parser would make it much easier to code autonomous NPCs. An
> NPC's daemon routine could contain a line of code such as:
>
> self.parse("take everything from the table except except the mcguffin
> then go north");
>
> instead of having to build lists of objects and call action routines
> directly (not trivial for the above example).

Brilliant idea. Absolutely!

--Jim Aikin

Jim Aikin

unread,
Sep 2, 1999, 3:00:00 AM9/2/99
to
Albert wrote:
>
> I'm in the process of creating my own IF engine, coded in C++ and
> OOD. Right now I'm reworking the parser (but before I do that I have
> to make my own custom stream class, but I expect to finish that by
> the end of this week), but I'd like to know any unique features you'd
> like to see that aren't easily done in either TADS, Inform, or any
> other popular IF engine. I've heard someone mention the ability to
> call a function to determine which room an exit leads to, but I couldn't
> think of anywhere else this could be applied.

1. I'd like very much to be able to send pointers as arguments to
functions rather than having to pass by value. This makes it possible to
alter two or three variables in the calling function without having to
use global variables to shuffle the data around.

2. At least 2-dimensional arrays, please. 3D would be better. Including
arrays of objects (like those little transparent "rooms" in the 3D
plastic cube maze, for instance).

3. Larger integers would be useful once in a while.

4. Built-in string variable operations for assembling output strings on
the fly:

if (a) str = "flying saucer";
else str = "Good Ship Lollipop";
print "You're aboard the ", str, ".";

--Jim Aikin

BrenBarn

unread,
Sep 3, 1999, 3:00:00 AM9/3/99
to
>objectloops allow a certain amount of that, particularly with >objectloop (i
ofclass foo), but I can immagine some extensions such >as, for example
objectloop (i has light) or perhaps objectloop (i >suchthat [generic
condition]) even.
Can't you aleady do this in Inform? The IDM says you can put any
condition in the obectloop parentheses, as long as it begins with a variable.
(I have, however, heard rumors that there are problems with this. Are there?)

BrenBarn

unread,
Sep 3, 1999, 3:00:00 AM9/3/99
to
>> In Inform, the details of whether an object is in reach (and other
>>virtually universal considerations) are handled automatically by the parser
>>itself. If you want to add to or detract from these restrictions, you can
>do
>>so with your own code.
>
>I don't think this is the right way to do things, because as you said,
>such considerations are *virtually* universal. Exceptions run rampant
>in IF, and it's much easier to deal with them if the exceptional
>behavior goes into the exceptional objects themselves than making a
>special case in the code that handles the general case. Or so I find.
True. Since, as you stated later in your message, discussions of the
relative merits of Inform/TADS/Hugo/etc. are not really relevant, I'll simply
agree with you. However, I do think that these "virtually universal" chores
should take place behind the scenes; what is needed is a way to override any
little part of that process, which means breaking down the "behind the scenes"
code into tiny bits.

>> I'm beginning to understand (I think). From my (limited)
>>understanding of TADS, the "verDo" is not automatically CREATED, it's
>>just automatically used if it IS created. (In other words, all
>>objects that don't define a "verDo" will use the default one, and all
>>objects that do define a "verDo" will use that one, overriding the
>>default.) I'm not exactly sure about object preferences.
>
>Right, you still have to create the apropriate handler methods in the
>objects, but you don't have to tediously tell the compiler what their
>names are, because it automatically generates their names. I'd like
>to be able to generate my own names in the same way.

I understand and yet I do not understand. Don't you have reference the
routine's name in each object anyway? Otherwise, how would the compiler know
what routine you're referring to? Or do you mean that you don't have to
explicity define a "verDoTake" in the verb definition?

>> I personally prefer that the verb decide which objects it prefers,
>rather
>>than the reverse. [Example, "eat".]
>
>I think perhaps "push" would be a better example. Certainly there are
>various classes of objects which the library will know should be
>preferred, like buttons and levers. But whereas I'm unlikely to think
>of any new classes of objects preferred for eating, it's not hard to
>come up with new defaults for pushing. One might have a puzzle
>involving pushing alphabet blocks around, pushing on various colored
>bricks in a given wall, or pushing midgets out of the way. When I add
>these things, I don't want to fuss with the parser code when I could
>simply give that class of objects a property "prefPush = &preferred".

I agree. In fact, I think it would be great if the preference could be
defined in EITHER the verb OR the object. So a programmer could use your
"prefPush=&preferred"-inside-the-object idea, and/or a
"prefer=AlphabetBlock"-inside-the-verb idea.

TenthStone

unread,
Sep 3, 1999, 3:00:00 AM9/3/99
to
On Thu, 02 Sep 1999 20:43:20 GMT, jon...@bright.net (Jonadab the
Unsightly One) wrote:

>jwe...@pacific.mps.ohio-state.edu (Jesse Welton) wrote:
>> What I'm saying is that I'd
>> like language features which allow me to add my own functionality, at
>> a similar abstraction level to what the system provides by default, in
>> this case the ability to programmatically generate references to
>> methods whose names I can construct.
>
>Sounds to me like you want to be able to edit the library,
>or at least replace parser functions. Can't you do that in
>TADS? I thought this functionality had been added? (I
>admit I'm not very "current" with TADS...)

In TADS -- as in Inform, I should think -- property names are
meaningless as strings. That is, you can't take a property
name like &matrix1 and edit it to get the property name &matrix1_1.

There are two special cases in TADS. To define a verb routine,
you put a statement like
doAction = 'Take'
in the verb declaration. TADS automatically generates the two
properties &doTake and &verDoTake from this declaration. I believe
what Jesse wants is some general way to take a string and derive
property names from it, which would probably be a pain in the ass to
implement.

(Incidentally, regarding someone's previous statement, there are no
"default" verb handlings in TADS except for some very primitive verb
disambiguation routines inherited from the verb class. If the
&verDoX routine is missing from an object completely, there _is_ an
automatic response along the lines of "You can't do that.", but
nothing will happen if &verDoX is present and &doX is absent.)

Getting back to the matter at hand, the reason why this would be
a pain is that TADS currently doesn't store property names in the
gamefile at all unless it's begin compiled for debugging. They're
simply numbered (and the numbers are inaccessible).

So to implement dynamic property creation, you'd first have to store
property names. Fine, there's already a procedure for doing in this
when compiling for debugging. Beyond that, you'd need two functions:
one to check whether a string is valid as a property
one to retrieve a property name from a string (dynamically
creating it if it doesn't exist)

It wouldn't be impossible to implement, just fairly difficult and very
bug-prone. The advantages, though, are appreciable -- e.g. matrices.

----------------
The Imperturbable TenthStone
mcc...@erols.com tenth...@hotmail.com mcc...@gsgis.k12.va.us

Jonadab the Unsightly One

unread,
Sep 3, 1999, 3:00:00 AM9/3/99
to
bren...@aol.comRemove (BrenBarn) wrote:

> Can't you aleady do this in Inform? The IDM says you can put any
> condition in the obectloop parentheses, as long as it begins with a variable.
> (I have, however, heard rumors that there are problems with this. Are there?)

Apologies; I haven't reviewed the objectloop section of the DM
since Inform 6 came out. I know about the ofclass cases and
such from discussions here.

The "problems with this" probably stem from it taking a long
time, or else from certain optimised cases (like (x in y))
going wrong when you cut off a branch you're standing on.

Andrew Plotkin

unread,
Sep 3, 1999, 3:00:00 AM9/3/99
to
BrenBarn <bren...@aol.comremove> wrote:
>>objectloops allow a certain amount of that, particularly with objectloop (i
>> ofclass foo), but I can immagine some extensions such as, for example
>> objectloop (i has light) or perhaps objectloop (i suchthat [generic
>> condition]) even.

> Can't you aleady do this in Inform?

Yes.

> (I have, however, heard rumors that there are problems with this. Are
> there?)

No. There are issues to be aware of if you've got a "move" or "remove"
statement inside the loop, but only if it's an "(x in y)" condition.

BrenBarn

unread,
Sep 3, 1999, 3:00:00 AM9/3/99
to
>3. Larger integers would be useful once in a while.
And floating point numbers would be nice, especially if you intend to use
the engine for anything other than IF.

BrenBarn

unread,
Sep 3, 1999, 3:00:00 AM9/3/99
to
>In TADS -- as in Inform, I should think -- property names are
>meaningless as strings. That is, you can't take a property
>name like &matrix1 and edit it to get the property name &matrix1_1.
>
>There are two special cases in TADS. To define a verb routine,
>you put a statement like
> doAction = 'Take'
>in the verb declaration. TADS automatically generates the two
>properties &doTake and &verDoTake from this declaration. I believe
>what Jesse wants is some general way to take a string and derive
>property names from it, which would probably be a pain in the ass to
>implement.
NOW I get it. And I agree, that sounds like a major implementing
nightmare. If you want to be able to have code like:
A="pref"
B="verDo"
C="Do"
CreateProperty(A+"Take")
CreateProperty(B+"Take")
CreateProperty(C+"Take")
And create properties like that, you're making a major bridge from the
game's ongoing run-time operations to the static data of the game.
But I agree that this would be a boon. The ability to alter the run-time
game state just as fundamentally as you alter it in compilation (i.e., creating
objects and properties) would open up new possiblities in programming IF.

Andrew Plotkin

unread,
Sep 3, 1999, 3:00:00 AM9/3/99
to
BrenBarn <bren...@aol.comremove> wrote:
>>I believe
>>what Jesse wants is some general way to take a string and derive
>>property names from it, which would probably be a pain in the ass to
>>implement.
>
> NOW I get it. And I agree, that sounds like a major implementing
> nightmare.

The way to handle this, if you really want it, is to store properties as
hashtables keyed by string. Java has this; Perl has it (under the name
"associative arrays"); C++ has it in the standard template library.

Nothing wrong with that approach.

J R Partington

unread,
Sep 3, 1999, 3:00:00 AM9/3/99
to
In article <19990903101613...@ng-cr1.aol.com> bren...@aol.comRemove (BrenBarn) writes:

>
>"Do not follow where the path may lead;
>go, instead, where there is no path, and leave a trail."
> --Author Unknown

These people think it's by Thoreau:
http://www.soaringeagleltd.com/businessruletypes.htm

Jonathan Partington

---

In "Teenage Leather Philosopher of Doom," you escape the manticore by
climbing down the rope but don't forget to bury the grave stone.

Jesse Welton

unread,
Sep 3, 1999, 3:00:00 AM9/3/99
to
Sorry about the monolithic response, but that the way it goes, this
time. Newsgroups trimmed.


In article <37cece0a...@news.bright.net>,


Jonadab the Unsightly One <jon...@bright.net> wrote:

>jwe...@pacific.mps.ohio-state.edu (Jesse Welton) wrote:
>
>> >> That particular feature is a special use of what should be a general
>> >> feature, that objects' members can be arbitrary functions (methods).
>> >
>> >Exactly. Well, most of them can, anyway. [nibble]
>>
>> There are exceptions in TADS, too, mostly being confined to the
>> vocabulary pseudoproperties (they don't really exist as such at
>> runtime), but also the contents member, which is overwritten by the
>> compiler.
>
>Right. If you allowed functions to determine the object tree
>you'd have all manner of nasty side-effects. Such kludges as
>found_in have wicked enough side-effects, without allowing
>child and sibling calls to be intercepted by an object's routine.
>That way lies madness. If you want to change the object tree,
>it's much safer to just move the objects.

Not necessarily. One reasonable use for overriding the contents
property with a method would be to redirect contents requests to
topContents, insideContents, or what have you. Why would you want to
do this? So that you could use separate lists for the objects on top
of a box and in it. Then you can have non-conflicting surface and
container classes. To get a combined container and surface, simply
derive from both classes. But to make such a library enhancement as
backwards-compatible as possible, you want old code which references
the plain contents of objects which are either surfaces or containers
(but not both) to redirect "contents" as appropriate automatically.

Used responsibly, there's no problem with it at all. A quite similar
use is the location method of TADS "floating objects", which track the
player. The feature in general (optionally using methods for
arbitrary properties) is useful in all manner of places.

(Note to TADS implementors: I'd appreciate at least an optional switch
to turn off overwriting of the contents property. This would preserve
backwards compatibility while allowing library authors greater freedom
of expression.)

>> >> * Flexible and powerful operations on collections, as in Smalltalk.
>> >

>> >objectloops allow a certain amount of that, [...]


>>
>> You could avoid having to check every object in the game by defining a
>> recursiveContents method on containers that returns a collection of
>> their contents (and their contents' contents, and...).
>
>That only solves the issue for the objectloop (x in y) and
>objectloop (x near y) cases, which already are optimised,
>if I am not mistaken. I don't know whether
>objectloop (x ofclass Foo) is optimised or not; it theoretically
>could be. But a case like objectloop (x has light) is not
>optimiseable. There is no recourse but to check every object
>in the game.

Uh, yeah. I think you miss my point. Much of the time, you actually
don't want to check every object in the game, you want to handle every
object in some scope satisfying some conditions. So, you define a
method to return every object in whatever scope you're interested in,
and you define an independent set of collection operations that allow
you to filter that list, perform operations on it, and so on. Then,
the author can use these in arbitrary combinations to achieve the
result desired in a particular situation.

I could be wrong, of course, but here are some things I would guess
objectloop doesn't handle nicely: Chaching the collection of objects
satisfying some (static) condition, to be operated on as a groups at
various times in the future. Collecting a list of objects to be
passed to a function. Transforming a list of objects into a list of
corresponding derived values (such as a list of their locations), to
be used in similar ways. Selecting some subset (according to
arbitrary filtering criteria) of a list, to be used in the same ways.
Sorting a list according to arbitrary criteria (so, for example,
daemons can be run in priority order). And, of course, operating on
collections non-object values.

>> You can then use the exact same code to process all stinky objects
>> within smelling range, all angry bees that can see you, all the whiny
>> fusspots you can hear, etc.
>
>Right, but it will NOT process all stinky objects in the game,
>all angry bees in the game, or all whiny fusspots in the game.
>For that you have to check every object in the game, not just
>every object in scope.

Of course. I was outlining a flexible way to process only those
objects which are in the relevant scope.

>> >> * Programmatic formation of code tokens: [nibble]
>> >
>> >You completely lost me here.
>>
>> I'm not very familiar with the Inform parser, but in TADS each verb
>> has several associated methods that are called on objects for
>> verification, processing, and so on. They form a family with a common
>> base, which is defined by the verb object, as in:
>>
>> take: deepverb
>> doAction = 'Take'
>> ;
>>
>> This tells the compiler that the parser is to call (in the direct
>> object) the verification method verDoTake to determine if it is
>> logical/possible to take an object, and the method doTake to actually
>> carry out the action.
>
>Oh. Grammar. Inform does exactly the same thing in a completely
>different way:
>
>Verb "take" * noun -> Take;
>
>Tells the library that the action should be set to ##Take when
>the preroutines are called and that if the preroutines
>don't return true the routine TakeSub should be called.
>
>Grammar, I might add, is Inform's big strength. Past
>threads have concluded, if I am not mistaken, that it's
>if anything more flexible than the system TADS uses.

Yes, it's more flexible than TADS's current parser. Mike Roberts is
seeing to that in TADS 3.

But actually, I'm not talking about grammar. "Take the wall" is
grammatically correct, and means exactly what it sounds like it means.
However, the wall is an illogical thing to take, which should be
reflected in the disambiguation process. For example, if there's a
green wall and a green block, and the player type "take green", the
green wall should be thrown out of consideration.

Now, Inform does at least some of this in the parsing process itself,
as reflected in the pattern

"drop" * held

which distinguishes held objects from unheld objects. I personally
don't think this should be part of the parsing, but that's not
entirely relevant. What is relevant is that operationally, this means
the preference selection is wrapped up in a single routine associated
with the verb. I'm trying to expand on a system which instead
delegates this responsibility to the objects, not in a single routine
for each object but in a separate routine for each verb/object pair.
More on this later.

>Oh, yes, and in Inform you could do exactly that by declaring
>a property and replacing the library routine that calls
>the various preroutines, adding a call to your new property
>if the object provides it. If I understand you correctly.

So far, so good. Obviously, I can define properties in each verb to
tell it which methods to call in the objects. What I want to do is
automate this so that the verbs can figure out for themselves what
properties to call, given that each verb already knows the equivalent
of ##Take.

In article <37ced8ad...@news.bright.net>,


Jonadab the Unsightly One <jon...@bright.net> wrote:
>jwe...@pacific.mps.ohio-state.edu (Jesse Welton) wrote:
>

>> Hmm... It may not be functionally different, but I think there are
>> good reasons to separate it into separate methods with different
>> purposes. The "verDo" methods perform checks on things like whether
>> the object is in reach, whether the action is currently sensible (eg,
>> don't open an open door), etc, in part to aid disambiguation. The
>> "do" methods actually carry out the action if it gets past the checks.
>
>Ah. I see. What you want is to have a before routine, an
>override routine, and an after routine. That could easily
>be implemented with very minor changes to the Inform library
>(I think one property would have to be declared and one line
>added to one routine).

Since I'm unfamiliar with the use of Inform's before, override, and
after routines, this suggestion means little to me. It sounds,
however, as though you're suggesting that for each special kind of
object, I have to add special considerations to a single monolithic
function (or rather, the appropriate one of a few such functions).

> These changes could be made in
>the game file (using the Replace directive) if you don't like
>editing your library files.

I actually don't mind editing my library files at all. I'm doing so
extensively. I just want to keep library code in the library, and
game-domain code in the game. I don't want to have to make changes to
library functions to accommodate objects which are peculiar to a
particular game.

>> If I want to change the default response to picking something up, I
>> don't want to have to include all the default checking code as well.
>> That should already be taken care of.
>
>Now I'm thoroughly lost. What default checking code? The parser?

Apparently, in Inform, this code is in the parser.

>No, you wouldn't have to replace the parser to change the default
>response. (Actually, if all you want to do is change the printed
>message you can do that with the after routine.)

So I still have to put the special considerations for all my special
objects into a single function, right? The whole point of what I want
to do is to break it up into atomic pieces.

>> Correct me if I'm wrong, but doesn't Inform separate out some of that
>> functionality by using different parsing routines for held objects,
>> reachable objects, visible objects, etc?
>
>No, now you're completely losing me.

Consider

"drop" * held

as opposed to

"drop" * noun

How does Inform handle these different patterns?

>> I mean the compiler automatically generates "verDoTake" and "doTake"
>> from "Take", and I want to add my own parser-assistance methods, like
>> "prefDoTake" to determine if the object is a preferred object for the
>> verb (in this case, take).
>
>Ah. Now we're dealing with disambiguation, which is another
>matter entirely. ChooseObjects could be made to call a
>routine residing in a particular property of the object in
>question to determine how to weight it. I think that's the
>sort of thing you're after here.

Actually, it's not another matter entirely. If I'm holding a sock,
and there's another sock on the floor, and I type "drop sock", the
parser figures I must be talking about the one I'm holding. That's
disambiguation. But yes, that's the sort of thing I'm after. Now, I
don't know how ChooseObjects is used, but basically what I want to be
able to do is have it take some equivalent of ##Take and figure out
that the property I want to call is ##PrefTake. If instead of ##Take
it got ##Drop, it should call ##PrefDrop, and so on. And I want to
use a function that can make this transformation general, so I don't
have to put in two hundred different switch statements.

>> Here's another example: Consider a game-defined debugging command,
>> "call <method> in <object>". The verb action is to take the string
>> the parser receives for <method>, and use the facility I'm talking
>> about to look that string up in a symbol table, returning the
>> corresponding method pointer, then to apply the returned method to the
>> object specified in the command.
>
>I could code that in Inform, but the library already provides it.

Okay, it was entirely unclear whether that was actually something
handled by the library (and therefore, in principle, accessible from
within the language), or a debugging feature provided at the
interpreter level. If it is, in fact, accessible from within the
language, could you (or someone) please tell me what it takes to
convert the string entered by the player into the appropriate method
name/pointer/symbol/reference/whatever you call it in Inform?

In article <37ced95f...@news.bright.net>,


Jonadab the Unsightly One <jon...@bright.net> wrote:
>jwe...@pacific.mps.ohio-state.edu (Jesse Welton) wrote:
>

>> I think perhaps "push" would be a better example. Certainly there are
>> various classes of objects which the library will know should be
>> preferred, like buttons and levers. But whereas I'm unlikely to think
>> of any new classes of objects preferred for eating, it's not hard to
>> come up with new defaults for pushing. One might have a puzzle
>> involving pushing alphabet blocks around, pushing on various colored
>> bricks in a given wall, or pushing midgets out of the way. When I add
>> these things, I don't want to fuss with the parser code when I could
>> simply give that class of objects a property "prefPush = &preferred".
>

>Ah. Yes, definitely what you want could be done in Inform by having
>ChooseObjects check the object for a VerbPreferences property (or
>whatever you'd like to call it), and then you can have something
>like this:
>
>class AlphabetBlock
> with VerbPreferences [ switch (action)
> { ##Push: return 50;
> default: rfalse;
> } ],
> ! insert other stuff here
> name 'block' 'alphabet',
> list_together "alphabet blocks";

Now you're suggesting that objects can have a property
"VerbPreferences" that will do a switch on all possible verbs (or at
least those for which it doesn't have default behavior). That's one
of the three basic ways one (AKA "I") might think to do this:

1) Each verb has a method to decide which kinds of objects it prefers
2) Each object has a method to decide if it's preferred for a given verb
3) Each verb knows a unique method to call in the object to determine
whether that object is preferred for that given verb

1 and 2 both require switch statements (or something equivalent) that
must be maintained. 1 requires that you change the verb code (which
is by and large library code) whenever you add a new kind of preferred
object (which is bound to happen eventually in game code). 2, which I
believe you've just suggested above, is even worse, because it breaks
horribly with multiple inheritance: food class defines pref method
which recognizes ##Eat, key class defines pref method which recognizes
##UnlockWith; but these pref methods aren't additive, so it has to be
tediously (and possibly inconsistently) redefined for the CheezKee
which inherits from both classes. 3 solves both problems elegantly.

You've now shown me more or less how to do 1 and 2 in Inform, which I
don't personally think shows the beauty of Inform's system
particularly well. (Bear in mind that I'm a big fan of high-level
languages, which is why I was requesting high-level language features
in the first place. I don't like for loops, and I don't like switch
statements, though I will live with them if I have to.) So now if you
could show me how to do 3, without having to give each verb property
references like ##Take, ##PrefTake, ##VerTake, and what have you
*separately*, I would be most appreciative. (Yes, I know Inform will
already deal with some of that functionality in the library, but there
really is a whole family of related functionality to be dealt with,
and I'd probably have to augment or replace parts of the library's
functionality to get it to behave as I'd like.) I *might* even switch
to Inform. :)

>> > As far as the "call <method> in <object>" idea, Inform's built-in
>> >debugging suite (called Infix) provides such a function. You can type ";
>> >apple.DoADance()" while running the game, and the DoADance method of the
>> >apple will be executed.
>>
>> I feel like we're getting farther and farther off the point here.
>> That was just another example I came up with to illustrate possible
>> uses of a general feature.
>
>And the fact that it has been coded in Inform (and in fact would
>not be difficult to code; I could have done it) indicates that
>the feature is provided, or an equivalent feature.

Assuming, of course, that it's part of the library and not a debugging
feature programmed directly into the interpreter. But yes, you're right.
If it's part of the library, I'd like to know how it's done.

>> What I'm saying is that I'd
>> like language features which allow me to add my own functionality, at
>> a similar abstraction level to what the system provides by default, in
>> this case the ability to programmatically generate references to
>> methods whose names I can construct.
>

>Sounds to me like you want to be able to edit the library,

No, it means I want *language* features that support a high level of
abstraction. (Language features, as I use it here, includes both
syntactical constructs and built-in "primitive" functions, in
particular those which give the programmer access to as much
meta-level information about itself as possible.)

>or at least replace parser functions. Can't you do that in
>TADS? I thought this functionality had been added? (I
>admit I'm not very "current" with TADS...)

Yes, TADS has recently had quite a large number of hooks added to the
parser, which is great. I wouldn't go back. But you'll notice that
my conversation keeps coming back to this issue of looking up methods
by name, which TADS does not provide, but is a great introspective
feature to have available in certain kinds of high-level code, like
the verification and preference operations associated with verbs that
I seem to be explaining inexplicably poorly.


In article <19990902222051...@ng-fy1.aol.com>,


BrenBarn <bren...@aol.comRemove> wrote:
>>I don't think this is the right way to do things, because as you said,
>>such considerations are *virtually* universal. Exceptions run rampant
>>in IF, and it's much easier to deal with them if the exceptional
>>behavior goes into the exceptional objects themselves than making a
>>special case in the code that handles the general case. Or so I find.
> True. Since, as you stated later in your message, discussions of the
>relative merits of Inform/TADS/Hugo/etc. are not really relevant, I'll simply
>agree with you. However, I do think that these "virtually universal" chores
>should take place behind the scenes; what is needed is a way to override any
>little part of that process, which means breaking down the "behind the scenes"
>code into tiny bits.

And this is exactly what I've been advocating: Rather than having
single functions or methods that handle several special cases at once,
break the process into lots of tiny pieces associated with each
verb/object pair. It's further subdivided according to whether the
object is the direct of indirect object, and what part of the command
processing sequence you're currently in, be it checking logic (don't
drop something you're not holding), checking preferences (you're more
likely to press the green button than the green wall), or processing
the action itself. Most of these have default actions, which are
found in the root "Thing" class for game objects; for many of these,
the default may be empty, in which case Thing doesn't have to worry
about them at all. Then when you have a special object (or class),
you simply override the part that needs to be overridden, and move on
with your work without mucking about modifying the verbs; multiple
inheritance works cleanly for non-conflicting object specializations;
and so on.

>>> I'm beginning to understand (I think). From my (limited)
>>>understanding of TADS, the "verDo" is not automatically CREATED, it's
>>>just automatically used if it IS created. (In other words, all
>>>objects that don't define a "verDo" will use the default one, and all
>>>objects that do define a "verDo" will use that one, overriding the
>>>default.) I'm not exactly sure about object preferences.
>>
>>Right, you still have to create the apropriate handler methods in the
>>objects, but you don't have to tediously tell the compiler what their
>>names are, because it automatically generates their names. I'd like
>>to be able to generate my own names in the same way.
> I understand and yet I do not understand. Don't you have reference the
>routine's name in each object anyway? Otherwise, how would the compiler know
>what routine you're referring to? Or do you mean that you don't have to
>explicity define a "verDoTake" in the verb definition?

You have to reference the routine's name when you define the default
behavior, but you have to do that in any case. (Exception: when the
default behavior is to ignore it, you don't have to define it -- or at
least, you shouldn't have to.) What it saves you is the necessity to
reference it an additional time in the verb object, which is tedious
and error-prone (in that it gives you another opportunity for
game-stopping typos).

>> When I add [new kinds of special objects],


>>I don't want to fuss with the parser code when I could
>>simply give that class of objects a property "prefPush = &preferred".
> I agree. In fact, I think it would be great if the preference could be
>defined in EITHER the verb OR the object. So a programmer could use your
>"prefPush=&preferred"-inside-the-object idea, and/or a
>"prefer=AlphabetBlock"-inside-the-verb idea.

That's not a half bad idea, really. (It could conceivably run into
problems if you want to make for example a special kind of button that
*isn't* preferred, such as the "Detonate" button on the atomic bomb,
but that's at least less likely than the opposite case.) In any case,
providing the functionality for both still requires providing the
functionality I was asking for.


In article <37cf6157...@news.erols.com>,


TenthStone <mcc...@erols.com> wrote:
>On Thu, 02 Sep 1999 20:43:20 GMT, jon...@bright.net (Jonadab the
>Unsightly One) wrote:
>

>In TADS -- as in Inform, I should think -- property names are
>meaningless as strings. That is, you can't take a property
>name like &matrix1 and edit it to get the property name &matrix1_1.
>
>There are two special cases in TADS. To define a verb routine,
>you put a statement like
> doAction = 'Take'
>in the verb declaration. TADS automatically generates the two

>properties &doTake and &verDoTake from this declaration. I believe


>what Jesse wants is some general way to take a string and derive
>property names from it, which would probably be a pain in the ass to
>implement.

Exactly so! I wish I'd managed to explain it so concisely. But I
differ with you as to how difficult it would be to implement.

>Getting back to the matter at hand, the reason why this would be
>a pain is that TADS currently doesn't store property names in the
>gamefile at all unless it's begin compiled for debugging. They're
>simply numbered (and the numbers are inaccessible).

So we create a table for converting the property names to the
corresponding numbers. Not hard, since...

>So to implement dynamic property creation, you'd first have to store
>property names. Fine, there's already a procedure for doing in this
>when compiling for debugging.

Hmmm... Actually, come to think of it, this table is probably set up
in the opposite way from what is needed here, numbers->names. We need
names->numbers, which means storing the table differently in memory
(though not in the game file). Probably a hash table. But this is a
standard programming exercise which should be no problem for anyone
implementing a compiler. Indeed, I'm sure the TADS compiler uses just
such a table, itself.

> Beyond that, you'd need two functions:
> one to check whether a string is valid as a property

This condition is determined easily by looking the property up on the
table. If you don't find it, it's not defined.

> one to retrieve a property name from a string (dynamically
> creating it if it doesn't exist)

The only complication I foresee here is what effect it will have on
the savefile format. The property creation would have to be recorded
in the savefile, whereas pre-defined properties don't have to be
specially referenced in the savefile at all. So it might be a
reasonable restriction to disallow property creation at runtime. I
don't see any problem with allowing it at compile-time, however, for
example in preinit.

>It wouldn't be impossible to implement, just fairly difficult and very
>bug-prone. The advantages, though, are appreciable -- e.g. matrices.

At what level do you think it's bug-prone, its implementation or its
use? If you mean its implementation, I think it should be elementary
in comparison to the guts of the compiler. If you mean its use, I
don't think it would be any more error-prone than the dynamic property
creation TADS has now (adding properties to objects when non-existent
properties are assigned to, and quietly returning nil when
non-existent properties are referenced).

-Jesse

Andrew Plotkin

unread,
Sep 3, 1999, 3:00:00 AM9/3/99
to
Not responding to this entire thing, but I want to point out that this no
longer has much to do with an IF *engine*. It's all about library code,
though that includes built-in code and library support in the compiler
(viz Inform's veneer code.)

Jesse Welton

unread,
Sep 3, 1999, 3:00:00 AM9/3/99
to
In article <7qou21$d...@dfw-ixnews15.ix.netcom.com>,

Andrew Plotkin <erky...@netcom.com> wrote:
>Not responding to this entire thing, but I want to point out that this no
>longer has much to do with an IF *engine*. It's all about library code,
>though that includes built-in code and library support in the compiler
>(viz Inform's veneer code.)

I don't know what Inform's veneer code is; what kind of library
support in the compiler are you taking about?

While I'll grant you that a good portion of what I'm going over is
more directly related to library issues, that portion of it is largely
motivation for (and explanation of) the language/engine features I was
originally asking for. In particular:

* The compiler should make as few assumptions as possible about how
code will be used. (Don't overwrite my contents method, thanks.)
* The language/engine should support transparently overriding properties
with zero-argument methods. (This can be done in library code, as in
Inform, but I think it is better placed directly in the engine.)
* The engine should provide support for introspective programming, such
as maintaining a symbol table to allow dynamic lookup of computed
method names.

I'll grant you that collection operations is largely a library issue, be
the library built-in or game-defined. (The game doesn't need access to
special information only available through the engine for that.) But it
does require engine support for higher-level programming features like
passing functions (preferably anonymous functions) as arguments.

I'm sorry if the uh, wealth of motiational material has completely
shadowed the on-topic core of my suggestions, and hope that this
summary helps to provide clarity and, perhaps, a little motivation for
the motivational material. :)

And thanks for helping me steer back to the topic.

-Jesse

BrenBarn

unread,
Sep 3, 1999, 3:00:00 AM9/3/99
to
>These people think [my sig is] by Thoreau:
>http://www.soaringeagleltd.com/businessruletypes.htm
Thanks. I've been wondering who said that. The wording there is a little
different, but the meaning is the same. (I originally saw the quote posted
over the door of a high school classroom.)

From,
Brendan B. B. (Bren...@aol.com)
(Name in header has spam-blocker, use the address above instead.)

"Do not follow where the path may lead;

BrenBarn

unread,
Sep 3, 1999, 3:00:00 AM9/3/99
to
> "Take the wall" is
>grammatically correct, and means exactly what it sounds like it means.
>However, the wall is an illogical thing to take, which should be
>reflected in the disambiguation process. For example, if there's a
>green wall and a green block, and the player type "take green", the
>green wall should be thrown out of consideration.
I agree wholeheartedly. Inform is not very helpful in this matter; I had
to write my own library patch to get this sort of thing to work the way I
wanted it.
I think the problem is that such disambiguation must be very specific.
You must go through and pin down EXACTLY what attributes prevent objects from
being accepted as viable targets for an action (i.e., inedible objects can't be
eaten, fixed or heavy objects can't be taken or pushed, etc.). Hard-coding it
like this very quickly decreases the flexibility of the system.
Another problem is that (at least with Inform) the disambiguation handling
is buried deep inside a massive, complex bunch of routines. There is no way to
isolate the tiny part of it that deals with this particular problem, and so if
you ever want to rework the disambiguation, you have to edit the library source
code directly.
(Actually, that last paragraph is all false. I fully intend to add hooks
to the library so that I can modify the disambiguation from my own code. I
just haven't gotten around to it yet. :-)

BrenBarn

unread,
Sep 3, 1999, 3:00:00 AM9/3/99
to
Wow, this is long. . . :-S

> "Take the wall" is
>grammatically correct, and means exactly what it sounds like it means.
>However, the wall is an illogical thing to take, which should be
>reflected in the disambiguation process. For example, if there's a
>green wall and a green block, and the player type "take green", the
>green wall should be thrown out of consideration.

I agree wholeheartedly. Inform is not very helpful in this matter; I had
to write my own library patch to get this sort of thing to work the way I
wanted it.
I think the problem is that such disambiguation must be very specific.
You must go through and pin down EXACTLY what attributes prevent objects from
being accepted as viable targets for an action (i.e., inedible objects can't be
eaten, fixed or heavy objects can't be taken or pushed, etc.). Hard-coding it
like this very quickly decreases the flexibility of the system.
Another problem is that (at least with Inform) the disambiguation handling
is buried deep inside a massive, complex bunch of routines. There is no way to
isolate the tiny part of it that deals with this particular problem, and so if
you ever want to rework the disambiguation, you have to edit the library source
code directly.
(Actually, that last paragraph is all false. I fully intend to add hooks
to the library so that I can modify the disambiguation from my own code. I
just haven't gotten around to it yet. :-)

>So far, so good. Obviously, I can define properties in each verb to


>tell it which methods to call in the objects. What I want to do is
>automate this so that the verbs can figure out for themselves what
>properties to call, given that each verb already knows the equivalent
>of ##Take.

That doesn't sound too hard. All you need to do is lay the foundation by
making a skeleton structure of a verb. This basic verb will have hooks in it
to call various methods (if they're provided) in its objects.

>Since I'm unfamiliar with the use of Inform's before, override, and
>after routines, this suggestion means little to me. It sounds,
>however, as though you're suggesting that for each special kind of
>object, I have to add special considerations to a single monolithic
>function (or rather, the appropriate one of a few such functions).

>I actually don't mind editing my library files at all. I'm doing so
>extensively. I just want to keep library code in the library, and
>game-domain code in the game. I don't want to have to make changes to
>library functions to accommodate objects which are peculiar to a
>particular game.

Disregarding the Inform specifics, I agree. This "ideal" engine/library
that we're talking about should have hooks all over the place that allow you to
essentially put special-purpose code wherever you need to, and the result
should be the same as if you had directly altered the library file.

>>(Actually, if all you want to do is change the printed
>>message you can do that with the after routine.)
>
>So I still have to put the special considerations for all my special
>objects into a single function, right? The whole point of what I want
>to do is to break it up into atomic pieces.
>

Well, no. You make a separate function for each special object. But this
seems to be leaning toward the discussion of specific, existing IF compilers,
so I'll stop there.

>Consider
>
> "drop" * held
>
>as opposed to
>
> "drop" * noun
>
>How does Inform handle these different patterns?

The first one will only accept a held object as its direct object. (So
"drop apple" will only work if I'm holding the apple.) The second will accept
any object "in scope" (which essentially means any object you can see).

>If I'm holding a sock,
>and there's another sock on the floor, and I type "drop sock", the
>parser figures I must be talking about the one I'm holding. That's
>disambiguation. But yes, that's the sort of thing I'm after. Now, I
>don't know how ChooseObjects is used, but basically what I want to be
>able to do is have it take some equivalent of ##Take and figure out
>that the property I want to call is ##PrefTake. If instead of ##Take
>it got ##Drop, it should call ##PrefDrop, and so on. And I want to
>use a function that can make this transformation general, so I don't
>have to put in two hundred different switch statements.

I don't think you'll find much argument on that idea :-). As far as the
implementation goes, though, there are a couple of ways to do that.
One basic issue that I think is really hampering some of our communication
here is the way verbs are handled. In Inform, verbs are not objects as such;
in TADS they are (albeit a special kind of object). Now, Inform-vs-TADS
battles aren't really important, but if we're talking about designing a new
compiler, we need to decide which way we're going to use (or if we're going to
use a totally different way :-).
If you don't make the verbs objects, they can't have properties and such.
If you do make them objects, though, you run into some strange constructs.
(For example, although I can clearly see how "weight" could be a property of an
apple, it's more difficult to understand how "verDoTake" is a property of
"Take".)
I think that, rather than simply spout off, I'll wait to see if you get my
meaning, and then we can decide how we want this "new" compiler to handle
verbs. Once we've decided that, I think a lot of these issues will become
easier to solve.

>Okay, it was entirely unclear whether that was actually something
>handled by the library (and therefore, in principle, accessible from
>within the language), or a debugging feature provided at the
>interpreter level. If it is, in fact, accessible from within the
>language, could you (or someone) please tell me what it takes to
>convert the string entered by the player into the appropriate method
>name/pointer/symbol/reference/whatever you call it in Inform?

I think I now understand what you're saying. No, I don't know how to
access this feature from within the language (which I assume means "looking at
the source code"). But someone else might.
Now that I understand your question, I share your curiosity. It seems to
me as though the compiler, having as it does access to the entire source file,
should easily be able to pick out whatever text it wants and use it however it
wants. (For example, it could find the word "Take" and add "verDo" to the
front, and in this way "create" the name "verDoTake".) It would indeed be an
amazing feature if this ability were passed on to the programmer.

>Now you're suggesting that objects can have a property
>"VerbPreferences" that will do a switch on all possible verbs (or at
>least those for which it doesn't have default behavior). That's one
>of the three basic ways one (AKA "I") might think to do this:
>
>1) Each verb has a method to decide which kinds of objects it prefers
>2) Each object has a method to decide if it's preferred for a given verb
>3) Each verb knows a unique method to call in the object to determine
> whether that object is preferred for that given verb
>
>1 and 2 both require switch statements (or something equivalent) that
>must be maintained. 1 requires that you change the verb code (which
>is by and large library code) whenever you add a new kind of preferred
>object (which is bound to happen eventually in game code). 2, which I
>believe you've just suggested above, is even worse, because it breaks
>horribly with multiple inheritance: food class defines pref method
>which recognizes ##Eat, key class defines pref method which recognizes
>##UnlockWith; but these pref methods aren't additive, so it has to be
>tediously (and possibly inconsistently) redefined for the CheezKee
>which inherits from both classes. 3 solves both problems elegantly.

Since we're talking about a theoritcal, "new" compiler here, I would
advocate a combination of #1 and #3. I agree that #3 is probably best for most
game-specific applications. There are, however, many, many standard situations
for which it would be tedious to apply #3. For example, I would be very
annoyed if, every time I wanted to program a game, I had to tell the compiler
that rocks were not edible.
Once again we have the "Inform way-vs.-TADS way" problem. If we use the
TADS way, the library (the equivalent of "std.tad" and :"adv.tad", I think)
could automatically define all these standard cases using #3. If we use the
Inform way, the library would define them using #1, and we could add to them by
editing the grammar (which is like #1, but not quite so bad).
The thing I don't like about #3 is that now, instead of the library
defining standard verb disambiguation, we have the library defining standard
object classes, which, to my fiercely individualistic mind, imposes an unfair
yoke on the game designer. (What if I don't WANT my classes to be like that?)
So I like #1 (which is much like what Inform uses) -- but it does need
work. I also like #3 (which is, I think, like what TADS uses) -- but it needs
work too. What we need is a #4 that combines the strengths of both.

>Rather than having
>single functions or methods that handle several special cases at once,
>break the process into lots of tiny pieces associated with each
>verb/object pair.

Yes. Yes. But you don't want to break it down TOO much, because then it
becomes tedious to put back together again. For example, if the Take action
disallows an object that is either: A) Too heavy; B) Too big; or C) Fixed in
place, and each of these is coded separately, then if I want to modify all of
them, I have to modify each one individually. What we need is a logical "tree
structure" in which varying degrees of refinement are built upon each other.
This is in fact what you suggested. We just need to work out the specifics.

>So we create a table for converting the property names to the
>corresponding numbers.

<and other related comments>
Right. But the problem is, this is created at compile time. And that
means you have to make double-sure that the table is set up before you start
trying to use it. It's not really a problem to know what to do, you just have
to be careful not to mess up in actually doing it.
(And I agree with your comments about runtime-vs.-compile time creation of
properties, too.)

Whew. That was long. . . :-)

L. Ross Raszewski

unread,
Sep 3, 1999, 3:00:00 AM9/3/99
to
In article <7qp0tq$908$1...@pacific.mps.ohio-state.edu>, Jesse Welton wrote:
>In article <7qou21$d...@dfw-ixnews15.ix.netcom.com>,
>Andrew Plotkin <erky...@netcom.com> wrote:
>>Not responding to this entire thing, but I want to point out that this no
>>longer has much to do with an IF *engine*. It's all about library code,
>>though that includes built-in code and library support in the compiler
>>(viz Inform's veneer code.)
>
>I don't know what Inform's veneer code is; what kind of library
>support in the compiler are you taking about?
>
Simply put, a lot of the really handy inform constructs, (verb, objectloop,
box, implied print-ret, etc) aren't really pert of the Z-machine, but
are constructs which inform expands at compile time into calls to functions
that inform builds into every game file. For example, the construction
box "tra" "la" "la";

is not pert of Z; inform turns it into a declaration of an array of three
strings, and a call to a function called (something like)Box__Routine,
with the array and its size (I may be slightly inaccurate techincally, but
you get the idea). Box__Routine is inserted into the top of the source code
(or the bottom. whatever), and contains the code nessecary to draw a box
given an array and its size (resize the window, calcualtew centering,
dput the cursor in the right position, write the string, etc.)

>While I'll grant you that a good portion of what I'm going over is
>more directly related to library issues, that portion of it is largely
>motivation for (and explanation of) the language/engine features I was
>originally asking for. In particular:
>
>* The compiler should make as few assumptions as possible about how
> code will be used. (Don't overwrite my contents method, thanks.)

To my knowledge, this is squirelly only with create, recreate, and destroy,
in Inform, at least.


>* The language/engine should support transparently overriding properties
> with zero-argument methods. (This can be done in library code, as in
> Inform, but I think it is better placed directly in the engine.)

That would be purely a language issue; at the engine level, functions don't
have textual names (And an engine in which they do is too high-level for
the likes of me.

>* The engine should provide support for introspective programming, such
> as maintaining a symbol table to allow dynamic lookup of computed
> method names.

Awwk~! Parse not found.
Seriously, though, if that means what I thimnk it means, then it's a compiler/
library issue.

>
>I'll grant you that collection operations is largely a library issue, be
>the library built-in or game-defined. (The game doesn't need access to
>special information only available through the engine for that.) But it
>does require engine support for higher-level programming features like
>passing functions (preferably anonymous functions) as arguments.


Either that doesn't mean what I think it means, or you can already do that in
inform. I'm guessing the former.

Jesse Welton

unread,
Sep 3, 1999, 3:00:00 AM9/3/99
to
In article <slrn7t0clj....@lucy.cs.loyola.edu>,

L. Ross Raszewski <lras...@lucy.cs.loyola.edu> wrote:
>In article <7qp0tq$908$1...@pacific.mps.ohio-state.edu>, Jesse Welton wrote:
>>In article <7qou21$d...@dfw-ixnews15.ix.netcom.com>,
>>
>>I don't know what Inform's veneer code is; what kind of library
>>support in the compiler are you taking about?
>>
>Simply put, a lot of the really handy inform constructs, (verb, objectloop,
>box, implied print-ret, etc) aren't really pert of the Z-machine, but
>are constructs which inform expands at compile time into calls to functions
>that inform builds into every game file.

Okay, that answers that question. Thanks.

>>* The compiler should make as few assumptions as possible about how
>> code will be used. (Don't overwrite my contents method, thanks.)
>To my knowledge, this is squirelly only with create, recreate, and destroy,
>in Inform, at least.

Inform compiles to a fairly low-level instruction set, and most all of
the game-related functionality is library-level, so this doesn't
surprize me. An engine doesn't have to be this way, though, so I
wanted to put it down as a request.

>>* The language/engine should support transparently overriding properties
>> with zero-argument methods. (This can be done in library code, as in
>> Inform, but I think it is better placed directly in the engine.)
>
>That would be purely a language issue; at the engine level, functions don't
>have textual names (And an engine in which they do is too high-level for
>the likes of me.

No, this particular feature has nothing to do with names. It means
that when the engine looks up the value of a property, it will return
the value if it is data, but if it is a method which takes no
arguments it will automatically call the method and return the value
returned by the method. That way, the code asking for the value of
the property doesn't have to know if it's computed or not.

I was told earlier in the thread that Inform uses a library function
that encapsulates this functionality. What I'm saying is that this
should be handled at the engine level, instead.

Why is an engine in which functions have names at too high a level for
you? I'm guessing it's because it would be grossly inefficient to
look up all your functions, methods, etc. by name. But in fact, these
can still be referenced by address, so you don't lose any runtime
efficiency. A symbol table mapping names to addresses will however
give you considerably expanded runtime capabilities, for example in
the areas I've been discussing here at considerable length, at a small
penalty to storage requirements.

>>* The engine should provide support for introspective programming, such
>> as maintaining a symbol table to allow dynamic lookup of computed
>> method names.
>Awwk~! Parse not found.
>Seriously, though, if that means what I thimnk it means, then it's a compiler/
>library issue.

What do you think it means? I can't think of any way to understand it
as other than an engine issue. Perhaps the word "engine" is catching
us up, here. If the interpreter doesn't provide a symbol table (which
will convert, say, method names into method ID numbers or whatever
low-level implementation method references have), I don't see how the
library can do so. At least, not without compiler support (and that
still means that the system implementors have to do it, not the
library or game author, which ammounts to the same thing).

>>I'll grant you that collection operations is largely a library issue, be
>>the library built-in or game-defined. (The game doesn't need access to
>>special information only available through the engine for that.) But it
>>does require engine support for higher-level programming features like
>>passing functions (preferably anonymous functions) as arguments.
>
>Either that doesn't mean what I think it means, or you can already do that in
>inform. I'm guessing the former.

Can you, in Inform, write a function "map" that takes as argument a
list of objects and a function to apply to each argument? (And nobody
tell me that you can do this with some ObjectLoop something or other.
I'm trying to get at the high-level concept of passing functions
around.) And can you define that function at the same point in the
code as you call "map"?

Whether this can be done in Inform or not, I'd like to see it in
future authoring systems.

-Jesse

BrenBarn

unread,
Sep 4, 1999, 3:00:00 AM9/4/99
to
>Perhaps the word "engine" is catching us up, here.
I think you're right. What exactly do you mean by "engine"? I've been
assuming that you meant "compiler".

>>>* The engine should provide support for introspective programming, such
>>> as maintaining a symbol table to allow dynamic lookup of computed
>>> method names.
>>Awwk~! Parse not found.
>>Seriously, though, if that means what I thimnk it means, then it's a
>compiler/
>>library issue.
>
>What do you think it means? I can't think of any way to understand it
>as other than an engine issue. Perhaps the word "engine" is catching
>us up, here. If the interpreter doesn't provide a symbol table (which
>will convert, say, method names into method ID numbers or whatever
>low-level implementation method references have), I don't see how the
>library can do so. At least, not without compiler support (and that
>still means that the system implementors have to do it, not the
>library or game author, which ammounts to the same thing).

This seems to be one of your main topics, and I'm still not fully
understanding you. What is "a symbol table to allow dynamic lookup of computed
method names"?

>Can you, in Inform, write a function "map" that takes as argument a
>list of objects and a function to apply to each argument? (And nobody
>tell me that you can do this with some ObjectLoop something or other.
>I'm trying to get at the high-level concept of passing functions
>around.) And can you define that function at the same point in the
>code as you call "map"?

Well, if I'm understanding you correctly, you can sort of do this in
Inform, but (sorry about this) it takes an objectloop. Is what you mean sort
of like a "for. . .in. . .do" loop? Like:
For x in (Object1 Object2 Object3) do ThisFunction(x);
The part of this that Inform doesn't provide a special construct for is if
Object1, Object2 and Object3 are completely unrelated objects. If they share a
common characteristic (among themselves only), you can use a (dare I say it?
:-) objectloop.
But I don't understand why you don't want an objectloop. Do you just want
a convenient shorthand for the above?

>Whether this can be done in Inform or not, I'd like to see it in
>future authoring systems.

I think that this should be our watchword as our fears of getting
off-topic grow. If we're really talking about a NEW system, we need use
existing systems only as a learning base; just because an existing compiler
provides a feature doesn't mean we shouldn't provide it too.

L. Ross Raszewski

unread,
Sep 4, 1999, 3:00:00 AM9/4/99
to
In article <7qpg2c$fiu$1...@pacific.mps.ohio-state.edu>, Jesse Welton wrote:

>
>No, this particular feature has nothing to do with names. It means
>that when the engine looks up the value of a property, it will return
>the value if it is data, but if it is a method which takes no
>arguments it will automatically call the method and return the value
>returned by the method. That way, the code asking for the value of
>the property doesn't have to know if it's computed or not.

Okay. I see now. I suppose that'd be handy at times (God knows I'd
havew liked it at a couple of points. THe only problem is, the present method
is a usefull enough feature that it would be adding an annoying
inconsistancy if the language did something different for one particular case.
(That is, I know full well that inform gives me a function address when I
type x.y and y's a function. To have it sometmes give me a function address
and sometimes call the function, however, would probably be more error prone
than the current method. What I'd personally prefer would be if the
(); operator could be extended to return the value of a variable, if applied to
a random variable (currently, x(); is supposed to call X if x is a function and
return the value of the function. if X is just a variable, it returns 0.)


>
>Why is an engine in which functions have names at too high a level for
>you? I'm guessing it's because it would be grossly inefficient to

It's basically just because I'm an old-fashioned sort who believes that the
low- level engine should be, well, low-level.

>
>What do you think it means? I can't think of any way to understand it
>as other than an engine issue. Perhaps the word "engine" is catching
>us up, here. If the interpreter doesn't provide a symbol table (which
>will convert, say, method names into method ID numbers or whatever
>low-level implementation method references have), I don't see how the
>library can do so. At least, not without compiler support (and that
>still means that the system implementors have to do it, not the
>library or game author, which ammounts to the same thing).

Okay. Except no. The Z machine engine designer had very little to do with the
inform compiler designer. Yes, you'd need to build a symbol table into
the compiler, and have it generate a veneer method to access the table.
I couldn't imagine there being anything like an "convert string to property
number" opcode in a virtual machine, though; it just feels too high-level.

>

>
>Can you, in Inform, write a function "map" that takes as argument a
>list of objects and a function to apply to each argument? (And nobody
>tell me that you can do this with some ObjectLoop something or other.
>I'm trying to get at the high-level concept of passing functions
>around.) And can you define that function at the same point in the
>code as you call "map"?

Yes-- er... no, actually. Ah. Now I see. I mostly did before, but there
was some haziness. You can do this:

[ foo x;
print(name) x;
];
[ bar y z x;
while(x>0)
z(y-->(x--));

];
...
bar(array,5,foo);

and function foo would be called with each of the entries in array "array"
as its argument. It would be very very difficult for a virtual machine not to
have this functionality, though it would be pretty easy for a compiler not to
(inform pre-6 required that function names stored in variables could only be
called using a library routine.

Now you can't define a function inside another, because inform doesn't allow
nested declarations, generally speaking, but that's a compiler thing.

I'd personally like on-the-fly definition of static arrays in code, another
compiler issue, and probably doable in the same way as nested function
declarations.

>


Gunther Schmidl

unread,
Sep 4, 1999, 3:00:00 AM9/4/99
to
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

RAIF-POOL does all that.

HTH. HAND.

- --
+-----------------+---------------+------------------------------+
| Gunther Schmidl | ICQ: 22447430 | IF: http://sgu.home.dhs.org/ |
|-----------------+----------+----+------------------------------|
| gschmidl (at) gmx (dot) at | please remove the "xxx." to reply |
+----------------------------+-----------------------------------+

-----BEGIN PGP SIGNATURE-----
Version: PGPfreeware 6.5.1 for non-commercial use <http://www.pgp.com>

iQA/AwUBN9FYtFDPJraD3kCIEQJvTQCfbFW931brrRvfWo1f3ybPvUWGL3YAoNSO
JZHw33r0gawQU4VnsfwU6Mz6
=uHk+
-----END PGP SIGNATURE-----


TenthStone

unread,
Sep 4, 1999, 3:00:00 AM9/4/99
to
On 3 Sep 1999 12:37:14 -0400, jwe...@pacific.mps.ohio-state.edu
(Jesse Welton) wrote:

>Sorry about the monolithic response, but that the way it goes, this
>time. Newsgroups trimmed.

Well, usually what we do is make seperate replies to seperate
articles, but I suppose you wanted to cut down on repeating yourself.

Oh, and I'm hyping Pianosa to death in parts of this.

>In article <37cece0a...@news.bright.net>,
>Jonadab the Unsightly One <jon...@bright.net> wrote:

>>Right. If you allowed functions to determine the object tree
>>you'd have all manner of nasty side-effects. Such kludges as
>>found_in have wicked enough side-effects, without allowing
>>child and sibling calls to be intercepted by an object's routine.
>>That way lies madness. If you want to change the object tree,
>>it's much safer to just move the objects.
>
>Not necessarily. One reasonable use for overriding the contents
>property with a method would be to redirect contents requests to
>topContents, insideContents, or what have you. Why would you want to
>do this? So that you could use separate lists for the objects on top
>of a box and in it. Then you can have non-conflicting surface and
>container classes. To get a combined container and surface, simply
>derive from both classes. But to make such a library enhancement as
>backwards-compatible as possible, you want old code which references
>the plain contents of objects which are either surfaces or containers
>(but not both) to redirect "contents" as appropriate automatically.

I tend not to hype my own works, but you should look at Pianosa:
ftp://ftp.gmd.de/if-archive/programming/tads/examples/pianosa.zip
I should be releasing the next version in a few days, though, so
you might want to hold off on it.

But one of the things it does is multiple contents lists. The way I
handled .contents is to make it an alias for the sum total of all
the object's contents; this actually achieves what you're saying here.

Yes, TADS's assumptions are annoying, but they're not too bad (oh,
and if you make .location a method or nil on all objects, .contents
shouldn't be modified at all). That is, you can often work around
them.

>Uh, yeah. I think you miss my point. Much of the time, you actually
>don't want to check every object in the game, you want to handle every
>object in some scope satisfying some conditions. So, you define a
>method to return every object in whatever scope you're interested in,
>and you define an independent set of collection operations that allow
>you to filter that list, perform operations on it, and so on. Then,
>the author can use these in arbitrary combinations to achieve the
>result desired in a particular situation.

(ahem) (TADS) In Pianosa, the gacx functions. The collection
operations are in the update.

>> These changes could be made in
>>the game file (using the Replace directive) if you don't like
>>editing your library files.
>
>I actually don't mind editing my library files at all. I'm doing so
>extensively. I just want to keep library code in the library, and
>game-domain code in the game. I don't want to have to make changes to
>library functions to accommodate objects which are peculiar to a
>particular game.

If you're writing a complex game, you will always have to make changes
to library functions to accomodate objects which are peculiar to a
game. If nothing else, you will add your own functions. This is
nothing new. This has to do with the library not being able to
anticipate everything you want.

A library's role in this case is to make the modifications you do make
less intense and less revolutionary.

>>No, you wouldn't have to replace the parser to change the default
>>response. (Actually, if all you want to do is change the printed
>>message you can do that with the after routine.)
>
>So I still have to put the special considerations for all my special
>objects into a single function, right? The whole point of what I want
>to do is to break it up into atomic pieces.

I believe it's generally conceded that TADS follows closer to the
object-oriented ideal. The counter-argument is that the ideal is not
always the most efficient way of going about things.

I happen to agree that it makes things easier on the end-user. But
that's just my opinion, and it falls apart when you test the limits of
the TADS engine.

>(Bear in mind that I'm a big fan of high-level languages, which is
>why I was requesting high-level language features in the first place.
>I don't like for loops, and I don't like switch statements, though I will
>live with them if I have to.)

Hmm. I always learned that switch statements were high-level.

>>> What I'm saying is that I'd
>>> like language features which allow me to add my own functionality, at
>>> a similar abstraction level to what the system provides by default, in
>>> this case the ability to programmatically generate references to
>>> methods whose names I can construct.
>>
>>Sounds to me like you want to be able to edit the library,
>
>No, it means I want *language* features that support a high level of
>abstraction. (Language features, as I use it here, includes both
>syntactical constructs and built-in "primitive" functions, in
>particular those which give the programmer access to as much
>meta-level information about itself as possible.)

The Inform language, I believe, is almost entirely based upon the
libraries. The underlying code is pure assembly.

I could very well be wrong on this.

>In article <37cf6157...@news.erols.com>,
>TenthStone <mcc...@erols.com> wrote:
>>In TADS -- as in Inform, I should think -- property names are
>>meaningless as strings. That is, you can't take a property
>>name like &matrix1 and edit it to get the property name &matrix1_1.
>>
>>There are two special cases in TADS. To define a verb routine,
>>you put a statement like
>> doAction = 'Take'
>>in the verb declaration. TADS automatically generates the two
>>properties &doTake and &verDoTake from this declaration. I believe
>>what Jesse wants is some general way to take a string and derive
>>property names from it, which would probably be a pain in the ass to
>>implement.
>
>Exactly so! I wish I'd managed to explain it so concisely. But I
>differ with you as to how difficult it would be to implement.

The chief difficulty lies in not being Mike Roberts.

>>Getting back to the matter at hand, the reason why this would be
>>a pain is that TADS currently doesn't store property names in the
>>gamefile at all unless it's begin compiled for debugging. They're
>>simply numbered (and the numbers are inaccessible).
>
>So we create a table for converting the property names to the
>corresponding numbers. Not hard, since...

Well, the thing is that TADS gamefiles are already very large, and
debugger files are even worse. Storing a table capable of fitting
64K entries into it might be fairly inefficient.

>>So to implement dynamic property creation, you'd first have to store
>>property names. Fine, there's already a procedure for doing in this
>>when compiling for debugging.
>
>Hmmm... Actually, come to think of it, this table is probably set up
>in the opposite way from what is needed here, numbers->names. We need
>names->numbers, which means storing the table differently in memory
>(though not in the game file). Probably a hash table. But this is a
>standard programming exercise which should be no problem for anyone
>implementing a compiler. Indeed, I'm sure the TADS compiler uses just
>such a table, itself.

I'm sure it does. It generates it on the fly as it's running through
the gamefile. "Oh look, here's a property we haven't seen before,
let's give it a new number."

Actually, consider that you'd want to be able to convert a property
name into a string as well.

>> one to retrieve a property name from a string (dynamically
>> creating it if it doesn't exist)
>
>The only complication I foresee here is what effect it will have on
>the savefile format. The property creation would have to be recorded
>in the savefile, whereas pre-defined properties don't have to be
>specially referenced in the savefile at all. So it might be a
>reasonable restriction to disallow property creation at runtime. I
>don't see any problem with allowing it at compile-time, however, for
>example in preinit.

Disallowing property creation at runtime would cut out most of the
utility for me. Being able to define a hundred .prefDoTakes is not a
real critical issue.

>>It wouldn't be impossible to implement, just fairly difficult and very
>>bug-prone. The advantages, though, are appreciable -- e.g. matrices.
>
>At what level do you think it's bug-prone, its implementation or its
>use? If you mean its implementation, I think it should be elementary
>in comparison to the guts of the compiler.

Yes, but the guts of the compiler are already written, are still being
debugged today, and are largely seperate from the guts of the
interpreter anyway.

>If you mean its use, I don't think it would be any more error-prone than the
>dynamic property creation TADS has now (adding properties to objects
>when non-existent properties are assigned to, and quietly returning nil
>when non-existent properties are referenced).

That's different. Those properties existed before, fully indexed.
They just weren't defined for the object itself.

I call it bug-prone in usage because typos can result in lost data,
not just incorrect data. If I assign data to the wrong property, I
can't necessarily find it, but I won't necessarily know that it's in
the wrong place until much later. It's not impossible to catch, just
much harder.

I still like the idea.

T Raymond

unread,
Sep 5, 1999, 3:00:00 AM9/5/99
to
mcc...@erols.com (TenthStone) spoke about :

>I tend not to hype my own works, but you should look at Pianosa:
> ftp://ftp.gmd.de/if-archive/programming/tads/examples/pianosa.zip
>I should be releasing the next version in a few days, though, so
>you might want to hold off on it.
>
>But one of the things it does is multiple contents lists. The way I
>handled .contents is to make it an alias for the sum total of all
>the object's contents; this actually achieves what you're saying here.

IS the update going to have any commenting or documentation, I
didn't check out the initial release. IS there any sample code of
it's features?? (hoping)

Tom

TenthStone

unread,
Sep 5, 1999, 3:00:00 AM9/5/99
to
On Sun, 05 Sep 1999 03:44:33 GMT, ar...@see.the.sig (T Raymond) wrote:

>mcc...@erols.com (TenthStone) spoke about :


>>I tend not to hype my own works, but you should look at Pianosa:
>> ftp://ftp.gmd.de/if-archive/programming/tads/examples/pianosa.zip
>>I should be releasing the next version in a few days, though, so
>>you might want to hold off on it.
>>
>>But one of the things it does is multiple contents lists. The way I
>>handled .contents is to make it an alias for the sum total of all
>>the object's contents; this actually achieves what you're saying here.
>

>IS the update going to have any commenting or documentation, I
>didn't check out the initial release. IS there any sample code of
>it's features?? (hoping)

Documentation will mostly be in the form of property listings for
classes. It's not much, but it's all I have right now.

Sample code is something that I'm working on and will release in
stages. If anyone is interested in writing a sample game, please
e-mail me at tenth...@hotmail.com. Thanks.

T Raymond

unread,
Sep 6, 1999, 3:00:00 AM9/6/99
to
mcc...@erols.com (TenthStone) spoke about :

>>IS the update going to have any commenting or documentation, I
>>didn't check out the initial release. IS there any sample code of
>>it's features?? (hoping)
>
>Documentation will mostly be in the form of property listings for
>classes. It's not much, but it's all I have right now.
>
>Sample code is something that I'm working on and will release in
>stages. If anyone is interested in writing a sample game, please
>e-mail me at tenth...@hotmail.com. Thanks.

Thanks for the update Tenth. I might actually get a chance to check it
out. :)

Tom

Jonadab the Unsightly One

unread,
Sep 6, 1999, 3:00:00 AM9/6/99
to
jwe...@pacific.mps.ohio-state.edu (Jesse Welton) wrote:

> No, this particular feature has nothing to do with names. It means
> that when the engine looks up the value of a property, it will return
> the value if it is data, but if it is a method which takes no
> arguments it will automatically call the method and return the value
> returned by the method. That way, the code asking for the value of
> the property doesn't have to know if it's computed or not.
>

> I was told earlier in the thread that Inform uses a library function
> that encapsulates this functionality. What I'm saying is that this
> should be handled at the engine level, instead.

Um, the engine shouldn't even KNOW whether a particular property
of a particular object has a routine in it or a string or a value.
That's totally a library issue, or possibly a compiler issue.
But I'd rather have it in the library than in the compiler,
because then I can override and change its behavior if I want.
ValueOrRun is *safe*. It checks to see that the object exists
and has that property before it executes the instructions to
access it. That's a Good Thing(TM). You could have the
compiler do that transparently, but I don't see what the
advantage would be. Probably nothing that could compare to
the potential advantage of being able to Replace the library
function that does it with your own version. Then you can
create your own extended format for objects and have it
work, for example...

> Why is an engine in which functions have names at too high a level for
> you?

That's WAY too high a level. You've got the VM knowing where a
particular table is located that stores the names... that means
the VM knows what kind of thing (table, routine, ...) is in
each part of memory. I'd rather have the engine consider
memory as a chunk of randomly addressable storage space.
Storing the names of the functions so they can be looked up
at run time is a compiler issue.

> I'm guessing it's because it would be grossly inefficient to

> look up all your functions, methods, etc. by name. But in fact, these
> can still be referenced by address, so you don't lose any runtime
> efficiency. A symbol table mapping names to addresses will however
> give you considerably expanded runtime capabilities, for example in
> the areas I've been discussing here at considerable length, at a small
> penalty to storage requirements.

It is handy for debugging, but it's a compiler issue. When you
compile a non-debug release, can you think of any reason to
have them in there?

> Perhaps the word "engine" is catching
> us up, here. If the interpreter doesn't provide a symbol table (which
> will convert, say, method names into method ID numbers or whatever
> low-level implementation method references have), I don't see how the
> library can do so.

The library can't. The compiler can. Inform does, and the z-machine
interpreter doesn't know or care about it.

> At least, not without compiler support (and that
> still means that the system implementors have to do it, not the
> library or game author, which ammounts to the same thing).

Why is that the same thing? In the case of Inform, the compiler
is maintained by the same person as the library, but the interpreters
are not. Your premise that the compiler and interpreter go together
is utterly without foundation. Talk has been passed around
repeatedly of writing an IF compiler that uses Java as its engine.
Inform already uses the z-machine. I'm pretty sure there's a
minor system or two somewhere that compiles to a DOS executable.
The compiler and the runtime engine may indeed not be maintained
together.

> Can you, in Inform, write a function "map" that takes as argument a
> list of objects and a function to apply to each argument?

Are you trolling?

[ CallRoutineOnObjects objecttable routinetorun n i;
n = objecttable-->0; ! number of entries in the list
for (i=1:i<=n:i++) indirect(routinetorun objecttable-->i);
];

This assumes you meant the same routine was to be run on
each object; if you meant that each object's foo routine
should be run, then it would be like this:

[ CallRoutineOnObjects objecttable prop n i;
n = objecttable-->0;
for (i=1:i<=n:i++) RunRoutines((objecttable-->i),prop);
];

> I'm trying to get at the high-level concept of passing functions
> around.)

Functions have the same status in Inform as strings or
dictionary entries or whatever. You can pass them*
around arbitrarily.

* -- Their addresses, technically.

> And can you define that function at the same point in the
> code as you call "map"?

I don't understand quite what you're asking here.

Jonadab the Unsightly One

unread,
Sep 6, 1999, 3:00:00 AM9/6/99
to
mcc...@erols.com (TenthStone) wrote:

> >jwe...@pacific.mps.ohio-state.edu (Jesse Welton) wrote:
> >> What I'm saying is that I'd
> >> like language features which allow me to add my own functionality, at
> >> a similar abstraction level to what the system provides by default, in
> >> this case the ability to programmatically generate references to
> >> methods whose names I can construct.
> >
> >Sounds to me like you want to be able to edit the library,

> >or at least replace parser functions. Can't you do that in
> >TADS? I thought this functionality had been added? (I
> >admit I'm not very "current" with TADS...)
>

> In TADS -- as in Inform, I should think -- property names are
> meaningless as strings. That is, you can't take a property
> name like &matrix1 and edit it to get the property name &matrix1_1.

You CAN, I just don't see the point.

The automatic property creation he describes is simply TADS'
way of implementing something. (Specifically, an object's
ability to intervene and change the behavior of a verb.)
Inform implements this differently.

> There are two special cases in TADS. To define a verb routine,
> you put a statement like
> doAction = 'Take'
> in the verb declaration. TADS automatically generates the two
> properties &doTake and &verDoTake from this declaration. I believe
> what Jesse wants is some general way to take a string and derive
> property names from it, which would probably be a pain in the ass to
> implement.

But he wants that BECAUSE he wants a general way to have more
entry points for an object to interfere with any given
arbitrary verb.

> (Incidentally, regarding someone's previous statement, there are no
> "default" verb handlings in TADS except for some very primitive verb
> disambiguation routines inherited from the verb class. If the
> &verDoX routine is missing from an object completely, there _is_ an
> automatic response along the lines of "You can't do that.", but
> nothing will happen if &verDoX is present and &doX is absent.)

What may have been meant is the default handling for any
particular verb; for example, in the case of the Take verb,
moving the object to the player.

> So to implement dynamic property creation, you'd first have to store
> property names.

It wasn't dynamic property creation he wanted; he was talking
about compile time, not run time.

Daniel Schepler

unread,
Sep 6, 1999, 3:00:00 AM9/6/99
to
bren...@aol.comRemove (BrenBarn) writes:

[snip]


>
> >> And can you define that function at the same point in the
> >> code as you call "map"?
> >
> >I don't understand quite what you're asking here.

> Nor I.
>

My interpretation is that this is possible in Scheme (which is also
probably the origin of the name "map"). For example, you could do

(define map ; If not already defined as a standard function
(lambda (f ls)
(cond
((null? ls) ls)
(t (cons (f (car ls))
(map f (cdr ls)))))))

(map (lambda (n) (+ n 2))
'(2 0 -4 8))
=> (4 2 -2 10)

So the answer, of course, is that it isn't possible in Inform; the
function to apply would have to be defined separately.
--
Daniel Schepler "Please don't disillusion me. I
sche...@math.berkeley.edu haven't had breakfast yet."
-- Orson Scott Card

BrenBarn

unread,
Sep 7, 1999, 3:00:00 AM9/7/99
to
>Um, the engine shouldn't even KNOW whether a particular property
>of a particular object has a routine in it or a string or a value.
I think that's what Jesse was saying too. I certainly agree.

>That's totally a library issue, or possibly a compiler issue.
>But I'd rather have it in the library than in the compiler,
>because then I can override and change its behavior if I want.
>ValueOrRun is *safe*. It checks to see that the object exists
>and has that property before it executes the instructions to
>access it. That's a Good Thing(TM). You could have the
>compiler do that transparently, but I don't see what the
>advantage would be. Probably nothing that could compare to
>the potential advantage of being able to Replace the library
>function that does it with your own version. Then you can
>create your own extended format for objects and have it
>work, for example...

I agree. If I understood Jesse right, he wasn't suggesting that the
compiler go out and try to grab property values without knowing whether the
object provides the property or not. He was suggesting that the simple
expression "apple.weight" should return the value of the apple's property
"weight", if it is a simple value, or the return value of the "weight" method,
if it's a method.
As someone else pointed out, though, this creates inconsistencies.
Currently, in Inform, the statement "x=apple.weight" assigns to "x" the value
of "weight" if it's a simple value, but assigns the ADDRESS of the method
"weight" if it's a method. Admittedly, this is a roadblock, but I think we
could get around it by using some operator like "pointer", where (assuming
apple.weight" is a method) "pointer(apple.weight)" returns the address of the
method, and "apple.weight" returns that method's return value.
As far as being able to Replace the control of accessing property values.
. . I think the compiler should implement that control transparently, but
provide a hook so that the everyday programmer could add to the functionality.
(It's not often that anyone will want to PREVENT themselves from accessing a
property value, which would seem to be the only thing you could achieve by
Replacing ValueOrRun, and could not achieve by the means I just suggested.)

>Your premise that the compiler and interpreter go together
>is utterly without foundation.

Once again, I think there are some communication problems here. Jesse has
been using the word "interpreter" in a sense that confused me, if no one else.
Here's the structure and vocabulary I envision for an IF design system, just so
you at least know how I'm using the terms:
I. The "Engine": The entire design system and associated programming language.
A. The "Compiler": The executable file which converts source code either
into a game file playable by an interpreter, or into a standalone executable
file).
B. The "Library": A collection of standard code which is added to every game
compiled by the compiler.
C. The "Interpreter": A program whose only function is to read in a
compiled game file and transmit the information within it to the player, in the
manner that the author designed it.

>> And can you define that function at the same point in the
>> code as you call "map"?
>
>I don't understand quite what you're asking here.
Nor I.

From,

BrenBarn

unread,
Sep 7, 1999, 3:00:00 AM9/7/99
to
>> So to implement dynamic property creation, you'd first have to store
>> property names.
>
>It wasn't dynamic property creation he wanted; he was talking
>about compile time, not run time.
There's been a lot of confusion about this (some of it my own). The way
that I interpreted Jesse's statement was that he wanted to be able to define
"automatic" uses for certain properties.
For example, the "description" property has an automatic function: it is
displayed when the object is examined. Likewise, I think Jesse wanted to be
able to define a property X and also define a default behavior for X, so that
every instance of X is used in a certain way.
This is technically not property "creation" (you can do that already), but
rather "property handling creation". And this "handling" is not really
"created" at run-time any more than a normal game object is. (That is, the
handling is not generated by the compiler, but is defined by the game
programmer.)
Of course I may be totally wrong about what Jesse was trying to say, in
which case -- what do you think of the above idea?

Jesse Welton

unread,
Sep 7, 1999, 3:00:00 AM9/7/99
to
In article <37d42a92...@news.bright.net>,

Jonadab the Unsightly One <jon...@bright.net> wrote:
>jwe...@pacific.mps.ohio-state.edu (Jesse Welton) wrote:
>
>> I was told earlier in the thread that Inform uses a library function
>> that encapsulates this functionality. What I'm saying is that this
>> should be handled at the engine level, instead.
>
>Um, the engine shouldn't even KNOW whether a particular property
>of a particular object has a routine in it or a string or a value.

You're talking about the virtual machine; then engine is more than the
virtual machine. Brendan's hit pretty close to the target of what I
think the engine is. The engine roughly consists of all the support
code that's not directly related to the particular objects or kinds of
objects in the game.

For example, Wolf is working on an engine in Python. He's not making
a new VM. It'll use the existing Python VM. He's also doing more
than defining a heirarchy of game object classes like containers,
rooms, chairs, doors, keys, and whatnot, which I don't think of as
part of the engine. He's writing the code that will cycle through
input, processing, and output, with places to call into the
game-specific code. In principle, this could be part of the compiler,
the library, or the VM; to a certain extent, it doesn't matter which.
What matters is that it calls my code according to a particular
interface.

>That's totally a library issue, or possibly a compiler issue.
>But I'd rather have it in the library than in the compiler,
>because then I can override and change its behavior if I want.
>ValueOrRun is *safe*. It checks to see that the object exists
>and has that property before it executes the instructions to
>access it. That's a Good Thing(TM). You could have the
>compiler do that transparently, but I don't see what the
>advantage would be.

The advantage is that the programmer doesn't have to type ValueOrRun
every time the program needs to access the value of a property.
That's not a Good Thing, it's Boring and Tedious. If the equivalent
of ValueOrRun is part of the object protocol of the engine (and this
can be veneer code from the compiler or built into the interpreter; I
don't care), it's every bit as safe as calling it everywhere in the
code. It's even better, really, since it can't accidentally be left
out somewhere.

> Probably nothing that could compare to
>the potential advantage of being able to Replace the library
>function that does it with your own version. Then you can
>create your own extended format for objects and have it
>work, for example...

Creating an extended object format is alot of work. I can't imagine
where you'd want to do it for an IF game, either, assuming the system
provided a sufficiently powerful object system in the first place.
But I can't say that it's a Bad Idea in principle. I'd be glad to
know of a situation in which defining a new object format would be
desireable. In the meantime, I'll grant you that this is a potential
benefit to defining your object interface above the VM level. You
don't necessarily have to sacrifice language features to get it,
though.

>> Why is an engine in which functions have names at too high a level for
>> you?
>
>That's WAY too high a level. You've got the VM knowing where a
>particular table is located that stores the names... that means

Not necessarily the VM. The engine is more than the VM.

>the VM knows what kind of thing (table, routine, ...) is in
>each part of memory. I'd rather have the engine consider
>memory as a chunk of randomly addressable storage space.

OK. Just don't reduce the whole system to that level. Provide a
layer of high-level functionaity on top of that.

>Storing the names of the functions so they can be looked up
>at run time is a compiler issue.

Which means it's still relevant to the question of features we as
programmers might want in our IF system.

>> I'm guessing it's because it would be grossly inefficient to
>> look up all your functions, methods, etc. by name. But in fact, these
>> can still be referenced by address, so you don't lose any runtime
>> efficiency. A symbol table mapping names to addresses will however
>> give you considerably expanded runtime capabilities, for example in
>> the areas I've been discussing here at considerable length, at a small
>> penalty to storage requirements.
>
>It is handy for debugging, but it's a compiler issue. When you
>compile a non-debug release, can you think of any reason to
>have them in there?

Have you paid any attention to what I've been writing at all? I've
given one particular extensive example, and a briefer
debugging-related example or how to use such a feature at runtime.
TenthStone mentioned yet another, using it as a way to develop
matrices (such as one might use for tables of who's talked to whom
about each object). It's hard to foresee all possible uses of any
given feature.

>> Perhaps the word "engine" is catching
>> us up, here. If the interpreter doesn't provide a symbol table (which
>> will convert, say, method names into method ID numbers or whatever
>> low-level implementation method references have), I don't see how the

>> library can do so. At least, not without compiler support (and that


>> still means that the system implementors have to do it, not the
>> library or game author, which ammounts to the same thing).
>
>Why is that the same thing? In the case of Inform, the compiler
>is maintained by the same person as the library, but the interpreters

>are not. Your premise that the compiler and interpreter go together
>is utterly without foundation.

Oh no? I rather suspect that the compiler authors have to target the
same instruction set as the interpreter authors. :)

In any case, my point is that as an IF author, modifying the library
is one thing, and modifying the compiler or interpreter is another
thing entirely. As an IF author, it doesn't matter whether the
language features used in programming are supported by the compiler or
the interpreter. What matters is that the engine, a combination of
interpreter and compiler support code, provides them for me.

>> Can you, in Inform, write a function "map" that takes as argument a
>> list of objects and a function to apply to each argument?
>
>Are you trolling?

What makes you think that? I'm trying to find out about specific
features of Inform, in order to better explain myself to Inform
programmers. Daniel's right on the nose in his response.

>[ CallRoutineOnObjects objecttable routinetorun n i;
> n = objecttable-->0; ! number of entries in the list
> for (i=1:i<=n:i++) indirect(routinetorun objecttable-->i);
>];

There, that takes care of half the question. I should have been
clearer that the result returned should be a list of the results of
each function call.

>> And can you define that function at the same point in the
>> code as you call "map"?
>
>I don't understand quite what you're asking here.

And here you miss the point of half of the question which does wonders
for the routine's usefulness. I gather that you cannot do something
like this:

CallRoutineOnObjects( box.contents [ obj; obj.moveTo(floor); ] )

Of course, this is still a tiny fraction of a complete collection
suite. But as I said (below), I was trying to get at how functions
are treated as data.

>> I'm trying to get at the high-level concept of passing functions
>> around.)
>
>Functions have the same status in Inform as strings or

>dictionary entries or whatever. You can pass [their addresses]
>around arbitrarily.

Correct me if I'm wrong, but I get the impression from what you wrote
above about the VM knowing (or not) what sort of object is stored at
each address that no such type information is available in Inform. If
you have a function address, you can't tell it from an object address,
a string address, or simple numerical data. If that's the case, and
that's the kind of architecture you're advocating, I think that's too
low a level for an IF engine. (Note: not necessarily for the VM.)
It's certainly not the level at which I want to be programming. It
should at least be hard to mistake one type of data for another, even
if you provide low-level hooks into accessing memory at the byte level
when you want it.

-Jesse


Jesse Welton

unread,
Sep 7, 1999, 3:00:00 AM9/7/99
to
In article <19990906223542...@ng-cb1.aol.com>,

BrenBarn <bren...@aol.comRemove> wrote:
>>Um, the engine shouldn't even KNOW whether a particular property
>>of a particular object has a routine in it or a string or a value.
> I think that's what Jesse was saying too. I certainly agree.

I think what Jonadab is saying that that the engine (which he is
taking to be identical to the VM) shouldn't have any access at all to
the type of a given property, it should just be a bit of binary data
to return. I think he intends the same thing to be true of the object
system, which in Inform is implemented above the VM layer. (How one
could not include the object system in the definition "engine", I
don't know.) So when you have "someObject.someProperty", you should
get the data if it's data, or a function pointer if it's a method.

That's the opposite of my position. There are times when it's useful
to access the raw function pointer, such as when you want to pass it
as an argument to a function, or assign it to another property. This,
unfortunately, isn't possible as such in TADS. But by far the more
common case is to want to override a data property with a method, so
in creating a new system I would make that behavior transparent, and
provide functions to access the raw data when needed.

>Here's the structure and vocabulary I envision for an IF design system, just
>so you at least know how I'm using the terms:
>I. The "Engine":

> A. The "Compiler"
> B. The "Library"
> C. The "Interpreter"

I think that's a great way to put it, though I wouldn't include all
library functionality in the "engine". I would, for example, include
any library support for an object system, but not the definitions of
typical game-object classes like doors and food.

-Jesse

Jesse Welton

unread,
Sep 7, 1999, 3:00:00 AM9/7/99
to
In article <37d3ef83...@news.bright.net>,

Jonadab the Unsightly One <jon...@bright.net> wrote:
>mcc...@erols.com (TenthStone) wrote:
>
>> In TADS -- as in Inform, I should think -- property names are
>> meaningless as strings. That is, you can't take a property
>> name like &matrix1 and edit it to get the property name &matrix1_1.
>
>You CAN, I just don't see the point.

That doesn't mean there isn't one. Features like this are used with
fair regularity in languages like Scheme and Smalltalk which provide
them. In Scheme, it's particularly useful in the creation of complex
macros; in Smalltalk, it's particularly useful in the compiler and the
debugger. But it can be used elsewhere, too.

>The automatic property creation he describes is simply TADS'
>way of implementing something.

It can also be used in other ways, such as TenthStone has described
(albeit briefly) here. I mentioned keeping track of conversation
topics as one use of these matrices just moments ago. That certainly
goes beyond TADS's implementation of a particular thing.

>Inform implements this differently.

Yeah, but that's practically irrelevant. The two systems implement a
particular thing differently. Whoop-dee-doo. If we want to discuss
desirable features for a future system (and that could BE an extension
of TADS or Inform), we should recognize that flexible features can be
used flexibly, no? From what I can tell, if I was programming in
Inform, I'd likely still want to extend the parser in a similar way,
because it allows me to make objects more modular by reducing the need
for switch statements and the like.

>But he wants that BECAUSE he wants a general way to have more
>entry points for an object to interfere with any given
>arbitrary verb.

And the key here, of course, is "general". It's a general-purpose way
of specifying a family of related property names dynamically, without
having to laboriously hard-code them into the program.

>It wasn't dynamic property creation he wanted; he was talking
>about compile time, not run time.

Well, many of the benefits could be achieved at compile time, quite
possibly most of the benefits. (I'm still ruminating over those
matrices...) But there are doubtless run-time benefits to be found,
as well.

And it wasn't *property* creation I was talking about at all, really.
Rather, it was dynamic lookup of properties by name. (Hmm, actually,
perhaps that first sentence is wrong; I do pretty much presuppose that
it's possible to add properties to objects at runtime. TADS handles
this as transparently as overriding data properties with methods,
though it's done with property references, not names.)

-Jesse

BrenBarn

unread,
Sep 8, 1999, 3:00:00 AM9/8/99
to
>There are times when it's useful
>to access the raw function pointer, such as when you want to pass it
>as an argument to a function, or assign it to another property. This,
>unfortunately, isn't possible as such in TADS. But by far the more
>common case is to want to override a data property with a method, so
>in creating a new system I would make that behavior transparent, and
>provide functions to access the raw data when needed.
I agree (just like before :-). We can have a special construct to access
a pointer, something like "pointer(Object.Method)".

<snipped my own nomenclature>


>I think that's a great way to put it, though I wouldn't include all
>library functionality in the "engine". I would, for example, include
>any library support for an object system, but not the definitions of
>typical game-object classes like doors and food.

I would not put game-object classes, such as doors and food, in the
library. Instead, I would put the building blocks of those classes (in this
case, the qualities "doorness" and "edibility) in the library, and allow the
user to create classes or not, as he or she sees fit.

wo...@one.net

unread,
Sep 9, 1999, 3:00:00 AM9/9/99
to

Hi Jesse,

>For example, Wolf is working on an engine in Python. He's not making
>a new VM. It'll use the existing Python VM. He's also doing more
>than defining a heirarchy of game object classes like containers,
>rooms, chairs, doors, keys, and whatnot, which I don't think of as
>part of the engine. He's writing the code that will cycle through
>input, processing, and output, with places to call into the
>game-specific code. In principle, this could be part of the compiler,
>the library, or the VM; to a certain extent, it doesn't matter which.
>What matters is that it calls my code according to a particular
>interface.

Just thought I'd butt in here with my own definitions. :)

The PAWS "engine" is roughly equivalent to the TADS runtime system. It
contains the parser, variables to hold function addresses for the
"skeleton" program (before and after turn handlers, the parser, prompt
function, etc), constants (TRUE, FALSE, etc), many utility functions
that aren't otherwise provided by Python (like SCase() to capitalize
sentences, etc), and a few fundamental classes that provide
"plumbing", for example adding nouns and verbs to the parser
dictionaries.

You're correct, the Python runtime is the VM for PAWS, however it's
much more like a BASIC interpreter than a Java VM in that it can
actually parse and compile code at run time.

The library (Universe) is very much like ADV.t or WorldClass in TADS
(I'm using TADS examples since I've forgotten most of the Inform I
learned). The game author rarely needs to reference the game engine
directly (though they can), just as in TADS or Inform they make calls
mostly to library code.

Finally, the "skeleton" program provides the logic cycle for the game
the author writes, it's conceptually part of the engine even though
it's a separate file.

Does that help any or have I just confused issues? :)

>The advantage is that the programmer doesn't have to type ValueOrRun
>every time the program needs to access the value of a property.
>That's not a Good Thing, it's Boring and Tedious. If the equivalent
>of ValueOrRun is part of the object protocol of the engine (and this
>can be veneer code from the compiler or built into the interpreter; I
>don't care), it's every bit as safe as calling it everywhere in the
>code. It's even better, really, since it can't accidentally be left
>out somewhere.

Classic OOP doctrine says that you *never* read or write properties
directly, you always write attribute methods. This quickly gets old,
however. But, having read what I wrote below it seems I agree with it
after all...

Python, like Inform (and unlike TADS) has no way to call a function
with a variable's syntax. One way I get around this problem is with
PAWS equivalent of ValueOrRun(), called Get().

Another way is to always use a method to return a given value. For
instance Location is the property that holds a (fixed) location for an
item, but PAWS usage rules say to always call the Where() method
instead. A simple Where() just returns Location, but a floating object
(for instance) has a more complex Where() that overrides the ancestor
method. Also, you never set Location directly, you always use an
object's MoveInto() method.

But this isn't a hard and fast rule, most of the time it's possible to
keep properties and methods conceptually distinct. For instance, to
find an object's weight you never refer to object.weight (which is the
weight of the object only) instead you either refer to
object.CurrentWeight() (for object weight + contents weight) or
Object.ContentsWeight() (for object contents weight only).

But certain properties are *never* methods, for those it's safe to
read or write them directly, like IsScenery, which is always TRUE or
FALSE, and never a method.

>Creating an extended object format is alot of work. I can't imagine
>where you'd want to do it for an IF game, either, assuming the system
>provided a sufficiently powerful object system in the first place.
>But I can't say that it's a Bad Idea in principle. I'd be glad to
>know of a situation in which defining a new object format would be
>desireable. In the meantime, I'll grant you that this is a potential
>benefit to defining your object interface above the VM level. You
>don't necessarily have to sacrifice language features to get it,
>though.

In Python you'd handle this with optional arguments. That way you can
put the most commonly used parameters in the beginning, and less
commonly used optional parameters afterward.

I had a situation with a disambiguate routine that may or may not have
had an actor. It was simple enough to put Actor as the last function
parameter and then default it to None. In effect, if no actor was
specified the parameter was still assigned a value.

Although easy, this is generally frowned upon as bad programming
practice.

>There, that takes care of half the question. I should have been
>clearer that the result returned should be a list of the results of
>each function call.

Python supports map and apply directly, and also allows lambda
notation if you absolutely *insist*... :)

Respectfully,

Wolf

"The world is my home, it's just that some rooms are draftier than
others". -- Wolf

Kevin Russell

unread,
Sep 9, 1999, 3:00:00 AM9/9/99
to

wo...@one.net wrote:

> Python, like Inform (and unlike TADS) has no way to call a function
> with a variable's syntax. One way I get around this problem is with
> PAWS equivalent of ValueOrRun(), called Get().

Wolf, Wolf, Wolf. You're forgetting Python's __getattr__.

All you, the library writer, have to do is define a __getattr__ function
for one of your high-up classes, like BaseThing. This will catch every
attempt to reference a descendant object's properties, and you can do
all kinds of neat stuff before or instead of dispatching the request in
the usual way.

This is just off the top of my head, so don't quote me if it doesn't
work exactly as advertised:

class BaseThing:
def __getattr__(self, attribute):
if attribute == 'weight':
return self.ComputeTotalWeight()
else:
return self.__dict__[attribute]

The user of the library can then blithely write Ogre3.weight and
get a number back again, without knowing or caring that the
value was computed on the fly rather than being permanently
stored.

This sounds like exactly what the originator of the thread wants.

So the answer to the original question is: "Yes, there's a system
that can do that. Provided you keep bugging Wolf to release PAWS.
:-)"

-- Kevin

Dan Schmidt

unread,
Sep 9, 1999, 3:00:00 AM9/9/99
to
wo...@one.net writes:

| [Someone else wrote:]


|
| >class BaseThing:
| > def __getattr__(self, attribute):
| > if attribute == 'weight':
| > return self.ComputeTotalWeight()
| > else:
| > return self.__dict__[attribute]
| >
| >The user of the library can then blithely write Ogre3.weight and
| >get a number back again, without knowing or caring that the
| >value was computed on the fly rather than being permanently
| >stored.

I don't think this is exactly right. __getattr__ doesn't get called
unless 'attribute' doesn't exist in the object's dictionary. So going
to the dictionary in the else clause seems like a lost cause.

| Good idea, except it's not really generic enough. In TADS for example
| you can (for any arbitrary method/property) write:
|
| Object.Weight
|
| to return weight regardless of whether weight was method or property.
| The problem with __getattr__ is that you have to define each and every
| property/method before hand. That could get cumbersome, especially
| when extending the base class method to handle user defined properties
| so you don't have to go mucking about in the library.
|
| In addition your approach also doesn't allow "weight" to be a property
| in one object and a method in the other.

I think this does what wolf is talking about:

class BaseThing:
def __getattr__(self, attribute):

if (attribute[0:4] == "get_"): raise AttributeError
return apply (getattr (self, "get_" + attribute))

Then I can do the following:

class Thing (BaseThing):
def __init__ (self):
self.x = 3
def get_y (self):
return 4

and voila:

>>> a = Thing()
>>> a.x
3
>>> a.y
4
>>> a.z
Traceback (innermost last):
File "<stdin>", line 1, in ?
File "c:/windows/temp/python--4044613NcI", line 5, in __getattr__
File "c:/windows/temp/python--4044613NcI", line 4, in __getattr__
AttributeError

I'm not claiming this is the best way to do it (there must be a better
way to avoid infinite recursion than the explicit check against "get_"
methods), but hey, it works.

--
Dan Schmidt -> df...@thecia.net, df...@alum.mit.edu
Honest Bob & the http://www2.thecia.net/users/dfan/
Factory-to-Dealer Incentives -> http://www2.thecia.net/users/dfan/hbob/
Gamelan Galak Tika -> http://web.mit.edu/galak-tika/www/

wo...@one.net

unread,
Sep 10, 1999, 3:00:00 AM9/10/99
to

Hi Kevin,

>class BaseThing:
> def __getattr__(self, attribute):
> if attribute == 'weight':
> return self.ComputeTotalWeight()
> else:
> return self.__dict__[attribute]
>
>The user of the library can then blithely write Ogre3.weight and
>get a number back again, without knowing or caring that the
>value was computed on the fly rather than being permanently
>stored.
>

>This sounds like exactly what the originator of the thread wants.

Good idea, except it's not really generic enough. In TADS for example


you can (for any arbitrary method/property) write:

Object.Weight

to return weight regardless of whether weight was method or property.
The problem with __getattr__ is that you have to define each and every
property/method before hand. That could get cumbersome, especially
when extending the base class method to handle user defined properties
so you don't have to go mucking about in the library.

In addition your approach also doesn't allow "weight" to be a property
in one object and a method in the other.

Object.Get("Weight")

isn't quite as syntactically simple as Object.Weight, but it does
allow one object's weight to be a property and the other to be a
method.

>So the answer to the original question is: "Yes, there's a system
>that can do that. Provided you keep bugging Wolf to release PAWS.
>:-)"

PAWS is only about 90% done, Kevin. :) But if anybody wants a copy
feel free to email me for one.

Jonadab the Unsightly One

unread,
Sep 10, 1999, 3:00:00 AM9/10/99
to
bren...@aol.comRemove (BrenBarn) wrote:

> I agree. If I understood Jesse right, he wasn't suggesting that the
> compiler go out and try to grab property values without knowing whether the
> object provides the property or not. He was suggesting that the simple
> expression "apple.weight" should return the value of the apple's property
> "weight", if it is a simple value, or the return value of the "weight" method,

> if it's a method.

There are AFAICT only three ways to implement this:

1. The compiler knows at compile time whether the property
(weight) contains a value or a routine.

2. The runtime engine knows whether the property (weight)
contains a value or a routine.

3. The compiler transparently inserts a certain routine
whenever it encounters this syntax.

1 is evil, because it means you can't assign to a property
at run time, or at least can't assign a value if it previously
stored a routine or vice versa. That's just plain wrong.

2 is almost as bad. Your object format is controlled by
the VM, which means an aweful lot of stuff is hardwired.
Doing anything different from the norm is going to require
a new interpreter.

3 looks better on the face of it, but you still have problems.
For one thing, now you need funky syntax if you want to
reliably assign the value of one object's property to another
object, for example. For another, the expression object.property
has one meaning in one context (say, on the left side of the
assignment operator) and another meaning in another context
(say, within an expression). If your language syntax
resembles C or C++, you're going to confuse the everliving
gumption out of people. (You might get away with this if
your syntax resembles BASIC, as context determines meaning
in BASIC to a greater degree than C.)

> As someone else pointed out, though, this creates inconsistencies.
> Currently, in Inform, the statement "x=apple.weight" assigns to "x" the value
> of "weight" if it's a simple value, but assigns the ADDRESS of the method
> "weight" if it's a method. Admittedly, this is a roadblock, but I think we
> could get around it by using some operator like "pointer", where (assuming
> apple.weight" is a method) "pointer(apple.weight)" returns the address of the
> method, and "apple.weight" returns that method's return value.

In a new system, you could do that, I suppose. (In an existing
system such a change would break all existing code and is thus
entirely out of the question.)

But what's wrong with this syntax: x = apple.weight();
Couldn't that be made to do what is requested? My rationale
is this:

When the weight property of apple is a routine, apple.weight
has an obvious meaning: the routine itself. apple.weight()
is the return value, of course.

But when the weight property of apple is a value,
apple.weight is the value, but what is apple.weight() ?
There's no routine to run. It has no obvious meaning.
So giving it a meaning (the same meaning as apple.weight
in this case) has fewer side effects.

Am I making any sense here, or am I just rambling?

> As far as being able to Replace the control of accessing property values.
> . . I think the compiler should implement that control transparently, but
> provide a hook so that the everyday programmer could add to the functionality.
> (It's not often that anyone will want to PREVENT themselves from accessing a
> property value, which would seem to be the only thing you could achieve by
> Replacing ValueOrRun, and could not achieve by the means I just suggested.)

I can't define at the moment the circumstances under which I'd
want to replace ValueOrRun, but I am stone cold certain such
circumstances could plausibly exist. I've at one time or
another wanted to replace or edit or in some fashion alter
the behavior of many (perhaps a third?) of Inform's library
routines, for one reason or another. Few of the reasons
would have been predictable before the situation arose.
And I haven't written very many games yet, so I'm sure
there are more situations yet to arise.

It's a philosophical point: I want to be able to replace
any routine I want to replace any time I want to replace it.
As little as possible should be hard wired into the VM
or even the compiler. Put as much in the library as can
be put there.

> Once again, I think there are some communication problems here. Jesse has
> been using the word "interpreter" in a sense that confused me, if no one else.

The interpreter is the runtime engine, also called a virtual machine.
Unless your compiler produces a platform-specific binary, you have
an interpreter that is your platform instead.

> Here's the structure and vocabulary I envision for an IF design system, just so
> you at least know how I'm using the terms:

> I. The "Engine": The entire design system and associated programming language.

Oh. I was assuming that "engine" meant "runtime engine". The
language is the language, and the compiler is the compiler.
The library is written in the language and compiled by the
compiler, along with your game, and the result is run by the
engine. All of the above, along with your text editor and
any IDE or debugger or whatnot, is the development system.

I do have a nasty habbit of saying "compiler" when I really
mean "compiler and linker", however. Most of the languages
I've used very much integrate the two so that you really
don't have to concern yourself with the line between them
unless you're linking in pre-compiled libraries (which, with
compile times of 3 seconds, seems rather pointless).
That's a Good Thing, IMO.

> B. The "Library": A collection of standard code which is added to every game
> compiled by the compiler.

Well, not EVERY game, but most.

Jesse Welton

unread,
Sep 10, 1999, 3:00:00 AM9/10/99
to
In article <wk1zc7y...@thecia.net>, Dan Schmidt <df...@thecia.net> wrote:
>
>I don't think this is exactly right. __getattr__ doesn't get called
>unless 'attribute' doesn't exist in the object's dictionary.
>
>| In addition your approach also doesn't allow "weight" to be a property
>| in one object and a method in the other.
>
>I think this does what wolf is talking about:
>
> class BaseThing:
> def __getattr__(self, attribute):
> if (attribute[0:4] == "get_"): raise AttributeError
> return apply (getattr (self, "get_" + attribute))
>
>Then I can [access data and methods with the same syntax]

This doesn't allow you to override a data member with a method, like
this:

class Thing (BaseThing):
def __init__ (self):
self.x = 3

class BigThing(Thing):
def get_x (self):
return 4

Since your Thing will have an x attribute, __getattr__ will not (as
you point out) be called, so it can't redirect to the get_x method
intended to override the x from Thing. So it's not useful in
precisely the situation where we'd want that behavior.

-Jesse

Jesse Welton

unread,
Sep 10, 1999, 3:00:00 AM9/10/99
to
In article <37d87fce...@news.bright.net>,

Jonadab the Unsightly One <jon...@bright.net> wrote:
>
>There are AFAICT only three ways to implement this:
>
>1. The compiler knows at compile time whether the property
> (weight) contains a value or a routine.
>
>2. The runtime engine knows whether the property (weight)
> contains a value or a routine.
>
>3. The compiler transparently inserts a certain routine
> whenever it encounters this syntax.
>
>1 is evil, because it means you can't assign to a property
>at run time, or at least can't assign a value if it previously
>stored a routine or vice versa. That's just plain wrong.

Agreed. IF programming needs to be fluid and dynamic.

>2 is almost as bad. Your object format is controlled by
>the VM, which means an aweful lot of stuff is hardwired.
>Doing anything different from the norm is going to require
>a new interpreter.

One could certainly imagine a game-extensible system of datatypes
known to the interpreter. This is almost certainly more trouble than
it's worth. (3 might well be better.)

But I certainly don't think having a core set of datatypes understood
by the interpreter is a bad thing.

Okay, I have to ask: how does Inform tell the difference between a
method and a data property, anyway? It has to be able to get
ValueOrRun to work somehow.

>3 looks better on the face of it, but you still have problems.
>For one thing, now you need funky syntax if you want to
>reliably assign the value of one object's property to another
>object, for example.

I'd hardly consider something like

object.property := RawGet(object,&method);

to be "funky syntax". In fact, this is normal TADS syntax; there just
isn't any RawGet function to call.

> For another, the expression object.property
>has one meaning in one context (say, on the left side of the
>assignment operator) and another meaning in another context
>(say, within an expression).

Now, I'm all in favor of language consistency, but...

Of course it has a different meaning! This is true in Inform, too.
If a.x is 5, and b.x is 4, a.x = b.x doesn't mean the same thing as
5 = 4. On the left side of the assignment operator, a.x indicates
which field of a to store into, while on the right side it indicates
the value to store there. On the left side, the value is not
retrieved, while it is retrieved on the right side.

The only difference introduced by the proposal is that default value
retrieval be extended to include calling zero-argument methods. It is
a difference of degree, not of kind.

> If your language syntax
>resembles C or C++, you're going to confuse the everliving
>gumption out of people.

I've never heard of anyone having trouble with the behavior of TADS in
this matter.

> (You might get away with this if
>your syntax resembles BASIC, as context determines meaning
>in BASIC to a greater degree than C.)

Ironically, I think you could equally well "get away with it" if your
syntax resembles Smalltalk, where context determines meaning to a
lesser degree than C.

>In a new system, you could do that, I suppose. (In an existing
>system such a change would break all existing code and is thus
>entirely out of the question.)

Isn't that how this discussion started in the first place? Ah, yes,
there it is: One artfulbobATmindspringDOTcom (Albert) kicked it all
off with, "I'm in the process of creating my own IF engine, coded in
C++ and OOD. [...]" I certainly wouldn't demand that Inform change
its evil ways, though I might suggest it as a possible improvement for
the next major version break. (In the case of Inform, I'd definitely
go with implementation #3 above. And since you have access to veneer
code, you could still change the behavior if you wanted, right?)

>But what's wrong with this syntax: x = apple.weight();
>Couldn't that be made to do what is requested?

Yes. [Rationale snipped.]

>Am I making any sense here, or am I just rambling?

Yes, it could definitely be made to do that. It makes sense. I'd say
it's better than ValueOrRun by a longshot. In fact, I daresay it has
a certain conceptual beauty about it (sort of making non-function
objects into self-returning functions), but it still has extra
syntactical overhead (compared to x = apple.weight) in the single most
common case.

>I can't define at the moment the circumstances under which I'd
>want to replace ValueOrRun, but I am stone cold certain such
>circumstances could plausibly exist.

That would probably be associated with some change in the object
format, no?

>The interpreter is the runtime engine, also called a virtual machine.
>Unless your compiler produces a platform-specific binary, you have
>an interpreter that is your platform instead.

Sure, the interpreter is the runtime engine for the language. (Or
should I say "...for the compiled program"?) But I definitely think
it's useful to differentiate this from the IF engine. The runtime
engine executes a loop of looking up bytecode values and dispatching
to code that carries out the operations associated with those
bytecodes, thereby providing the framework with runs the program.
Similarly, the IF engine is the code which provides the framework for
running the IF program, getting user input, dispatching to parser
routines, dispatching to routines defined in the objects. It's the
code that runs the show, the main loop and associated subsidiaries
that fetch info about the particular game and dispatch to code
associated with the game objects.

Someone could very well provide a framework for defining adventures in
C, and although there is no interpreter in the final product, the
support libraries (or at least portions thereof) might quite
reasonably be called an IF engine.

>Oh. I was assuming that "engine" meant "runtime engine". The
>language is the language, and the compiler is the compiler.

There's no need to be snide. The original poster was asking what
features people want in an IF engine. In that context, it's pretty
unreasonable to restrict the definition of "engine" to the virtual
machine. TADS compiled code could be recompiled to z-code, with
appropriate support z-code added. That could be compiled to machine
code. That could be interpreted by a hardware emulator, or recompiled
to machine code for another platform, or recompiled to Touring Machine
code. So what features does the runtime engine require? Let's
see... Could it be text input, text output, and a Touring-complete
instruction set? But now I'm being snide.

The point is that there are many levels on which a program can be
interpretted. The actual compiled bytecodes is but one of them.
Another is the conceptual space in which the program runs, in which by
and large it doesn't matter for instance whether the object system is
primitive or part of the library. So the relevant question is, what
features are available to the IF programmer that are particularly
suited to programming IF? In that context, it's obvious to me that we
should interpret "IF engine" in a broader sense than just the bytecode
interpreter.

-Jesse

Andrew Plotkin

unread,
Sep 10, 1999, 3:00:00 AM9/10/99
to
Jesse Welton <jwe...@pacific.mps.ohio-state.edu> wrote:
> But I certainly don't think having a core set of datatypes understood
> by the interpreter is a bad thing.
>
> Okay, I have to ask: how does Inform tell the difference between a
> method and a data property, anyway? It has to be able to get
> ValueOrRun to work somehow.

You're not gonna like it...

If the value is less than 256, it's considered a data value. Otherwise,
it's considered a string or function. This work "well enough", but it can
obviously fail (in both directions.)

(Inform *can* reliably distinguish strings from functions, since it knows
where it puts them in memory.)

When Z-machine successors were being debated, this was the biggest point
of argument. How do you distinguish numeric values from object values?
("Object" in this case meaning any kind of referenced thing, including
game objects, strings, functions, dict words, etc.)

I solved the problem by ignoring it. Glulx has no way to distinguish, just
like the Z-machine, and the Glulx Inform library's ValueOrRun function
uses the same "good enough" hack.

This *doesn't* mean that I think it's an unimportant problem. However, I
didn't see any way to solve it while still being compatible with the
Inform language. If you wanted a Glulx-based IF engine with strong typing,
you could easily invent a new "integer object", a wrapper around a
machine-native integer, and use *those* in properties. (Java takes this
approach; there are plain integers and there are Integer objects.)

Such a system would require support in the compiler and in the library,
but the VM wouldn't know or care about it.

--Z

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

John Elliott

unread,
Sep 10, 1999, 3:00:00 AM9/10/99
to
jon...@bright.net (Jonadab the Unsightly One) wrote:
>3. The compiler transparently inserts a certain routine
> whenever it encounters this syntax.

This sounds rather like a certain Microsoft C extension -
"__declspec(property)". I haven't got the exact syntax on me but it's
something like:

__declspec(property, get=GetX, put=PutX) int x;

and then the compiler transparently replaces "y = obj.x" with "y =
obj.GetX()" and "obj.x = y" with "obj.PutX(y)".

If you had a compiler do that for every property on every object, then
you would get massive bloat. But you would also have a system where you
could override a numberic property with a function.

------------- http://www.seasip.demon.co.uk/index.html --------------------
John Elliott |BLOODNOK: "But why have you got such a long face?"
|SEAGOON: "Heavy dentures, Sir!" - The Goon Show
:-------------------------------------------------------------------------)

BrenBarn

unread,
Sep 11, 1999, 3:00:00 AM9/11/99
to
>3. The compiler transparently inserts a certain routine
> whenever it encounters this syntax [the "apple.weight"].
<snip>
This is what I would suggest

.
>3 looks better on the face of it, but you still have problems.
>For one thing, now you need funky syntax if you want to
>reliably assign the value of one object's property to another
>object, for example.
See below.

>But what's wrong with this syntax: x = apple.weight();
>Couldn't that be made to do what is requested? My rationale
>is this:

I don't see how "apple.weight()" is different from the
"pointer(apple.weight)" idea that I suggested. It seems like a different
nomenclature for the same thing.

>I can't define at the moment the circumstances under which I'd
>want to replace ValueOrRun, but I am stone cold certain such
>circumstances could plausibly exist. I've at one time or
>another wanted to replace or edit or in some fashion alter
>the behavior of many (perhaps a third?) of Inform's library
>routines, for one reason or another. Few of the reasons
>would have been predictable before the situation arose.
>And I haven't written very many games yet, so I'm sure
>there are more situations yet to arise.

Ideally, you would still be able to replace it, but it (or whatever you
replaced it with) would be automatically called at every reference to a
property value. I'm not sure if this is possible. Can you define a "built-in"
routine like that in the library, but define the handling for it in the
compiler?

>Oh. I was assuming that "engine" meant "runtime engine".

I think this points up the communications issues we're having here. It's
not that one word is better than another, it's just that we need to know what
other people are hearing when we say something. (Out of curiosity, what do you
call what I call the "engine"?)

>The
>language is the language, and the compiler is the compiler.

Thank you for clarifying this. :-)

>I do have a nasty habbit of saying "compiler" when I really
>mean "compiler and linker", however. Most of the languages
>I've used very much integrate the two so that you really
>don't have to concern yourself with the line between them

<snip>
I agree that this distinction is mostly immaterial.


>> B. The "Library": A collection of standard code which is added to every
>game
>> compiled by the compiler.
>
>Well, not EVERY game, but most.

I'm not sure about that. It seems to me like the library should be
included in EVERY game. If you want to replace routines, you can, but the
library code goes in along with the rest.

BrenBarn

unread,
Sep 11, 1999, 3:00:00 AM9/11/99
to
Since no one replied to my new thread, I'll humbly come back to this one.
. .
It looks like we're making a lot of progress here. We've got a lot of
ideas on what this new engine should do, and we've largely moved away from the
Inform-vs.-TADS stuff.
The original post on this thread was a call for FEATURES requests, but it
now seems like this is becoming more of a general discussion of the entire
architecture of an IF engine. (And that's a good thing, in my opinion.)
It seems like what we need most is the clear statement of ideas. It's
much easier to discuss something when you know what you're discussing. Part of
the confusion in the past has been due to the nomenclature differences, but
another part has been due to the fact that, because we're talking about a NEW
engine here, people have been putting out specific ideas without knowing how
the underlying structure is going to be.
Any thoughts on this? Do you think we should just keep the discussion in
the realm of surface-level features? Or should we really consider a new
architecture for this new engine? And if so, shouldn't we start building from
the ground up?

L. Ross Raszewski

unread,
Sep 11, 1999, 3:00:00 AM9/11/99
to
On 11 Sep 1999 00:24:50 GMT, BrenBarn <bren...@aol.comRemove> wrote:
>>> B. The "Library": A collection of standard code which is added to every
>>game
>>> compiled by the compiler.
>>
>>Well, not EVERY game, but most.
> I'm not sure about that. It seems to me like the library should be
>included in EVERY game. If you want to replace routines, you can, but the
>library code goes in along with the rest.
>

Um, if you're talking about, say, inform, then no. In an ideal world, well,
STILL no. If I'm not writing IF, I don't want inform's standard library
in my zcode file. Even if you believe that zcode should never be used
for anything but IF, permanantly installing the library prevents you
from using an alternative library. The library is not included in
Zball, Paint and Corners, or InvaderZ.

Andrew Plotkin

unread,
Sep 11, 1999, 3:00:00 AM9/11/99
to
L. Ross Raszewski <lrasz...@loyola.edu> wrote:
>> I'm not sure about that. It seems to me like the library should be
>>included in EVERY game. If you want to replace routines, you can, but the
>>library code goes in along with the rest.
>>
>
> Um, if you're talking about, say, inform, then no. In an ideal world, well,
> STILL no. If I'm not writing IF, I don't want inform's standard library
> in my zcode file. Even if you believe that zcode should never be used
> for anything but IF, permanantly installing the library prevents you
> from using an alternative library. The library is not included in
> Zball, Paint and Corners, or InvaderZ.

Or "The Space Under The Window", to name a game which is more or less IF.
I copied in a couple of routines, but most of the library is missing.

The Inform compiler is even pretty good about leaving out veneer routines,
when they aren't necessary.

BrenBarn

unread,
Sep 11, 1999, 3:00:00 AM9/11/99
to
>If I'm not writing IF, I don't want inform's standard library
>in my zcode file. Even if you believe that zcode should never be used
>for anything but IF, permanantly installing the library prevents you
>from using an alternative library. The library is not included in
>Zball, Paint and Corners, or InvaderZ.
Gotcha. I was assuming that we were referring to IF (and I failed to
specify this assumption). Clearly, non-IF games will require non-IF libraries.

Gareth Rees

unread,
Sep 13, 1999, 3:00:00 AM9/13/99
to
Andrew Plotkin wrote:
> This *doesn't* mean that I think it's an unimportant problem. However,
> I didn't see any way to solve it while still being compatible with the
> Inform language. If you wanted a Glulx-based IF engine with strong
> typing, you could easily invent a new "integer object", a wrapper
> around a machine-native integer, and use *those* in properties. (Java
> takes this approach; there are plain integers and there are Integer
> objects.)
>
> Such a system would require support in the compiler and in the
> library, but the VM wouldn't know or care about it.

An alternative approach (again requiring compiler and library support
but not affecting the VM) that's better than the Java approach is to use
tagged data values. The lowest two or three bits of each word of data
are a tag giving information about the type of (the remainder of) that
value.

--
Gareth Rees

Ross Presser

unread,
Sep 13, 1999, 3:00:00 AM9/13/99
to
alt.distingui...@aol.comRemove (BrenBarn).wrote.posted.offered:

>>If I'm not writing IF, I don't want inform's standard library
>>in my zcode file. Even if you believe that zcode should never be used
>>for anything but IF, permanantly installing the library prevents you
>>from using an alternative library. The library is not included in
>>Zball, Paint and Corners, or InvaderZ.
> Gotcha. I was assuming that we were referring to IF (and I failed
> to
>specify this assumption). Clearly, non-IF games will require non-IF
>libraries.
>

More than that is being said. Any good runtime library will include
many, many routines, not nearly all of which will be used in a typical
game. A good system (whether for IF or not for IF) will include only the
routines that are actually needed. You don't need, for example, a help
menu system if your game provides no help. Likewise, an ASK/TELL system,
a sound propagation system, a realtime events system, or whatever. Yet
all of these are useful enough to many games, to warrant encapsulation
and inclusion in a library.

--
Ross Presser
ross_p...@imtek.com


Jesse Welton

unread,
Sep 13, 1999, 3:00:00 AM9/13/99
to
In article <siso4ih...@cre.canon.co.uk>,
Gareth Rees <gar...@cre.canon.co.uk> wrote:
[On marking the types of objects in memory]

>An alternative approach (again requiring compiler and library support
>but not affecting the VM) that's better than the Java approach is to use
>tagged data values. The lowest two or three bits of each word of data
>are a tag giving information about the type of (the remainder of) that
>value.

This seems to get back to my question (to Jonadab) about why someone
would want to change the low-level object format used by the game. I
can certainly appreciate the advantage of being able to do this above
the VM level. However, there is a disadvantage to it as well, if you
ever want the VM to help you with memory management.

IF may not by quite as much in need of automatic memory management as
many other application areas, because IF objects can mostly be
statically allocated. But the requirement of manual memory management
holds back the use of dynamic objects (where they're available at all)
in challenging new ways.

Now, if you're going to have an automatic memory management system
freeing storage that's no longer needed, it needs to understand the
object format. So you can either implement it in the VM, or above the
VM. If you implement it in the VM, it can be much more efficient, but
the VM needs an understanding of some fundamental data types. If you
implement it above the VM, it's fully customizable, but it will be far
less efficient, and each game file has to lug it around. There's
always a trade-off.

-Jesse

BrenBarn

unread,
Sep 14, 1999, 3:00:00 AM9/14/99
to
>Any good runtime library will include
>many, many routines, not nearly all of which will be used in a typical
>game. A good system (whether for IF or not for IF) will include only the
>routines that are actually needed. You don't need, for example, a help
>menu system if your game provides no help. Likewise, an ASK/TELL system,
>a sound propagation system, a realtime events system, or whatever. Yet
>all of these are useful enough to many games, to warrant encapsulation
>and inclusion in a library.
I agree. Some time ago I suggested that perhaps there could be two
libraries. But you still have to draw the line somewhere. Since this is,
after all, a discussion of an IF engine, I think it wouldn't be out of line to
propose the following division of the library:
Library A - Routines and objects that affect the actual mechanics of game
play. (For example, in Inform this would include the parser and its associated
routines, and routines like MoveFloatingObjects.)
Library B - Routines and objects that are convenient for most games. This
would include definitions of standard game properties -- edible, openable, etc.
-- or a standard hierarchy of object classes, depending on how you want to
implement it.

Ross Presser

unread,
Sep 14, 1999, 3:00:00 AM9/14/99
to
alt.distingui...@aol.comRemove (BrenBarn).wrote.posted.offered:

> I agree. Some time ago I suggested that perhaps there could be two
>libraries. But you still have to draw the line somewhere. Since this
>is, after all, a discussion of an IF engine, I think it wouldn't be out
>of line to propose the following division of the library:
> Library A - Routines and objects that affect the actual mechanics of
>game play. (For example, in Inform this would include the parser and
>its associated routines, and routines like MoveFloatingObjects.)
> Library B - Routines and objects that are convenient for most games.
> This would include definitions of standard game properties -- edible,
>openable, etc. -- or a standard hierarchy of object classes, depending
>on how you want to implement it.
>

You're missing my point. You can mush the libraries together if you want;
you can put every damn thing anyone ever thinks of in one big honking
library. But the if the development side of the system is done correctly,
the FINISHED GAME will omit every routine that is not actually called.

Libraries are not Big Blocks Of Stuff That The Game Includes. They are
repositories for useful routines, and the assembled game only includes what
it actually needs.

Jesse Welton

unread,
Sep 14, 1999, 3:00:00 AM9/14/99
to
In article <8E41753A...@10.4.0.21>,

Ross Presser <ross_p...@NOSPAMimtek.com.invalid> wrote:
>
>You're missing my point. You can mush the libraries together if you want;
>you can put every damn thing anyone ever thinks of in one big honking
>library. But the if the development side of the system is done correctly,
>the FINISHED GAME will omit every routine that is not actually called.

This is a great idea. This is essentially like performing a full
garbage collection right at the end of compilation. I am a bit
concerned about the extent to which this can be carried out in some
cases, though. For instance, with a low-level VM which allows
arbitrary pointer manipulations, it would be extraordinarily easy to
make the question of what parts of the library are used by the game
undecidable. So there's yet another reason to impose some discipline
on the memory model and how it's accessed by the program.

-Jesse

BrenBarn

unread,
Sep 15, 1999, 3:00:00 AM9/15/99
to
>You're missing my point. You can mush the libraries together if you want;
>you can put every damn thing anyone ever thinks of in one big honking
>library. But the if the development side of the system is done correctly,
>the FINISHED GAME will omit every routine that is not actually called.
>
>Libraries are not Big Blocks Of Stuff That The Game Includes. They are
>repositories for useful routines, and the assembled game only includes what
>it actually needs.
This would indeed be ideal, and should be the ultimate goal in the
designing of a library for a new IF engine.

Ross Presser

unread,
Sep 15, 1999, 3:00:00 AM9/15/99
to
alt.distingu...@pacific.mps.ohio-state.edu (Jesse
Welton).wrote.posted.offered:

>In article <8E41753A...@10.4.0.21>,
>Ross Presser <ross_p...@NOSPAMimtek.com.invalid> wrote:
>>

>>You're missing my point. You can mush the libraries together if you
>>want; you can put every damn thing anyone ever thinks of in one big
>>honking library. But the if the development side of the system is done
>>correctly, the FINISHED GAME will omit every routine that is not
>>actually called.
>

>This is a great idea. This is essentially like performing a full
>garbage collection right at the end of compilation. I am a bit
>concerned about the extent to which this can be carried out in some
>cases, though. For instance, with a low-level VM which allows
>arbitrary pointer manipulations, it would be extraordinarily easy to
>make the question of what parts of the library are used by the game
>undecidable. So there's yet another reason to impose some discipline
>on the memory model and how it's accessed by the program.
>

You mean ... gulp ... the system used for decades for linking C programs,
IS NOT USED BY INFORM OR TADS?

Ack.

C allows arbitrary pointer manipulations. It's up to the programmer to
make sure he doesn't call unlawful routines. The compiler can decide
from the syntax used ("was printf() declared?") whether a function needs
to be pulled in from the library. --
Ross Presser
ross_p...@imtek.com


Fraser Wilson

unread,
Sep 15, 1999, 3:00:00 AM9/15/99
to
paene lacrimavi postquam Ross Presser scripsit:

>You mean ... gulp ... the system used for decades for linking C programs,
>IS NOT USED BY INFORM OR TADS?

Weeeeeell ... the system you're talking about pulls things in on
the object file level, which isn't exactly the same as doing it
on a purely as-needed basis.

>C allows arbitrary pointer manipulations. It's up to the programmer to
>make sure he doesn't call unlawful routines. The compiler can decide
>from the syntax used ("was printf() declared?") whether a function needs
>to be pulled in from the library. --

That's not strictly true. The portion of libc that contains printf
is pulled in if the symbol "_printf" is mentioned anywhere. This is
not the same thing as declaring it.

Yours in utter pedantry,
Fraser.

David Glasser

unread,
Sep 15, 1999, 3:00:00 AM9/15/99
to
Ross Presser <ross_p...@NOSPAMimtek.com.invalid> wrote:

> You mean ... gulp ... the system used for decades for linking C programs,
> IS NOT USED BY INFORM OR TADS?

Well, there are some differences, the main one being that Inform and
TADS (and so on) don't allow separate compilation or dynamicly loaded
libraries. (Precompiled headers have nothing to do with that.) So
linking is much more simple.

Granted, this has nothing to do with the exclusion of unneeded routines
and in fact should make it simpler. (In TADS' defense, one doesn't
usually make too many functions that aren't object methods.)

--
David Glasser | gla...@iname.com | http://www.davidglasser.net/
rec.arts.int-fiction FAQ: http://www.davidglasser.net/raiffaq/
"So what's the story with Tetris? Block meets block, block loses block,
block meets another block?" --Russ Williams

Ross Presser

unread,
Sep 16, 1999, 3:00:00 AM9/16/99
to
alt.distingu...@iname.com (David Glasser).wrote.posted.offered:

>Ross Presser <ross_p...@NOSPAMimtek.com.invalid> wrote:
>
>> You mean ... gulp ... the system used for decades for linking C
>> programs, IS NOT USED BY INFORM OR TADS?
>
>Well, there are some differences, the main one being that Inform and
>TADS (and so on) don't allow separate compilation or dynamicly loaded
>libraries. (Precompiled headers have nothing to do with that.) So
>linking is much more simple.
>
>Granted, this has nothing to do with the exclusion of unneeded routines
>and in fact should make it simpler. (In TADS' defense, one doesn't
>usually make too many functions that aren't object methods.)
>

I can see I'm in over my depth again....
--
Ross "open mouth, insert foot" Presser
ross_p...@imtek.com


David Glasser

unread,
Sep 17, 1999, 3:00:00 AM9/17/99
to
Ross Presser <ross_p...@NOSPAMimtek.com.invalid> wrote:

Either that, or I'm saying things that I have no clue about. (I'm not
sure.)

Basically, when doing Inform, Hugo, or TADS, one does COMPIILE
<SOURCEFILE >GAMEFILE. With C, one does (figuratively) COMPILE <SOURCE
>OBJECT; COMPILE <SOURCE2 >OBJECT2; LINK <OBJECT <OBJECT2 >PROGRAM. In
Inform/Hugo/TADS, the compiler sees everything in one execution, whereas
the linker is often a separate program from the compiler in C and so
header files are only interfaces, not the real code. (The main
advantage of this is that linking is pretty fast and so you don't have
to recompile all your .c files.)

(Inform, Hugo, and TADS all let you compile files and then include them
in compiled form in another file, but this is slightly different as the
I/H/T compiler still makes the output based on the source.)

(However, none of this presents a reason for not dropping unneeded
functions, and in fact makes that easier. Hugo does do this (though it
doesn't drop functions from precompiled headers); I don't know about the
other two but I'd guess that TADS does and Inform doesn't, just because
that would be a very non-Informy thing to do.)

(And as I said, you usually have only a handful of standalone routines
in TADS.)

tr/y/k;

Curt Siffert

unread,
Sep 19, 1999, 3:00:00 AM9/19/99
to
David, your response has more parenthetical content than
real content. Isn't there some Usenet netiquette rule
against that? :-)

Curt

gla...@iname.com (David Glasser) sayeth:

Ross Presser

unread,
Sep 21, 1999, 3:00:00 AM9/21/99
to
alt.distingu...@iname.com (David Glasser).wrote.posted.offered:

[snip to the relevant bit]

>In Inform/Hugo/TADS, the compiler sees everything in one execution,
>whereas the linker is often a separate program from the compiler in C
>and so header files are only interfaces, not the real code. (The main
>advantage of this is that linking is pretty fast and so you don't have
>to recompile all your .c files.)

This is the part I didn't quite grasp before, that there is usually no
separate compilation with IF languages. Thanks for improving my
knowledge.

--
Ross Presser
ross_p...@imtek.com


0 new messages