This file is to hopefully detail some of programming guidelines that
people should use when working on crossfire.

function names:  No real standard, but functions that work on commonly
used structures typically use the following:  ob for object structure,
map for map structure, and arch for archetype.  Thus, functions like
insert_ob_in_map inserts an object into the map (both passed as
arguments to the function.)

variable names:  Once again, no real standard.  In general, try to be
descriptive and brief.  op is typically used for object (op = object
pointer?) and pl is used for players.

Indentation:  The orignally standard seemed to be 2 spaces for nested
level.  I personally prefer 4: with 2 spaces, it can be difficult to see
how deeply nested something is.

#ifdef and configurable options:  This is only really needed if the option
may not be desirable for all users.  Cases where things should be
configuration options is when they use non standard libraries (XPM as one
example) or make great and major changes that can be isolated in just a few
#ifdefs.  This is a real grey area of what should and should not be a
configurable option.  If not sure, send me mail and hopefully I can give you
a definitive answer on a case by case basis.

If putting in LOG error messages, it is nice to put in the function
name that the error is occuring in.  Since errors, by definition, should
not be happening, it means that the code needs to be fixed or changed,
and finding out the function where the error occurred makes things easier.

When putting LOG debug messages in your, code, #ifdef with a
local define (ie, #ifdef INPUT_DEBUG or #ifdef TREASURE_DEBUG).  Don't use
the generic DEBUG variable -- If everyone uses that, it just creates to much
output, and becomes meaningless.  Using local defines makes it easy to turn
on debugging information on that area of code, or likewise, turn it off, if
it appears to work correctly.

When adding new fields to structures, use the [s/u]int[8/16/32] types.
These types are meant to be at least that number of bits specified after
the int, while 's' means signed, and 'u' unsigned.  Using these types
will make porting to other systems easier, and for systems that may
have large default values (64 bit ints), the typedefs can be changed so
that uint32 is still 32 bits, and thus save memory.  This is especially
necessary if you are using 8 bit types (normally char's) to store non
character data.  The signedness of char's is not standard.  Thus, if you are
assuming it is signed, and storing negative values, things may not work
properly when it is unsigned.

For functions, using these values is not required, unless you need to make
sure you have at least that precision.  A lot of functions just use
ints for the value in for loops - this value is never likely to so
large that using a special type is needed.

For strings, just use the native 'char' type.  Using sint8 or uint8
probably will not work - at least not on all systems.  Plus, there is
no reason to use those types for strings.

Other notes:
Comments around code changes is also nice.  In many cases, why a change is
being made is not readily apparent, and in these cases, I may not make the
change.

Do not use the same name for function parameters as are typedef's.  Thus,
things like char foo (int spell) should not be used, because spell is a
typedef type.  This is apparantly illegal via ANSI standard, but I guess
most compilers don't check for it.

------------------------------------------------------------------------------
PATCHES:

I prefer patches on a subject basis.  Thus, if you fix up some spell code,
just send that along as a single patch.  Don't make jumbo patches that fixes
half a dozen unrelated things.  It makes it more difficult for me on what is
being changed and why.  Also, if one of the problems your patch fixes has
already been corrected, it then needs to be sorted out by hand instead of not
applying a particular patch.


Patches can be submitted that fix bugs or that add additional features
or otherwise improve the game.  Here are some hints for creating patches
if you do not know how.
  

To make patches, make a diff file of the changes.  Try to only make a diff
file of the pertinent files (ie, I don't need to see all the changes you
might have made to your config.h file, unless you add new options.)  Make a
context diff.  5 lines of context if preferable to the 3 default lines.  To
do this, do:
 
   'diff -c5 (oldfile) (newfile)'

You can also do diffs of entire directories.  Do do this, type:

'diff -c5 -r (old_directory) (new_directory)'

An example:

'diff -c5 -r crossfire-0.90.1 crossfire-0.90.2'. 

This will create a context diff of all the changes made between version 90.1
and 90.2.  Note that this will not include new files, but will include a
message saying that a file exists in one version and not the other.  Also
note that if you do a diff at the top level, diffs will be created for the
various font and archetype files in the lib directory, greatly increasing
the size, and not containing any useful information.

Note that some diff programs (Gnu diff for one) will put new files
into patch archives.  You may need to give special command line options to
do this.

 Please make sure that the actually directory the file is in included (ie,
common, server, etc.)

To send new files (archetypes, or source files), shar archives, or
uuencode tar archives (compressed or gzip'd is fine), are the preferred
method.  IF you have an ftp site available to you, you can put the
files up there instead of mailing them to me, but for smaller
changes, mail is easier for me.

Mail all patches to mark@pyramid.com

------------------------------------------------------------------------------
Special notes:

Some elements in some of the structures should seldom be accessed
directory.  If this was C++, they would probably be private members, with
member functions to get the data.  The following will try to document them:

object->owner: Should never be access directly - get_owner and set_owner
should be used instead.  Those functions set/check refcounts.  What this
means is that if you do a get_owner and the owner has disappeared, you will
get back a null pointer, instead of whatever object is now using that
address (remember that objects get recycled.)

object->nrof: decrease_ob_nr should be used when decreasing the value
(increasing should be done by inserting a new object with a count, and the
insert function will merge them together.)  The reason decrease_ob_nr should
be used is to handle weight properly - if this value is just decreased and
is in some inventory, the weight will not be updated properly.  If it is
situation when it is known that the object is 'removed', then adjustments to
this variable are fine.

  Mark Wedel
mwedel@pyramid.com
