sokoban.h
It is common practise to put configuration parameters as define'd
values in include files.
/***********************************************************************
You may wish to alter the following directory paths
***********************************************************************/
/**/
/* SCREENPATH: the name of the directioy where the screen file are held */
/**/
#define SCREENPATH "/usr/local/lib/sokoban/screens"
/**/
/* SAVEPATH: the name of the path where save files are held */
/* Attention: Be sure that there are no other files with */
/* the name .sav */
/**/
#define SAVEPATH "/usr/local/lib/sokoban"
/**/
/* LOCKPATH: temporary file which is created to ensure that no users */
/* work with the scorefile at the same time */
/**/
#define LOCKFILE "/tmp/sok.lock"
/**/
/* SCOREFILE: the full pathname of the score file */
/**/
#define SCOREFILE "/usr/local/lib/sokoban/sok.score"
/**/
/* MAXUSERNAME: defines the maximum length of a system's user name */
/**/
#define MAXUSERNAME 10
Potential for obscure error in ``MAXUSERNAME''. The user's name is found from
a system call, ``getpwuid''. This returns a pointer to a structure of type
``passwd'' with a field
char *pw_name;
This field may be of any length, not just 10. The Unix standard does not
specify a limit. The global variable
char *username;
is set to point to this in ``main'', and later may be copied to an array
of players in function ``makescore''. This is done by a ``strcpy'', not
a ``strncpy'' so may overwrite a piece of memory
if the name is actually longer than ``MAXUSERNAME'', causing a random crash
at some stage.
/**/
/* MAXSCOREENTRIES: defines the maximum numner of entries in the scoretable */
/**/
#define MAXSCOREENTRIES 50
/**/
/* SUPERUSER: defines the name of the game superuser */
/**/
#define SUPERUSER "root"
/**/
/* PASSWORD: defines the password necessary for creating a new score file */
/**/
#define PASSWORD "nabokos"
This is a simple game, but storing a password in plain text is not really
a good idea. It will appear as a string in the program, and may be tracked
down.
/**/
/* OBJECT: this typedef is used for internal and external representation */
/* of objects */
/**/
typedef struct {
char obj_intern; /* internal representation of the object */
char obj_display; /* display char for the object */
short invers; /* if set to 1 the object will be shown invers */
} OBJECT;
This structure never got a structure name, only a typedef synonym.
That doesn't matter, because it isn't a recursive structure requiring
a self-reference.
/**/
/* You can now alter the definitions below.
/* Attention: Do not alter `obj_intern'. This would cause an error */
/* when reading the screenfiles */
/**/
static OBJECT
player = { '@', '@', 0 },
playerstore = { '+', '@', 1 },
store = { '.', '.', 0 },
packet = { '$', '$', 0 },
save = { '*', '$', 1 },
ground = { ' ', ' ', 0 },
wall = { '#', ' ', 1 };
That was a nasty piece of code!
You should never define (i.e. associate a name with a piece of memory)
any variables in include files.
What happens here is subtle. Each ``.c'' file includes this file. So,
after the preprocessor has been over the ``.c'' file, it now contains a
copy of the above definition.
The definition is for a static variable,
so that it only has file scope. That is, each file has a set of
variables ``player'', ``playerstore'', etc that are local to that file.
So in file sok.c there is variable ``player'', and in file ``score.c''
there is a variable ``player'' and these are not the same variable!
The intent is to allow you to customise the appearance of each object.
This would be better done in the include file by
#define PLAYER {'@', '@', 0}
extern OBJECT player;
and in one of the files (say sok.c)
OBJECT player = PLAYER;
as a global variable.
Anyway, after all that, the effect is to create structure variables with
all fields intialised. The statement
OBJECT player = {'@', '@', 0};
is equivalent to
OBJECT player;
player.obj_intern = '@';
player.obj_display = '@';
player.invers = 0;
(although this would not be legal C).
/*************************************************************************
********************** DO NOT CHANGE BELOW THIS LINE *********************
*************************************************************************/
The following stuff is all good practise.
Note the prefix ``E_'' (for error).
This means there is less likelihood of name clashes with
other define's.
#define MAXROW 20
#define MAXCOL 40
typedef struct {
short x, y;
} POS;
#define E_FOPENSCREEN 1
#define E_PLAYPOS1 2
#define E_ILLCHAR 3
#define E_PLAYPOS2 4
#define E_TOMUCHROWS 5
#define E_TOMUCHCOLS 6
#define E_ENDGAME 7
#define E_NOUSER 9
#define E_FOPENSAVE 10
#define E_WRITESAVE 11
#define E_STATSAVE 12
#define E_READSAVE 13
#define E_ALTERSAVE 14
#define E_SAVED 15
#define E_TOMUCHSE 16
#define E_FOPENSCORE 17
#define E_READSCORE 18
#define E_WRITESCORE 19
#define E_USAGE 20
#define E_ILLPASSWORD 21
#define E_LEVELTOOHIGH 22
#define E_NOSUPER 23
#define E_NOSAVEFILE 24