1 /* copyright (c) 1987,1988,1989 by Laurence Raphael Brothers */
2 /* utils.c */
3
4 /* Random utility functions called from all over */
5
6 #ifndef MSDOS_SUPPORTED_ANTIQUE
7 #include <sys/types.h>
8 #include <sys/time.h>
9 #include <sys/wait.h>
10 #include <unistd.h>
11 #include <stdlib.h>
12 #endif
13
14 #include "glob.h"
15
16 /* x and y on level? */
inbounds(x,y)17 int inbounds(x,y)
18 int x,y;
19 {
20 return((x>=0)&&(y>=0)&&(x<WIDTH)&&(y<LENGTH));
21 }
22
23 /* RANDFUNCTION is defined in odefs.h */
random_range(k)24 int random_range(k)
25 int k;
26 {
27 /*return( k==0 ? 0 : (int) RANDFUNCTION() % k ) ;*/
28 return( k==0 ? 0 : (int) ((RANDFUNCTION()%10000)*k)/10000);
29 }
30
31
32 /* modify absolute y coord relative to which part of level we are on */
screenmod(y)33 int screenmod(y)
34 int y;
35 {
36 return(y-ScreenOffset);
37 }
38
39
offscreen(y)40 int offscreen(y)
41 int y;
42 {
43 return((y<0)||
44 (y<ScreenOffset) ||
45 (y>ScreenOffset+ScreenLength-1) ||
46 (y>LENGTH));
47 }
48
49
50 /* always hit on a natural 0; never hit on a natural 19 */
hitp(hit,ac)51 int hitp(hit,ac)
52 int hit,ac;
53 {
54 int roll = random_range(20);
55 if (roll == 0) return(TRUE);
56 else if (roll == 19) return(FALSE);
57 else return((roll < (hit - ac)) ? TRUE : FALSE );
58 }
59
60
61
62
63 /* number of moves from x1,y1 to x2,y2 */
distance(x1,y1,x2,y2)64 int distance(x1,y1,x2,y2)
65 int x1,y1,x2,y2;
66 {
67 return(max(abs(x2-x1),abs(y2-y1)));
68 }
69
70
71 /* can you shoot, or move monsters through a spot? */
unblocked(x,y)72 int unblocked(x,y)
73 int x,y;
74 {
75 if ((! inbounds(x,y)) ||
76 (Level->site[x][y].creature != NULL) ||
77 (Level->site[x][y].locchar == WALL) ||
78 (Level->site[x][y].locchar == PORTCULLIS) ||
79 (Level->site[x][y].locchar == STATUE) ||
80 (Level->site[x][y].locchar == HEDGE) ||
81 (Level->site[x][y].locchar == CLOSED_DOOR) ||
82 loc_statusp(x,y,SECRET) ||
83 ((x==Player.x) && (y==Player.y)))
84 return(FALSE);
85 else
86 return(TRUE);
87 }
88
89
90 /* do monsters want to move through a spot */
m_unblocked(m,x,y)91 int m_unblocked(m,x,y)
92 struct monster *m;
93 int x,y;
94 {
95 if ((! inbounds(x,y)) || ((x==Player.x) && (y==Player.y)))
96 return(FALSE);
97 else if ((Level->site[x][y].creature != NULL) ||
98 (Level->site[x][y].locchar == SPACE)) return(FALSE);
99 else if (m_statusp(m,ONLYSWIM))
100 return(Level->site[x][y].locchar == WATER);
101 else if (loc_statusp(x,y,SECRET)) {
102 if (m->movef == M_MOVE_SMART) {
103 if (los_p(x, y, Player.x, Player.y)) {
104 mprint("You see a secret door swing open!");
105 lreset(x, y, SECRET);
106 lset(x, y, CHANGED);
107 }
108 else
109 mprint("You hear a door creak open, and then close again.");
110 /* smart monsters would close secret doors behind them if the */
111 /* player didn't see them using it */
112 return(TRUE);
113 }
114 else
115 return(m_statusp(m,INTANGIBLE));
116 }
117 else if ((Level->site[x][y].locchar == FLOOR) ||
118 (Level->site[x][y].locchar == OPEN_DOOR))
119 return(TRUE);
120 else if ((Level->site[x][y].locchar == PORTCULLIS) ||
121 (Level->site[x][y].locchar == WALL) ||
122 (Level->site[x][y].locchar == STATUE))
123 return(m_statusp(m,INTANGIBLE));
124 else if (Level->site[x][y].locchar==WATER)
125 return(m_statusp(m,SWIMMING) ||
126 m_statusp(m,ONLYSWIM) ||
127 m_statusp(m,INTANGIBLE) ||
128 m_statusp(m,FLYING));
129 else if (Level->site[x][y].locchar == CLOSED_DOOR) {
130 if (m->movef==M_MOVE_SMART) {
131 mprint("You hear a door creak open.");
132 Level->site[x][y].locchar = OPEN_DOOR;
133 lset(x, y, CHANGED);
134 return(TRUE);
135 }
136 else if (random_range(m->dmg) > random_range(100)) {
137 mprint("You hear a door shattering.");
138 Level->site[x][y].locchar = RUBBLE;
139 lset(x, y, CHANGED);
140 return(TRUE);
141 }
142 else return(m_statusp(m,INTANGIBLE));
143 }
144 else if (Level->site[x][y].locchar == LAVA)
145 return((m_immunityp(m,FLAME) &&
146 m_statusp(m,SWIMMING)) ||
147 m_statusp(m,INTANGIBLE) ||
148 m_statusp(m,FLYING));
149 else if (Level->site[x][y].locchar == FIRE)
150 return(m_statusp(m,INTANGIBLE) ||
151 m_immunityp(m,FLAME));
152 else if ((Level->site[x][y].locchar == TRAP) ||
153 (Level->site[x][y].locchar == HEDGE) ||
154 (Level->site[x][y].locchar == ABYSS))
155 return((m->movef == M_MOVE_CONFUSED) ||
156 m_statusp(m,INTANGIBLE) ||
157 m_statusp(m,FLYING));
158 else return(TRUE);
159 }
160
161
162
163 /* can you see through a spot? */
view_unblocked(x,y)164 int view_unblocked(x,y)
165 int x,y;
166 {
167 if (! inbounds(x,y)) return(FALSE);
168 else if ((Level->site[x][y].locchar == WALL) ||
169 (Level->site[x][y].locchar == STATUE) ||
170 (Level->site[x][y].locchar == HEDGE) ||
171 (Level->site[x][y].locchar == FIRE) ||
172 (Level->site[x][y].locchar == CLOSED_DOOR) ||
173 loc_statusp(x,y,SECRET))
174 return(FALSE);
175 else
176 return(TRUE);
177 }
178
179
180 #ifndef MSDOS_SUPPORTED_ANTIQUE
181 /* 8 moves in Dirs */
initdirs()182 void initdirs()
183 {
184 Dirs[0][0] = 1;
185 Dirs[0][1] = 1;
186 Dirs[0][2] = -1;
187 Dirs[0][3] = -1;
188 Dirs[0][4] = 1;
189 Dirs[0][5] = -1;
190 Dirs[0][6] = 0;
191 Dirs[0][7] = 0;
192 Dirs[0][8] = 0;
193 Dirs[1][0] = 1;
194 Dirs[1][1] = -1;
195 Dirs[1][2] = 1;
196 Dirs[1][3] = -1;
197 Dirs[1][4] = 0;
198 Dirs[1][5] = 0;
199 Dirs[1][6] = 1;
200 Dirs[1][7] = -1;
201 Dirs[1][8] = 0;
202 }
203 #endif
204
205
206
207
208
209 /* do_los moves pyx along a lineofsight from x1 to x2 */
210 /* x1 and x2 are pointers because as a side effect they are changed */
211 /* to the final location of the pyx */
do_los(pyx,x1,y1,x2,y2)212 void do_los(pyx,x1,y1,x2,y2)
213 Symbol pyx;
214 int *x1,*y1,x2,y2;
215 {
216 int dx,dy,ox,oy;
217 int major, minor;
218 int error, delta, step;
219 int blocked;
220
221 if (x2 - *x1 < 0) dx = 5;
222 else if (x2 - *x1 > 0) dx = 4;
223 else dx = -1;
224 if (y2 - *y1 < 0) dy = 7;
225 else if (y2 - *y1 > 0) dy = 6;
226 else dy = -1;
227 if (abs(x2 - *x1) > abs(y2 - *y1)) {
228 major = dx;
229 minor = dy;
230 step = abs(x2 - *x1);
231 delta = 2*abs(y2 - *y1);
232 }
233 else {
234 major = dy;
235 minor = dx;
236 step = abs(y2 - *y1);
237 delta = 2*abs(x2 - *x1);
238 }
239 if (major == -1) /* x1,y2 already == x2,y2 */
240 return;
241 error = 0;
242 do {
243 ox = *x1; oy = *y1;
244 *x1 += Dirs[0][major];
245 *y1 += Dirs[1][major];
246 error += delta;
247 if (error > step) { /* don't need to check that minor >= 0 */
248 *x1 += Dirs[0][minor];
249 *y1 += Dirs[1][minor];
250 error -= 2*step;
251 }
252 blocked = !unblocked(*x1,*y1);
253 if (error < 0 && (*x1 != x2 || *y1 != y2) && blocked) {
254 *x1 -= Dirs[0][minor];
255 *y1 -= Dirs[1][minor];
256 error += 2*step;
257 blocked = !unblocked(*x1,*y1);
258 }
259 Level->site[*x1][*y1].showchar = pyx;
260 plotchar(pyx,*x1,*y1);
261 plotspot(ox,oy,TRUE);
262 usleep(50000);
263 } while ((*x1 != x2 || *y1 != y2) && !blocked);
264 plotspot(*x1,*y1,TRUE);
265 levelrefresh();
266 }
267
268
269 /* This is the same as do_los, except we stop before hitting nonliving
270 obstructions */
do_object_los(pyx,x1,y1,x2,y2)271 void do_object_los(pyx,x1,y1,x2,y2)
272 Symbol pyx;
273 int *x1,*y1,x2,y2;
274 {
275 int dx,dy,ox,oy;
276 int major, minor;
277 int error, delta, step;
278 int blocked;
279
280 if (x2 - *x1 < 0) dx = 5;
281 else if (x2 - *x1 > 0) dx = 4;
282 else dx = -1;
283 if (y2 - *y1 < 0) dy = 7;
284 else if (y2 - *y1 > 0) dy = 6;
285 else dy = -1;
286 if (abs(x2 - *x1) > abs(y2 - *y1)) {
287 major = dx;
288 minor = dy;
289 step = abs(x2 - *x1);
290 delta = 2*abs(y2 - *y1);
291 }
292 else {
293 major = dy;
294 minor = dx;
295 step = abs(y2 - *y1);
296 delta = 2*abs(x2 - *x1);
297 }
298 if (major == -1) /* x1,y2 already == x2,y2 */
299 return;
300 error = 0;
301 do {
302 ox = *x1; oy = *y1;
303 *x1 += Dirs[0][major];
304 *y1 += Dirs[1][major];
305 error += delta;
306 if (error > step) { /* don't need to check that minor >= 0 */
307 *x1 += Dirs[0][minor];
308 *y1 += Dirs[1][minor];
309 error -= 2*step;
310 }
311 blocked = !unblocked(*x1,*y1);
312 if (error < 0 && (*x1 != x2 || *y1 != y2) && blocked) {
313 *x1 -= Dirs[0][minor];
314 *y1 -= Dirs[1][minor];
315 error += 2*step;
316 blocked = !unblocked(*x1,*y1);
317 }
318 plotspot(ox,oy,TRUE);
319 if (unblocked(*x1,*y1)) {
320 plotchar(pyx,*x1,*y1);
321 Level->site[*x1][*y1].showchar = pyx;
322 usleep(50000);
323 }
324 } while ((*x1 != x2 || *y1 != y2) && !blocked);
325 if (Level->site[*x1][*y1].creature == NULL && blocked) {
326 *x1 = ox;
327 *y1 = oy;
328 }
329 plotspot(*x1,*y1,TRUE);
330 levelrefresh();
331 }
332
333
334 /* los_p checks to see whether there is an unblocked los from x1,y1 to x2,y2 */
los_p(x1,y1,x2,y2)335 int los_p(x1,y1,x2,y2)
336 int x1,y1,x2,y2;
337 {
338 int dx,dy;
339 int major, minor;
340 int error, delta, step;
341 int blocked;
342
343 if (x2-x1 < 0) dx = 5;
344 else if (x2-x1 > 0) dx = 4;
345 else dx = -1;
346 if (y2-y1 < 0) dy = 7;
347 else if (y2-y1 > 0) dy = 6;
348 else dy = -1;
349 if (abs(x2-x1) > abs(y2-y1)) {
350 major = dx;
351 minor = dy;
352 step = abs(x2 - x1);
353 delta = 2*abs(y2 - y1);
354 }
355 else {
356 major = dy;
357 minor = dx;
358 step = abs(y2 - y1);
359 delta = 2*abs(x2 - x1);
360 }
361 if (major == -1) /* x1,y2 already == x2,y2 */
362 return TRUE;
363 error = 0;
364 do {
365 x1 += Dirs[0][major];
366 y1 += Dirs[1][major];
367 error += delta;
368 if (error > step) { /* don't need to check that minor >= 0 */
369 x1 += Dirs[0][minor];
370 y1 += Dirs[1][minor];
371 error -= 2*step;
372 }
373 blocked = !unblocked(x1,y1);
374 if (error < 0 && (x1 != x2 || y1 != y2) && blocked) {
375 x1 -= Dirs[0][minor];
376 y1 -= Dirs[1][minor];
377 error += 2*step;
378 blocked = !unblocked(x1,y1);
379 }
380 } while ((x1 != x2 || y1 != y2) && !blocked);
381 return((x1==x2) && (y1==y2));
382 }
383
384
385 /* view_los_p sees through monsters */
view_los_p(x1,y1,x2,y2)386 int view_los_p(x1,y1,x2,y2)
387 int x1,y1,x2,y2;
388 {
389 int dx,dy;
390 int major, minor;
391 int error, delta, step;
392 int blocked;
393
394 if (x2-x1 < 0) dx = 5;
395 else if (x2-x1 > 0) dx = 4;
396 else dx = -1;
397 if (y2-y1 < 0) dy = 7;
398 else if (y2-y1 > 0) dy = 6;
399 else dy = -1;
400 if (abs(x2-x1) > abs(y2-y1)) {
401 major = dx;
402 minor = dy;
403 step = abs(x2 - x1);
404 delta = 2*abs(y2 - y1);
405 }
406 else {
407 major = dy;
408 minor = dx;
409 step = abs(y2 - y1);
410 delta = 2*abs(x2 - x1);
411 }
412 if (major == -1) /* x1,y2 already == x2,y2 */
413 return TRUE;
414 error = 0;
415 do {
416 x1 += Dirs[0][major];
417 y1 += Dirs[1][major];
418 error += delta;
419 if (error > step) {
420 x1 += Dirs[0][minor];
421 y1 += Dirs[1][minor];
422 error -= 2*step;
423 }
424 blocked = !view_unblocked(x1,y1);
425 if (error < 0 && (x1 != x2 || y1 != y2) && blocked) {
426 x1 -= Dirs[0][minor];
427 y1 -= Dirs[1][minor];
428 error += 2*step;
429 blocked = !view_unblocked(x1,y1);
430 }
431 } while ((x1 != x2 || y1 != y2) && !blocked);
432 return((x1==x2) && (y1==y2));
433 }
434
435 #ifndef MSDOS_SUPPORTED_ANTIQUE
436 /* returns the command direction from the index into Dirs */
inversedir(dirindex)437 char inversedir(dirindex)
438 int dirindex;
439 {
440 switch (dirindex) {
441 case 0:return('n');
442 case 1:return('u');
443 case 2:return('b');
444 case 3:return('y');
445 case 4:return('l');
446 case 5:return('h');
447 case 6:return('j');
448 case 7:return('k');
449 default:return('\0');
450 }
451 }
452 #endif
453
454
calc_points()455 long calc_points()
456 {
457 int i;
458 long points=0;
459
460 if (gamestatusp(SPOKE_TO_DRUID)) points += 50;
461 if (gamestatusp(COMPLETED_CAVES)) points += 100;
462 if (gamestatusp(COMPLETED_SEWERS)) points += 200;
463 if (gamestatusp(COMPLETED_CASTLE)) points += 300;
464 if (gamestatusp(COMPLETED_ASTRAL)) points += 400;
465 if (gamestatusp(COMPLETED_VOLCANO)) points += 500;
466 if (gamestatusp(KILLED_DRAGONLORD)) points += 100;
467 if (gamestatusp(KILLED_EATER)) points += 100;
468 if (gamestatusp(KILLED_LAWBRINGER)) points += 100;
469
470 points += Player.xp/50;
471
472 points += Player.cash/500;
473
474 for (i=0;i<MAXITEMS;i++)
475 if (Player.possessions[i] != NULL)
476 points += Player.possessions[i]->level*(Player.possessions[i]->known+1);
477
478 for (i=0;i<MAXPACK;i++)
479 if (Player.pack[i] != NULL)
480 points += Player.pack[i]->level*(Player.pack[i]->known+1);
481
482 for (i=0;i<NUMRANKS;i++) {
483 if (Player.rank[i] == 5) points += 500;
484 else points += 20*Player.rank[i];
485 }
486
487 if (Player.hp < 1)
488 points = (points / 2);
489
490 else if (Player.rank[ADEPT])
491 points *= 10;
492
493 return(points);
494 }
495
496
497 /* returns the 24 hour clock hour */
hour()498 int hour()
499 {
500 return((int)(((Time+720) / 60) % 24));
501 }
502
503 /* returns 0, 10, 20, 30, 40, or 50 */
showminute()504 int showminute()
505 {
506 return((int)((Time % 60)/10)*10);
507 }
508
509 /* returns the 12 hour clock hour */
showhour()510 int showhour()
511 {
512 int showtime;
513 if ((hour() == 0) || (hour() == 12)) showtime = 12;
514 else showtime = (hour() % 12);
515 return(showtime);
516 }
517
518 /* nighttime is defined from 9 PM to 6AM */
nighttime()519 int nighttime()
520 {
521 return((hour() > 20) || (hour() < 7));
522 }
523
getarticle(str)524 char *getarticle(str)
525 char *str;
526 {
527 if ((str[0]=='a') || (str[0]=='A') ||
528 (str[0]=='e') || (str[0]=='E') ||
529 (str[0]=='i') || (str[0]=='I') ||
530 (str[0]=='o') || (str[0]=='O') ||
531 (str[0]=='u') || (str[0]=='U') ||
532 (((str[0]=='h') || (str[0]=='H')) &&
533 ((str[1]=='i') || (str[1]=='e'))))
534 return("an ");
535 else return("a ");
536 }
537
day()538 int day()
539 {
540 return ((Date % 30) + 1);
541 }
542
ordinal(number)543 char *ordinal(number)
544 int number;
545 {
546 if ((number == 11) || (number == 12) || (number == 13)) return("th");
547 else switch(number % 10) {
548 case 1:return("st");
549 case 2:return("nd");
550 case 3:return("rd");
551 default: return("th");
552 }
553 }
554
month()555 char *month()
556 {
557 switch((Date % 360) / 30) {
558 case 0: return("Freeze");
559 case 1: return("Ice");
560 case 2: return("Mud");
561 case 3: return("Storm");
562 case 4: return("Breeze");
563 case 5: return("Light");
564 case 6: return("Flame");
565 case 7: return("Broil");
566 case 8: return("Cool");
567 case 9: return("Haunt");
568 case 10: return("Chill");
569 case 11: return("Dark");
570 case 12: return("Twixt");
571 default: return("***Error***");
572 }
573 }
574
575
576 /* WDT: code for the following two functions contributed by Sheldon
577 * Simms. */
578 /* finds floor space on level with buildaux not equal to baux,
579 sets x,y there. There must *be* floor space somewhere on level.... */
spaceok(int i,int j,int baux)580 int spaceok( int i, int j, int baux )
581 {
582 return (( Level->site[ i ][ j ].locchar == FLOOR ) &&
583 ( Level->site[ i ][ j ].creature == NULL ) &&
584 ( !loc_statusp( i, j, SECRET )) &&
585 ( Level->site[ i ][ j ].buildaux != baux ));
586 }
587
findspace(int * x,int * y,int baux)588 void findspace( int *x, int *y, int baux )
589 {
590 int i, j, tog = TRUE, done = FALSE;
591
592 do {
593 i = random_range( WIDTH );
594 j = random_range( LENGTH );
595 if ( spaceok( i, j, baux ))
596 {
597 done = TRUE;
598 }
599 else
600 {
601 if ( tog )
602 {
603 tog = !tog;
604 while( 1 )
605 {
606 i++;
607 if ( i >= WIDTH )
608 break;
609 else if ( spaceok( i, j, baux ))
610 {
611 done = TRUE;
612 break;
613 }
614 }
615 }
616 else
617 {
618 tog = !tog;
619 while( 1 )
620 {
621 j++;
622 if ( j >= LENGTH )
623 break;
624 else if ( spaceok( i, j, baux ))
625 {
626 done = TRUE;
627 break;
628 }
629 }
630 }
631 }
632 } while ( !done );
633 *x = i;
634 *y = j;
635 }
636
637 /* is prefix a prefix of s? */
strprefix(prefix,s)638 int strprefix(prefix,s)
639 char *prefix,*s;
640 {
641 int i=0,matched=TRUE;
642 if (strlen(prefix) > strlen(s)) return(FALSE);
643 else {
644 while (matched && (i<strlen(prefix))) {
645 matched = (prefix[i] == s[i]);
646 i++;
647 }
648 return(matched);
649 }
650 }
651
confirmation()652 int confirmation()
653 {
654 switch(random_range(4)) {
655 case 0: mprint("Are you sure? [yn] "); break;
656 case 1: mprint("Certain about that? [yn] "); break;
657 case 2: mprint("Do you really mean it? [yn] "); break;
658 case 3: mprint("Confirm that, would you? [yn] "); break;
659 }
660 return(ynq()=='y');
661 }
662
663
664 /* is character c a member of string s */
strmem(c,s)665 int strmem(c,s)
666 char c;
667 char *s;
668 {
669 int i,found=FALSE;
670 for(i=0;((i<strlen(s)) && (! found));i++)
671 found = (s[i] == c);
672 return(found);
673 }
674
calc_weight()675 void calc_weight()
676 {
677 int i,weight=0;
678
679 for(i=1;i<MAXITEMS;i++)
680 if (Player.possessions[i] != NULL)
681 weight += Player.possessions[i]->weight *
682 Player.possessions[i]->number;
683 if ((Player.possessions[O_WEAPON_HAND] != NULL) &&
684 (Player.possessions[O_READY_HAND] == Player.possessions[O_WEAPON_HAND]))
685 weight -= Player.possessions[O_READY_HAND]->weight *
686 Player.possessions[O_READY_HAND]->number;
687 for(i=0;i<MAXPACK;i++)
688 if (Player.pack[i] != NULL)
689 weight += Player.pack[i]->weight *
690 Player.pack[i]->number;
691 Player.itemweight = weight;
692 dataprint();
693 }
694
695 /* returns true if its ok to get rid of a level */
ok_to_free(level)696 int ok_to_free(level)
697 plv level;
698 {
699 if (level == NULL) return(FALSE);
700 else return((level->environment != E_CITY) &&
701 (level->environment != E_VILLAGE) &&
702 (level->environment != Current_Dungeon));
703 }
704
free_objlist(pobjlist)705 void free_objlist(pobjlist)
706 pol pobjlist;
707 {
708 pol tmp;
709
710 while (pobjlist) {
711 free((tmp = pobjlist)->thing);
712 pobjlist = pobjlist->next;
713 free(tmp);
714 }
715 }
716
free_mons_and_objs(mlist)717 void free_mons_and_objs(mlist)
718 pml mlist;
719 {
720 pml tmp;
721
722 while (mlist) {
723 free_objlist((tmp = mlist)->m->possessions);
724 free(tmp->m);
725 mlist = mlist->next;
726 free(tmp);
727 }
728 }
729
730 /* Free up monsters and items on a level*/
free_level(level)731 void free_level(level)
732 plv level;
733 {
734 int i,j;
735
736 free_mons_and_objs(level->mlist);
737 for (i = 0; i < MAXWIDTH; i++)
738 for (j = 0; j < MAXLENGTH; j++)
739 if (level->site[i][j].things) {
740 free_objlist(level->site[i][j].things);
741 level->site[i][j].things = NULL;
742 }
743 #ifndef SAVE_LEVELS
744 free(level);
745 #endif
746 }
747
748 /* malloc function that checks its return value - if NULL, tries to free */
749 /* some memory... */
checkmalloc(unsigned int bytes)750 void *checkmalloc(unsigned int bytes)
751 {
752 void *ptr = malloc(bytes);
753 struct level *curr, **prev, **oldest;
754
755 if (ptr)
756 return ptr;
757 for (curr = Dungeon, oldest = prev = &Dungeon; curr; curr = curr->next) {
758 if ((*oldest)->last_visited > curr->last_visited)
759 oldest = prev;
760 prev = &(curr->next);
761 }
762 if (*oldest && *oldest != Level) {
763 curr = *oldest;
764 *oldest = (*oldest)->next;
765 free_level(curr);
766 ptr = malloc(bytes);
767 }
768 if (ptr)
769 return ptr;
770 else {
771 print1("Out of memory! Saving and quitting.");
772 morewait();
773 save(FALSE, TRUE);
774 endgraf();
775 exit(0);
776 }
777 }
778
779 /* alloc just enough string space for str, strcpy, and return pointer */
salloc(str)780 char *salloc(str)
781 char *str;
782 {
783 char *s=checkmalloc((unsigned)(strlen(str)+1));
784 strcpy(s,str);
785 return(s);
786 }
787
788 #ifdef MSDOS
789 /* ****Moved here from another file**** */
790 /* reads a string from a file. If it is a line with more than 80 char's,
791 then remainder of line to \n is consumed */
filescanstring(fd,fstr)792 void filescanstring(fd,fstr)
793 FILE *fd;
794 char *fstr;
795 {
796 int i= -1;
797 int byte='x';
798 while ((i<80) && (byte != '\n') && (byte != EOF)) {
799 i++;
800 byte=fgetc(fd);
801 fstr[i] = byte;
802 }
803 if (byte != '\n')
804 while((byte!='\n') && (byte != EOF))
805 byte=fgetc(fd);
806 fstr[i]=0;
807 }
808 #endif
809
810 #ifdef MSDOS_SUPPORTED_ANTIQUE
811 /* ****Moved here from another file**** */
812 /* returns a "level of difficulty" based on current environment
813 and depth in dungeon. Is somewhat arbitrary. value between 1 and 10.
814 May not actually represent real difficulty, but instead level
815 of items, monsters encountered. */
difficulty()816 int difficulty()
817 {
818 int depth = 1;
819 if (Level != NULL) depth = Level->depth;
820 switch(Current_Environment) {
821 case E_COUNTRYSIDE: return(7);
822 case E_CITY: return(3);
823 case E_VILLAGE: return(1);
824 case E_TACTICAL_MAP: return(7);
825 case E_SEWERS: return(depth/6)+3;
826 case E_CASTLE: return(depth/4)+4;
827 case E_CAVES: return(depth/3)+1;
828 case E_VOLCANO: return(depth/4)+5;
829 case E_ASTRAL: return(8);
830 case E_ARENA: return(5);
831 case E_HOVEL: return(3);
832 case E_MANSION: return(7);
833 case E_HOUSE: return(5);
834 case E_DLAIR: return(9);
835 case E_ABYSS: return(10);
836 case E_STARPEAK: return(9);
837 case E_CIRCLE: return(8);
838 case E_MAGIC_ISLE: return(8);
839 case E_TEMPLE: return(8);
840 default: return(3);
841 }
842 }
843 #endif
844
cryptkey(fname)845 char cryptkey(fname)
846 char *fname;
847 {
848 int pos, key = 0;
849
850 for (pos = 0; fname[pos]; pos++)
851 key += 3*(fname[pos] - ' ');
852 return (key&0xff);
853 }
854
855 int game_uid;
856 int user_uid;
857
init_perms()858 void init_perms()
859 {
860 #if (defined(BSD) || defined(SYSV)) && !defined(__DJGPP__)
861 user_uid = getuid();
862 game_uid = geteuid();
863 #endif
864 }
865
866 /*
867 #ifdef BSD
868 void setreuid(int, int);
869 #endif
870 */
871
change_to_user_perms()872 void change_to_user_perms()
873 {
874 #if (defined( BSD ) || defined( SYSV )) && !defined(__EMX__) && !defined(__DJGPP__)
875 #ifdef BSD
876 setreuid(game_uid, user_uid);
877 #else /* SYSV */
878 seteuid(user_uid);
879 #endif /* BSD */
880 #endif /* BSD || SYSV */
881 }
882
change_to_game_perms()883 void change_to_game_perms()
884 {
885 #if (defined( BSD ) || defined( SYSV )) && !defined(__EMX__) && !defined(__DJGPP__)
886 #ifdef BSD
887 setreuid(user_uid, game_uid);
888 #else /* SYSV */
889 seteuid(game_uid);
890 #endif /* BSD */
891 #endif /* BSD || SYSV */
892 }
893
894 #ifdef NO_USLEEP
usleep(int usecs)895 void usleep(int usecs)
896 {
897 fd_set null;
898 struct timeval timeout;
899
900 FD_ZERO(&null);
901 timeout.tv_usec = usecs;
902 timeout.tv_sec = 0;
903 select(0, &null, &null, &null, &timeout);
904 }
905 #endif
906