home *** CD-ROM | disk | FTP | other *** search
/ Assassins - Ultimate CD Games Collection 4 / Assassins 4 (1999)(Weird Science).iso / misc / omega / source / util.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-02  |  19.0 KB  |  870 lines

  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
  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? */
  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 */
  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 */
  33. int screenmod(y)
  34. int y;
  35. {
  36.   return(y-ScreenOffset);
  37. }
  38.  
  39.  
  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 */
  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 */
  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? */
  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 */
  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? */
  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
  181. /* 8 moves in Dirs */
  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 */
  212. void do_los(pyx,x1,y1,x2,y2)
  213. short 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 */
  271. void do_object_los(pyx,x1,y1,x2,y2)
  272. short 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 */
  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 */
  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
  436. /* returns the command direction from the index into Dirs */
  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.  
  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 */
  498. int hour()
  499. {
  500.   return((int)(((Time+720) / 60) % 24));
  501. }
  502.  
  503. /* returns 0, 10, 20, 30, 40, or 50 */
  504. int showminute()
  505. {
  506.   return((int)((Time % 60)/10)*10);
  507. }
  508.  
  509. /* returns the 12 hour clock hour */
  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 */
  519. int nighttime()
  520. {
  521.   return((hour() > 20) || (hour() < 7));
  522. }
  523.  
  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.  
  538. int day()
  539. {
  540.   return ((Date % 30) + 1);
  541. }
  542.  
  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.        
  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. /* finds floor space on level with buildaux not equal to baux, 
  577. sets x,y there. There must *be* floor space somewhere on level.... */
  578.  
  579. void findspace(x,y,baux)
  580. int *x,*y, baux;
  581. {
  582.   int i,j,k,l,done=FALSE;
  583.   i = k = random_range(WIDTH);
  584.   j = l = random_range(LENGTH);
  585.   do {
  586.     i++;
  587.     if (i >= WIDTH) {
  588.       i = 0;
  589.       j++;
  590.       if (j > LENGTH)
  591.     j = 0;
  592.       done = ((i == k) && (j == l));
  593.     }
  594.     done = done || 
  595.       ((Level->site[i][j].locchar == FLOOR) &&
  596.        (Level->site[i][j].creature == NULL) &&
  597.        (Level->site[i][j].buildaux != baux));
  598.   } while (! done);
  599.   *x = i;
  600.   *y = j;
  601. }
  602.  
  603. /* is prefix a prefix of s? */
  604. int strprefix(prefix,s)
  605. char *prefix,*s;
  606. {
  607.   int i=0,matched=TRUE;
  608.   if (strlen(prefix) > strlen(s)) return(FALSE);
  609.   else {
  610.     while (matched && (i<strlen(prefix))) {
  611.       matched = (prefix[i] == s[i]);
  612.       i++;
  613.     }
  614.     return(matched);
  615.   }
  616. }
  617.  
  618. int confirmation()
  619. {
  620.   switch(random_range(4)) {
  621.   case 0:  mprint("Are you sure? [yn] "); break;
  622.   case 1:  mprint("Certain about that? [yn] "); break;
  623.   case 2:  mprint("Do you really mean it? [yn] "); break;
  624.   case 3:  mprint("Confirm that, would you? [yn] "); break;
  625.   }
  626.   return(ynq()=='y');
  627. }
  628.  
  629.  
  630. /* is character c a member of string s */
  631. int strmem(c,s)
  632. char c;
  633. char *s;
  634. {
  635.   int i,found=FALSE;
  636.   for(i=0;((i<strlen(s)) && (! found));i++)
  637.     found = (s[i] == c);
  638.   return(found);
  639. }
  640.  
  641. void calc_weight()
  642. {
  643.   int i,weight=0;
  644.  
  645.   for(i=1;i<MAXITEMS;i++) 
  646.     if (Player.possessions[i] != NULL)
  647.       weight += Player.possessions[i]->weight *
  648.     Player.possessions[i]->number;
  649.   if ((Player.possessions[O_WEAPON_HAND] != NULL) &&
  650.       (Player.possessions[O_READY_HAND] == Player.possessions[O_WEAPON_HAND]))
  651.     weight -= Player.possessions[O_READY_HAND]->weight *
  652.       Player.possessions[O_READY_HAND]->number;
  653.   for(i=0;i<MAXPACK;i++) 
  654.     if (Player.pack[i] != NULL)
  655.       weight += Player.pack[i]->weight *
  656.     Player.pack[i]->number;
  657.   Player.itemweight = weight;
  658.   dataprint();
  659. }
  660.  
  661. /* returns true if its ok to get rid of a level */
  662. int ok_to_free(level)
  663. plv level;
  664. {
  665.   if (level == NULL) return(FALSE);
  666.   else return((level->environment != E_CITY) &&
  667.           (level->environment != E_VILLAGE) &&
  668.           (level->environment != Current_Dungeon));
  669. }
  670.  
  671. void free_objlist(pobjlist)
  672. pol pobjlist;
  673. {
  674.   pol tmp;
  675.  
  676.   while (pobjlist) {
  677.     free((tmp = pobjlist)->thing);
  678.     pobjlist = pobjlist->next;
  679.     free(tmp);
  680.   }
  681. }
  682.  
  683. void free_mons_and_objs(mlist)
  684. pml mlist;
  685. {
  686.   pml tmp;
  687.  
  688.   while (mlist) {
  689.     free_objlist((tmp = mlist)->m->possessions);
  690.     free(tmp->m);
  691.     mlist = mlist->next;
  692.     free(tmp);
  693.   }
  694. }
  695.  
  696. /* Free up monsters and items on a level*/
  697. void free_level(level)
  698. plv level;
  699. {
  700.   int i,j;
  701.  
  702.   free_mons_and_objs(level->mlist);
  703.   for (i = 0; i < MAXWIDTH; i++)
  704.     for (j = 0; j < MAXLENGTH; j++)
  705.       if (level->site[i][j].things) {
  706.     free_objlist(level->site[i][j].things);
  707.     level->site[i][j].things = NULL;
  708.       }
  709. #ifndef SAVE_LEVELS
  710.   free(level);
  711. #endif
  712. }
  713.  
  714. /* malloc function that checks its return value - if NULL, tries to free */
  715. /* some memory... */
  716. void *checkmalloc(unsigned int bytes)
  717. {
  718.   void *ptr = malloc(bytes);
  719.   struct level *curr, **prev, **oldest;
  720.  
  721.   if (ptr)
  722.     return ptr;
  723.   for (curr = Dungeon, oldest = prev = &Dungeon; curr; curr = curr->next) {
  724.     if ((*oldest)->last_visited > curr->last_visited)
  725.       oldest = prev;
  726.     prev = &(curr->next);
  727.   }
  728.   if (*oldest && *oldest != Level) {
  729.     curr = *oldest;
  730.     *oldest = (*oldest)->next;
  731.     free_level(curr);
  732.     ptr = malloc(bytes);
  733.   }
  734.   if (ptr)
  735.     return ptr;
  736.   else {
  737.     print1("Out of memory!  Saving and quitting.");
  738.     morewait();
  739.     save(FALSE, TRUE);
  740.     endgraf();
  741.     exit(0);
  742.   }
  743. }
  744.  
  745. /* alloc just enough string space for str, strcpy, and return pointer */
  746. char *salloc(str)
  747. char *str;
  748. {
  749.   char *s=checkmalloc((unsigned)(strlen(str)+1));
  750.   strcpy(s,str);
  751.   return(s);
  752. }
  753.  
  754. #ifdef MSDOS
  755. /* ****Moved here from another file**** */
  756. /* reads a string from a file. If it is a line with more than 80 char's,
  757.    then remainder of line to \n is consumed */
  758. void filescanstring(fd,fstr)
  759. FILE *fd;
  760. char *fstr;
  761. {
  762.   int i= -1;
  763.   int byte='x';
  764.   while ((i<80) && (byte != '\n') && (byte != EOF)) {
  765.     i++;
  766.     byte=fgetc(fd);
  767.     fstr[i] = byte;
  768.   } 
  769.   if (byte != '\n')
  770.     while((byte!='\n') && (byte != EOF))
  771.       byte=fgetc(fd);
  772.   fstr[i]=0;
  773. }
  774. #endif
  775.  
  776. #ifdef MSDOS
  777. /* ****Moved here from another file**** */
  778. /* returns a "level of difficulty" based on current environment
  779.    and depth in dungeon. Is somewhat arbitrary. value between 1 and 10.
  780.    May not actually represent real difficulty, but instead level
  781.    of items, monsters encountered.    */
  782. int difficulty()
  783. {
  784.   int depth = 1;
  785.   if (Level != NULL) depth = Level->depth;
  786.   switch(Current_Environment) {
  787.   case E_COUNTRYSIDE: return(7);
  788.   case E_CITY: return(3);
  789.   case E_VILLAGE: return(1);
  790.   case E_TACTICAL_MAP: return(7);
  791.   case E_SEWERS: return(depth/6)+3;
  792.   case E_CASTLE: return(depth/4)+4;
  793.   case E_CAVES: return(depth/3)+1;
  794.   case E_VOLCANO: return(depth/4)+5;
  795.   case E_ASTRAL: return(8);
  796.   case E_ARENA: return(5);
  797.   case E_HOVEL: return(3);
  798.   case E_MANSION: return(7);
  799.   case E_HOUSE: return(5);
  800.   case E_DLAIR: return(9);
  801.   case E_ABYSS: return(10);
  802.   case E_STARPEAK: return(9);
  803.   case E_CIRCLE: return(8);
  804.   case E_MAGIC_ISLE: return(8);
  805.   case E_TEMPLE: return(8);
  806.   default: return(3);
  807.   }
  808. }
  809. #endif
  810.  
  811. char cryptkey(fname)
  812. char *fname;
  813. {
  814.     int pos, key = 0;
  815.  
  816.     for (pos = 0; fname[pos]; pos++)
  817.     key += 3*(fname[pos] - ' ');
  818.     return (key&0xff);
  819. }
  820.  
  821. int game_uid;
  822. int user_uid;
  823.  
  824. void init_perms()
  825. {
  826. #if defined(BSD) || defined(SYSV)
  827.     user_uid = getuid();
  828.     game_uid = geteuid();
  829. #endif
  830. }
  831.  
  832. #ifdef BSD
  833. void setreuid(int, int);
  834. #endif
  835.  
  836. void change_to_user_perms()
  837. {
  838. #if (defined( BSD ) || defined( SYSV )) && !defined(__EMX__)
  839. #ifdef BSD
  840.     setreuid(game_uid, user_uid);
  841. #else /* SYSV */
  842.     seteuid(user_uid);
  843. #endif /* BSD */
  844. #endif /* BSD || SYSV */
  845. }
  846.  
  847. void change_to_game_perms()
  848. {
  849. #if (defined( BSD ) || defined( SYSV )) && !defined(__EMX__)
  850. #ifdef BSD
  851.     setreuid(user_uid, game_uid);
  852. #else /* SYSV */
  853.     seteuid(game_uid);
  854. #endif /* BSD */
  855. #endif /* BSD || SYSV */
  856. }
  857.  
  858. #ifdef NO_USLEEP
  859. void usleep(int usecs)
  860. {
  861.   fd_set null;
  862.   struct timeval timeout;
  863.  
  864.   FD_ZERO(&null);
  865.   timeout.tv_usec = usecs;
  866.   timeout.tv_sec = 0;
  867.   select(0, &null, &null, &null, &timeout);
  868. }
  869. #endif
  870.