vehicle
Occasionally, you may need to have a vehicle in your game. Be it a car (in a city), a horse (in a western) or a flying saucer. You’re in luck, as objlib.h defines a basic vehicle class!
First Things First
If you’re going to use a vehicle in your game, you’ll need to set the USE_VEHICLES flag near the top of your code.
#set USE_VEHICLES
“Driving” Verbs
You will also need to define the verb(s) used to “drive” your vehicle (or fly, or ride, etc…)
verb "drive"
* DoMoveinVehicle
* object DoMoveinVehicle
Defining the Vehicle
Here’s a simple example of a car definition:
vehicle rollsroyce "Rolls Royce"
{
article "my"
adjectives "silver", "expensive", "rolls"
nouns "car", "rolls", "royce", "wraith"
vehicle_verb "drive"
long_desc
{
! your description would go here
}
! can't drive the car if it's out of gas
vehicle_move
{
if self is not filled ! Assuming we've defined a 'filled' attribute
{
"The fuel gauge is sitting on empty, this beautiful car isn't going
anywhere at the moment."
return false ! returning false here stops the MoveinVehicle action
}
else
{
return true
}
}
The Vehicle Path
The Hugo Library assumes that vehicles cannot be moved in any location by default (you probable wouldn’t want a car to be able to be driven in your kitchen) so you have to define a property for each room where a vehicle can be driven, and also, which vehicles are allowed where. (for example, you may not want to allow a tricycle on a freeway)
! a couple of simple rooms where the rollsroyce defined above can be driven
room mainStreet "Main street"
{
long_desc
{
"A really nifty description of Main Street would go here"
}
e_to myHouse
s_to bentonStreet
n_to thirdStreet
vehicle_path rollsroyce
}
room bentonStreet "Benton Street"
{
! descriptions and exits definitions here
vehicle_path rollsroyce
}
room myHouse "My House"
{
long_desc
{
"123 Main Street, the house I grew up in"
}
w_to mainStreet
e_to entryHall
! and so on and so forth
! notice, there is no vehicle_path defined in this room, because
! driving a car here would be kind of silly
}
Determining whether player is in the vehicle
To determine if the player is in the vehicle, compare the parent to the vehicle:
if (parent(player)=rollsroyce) {
! code if they're in the car
} else {
! if they're not
}
Things not to do
If you are using a test on a place, and the test succeeded, do not use MovePlayer, because the player would be pulled out of the vehicle:
! We presume two other vehicles called Taxicab and PoliceCar were defined elsewhere
room Airport2 "Chase International Airport"
{
vehicle_path Taxicab, PoliceCar, rollsroyce
long_desc
{
"A sign out front says
'Chase International Airport
Welcomes you to the City of Panus
Established 1700, Incorporated 1830.
Chevy Chase County
Established 1750
Incorporated 1910
Welcomes you to the Home of East-Coast University.'
The main pick up/departure roadway continues north and south, while
to the west is a driveway with a sign reading 'Authorized Vehicles Only'"
}
n_to Airport1
s_to Airport3
w_to
{
if (parent(player)=Taxicab or parent(player)=policecar)
{
print "The police waive you through."
Moveplayer(Airport4) ! NO! THIS IS WRONG! THIS WILL PULL THE PLAYER OUT OF THE VEHICLE!
} else {
if (parent(player)=rollsroyce)
"Your vehicle is not authorized."
else:
"Pedestrians are not permitted past this point."
}
}
}
Instead, you need to cover the two conditions, when the user is in a vehicle and when they are not, in the before event:
room Airport2 "Chase International Airport"
{
vehicle_path Taxicab, PoliceCar, rollsroyce
long_desc
{
"A sign out front says
'Chase International Airport
Welcomes you to the City of Panus
Established 1700, Incorporated 1830.
Chevy Chase County
Established 1750
Incorporated 1910
Welcomes you to the Home of East-Coast University.'
The main pick up/departure roadway continues north and south, while
to the west is a driveway with a sign reading 'Authorized Vehicles Only'"
}
before
{
location DoMoveinVehicle
{
! if you have multiple exits, specify each with or between them, e.g. if ((object=e_obj) or (object=nw_obj)) etc
if ((object=w_obj) )
{
if (parent(player) = PoliceCar or parent(player)=Taxicab)
{
print "The Police waive you through "
return false ! This permits the move to go through
} else
"Your vehicle is not authorized."
}
}
}
location DoGo
{
if ((object=w_obj))
{
"Pedestrians are not permitted past this point. "
return true ! This is optional, it happens automatically
}
}
! If neither of these were the case or they weren't traveling west, the go or drive command
! proceeds as if this code was not here
}
n_to Airport1
s_to Airport3
w_to Airport4 ! this will be overridden by the 'before' event
}
In the above example, a police car or taxi can be driven west, but you can’t walk there or drive the Rolls.
Lurking Forklifts
In the Infocom game The Lurking Horror, there is a forklift that
allows you to drive it with regular navigation commands (GO EAST. N.
WEST.) as long as the forklift is turned on. The following code does
its best approximation of the Lurking Horror behavior. The most
challenging aspect was that DoMoveInVehicle
requires the
word array to have one of the vehicle_verb
words in
it, so we had to use InsertWord to make room
for it if the player had typed a one-word command like “NORTH.”
room basement "Basement"
{
e_to tempbase
u_to compcenter
vehicle_path forklift
before
{
location DoMoveinVehicle
{
if object = u_obj
"The forklift won't fit into the stairwell."
else
return false
}
}
}
room compcenter "Computer Center"
{
d_to basement
}
vehicle forklift "forklift"
{
article "the"
noun "forklift"
in basement
prep "on", "off"
short_desc
"There is a forklift here."
long_desc
"It is a rusty and wheezing old forklift. It looks like you could control it fairly easy, though."
vehicle_verb "go" "drive" "ride" ! "go" is first so it still says "You can't go that way."
vehicle_move
{
if self is not switchedon
{
"You can't go anywhere in a forklift that isn't running."
return false
}
else
return true
}
before
{
object DoSwitchOn, DoSwitchoff
{
if parent(player) ~= self
"You'll have to get in it first."
else
return false
}
}
react_before {
if verbroutine = &DoGo and parent(player) = self
{
if object = d_obj, out_obj ! let's interpret >OUT and >DOWN
{ ! as getting out of the forklift
words = 0 ! stop SetupDirectionObjects from
verbroutine = 0 ! resetting the object (it's called by
object = out_obj ! Perform)
return false
}
if self is switchedon
{
if words > 1
word[1] = "drive"
else
{
InsertWord(1)
word[1] = "drive"
}
Perform(&DoMoveInVehicle, object)
return true
}
else
{
"You can't go anywhere in a forklift that isn't running."
return true
}
}
return false
}
after
{
object DoSwitchOn
{
"The forklift sputters to life."
}
object DoSwitchOff
{
"The forklift coughs ones, and dies."
}
object DoListen
{
"At the moment, the forklift is quiet as a graveyard."
}
object DoExit
{
"You are now on your feet."
}
}
is switchable
}
room tempbase "Temporary Basement"
{
w_to basement
e_to deadstorage
vehicle_path forklift
before
{
location DoMoveinVehicle
{
if object = u_obj
"The forklift won't fit into the stairwell."
else
return false
}
}
}
room deadstorage "Dead Storage"
{
w_to tempbase
vehicle_path forklift
is not light
}
replace NewVMessages(r, num, a, b)
{
select r
case &DoSwitchOn
{
select num
case 1: {
if object = forklift
"It's wheezing away already."
else
print CThe(object); IsorAre(object); " already turned on."
}
case 2: return false
}
case &DoSwitchOff
{
select num
case 1: {
if object = forklift
"It's already off."
else
print CThe(object); IsorAre(object); " already turned off."
}
case 2: return false
}
case else : return false
return true ! this line is only reached if we replaced something
}
replace DarkWarning
{
"It is pitch black."
}
Shenanigans
In the above example, we had to do several things in the react_before property so that “down” would an acceptable direction for leaving the forklift:
- We changed the object from
d_obj
toout_obj
so that DoGo doesn’t automatically print a “You’ll have to get off” message. - We cleared the words global so that when
SetupDirectionObjects is called
by Perform, it doesn’t reset the
object global back to
d_obj
- We clear the verbroutine global so that
DoGo
can’t call the vehicle class’sbefore
property.