Home | History | Annotate | Line # | Download | only in larn
diag.c revision 1.8
      1 /*	$NetBSD: diag.c,v 1.8 1997/10/18 20:03:12 christos Exp $	*/
      2 
      3 /* diag.c		Larn is copyrighted 1986 by Noah Morgan. */
      4 #include <sys/cdefs.h>
      5 #ifndef lint
      6 __RCSID("$NetBSD: diag.c,v 1.8 1997/10/18 20:03:12 christos Exp $");
      7 #endif				/* not lint */
      8 
      9 #include <sys/types.h>
     10 #include <sys/times.h>
     11 #include <sys/stat.h>
     12 #include <stdlib.h>
     13 #include <unistd.h>
     14 #include "header.h"
     15 #include "extern.h"
     16 static struct tms cputime;
     17 /*
     18 	***************************
     19 	DIAG -- dungeon diagnostics
     20 	***************************
     21 
     22 	subroutine to print out data for debugging
     23  */
     24 #ifdef EXTRA
     25 static int      rndcount[16];
     26 void
     27 diag()
     28 {
     29 	int    i, j;
     30 	int             hit, dam;
     31 	cursors();
     32 	lwclose();
     33 	if (lcreat(diagfile) < 0) {	/* open the diagnostic file	 */
     34 		lcreat((char *) 0);
     35 		lprcat("\ndiagnostic failure\n");
     36 		return (-1);
     37 	}
     38 	write(1, "\nDiagnosing . . .\n", 18);
     39 	lprcat("\n\nBeginning of DIAG diagnostics ----------\n");
     40 
     41 	/* for the character attributes	 */
     42 
     43 	lprintf("\n\nPlayer attributes:\n\nHit points: %2d(%2d)", (long) c[HP], (long) c[HPMAX]);
     44 	lprintf("\ngold: %d  Experience: %d  Character level: %d  Level in caverns: %d",
     45 	(long) c[GOLD], (long) c[EXPERIENCE], (long) c[LEVEL], (long) level);
     46 	lprintf("\nTotal types of monsters: %d", (long) MAXMONST + 8);
     47 
     48 	lprcat("\f\nHere's the dungeon:\n\n");
     49 
     50 	i = level;
     51 	for (j = 0; j < MAXLEVEL + MAXVLEVEL; j++) {
     52 		newcavelevel(j);
     53 		lprintf("\nMaze for level %s:\n", levelname[level]);
     54 		diagdrawscreen();
     55 	}
     56 	newcavelevel(i);
     57 
     58 	lprcat("\f\nNow for the monster data:\n\n");
     59 	lprcat("   Monster Name      LEV  AC   DAM  ATT  DEF    GOLD   HP     EXP   \n");
     60 	lprcat("--------------------------------------------------------------------------\n");
     61 	for (i = 0; i <= MAXMONST + 8; i++) {
     62 		lprintf("%19s  %2d  %3d ", monster[i].name, (long) monster[i].level, (long) monster[i].armorclass);
     63 		lprintf(" %3d  %3d  %3d  ", (long) monster[i].damage, (long) monster[i].attack, (long) monster[i].defense);
     64 		lprintf("%6d  %3d   %6d\n", (long) monster[i].gold, (long) monster[i].hitpoints, (long) monster[i].experience);
     65 	}
     66 
     67 	lprcat("\n\nHere's a Table for the to hit percentages\n");
     68 	lprcat("\n     We will be assuming that players level = 2 * monster level");
     69 	lprcat("\n     and that the players dexterity and strength are 16.");
     70 	lprcat("\n    to hit: if (rnd(22) < (2[monst AC] + your level + dex + WC/8 -1)/2) then hit");
     71 	lprcat("\n    damage = rund(8) + WC/2 + STR - c[HARDGAME] - 4");
     72 	lprcat("\n    to hit:  if rnd(22) < to hit  then player hits\n");
     73 	lprcat("\n    Each entry is as follows:  to hit / damage / number hits to kill\n");
     74 	lprcat("\n          monster     WC = 4         WC = 20        WC = 40");
     75 	lprcat("\n---------------------------------------------------------------");
     76 	for (i = 0; i <= MAXMONST + 8; i++) {
     77 		hit = 2 * monster[i].armorclass + 2 * monster[i].level + 16;
     78 		dam = 16 - c[HARDGAME];
     79 		lprintf("\n%20s   %2d/%2d/%2d       %2d/%2d/%2d       %2d/%2d/%2d",
     80 			monster[i].name,
     81 			(long) (hit / 2), (long) max(0, dam + 2), (long) (monster[i].hitpoints / (dam + 2) + 1),
     82 			(long) ((hit + 2) / 2), (long) max(0, dam + 10), (long) (monster[i].hitpoints / (dam + 10) + 1),
     83 			(long) ((hit + 5) / 2), (long) max(0, dam + 20), (long) (monster[i].hitpoints / (dam + 20) + 1));
     84 	}
     85 
     86 	lprcat("\n\nHere's the list of available potions:\n\n");
     87 	for (i = 0; i < MAXPOTION; i++)
     88 		lprintf("%20s\n", &potionhide[i][1]);
     89 	lprcat("\n\nHere's the list of available scrolls:\n\n");
     90 	for (i = 0; i < MAXSCROLL; i++)
     91 		lprintf("%20s\n", &scrollhide[i][1]);
     92 	lprcat("\n\nHere's the spell list:\n\n");
     93 	lprcat("spell          name           description\n");
     94 	lprcat("-------------------------------------------------------------------------------------------\n\n");
     95 	for (j = 0; j < SPNUM; j++) {
     96 		lprc(' ');
     97 		lprcat(spelcode[j]);
     98 		lprintf(" %21s  %s\n", spelname[j], speldescript[j]);
     99 	}
    100 
    101 	lprcat("\n\nFor the c[] array:\n");
    102 	for (j = 0; j < 100; j += 10) {
    103 		lprintf("\nc[%2d] = ", (long) j);
    104 		for (i = 0; i < 9; i++)
    105 			lprintf("%5d ", (long) c[i + j]);
    106 	}
    107 
    108 	lprcat("\n\nTest of random number generator ----------------");
    109 	lprcat("\n    for 25,000 calls divided into 16 slots\n\n");
    110 
    111 	for (i = 0; i < 16; i++)
    112 		rndcount[i] = 0;
    113 	for (i = 0; i < 25000; i++)
    114 		rndcount[rund(16)]++;
    115 	for (i = 0; i < 16; i++) {
    116 		lprintf("  %5d", (long) rndcount[i]);
    117 		if (i == 7)
    118 			lprc('\n');
    119 	}
    120 
    121 	lprcat("\n\n");
    122 	lwclose();
    123 	lcreat((char *) 0);
    124 	lprcat("Done Diagnosing . . .");
    125 	return (0);
    126 }
    127 /*
    128 	subroutine to count the number of occurrences of an object
    129  */
    130 int
    131 dcount(l)
    132 	int l;
    133 {
    134 	int i, j, p;
    135 	int k;
    136 	k = 0;
    137 	for (i = 0; i < MAXX; i++)
    138 		for (j = 0; j < MAXY; j++)
    139 			for (p = 0; p < MAXLEVEL; p++)
    140 				if (cell[p * MAXX * MAXY + i * MAXY + j].item == l)
    141 					k++;
    142 	return (k);
    143 }
    144 
    145 /*
    146 	subroutine to draw the whole screen as the player knows it
    147  */
    148 void
    149 diagdrawscreen()
    150 {
    151 	int    i, j, k;
    152 
    153 	for (i = 0; i < MAXY; i++)
    154 		/* for the east west walls of this line	 */
    155 	{
    156 		for (j = 0; j < MAXX; j++)
    157 			if (k = mitem[j][i])
    158 				lprc(monstnamelist[k]);
    159 			else
    160 				lprc(objnamelist[item[j][i]]);
    161 		lprc('\n');
    162 	}
    163 }
    164 #endif
    165 
    166 
    167 /*
    168 	to save the game in a file
    169  */
    170 static time_t   zzz = 0;
    171 int
    172 savegame(fname)
    173 	char *fname;
    174 {
    175 	int    i, k;
    176 	struct sphere *sp;
    177 	struct stat     statbuf;
    178 
    179 	nosignal = 1;
    180 	lflush();
    181 	savelevel();
    182 	ointerest();
    183 	if (lcreat(fname) < 0) {
    184 		lcreat((char *) 0);
    185 		lprintf("\nCan't open file <%s> to save game\n", fname);
    186 		nosignal = 0;
    187 		return (-1);
    188 	}
    189 	set_score_output();
    190 	lwrite((char *) beenhere, MAXLEVEL + MAXVLEVEL);
    191 	for (k = 0; k < MAXLEVEL + MAXVLEVEL; k++)
    192 		if (beenhere[k])
    193 			lwrite((char *) &cell[k * MAXX * MAXY], sizeof(struct cel) * MAXY * MAXX);
    194 	times(&cputime);	/* get cpu time */
    195 	c[CPUTIME] += (cputime.tms_utime + cputime.tms_stime) / 60;
    196 	lwrite((char *) &c[0], 100 * sizeof(long));
    197 	lprint((long) gltime);
    198 	lprc(level);
    199 	lprc(playerx);
    200 	lprc(playery);
    201 	lwrite((char *) iven, 26);
    202 	lwrite((char *) ivenarg, 26 * sizeof(short));
    203 	for (k = 0; k < MAXSCROLL; k++)
    204 		lprc(scrollname[k][0]);
    205 	for (k = 0; k < MAXPOTION; k++)
    206 		lprc(potionname[k][0]);
    207 	lwrite((char *) spelknow, SPNUM);
    208 	lprc(wizard);
    209 	lprc(rmst);		/* random monster generation counter */
    210 	for (i = 0; i < 90; i++)
    211 		lprc(itm[i].qty);
    212 	lwrite((char *) course, 25);
    213 	lprc(cheat);
    214 	lprc(VERSION);
    215 	for (i = 0; i < MAXMONST; i++)
    216 		lprc(monster[i].genocided);	/* genocide info */
    217 	for (sp = spheres; sp; sp = sp->p)
    218 		lwrite((char *) sp, sizeof(struct sphere));	/* save spheres of
    219 								 * annihilation */
    220 	time(&zzz);
    221 	lprint((long) (zzz - initialtime));
    222 	lwrite((char *) &zzz, sizeof(long));
    223 	if (fstat(lfd, &statbuf) < 0)
    224 		lprint(0L);
    225 	else
    226 		lprint((long) statbuf.st_ino);	/* inode # */
    227 	lwclose();
    228 	lastmonst[0] = 0;
    229 #ifndef VT100
    230 	setscroll();
    231 #endif	/* VT100 */
    232 	lcreat((char *) 0);
    233 	nosignal = 0;
    234 	return (0);
    235 }
    236 
    237 void
    238 restoregame(fname)
    239 	char           *fname;
    240 {
    241 	int    i, k;
    242 	struct sphere *sp, *sp2;
    243 	struct stat     filetimes;
    244 	cursors();
    245 	lprcat("\nRestoring . . .");
    246 	lflush();
    247 	if (lopen(fname) <= 0) {
    248 		lcreat((char *) 0);
    249 		lprintf("\nCan't open file <%s>to restore game\n", fname);
    250 		nap(2000);
    251 		c[GOLD] = c[BANKACCOUNT] = 0;
    252 		died(-265);
    253 		return;
    254 	}
    255 	lrfill((char *) beenhere, MAXLEVEL + MAXVLEVEL);
    256 	for (k = 0; k < MAXLEVEL + MAXVLEVEL; k++)
    257 		if (beenhere[k])
    258 			lrfill((char *) &cell[k * MAXX * MAXY], sizeof(struct cel) * MAXY * MAXX);
    259 
    260 	lrfill((char *) &c[0], 100 * sizeof(long));
    261 	gltime = lrint();
    262 	level = c[CAVELEVEL] = lgetc();
    263 	playerx = lgetc();
    264 	playery = lgetc();
    265 	lrfill((char *) iven, 26);
    266 	lrfill((char *) ivenarg, 26 * sizeof(short));
    267 	for (k = 0; k < MAXSCROLL; k++)
    268 		scrollname[k] = lgetc() ? scrollhide[k] : "";
    269 	for (k = 0; k < MAXPOTION; k++)
    270 		potionname[k] = lgetc() ? potionhide[k] : "";
    271 	lrfill((char *) spelknow, SPNUM);
    272 	wizard = lgetc();
    273 	rmst = lgetc();		/* random monster creation flag */
    274 
    275 	for (i = 0; i < 90; i++)
    276 		itm[i].qty = lgetc();
    277 	lrfill((char *) course, 25);
    278 	cheat = lgetc();
    279 	if (VERSION != lgetc()) {	/* version number  */
    280 		cheat = 1;
    281 		lprcat("Sorry, But your save file is for an older version of larn\n");
    282 		nap(2000);
    283 		c[GOLD] = c[BANKACCOUNT] = 0;
    284 		died(-266);
    285 		return;
    286 	}
    287 	for (i = 0; i < MAXMONST; i++)
    288 		monster[i].genocided = lgetc();	/* genocide info */
    289 	for (sp = 0, i = 0; i < c[SPHCAST]; i++) {
    290 		sp2 = sp;
    291 		sp = (struct sphere *) malloc(sizeof(struct sphere));
    292 		if (sp == 0) {
    293 			write(2, "Can't malloc() for sphere space\n", 32);
    294 			break;
    295 		}
    296 		lrfill((char *) sp, sizeof(struct sphere));	/* get spheres of
    297 								 * annihilation */
    298 		sp->p = 0;	/* null out pointer */
    299 		if (i == 0)
    300 			spheres = sp;	/* beginning of list */
    301 		else
    302 			sp2->p = sp;
    303 	}
    304 
    305 	time(&zzz);
    306 	initialtime = zzz - lrint();
    307 	fstat(fd, &filetimes);	/* get the creation and modification time of
    308 				 * file	 */
    309 	lrfill((char *) &zzz, sizeof(long));
    310 	zzz += 6;
    311 	if (filetimes.st_ctime > zzz)
    312 		fsorry();	/* file create time	 */
    313 	else if (filetimes.st_mtime > zzz)
    314 		fsorry();	/* file modify time	 */
    315 	if (c[HP] < 0) {
    316 		died(284);
    317 		return;
    318 	}			/* died a post mortem death */
    319 	oldx = oldy = 0;
    320 	i = lrint();		/* inode # */
    321 	if (i && (filetimes.st_ino != i))
    322 		fsorry();
    323 	lrclose();
    324 	if (strcmp(fname, ckpfile) == 0) {
    325 		if (lappend(fname) < 0)
    326 			fcheat();
    327 		else {
    328 			lprc(' ');
    329 			lwclose();
    330 		}
    331 		lcreat((char *) 0);
    332 	} else if (unlink(fname) < 0)
    333 		fcheat();	/* can't unlink save file */
    334 	/* for the greedy cheater checker	 */
    335 	for (k = 0; k < 6; k++)
    336 		if (c[k] > 99)
    337 			greedy();
    338 	if (c[HPMAX] > 999 || c[SPELLMAX] > 125)
    339 		greedy();
    340 	if (c[LEVEL] == 25 && c[EXPERIENCE] > skill[24]) {	/* if patch up lev 25
    341 								 * player */
    342 		long            tmp;
    343 		tmp = c[EXPERIENCE] - skill[24];	/* amount to go up */
    344 		c[EXPERIENCE] = skill[24];
    345 		raiseexperience((long) tmp);
    346 	}
    347 	getlevel();
    348 	lasttime = gltime;
    349 }
    350 
    351 /*
    352 	subroutine to not allow greedy cheaters
    353  */
    354 void
    355 greedy()
    356 {
    357 #if WIZID
    358 	if (wizard)
    359 		return;
    360 #endif
    361 
    362 	lprcat("\n\nI am so sorry, but your character is a little TOO good!  Since this\n");
    363 	lprcat("cannot normally happen from an honest game, I must assume that you cheated.\n");
    364 	lprcat("In that you are GREEDY as well as a CHEATER, I cannot allow this game\n");
    365 	lprcat("to continue.\n");
    366 	nap(5000);
    367 	c[GOLD] = c[BANKACCOUNT] = 0;
    368 	died(-267);
    369 	return;
    370 }
    371 
    372 /*
    373 	subroutine to not allow altered save files and terminate the attempted
    374 	restart
    375  */
    376 void
    377 fsorry()
    378 {
    379 	lprcat("\nSorry, but your savefile has been altered.\n");
    380 	lprcat("However, seeing as I am a good sport, I will let you play.\n");
    381 	lprcat("Be advised though, you won't be placed on the normal scoreboard.");
    382 	cheat = 1;
    383 	nap(4000);
    384 }
    385 
    386 /*
    387 	subroutine to not allow game if save file can't be deleted
    388  */
    389 void
    390 fcheat()
    391 {
    392 #if WIZID
    393 	if (wizard)
    394 		return;
    395 #endif
    396 
    397 	lprcat("\nSorry, but your savefile can't be deleted.  This can only mean\n");
    398 	lprcat("that you tried to CHEAT by protecting the directory the savefile\n");
    399 	lprcat("is in.  Since this is unfair to the rest of the larn community, I\n");
    400 	lprcat("cannot let you play this game.\n");
    401 	nap(5000);
    402 	c[GOLD] = c[BANKACCOUNT] = 0;
    403 	died(-268);
    404 	return;
    405 }
    406