Newsgroups: rec.arts.int-fiction
Path: gmd.de!xlink.net!howland.reston.ans.net!noc.near.net!news.cs.brandeis.edu!binah.cc.brandeis.edu!EVANS
From: evans@binah.cc.brandeis.edu (Ron Hale-Evans)
Subject: Goal-oriented behavior in TADS (LONG)
Message-ID: <1993Jun14.182700.3151@news.cs.brandeis.edu>
Sender: news@news.cs.brandeis.edu (USENET News System)
Reply-To: evans@binah.cc.brandeis.edu
Organization: Brandeis University
Date: Mon, 14 Jun 1993 18:27:00 GMT
Lines: 228

Hello, Sailor!

This is my first real post to rec.arts.int-fiction. I'm a registered
and devoted TADS user who has been working on his own text game for
about two months. The game is called "Mad Venture," and is belongs to
the genre of what I call "interactive autobiography." It details my
own experiences with schizophrenia. I will be more than happy to post
details of the implementation as it develops. I've hesitated to post
so long because I really wanted to have something to contribute before
I posted. Now (I hope) I do.

In this article I will briefly show how to implement goal-oriented
behavior in TADS. Rather than redefine "goal-oriented behavior" I will
quote David Graves's excellent paper, "Second Generation Adventure
Games." (For information on how to obtain this and other papers of Mr.
Graves, consult the r.a.i-f FAQ.) NOTE: I am posting this snippet
without Mr. Graves's permission, but since he makes his articles
freely available, I thought it would be OK to treat them as net text a
la Usenet articles. Sorry if this assumption is unwarranted or
offensive.

BEGIN QUOTE:

GOALS AND SUB-GOALS

  A standard feature in many adventure  games  is  the  requirement
  that  the  player  remember  long  sequences of actions in minute
  detail and type  these  sequences  when  needed.   Forgetting  to
  perform  one  of  the  steps  in  a  sequence results in an error
  message.  For example, if the player sees a bottle of beer on the
  table  and  says  "Drink  the beer," he is likely to get an error
  message like "You aren't holding the beer"  or  "The  beer  isn't
  open".  Memorizing detailed sequences of instructions is not what
  most people would call fun.  Wouldn't it be  much  nicer  if  the
  computer could just "understand" the player's intent?

  It turns out that it is relatively easy to create a system  where
  the  programmer  defines  a  corrective action for such an error,
  instead of giving an error message.  By defining the prerequisite
  state  attributes  for  any  action, the system can automatically
  break a goal into sub-goals.  Thus, when the Drink routine  finds
  that  the  player is not holding the beer, a new sub-goal is set:
  get the beer.  Upon resolving that sub-goal, the Drink routine is
  re-entered.   It then checks to see if this container is open and
  if not, it sets a new goal:  open the container.  In the end  the
  player  is  told of how all these events proceeded with a message
  like:  "You take the beer from the table, open it, and drink from
  it".

  Filling in the implied prerequisite actions is a simple  form  of
  planning,  called  backwards  chaining.   Any  new  goals must be
  stored on a stack rather than in a static  structure,  since  any
  goal  can  create  new  sub-goals, which may create others.  Each
  goal must be resolved in order, the latest goal first.  The  game
  program  simply attempts the action on the top of the stack, pops
  it off if successful, or pushes new sub-goals if needed.   It  is
  important to note that only errors concerning variable attributes
  are correctable.  Errors caused by conflicts in fixed  attributes
  (such  as  attempting to set fire to a stone) are not correctable
  by creating a new sub-goal.  If a non-correctable  error  occurs,
  the player is informed and his goal stack is cleared.

  Note  that  once  all  of  the  verb  routine  have   all   their
  prerequisite states defined as sub-goals, it becomes very easy to
  simulate intelligent behavior by other actors in the story.   For
  example, if the player asks another character to "Go out, get the
  rope and return,"  the  character  appears  to  make  intelligent
  decisions  like  opening  the door before attempting to exit, and
  untying the rope from a tree before attempting to walk away  with
  it.  The pace of the game remains brisk since the player need not
  specify  each  detailed  step  in  a   process.    The   software
  "understands" what is implied by the player.

END QUOTE.

To demonstrate an easy way to implement goal-oriented behaviour in
TADS, I am including a little "adventure" written under TADS 2.1. If
you have TADS 2.1 and strip the code out of this message, you should
be able to run it as-is. Note that this code will not run under
versions of TADS lower than 2.1 because of my use of the "modify"
command.

What this code does, in a nutshell, is modify the "fooditem" class so
that any adventure using the code will treat food a little more
intelligently, to wit: when you give the command EAT SANDWICH (or
whatever), TADS will not respond with a message to the effect that you
don't have the sandwich, but will GET the sandwich for you, then EAT
it. Of course, this can be extended to other actors as well, as Mr.
Graves points out, so that they will seem to behave intelligently too.
With a little skull sweat, goal orientation can be made more general.

(TO MICHAEL J. ROBERTS: Mike, in the documentation to the TADS
package, you call for adventure authors to contribute code
improvements to future versions of adv.t. Are you at all interested in
including whatever I come up with?)

Before I include the code, here's a sample session with the game:

**********************************************

A TADS Adventure
Developed with TADS, the Text Adventure Development System.
Your room
   You are stuck in a room.  Good luck, chump.
   You see a Cheez(tm) sandwich, a dill pickle, a pancake, a
McIntosh apple, some lutefisk, and a Macintosh computer
here.

>look at sandwich
It's a Cheez(tm) sandwich, which, as we know, is better than
eternal life, because nothing is better than eternal life
and a Cheez(tm) sandwich is better than nothing.

>eat macintosh
The Macintosh computer doesn't appear appetizing.

>eat mcintosh
Taken.  That was delicious!

>eat sandwich
Taken.  That was delicious!

>eat pancake
Taken.  That was delicious!

>quit
In a total of 5 turns, you have achieved a score of 0 points
out of a possible 100.

Do you really want to quit?  (YES or NO) >y


*******************************

And now... the album of the soundtrack of the trailer of the film of
the snippet of the code of... testGoals.t !!!

*** cut here ***

/*
 * testGoals.t
 * by Ron Hale-Evans
 * a boring li'l adventure to demonstrate goal-oriented behavior in TADS
 * this file requires TADS >= 2.1
 *
 * Prototyped by the TADS Template Stack v0.9 -- 1993 by Jared L. Reisinger
 *
 * File: Severian:TADS Template:testGoals.t
 * Date: Monday, June 14, 1993
 * Time: 12:50:18 PM
 *
 */

#include <adv.t>
#include <std.t>

modify fooditem
	doEat(actor) =
	{
		if (self.location <> actor)
			self.doTake(actor);
		pass doEat;
	}
;

startroom: room
  sdesc = "Your room"
  ldesc = "You are stuck in a room. Good luck, chump."
;

sandwich: fooditem
  sdesc    = "Cheez(tm) sandwich"
  ldesc = "It's a Cheez(tm) sandwich, which, as we know, is better than
  	   eternal life, because nothing is better than eternal life
           and a Cheez(tm) sandwich is better than nothing."
  noun     = 'sandwich'
  adjective = 'cheez' 'cheez(tm)' '(tm)'
  location = startroom
;

pickle: fooditem
  sdesc    = "dill pickle"
  ldesc = "It's the extra-crunchy, half-sour kosher kind."
  noun     = 'pickle'
  adjective = 'dill' 'kosher' 'crunchy' 'extra' 'extra-crunchy'
  	      'half' 'sour' 'half-sour'
  location = startroom
;

pancake: fooditem
  sdesc    = "pancake"
  ldesc = "Yum! It's a delicious blueberry flapjack!"
  noun     = 'pancake' 'flapjack'
  adjective = 'blueberry'
  location = startroom
;

apple: fooditem
  sdesc    = "McIntosh apple"
  ldesc = "It's a McIntosh, not to be confused with a Macintosh."
  noun     = 'apple' 'mcintosh'
  adjective = 'mcintosh'
  location = startroom
;

lutefisk: fooditem
  sdesc    = "lutefisk"
  adesc = "some lutefisk"
  ldesc = "Yuk. It's *lutefisk*!"
  noun     = 'lutefisk'
  location = startroom
;

macintosh: item
	sdesc = "Macintosh computer"
	ldesc = "It's a Macintosh, not to be confused with a McIntosh."
	noun = 'mac' 'macintosh' 'computer'
	adjective = 'macintosh'
	location = startroom
;

*** cut here ***

That's all, folx. Let me know if you have any new ideas.

"The Sea refuses no river; remember that when a beggar buys a round."
  --Pete Townshend  * * * * *  Ron Hale-Evans evans@binah.cc.brandeis.edu
PGP 2 public key: finger evans@binah.cc.brandeis.edu
