installer - Several improvements
[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 #include <sys/types.h>
4 #include <sys/times.h>
5 #include <sys/stat.h>
6 #include "header.h"
7 extern int rmst, maxitm, lasttime;
8
9 static void greedy(void);
10 static void fsorry(void);
11 static void fcheat(void);
12
13 static struct tms cputime;
14
15 /*
16         ***************************
17         DIAG -- dungeon diagnostics
18         ***************************
19
20         subroutine to print out data for debugging
21  */
22 #ifdef EXTRA
23 static int dcount(int);
24 static void drawdiagscreen(void);
25
26 static int rndcount[16];
27
28 int
29 diag(void)
30 {
31         int i, j;
32         int hit, dam;
33         cursors();
34         lwclose();
35         if (lcreat(diagfile) < 0) {     /* open the diagnostic file */
36                 lcreat(NULL);
37                 lprcat("\ndiagnostic failure\n");
38                 return (-1);
39         }
40
41         write(1, "\nDiagnosing . . .\n", 18);
42         lprcat("\n\nBeginning of DIAG diagnostics ----------\n");
43
44 /* for the character attributes */
45
46         lprintf("\n\nPlayer attributes:\n\nHit points: %2d(%2d)", (long)c[HP], (long)c[HPMAX]);
47         lprintf("\ngold: %d  Experience: %d  Character level: %d  Level in caverns: %d",
48             (long)c[GOLD], (long)c[EXPERIENCE], (long)c[LEVEL], (long)level);
49         lprintf("\nTotal types of monsters: %d", (long)MAXMONST + 8);
50
51         lprcat("\f\nHere's the dungeon:\n\n");
52
53         i = level;
54         for (j = 0; j < MAXLEVEL + MAXVLEVEL; j++) {
55                 newcavelevel(j);
56                 lprintf("\nMaze for level %s:\n", levelname[level]);
57                 diagdrawscreen();
58         }
59         newcavelevel(i);
60
61         lprcat("\f\nNow for the monster data:\n\n");
62         lprcat("   Monster Name      LEV  AC   DAM  ATT  DEF    GOLD   HP     EXP   \n");
63         lprcat("--------------------------------------------------------------------------\n");
64         for (i = 0; i <= MAXMONST + 8; i++) {
65                 lprintf("%19s  %2d  %3d ", monster[i].name, (long)monster[i].level, (long)monster[i].armorclass);
66                 lprintf(" %3d  %3d  %3d  ", (long)monster[i].damage, (long)monster[i].attack, (long)monster[i].defense);
67                 lprintf("%6d  %3d   %6d\n", (long)monster[i].gold, (long)monster[i].hitpoints, (long)monster[i].experience);
68         }
69
70         lprcat("\n\nHere's a Table for the to hit percentages\n");
71         lprcat("\n     We will be assuming that players level = 2 * monster level");
72         lprcat("\n     and that the players dexterity and strength are 16.");
73         lprcat("\n    to hit: if (rnd(22) < (2[monst AC] + your level + dex + WC/8 -1)/2) then hit");
74         lprcat("\n    damage = rund(8) + WC/2 + STR - c[HARDGAME] - 4");
75         lprcat("\n    to hit:  if rnd(22) < to hit  then player hits\n");
76         lprcat("\n    Each entry is as follows:  to hit / damage / number hits to kill\n");
77         lprcat("\n          monster     WC = 4         WC = 20        WC = 40");
78         lprcat("\n---------------------------------------------------------------");
79         for (i = 0; i <= MAXMONST + 8; i++) {
80                 hit = 2 * monster[i].armorclass + 2 * monster[i].level + 16;
81                 dam = 16 - c[HARDGAME];
82                 lprintf("\n%20s   %2d/%2d/%2d       %2d/%2d/%2d       %2d/%2d/%2d",
83                         monster[i].name,
84                         (long)(hit / 2), (long)max(0, dam + 2), (long)(monster[i].hitpoints / (dam + 2) + 1),
85                         (long)((hit + 2) / 2), (long)max(0, dam + 10), (long)(monster[i].hitpoints / (dam + 10) + 1),
86                         (long)((hit + 5) / 2), (long)max(0, dam + 20), (long)(monster[i].hitpoints / (dam + 20) + 1));
87         }
88
89         lprcat("\n\nHere's the list of available potions:\n\n");
90         for (i = 0; i < MAXPOTION; i++)
91                 lprintf("%20s\n", &potionhide[i][1]);
92         lprcat("\n\nHere's the list of available scrolls:\n\n");
93         for (i = 0; i < MAXSCROLL; i++)
94                 lprintf("%20s\n", &scrollhide[i][1]);
95         lprcat("\n\nHere's the spell list:\n\n");
96         lprcat("spell          name           description\n");
97         lprcat("-------------------------------------------------------------------------------------------\n\n");
98         for (j = 0; j < SPNUM; j++) {
99                 lprc(' ');
100                 lprcat(spelcode[j]);
101                 lprintf(" %21s  %s\n", spelname[j], speldescript[j]);
102         }
103
104         lprcat("\n\nFor the c[] array:\n");
105         for (j = 0; j < 100; j += 10) {
106                 lprintf("\nc[%2d] = ", (long)j);
107                 for (i = 0; i < 9; i++)
108                         lprintf("%5d ", (long)c[i + j]);
109         }
110
111         lprcat("\n\nTest of random number generator ----------------");
112         lprcat("\n    for 25,000 calls divided into 16 slots\n\n");
113
114         for (i = 0; i < 16; i++)
115                 rndcount[i] = 0;
116         for (i = 0; i < 25000; i++)
117                 rndcount[rund(16)]++;
118         for (i = 0; i < 16; i++) {
119                 lprintf("  %5d", (long)rndcount[i]);
120                 if (i == 7)
121                         lprc('\n');
122         }
123
124         lprcat("\n\n");
125         lwclose();
126         lcreat(NULL);
127         lprcat("Done Diagnosing . . .");
128         return (0);
129 }
130 /*
131         subroutine to count the number of occurrences of an object
132  */
133 static int
134 dcount(int l)
135 {
136         int i, j, p;
137         int k;
138         k = 0;
139         for (i = 0; i < MAXX; i++)
140                 for (j = 0; j < MAXY; j++)
141                         for (p = 0; p < MAXLEVEL; p++)
142                                 if (cell[p * MAXX * MAXY + i * MAXY + j].item == l)
143                                         k++;
144         return (k);
145 }
146
147 /*
148         subroutine to draw the whole screen as the player knows it
149  */
150 static void
151 diagdrawscreen(void)
152 {
153         int i, j, k;
154
155         /* for the east west walls of this line */
156         for (i = 0; i < MAXY; i++) {
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         to save the game in a file
169  */
170 static time_t zzz = 0;
171
172 int
173 savegame(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(NULL);
185                 lprintf("\nCan't open file <%s> to save game\n", fname);
186                 nosignal = 0;
187                 return (-1);
188         }
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)gtime);
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         /* save spheres of annihilation */
219         for (sp = spheres; sp; sp = sp->p)
220                 lwrite((char *)sp, sizeof(struct sphere));
221         time(&zzz);
222         lprint((long)(zzz - initialtime));
223         lwrite((char *)&zzz, sizeof(long));
224         if (fstat(io_outfd, &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(NULL);
234         nosignal = 0;
235         return (0);
236 }
237
238 void
239 restoregame(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(NULL);
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         gtime = lrint_x();
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
288         for (i = 0; i < MAXMONST; i++)
289                 monster[i].genocided = lgetc(); /* genocide info */
290         for (sp = NULL, i = 0; i < c[SPHCAST]; i++) {
291                 sp2 = sp;
292                 sp = malloc(sizeof(struct sphere));
293                 if (sp == NULL) {
294                         write(2, "Can't malloc() for sphere space\n", 32);
295                         break;
296                 }
297                 /* get spheres of annihilation */
298                 lrfill((char *)sp, sizeof(struct sphere));
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_x();
308         /* get the creation and modification time of file */
309         fstat(io_infd, &filetimes);
310         lrfill((char *)&zzz, sizeof(long));
311         zzz += 6;
312         if (filetimes.st_ctime > zzz)           /* file create time */
313                 fsorry();
314         else if (filetimes.st_mtime > zzz)      /* file modify time */
315                 fsorry();
316         if (c[HP] < 0) {
317                 died(284);
318                 return;
319         }                       /* died a post mortem death */
320
321         oldx = oldy = 0;
322         i = lrint_x();          /* inode # */
323         if (i && (filetimes.st_ino != (unsigned)i))
324                 fsorry();
325         lrclose();
326         if (strcmp(fname, ckpfile) == 0) {
327                 if (lappend(fname) < 0)
328                         fcheat();
329                 else {
330                         lprc(' ');
331                         lwclose();
332                 }
333                 lcreat(NULL);
334         } else if (unlink(fname) < 0)
335                 fcheat();       /* can't unlink save file */
336         /* for the greedy cheater checker */
337         for (k = 0; k < 6; k++)
338                 if (c[k] > 99)
339                         greedy();
340         if (c[HPMAX] > 999 || c[SPELLMAX] > 125)
341                 greedy();
342         /* if patch up lev 25 player */
343         if (c[LEVEL] == 25 && c[EXPERIENCE] > skill[24]) {
344                 long tmp;
345                 tmp = c[EXPERIENCE] - skill[24];        /* amount to go up */
346                 c[EXPERIENCE] = skill[24];
347                 raiseexperience((long)tmp);
348         }
349         getlevel();
350         lasttime = gtime;
351 }
352
353 /*
354         subroutine to not allow greedy cheaters
355  */
356 static void
357 greedy(void)
358 {
359 #if WIZID
360         if (wizard)
361                 return;
362 #endif
363
364         lprcat("\n\nI am so sorry, but your character is a little TOO good!  Since this\n");
365         lprcat("cannot normally happen from an honest game, I must assume that you cheated.\n");
366         lprcat("In that you are GREEDY as well as a CHEATER, I cannot allow this game\n");
367         lprcat("to continue.\n");
368         nap(5000);
369         c[GOLD] = c[BANKACCOUNT] = 0;
370         died(-267);
371 }
372
373 /*
374         subroutine to not allow altered save files and terminate the attempted
375         restart
376  */
377 static void
378 fsorry(void)
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 static void
391 fcheat(void)
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 }