1 /* $NetBSD: diag.c,v 1.11 2008/01/28 05:38:53 dholland Exp $ */
3 /* diag.c Larn is copyrighted 1986 by Noah Morgan. */
6 __RCSID("$NetBSD: diag.c,v 1.11 2008/01/28 05:38:53 dholland Exp $");
10 #include <sys/times.h>
18 static void greedy(void);
19 static void fsorry(void);
20 static void fcheat(void);
22 static struct tms cputime
;
25 ***************************
26 DIAG -- dungeon diagnostics
27 ***************************
29 subroutine to print out data for debugging
32 static int rndcount
[16];
40 if (lcreat(diagfile
) < 0) { /* open the diagnostic file */
42 lprcat("\ndiagnostic failure\n");
45 write(1, "\nDiagnosing . . .\n", 18);
46 lprcat("\n\nBeginning of DIAG diagnostics ----------\n");
48 /* for the character attributes */
50 lprintf("\n\nPlayer attributes:\n\nHit points: %2ld(%2ld)", (long) c
[HP
], (long) c
[HPMAX
]);
51 lprintf("\ngold: %ld Experience: %ld Character level: %ld Level in caverns: %ld",
52 (long) c
[GOLD
], (long) c
[EXPERIENCE
], (long) c
[LEVEL
], (long) level
);
53 lprintf("\nTotal types of monsters: %ld", (long) MAXMONST
+ 8);
55 lprcat("\f\nHere's the dungeon:\n\n");
58 for (j
= 0; j
< MAXLEVEL
+ MAXVLEVEL
; j
++) {
60 lprintf("\nMaze for level %s:\n", levelname
[level
]);
65 lprcat("\f\nNow for the monster data:\n\n");
66 lprcat(" Monster Name LEV AC DAM ATT DEF GOLD HP EXP \n");
67 lprcat("--------------------------------------------------------------------------\n");
68 for (i
= 0; i
<= MAXMONST
+ 8; i
++) {
69 lprintf("%19s %2ld %3ld ", monster
[i
].name
, (long) monster
[i
].level
, (long) monster
[i
].armorclass
);
70 lprintf(" %3ld %3ld %3ld ", (long) monster
[i
].damage
, (long) monster
[i
].attack
, (long) monster
[i
].defense
);
71 lprintf("%6ld %3ld %6ld\n", (long) monster
[i
].gold
, (long) monster
[i
].hitpoints
, (long) monster
[i
].experience
);
74 lprcat("\n\nHere's a Table for the to hit percentages\n");
75 lprcat("\n We will be assuming that players level = 2 * monster level");
76 lprcat("\n and that the players dexterity and strength are 16.");
77 lprcat("\n to hit: if (rnd(22) < (2[monst AC] + your level + dex + WC/8 -1)/2) then hit");
78 lprcat("\n damage = rund(8) + WC/2 + STR - c[HARDGAME] - 4");
79 lprcat("\n to hit: if rnd(22) < to hit then player hits\n");
80 lprcat("\n Each entry is as follows: to hit / damage / number hits to kill\n");
81 lprcat("\n monster WC = 4 WC = 20 WC = 40");
82 lprcat("\n---------------------------------------------------------------");
83 for (i
= 0; i
<= MAXMONST
+ 8; i
++) {
84 hit
= 2 * monster
[i
].armorclass
+ 2 * monster
[i
].level
+ 16;
85 dam
= 16 - c
[HARDGAME
];
86 lprintf("\n%20s %2ld/%2ld/%2ld %2ld/%2ld/%2ld %2ld/%2ld/%2ld",
88 (long) (hit
/ 2), (long) max(0, dam
+ 2), (long) (monster
[i
].hitpoints
/ (dam
+ 2) + 1),
89 (long) ((hit
+ 2) / 2), (long) max(0, dam
+ 10), (long) (monster
[i
].hitpoints
/ (dam
+ 10) + 1),
90 (long) ((hit
+ 5) / 2), (long) max(0, dam
+ 20), (long) (monster
[i
].hitpoints
/ (dam
+ 20) + 1));
93 lprcat("\n\nHere's the list of available potions:\n\n");
94 for (i
= 0; i
< MAXPOTION
; i
++)
95 lprintf("%20s\n", &potionhide
[i
][1]);
96 lprcat("\n\nHere's the list of available scrolls:\n\n");
97 for (i
= 0; i
< MAXSCROLL
; i
++)
98 lprintf("%20s\n", &scrollhide
[i
][1]);
99 lprcat("\n\nHere's the spell list:\n\n");
100 lprcat("spell name description\n");
101 lprcat("-------------------------------------------------------------------------------------------\n\n");
102 for (j
= 0; j
< SPNUM
; j
++) {
105 lprintf(" %21s %s\n", spelname
[j
], speldescript
[j
]);
108 lprcat("\n\nFor the c[] array:\n");
109 for (j
= 0; j
< 100; j
+= 10) {
110 lprintf("\nc[%2ld] = ", (long) j
);
111 for (i
= 0; i
< 9; i
++)
112 lprintf("%5ld ", (long) c
[i
+ j
]);
115 lprcat("\n\nTest of random number generator ----------------");
116 lprcat("\n for 25,000 calls divided into 16 slots\n\n");
118 for (i
= 0; i
< 16; i
++)
120 for (i
= 0; i
< 25000; i
++)
121 rndcount
[rund(16)]++;
122 for (i
= 0; i
< 16; i
++) {
123 lprintf(" %5ld", (long) rndcount
[i
]);
131 lprcat("Done Diagnosing . . .");
135 subroutine to count the number of occurrences of an object
144 for (i
= 0; i
< MAXX
; i
++)
145 for (j
= 0; j
< MAXY
; j
++)
146 for (p
= 0; p
< MAXLEVEL
; p
++)
147 if (cell
[p
* MAXX
* MAXY
+ i
* MAXY
+ j
].item
== l
)
153 subroutine to draw the whole screen as the player knows it
160 for (i
= 0; i
< MAXY
; i
++)
161 /* for the east west walls of this line */
163 for (j
= 0; j
< MAXX
; j
++)
165 lprc(monstnamelist
[k
]);
167 lprc(objnamelist
[item
[j
][i
]]);
175 to save the game in a file
177 static time_t zzz
= 0;
190 if (lcreat(fname
) < 0) {
192 lprintf("\nCan't open file <%s> to save game\n", fname
);
197 lwrite((char *) beenhere
, MAXLEVEL
+ MAXVLEVEL
);
198 for (k
= 0; k
< MAXLEVEL
+ MAXVLEVEL
; k
++)
200 lwrite((char *) &cell
[k
* MAXX
* MAXY
], sizeof(struct cel
) * MAXY
* MAXX
);
201 times(&cputime
); /* get cpu time */
202 c
[CPUTIME
] += (cputime
.tms_utime
+ cputime
.tms_stime
) / 60;
203 lwrite((char *) &c
[0], 100 * sizeof(long));
204 lprint((long) gltime
);
208 lwrite((char *) iven
, 26);
209 lwrite((char *) ivenarg
, 26 * sizeof(short));
210 for (k
= 0; k
< MAXSCROLL
; k
++)
211 lprc(scrollname
[k
][0]);
212 for (k
= 0; k
< MAXPOTION
; k
++)
213 lprc(potionname
[k
][0]);
214 lwrite((char *) spelknow
, SPNUM
);
216 lprc(rmst
); /* random monster generation counter */
217 for (i
= 0; i
< 90; i
++)
219 lwrite((char *) course
, 25);
222 for (i
= 0; i
< MAXMONST
; i
++)
223 lprc(monster
[i
].genocided
); /* genocide info */
224 for (sp
= spheres
; sp
; sp
= sp
->p
)
225 lwrite((char *) sp
, sizeof(struct sphere
)); /* save spheres of
228 lprint((long) (zzz
- initialtime
));
229 lwrite((char *) &zzz
, sizeof(long));
230 if (fstat(io_outfd
, &statbuf
) < 0)
233 lprint((long) statbuf
.st_ino
); /* inode # */
249 struct sphere
*sp
, *sp2
;
250 struct stat filetimes
;
252 lprcat("\nRestoring . . .");
254 if (lopen(fname
) <= 0) {
256 lprintf("\nCan't open file <%s>to restore game\n", fname
);
258 c
[GOLD
] = c
[BANKACCOUNT
] = 0;
262 lrfill((char *) beenhere
, MAXLEVEL
+ MAXVLEVEL
);
263 for (k
= 0; k
< MAXLEVEL
+ MAXVLEVEL
; k
++)
265 lrfill((char *) &cell
[k
* MAXX
* MAXY
], sizeof(struct cel
) * MAXY
* MAXX
);
267 lrfill((char *) &c
[0], 100 * sizeof(long));
268 gltime
= larn_lrint();
269 level
= c
[CAVELEVEL
] = lgetc();
272 lrfill((char *) iven
, 26);
273 lrfill((char *) ivenarg
, 26 * sizeof(short));
274 for (k
= 0; k
< MAXSCROLL
; k
++)
275 scrollname
[k
] = lgetc() ? scrollhide
[k
] : "";
276 for (k
= 0; k
< MAXPOTION
; k
++)
277 potionname
[k
] = lgetc() ? potionhide
[k
] : "";
278 lrfill((char *) spelknow
, SPNUM
);
280 rmst
= lgetc(); /* random monster creation flag */
282 for (i
= 0; i
< 90; i
++)
283 itm
[i
].qty
= lgetc();
284 lrfill((char *) course
, 25);
286 if (VERSION
!= lgetc()) { /* version number */
288 lprcat("Sorry, But your save file is for an older version of larn\n");
290 c
[GOLD
] = c
[BANKACCOUNT
] = 0;
294 for (i
= 0; i
< MAXMONST
; i
++)
295 monster
[i
].genocided
= lgetc(); /* genocide info */
296 for (sp
= 0, i
= 0; i
< c
[SPHCAST
]; i
++) {
298 sp
= (struct sphere
*) malloc(sizeof(struct sphere
));
300 write(2, "Can't malloc() for sphere space\n", 32);
303 lrfill((char *) sp
, sizeof(struct sphere
)); /* get spheres of
305 sp
->p
= 0; /* null out pointer */
307 spheres
= sp
; /* beginning of list */
313 initialtime
= zzz
- larn_lrint();
314 /* get the creation and modification time of file */
315 fstat(io_infd
, &filetimes
);
316 lrfill((char *) &zzz
, sizeof(long));
318 if (filetimes
.st_ctime
> zzz
)
319 fsorry(); /* file create time */
320 else if (filetimes
.st_mtime
> zzz
)
321 fsorry(); /* file modify time */
325 } /* died a post mortem death */
327 /* XXX the following will break on 64-bit inode numbers */
328 i
= larn_lrint(); /* inode # */
329 if (i
&& (filetimes
.st_ino
!= (ino_t
) i
))
332 if (strcmp(fname
, ckpfile
) == 0) {
333 if (lappend(fname
) < 0)
340 } else if (unlink(fname
) < 0)
341 fcheat(); /* can't unlink save file */
342 /* for the greedy cheater checker */
343 for (k
= 0; k
< 6; k
++)
346 if (c
[HPMAX
] > 999 || c
[SPELLMAX
] > 125)
348 if (c
[LEVEL
] == 25 && c
[EXPERIENCE
] > skill
[24]) { /* if patch up lev 25
351 tmp
= c
[EXPERIENCE
] - skill
[24]; /* amount to go up */
352 c
[EXPERIENCE
] = skill
[24];
353 raiseexperience((long) tmp
);
360 subroutine to not allow greedy cheaters
370 lprcat("\n\nI am so sorry, but your character is a little TOO good! Since this\n");
371 lprcat("cannot normally happen from an honest game, I must assume that you cheated.\n");
372 lprcat("In that you are GREEDY as well as a CHEATER, I cannot allow this game\n");
373 lprcat("to continue.\n");
375 c
[GOLD
] = c
[BANKACCOUNT
] = 0;
381 subroutine to not allow altered save files and terminate the attempted
387 lprcat("\nSorry, but your savefile has been altered.\n");
388 lprcat("However, seeing as I am a good sport, I will let you play.\n");
389 lprcat("Be advised though, you won't be placed on the normal scoreboard.");
395 subroutine to not allow game if save file can't be deleted
405 lprcat("\nSorry, but your savefile can't be deleted. This can only mean\n");
406 lprcat("that you tried to CHEAT by protecting the directory the savefile\n");
407 lprcat("is in. Since this is unfair to the rest of the larn community, I\n");
408 lprcat("cannot let you play this game.\n");
410 c
[GOLD
] = c
[BANKACCOUNT
] = 0;