home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
vsiftp.vmssoftware.com
/
VSIPUBLIC@vsiftp.vmssoftware.com.tar
/
FREEWARE
/
FREEWARE40.ZIP
/
xsokoban-31
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-06-16
|
16KB
|
383 lines
#include <stdio.h>
#ifdef VMS
#include "pwd.h"
#else
#include <pwd.h>
#endif
#include <X11/Xlib.h>
/* #ifdef VMS */
/* #define CADDR_T */
/* #endif */
#include <X11/Xresource.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "externs.h"
#include "globals.h"
#include "options.h"
#include "errors.h"
/* useful globals */
Boolean scoring = _true_ ;
short level, packets, savepack, moves, pushes, rows, cols ;
unsigned short scorelevel, scoremoves, scorepushes ;
POS ppos ;
char map[MAXROW + 1][MAXCOL + 1] ;
char *username = NULL, *progname = NULL, *bitpath = NULL ;
XrmDatabase rdb ;
static short optlevel = 0, userlevel ;
static Boolean optshowscore = _false_, optmakescore = _false_ ,
optrestore = _false_, superuser = _false_, optmerge = _false_;
static struct passwd *pwd ;
/* do all the setup foo, and make sure command line gets parsed. */
#ifdef VMS
int
#else
void
#endif
main(int argc, char **argv)
{
short ret = 0, ret2 = 0 ;
#ifdef VICE
Authenticate() ;
#endif
scorelevel = 0 ;
moves = pushes = packets = savepack = 0 ;
/* make the program name be what it is invoked with */
#ifdef VMS
progname = strrchr(argv[0], ']') ;
#else
progname = strrchr(argv[0], '/') ;
#endif
if(progname == NULL)
progname = argv[0] ;
else
progname++ ;
/* find out who is playing us. (pwd will be kept around in case we need to
* build the Xresources stuff later.
*/
#ifndef VMS
pwd = getpwuid(getuid()) ;
if(pwd == NULL)
#else
username = getenv("USER") ;
if (username == NULL)
/* we MUST be being played by somebody, sorry */
ret = E_NOUSER ;
#endif
else {
/* find out who we are. */
#ifndef VMS
username = pwd->pw_name ;
/* see if we are the superuser */
#endif
/* JLauret 13-Jun-97 -- I don't see why this would not work under VMS */
/* SUPERUSER have to be uppercased that's all */
superuser = (strcmp(username, SUPERUSER) == 0) ? _true_ : _false_ ;
#ifdef DEBUG
printf("SuperUser : %d\n",superuser) ;
#endif
/* Parse the command line */
ret = CheckCommandLine(&argc, argv) ;
if(ret == 0) {
if(optshowscore)
ret = OutputScore(optlevel) ;
else if(optmakescore) {
if(superuser) {
/* make sure of that, shall we? */
ret = GetGamePassword() ;
if(ret == 0)
ret = MakeNewScore() ;
} else
/* sorry, BAD superuser */
ret = E_NOSUPER ;
} else if(optrestore) {
ret = RestoreGame() ;
} else if(optmerge){
#ifdef DEBUG
MergeScore() ;
#else
ret = GetGamePassword() ;
if(ret == 0)ret = MergeScore() ;
#endif
} else {
ret = GetUserLevel(&userlevel) ;
if(ret == 0) {
if(optlevel > 0) {
#if !ANYLEVEL
if (userlevel < optlevel) {
if (superuser) {
/* superusers can play any level (but not score),
* which is useful for testing out new boards.
*/
level = optlevel ;
scoring = _false_ ;
} else {
ret = E_LEVELTOOHIGH ;
}
} else
#endif
level = optlevel ;
} else
level = userlevel ;
}
}
}
}
if(ret == 0) {
/* play till we drop, then nuke the good stuff */
ret = GameLoop() ;
DestroyDisplay() ;
}
/* always report here since the game returns E_ENDGAME when the user quits.
* Sigh.. it would be so much easier to just do it right.
*/
Error(ret) ;
/* see if they score, and do it (again report an error */
if((scorelevel > 0) && scoring) {
ret2 = Score(_true_) ;
Error(ret2) ;
}
/* exit with whatever status we ended with */
switch(ret)
{
case E_ENDGAME:
case E_SAVED:
ret = 0; /* normal exits */
break ;
}
exit(ret) ;
}
/* Oh boy, the fun stuff.. Follow along boys and girls as we parse the command
* line up into little bitty pieces and merge in all the xdefaults that we
* need.
*/
short CheckCommandLine(int *argcP, char **argv)
{
XrmDatabase command = NULL, temp = NULL ;
char *res ;
char buf[1024] ;
int option ;
/* let's do this the sensible way, Command line first! */
/* we will also OPEN the display here, though we won't do anything with it */
XrmInitialize() ;
/* build an XrmDB from the command line based on the options (options.h) */
XrmParseCommand(&command, options, sizeof(options)/sizeof(*options) ,
progname, argcP, argv) ;
/* okay, we now have the X command line options parsed, we might as well
* make sure we need to go further before we do. These command line options
* are NOT caught by XrmParseCommand(), so we need to do them ourselves.
* Remember, they are all exclusive of one another.
*/
for(option = 1; option < *argcP; option++) {
if(argv[option][0] == '-') {
switch(argv[option][1]) {
case 'm':
optmerge = _true_ ;
break ;
case 's':
if(optshowscore || optmakescore || optrestore || (optlevel > 0))
return E_USAGE ;
optshowscore = _true_ ;
optlevel = atoi(&argv[option][2]) ;
if (optlevel == 0 && argv[option+1] &&
argv[option+1][0] != '-') {
optlevel = atoi(argv[option+1]) ;
option++ ;
}
break ;
case 'c':
if(optshowscore || optmakescore || optrestore || (optlevel > 0))
return E_USAGE ;
optmakescore = _true_ ;
break ;
case 'r':
if(optshowscore || optmakescore || optrestore || (optlevel > 0))
return E_USAGE ;
optrestore = _true_ ;
break ;
default:
if(optshowscore || optrestore || optmakescore || (optlevel > 0))
return E_USAGE ;
optlevel = atoi(argv[option]+1) ;
if(optlevel == 0)
return E_USAGE ;
break ;
}
} else
/* found an option that didn't begin with a - (oops) */
return E_USAGE ;
}
if (optshowscore || optmakescore) return 0; /* Don't mess with X any more */
/* okay.. NOW, find out what display we are currently attached to. This
* allows us to put the display on another machine
*/
res = GetDatabaseResource(command, "display") ;
/* open up the display */
dpy = XOpenDisplay(res) ;
if(dpy == (Display *)NULL)
return E_NODISPLAY ;
display_alloc = _true_ ;
/* okay, we have a display, now we can get the std xdefaults and stuff */
res = XResourceManagerString(dpy) ;
if(res != NULL)
/* try to get it off the server first (ya gotta love R4) */
rdb = XrmGetStringDatabase(res) ;
else {
/* can't get it from the server, let's do it the slow way */
/* try HOME first in case you have people sharing accounts :) */
res = getenv("HOME") ;
if(res != NULL)
strcpy(buf, res) ;
else
/* no HOME, let's try and make one from the pwd (whee) */
strcpy(buf, pwd->pw_dir) ;
strcat(buf, "/.Xdefaults") ;
rdb = XrmGetFileDatabase(buf) ;
}
/* let's merge in the X environment */
res = getenv("XENVIRONMENT") ;
if(res != NULL) {
temp = XrmGetFileDatabase(res) ;
XrmMergeDatabases(temp, &rdb) ;
}
/* now merge in the rest of the X command line options! */
XrmMergeDatabases(command, &rdb) ;
return 0 ;
}
/* we just sit here and keep playing level after level after level after .. */
short GameLoop(void)
{
short ret = 0 ;
/* make sure X is all set up and ready for us */
ret = InitX() ;
if(ret != 0)
return ret ;
/* get where we are starting from */
if(!optrestore)
ret = ReadScreen() ;
/* until we quit or get an error, just keep on going. */
while(ret == 0) {
ret = Play() ;
if((scorelevel > 0) && scoring) {
int ret2 ;
ret2 = Score(_false_) ;
Error(ret2) ;
scorelevel = 0 ;
DisplayScores() ;
}
if(ret == 0) {
level++ ;
moves = pushes = packets = savepack = 0 ;
ret = ReadScreen() ;
}
}
return ret ;
}
/* Does this really need a comment :) */
short GetGamePassword(void)
{
#ifdef VMS
int status ;
printf("Password: ") ;
/* A better way might exist to perform a SET TERM/NOECHO */
status = system("SET TERMINAL/NOECHO") ;
if(!status){
printf("Terminal is not secure. Abort") ;
return 0 ;
} else {
char passwd[80] ;
/* Get it now */
scanf("%s",passwd) ;
system("SET TERMINAL/ECHO") ;
return ( (strcmp(passwd,PASSWORD) == 0) ? 0 : E_ILLPASSWORD) ;
}
#else
return ((strcmp(getpass("Password: "), PASSWORD) == 0) ? 0 : E_ILLPASSWORD);
#endif
}
/* display the correct error message based on the error number given us.
* There are 2 special cases, E_ENDGAME (in which case we don't WANT a
* silly error message cause it's not really an error, and E_USAGE, in which
* case we want to give a really nice list of all the legal options.
*/
void Error(short err)
{
switch(err) {
case E_FOPENSCREEN:
case E_PLAYPOS1:
case E_ILLCHAR:
case E_PLAYPOS2:
case E_TOMUCHROWS:
case E_TOMUCHCOLS:
case E_NOUSER:
case E_FOPENSAVE:
case E_WRITESAVE:
case E_STATSAVE:
case E_READSAVE:
case E_ALTERSAVE:
case E_SAVED:
case E_TOMUCHSE:
case E_FOPENSCORE:
case E_READSCORE:
case E_WRITESCORE:
case E_USAGE:
case E_ILLPASSWORD:
case E_LEVELTOOHIGH:
case E_NOSUPER:
case E_NOSAVEFILE:
case E_NOBITMAP:
case E_NODISPLAY:
case E_NOFONT:
case E_NOMEM:
case E_NOCOLOR:
fprintf(stderr, "%s: %s\n", progname, errmess[err]) ;
if(err == E_USAGE)
Usage() ;
break ;
default:
if(err != E_ENDGAME)
fprintf(stderr, "%s: %s\n", progname, errmess[0]) ;
break ;
}
}
/* this simply prints out the usage string nicely. */
void Usage(void)
{
short i ;
fprintf(stderr, USAGESTR, progname) ;
for (i = 0; usages[i] != NULL; i++)
fprintf(stderr, "%s", usages[i]) ;
}