o Add support for zlib compression via ZLIB_COMP in config.h (ZLIB_COMP and COMPRESS are mutually exclusive). o rlecomp and zerocomp are run time options available if RLECOMP and ZEROCOMP are defined, but not turned on by default if either COMPRESS or ZLIB_COMP are defined. o Add information to the save file about internal compression options used when writing the save file, particularly rlecomp and zerocomp support. o Automatically adjust rlecomp and zerocomp (if support compiled in) when reading in an existing savefile that was saved with those options turned on. Still allows writing out of savefile in preferred format. o In order to support zlib and not conflict with compress and uncompress routines there, the NetHack internal functions were changed to nh_uncompress and nh_compress as done in the zlib contribution received in 1999 from <Someone>. I tagged the sources NETHACK_3_5_0_PREZLIB prior to applying these changes.
269 lines
5.4 KiB
C
269 lines
5.4 KiB
C
/* SCCS Id: @(#)bemain.c 3.5 1998/07/15 */
|
|
/* Copyright (c) Dean Luick, 1996. */
|
|
/* NetHack may be freely redistributed. See license for details. */
|
|
|
|
#include "hack.h"
|
|
#include "dlb.h"
|
|
#include <fcntl.h>
|
|
|
|
static void whoami(void);
|
|
static void process_options(int argc, char **argv);
|
|
static void chdirx(const char *dir);
|
|
static void getlock(void);
|
|
|
|
#ifdef __begui__
|
|
#define MAIN nhmain
|
|
int nhmain(int argc, char **argv);
|
|
#else
|
|
#define MAIN main
|
|
#endif
|
|
|
|
|
|
int MAIN(int argc, char **argv)
|
|
{
|
|
int fd;
|
|
char *dir;
|
|
|
|
dir = nh_getenv("NETHACKDIR");
|
|
if (!dir) dir = nh_getenv("HACKDIR");
|
|
|
|
choose_windows(DEFAULT_WINDOW_SYS);
|
|
chdirx(dir);
|
|
initoptions();
|
|
|
|
init_nhwindows(&argc, argv);
|
|
whoami();
|
|
|
|
/*
|
|
* It seems you really want to play.
|
|
*/
|
|
u.uhp = 1; /* prevent RIP on early quits */
|
|
process_options(argc, argv); /* command line options */
|
|
|
|
|
|
#ifdef WIZARD
|
|
if (wizard)
|
|
Strcpy(plname, "wizard");
|
|
else
|
|
#endif
|
|
if(!*plname || !strncmp(plname, "player", 4)
|
|
|| !strncmp(plname, "games", 4))
|
|
askname();
|
|
plnamesuffix(); /* strip suffix from name; calls askname() */
|
|
/* again if suffix was whole name */
|
|
/* accepts any suffix */
|
|
|
|
Sprintf(lock,"%d%s", getuid(), plname);
|
|
getlock();
|
|
|
|
|
|
dlb_init(); /* must be before newgame() */
|
|
|
|
/*
|
|
* Initialization of the boundaries of the mazes
|
|
* Both boundaries have to be even.
|
|
*/
|
|
x_maze_max = COLNO-1;
|
|
if (x_maze_max % 2)
|
|
x_maze_max--;
|
|
y_maze_max = ROWNO-1;
|
|
if (y_maze_max % 2)
|
|
y_maze_max--;
|
|
|
|
/*
|
|
* Initialize the vision system. This must be before mklev() on a
|
|
* new game or before a level restore on a saved game.
|
|
*/
|
|
vision_init();
|
|
|
|
display_gamewindows();
|
|
|
|
if ((fd = restore_saved_game()) >= 0) {
|
|
#ifdef WIZARD
|
|
/* Since wizard is actually flags.debug, restoring might
|
|
* overwrite it.
|
|
*/
|
|
boolean remember_wiz_mode = wizard;
|
|
#endif
|
|
#ifdef NEWS
|
|
if(iflags.news) {
|
|
display_file(NEWS, FALSE);
|
|
iflags.news = FALSE; /* in case dorecover() fails */
|
|
}
|
|
#endif
|
|
pline("Restoring save file...");
|
|
mark_synch(); /* flush output */
|
|
if(!dorecover(fd))
|
|
goto not_recovered;
|
|
#ifdef WIZARD
|
|
if(!wizard && remember_wiz_mode) wizard = TRUE;
|
|
#endif
|
|
check_special_room(FALSE);
|
|
if (discover)
|
|
You("are in non-scoring discovery mode.");
|
|
|
|
if (discover || wizard) {
|
|
if(yn("Do you want to keep the save file?") == 'n')
|
|
(void) delete_savefile();
|
|
else {
|
|
nh_compress(fqname(SAVEF, SAVEPREFIX, 0));
|
|
}
|
|
}
|
|
|
|
flags.move = 0;
|
|
} else {
|
|
not_recovered:
|
|
player_selection();
|
|
newgame();
|
|
if (discover)
|
|
You("are in non-scoring discovery mode.");
|
|
|
|
flags.move = 0;
|
|
set_wear();
|
|
(void) pickup(1);
|
|
}
|
|
|
|
moveloop();
|
|
return 0;
|
|
}
|
|
|
|
static void whoami(void)
|
|
{
|
|
/*
|
|
* Who am i? Algorithm: 1. Use name as specified in NETHACKOPTIONS
|
|
* 2. Use $USER or $LOGNAME (if 1. fails)
|
|
* The resulting name is overridden by command line options.
|
|
* If everything fails, or if the resulting name is some generic
|
|
* account like "games", "play", "player", "hack" then eventually
|
|
* we'll ask him.
|
|
*/
|
|
char *s;
|
|
|
|
if (*plname) return;
|
|
if (s = nh_getenv("USER")) {
|
|
(void) strncpy(plname, s, sizeof(plname)-1);
|
|
return;
|
|
}
|
|
if (s = nh_getenv("LOGNAME")) {
|
|
(void) strncpy(plname, s, sizeof(plname)-1);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* normalize file name - we don't like .'s, /'s, spaces */
|
|
void regularize(char *s)
|
|
{
|
|
register char *lp;
|
|
|
|
while((lp=strchr(s, '.')) || (lp=strchr(s, '/')) || (lp=strchr(s,' ')))
|
|
*lp = '_';
|
|
}
|
|
|
|
static void process_options(int argc, char **argv)
|
|
{
|
|
int i;
|
|
|
|
while (argc > 1 && argv[1][0] == '-') {
|
|
argv++;
|
|
argc--;
|
|
switch (argv[0][1]) {
|
|
case 'D':
|
|
#ifdef WIZARD
|
|
wizard = TRUE;
|
|
break;
|
|
#endif
|
|
/* otherwise fall thru to discover */
|
|
case 'X':
|
|
discover = TRUE;
|
|
break;
|
|
#ifdef NEWS
|
|
case 'n':
|
|
iflags.news = FALSE;
|
|
break;
|
|
#endif
|
|
case 'u':
|
|
if(argv[0][2])
|
|
(void) strncpy(plname, argv[0]+2, sizeof(plname)-1);
|
|
else if (argc > 1) {
|
|
argc--;
|
|
argv++;
|
|
(void) strncpy(plname, argv[0], sizeof(plname)-1);
|
|
} else
|
|
raw_print("Player name expected after -u");
|
|
break;
|
|
case 'p': /* profession (role) */
|
|
if (argv[0][2]) {
|
|
if ((i = str2role(&argv[0][2])) >= 0)
|
|
flags.initrole = i;
|
|
} else if (argc > 1) {
|
|
argc--;
|
|
argv++;
|
|
if ((i = str2role(argv[0])) >= 0)
|
|
flags.initrole = i;
|
|
}
|
|
break;
|
|
case 'r': /* race */
|
|
if (argv[0][2]) {
|
|
if ((i = str2race(&argv[0][2])) >= 0)
|
|
flags.initrace = i;
|
|
} else if (argc > 1) {
|
|
argc--;
|
|
argv++;
|
|
if ((i = str2race(argv[0])) >= 0)
|
|
flags.initrace = i;
|
|
}
|
|
break;
|
|
case '@':
|
|
flags.randomall = 1;
|
|
break;
|
|
default:
|
|
raw_printf("Unknown option: %s", *argv);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void chdirx(const char *dir)
|
|
{
|
|
if (!dir) dir = HACKDIR;
|
|
|
|
if (chdir(dir) < 0)
|
|
error("Cannot chdir to %s.", dir);
|
|
|
|
/* Warn the player if we can't write the record file */
|
|
/* perhaps we should also test whether . is writable */
|
|
check_recordfile(dir);
|
|
}
|
|
|
|
void getlock(void)
|
|
{
|
|
int fd;
|
|
|
|
regularize(lock);
|
|
set_levelfile_name(lock, 0);
|
|
fd = creat(lock, FCMASK);
|
|
if(fd == -1) {
|
|
error("cannot creat lock file.");
|
|
} else {
|
|
if(write(fd, (genericptr_t) &hackpid, sizeof(hackpid))
|
|
!= sizeof(hackpid)){
|
|
error("cannot write lock");
|
|
}
|
|
if(close(fd) == -1) {
|
|
error("cannot close lock");
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifndef __begui__
|
|
/*
|
|
* If we are not using the Be GUI, then just exit -- we don't need to
|
|
* do anything extra.
|
|
*/
|
|
void nethack_exit(int status);
|
|
void nethack_exit(int status)
|
|
{
|
|
exit(status);
|
|
}
|
|
#endif /* !__begui__ */
|