/*
* Rogue
* Exploring the dungeons of doom
*
* @(#)main.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <fcntl.h>
#include <stdio.h>
#include <limits.h>
#include <errno.h>
#include <sys/stat.h>
#include "rogue.h"
#ifdef ATT
#include <time.h>
#endif
#ifdef BSD
#include <sys/time.h>
#endif
#include "rogue.ext"
char *roguehome(void);
void open_records(void);
extern FILE *scoreboard;
extern FILE *logfile;
int
main(int argc, char *argv[], char *envp[])
{
register char *env;
register struct linked_list *item;
register struct object *obj;
char alldone;
int wpt;
char *getpass(), *xcrypt(), *strrchr();
char *homedir = roguehome();
md_init();
if (homedir == NULL)
homedir = "";
playuid = md_getuid();
playgid = md_getgid();
/* check for print-score option */
#ifdef SCOREFILE
strncpy(scorefile, SCOREFILE, LINLEN);
scorefile[LINLEN - 1] = '\0';
#else
strncpy(scorefile, homedir, LINLEN-11);
if (scorefile[LINLEN-12] != '\0')
scorefile[0] = '\0';
if (*scorefile)
strcat(scorefile,"/");
strcat(scorefile, "srogue.scr");
#endif
open_records();
if(argc >= 2 && strcmp(argv[1], "-s") == 0)
{
showtop(0);
exit(0);
}
#ifdef WIZARD
if (argc >= 2 && author() && strcmp(argv[1],"-a") == 0)
{
wizard = TRUE;
argv++;
argc--;
}
/* Check to see if he is a wizard */
if (argc >= 2 && strcmp(argv[1],"-w") == 0)
{
if (strcmp(PASSWD, xcrypt(getpass(wizstr),"mT")) == 0)
{
wizard = TRUE;
argv++;
argc--;
}
}
#endif
#ifdef SAVEDIR
if (argc >= 3 && !strcmp(argv[1], "-n")) {
strncpy(whoami, argv[2], LINLEN);
whoami[LINLEN - 1] = '\0';
use_savedir = TRUE;
if (snprintf(file_name, 256, "%s/%d-%s.srsav", SAVEDIR,
playuid, whoami) >= 256) {
/* Just in case it doesn't fit */
strcpy(file_name, "srogue.save");
use_savedir = FALSE;
}
}
#endif
if (!use_savedir)
md_normaluser();
/* get home and options from environment */
if ((env = getenv("HOME")) != NULL)
strcpy(home, env);
else {
strncpy(home, md_gethomedir(), LINLEN);
if (home[LINLEN-1] != '\0')
home[0] = '\0';
}
if (strcmp(home,"/") == 0)
home[0] = '\0';
if ((strlen(home) > 0) && (home[strlen(home)-1] != '/'))
strcat(home, "/");
if (!use_savedir) {
strcpy(file_name, home);
strcat(file_name, "srogue.sav");
}
if ((env = getenv("ROGUEOPTS")) != NULL)
parse_opts(env);
if (!use_savedir && (env == NULL || whoami[0] == '\0'))
{
strucpy(whoami, md_getusername(), strlen(md_getusername()));
}
if (env == NULL || fruit[0] == '\0')
strcpy(fruit, "juicy-fruit");
if (use_savedir)
{
/* restore() won't return if the restore succeeded. If
* file_name doesn't exist, it will return TRUE. In that
* case, start a new game. */
if (!restore(file_name, envp))
exit(1);
}
else if (argc == 2)
if(!restore(argv[1], envp)) /* NOTE: NEVER RETURNS */
exit(1);
/* START NEW GAME */
dnum = (wizard && getenv("SEED") != NULL ?
atoi(getenv("SEED")) : md_random_seed());
if(wizard)
printf("Hello %s, welcome to dungeon #%d\n", whoami, dnum);
else
printf("Hello %s, One moment while I open the door to the dungeon...\n", whoami);
fflush(stdout);
seed = dnum;
md_srandom(seed); /* init rnd number gen */
md_onsignal_exit(); /* just in case */
init_everything();
#ifdef __INTERIX
setenv("TERM","interix");
#endif
initscr(); /* Start up cursor package */
if (strcmp(termname(),"dumb") == 0)
{
endwin();
printf("ERROR in terminal parameters.\n");
printf("Check TERM in environment.\n");
byebye(1);
}
if (LINES < 24 || COLS < 80) {
endwin();
printf("ERROR: screen size too small\n");
byebye(1);
}
if ((*whoami == '\0') || (strcmp(whoami,"dosuser")==0))
{
echo();
mvaddstr(23,2,"Rogue's Name? ");
wgetnstr(stdscr,whoami,MAXSTR);
noecho();
}
if (*whoami == '\0')
strcpy(whoami,"Rodney");
setup();
/* Set up windows */
cw = newwin(0, 0, 0, 0);
mw = newwin(0, 0, 0, 0);
hw = newwin(0, 0, 0, 0);
keypad(cw, 1);
waswizard = wizard;
/* Draw current level */
new_level(NORMLEV);
/* Start up daemons and fuses */
start_daemon(status, TRUE, BEFORE);
start_daemon(runners, TRUE, AFTER);
/*
* These daemons have been moved to AFTER because BEFORE daemons
* get called every command, even invalid ones. Hopefully this
* won't break anything.
*/
start_daemon(doctor, TRUE, AFTER);
start_daemon(stomach, TRUE, AFTER);
fuse(swander, TRUE, WANDERTIME);
/* Give the rogue his weaponry */
do {
wpt = pick_one(w_magic);
switch (wpt)
{
case MACE: case SWORD: case TWOSWORD:
case SPEAR: case TRIDENT: case SPETUM:
case BARDICHE: case PIKE: case BASWORD:
case HALBERD:
alldone = TRUE;
otherwise:
alldone = FALSE;
}
} while(!alldone);
item = new_thing(FALSE, WEAPON, wpt);
obj = OBJPTR(item);
obj->o_hplus = rnd(3);
obj->o_dplus = rnd(3);
obj->o_flags = ISKNOW;
add_pack(item, TRUE);
cur_weapon = obj;
/* Now a bow */
item = new_thing(FALSE, WEAPON, BOW);
obj = OBJPTR(item);
obj->o_hplus = rnd(3);
obj->o_dplus = rnd(3);
obj->o_flags = ISKNOW;
add_pack(item, TRUE);
/* Now some arrows */
item = new_thing(FALSE, WEAPON, ARROW);
obj = OBJPTR(item);
obj->o_count = 25 + rnd(15);
obj->o_hplus = rnd(2);
obj->o_dplus = rnd(2);
obj->o_flags = ISKNOW;
add_pack(item, TRUE);
/* And his suit of armor */
wpt = pick_one(a_magic);
item = new_thing(FALSE, ARMOR, wpt);
obj = OBJPTR(item);
obj->o_flags = ISKNOW;
obj->o_ac = armors[wpt].a_class - rnd(4);
cur_armor = obj;
add_pack(item, TRUE);
/* Give him some food */
item = new_thing(FALSE, FOOD, 0);
add_pack(item, TRUE);
playit();
}
/*
* endit:
* Exit the program abnormally.
*/
void
endit(int a)
{
fatal("Ok, if you want to exit that badly, I'll have to allow it");
}
/*
* fatal:
* Exit the program, printing a message.
*/
void
fatal(char *s)
{
clear();
refresh();
endwin();
fprintf(stderr,"%s\n\r",s);
fflush(stderr);
byebye(2);
}
/*
* byebye:
* Exit here and reset the users terminal parameters
* to the way they were when he started
*/
void
byebye(int how)
{
if (!isendwin())
endwin();
exit(how); /* exit like flag says */
}
/*
* rnd:
* Pick a very random number.
*/
int
rnd(int range)
{
reg int wh;
if (range == 0)
wh = 0;
else {
wh = md_random() % range;
wh &= 0x7FFFFFFF;
}
return wh;
}
/*
* roll:
* roll a number of dice
*/
int
roll(int number, int sides)
{
reg int dtotal = 0;
while(number-- > 0)
dtotal += rnd(sides)+1;
return dtotal;
}
/*
** setup: Setup signal catching functions
*/
void
setup(void)
{
md_onsignal_autosave();
nonl();
cbreak();
noecho();
}
/*
** playit: The main loop of the program. Loop until the game is over,
** refreshing things and looking at the proper times.
*/
void
playit(void)
{
reg char *opts;
/* parse environment declaration of options */
if ((opts = getenv("ROGUEOPTS")) != NULL)
parse_opts(opts);
player.t_oldpos = hero;
oldrp = roomin(&hero);
nochange = FALSE;
while (playing)
command(); /* Command execution */
endit(0);
}
/*
** author: See if a user is an author of the program
*/
bool
author(void)
{
switch (playuid) {
case 100:
case 0:
return TRUE;
default:
return FALSE;
}
}
int
directory_exists(char *dirname)
{
struct stat sb;
if (stat(dirname, &sb) == 0) /* path exists */
return ((sb.st_mode & S_IFMT) == S_IFDIR);
return(0);
}
char *
roguehome(void)
{
static char path[LINLEN+16];
char *end,*home;
if ( (home = getenv("ROGUEHOME")) != NULL)
{
if (*home)
{
/* LINLEN - 11 is all that will fit into scorefile */
strncpy(path, home, LINLEN - 11);
if (path[LINLEN - 12] == '\0')
{
end = &path[strlen(path)-1];
while( (end >= path) && ((*end == '/') || (*end == '\\')))
*end-- = '\0';
if (directory_exists(path))
return(path);
}
/* Otherwise home was truncated and should be ignored */
}
}
if (directory_exists("/var/games/roguelike"))
return("/var/games/roguelike");
if (directory_exists("/var/lib/roguelike"))
return("/var/lib/roguelike");
if (directory_exists("/var/roguelike"))
return("/var/roguelike");
if (directory_exists("/usr/games/lib"))
return("/usr/games/lib");
if (directory_exists("/games/roguelik"))
return("/games/roguelik");
return(NULL);
}
void
open_records(void)
{
if (scoreboard == NULL)
scoreboard = fopen(scorefile, "r+");
if (scoreboard == NULL && errno == ENOENT) {
scoreboard = fopen(scorefile, "w+");
}
#ifdef LOGFILE
if (logfile == NULL)
logfile = fopen(LOGFILE, "a");
#endif
}