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