omega-rpg/file.c

673 lines
16 KiB
C

/* omega (c) 1987,1988,1989 by Laurence Raphael Brothers */
/* file.c */
/* functions with file access in them. Also some direct calls to
curses functions */
#ifdef MSDOS_SUPPORTED_ANTIQUE
# include "curses.h"
#else
# ifdef AMIGA
# include <curses210.h>
# elif defined(USE_OPCURSES)
# include "../opcurses/curses.h"
# else
# include <curses.h>
# endif
# include <sys/types.h>
# include <unistd.h>
# include <sys/file.h>
# include <fcntl.h>
# include <errno.h>
#endif
#include "glob.h"
FILE *checkfopen(char *filestring, char *optionstring)
{
FILE *fd;
char response;
change_to_game_perms();
fd = fopen(filestring,optionstring);
clearmsg();
while (fd == NULL) {
print3("Warning! Error opening file:");
nprint3(filestring);
print1(" Abort or Retry? [ar] ");
do response = (char) mcigetc();
while ((response != 'a') && (response != 'r'));
if (response == 'r') fd = fopen(filestring,optionstring);
else {
print2("Sorry 'bout that.... Saving character, then quitting.");
morewait();
save(optionp(COMPRESS_OPTION), TRUE);
endgraf();
exit(0);
}
}
return(fd);
}
void commandlist(void)
{
strcpy(Str1,Omegalib);
if (Current_Environment == E_COUNTRYSIDE)
strcat(Str1,"help13.txt");
else strcat(Str1,"help12.txt");
displayfile(Str1);
xredraw();
}
void user_intro(void)
{
strcpy(Str1,Omegalib);
strcat(Str1,"intro.txt");
displaycryptfile(Str1);
xredraw();
}
void show_license(void)
{
strcpy(Str1,Omegalib);
strcat(Str1,"license.txt");
displayfile(Str1);
xredraw();
}
void abyss_file(void)
{
strcpy(Str1,Omegalib);
strcat(Str1,"abyss.txt");
displaycryptfile(Str1);
}
void inv_help(void)
{
strcpy(Str1,Omegalib);
strcat(Str1,"help3.txt");
displayfile(Str1);
xredraw();
}
void combat_help(void)
{
strcpy(Str1,Omegalib);
strcat(Str1,"help5.txt");
displayfile(Str1);
menuclear();
}
void cityguidefile(void)
{
strcpy(Str1,Omegalib);
strcat(Str1,"scroll2.txt");
displaycryptfile(Str1);
xredraw();
}
void wishfile(void)
{
strcpy(Str1,Omegalib);
strcat(Str1,"scroll3.txt");
displaycryptfile(Str1);
xredraw();
}
void adeptfile(void)
{
strcpy(Str1,Omegalib);
strcat(Str1,"scroll4.txt");
displaycryptfile(Str1);
xredraw();
}
void theologyfile(void)
{
strcpy(Str1,Omegalib);
strcat(Str1,"scroll1.txt");
displaycryptfile(Str1);
xredraw();
}
void showmotd(void)
{
strcpy(Str1,Omegalib);
strcat(Str1,"motd.txt");
displayfile(Str1);
}
void lock_score_file(void)
{
#ifndef MSDOS
int lock;
int thispid;
int lastpid = 0;
int attempts = 0;
FILE * lockfile;
strcpy(Str1,Omegalib);
strcat(Str1,"omega.hi.lock");
do
{
/* create lock file */
lock = open(Str1, O_CREAT | O_EXCL, 0600);
if (lock < 0 && errno == EEXIST)
{
lockfile = fopen(Str1, "rb");
if (lockfile)
{
fscanf(lockfile, "%d", &thispid);
fclose(lockfile);
if (thispid != lastpid)
attempts = 0;
lastpid = thispid;
}
attempts++;
/* assume that lock file has been abandoned */
if (attempts > 10)
{
/* so we unlink it ourselves - ugly... */
unlink(Str1);
}
else
sleep(2);
}
else if (lock < 0)
{
/* oops - something very wrong */
return;
}
}
while (lock < 0);
sprintf(Str1, "%d", getpid());
write(lock, Str1, strlen(Str1));
close(lock);
#endif
}
void unlock_score_file(void)
{
#ifndef MSDOS
strcpy(Str1,Omegalib);
strcat(Str1,"omega.hi.lock");
unlink(Str1);
#endif
}
void showscores(void)
{
FILE *fd;
int i;
lock_score_file();
strcpy(Str1,Omegalib);
strcat(Str1,"omega.hi");
fd = checkfopen(Str1,"rb");
filescanstring(fd,Hiscorer);
filescanstring(fd,Hidescrip);
fscanf(fd,"%ld %d %d\n",&Hiscore,&Hilevel,&Hibehavior);
for(i=1;i<7;i++) {
filescanstring(fd,Priest[i]);
fscanf(fd,"%d %d\n",&(Priestlevel[i]),&(Priestbehavior[i]));
}
filescanstring(fd,Shadowlord);
fscanf(fd,"%d %d\n",&Shadowlordlevel,&Shadowlordbehavior);
filescanstring(fd,Commandant);
fscanf(fd,"%d %d\n",&Commandantlevel,&Commandantbehavior);
filescanstring(fd,Archmage);
fscanf(fd,"%d %d\n",&Archmagelevel,&Archmagebehavior);
filescanstring(fd,Prime);
fscanf(fd,"%d %d\n",&Primelevel,&Primebehavior);
filescanstring(fd,Champion);
fscanf(fd,"%d %d\n",&Championlevel,&Championbehavior);
filescanstring(fd,Duke);
fscanf(fd,"%d %d\n",&Dukelevel,&Dukebehavior);
filescanstring(fd,Chaoslord);
fscanf(fd,"%d %d %d\n",&Chaoslordlevel,&Chaos,&Chaoslordbehavior);
filescanstring(fd,Lawlord);
fscanf(fd,"%d %d %d\n",&Lawlordlevel,&Law,&Lawlordbehavior);
filescanstring(fd,Justiciar);
fscanf(fd,"%d %d\n",&Justiciarlevel,&Justiciarbehavior);
filescanstring(fd,Grandmaster);
fscanf(fd,"%d %d\n",&Grandmasterlevel,&Grandmasterbehavior);
fclose(fd);
unlock_score_file();
clear();
printw("High Score: %ld",Hiscore);
printw(", by %s (%s)",Hiscorer,levelname(Hilevel));
printw("\n%s\n",Hidescrip);
printw("\nLord of Chaos: %s (%s)",Chaoslord,levelname(Chaoslordlevel));
printw("\nLord of Law: %s (%s)",Lawlord,levelname(Lawlordlevel));
printw("\n\nDuke of Rampart: ");
printw("%s (%s)",Duke,levelname(Dukelevel));
printw("\nJusticiar: ");
printw("%s (%s)",Justiciar,levelname(Justiciarlevel));
printw("\nCommandant: ");
printw("%s (%s)",Commandant,levelname(Commandantlevel));
printw("\nChampion: ");
printw("%s (%s)",Champion,levelname(Championlevel));
printw("\nArchmage: ");
printw("%s (%s)",Archmage,levelname(Archmagelevel));
printw("\nPrime Sorceror: ");
printw("%s (%s)",Prime,levelname(Primelevel));
printw("\nShadowlord: ");
printw("%s (%s)",Shadowlord,levelname(Shadowlordlevel));
printw("\n\nHigh Priests:");
printw("\n of Odin: ");
printw("%s (%s)",Priest[ODIN],levelname(Priestlevel[ODIN]));
printw("\n of Set: ");
printw("%s (%s)",Priest[SET],levelname(Priestlevel[SET]));
printw("\n of Athena: ");
printw("%s (%s)",Priest[ATHENA],levelname(Priestlevel[ATHENA]));
printw("\n of Hecate: ");
printw("%s (%s)",Priest[HECATE],levelname(Priestlevel[HECATE]));
printw("\n of the Lords of Destiny: ");
printw("%s (%s)",Priest[DESTINY],levelname(Priestlevel[DESTINY]));
printw("\nThe ArchDruid: ");
printw("%s (%s)",Priest[DRUID],levelname(Priestlevel[DRUID]));
printw("\nTholian Grandmaster: ");
printw("%s (%s)",Grandmaster,levelname(Grandmasterlevel));
printw("\n\nHit any key to continue.");
refresh();
wgetch(stdscr);
clear_screen();
}
/* Writes a new high-score file, with the nominated npc as whatever it is */
/* in this particular game, but the others as they appear in the file. */
void save_hiscore_npc(int npc)
{
FILE *infile, *outfile;
char buffer[80];
int i;
if (gamestatusp(CHEATED))
return;
lock_score_file();
strcpy(Str1,Omegalib);
strcat(Str1,"omega.hi");
infile = checkfopen(Str1,"rb");
strcpy(Str2,Omegalib);
#ifdef MSDOS
strcat(Str2,"omegahi.new"); /* stupid 8.3 msdos filename limit */
#else
strcat(Str2,"omega.hi.new");
#endif
outfile = checkfopen(Str2,"wb");
for (i = 0; i < 17; i++) {
if (npc == i) {
switch (i) {
case 0:
fprintf(outfile,"%s\n%s\n%ld %d %d\n",Hiscorer, Hidescrip, Hiscore,
Hilevel, Hibehavior);
break;
case 1: case 2: case 3: case 4: case 5: case 6:
fprintf(outfile,"%s\n%d %d\n", Priest[i], Priestlevel[i],
Priestbehavior[i]);
break;
case 7:
fprintf(outfile,"%s\n%d %d\n", Shadowlord, Shadowlordlevel,
Shadowlordbehavior);
break;
case 8:
fprintf(outfile,"%s\n%d %d\n", Commandant, Commandantlevel,
Commandantbehavior);
break;
case 9:
fprintf(outfile,"%s\n%d %d\n", Archmage, Archmagelevel,
Archmagebehavior);
break;
case 10:
fprintf(outfile,"%s\n%d %d\n", Prime, Primelevel, Primebehavior);
break;
case 11:
fprintf(outfile,"%s\n%d %d\n", Champion, Championlevel,
Championbehavior);
break;
case 12:
fprintf(outfile,"%s\n%d %d\n", Duke, Dukelevel, Dukebehavior);
break;
case 13:
fprintf(outfile,"%s\n%d %d %d\n",Chaoslord, Chaoslordlevel, Chaos,
Chaoslordbehavior);
break;
case 14:
fprintf(outfile,"%s\n%d %d %d\n", Lawlord, Lawlordlevel, Law,
Lawlordbehavior);
break;
case 15:
fprintf(outfile,"%s\n%d %d\n", Justiciar, Justiciarlevel,
Justiciarbehavior);
break;
case 16:
fprintf(outfile,"%s\n%d %d\n", Grandmaster, Grandmasterlevel,
Grandmasterbehavior);
break;
}
}
if (i == 0) {
fgets(buffer, 80, infile);
if (i != npc)
fputs(buffer, outfile);
}
fgets(buffer, 80, infile);
if (i != npc)
fputs(buffer, outfile);
fgets(buffer, 80, infile);
if (i != npc)
fputs(buffer, outfile);
}
fclose(infile);
fclose(outfile);
unlink(Str1);
#if defined(MSDOS) || defined(AMIGA)
rename(Str2, Str1);
#else
link(Str2, Str1);
unlink(Str2); /* renames, but sys-V doesn't have rename()... */
#endif
unlock_score_file();
}
void checkhigh(char *descrip, int behavior)
{
long points;
if (FixedPoints > 0) points = FixedPoints;
else points = calc_points();
if (!gamestatusp(CHEATED)) {
if (Hiscore < points) {
strcpy(Hiscorer, Player.name);
strcpy(Hidescrip, descrip);
Hiscore = points;
Hilevel = Player.level;
Hibehavior = behavior;
save_hiscore_npc(0);
mprint("Yow! A new high score!");
morewait();
}
if (Player.alignment < Chaos) {
strcpy(Chaoslord, Player.name);
Chaoslordlevel = Player.level;
Chaos = Player.alignment;
Chaoslordbehavior = behavior;
save_hiscore_npc(13);
mprint("Criminy! A new Lord of Chaos!");
morewait();
}
if (Player.alignment > Law) {
strcpy(Lawlord, Player.name);
Lawlordlevel = Player.level;
Law = Player.alignment;
Lawlordbehavior = behavior;
save_hiscore_npc(14);
mprint("Gosh! A new Lord of Law!");
morewait();
}
}
}
void extendlog(char *descrip, int lifestatus)
{
FILE *fd;
int npcbehavior;
if ((Player.level > 0) && (! gamestatusp(CHEATED))) {
change_to_game_perms();
npcbehavior=fixnpc(lifestatus);
checkhigh(descrip,npcbehavior);
strcpy(Str1,Omegalib);
strcat(Str1,"omega.log");
fd = checkfopen(Str1,"a");
fprintf(fd, " %d %d %d %s\n", lifestatus, Player.level, npcbehavior,
Player.name);
fclose(fd);
}
}
#ifndef MSDOS
/* reads a string from a file. If it is a line with more than 80 char's,
then remainder of line to \n is consumed */
void filescanstring(FILE *fd, char *fstr)
{
int i= -1;
int byte='x';
while ((i<80) && (byte != '\n') && (byte != EOF)) {
i++;
byte=fgetc(fd);
fstr[i] = byte;
}
if (byte != '\n')
while((byte!='\n') && (byte != EOF))
byte=fgetc(fd);
fstr[i]=0;
}
#endif
#ifdef MSDOS
int test_file_access(char *file_name, char mode)
{
FILE *fd;
if (mode == 'r')
fd = fopen(file_name, "r");
else
fd = fopen(file_name, "r+");
if (!fd)
return 0;
fclose(fd);
return 1;
}
#else
int test_file_access(char *file_name, char mode)
{
int fd;
if (mode == 'r')
fd = open(file_name, O_RDONLY, 0);
else
fd = open(file_name, O_RDWR, 0);
if (fd < 0)
return 0;
close(fd);
return 1;
}
#endif
char *required_file_list[] =
{
"maps.dat", "omega.hi", "omega.log", "motd.txt",
"license.txt", NULL
};
char *optional_file_list[] =
{
"help1.txt", "help2.txt", "help3.txt", "help4.txt", "help5.txt",
"help6.txt", "help7.txt", "help8.txt", "help9.txt", "help10.txt",
"help11.txt", "help12.txt", "help13.txt", "abyss.txt", "scroll1.txt",
"scroll2.txt", "scroll3.txt", "scroll4.txt", NULL
};
/* Checks existence of omega data files */
/* Returns 1 if OK, 0 if impossible to run, -1 if possible but not OK */
int filecheck(void)
{
int impossible=FALSE,badbutpossible=FALSE;
int endpos;
int file;
strcpy(Str1, Omegalib);
endpos = strlen(Str1);
for (file = 0; required_file_list[file]; file++)
{
strcpy(&(Str1[endpos]), required_file_list[file]);
if ((strcmp(required_file_list[file], "omega.hi") == 0 ||
strcmp(required_file_list[file], "omega.log") == 0) &&
test_file_access(Str1, 'w') == 0)
{
impossible = TRUE;
printf("\nError! File not appendable or accessible: %s", Str1);
}
else if (test_file_access(Str1, 'r') == 0)
{
impossible = TRUE;
printf("\nError! File not accessible: %s", Str1);
}
}
for (file = 0; optional_file_list[file]; file++)
{
strcpy(&(Str1[endpos]), optional_file_list[file]);
if (test_file_access(Str1, 'r') == 0)
{
badbutpossible = TRUE;
printf("\nWarning! File not accessible: %s", Str1);
}
}
if (impossible) {
printf("\nFurther execution is impossible. Sorry.");
if (strcmp(Omegalib, OMEGALIB))
printf("\nEnvironment variable OMEGALIB badly set\n");
else {
printf("\nOMEGALIB may be badly #defined in defs.h\n");
#ifndef FIXED_OMEGALIB
printf("\nYou can set the environment variable OMEGALIB to\n");
printf("the location of the omegalib directory.\n");
#endif
}
return(0);
}
else if (badbutpossible) {
printf("\nFurther execution may cause anomalous behavior.");
printf("\nContinue anyhow? [yn] ");
if (getchar()=='y') return(-1);
else return(0);
}
else return(1);
}
/* display a file given a string name of file */
void displayfile(char *filestr)
{
FILE *fd = checkfopen(filestr,"r");
int c,d=' ';
int x,y;
clear();
refresh();
c = fgetc(fd);
while ((c != EOF)&&((char) d != 'q')&&((char) d!=ESCAPE)) {
getyx(stdscr,y,x);
if (y > ScreenLength) {
standout();
printw("\n-More-");
standend();
refresh();
d = wgetch(stdscr);
clear();
}
printw("%c",(char) c);
c = fgetc(fd);
}
if (((char) d != 'q')&&((char) d!=ESCAPE)) {
standout();
printw("\n-Done-");
standend();
refresh();
getch();
}
clear();
refresh();
fclose(fd);
}
/* display a file given a string name of file */
void displaycryptfile(char *filestr)
{
FILE *fd = checkfopen(filestr,"rb");
int c,d=' ';
int x,y;
char key = 100;
clear();
refresh();
c = fgetc(fd);
while ((c != EOF)&&((char) d != 'q')&&((char) d!=ESCAPE)) {
getyx(stdscr,y,x);
if (y > ScreenLength) {
standout();
printw("\n-More-");
standend();
refresh();
d = wgetch(stdscr);
clear();
}
key = ((unsigned char) c)^key;
printw("%c", key);
c = fgetc(fd);
}
if (((char) d != 'q')&&((char) d!=ESCAPE)) {
standout();
printw("\n-Done-");
standend();
refresh();
getch();
}
clear();
refresh();
fclose(fd);
}
/* copy a file given a string name of file */
void copyfile(char *srcstr)
{
char deststr[80];
char buffer[STRING_LEN];
FILE *in, *out;
print1("Enter name of file to create: ");
strcpy(deststr,msgscanstring());
if (strlen(deststr) == 0) {
print2("Aborting...");
morewait();
return;
}
in = checkfopen(srcstr, "rb");
change_to_user_perms();
out = fopen(deststr, "wb");
if (!out) {
sprintf(buffer, "Unable to write to file %s - Aborting.", deststr);
print2(buffer);
change_to_game_perms();
morewait();
fclose(in);
return;
}
print2("Copying file....");
while (fgets(buffer, STRING_LEN, in))
fputs(buffer, out);
fclose(in);
fclose(out);
change_to_game_perms();
print3("Done.");
}