1 /* source/files.c: misc code to access files used by Moria
2
3 Copyright (c) 1989-94 James E. Wilson, Robert A. Koeneke
4
5 This software may be copied and distributed for educational, research, and
6 not for profit purposes provided that this copyright and statement are
7 included in all such copies. */
8
9 #include <stdio.h>
10
11 #ifndef STDIO_LOADED
12 #define STDIO_LOADED
13 #endif
14
15 #if 0
16 /* moved to externs.h to avoid VMS 'psect' problem */
17 #include <errno.h>
18 #endif
19
20 #ifdef __TURBOC__
21 #include <io.h>
22 #include <stdlib.h>
23 #endif /* __TURBOC__ */
24
25 #include "config.h"
26 #include "constant.h"
27 #include "types.h"
28
29 #if defined(GEMDOS) && (__STDC__ == 0) && !defined(ATARIST_TC)
30 #include <access.h>
31 char *strcat();
32 #endif
33
34 #ifdef VMS
35 #include <string.h>
36 #include <file.h>
37 #else
38 #ifdef USG
39 #ifndef ATARIST_MWC
40 #include <string.h>
41 #ifndef ATARIST_TC
42 #include <fcntl.h>
43 #endif
44 #endif
45 #else
46 #include <strings.h>
47 #include <sys/file.h>
48 #endif
49 #if defined(ultrix) || defined(USG)
50 void exit();
51 #endif
52 #endif
53
54 /* This must be included after fcntl.h, which has a prototype for `open'
55 on some systems. Otherwise, the `open' prototype conflicts with the
56 `topen' declaration. */
57 #include "externs.h"
58
59 #ifdef ATARIST_TC
60 /* Include this to get prototypes for standard library functions. */
61 #include <stdlib.h>
62 #endif
63
64 #ifdef MAC
65 #include "ScrnMgr.h"
66 #define GNRL_ALRT 1024
67 #endif
68
69 /*
70 * init_scorefile
71 * Open the score file while we still have the setuid privileges. Later
72 * when the score is being written out, you must be sure to flock the file
73 * so we don't have multiple people trying to write to it at the same time.
74 * Craig Norborg (doc) Mon Aug 10 16:41:59 EST 1987
75 */
init_scorefile()76 void init_scorefile()
77 {
78 #ifdef MAC
79 appldirectory ();
80 #endif
81
82 #if defined(atarist) || defined(ATARI_ST) || defined(MAC)
83 highscore_fp = fopen(MORIA_TOP, "rb+");
84 #else
85 highscore_fp = fopen(MORIA_TOP, "r+");
86 #endif
87
88 if (highscore_fp == NULL)
89 {
90 #ifdef MAC
91 highscore_fp = fopen (MORIA_TOP, "wb"); /* Create it if not there. */
92 if (highscore_fp == NULL)
93 {
94 ParamText ("\pCan't create score file!", NULL, NULL, NULL);
95 DoScreenALRT (GNRL_ALRT, akStop, fixHalf, fixThird);
96 ExitToShell ();
97 }
98 setfileinfo (MORIA_TOP, currentdirectory (), SCORE_FTYPE);
99 #else
100 (void) fprintf (stderr, "Can't open score file \"%s\"\n", MORIA_TOP);
101 exit(1);
102 #endif
103 }
104 #if defined(MSDOS) || defined(VMS) || defined(MAC) || defined(APOLLO)
105 /* can't leave it open, since this causes problems on networked PCs and VMS,
106 we DO want to check to make sure we can open the file, though */
107 fclose (highscore_fp);
108 #endif
109
110 #ifdef MAC
111 restoredirectory ();
112 #endif
113 }
114
115 #ifndef MAC
116 /* Attempt to open the intro file -RAK- */
117 /* This routine also checks the hours file vs. what time it is -Doc */
read_times()118 void read_times()
119 {
120 vtype in_line;
121 register int i;
122 FILE *file1;
123
124 #ifdef MORIA_HOU
125 /* Attempt to read hours.dat. If it does not exist, */
126 /* inform the user so he can tell the wizard about it */
127 if ((file1 = fopen(MORIA_HOU, "r")) != NULL)
128 {
129 while (fgets(in_line, 80, file1) != CNIL)
130 if (strlen(in_line) > 3)
131 {
132 if (!strncmp(in_line, "SUN:", 4))
133 (void) strcpy(days[0], in_line);
134 else if (!strncmp(in_line, "MON:", 4))
135 (void) strcpy(days[1], in_line);
136 else if (!strncmp(in_line, "TUE:", 4))
137 (void) strcpy(days[2], in_line);
138 else if (!strncmp(in_line, "WED:", 4))
139 (void) strcpy(days[3], in_line);
140 else if (!strncmp(in_line, "THU:", 4))
141 (void) strcpy(days[4], in_line);
142 else if (!strncmp(in_line, "FRI:", 4))
143 (void) strcpy(days[5], in_line);
144 else if (!strncmp(in_line, "SAT:", 4))
145 (void) strcpy(days[6], in_line);
146 }
147 (void) fclose(file1);
148 }
149 else
150 {
151 restore_term();
152 (void) fprintf(stderr, "There is no hours file \"%s\".\n", MORIA_HOU);
153 (void) fprintf(stderr, "Please inform the wizard, %s, so he ", WIZARD);
154 (void) fprintf(stderr, "can correct this!\n");
155 exit(1);
156 }
157
158 /* Check the hours, if closed then exit. */
159 if (!check_time())
160 {
161 if ((file1 = fopen(MORIA_HOU, "r")) != NULL)
162 {
163 clear_screen();
164 #ifdef VMS
165 restore_screen();
166 #endif
167 for (i = 0; fgets(in_line, 80, file1) != CNIL; i++)
168 put_buffer(in_line, i, 0);
169 pause_line (23);
170 (void) fclose(file1);
171 }
172 exit_game();
173 }
174 #endif
175
176 /* Print the introduction message, news, etc. */
177 if ((file1 = fopen(MORIA_MOR, "r")) != NULL)
178 {
179 clear_screen();
180 #ifdef VMS
181 restore_screen();
182 #endif
183 for (i = 0; fgets(in_line, 80, file1) != CNIL; i++)
184 put_buffer(in_line, i, 0);
185 pause_line(23);
186 (void) fclose(file1);
187 }
188 }
189 #endif
190
191 /* File perusal. -CJS-
192 primitive, but portable */
helpfile(filename)193 void helpfile(filename)
194 char *filename;
195 #ifdef MAC
196 {
197 mac_helpfile(filename, TRUE);
198 }
199 #else
200 {
201 bigvtype tmp_str;
202 FILE *file;
203 char input;
204 int i;
205
206 file = fopen(filename, "r");
207 if (file == NULL)
208 {
209 (void) sprintf (tmp_str, "Can not find help file \"%s\".\n", filename);
210 prt (tmp_str, 0, 0);
211 return;
212 }
213
214 save_screen();
215
216 while (!feof(file))
217 {
218 clear_screen();
219 for (i = 0; i < 23; i++)
220 if (fgets (tmp_str, BIGVTYPESIZ-1, file) != CNIL)
221 put_buffer (tmp_str, i, 0);
222 prt("[Press any key to continue.]", 23, 23);
223 input = inkey();
224 if (input == ESCAPE)
225 break;
226 }
227
228 (void) fclose(file);
229 restore_screen();
230 }
231 #endif
232
233 /* Prints a list of random objects to a file. Note that -RAK- */
234 /* the objects produced is a sampling of objects which */
235 /* be expected to appear on that level. */
print_objects()236 void print_objects()
237 {
238 register int i;
239 int nobj, j, level, small;
240 vtype filename1; bigvtype tmp_str;
241 register FILE *file1;
242 register inven_type *i_ptr;
243 #ifdef MAC
244 short vrefnum;
245 #endif
246 #ifdef ATARIST_MWC
247 int32u holder;
248 #endif
249
250 prt("Produce objects on what level?: ", 0, 0);
251 level = 0;
252 if (!get_string(tmp_str, 0, 32, 10))
253 return;
254 level = atoi(tmp_str);
255 prt("Produce how many objects?: ", 0, 0);
256 nobj = 0;
257 if (!get_string(tmp_str, 0, 27, 10))
258 return;
259 nobj = atoi(tmp_str);
260 small = get_check("Small objects only?");
261 if ((nobj > 0) && (level > -1) && (level < 1201))
262 {
263 if (nobj > 10000)
264 nobj = 10000;
265 #ifdef MAC
266 (void) strcpy(filename1, "Objects");
267 if (doputfile("Save objects in:", filename1, &vrefnum))
268 #else
269 prt("File name: ", 0, 0);
270 if (get_string(filename1, 0, 11, 64))
271 #endif
272 {
273 if (strlen(filename1) == 0)
274 return;
275 #ifdef MAC
276 changedirectory(vrefnum);
277 #endif
278 if ((file1 = fopen(filename1, "w")) != NULL)
279 {
280 #ifdef MAC
281 macbeginwait ();
282 #endif
283
284 (void) sprintf(tmp_str, "%d", nobj);
285 prt(strcat(tmp_str, " random objects being produced..."), 0, 0);
286 put_qio();
287 (void) fprintf(file1, "*** Random Object Sampling:\n");
288 (void) fprintf(file1, "*** %d objects\n", nobj);
289 (void) fprintf(file1, "*** For Level %d\n", level);
290 (void) fprintf(file1, "\n");
291 (void) fprintf(file1, "\n");
292 j = popt();
293 for (i = 0; i < nobj; i++)
294 {
295 invcopy(&t_list[j],
296 sorted_objects[get_obj_num(level,small)]);
297 magic_treasure(j, level);
298 i_ptr = &t_list[j];
299 store_bought(i_ptr);
300 #ifdef ATARIST_MWC
301 if (i_ptr->flags & (holder = TR_CURSED))
302 #else
303 if (i_ptr->flags & TR_CURSED)
304 #endif
305 add_inscribe(i_ptr, ID_DAMD);
306 objdes(tmp_str, i_ptr, TRUE);
307 (void) fprintf(file1, "%d %s\n", i_ptr->level, tmp_str);
308 }
309 pusht((int8u)j);
310 (void) fclose(file1);
311 #ifdef MAC
312 setfileinfo(filename1, vrefnum, INFO_FTYPE);
313 macendwait ();
314 #endif
315 prt("Completed.", 0, 0);
316 }
317 else
318 prt("File could not be opened.", 0, 0);
319 #ifdef MAC
320 restoredirectory();
321 #endif
322 }
323 }
324 else
325 prt ("Parameters no good.", 0, 0);
326 }
327
328
329 /* Print the character to a file or device -RAK- */
330 #ifdef MAC
file_character()331 int file_character()
332 #else
333 int file_character(filename1)
334 char *filename1;
335 #endif
336 {
337 register int i;
338 int j, xbth, xbthb, xfos, xsrh, xstl, xdis, xsave, xdev;
339 vtype xinfra;
340 int fd;
341 register FILE *file1;
342 bigvtype prt2;
343 register struct misc *p_ptr;
344 register inven_type *i_ptr;
345 vtype out_val, prt1;
346 char *p, *colon, *blank;
347 #ifdef MAC
348 vtype filename1;
349 short vrefnum;
350 #endif
351
352 #ifdef MAC
353 (void) makefilename(filename1, "Stats", TRUE);
354 if (!doputfile("Save character description in:", filename1, &vrefnum))
355 return (FALSE);
356 #endif
357
358 #ifndef VMS
359 /* VMS creates a new version of a file, so no need to check for rewrite. */
360 #ifdef MAC
361 changedirectory(vrefnum);
362 fd = open (filename1, O_WRONLY|O_CREAT|O_TRUNC);
363 restoredirectory();
364 macbeginwait ();
365 #else
366 #if defined(GEMDOS) && (__STDC__ == 0) && !defined(ATARIST_TC)
367 if (!access(filename1, AREAD))
368 {
369 (void) sprintf(out_val, "Replace existing file %s?", filename1);
370 if (get_check(out_val))
371 fd = creat(filename1, 1);
372 }
373 else
374 fd = creat (filename1, 1);
375 #else
376 fd = open (filename1, O_WRONLY|O_CREAT|O_EXCL, 0644);
377 if (fd < 0 && errno == EEXIST)
378 {
379 (void) sprintf(out_val, "Replace existing file %s?", filename1);
380 if (get_check(out_val))
381 fd = open(filename1, O_WRONLY, 0644);
382 }
383 #endif
384 #endif
385 if (fd >= 0)
386 {
387 /* on some non-unix machines, fdopen() is not reliable, hence must call
388 close() and then fopen() */
389 (void) close(fd);
390 file1 = fopen(filename1, "w");
391 }
392 else
393 file1 = NULL;
394 #else /* VMS */
395 fd = -1;
396 file1 = fopen (filename1, "w");
397 #endif
398
399 if (file1 != NULL)
400 {
401 prt("Writing character sheet...", 0, 0);
402 put_qio();
403 colon = ":";
404 blank = " ";
405 #ifdef MAC
406 (void) fprintf(file1, "\n\n");
407 #else
408 (void) fprintf(file1, "%c\n\n", CTRL('L'));
409 #endif
410 (void) fprintf(file1, " Name%9s %-23s", colon, py.misc.name);
411 (void) fprintf(file1, " Age%11s %6d", colon, (int)py.misc.age);
412 cnv_stat(py.stats.use_stat[A_STR], prt1);
413 (void) fprintf(file1, " STR : %s\n", prt1);
414 (void) fprintf(file1, " Race%9s %-23s", colon,
415 race[py.misc.prace].trace);
416 (void) fprintf(file1, " Height%8s %6d", colon, (int)py.misc.ht);
417 cnv_stat(py.stats.use_stat[A_INT], prt1);
418 (void) fprintf(file1, " INT : %s\n", prt1);
419 (void) fprintf(file1, " Sex%10s %-23s", colon,
420 (py.misc.male ? "Male" : "Female"));
421 (void) fprintf(file1, " Weight%8s %6d", colon, (int)py.misc.wt);
422 cnv_stat(py.stats.use_stat[A_WIS], prt1);
423 (void) fprintf(file1, " WIS : %s\n", prt1);
424 (void) fprintf(file1, " Class%8s %-23s", colon,
425 class[py.misc.pclass].title);
426 (void) fprintf(file1, " Social Class : %6d", py.misc.sc);
427 cnv_stat(py.stats.use_stat[A_DEX], prt1);
428 (void) fprintf(file1, " DEX : %s\n", prt1);
429 (void) fprintf(file1, " Title%8s %-23s", colon, title_string());
430 (void) fprintf(file1, "%22s", blank);
431 cnv_stat(py.stats.use_stat[A_CON], prt1);
432 (void) fprintf(file1, " CON : %s\n", prt1);
433 (void) fprintf(file1, "%34s", blank);
434 (void) fprintf(file1, "%26s", blank);
435 cnv_stat(py.stats.use_stat[A_CHR], prt1);
436 (void) fprintf(file1, " CHR : %s\n\n", prt1);
437
438 (void) fprintf(file1, " + To Hit : %6d", py.misc.dis_th);
439 (void) fprintf(file1, "%7sLevel : %7d", blank, (int)py.misc.lev);
440 (void) fprintf(file1, " Max Hit Points : %6d\n", py.misc.mhp);
441 (void) fprintf(file1, " + To Damage : %6d", py.misc.dis_td);
442 (void) fprintf(file1, "%7sExperience : %7ld", blank, py.misc.exp);
443 (void) fprintf(file1, " Cur Hit Points : %6d\n", py.misc.chp);
444 (void) fprintf(file1, " + To AC : %6d", py.misc.dis_tac);
445 (void) fprintf(file1, "%7sMax Exp : %7ld", blank, py.misc.max_exp);
446 (void) fprintf(file1, " Max Mana%8s %6d\n", colon, py.misc.mana);
447 (void) fprintf(file1, " Total AC : %6d", py.misc.dis_ac);
448 if (py.misc.lev >= MAX_PLAYER_LEVEL)
449 (void) fprintf (file1, "%7sExp to Adv : *******", blank);
450 else
451 (void) fprintf(file1, "%7sExp to Adv : %7ld", blank,
452 (int32)(player_exp[py.misc.lev-1]
453 * py.misc.expfact / 100));
454 (void) fprintf(file1, " Cur Mana%8s %6d\n", colon, py.misc.cmana);
455 (void) fprintf(file1, "%28sGold%8s %7ld\n\n", blank, colon,
456 py.misc.au);
457
458 p_ptr = &py.misc;
459 xbth = p_ptr->bth + p_ptr->ptohit * BTH_PLUS_ADJ
460 + (class_level_adj[p_ptr->pclass][CLA_BTH] * p_ptr->lev);
461 xbthb = p_ptr->bthb + p_ptr->ptohit * BTH_PLUS_ADJ
462 + (class_level_adj[p_ptr->pclass][CLA_BTHB] * p_ptr->lev);
463 /* this results in a range from 0 to 29 */
464 xfos = 40 - p_ptr->fos;
465 if (xfos < 0)
466 xfos = 0;
467 xsrh = p_ptr->srh;
468 /* this results in a range from 0 to 9 */
469 xstl = p_ptr->stl + 1;
470 xdis = p_ptr->disarm + 2 * todis_adj() + stat_adj(A_INT)
471 + (class_level_adj[p_ptr->pclass][CLA_DISARM] * p_ptr->lev / 3);
472 xsave = p_ptr->save + stat_adj(A_WIS)
473 + (class_level_adj[p_ptr->pclass][CLA_SAVE] * p_ptr->lev / 3);
474 xdev = p_ptr->save + stat_adj(A_INT)
475 + (class_level_adj[p_ptr->pclass][CLA_DEVICE] * p_ptr->lev / 3);
476
477 (void) sprintf(xinfra, "%d feet", py.flags.see_infra * 10);
478
479 (void) fprintf(file1, "(Miscellaneous Abilities)\n\n");
480 (void) fprintf(file1, " Fighting : %-10s", likert(xbth, 12));
481 (void) fprintf(file1, " Stealth : %-10s", likert(xstl, 1));
482 (void) fprintf(file1, " Perception : %s\n", likert(xfos, 3));
483 (void) fprintf(file1, " Bows/Throw : %-10s", likert(xbthb, 12));
484 (void) fprintf(file1, " Disarming : %-10s", likert(xdis, 8));
485 (void) fprintf(file1, " Searching : %s\n", likert(xsrh, 6));
486 (void) fprintf(file1, " Saving Throw: %-10s", likert(xsave, 6));
487 (void) fprintf(file1, " Magic Device: %-10s", likert(xdev, 6));
488 (void) fprintf(file1, " Infra-Vision: %s\n\n", xinfra);
489 /* Write out the character's history */
490 (void) fprintf(file1, "Character Background\n");
491 for (i = 0; i < 4; i++)
492 (void) fprintf(file1, " %s\n", py.misc.history[i]);
493 /* Write out the equipment list. */
494 j = 0;
495 (void) fprintf(file1, "\n [Character's Equipment List]\n\n");
496 if (equip_ctr == 0)
497 (void) fprintf(file1, " Character has no equipment in use.\n");
498 else
499 for (i = INVEN_WIELD; i < INVEN_ARRAY_SIZE; i++)
500 {
501 i_ptr = &inventory[i];
502 if (i_ptr->tval != TV_NOTHING)
503 {
504 switch (i)
505 {
506 case INVEN_WIELD: p = "You are wielding"; break;
507 case INVEN_HEAD: p = "Worn on head"; break;
508 case INVEN_NECK: p = "Worn around neck"; break;
509 case INVEN_BODY: p = "Worn on body"; break;
510 case INVEN_ARM: p = "Worn on shield arm";break;
511 case INVEN_HANDS: p = "Worn on hands"; break;
512 case INVEN_RIGHT: p = "Right ring finger";break;
513 case INVEN_LEFT: p = "Left ring finger";break;
514 case INVEN_FEET: p = "Worn on feet"; break;
515 case INVEN_OUTER: p = "Worn about body"; break;
516 case INVEN_LIGHT: p = "Light source is"; break;
517 case INVEN_AUX: p = "Secondary weapon"; break;
518 default: p = "*Unknown value*"; break;
519 }
520 objdes(prt2, &inventory[i], TRUE);
521 (void) fprintf(file1, " %c) %-19s: %s\n", j+'a', p, prt2);
522 j++;
523 }
524 }
525
526 /* Write out the character's inventory. */
527 #ifdef MAC
528 (void) fprintf(file1, "\n\n");
529 #else
530 (void) fprintf(file1, "%c\n\n", CTRL('L'));
531 #endif
532 (void) fprintf(file1, " [General Inventory List]\n\n");
533 if (inven_ctr == 0)
534 (void) fprintf(file1, " Character has no objects in inventory.\n");
535 else
536 {
537 for (i = 0; i < inven_ctr; i++)
538 {
539 objdes(prt2, &inventory[i], TRUE);
540 (void) fprintf(file1, "%c) %s\n", i+'a', prt2);
541 }
542 }
543 #ifndef MAC
544 (void) fprintf(file1, "%c", CTRL('L'));
545 #endif
546 (void) fclose(file1);
547 #ifdef MAC
548 setfileinfo(filename1, vrefnum, INFO_FTYPE);
549 macendwait ();
550 #endif
551 prt("Completed.", 0, 0);
552 return TRUE;
553 }
554 else
555 {
556 if (fd >= 0)
557 (void) close (fd);
558 (void) sprintf (out_val, "Can't open file %s:", filename1);
559 msg_print(out_val);
560 return FALSE;
561 }
562 }
563