File: code.txt

package info (click to toggle)
aime 0.60.3-7
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 6,016 kB
  • ctags: 5,217
  • sloc: cpp: 77,611; ansic: 3,765; sh: 2,996; makefile: 234; sed: 93
file content (481 lines) | stat: -rw-r--r-- 24,467 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481

                       The AIME Codebase Code Description

An Overview:

   The AIME code (stands for Advanced Interactive Mudding Environment) was 
started over a year ago because of the perceived inadequacies of the Aber code. 
In designing the code, attention was placed on flexibility and efficiency.  
The idea was to provide the mud creator an easy way to create almost anything 
he or she could think of without requiring them to touch the code very much.  
It uses an object-oriented design to facilitate flexibility and variety in 
object/location/mobile types without requiring large memory signatures per
object.  Mud games provide an excellent environment for Object-Oriented design 
since everything is essentially an object in the game of some sort or another. 
   The AIME code has been designed to be as flexible and as efficient as 
possible.  Effort has been placed into ensuring this, but you may find 
something that you think could be done better a different way and if so, 
please let Slate (noelg@acm.org) know.
   Before reading this or starting to code on the mud, you should have a
fairly good understanding of both C++ and object-oriented design, as the
mud has been designed using many of those design methods.

The Configs Object:

   Configuration information for the AIME codebase is loaded into the_config
object  (Configs class, defined in configs.h) from the first file found of
"../data/aime.conf", "./aime.conf", "./data/aime.conf",  "/etc/aime.conf",    
or "/etc/aime/aime.conf". Or if not found, the user is prompted for its location.

The Main Mud Object:

   The entire mud is run by a single mud object (Mud class, defined in mud.h), 
which maintains everything from the player list and object database to the 
listening socket.  The only globally defined variable should be mainstruct, 
which is a pointer to the Mud object.  When the mudbin executable is run, it 
first creates the Mud object, daemonizes the mud (if "Daemonize"  is set to
yes in the aime.conf file) and then starts the main mud loop.

   When the Mud object is created, the constructor function (Mud() in mud.cc) 
is run and initializes all objects needed for the functioning of the mud.  
First, logs are started, then the mud is "bootstrapped", meaning it loads all 
environment variables, areas, actions, and levels into memory.  It then starts 
the user database manager, and finally the game and builder listening ports are 
initialized and started.

   Once the mud is loaded, it then starts up all game timers (objects that keep
track of things like game time, weather changes, time of day changes, checks
mobiles for action, etc) and enters into the main loop (located in main.cc).
First, it checks to see if the mud is shutting down and if not, checks for
quitting players.  It then checks all players for activity, all builders for
activity, and finally checks the mud for events.  An event could be something
like mobiles moving, attacking players, or a torch burning out.

   This main loop is where all mud activity takes place.  If input is found
while checking the players, it handles it...possibly running commands that
manipulate things on the mud.  The commands can access mud structures in 
the main Mud object, such as the object database, the user database, or even
send messages to other players.  The Mud object acts as a central repository,
bringing together all aspects of the mud.

   The following objects are contained in the Mud object and described in
detail.


The Port Object:

   The Port object is the listening port that accepts connections.  When a
player connects to the mud, the listening socket will detect their connection, 
accept or deny it (based on an access control list located in the Mud object
as GameAccess and BldrAccess object), and create the Player or Builder 
(depending on the port).  It creates a Connection object (described later  
on) that handles all user activity, such as receiving input or sending room 
descriptions to the player.  You can set how often it checks the listening 
port in the aime.conf file, with the "PollsPerSec" setting.  


The Access_List Object:

   The Access_List object called builder_access_list for the builder port or
game_access_list for the game port, maintains the list of hosts that can 
access the specified port.  It permits for defining a security default (allow
by default, deny by default) and then a list of hosts which are exceptions
to the default.  If the access list denies a host, it is allowed to connect
only long enough to inform the connection that it has been refused access.


The Object_List Object:

   The Object_List object called mudobjects maintains the entire object
database that stores all the areas in the mud.  It consists of a binary tree 
(uses the class btree_a to maintain this list) of Area_Dbase objects 
(discussed next) which in turn store all objects in the game, from weapons to 
spells to quests.  The Object_List object provides methods for adding, 
removing, and retrieving objects in the database.  It also provides the 
cloning method which allows you to safely duplicate objects in the mud.  It 
also manages resetting of zones, ensuring safe reloads without game objects 
getting messed up.


The Area_Dbase Object:

   The Area_Dbase object is what stores most of the game 'objects', ranging 
from mobiles to locations.  It also stores objects on the builder port when 
a builder loads an area.  Even help files are stored in an Area_Dbase when 
the builder loads the help area.  They can then modify help files and 
'commit' them, which writes all help files back with the new changes.  
Area_Dbase objects provide the means to gracefully reload zones on a lower 
level than the Object_List object.  Spells and Skills (Abilities) are 
stored in an Area_Dbase object during gameplay and retrieved when a player 
casts or performs them.  The objects in the Area_Dbase object are stored in 
a binary tree for fast lookup (the btree_l object handles this binary tree) 
(with a linked list also present to facilitate searching through all objects) 
and are stored as Entity objects (discussed later).


Verb_List Object:

   The Verb_List object exists in two places in the Mud object.  The first 
handles all commands available for the game port and the second all commands 
available to the builder port.  It stores both verbs and actions in a modified 
lexical tree.  (The lextree object handles all methods and attributes for 
this)  The tree is modified in that there is only one node per word, as 
opposed to the normal way of doing a lexical tree which would provide one 
node per letter of that word.  The modified lextree is much more efficient 
memory-wise and has a faster lookup than conventional lextrees.  However, it 
does have a much less efficient add and delete function.  Since we rarely add 
or delete after the first bootstrap, this is not really a problem.  A Verb 
object stores the verbs in the lextree and an Action object stores the 
actions.  The Verb object stores permissions for that verb (see comflags.h 
for command flag permissions) and a pointer to the function that should be 
run.  An Action object stores the strings that a player sees when they 
perform an action.  


Player Object (subclass of Individual, discussed later):

   The player object, attached to the Mud object by a linked list, is what 
stores all player attributes and handles much of the player interaction with 
the mudworld.  It provides functions to interact with the Connection object, 
which handles the player's network connection (discussed more later on).  It 
manages name, prompt, description, abilities (spells and skills), getting 
objects into the inventory, dropping objects, and storing and reading data 
to and from the player's data file.  It provides means for sending text to 
the player's screen and allowing the player to see their completed quests.


Builder Object (subclass of MudObject, discussed later):

   The builder object, attached to the Mud object by a linked list, is what
handles the builder's interaction with the building port.  It handles loading
zones (stored in the Builder object with an Area_Dbase object), modifying
of objects in that zone, and interaction with the builder's network connection,
attached to the builder with a Connection object. 


Connection Object:

   When a new connection is received at the Port object, it creates a Connection
object.  On creation, the Connection object will accept the connection, store
the IP and host (if it can get the host), and initialize the socket for non-
blocking (meaning if it does not receive data it won't keep trying to find data
until it does and hang the mud).  The Connection object handles attributes of
the connection, such as should it use color, have we lost connection and if so,
how long ago (for linkdead purposes). It maintains the read and write buffer for
more efficient socket functioning.  It also modifies incoming data to a form the
mud can read, as well as modifying outgoing data to a form the player's client
can read.  This involves such things as converting the colorcodes to ANSI color
codes and adding \r to lines if necessary.


User_Dbase Object:

   The User_Dbase object maintains the player database.  When a player tries to
logon, the Port object will create the Player object (and subsequently, the
Connection object will be created) and a login input handler will be pushed onto
the player's Inp_Handler stack (discussed next).  The login functions will ask
the player for their name and when received, it will turn to the User_Dbase
object to request data on a user by that name.  It will fill the Player (or 
Builder) object with that data, including the password, and then ask the player
for the password, comparing with what it loaded from the User_Dbase object.
The player data is stored in a directory (one for each letter of the alphabet)
as <name>.user under the ~/aime/data/users directory.  


Inp_Handler Object:

   The Inp_Handler object is attached to a Player object, and controls which
input handler function should be used to gather input from the player.  It
consists of a stack of handlers, which store information on that handler, such
as the prompt to use, the command to run, what function to run (if any) when the
input handler is popped.  It also can store data, such as a Pager object
(discussed next) and Mailer object to interact with.  The main input handler
should always be there and it gets the player's input and runs the appropriate
command based on that input (all commands are located in commands.cc, 
bcommands.cc, and jcommands.cc).  When a player enters the mailer, the mailer
input handler is pushed on the stack and will interpret all commands until it
is popped, where it will refer back to the last input handler.  


Pager Object:

   The Pager object provides a means to control output to the player.  When
created and a string or file is passed to it, the pager will push a pager
input handler on the stack and it will display x number of lines, prompting
the user to press enter to continue.  Once all lines have been displayed, it
will pop the pager input handler and return to the previous input handler.


Level_List Object:

   The Level_List object controls the list of levels for gameplay.  Levels are
stored in Level_Chain objects, which store the Level objects (discussed next)
in a sorted linked list from lowest level to highest.  The Level_Chain objects
are stored in the Level_List object in a linked list, which basically just
manages the list and provides methods for searching out levels, adding levels, 
and checking to see if a player has advanced a level.  


Level Object:

   The Level object maintains all data on a certain level, from what criteria a
player must meet to advance to this level to the string to display when they
do advance.  When a player has their level checked via the Level_List object,
it checks their current level in the chain, checks the criteria in the next
level to see if the player meets it, and if needed, advances the player level.
On level advance, the award_string string is displayed to the player telling
them that they have advanced a level. 


Logs Object:

   The Logs object maintains the various logs in the game.  It provides methods
for opening the logs, archiving the logs, displaying the logs, and finally 
closing the logs.  Various subclasses define particular attributes for each log.
In addition to the inherited Logs methods, the ErrLog subclass provides a method
to write errors to the logfile.  The SysLog subclass is similar, providing a
tailored method to write system log entries.  Finally, the Data_Log subclass
provides methods to allow the players to submit information to the mud
administration.  This is used in the suggestions log, the bug log, and the typo
log.


Timing Object:

   The Timing Object maintains the game clock and keeps track of how long it
has been since we performed a particular action.  The game may up a player's
health once every 3 seconds, and this object keeps track of how many seconds
it has been since the last health increase (gradual healing).  It also keeps
track of the time of day (is it night, morning, etc) and the time since last
level check (checking if players will increase in level).  


   Thats all the objects that are in the Mud Object.  The rest of the Mud
object attributes perform various functions to maintain the game and should
each be documented somewhere in the mud code.  There are a few objects that
have not yet been discussed, (with the exception of Entity and all subclasses,
discussed last) and I will go through them here.


Lexer functions:

   The functions in lexer.cc provide an effective and safe means for reading
in a file.  It divides out words and numbers, placing them in a token and
marking that token with the type of data stored there.  It ensures that in 
the process of reading a file, you don't crash the mud.  If you are going to
read in a file, you should use this to ensure you don't introduce errors into
the code.


LinkedList Object:

   The linkedlist object maintains a linked list that is used in storing the
inventory of any game object.  It stores player's inventory or the contents
of a sack.  


The path of User Input:

   With the normal game or builder input handler, it uses a few objects before
it finally executes the command.  First, the Connection object detects the 
input and reads it in, passing it off to the player's input handler.  The
input handler then creates an Input object which takes the input and
determines the appropriate verb needed.  It then passes the input string to 
a Parse object, which breaks it up into sections depending on the verb format
(see verbs.h for a list of verbs and their assigned formats).  Finally, the
Input object calls the function, passing in the Parse object and a pointer to
the player or builder.


Editor object:

   The Editor Object is used to handle editor sessions.  This provides an
easy way for the user to input multi-line text.  In full mode, the editor
provides functions for inserting, deleting lines, replacing words, and a few
other features.


Flags Object:

   The Flags Object provides for a compact way to represent many flags in one
or more long integers.  On creation, you give it how many sets of 32 flags you
want (how many long ints it should use) and it will then maintain those ints
for you, using methods to give the impression of one large set of flags.  


Mailer object:

   The Mailer object handles the player's mailer.  It maintains attributes
describing the mailer, such as the filename to use and the username who owns
the mailer.  It reads in mail from the file, adds new mail, removes old mail,
and displays mail to the screen.  It holds information such as if the player
has new mail and maintains a linked list of Letter objects.  The letter
contain all the information for each piece of mail, such as the title string,
body string, and if the mail has been read yet.  The Letter object provides
methods for delivering mail to others as well.  The file mailer.cc also
contains the input handler functions for proper mailer functioning.


Strings Object:

   The Strings object provides methods and attributes for maintaining a
string safely.  The idea with the Strings object was to control the
allocation size for a string to ensure that nobody overflows the buffer and
causes big problems.  It was designed to contain most methods so the coder
rarely needed to touch char pointers.  You should never write to a char string
that is in a Strings object without using one of the methods, as it could
really cause problems.  If you do, do so with care.  


Timespan Object:

   The Timespan object is used to keep track of the time elapsed since the
object was created.  It can be used to determine how long it takes a player
to run through a hallway full of flying spears.  I use it to keep track of
how long it takes to do object lookups in Object_List and other database
lookups to ensure the code is efficient.


Object Hierarchy:

   All game objects that the player sees are represented by many different
classes of objects.  From Locations to Weapons and Mobiles, each has a parent
class and its own attributes.  At the top of the object hierarchy is the
Entity object, which includes all the game objects.  The following represents
the heirarchy for all mud objects in the game.

                                   Entity
                                     |
       ------------------------------------------------------------------------
       |         |         |         |         |           |         |       |
    Ability   Specials   Quest   MudObject   Action      Level      Text    Verb
       |                             |
       |                             |
   ----------        ------------------------------------------
   |        |        |           |               |            |
 Spell    Skill   Location     Item         Individual    Builder
                                 |               |
                                 |          ------------
                                 |          |          |
                                 |       Mobile      Player
                                 |
                    --------------------------
                    |            |           |
                  Marker      Moveable      Door
                                 |
        ------------------------------------------------------
        |        |       |       |        |        |         |
       Boat     Book    Key    Merger   Rope     Weapon   Wearable
                                 |
                            -----------
                            |         |
                          Food      Money


Entity Object:

   The Entity object contains a name attribute used to provide a unique
identifier for the particular entity in the area.  If you call a moveable
pebble1, it is the only entity in that area that can be pebble1 (Other areas
can have pebble1 entities).  The main purpose of the Entity class is to
provide a similarity between objects.  This allows us to have areas filled 
with many different types of objects, with only one type of pointer 
(Entity *).  

   Under Entity, you will find various objects that really are not "in"
the game per-say, but the game does use.  The reasons they are classified
as Entity is so that we can edit them on the builder port by loading them
into an Area_Dbase.  The Text object is a good example of this.  It is
merely a way to load help, info, and banner text files onto the game port
and modify them.  When the builder commits, the help files would be written
to the help directory.  In the game port, the help files are read directly
from the file and never loaded into a Text object.  In fact, the Text object
is never used on the game port.  

   Quests, Levels, Spells, Skills, Actions, Specials and Text objects are 
all objects that can be loaded in the builder port and edited.  See the 
builder tutorial for a description of each object and what it is used for.


MudObject Object:

   MudObjects are really the "meat" of the mud.  They are what the player
interacts with during gameplay.  In fact, even the player is a MudObject.
The MudObject class contains all the attributes and methods that you would
find in all MudObjects, such as location of the object and title for that
particular object.  During gameplay, the players never see the actual name
of the MudObject.  That is only for the mud engine.  The title is what they
actually see, so when referring to objects, you should always refer to the
title instead of the name.  

   The MudObject holds the specials attached, which execute whenever a
certain "trigger" is met.  You will have to write in a command to perform
a special check for a certain trigger (the check_specials command in
utils.cc) in the player or builder command.

    MudObjects also hold the inventory of that object.  Using the
LinkedList object, it maintains a linked list of MudObjects that are in
the object.  When a player enters a location, they are added to that 
location's linked list.  When a player gets something, it is added to that
player's linked list.


All Other Objects:

   The MudObject consists of four different subtypes (two of which have 
several subtypes of its own).  The Builder really isn't a part of the 
gameplay and will probably be moved under Entity down the road.  Location 
defines the rooms a player can go to and has attributes to provide links 
to other locations in all directions.  Individual defines anything that 
walks around the mud, from a Player to a Mobile (creature defined by the 
builders).  Finally, the Item object defines any inanimate object ranging
from a Door to a Book.

   The Item object consists of three types.  The Marker object (used for
examinable objects that you can't pick up...a tree for example) and the
Door object are both objects that can't be picked up.  A Moveable object
is any other object that can be picked up and placed into the player's
inventory.  

   All objects in the Moveable object subclasses are described best in the
builder tutorial.  The Merger object and subclasses are unique in that only
one object will be in any inventory at a given time.  The code ensures this.
So if you have a Money object of coins (marked with 50, indicating you have
50 of these when actually you only have one object marked as 50) and you
get an object of coins(30), it will increase the number on your carried
coins object by 30 and delete the one marked 30.  So now you will have one
object in your inventory called coins and marked 80.  Hence where the
name came from, Merger.  The objects merge and divide as necessary to
ensure there is only one in a specific inventory.


Windows Code:

   The windows code is all stored in win32 directory (with a few segments
inside the main src code).  The main dialog box is taken care of in 
aime_w32Dlg.cpp which handles the messages.  A timer is set up to run
the mud which fires every couple of times per second looping through the
mud for events.  It also checks for user connections and handles user
input and output that has been stored in the buffers.  During a bootstrap,
the timers will progressively run more code in the bootstrap function 
(located in mud.cpp) each time the timer code fires.  This makes it so
output will show in the output window of the dialog box and the user can
halt the bootstrap at any time.  They also will have the opportunity if
the need arises to convert data files or create directories.

   In the linux version, all this is handled in main.cpp by a program
loop.


Summary:

   This was a basic overview of the objects in the code and the main
design of the mud.  It should help you get started on coding things into
the mud.  For more details on the specifics of each object, you can check
the code.  If there is anything that is not documented to your liking or
you don't understand and would like it worded a different way, please let
Slate know at noelg@acm.org.  The mud should be documented so that it isn't
too difficult for anyone to write code for it and if not, it should be
corrected.  Any comments or suggestions for the code, something that you
think could be done better another way, please let Slate know (noelg@acm.org).  
Thanks and have fun!