Index / Last updated: Oct 2007
The plan was to make the NPCs wander around the CE Realm at random. This is how I did it.
First, I told the rooms where all the exits are. That is, all the exits that the NPCs may use. For example, in the Spaceport Lobby (#8856), there are six exits, but only five are valid for the NPCs to use. They are: north (#8911), west (#10753), east (#8894), south (#8994), and down (#9150). So the code to teach the Lobby about its exits is:
@field #8856 = nexits : 5 @field #8856 = exit_0 : 8911 @field #8856 = exit_1 : 8994 @field #8856 = exit_2 : 10753 @field #8856 = exit_3 : 8894 @field #8856 = exit_4 : 9150 |
It doesn't matter in what order the exits are listed, but I numbered them starting from 0, because I knew I'd be using @rand() to pick from them randomly. I did this for every room that the NPCs could visit.
Second, select one object (or room) as the master control object, and teach it who all the NPCs are. My master control object is the Elder (#10633), and since all my NPCs are aliens, the code looks like:
@field #10633 = alien_plant : 10881 @field #10633 = alien_laser : 10876 @field #10633 = alien_silencer : 10389 @field #10633 = alien_healer : 10403 @field #10633 = alien_calculator : 10649 @field #10633 = alien_dragon : 10647 ...etc... |
This part was easy, since I only plan to use @fieldloop() to cycle thru the aliens, and I didn't care what order that @fieldloop() would process them in.
Third, I taught the Elder how to move just one
alien. This code assumes that I've previously set the the_alien
and the the_room
fields:
@field #10633 = the_alien : 10390 // Which alien am I moving? @field #10633 = the_room : 9000 // Which room is it moving from? @field #10633 = the_exit : 9121 // Which exit is it using? @field #10633 = the_newroom : 9000 // Which room is it moving to? // If there are less than 1 exits from the_room, do nothing. // Else do_wander2 50-percent of the time. @field #10633 = do_wander : @switch(1,@lt(@getfield(@g("the_room"),"nexits"),1), "", @rand(2),@call("10633","do_wander2")); // First, calculate which of the_room's exits will be the_exit. // Second, calculate the_newroom, the room that exit goes to. // If the exit has a destination, use the exit's normal osuccess // and odrop messages to inform the two rooms of the alien's movement, // and of course, move the alien inbetween the osuccess and odrop. // Else test the exit's lock2, and use the exit's osuccess2, odrop2, // and action2 fields as appropriate. [this latter bit was added later // to handle semi-locked exits like the washrooms] @field #10633 = do_wander2 : @s("the_exit",@getfield(@g("the_room"),@print("exit_", @rand(@getfield(@g("the_room"),"nexits"))))); @s("the_newroom",@getfield(@g("the_exit"),"action")); @switch(1,@not(@eq(@g("the_newroom"),-3)),@print( @tellroom(@g("the_room"),"",@print( @shortname(@g("the_alien"))," ", @getfield(@g("the_exit"),"osuccess"))), @move(@g("the_alien"),@g("the_newroom")), @tellroom(@g("the_newroom"),"",@print( @shortname(@g("the_alien"))," ", @getfield(@g("the_exit"),"odrop"))) ), @call(@g("the_exit"),"lock2"),@print( @s("the_newroom",@getfield(@g("the_exit"),"action2")), @tellroom(@g("the_room"),"",@print( @shortname(@g("the_alien"))," ", @getfield(@g("the_exit"),"osuccess2"))), @move(@g("the_alien"),@g("the_newroom")), @tellroom(@g("the_newroom"),"",@print( @shortname(@g("the_alien"))," ", @getfield(@g("the_exit"),"odrop2"))))); |
Fourth, I taught the Elder the each_turn
routine,
which moves all the aliens each turn. (What do I mean by "each turn"?
Keep reading.)
@field #10633 = each_turn : @fieldloop(10633,"alien_",@print( @s("the_alien","%v"), @s("the_room",@location(@g("the_alien"))), @switch(@getfield(@g("the_alien"),"task"), "wander",@call(10633,"do_wander")) )); |
Note, my true version of each_turn
does more than this,
but I wanted to simplify things here a bit.
Also note, the way my code is written, only aliens whose task
field is "wander" will wander. In the future, aliens will get new
tasks, but in the meantime:
@field plant = task : wander @field assassin = task : wander @field mind = task : wander @field philanthropist = task : wander ...etc... |
Fifth, I changed all of my descriptions to call the Elder's
each_turn
function. That means, all my room descriptions, all my
object descriptions, and all my exit descriptions. So whenever a player
"looks" at anything that's mine, the NPCs will take a turn.
What this usually means is that I wrapped the description in a @tell();
followed by @call(10633,"each_turn")
. It's not okay to use @print
instead
of @tell
, because of the timing of what gets printed when.
Books are exempt from this fun, because of how signing works. But for everything else, I had to be ruthless...
@desc here = @tell("%#","The lobby is both the entrance/exit point to the Cosmic Encounter Realm, but also at the hub of a major spaceport in the vicinity of the dread Warp. The curious traveller can explore strange new worlds, meet exotic aliens, solve a puzzle or two, or just play \"tourist\". Come in and have fun!"); @call(10633,"each_turn"); @desc desk = @tell("%#","A large block of black onyx serves as the information desk for the lobby. It hardly seems practical. There is a guestbook on the desk."); @call(10633,"each_turn"); @desc mind = @tell("%#","Oh, lovely. It's a big ambulatory brain. Since its one large eyeball is sporting an equally large false eyelash, you suppose that it must be a girl."); @call(10633,"each_turn"); @desc north = @tell("%#","To the north, you see the North Departure Lounge. From there, you can board shuttles to the gas giant, space dust, and rings systems."); @call(10633,"each_turn"); ...etc...etc...etc... |
That handled "looking". Next step, "taking"...
Sixth, I changed all of my objects' @success
and
@fail
messages to also call each_turn
. And @fail
messages for exits, too, if applicable. But I didn't change
the @success
messages for normal exits, since the room description
on the player's arrival would already call each_turn
.
And of course, I had to change the @success
and
@fail
messages of actions on objects, too -- unless they move a
player to another one of my rooms, in which case I can leave it alone.
Seventh and last, I changed any special fields like eat, search, push,
pull, etc. to likewise call each_turn
, in case players want to
use any of those actions too.
And that's how I made NPCs move about on their own in my area in the ifMUD.