#charset "us-ascii"
/*
* Copyright (c) 1999, 2002 by Michael J. Roberts. Permission is granted
* to anyone to copy and use this file for any purpose.
*
* This is a starter TADS 3 source file. This is a complete TADS game
* that you can compile and run.
*
* To compile this game in TADS Workbench, open the "Build" menu and
* select "Compile for Debugging." To run the game, after compiling it,
* open the "Debug" menu and select "Go."
*
* This is the "advanced" starter game - it has only the minimum set of
* definitions needed for a working game. If you would like some more
* examples, create a new game, and choose the "introductory" version when
* asked for the type of starter game to create.
*/
/*
* Include the main header for the standard TADS 3 adventure library. Note
* that this does NOT include the entire source code for the library; this
* merely includes some definitions for our use here. The main library
* must be "linked" into the finished program by including the file
* "adv3.tl" in the list of modules specified when compiling. In TADS
* Workbench, simply include adv3.tl in the "Source Files" section of the
* project.
*
* Also include the US English definitions, since this game is written in
* English.
*/
#include
#include
/*
* Our game credits and version information. This object isn't required
* by the system, but our GameInfo initialization above needs this for
* some of its information.
*
* IMPORTANT - You should customize some of the text below, as marked: the
* name of your game, your byline, and so on.
*/
versionInfo: GameID
IFID = '573a8b18-1008-ca66-9580-9a156f82eefa '
name = 'The Further Adventures of Heidi'
byline = 'by An Author'
htmlByline = 'by
ERIC EVE'
version = '3.0.16'
authorEmail = 'ERIC EVE '
desc = 'This is an unexciting tutorial game based loosely on
The Adventures of Heidi by Roger Firth and Sonja Kesserich.'
htmlDesc = 'This is an unexciting tutorial game based loosely on
The Adventures of Heidi by Roger Firth and Sonja Kesserich.'
showCredit()
{
/* show our credits */
"The TADS 3 language and library were created by Michael J. Roberts.<.p>
The original Adventures of Heidi was a simple tutorial game for
the Inform language written by Roger Firth and Sonja Kesserich.";
/*
* The game credits are displayed first, but the library will
* display additional credits for library modules. It's a good
* idea to show a blank line after the game credits to separate
* them visually from the (usually one-liner) library credits that
* follow.
*/
"\b";
}
showAbout()
{
"The Further Adventures of Heidi<.p>
A Tutorial Game for TADS 3";
}
;
/*
* Define the player character. The name of this object is not important,
* but note that it has to match up with the name we use in the main()
* routine to initialize the game, below.
*
* Note that we aren't required to define any vocabulary or description
* for this object, because the class Actor, defined in the library,
* automatically provides the appropriate definitions for an Actor when
* the Actor is serving as the player character. Note also that we don't
* have to do anything special in this object definition to make the Actor
* the player character; any Actor can serve as the player character, and
* we'll establish this one as the PC in main(), below.
*/
me: Actor
/* the initial location */
location = outsideCottage
;
+ Wearable 'plain pretty blue dress' 'blue dress'
"It's quite plain, but you think it pretty enough. "
wornBy = me
dobjFor(Doff)
{
check()
{
failCheck('You can\'t wander around half naked! ');
}
}
;
/*
* The only thing that HAS to be done in gameMain is to set the
* initialPlayerChar, which can be called anything we like, but which is
* normally (since it's the default) called me.
*
* In practice you'll normally want to override the showIntro() method as
* well to display an introduction -- usually one that's rather more
* substantial than than shown here.
*/
gameMain: GameMainDef
initialPlayerChar = me
showIntro()
{
"Welcome to the Further Adventures of Heidi!\b";
}
showGoodbye()
{
"<.p>Thanks for playing!\b";
}
maxScore = 7
;
/*
* This exemplifies how a function may be defined in TADS 3. This one is
* fairly pointless, since it's only called from one point in the game. In
* a game that called finishGameMsg from may different places, a wrapper
* function like this might be more useful.
*
* Note that the function keyword here is optional, and most TADS 3 code
* would omit it, defining the function thus:
*
* endGame(flag) { finishGameMsg(flag,
* [finishOptionUndo,finishOptionFullScore]); }
*/
function endGame(flag)
{
finishGameMsg(flag, [finishOptionUndo,finishOptionFullScore]);
}
/* Modifications to behaviour of various classes */
modify Actor
makeProper
{
if(isProperName == nil && properName != nil)
{
isProperName = true;
name = properName;
/* Method 1: */
local tokList = Tokenizer.tokenize(properName);
for (local i = 1, local cnt = tokList.length() ; i <= cnt ; ++i)
{
if(i < cnt)
cmdDict.addWord(self, getTokVal(tokList[i]), &adjective);
cmdDict.addWord(self, getTokVal(tokList[i]), &noun);
}
/*
* Simpler Alternative: this doesn't add forenames as both
* nouns and adjectives, but as adjectives only with the final
* name as a noun:
*/
// initializeVocabWith(properName);
}
}
;
/*
* Modifications to Thing to implement a listRemoteContents() method, for
* looking through the cottage window.
*/
modify Thing
listLocation_ = nil
listRemoteContents(otherLocation)
{
listLocation_ = otherLocation;
try
{
lookAround(gActor, LookListSpecials | LookListPortables);
}
finally
{
listLocation_ = nil;
}
}
adjustLookAroundTable(tab, pov, actor)
{
inherited(tab, pov, actor);
if(listLocation_ != nil)
{
local lst = tab.keysToList();
foreach(local cur in lst)
{
if(!cur.isIn(listLocation_))
tab.removeElement(cur);
}
}
}
;
/* Definition of additional verbs */
DefineTAction(Cross);
VerbRule(Cross)
('cross' | 'ford' | 'wade') singleDobj
: CrossAction
verbPhrase = 'cross/crossing (what)'
;
modify Thing
dobjFor(Cross)
{
preCond = [objVisible]
verify() {illogical('{The dobj/he} is not something you can cross. ' ); }
}
;
DefineTAction(Row);
VerbRule(Row)
'row' singleDobj
: RowAction
verbPhrase = 'row/rowing (what)'
;
modify Thing
dobjFor(Row)
{
preCond = [touchObj]
verify() { illogical('{You/he} can\'t row {that dobj/him}'); }
}
;
DefineTAction(Ring);
VerbRule(Ring)
'ring' singleDobj
: RingAction
verbPhrase = 'ring/ring (what)'
;
modify Thing
dobjFor(Ring)
{
preCond = [touchObj]
verify() { illogical('{You/he} can\'t ring {that dobj/him}'); }
}
;
/* Definitions of additional special classes */
class Diggable : Floor
dobjFor(DigWith)
{
preCond = [objVisible, touchObj]
verify() {}
check() {}
action()
{
"Digging here reveals nothing of interest. ";
}
}
putDestMessage = &putDestFloor
;
class ForestRoom : OutdoorRoom
atmosphereList : ShuffledEventList
{
[
'A fox dashes across your path.\n',
'A clutch of rabbits dash back among the trees.\n',
'A deer suddenly leaps out from the trees, then darts back off into the forest.\n',
'There is a rustling in the undergrowth.\n',
'There is a sudden flapping of wings as a pair of birds take flight off to the left.\n'
]
eventPercent = 90
eventReduceAfter = 6
eventReduceTo = 50
}
;
/*
* This MultiInstance effectively extends the functionality of the
* ForestRoom class by ensuring that we provide a response to EXAMINE
* TREES in every room of the ForestRoom class
*/
MultiInstance
instanceObject : Decoration { 'pine tree*trees*pines' 'pine trees'
"The forest is full of tall, fast-growing pines, although the occasional oak,
beach and sycamore can occasionally be seen among them. "
isPlural = true
}
initialLocationClass = ForestRoom
;
modify Thing
dobjFor(CleanWith)
{
verify() {}
check() { failCheck(&cannotCleanMsg); }
}
;
modify InstructionsAction
customVerbs = ['ROW THE BOAT', 'CROSS STREAM','RING THE BELL' ]
;
modify playerActionMessages
notASurfaceMsg = '{You/he} can\'t put anything on {the iobj/him}. '
;
/*
* Now for the actual scenario code - the definition of objects that
* define the rooms, things and actors in the game.
*/
/*
* ********************** OUTSIDE THE COTTAGE *
*************************/
outsideCottage : OutdoorRoom 'In front of a cottage' 'the front of the cottage'
"You stand just outside a cottage; the forest stretches east.
A short path leads round the cottage to the northwest. "
east = forest
in = cottageDoor
west asExit(in)
northwest = cottageGarden
;
+ Enterable -> (outsideCottage.in) 'pretty little cottage/house/building' 'pretty little cottage'
"It's just the sort of pretty little cottage that townspeople dream of living
in, with roses round the door and a neat little window frame freshly painted in
green. "
cannotTakeMsg = 'It may be a small cottage, but it\'s still a lot bigger than you are;
you can\'t walk around with it! '
cannotCleanMsg = dobjMsg('You don\'t have time for that right now. ')
notASurfaceMsg = iobjMsg('You can\'t reach the roof. ')
;
+ cottageDoor : LockableWithKey, Door 'door' 'door'
"It's a neat little door, painted green to match the window frame. "
keyList = [cottageKey]
;
+ Distant 'forest' 'forest'
"The forest is off to the east. "
tooDistantMsg = 'It\'s too far away for that. '
;
cottageWindow : SenseConnector, Fixture 'window' 'window'
"The cottage window has a freshly painted green frame. The glass has been recently
cleaned. "
dobjFor(LookThrough)
{
verify() {}
check() {}
action()
{
local otherLocation;
connectorMaterial = glass;
if(gActor.isIn(outsideCottage))
{
otherLocation = insideCottage;
"You peer through the window into the neat little room inside the cottage. ";
}
else
{
otherLocation = outsideCottage;
"Looking out through the window you see a path leading into the forest. ";
}
gActor.location.listRemoteContents(otherLocation);
}
}
connectorMaterial = adventium
locationList = [outsideCottage, insideCottage]
;
/*
* ********************** DEEP IN THE FOREST *
*************************/
forest : ForestRoom 'Deep in the Forest' 'the depths of the forest'
"Through the deep foliage you glimpse a building to the west.
A track leads to the northeast, and a path leads south."
west = outsideCottage
northeast = clearing
south = outsideCave
;
/*
* ********************** THE CLEARING *
*************************/
clearing : ForestRoom 'Clearing'
"A tall sycamore tree stands in the middle of this clearing.
One path winds to the southwest, and another to the north."
southwest = forest
// up : NoTravelMessage { "The lowest bough is just too high for you to reach. "}
up : TravelMessage
{ ->topOfTree
"By clinging on to the bough you manage to haul yourself
up the tree. "
canTravelerPass(traveler) {return traveler.isIn(chair); }
explainTravelBarrier(traveler) { "The lowest bough is just out of reach. "; }
}
north = forestPath
;
+ tree : Fixture
'tall sycamore tree' 'sycamore tree'
"Standing proud in the middle of the clearing, the stout
tree looks like it should be easy to climb. A small pile of loose twigs
has gathered at its base. "
dobjFor(Climb) remapTo(Up)
;
++ bough : OutOfReach, Fixture 'lowest bough' 'lowest bough'
"The lowest bough of the tree is just a bit too high up for you
to reach from the ground. "
canObjReachContents(obj)
{
if(obj.posture == standing && obj.location == chair)
return true;
return inherited(obj);
}
cannotReachFromOutsideMsg(dest)
{
return 'The bough is just too far from the ground for you to reach. ';
}
;
+ Decoration 'loose small pile/twigs' 'pile of twigs'
"There are several small twigs here, most of them small, insubstantial,
and frankly of no use to anyone bigger than a blue-tit <>.
<>"
dobjFor(Search) asDobjFor(Examine)
;
+ stick : Hidden 'long substantial stick' 'long stick'
"It's about two feet long, a quarter of an inch in diameter, and reasonably straight. "
iobjFor(MoveWith)
{
verify() {}
check() {}
action()
{
if(gDobj==nest && !nest.moved)
replaceAction(Take, nest);
}
}
;
/*
* ********************** THE TOP OF THE TREE *
*************************/
topOfTree : FloorlessRoom 'At the top of the tree' 'the top of the tree'
"You cling precariously to the trunk, next to a firm, narrow branch. "
down = clearing
enteringRoom(traveler)
{
if(!traveler.hasSeen(self) && traveler == gPlayerChar)
addToScore(1, 'reaching the top of the tree. ');
}
bottomRoom = clearing
// receiveDrop(obj, desc)
// {
// obj.moveInto(clearing);
// "\^<> falls to the ground below. ";
// }
roomBeforeAction()
{
if(gActionIs(Jump))
failCheck('Not here - you might fall to the ground and
hurt yourself. ');
}
roomAfterAction()
{
if(gActionIs(Yell))
"Your shout is lost on the breeze. ";
}
;
+ branch : Surface, Fixture 'branch' 'branch'
"The branch looks too narrow to walk, crawl or climb along, but firm enough to support
a reasonable weight. "
;
++ nest : Container 'bird\'s nest' 'bird\'s nest'
"It's carefully woven from twigs and moss. "
dobjFor(LookIn)
{
check()
{
if(!isHeldBy(gActor))
{
"You really need to hold the nest to take a good look at what's inside. ";
exit;
}
}
action()
{
if(ring.moved)
{
"You find nothing else of interest in the nest. ";
exit;
}
ring.makePresent();
"A closer examination of the nest reveals a diamond ring inside! ";
addToScore(1, 'finding the ring');
}
}
dobjFor(Take)
{
check()
{
if(!moved && !stick.isIn(gActor))
{
"The nest is too far away for you to reach. ";
exit;
}
}
action()
{
if(!moved)
"Using the stick you manage to pull the nest near enough to take, which
you promptly do. ";
inherited;
}
}
dobjFor(MoveWith)
{
verify()
{
if(isHeldBy(gActor))
illogicalAlready('{You/he} {is} already holding it. ');
}
check()
{
if(gIobj != stick)
{
"{You/he} can't move the nest with that. ";
exit;
}
}
}
;
+++ ring : PresentLater, Thing 'platinum diamond ring' 'diamond ring'
"The ring comprises a sparkling solitaire diamond set in platinum. It looks like it
could be intended as an engagement ring. "
;
/*
* ********************** INSIDE THE COTTAGE *
*************************/
insideCottage : Room 'Inside Cottage' 'the inside of the cottage'
"The front parlour of the little cottage looks impeccably neat.
The door out is to the east. "
out = cottageDoorInside
east asExit(out)
inRoomName(pov) { return 'inside the cottage'; }
remoteRoomContentsLister(other)
{
return new CustomRoomLister('Through the window, {you/he} see{s}',
' lying on the ground.');
}
;
+ cottageDoorInside : Lockable, Door -> cottageDoor 'door' 'door';
+ chair : Chair 'wooden chair' 'wooden chair'
"It's a plain wooden chair. "
initSpecialDesc = "A plain wooden chair sits in the corner. "
remoteInitSpecialDesc(actor) { "Through the cottage window you can
see a plain wooden chair sitting in the corner of the front room. "; }
;
/*
* ********************** THE FOREST PATH *
*************************/
forestPath : ForestRoom 'forest Path'
"This broad path leads more or less straight north-south
through the forest. To the north the occasional puff of
smoke floats up above the trees. "
south = clearing
north = fireClearing
;
/*
* ********************** THE FIRE CLEARING *
*************************/
fireClearing : OutdoorRoom 'Clearing with Fire' 'the clearing with the fire'
"The main feature of this large clearing a large, smouldering charcoal
fire that periodically lets off clouds of smoke. A path leads off
to the south, and another to the northwest. "
south = forestPath
northwest = pathByStream
;
+ fire : Fixture 'large smoking charcoal fire' 'fire'
"The fire is burning slowly, turning wood into charcoal. It nevertheless
feels quite hot even from a distance, and every now and again lets out
billows of smoke that get blown in your direction. "
dobjFor(Examine)
{
verify() {}
action() { inherited; }
}
dobjFor(Smell) remapTo(Smell, smoke)
dobjFor(Default)
{
verify() { illogical('The fire is best left well alone; it\'s very
hot and {you/he} do{es}n\'t want to get too close.<.p>'); }
}
;
+ smoke : Vaporous 'smoke' 'smoke'
"The thick, grey smoke rises steadily from the fire, but gusts of wind occasionally send
billows of it in your direction. "
// smellDesc = "The smoke from the fire smells acrid and makes you cough. "
;
++ Odor 'acrid smokey smell/whiff/pong' 'smell of smoke'
sourceDesc = "The smoke from the fire smells acrid and makes you cough. "
descWithSource = "The smoke smells strongly of charred wood."
hereWithSource = "You catch a whiff of the smoke from the fire. "
displaySchedule = [2, 4, 6]
;
spade : Thing 'sturdy spade' 'spade'
@burner
"It's a sturdy spade with a broad steel blade and a firm wooden handle. "
iobjFor(DigWith)
{
verify() {}
check() {}
}
;
/*
* ********************** BANK OF THE STREAM *
*************************/
pathByStream : OutdoorRoom 'By a stream' 'the bank of the stream'
"The path through the trees from the southeast comes to an end on
the banks of a stream. Across the stream to the west you can see
an open meadow. "
southeast = fireClearing
west = streamWade
;
streamWade : RoomConnector
room1 = pathByStream
room2 = meadow
canTravelerPass(traveler) { return boots.isWornBy(traveler); }
explainTravelBarrier(traveler)
{
"Your shoes aren't waterproof. If you wade across you'll get your feet wet
and probably catch your death of cold. ";
}
;
/*
* ********************** THE MEADOW *
*************************/
meadow : OutdoorRoom 'Large Meadow'
"This large, open meadow stretches almost as far as you can see
to north, west, and south, but is bordered by a fast-flowing stream
to the east. "
east = streamWade
;
+ cottageKey : Key 'small brass brassy key/object/something' 'object'
"It's a small brass key, with a faded tag you can no longer read. "
initSpecialDesc = "A small brass object lies in the grass. "
remoteInitSpecialDesc(actor) {
"There is a momentary glint of something brassy as
the sun reflects off something lying in the meadow across the stream. "; }
dobjFor(Take)
{
action()
{
if(!moved) addToScore(1, 'retrieving the key');
inherited;
name = 'small brass key';
}
}
;
DistanceConnector [pathByStream, meadow];
stream : MultiLoc, Fixture 'stream' 'stream'
"The stream is not terribly deep at this point, though it's flowing
quite rapidly towards the south. "
locationList = [pathByStream, meadow]
dobjFor(Cross)
{
verify() {}
check() {}
action()
{
replaceAction(TravelVia, streamWade);
}
}
;
/*
* ********************** OUTSIDE THE CAVE *
*************************/
outsideCave : OutdoorRoom 'Just Outside a Cave' 'just outside the cave'
"The path through the trees from the north comes to an end
just outside the mouth of a large cave to the south. Behind the cave
rises a sheer wall of rock. "
north = forest
in = insideCave
south asExit(in)
;
+ Enterable 'cave/entrance' 'cave'
"The entrance to the cave looks quite narrow, but probably just wide
enough for someone to squeeze through. "
connector = insideCave
;
/*
* ********************** INSIDE THE COTTAGE *
*************************/
insideCave : DarkRoom 'Inside a large cave' 'the interior of the cave'
"The cave is larger than its narrow entrance might lead one to expect. Even
a tall adult could stand here quite comfortably, and the cave stretches back
quite some way. <>"
out = outsideCave
north asExit(out)
roomParts = [caveFloor, defaultCeiling,
caveNorthWall, defaultSouthWall,
caveEastWall, defaultWestWall]
;
caveFloor : Diggable 'cave floor/ground' 'cave floor'
"The floor of the cave is quite sandy; near the centre is
<>. "
hasBeenDug = nil
dobjFor(DigWith)
{
check()
{
if(hasBeenDug)
{
"You've already dug a hole here. ";
exit;
}
}
action()
{
hasBeenDug = true;
"You dig a small hole in the sandy floor and find a buried pair of
old Wellington boots. ";
hole.moveInto(self);
addToScore(1, 'finding the boots');
}
}
;
hole : Container, Fixture 'hole' 'hole'
"There's a small round hole, freshly dug in the floor near the centre
of the cave. "
;
+ boots : Wearable 'old wellington pair/boots/wellies' 'old pair of boots'
"They look ancient, battered, and scuffed, but probably still waterproof. "
initSpecialDesc = "A pair of old Wellington boots lies in the hole. "
;
caveNorthWall : DefaultWall 'north wall' 'north wall'
"In the north wall is a narrow gap leading out of the cave. "
;
caveEastWall : DefaultWall 'east wall' 'east wall'
"The east wall of the cave is quite smooth and has the faint remains of
something drawn or written on it. Unfortunately it's no longer possible
to discern whether it was once a Neolithic cave painting or an example
of modern graffiti. "
;
/*
* ********************** THE COTTAGE GARDEN *
*************************/
cottageGarden : OutdoorRoom 'Cottage Garden'
"This neat little garden is situated on the north side of the cottage. A
stream runs along the bottom of the garden, while a short path disappears
through a gap in the fence to the southeast, and another leads westwards down to
the road. Next to the fence stands a small garden shed. "
southeast = outsideCottage
north : NoTravelMessage {"<> "}
east : NoTravelMessage {"You can't walk through the fence. "}
west : FakeConnector {"That path leads down to the road, and you don't fancy
going near all those nasty, smelly, noisy cars right now. " }
in = insideShed
vocabWords = '(cottage) garden'
;
+ Decoration 'cottage' 'cottage'
"The neat little cottage is situated at the southern end of the garden,
which it overlooks through a pair of small windows. ";
;
+ Decoration 'wooden fence' 'wooden fence'
"The tall wooden fence runs along the eastern side of the garden, with
a small gap at its southern end. "
;
+ gardenStream: Fixture 'stream' 'stream'
"<>"
dobjFor(Cross)
{
verify() {}
check() { failCheck(cannotCrossMsg); }
}
cannotCrossMsg = ' The stream is quite wide at this point, and too deep to cross. '
;
+ Openable, Enterable -> insideShed 'small wooden (garden) shed' 'garden shed'
"It's a small, wooden shed. "
dobjFor(LookIn) asDobjFor(Enter)
/*
* The following commented out code shows how matchNameCommon() could
* be used here, but in practice it's easier in this case just to use
* 'weak' tokens (i.e. tokens enclosed in parentheses) in our
* vocabWords property.
*/
// matchNameCommon(origTokens, adjustedTokens)
// {
// if(adjustedTokens.indexOf('shed'))
// return self;
// else
// return cottageGarden;
// }
;
/*
* ********************** INSIDE THE SHED *
*************************/
insideShed : Room 'Inside the Garden Shed'
"The inside of the shed is full of garden implements, leaving just about enough
room for one person to stand. An old cupboard stands in the corner. "
out = cottageGarden
;
+ Decoration 'garden implements/hoe/rake/shears' 'garden implements'
"There's a hoe, a rake, some shears, and several other bits and pieces. "
isPlural = true
;
+ oars : Thing 'pair/oars' 'pair of oars'
"The oars look like they're meant for a small rowing-boat. "
bulk = 10
initSpecialDesc = "A pair of oars leans against the wall. "
;
+ cupboard: ComplexContainer, Heavy 'battered old wooden cupboard' 'old cupboard'
"The cupboard is a battered old wooden thing, with chipped blue and
white paint. "
subContainer : ComplexComponent, OpenableContainer { }
subSurface : ComplexComponent, Surface { }
;
++ tin : OpenableContainer 'small square tin' 'small tin'
"It's a small square tin with a lid. "
subLocation = &subSurface
bulkCapacity = 5
;
class Coin : Thing 'pound coin/pound*coins*pounds' 'pound coin'
"It's gold in colour, has the Queen's head on one side and One Pound
written on the reverse. The edge is inscribed with the words
DECUS ET TUTAMEN
"
isEquivalent = true
;
+++ Coin;
+++ Coin;
+++ Coin;
+++ Coin;
++ torch : Flashlight, OpenableContainer 'small blue torch/flashlight' 'small blue torch'
"It's just a small blue torch. "
subLocation = &subContainer
bulkCapacity = 1
dobjFor(TurnOn)
{
check()
{
if(! battery.isIn(self))
{
"Nothing happens. ";
exit;
}
}
}
iobjFor(PutIn)
{
check()
{
if(gDobj != battery)
{
"{The dobj/he} doesn't fit in the torch. ";
exit;
}
}
action()
{
inherited;
makeOpen(nil);
achieve.addToScoreOnce(1);
}
}
notifyRemove(obj)
{
if(isOn)
{
"Removing the battery causes the torch to go out. ";
makeOn(nil);
}
}
achieve: Achievement
{ desc = "fitting the battery into the torch" }
;
/*
* ********************** THE ROWING BOAT *
*************************/
boat : Heavy, Enterable -> insideBoat 'rowing boat/dinghy' 'rowing boat'
//boat : Heavy 'rowing boat' 'rowing boat'
@cottageGarden
"It's a small rowing boat. "
specialDesc = "A small rowing boat floats on the stream, just by the bank. "
useSpecialDesc { return true; }
dobjFor(Board) asDobjFor(Enter)
dobjFor(Row)
{
verify()
{
illogicalNow('You need to be aboard the boat before you can row it. ');
}
}
getFacets = [rowBoat]
;
boatBottom : Floor 'floor/bottom/(boat)' 'bottom of the boat'
;
insideBoat : OutdoorRoom
name = ('In the boat (by '+ boat.location.name + ')')
desc = "The boat is a plain wooden rowing dinghy with a single wooden seat. It
is floating on the stream just by the <>. "
out = (boat.location)
roomParts = [boatBottom, defaultSky]
;
+ rowBoat: Fixture 'plain wooden rowing boat/dighy' 'boat'
"<>"
dobjFor(Take)
{
verify() {illogical('{You/he} can\'t take the boat - {you\'re/he\'s} in it!'); }
}
dobjFor(Row)
{
verify() {}
check()
{
if(!oars.isHeldBy(gActor))
{
"{You/he} need to be holding the oars before you can row this boat. ";
exit;
}
}
action()
{
"You row the boat along the stream and under a low bridge, finally arriving
at ";
if(boat.isIn(jetty))
{
"the bottom of the cottage garden.<.p> ";
boat.moveInto(cottageGarden);
}
else
{
"the side of a small wooden jetty.<.p> ";
boat.moveInto(jetty);
}
nestedAction(Look);
}
}
getFacets = [boat]
;
+ Chair, Fixture 'single wooden seat' 'wooden seat'
;
/*
* ********************** THE JETTY *
*************************/
jetty : OutdoorRoom 'Jetty'
"This small wooden jetty stands on the bank of the stream. Upstream to the
east you can see a road-bridge, and a path runs downstream along the bank
to the west. Just to the south stands a small shop. "
west : FakeConnector {"You could go wandering down the path but you don't
feel you have much reason to. "}
east : NoTravelMessage {"The path doesn't run under the bridge. "}
south = insideShop
is asExit(south)
;
+ Distant 'bridge' 'bridge'
"It's a small brick-built hump-backed bridge carrying the road over
the stream. "
;
+ Fixture 'stream' 'stream'
"The stream becomes quite wide at this point, almost reaching the proportions
of a small river. To the east it flows under a bridge, and to the west it
carries on through the village. "
dobjFor(Cross)
{
verify() {}
check()
{ failCheck ('The stream is far too wide and deep to cross here. '); }
}
;
+ Enterable -> insideShop 'small shop/store' 'shop'
"The small, timber-clad shop has an open door, above which is a sign reading
GENERAL STORE"
;
/*
* ********************** INSIDE THE SHOP *
*************************/
insideShop : Room 'Inside Shop' 'inside the shop'
"The interior of the shop is lined with shelves containing all sorts of items,
including basic foodstuffs, sweets, snacks, stationery, batteries, soft
drinks and tissues. Behind the counter is a door marked 'PRIVATE'. "
out = jetty
north asExit(out)
south : OneWayRoomConnector
{
destination = backRoom
canTravelerPass(traveler) { return traveler != gPlayerChar; }
explainTravelBarrier(traveler)
{ "The counter bars your way to the door. "; }
}
;
+ Decoration 'private door*doors' 'door'
"The door marked 'PRIVATE' is on the far side of the counter, and there seems to be
no way you can reach it. The other door out to the jetty is to the north. "
;
+ Fixture, Surface 'counter' 'counter'
"The counter is about four feet long and eighteen inches wide. "
;
++ bell : Thing 'small brass bell' 'small brass bell'
"The bell comprises an inverted hemisphere with a small brass knob protruding
through the top. Attached to the bell is a small sign. "
dobjFor(Ring)
{
verify() {}
check() {}
action()
{
bellRing.triggerEvent(self);
}
}
;
+++ Component, Readable 'sign' 'sign'
"The sign reads RING BELL FOR SERVICE. "
;
+++ Component 'knob/button' 'knob'
"The knob protrudes through the top of the brass hemisphere of the bell. "
dobjFor(Push) remapTo(Ring, bell)
;
+ Distant, Surface 'shelf*shelves' 'shelves'
"The shelves with the most interesting goodies are behind the counter. "
isPlural = true
;
++ batteries : Distant 'battery*batteries' 'batteries on shelf'
"A variety of batteries sits on the shelf behind the counter. "
isPlural = true
salePrice = 3
saleName = 'torch battery'
saleItem = battery
;
++ sweets : Distant 'candy/sweets' 'sweets on shelf'
"All sorts of tempting jars, bags, packets and boxes of sweets lurk temptingly
on the shelves behind the counter. "
isPlural = true
salePrice = 1
saleName = 'bag of sweets'
saleItem = sweetBag
;
battery : Thing 'small red battery' 'small red battery'
"It's a small red battery, 1.5v, manufactured by ElectroLeax
and made in the People's Republic of Erewhon. "
bulk = 1
;
sweetBag : Dispenser 'bag of candy/sweets' 'bag of sweets'
"A bag of sweets. "
canReturnItem = true
myItemClass = Sweet
;
class Sweet : Dispensable, Food
desc = "It's a small, round, clear, <> boiled sweet. "
vocabWords = 'sweet/candy*sweets'
location = sweetBag
listWith = [sweetGroup]
sweetGroupBaseName = ''
collectiveGroup = sweetCollective
sweetGroupName = ('one ' + sweetGroupBaseName)
countedSweetGroupName(cnt)
{ return spellIntBelow(cnt, 100) + ' ' + sweetGroupBaseName; }
tasteDesc = "It tastes sweet and tangy. "
dobjFor(Eat)
{
action()
{
"You pop <> into your mouth and suck it. It tastes nice
but it doesn't last as long as you'd like.<.p>";
inherited;
}
}
;
class RedSweet : Sweet 'red - ' 'red sweet'
isEquivalent = true
sweetGroupBaseName = 'red'
;
class GreenSweet : Sweet 'green - ' 'green sweet'
isEquivalent = true
sweetGroupBaseName = 'green'
;
class YellowSweet : Sweet 'yellow - ' 'yellow sweet'
isEquivalent = true
sweetGroupBaseName = 'yellow'
;
sweetGroup: ListGroupParen
showGroupCountName(lst)
{
"<> sweets";
}
showGroupItem(lister, obj, options, pov, info)
{ say(obj.sweetGroupName); }
showGroupItemCounted(lister, lst, options, pov, infoTab)
{ say(lst[1].countedSweetGroupName(lst.length())); }
;
sweetCollective: ItemizingCollectiveGroup 'candy*sweets' 'sweets'
;
RedSweet;
RedSweet;
RedSweet;
RedSweet;
GreenSweet;
GreenSweet;
GreenSweet;
YellowSweet;
YellowSweet;
bellRing : SoundEvent
triggerEvent(source)
{
"TING!<.p>";
inherited(source);
}
;
backRoom: Room
north = insideShop
;
SenseConnector, Intangible 'wall' 'wall'
connectorMaterial = paper
locationList = [backRoom, insideShop]
;
/*
* *********************************************************************
* NON PLAYER CHARACTERS *
************************************************************************/
/*
* Definition of Joe Black, the Burner NPC - as this is complex we
* separate it from the other code and put it at the end
*/
burner : Person 'charcoal burner' 'charcoal burner'
@fireClearing
"It's rather difficult to make out his features under all the grime and soot. "
properName = 'Joe Black'
globalParamName = 'burner'
isHim = true
;
+ GiveShowTopic @ring
topicResponse
{
"As you hand the ring over to {the burner/him}, his eyes light up in delight
and his jaws drop in amazement. You found it!
he declares, God bless
you, you really found it! Now I can go and call on my sweetheart after all!
Thank you, my dear, that's absolutely wonderful!
<.p>";
addToScore (2, 'giving {the burner/him} his ring back. ');
/* CHANGED IN 3.0.6n */
finishGameMsg(ftVictory, [finishOptionUndo,finishOptionFullScore]);
}
;
+ DefaultGiveShowTopic, ShuffledEventList
[
'{The burner/he} shakes his head, No thanks, love.
',
'He looks at it and grins, That\'s nice, my dear.
he remarks,
handing it back.',
'I\'d hang on to that if I were you.
he advises. '
]
;
+ burnerTalking : InConversationState
stateDesc = "He's standing talking with you. "
specialDesc = "{The burner/he} is leaning on his spade
talking with you. "
nextState = burnerWorking
;
++ burnerWorking : ConversationReadyState
stateDesc = "He's busily tending the fire. "
specialDesc = "<>
is walking round the fire, occasionally shovelling dirt onto it with his spade. "
isInitState = true
a = 0
;
+++ HelloTopic, StopEventList
[
'Er, excuse me,
you say, trying to get {the\'s burner/her} attention.\b
{The burner/he} moves away from the fire and leans on his spade to talk to
you. Hello, young lady. Mind you don\'t get too close to that fire now.
',
'Hello!
you call cheerfully.\b
Hello again!
{the burner/he} declares, pausing from his labours to
rest on his spade.'
]
;
+++ ByeTopic
"Bye for now, then.
you say.<.p>
Take care, now.
{the burner/he} admonishes you as he returns to his work."
;
+++ ImpByeTopic
"{The burner/he} gives a little shake of the head and returns to work."
;
++ AskTopic, SuggestedAskTopic @smoke
"Doesn't that smoke bother you?
you ask.<.p>
Nah! You get used to it - you just learn not to breathe too deep when it
gets blown your way.
he assures you."
name = 'the smoke'
;
++ AskTopic, SuggestedAskTopic, ShuffledEventList @fire
[
'Why have you got that great big bonfire in the middle of the forest?
you ask.<.p>
It\'s not a bonfire, Miss, it\'s a fire for making charcoal.
he explains,
And to make charcoal I need to burn wood - slow like - and a forest is a
good place to find wood - see?
',
'Doesn\'t it get a bit hot, working with that fire all day?
you wonder.<.p>
Yes, but it beats being cooped up in an office all day.
he replies,
I couldn\'t stand that!
',
'Why do you keep putting that dust on the fire?
you wonder.<.p>
To stop it burning too quick.
he tells you.'
]
name = 'the fire'
;
++ AskTopic, SuggestedAskTopic @burner
"My name's Heidi.
you announce. What's yours?
<.p>
<>,
he replies, Mind you, it'll soon be mud.
<.convnode burner-mud><>"
name = 'himself'
;
+++ AltTopic, SuggestedAskTopic, StopEventList
[
'Have you been a charcoal burner long?
you ask.<.p>
About ten years.
he replies.',
'Do you like being a charcoal burner?
you wonder, It seems
rather messy!
<.p>
It\'s better than being cooped up in some office or factory all day,
at any rate.
he tells you.',
'What do you do when you\'re not burning charcoal?
you enquire.<.p>
Oh -- this and that.
he shrugs.'
]
isActive = (burner.isProperName)
name = 'himself'
;
++ AskTellTopic, SuggestedAskTopic, StopEventList @ring
[
'What happened to the ring -- how did you manage to lose it?
you ask.<.p>
You wouldn\'t believe it.
he shakes his head again, I took it out to
take a look at it a couple of hours back, and then dropped the thing. Before
I could pick it up again, blow me if a thieving little magpie didn\'t flutter
down and fly off with it!
',
'Where do you think the ring could have gone?
you wonder.<.p>
I suppose it\'s fetched up in some nest somewhere,
he sighs, Goodness
knows how I\'ll ever get it back again!
',
'Would you like me to try to find your ring for you?
you volunteer
earnestly.<.p>
Yes, sure, that would be wonderful.
he agrees, without sounding in the
least convinced that you\'ll be able to.'
]
name = 'the ring'
;
+++ AltTopic, SuggestedTellTopic
"I found a ring in a bird's nest, up a tree just down there.
you tell him,
pointing vaguely southwards, Could it be yours?
<.p>
Really?
he asks, his eyes lighting up with disbelieving hope, Let me
see it!
"
isActive = (gPlayerChar.hasSeen(ring))
name = 'the ring'
;
++ AskForTopic @spade
topicResponse
{
"Could I borrow your spade, please?
you ask.<.p>
All right then,
he agrees a little reluctantly, handing you the spade,
but make sure you bring it back.
";
spade.moveInto(gActor);
getActor().setCurState(burnerFretting);
}
;
++ DefaultAskTellTopic
"What do you think about <>?
you ask.<.p>
Ah, yes indeed, <>,
he nods sagely,
<>.
"
;
+ ConvNode 'burner-mud';
++ SpecialTopic, StopEventList
'deny that mud is a name'
['deny', 'that', 'mud', 'is', 'a', 'name']
[
'Mud! What kind of name is that? you ask.<.p>
My name -- tonight.
he replied gloomily.<.convstay>',
'But you can\'t really be called Mud
you insist.<.p>
Oh yes I can!
he assures you.<.convstay>'
]
;
++ SpecialTopic 'ask why' ['ask','why']
"Why will your name be mud?
you want to know.<.p>
He shakes his head, lets out an enormous sigh, and replies,
I was going to give her the ring tonight -- her engagement ring --
only I've gone and lost it. Cost me two months' wages it did. And
now she'll never speak to me again,
he concludes, with another
mournful shake of the head, never.
<>"
;
++ DefaultAskTellTopic
"And why does...
you begin.<.p>
Mud.
he repeats with a despairing sigh.<.convstay>"
;
+ burnerFretting : InConversationState
specialDesc = "{The burner/he} is standing talking to you with his
hands on his hips. "
stateDesc = "He's standing talking to you with his hands on his hips. "
nextState = burnerWaiting
;
++ burnerWaiting : ConversationReadyState
specialDesc = "{The burner/he} is walking round the fire, frowning as
he keeps instinctively reaching for the spade that isn't there. "
stateDesc = "He's walking round the fire. "
afterTravel(traveler, connector)
{
getActor().initiateConversation(burnerFretting, 'burner-spade');
}
;
+++ HelloTopic
"Hello, there.
you say.<.p>
Hello, young lady - have you brought my spade?
he asks."
;
+++ ByeTopic
"Bye, then.
you say.<.p>
Don't be too long with that spade -- be sure to bring it right back!
he admonishes you."
;
++ GiveShowTopic @spade
topicResponse
{
"Here's your spade then,
you say, handing it over.<.p>
Ah, thanks!
he replies taking it with evident relief. ";
spade.moveInto(burner);
burner.setCurState(burnerTalking);
}
;
++ AskForTopic @spade
"He doesn't have the spade. "
isConversational = nil
;
++ AskTellTopic @spade
"This seems a very sturdy spade,
you remark.\b
It is -- look after it well, I need it for my work!
{the burner/he} replies."
;
+++ AltTopic
"I seem to have left your spade somewhere,
you confess.\b
I hope you can find it then!
{the burner/he} remarks anxiously."
isActive = (!spade.isIn(burner.location))
;
++ DefaultAskTellTopic
"We can talk about that when I've got my spade back,
he tells you."
;
+ ConvNode 'burner-spade'
npcGreetingMsg = "<.p>He looks up at your approach, and walks
away from the fire to meet you. Have you finished with my spade
yet?
he enquires anxiously.<.p>"
npcContinueMsg = "What about my spade? Have you finished with it yet?
{the burner/he} repeats anxiously. "
;
++ YesTopic
"Yes, I have.
you reply.<.p>
Can I have it back then, please?
he asks."
;
++ NoTopic
"Not quite; can I borrow it a bit longer?
you ask.<.p>
Very well, then.
he conceded grudgingly, But I need it
to get on with my job, so please be quick about it.
"
;
/*
* Definition of Sally the Shopkeeper
*/
shopkeeper : SoundObserver, Person 'young shopkeeper/woman' 'young shopkeeper'
@backRoom
"The shopkeeper is a jolly woman with rosy cheeks and fluffy blonde curls. "
isHer = true
properName = 'Sally'
notifySoundEvent(event, source, info)
{
if(event == bellRing && daemonID == nil && isIn(backRoom))
daemonID = new SenseDaemon(self, &daemon, 2, self, sight);
else if(isIn(insideShop) && event == bellRing)
"All right, all right, here I am!
says {the shopkeeper/she}.<.p>";
}
daemonID = nil
daemon
{
moveIntoForTravel(insideShop);
"{The shopkeeper/she} comes through the door and stands behind the counter.<.p>";
daemonID.removeEvent();
daemonID = nil;
if(canTalkTo(gPlayerChar))
initiateConversation(sallyTalking, 'sally-1');
}
globalParamName = 'shopkeeper'
cashReceived = 0
price = 0
saleObject = nil
// cashFuseID = nil
// cashFuse
// {
// if(saleObject == nil)
// {
// "What's this for?
asks {the shopkeeper/she}, handing the money
// back, Shouldn't you tell me what you want to buy first?
";
// cashReceived = 0;
// }
// else if(cashReceived < price)
// "Er, that's not enough.
she points out, looking at you expectantly
// while she waits for the balance. ";
// else
// {
// "{The shopkeeper/she} takes the money and turns to take <>
// off the shelf. She hands you <> saying, Here you are
// then";
// if(cashReceived > price)
// ", and here's your change";
// ".
";
// saleObject.moveInto(gPlayerChar);
// price = 0;
// cashReceived = 0;
// saleObject = nil;
// }
// cashFuseID = nil;
// }
;
+ ConvNode 'sally-1'
npcGreetingMsg = "Hello, what can I get you?
she asks. <.p>"
;
+ sallyTalking : InConversationState
specialDesc = "{The shopkeeper/she} is standing behind the counter talking
with you. "
stateDesc = "She's standing behind the counter talking with you. "
nextState = sallyWaiting
;
++ sallyWaiting : ConversationReadyState
specialDesc = "{The shopkeeper/she} is standing behind the counter, checking
the stock on the shelves. "
stateDesc = "She's checking the stock on the shelves behind the counter. "
isInitState = true
takeTurn
{
if(!gPlayerChar.isIn(insideShop) && shopkeeper.isIn(insideShop))
shopkeeper.moveIntoForTravel(backRoom);
inherited;
}
;
+++ HelloTopic
"Hello, <>,
you say.<.p>
Hello, <>, what can I do
for you?
asks {the shopkeeper/she}."
;
+++ ByeTopic
"'Bye, then!
you say.<.p>
Goodbye<>. See you again soon!
{the shopkeeper/she} beams in return."
;
+++ ImpByeTopic
"{The shopkeeper/she} turns away and starts checking the stock on the shelves."
;
++ AskTellTopic [shopkeeper, gPlayerChar]
"I'm Heidi. What's your name?
you ask.<.p>
Hello, Heidi; I'm <>,
she smiles.
<>"
;
+++ AltTopic
"I'm feeling really very well today; how are you?
you ask.<.p>
I'm feeling very well too, thanks.
she tells you."
isActive = (shopkeeper.isProperName)
;
++ AskTellTopic @burner
"Do you know {the burner/him}, the old fellow who works in the forest?
you enquire innocently.<.p>
He's not that old,
she replies coyly."
;
++ AskTellTopic @tWeather
"Lovely weather we're having, don't you think?
you remark.<.p>
Absolutely,
she agrees, and with luck, it should stay fine tomorrow.
"
;
++ DefaultAskTellTopic, ShuffledEventList
[
'What do you think about ' + gTopicText + '?
you ask.<.p>
Frankly, not a lot.
she replies.',
'I think it\'s really interesting that...
you begin.<.p>
Oh yes, really interesting.
she agrees.',
'You make polite conversation about ' + gTopicText + ' and
{the shopkeeper/she} makes polite conversation in return.'
]
;
++ DefaultGiveShowTopic
"No thanks, dear.
she says, handing it back. ";
;
++ GiveShowTopic
matchTopic(fromActor, obj)
{
return obj.ofKind(Coin) ? matchScore : 0;
}
handleTopic(fromActor, obj)
{
// if(shopkeeper.cashFuseID == nil)
// shopkeeper.cashFuseID = new Fuse(shopkeeper, &cashFuse, 0);
shopkeeper.cashReceived ++;
currency = obj;
// if(shopkeeper.cashReceived > 1)
// "number <>";
if(shopkeeper.cashReceived <= shopkeeper.price)
obj.moveInto(shopkeeper);
/* add our special report */
gTranscript.addReport(new GiveCoinReport(obj));
/* register for collective handling at the end of the command */
gAction.callAfterActionMain(self);
}
afterActionMain()
{
/*
* adjust the transcript by summarizing consecutive coin
* acceptance reports
*/
gTranscript.summarizeAction(
{x: x.ofKind(GiveCoinReport)},
{vec: 'You hand over '
+ spellInt(vec.length())+' ' + currency.name+'s.\n'});
if(shopkeeper.saleObject == nil)
{
"What's this for?
asks {the shopkeeper/she}, handing the money
back, Shouldn't you tell me what you want to buy first?
";
shopkeeper.cashReceived = 0;
}
else if(shopkeeper.cashReceived < shopkeeper.price)
"Er, that's not enough.
she points out, looking at you expectantly
while she waits for the balance. ";
else
{
"{The shopkeeper/she} takes the money and turns to take <>
off the shelf. She hands you <> saying, Here you are
then";
if(shopkeeper.cashReceived > shopkeeper.price)
", and here's your change";
".
";
shopkeeper.saleObject.moveInto(gPlayerChar);
shopkeeper.price = 0;
shopkeeper.cashReceived = 0;
shopkeeper.saleObject = nil;
}
}
currency = nil
;
class GiveCoinReport: MainCommandReport
construct(obj)
{
/* remember the coin we accepted */
coinObj = obj;
/* inherit the default handling */
gMessageParams(obj);
inherited('You hand over {a obj/him}. ');
}
/* my coin object */
coinObj = nil
;
++ BuyTopic @batteries
alreadyBought = "You only need one battery, and you've already bought it.<.p>"
;
++ BuyTopic @sweets
alreadyBought = "You've already bought one bag of sweets. Think of your figure!
Think of your teeth!<.p>"
;
class BuyTopic : AskAboutForTopic
topicResponse
{
if(matchObj.saleItem.moved)
alreadyBought;
else if (shopkeeper.saleObject == matchObj.saleItem)
"Can I have the <>, please?
you ask.<.p>
I need another <> from you.
she points out.<.p>";
else if (shopkeeper.saleObject != nil)
"Oh, and I'd like a <> too, please.
you announce.<.p>
Shall we finish dealing with the <> first?
{the shopkeeper/she} suggests. ";
else
{
purchaseRequest();
purchaseResponse();
shopkeeper.price = matchObj.salePrice;
shopkeeper.saleObject = matchObj.saleItem;
}
}
alreadyBought = "You've already bought a <>.<.p>"
purchaseRequest = "I'd like a <> please,
you request.<.p>"
purchaseResponse = "Certainly, that'll be <>,
{the shopkeeper/she} informs you.<.p>"
;
function currencyString(amount)
{
return spellInt(amount) + ' ' + ((amount>1) ? 'pounds' : 'pound');
}
tWeather : Topic 'weather';
/*
* ******************** DEBUGGING VERBS *
***********************/
#ifdef __DEBUG
/*
* The purpose of the everything object is to contain a list of all usable
* game objects which can be used as a list of objects in scope for
* certain debugging verb. Everything caches a list of all relevant
* objects the first time its lst method is called.
*/
everything : object
/*
* lst_ will contain the list of all objects. We initialize it to nil
* to show that the list is yet to be cached
*/
lst_ = nil
/*
* The lst_ method checks whether the list of objects has been cached
* yet. If so, it simply returns it; if not, it calls initLst to build
* it first (and then returns it).
*/
lst()
{
if (lst_ == nil)
initLst();
return lst_;
}
/*
* initLst loops through every game object descended from Thing and
* adds it to lst_, thereby constructing a list of physical game
* objects.
*/
initLst()
{
lst_ = new Vector(50);
local obj = firstObj();
while (obj != nil)
{
if(obj.ofKind(Thing))
lst_.append(obj);
obj = nextObj(obj);
}
lst_ = lst_.toList();
}
;
DefineTAction(Purloin)
cacheScopeList()
{
scope_ = everything.lst();
}
;
VerbRule(Purloin)
('purloin'|'pn') dobjList
:PurloinAction
verbPhrase = 'purloin/purloining (what)'
;
modify Thing
dobjFor(Purloin)
{
verify()
{
if(isHeldBy(gActor)) illogicalNow('{You/he} {is} already holding it. ');
}
check() {}
action
{
mainReport('{The/he dobj} pops into your hands.\n ');
moveInto(gActor);
}
}
;
modify Fixture
dobjFor(Purloin)
{
verify {illogical ('That is not something you can purloin - it is fixed in place.'); }
}
;
modify Immovable
dobjFor(Purloin)
{
check()
{
"You can't take {the/him dobj}. ";
exit;
}
}
;
DefineTAction(Gonear)
// cacheScopeList()
// {
// scope_ = everything.lst();
// }
/*
* defining objInScope is an alternative to defining cacheScopeList in
* this particular situation; you can try out either way by commenting
* out one method and uncommenting in the other. This also applies to
* the Purloin verb.
*/
objInScope(obj) { return true; }
;
VerbRule(Gonear)
('gonear'|'gn'|'go' 'near') singleDobj
:GonearAction
verbPhrase = 'gonear/going near (what)'
;
modify Thing
dobjFor(Gonear)
{
verify() {}
check() {}
action()
{
local obj = self.roomLocation;
if(obj != nil)
{
"{You/he} {are} miraculously transported...";
replaceAction(TravelVia, obj);
}
else
"{You/he} can't go there. ";
}
}
;
modify Decoration
dobjFor(Gonear)
{
verify() {}
check() {}
action() {inherited;}
}
;
modify Distant
dobjFor(Gonear)
{
verify() {}
check() {}
action() {inherited;}
}
;
modify MultiLoc
dobjFor(Gonear)
{
verify() { illogical('{You/he} cannot gonear {the dobj/him}, since it exists
in more than one location. '); }
}
dobjFor(Purloin)
{
verify() { illogical('{You/he} cannot purloin {the dobj/him}, since it exists
in more than one location. '); }
}
;
#endif