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