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