|
Once
you have named the types, you then name the attributes and
relationships objects can have. Attributes are tuples of up-to-5, where
there can be any number of “selector arguments” but only one “value
argument”. That is, attributes are mutually exclusive. For example,
objects of type vehicle might have an attribute fuel-level, which can
be a specific number, but only one number at a time. Relationships are
like attributes, but are not mutually exclusive. A human might have a
relationship of loves, and can love any number of people or things at
the same time.
Attributes and relationships are
propositional data that gets stored in a world database. You assert and
retract facts in this database to describe the current world and how it
evolves over time (or in lookahead). Some of these facts match facts of
the game engine itself, so you can reason about a world that is not
pretend.
Attributes are defined by a name, and an
argument list. The only essential things in the argument list are the
type and order of arguments. The names supplied are there only to act
as documentation for the user.
ATTRIBUTE holding( what)
ATTRIBUTE status( who state)
The
zookeeper’s hands are represented by attribute holding (he can only
hold one animal or nothing at a time). Each animal can exist in a
single state at a time.
The basic actions
available in the world are called ACTs and can be predeclared as they
are here. Eventually you have to supply the code for them or link them
up to game engine routines. is the predefined supertype
over all types.
ACT intercept( who what)
ACT pickup(what)
ACT putincage( where)
ACT Intercept( where)
ACT stake( who)
Once
you have acts, you can write plan pieces. A plan is a name, an IF
section (consisting of anding all its clauses) and a THEN clause
consisting of ACTS and or PLANS to be executed in order.
Below
is a quick rendition of a way to save animals that depends primarily on
automatic lookahead to find the order in which to save them. The plan
only goes to an animal, picks him up, goes to a cage and then dumps him
in the cage. It does not look at staking an animal, or carrying one
around and placing it down on the ground elsewhere.
Plans
can call functions that return values, including making queries upon
the built-in database system. Whenever you use a ?variable, it means
you are seeking an answer to be bound to that variable. A function like
FINDLOW will iterate over the set of possible answers to its query
(here it iterates over the set of animal objects) and perform the AND
of all the tests in brackets. So SaveAnimals looks at each animal and
first asks the database using the Attribute Status, whether the animal
is free or not. If not the find fails and goes on to the next instance.
If the animal is free, the FINDLOW calls a function ObjectDistance,
which computes how far the animal is from the zookeeper and binds that
onto ?dist. FINDLOW is a filter that will return the animal (?what)
with the lowest distance (?dist). It is also backtrackable, so if the
plan later fails, it can try again with the second closest animal, etc.
Taking a cue from the design of ICE, HIPE supports events and filtered waiting for some event/argument combination to happen.
EVENT Arrived(from,to)
Event Escaped( who )
In Zookeeper the interesting events are Arrived, You can’t do much about Escaped.
The
following code illustrates acts that are defined in this example, but
there is no point in going into tremendous detail about what they do.
Infer it from context and comments.
In
addition to the basic translator/runtime package, there was also a
source-level debugger. Debugging something running through the loop of
an interpreter is a big pain if you haven’t got source-level debugging.
|