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