home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume12 / torus / part01 / main.c < prev    next >
C/C++ Source or Header  |  1991-05-15  |  9KB  |  521 lines

  1. /*
  2.  *    R O B O T S   ( T O R U S )
  3.  *
  4.  *    The game of robots.
  5.  *    History:
  6.  *    Original Implementation
  7.  *        Allan Black <allan@cs.strath.ac.uk>
  8.  *    Updated for fast robots, moveable heaps, ROBOTOPTS
  9.  *    antimatter, v7/sys5/4.2 portability etc.
  10.  *        Graeme Lunt <gal@cs.nott.ac.uk>
  11.  *        Julian Onions <jpo@cs.nott.ac.uk>
  12.  *    Topological modifications:
  13.  *        Tad White <tadpole@math.ucla.edu>
  14.  *
  15.  * Provided free as long as you don't make money from it!
  16.  */
  17.  
  18. # include "robots.h"
  19.  
  20. char    whoami[MAXSTR];
  21. char    my_user_name[MAXSTR];
  22. char    cmd_ch;
  23.  
  24. bool    dead = FALSE;
  25. bool    last_stand;
  26. bool    show_highscore = TRUE;
  27. bool    adjacent, first_move, bad_move, waiting;
  28. bool    moveable_heaps = TRUE;
  29. bool    hsew = TRUE;
  30. bool    vsew = TRUE;
  31. bool    toral = TRUE;
  32. bool    hrev = FALSE;
  33. bool    vrev = FALSE;
  34. bool    wimpy = FALSE;
  35. bool    all_moves = FALSE;
  36. bool    continuous = FALSE;
  37.  
  38. int    my_x, my_y;
  39. int    new_x, new_y;
  40. int    level = 0;
  41. int    free_teleports = 0;
  42. int    old_free;
  43. int    free_per_level = 1;
  44. int    count;
  45. int    dots = 0;
  46. int    robot_value = MIN_VALUE;
  47. int    max_robots = MIN_ROBOTS;
  48. int    nrobots_alive;
  49. int    scrap_heaps = 1;  /* to allow for first level */
  50.  
  51. long    score = 0;
  52. long    seed;
  53.  
  54. # ifdef TIOCSLTC
  55. struct ltchars    ltc;
  56. char    dsusp;
  57. # endif TIOCSLTC
  58.  
  59. # ifdef TURBOC
  60. int
  61. #endif
  62. r_interrupt();
  63.  
  64. # define    TERM_UNINIT    00
  65. # define    TERM_CURSES    01
  66. # define    TERM_LTC    02
  67.  
  68. int    term_state = TERM_UNINIT;    /* cuts out some race conditions */
  69. char    *getenv();
  70. # ifndef TURBOC /* rfs */
  71. struct    passwd    *getpwuid();
  72. char    _obuf[BUFSIZ];
  73. # endif
  74.  
  75. main(argc,argv)
  76.      int argc;
  77.      char *argv[];
  78. {
  79. # ifndef TURBOC /* rfs */
  80.   register struct passwd *pass;
  81. # endif
  82.  
  83.   register char *x;
  84.   int i;
  85.  
  86. # ifndef TURBOC /* rfs */
  87.   setbuf(stdout, _obuf);
  88. # endif
  89.   if(argc > 1)
  90.     for(i=1;i<argc;i++) {
  91.       if(argv[i][0] == '-')
  92.     switch(argv[i][1]) {
  93.     case 's':
  94.       show_highscore = TRUE;
  95.       scoring(FALSE);
  96.       exit(0);
  97.       break;
  98.     case 'h':
  99.       hsew = FALSE;
  100.       /* hrev = TRUE; */
  101.       break;
  102.     case 'v':
  103.       vsew = FALSE;
  104.       /* vrev = TRUE; */
  105.       break;
  106.     case 'w':
  107.       wimpy = FALSE;
  108.       break;
  109.     case 'c':
  110.       continuous = FALSE;
  111.       break;
  112.     }
  113.       if(argv[i][0] == '+') {
  114.     switch(argv[i][1]) {
  115.     case 'h':
  116.       hsew = TRUE;
  117.       hrev = FALSE;
  118.       break;
  119.     case 'v':
  120.       vsew = TRUE;
  121.       vrev = FALSE;
  122.       break;
  123.     case 'w':
  124.       wimpy = TRUE;
  125.       break;
  126.     case 'c':
  127.       continuous = TRUE;
  128.       break;
  129.     }
  130.       }
  131.       if (argv[i][0] == '0') {
  132.     switch(argv[i][1]) {
  133.     case 'h':
  134.       hsew = FALSE;
  135.       hrev = FALSE;
  136.       break;
  137.     case 'v':
  138.       vsew = FALSE;
  139.       vrev = FALSE;
  140.       break;
  141.     }
  142.       }
  143.     }
  144. # ifdef TURBOC /* rfs */
  145.   if (strcmp(x=getenv("USERNAME"),"")==0) x="ANON";
  146. # else
  147.   if((pass = getpwuid(getuid())) == 0) {
  148.     x = "ANON";
  149.   } else {
  150.     x = pass->pw_name;
  151.   }
  152. # endif
  153.   (void) strcpy(my_user_name, x);
  154.   (void) strcpy(whoami,x);
  155.   if((x = getenv(ROBOTOPTS)) != NULL && *x != '\0')
  156.     get_robot_opts(x);
  157.   seed = time((time_t *)0)+getuid();
  158. # ifndef TURBOC /* rfs */
  159.   (void) signal(SIGQUIT,r_interrupt);
  160.   (void) signal(SIGINT,r_interrupt);
  161. # endif
  162.   if( initscr() == ERR) {
  163.     fprintf(stderr, "Curses won't initialize - seek a guru\n");
  164.     quit();
  165.   }
  166.   term_state |= TERM_CURSES;
  167.   crmode();
  168.   noecho();
  169. # ifdef TIOCSLTC
  170.   (void) ioctl(1,TIOCGLTC,<c);
  171.   dsusp = ltc.t_dsuspc;
  172.   ltc.t_dsuspc = ltc.t_suspc;
  173.   (void) ioctl(1,TIOCSLTC,<c);
  174.   term_state |= TERM_LTC;
  175. # endif TIOCSLTC
  176. restart:  
  177.   dead = FALSE;
  178.   free_teleports = 0;
  179.   level = 0;
  180.   free_per_level = 1;
  181.   scrap_heaps = 1;
  182.   score = 0;
  183.   robot_value = MIN_VALUE;
  184.   max_robots = MIN_ROBOTS;
  185.   for(;;) {
  186.     count = 0;
  187.     adjacent = FALSE;
  188.     waiting = FALSE;
  189.     last_stand = FALSE;
  190.     old_free = -1;
  191.     if(rnd(free_per_level) < free_teleports) {
  192.       free_per_level++;
  193.       if(free_per_level > MAX_FREE) free_per_level = MAX_FREE;
  194.     }
  195.     free_teleports += free_per_level;
  196.     leaveok(stdscr,FALSE);
  197.     draw_screen();
  198.     put_robots();
  199.     do {
  200.       my_x = rndx();
  201.       my_y = rndy();
  202.       move(my_y,my_x);
  203.     } while(inch() != ' ');
  204.     addch(ME);
  205.     if (dots) put_dots();
  206.     for(;;) {
  207.       scorer();
  208.       if(nrobots_alive == 0) break;
  209.       command();
  210.       for(i=1;i<=FASTEST;i++)
  211.     robots(i);
  212.       if(dead) { munch(); goto restart; }
  213.     }
  214.     msg("%d robots are now %d scrap heaps",max_robots, scrap_heaps);
  215.     leaveok(stdscr,FALSE);
  216.     move(my_y,my_x);
  217.     refresh();
  218.     (void) readchar();
  219.     level++;
  220.   }
  221. }
  222.  
  223. draw_screen()
  224. {
  225.     register int x, y;
  226.     clear();
  227.     for(y = 1; y < LINES-2; y++) {
  228.         mvaddch(y,0,VERT);
  229.         mvaddch(y,COLS-1,VERT);
  230.     }
  231.     for(x = 0; x < COLS; x++) {
  232.         mvaddch(0,x,HORIZ);
  233.         mvaddch(LINES-2,x,HORIZ);
  234.     }
  235. }
  236.  
  237. readchar()
  238. {
  239. # ifdef TURBOC /* rfs */
  240.     return getch();
  241. # else
  242.     static char buf[1];
  243.     extern int errno;
  244.  
  245.     while(read(0,buf,1) != 1)
  246.         if( errno != EINTR) {
  247.             scoring(TRUE);
  248.             quit();
  249.         }
  250.     return(buf[0]);
  251. # endif
  252. }
  253.  
  254. put_dots()
  255. {
  256.     register int x, y;
  257.     for(x = my_x-dots; x <= my_x+dots; x++) {
  258.         for(y = my_y-dots; y <= my_y+dots; y++) {
  259.             tmove(y,x);
  260.             if(inch() == ' ') addch(DOT);
  261.         }
  262.     }
  263. }
  264.  
  265. erase_dots()
  266. {
  267.     register int x, y;
  268.     for(x = my_x-dots; x <= my_x+dots; x++) {
  269.         for(y = my_y-dots; y <= my_y+dots; y++) {
  270.             tmove(y,x);
  271.             if(inch() == DOT) addch(' ');
  272.         }
  273.     }
  274. }
  275.  
  276. xinc(dir)
  277.     char dir;
  278. {
  279.     switch(dir) {
  280.     case 'h':
  281.     case 'y':
  282.     case 'b':
  283.         return(-1);
  284.     case 'l':
  285.     case 'u':
  286.     case 'n':
  287.         return(1);
  288.     case 'j':
  289.     case 'k':
  290.     default:
  291.         return(0);
  292.     }
  293. }
  294.  
  295. yinc(dir)
  296.     char dir;
  297. {
  298.     switch(dir) {
  299.     case 'k':
  300.     case 'y':
  301.     case 'u':
  302.         return(-1);
  303.     case 'j':
  304.     case 'b':
  305.     case 'n':
  306.         return(1);
  307.     case 'h':
  308.     case 'l':
  309.     default:
  310.         return(0);
  311.     }
  312. }
  313.  
  314. int vbound(y,x)  /* for toral robots:  converts y to lie within boundary */
  315.      int y,x;
  316. {
  317.   register int t_y;
  318.   t_y = y;
  319.   if ( vsew /* ||vrev */ ) {
  320.     if (y >= LINES-2) t_y = y - (LINES-3);
  321.     if (y <= 0) t_y = y + (LINES-3);
  322.   }
  323.   /* if ( (hrev) && ((x >= COLS-1) || (x <= 0)) ) t_y = LINES - 2 - t_y; */
  324.   return(t_y);
  325. }
  326.  
  327. int hbound(y,x)
  328.      int y,x;
  329. {
  330.   register int t_x;
  331.   t_x = x;
  332.   if (hsew /*||hrev*/ ) {
  333.     if (x >= COLS-1) t_x = x - (COLS-2);
  334.     if (x <= 0) t_x = x + (COLS-2);
  335.   }
  336.   /* if ( (vrev) && ((y >= LINES-2) || (y <= 0)) ) t_x = COLS - 1 - t_x; */
  337.   return(t_x);
  338. }
  339.  
  340. tmove(y,x)  /* move with wrap-around, if edge identifications made. */
  341. int y,x;
  342. {
  343.   move(vbound(y,x),hbound(y,x));
  344. }
  345.  
  346. munch()
  347. {
  348.     scorer();
  349.     msg("MUNCH! You're robot food");
  350.     leaveok(stdscr,FALSE);
  351.     mvaddch(my_y,my_x,MUNCH);
  352.     move(my_y,my_x);
  353.     refresh();
  354.     (void) readchar();
  355.     scoring(TRUE);
  356.     if (!continuous) quit();
  357. }
  358.  
  359. quit()
  360. {
  361.     if( term_state & TERM_CURSES ) {
  362.         move(LINES-1,0);
  363.         refresh();
  364.         endwin();
  365.         term_state &= ~ TERM_CURSES;
  366.     }
  367.     putchar('\n');
  368. # ifdef TIOCSLTC
  369.     if( term_state & TERM_LTC ) {
  370.         ltc.t_dsuspc = dsusp;
  371.         (void) ioctl(1,TIOCSLTC,<c);
  372.         term_state &= ~ TERM_LTC;
  373.     }
  374. # endif TIOCSLTC
  375.     (void) signal(SIGINT, SIG_DFL);
  376.     exit(0);
  377. }
  378.  
  379. rndx()
  380. {
  381.     return(rnd(COLS-2)+1);
  382. }
  383.  
  384. rndy()
  385. {
  386.     return(rnd(LINES-3)+1);
  387. }
  388.  
  389. rnd(mod)
  390.     int mod;
  391. {
  392.     if(mod <= 0) return(0);
  393.     return((((seed = seed*11109L+13849L) >> 16) & 0xffffL) % mod);
  394. }
  395.  
  396. /* VARARGS 1 */
  397. msg(message,a1, a2, a3, a4, a5, a6, a7)
  398.     char *message;
  399.     unsigned int a1, a2, a3, a4, a5, a6, a7;
  400. {
  401.     static char msgbuf[1000];
  402.  
  403.     (void) sprintf(msgbuf, message, a1, a2, a3, a4, a5, a6, a7);
  404.     mvaddstr(LINES-1,MSGPOS,msgbuf);
  405.     clrtoeol();
  406.     refresh();
  407. }
  408.  
  409. # ifdef TURBOC /* rfs */
  410. int
  411. # endif
  412. r_interrupt()
  413. {
  414.     scoring(FALSE);
  415.     quit();
  416. }
  417.  
  418. /*
  419.  * file locking routines - much nicer under BSD ...
  420.  */
  421.  
  422. # ifdef TURBOC /* rfs */
  423. lk_open(file,mode) /* don't need to lock score files on IBM PCs */
  424. char *file;
  425. int mode;
  426. {
  427.     int    fd;
  428.     if ((fd = open(file, mode, S_IREAD|S_IWRITE)) < 0)  return -1;
  429.     return fd;
  430. }
  431.  
  432. lk_close(fd, fname)
  433. int    fd;
  434. char    *fname;
  435. {
  436.     return close(fd);
  437. }
  438.  
  439. # endif
  440. # if defined(BSD42)
  441. lk_open(file, mode)    /* lock a file using the flock sys call */
  442. char    *file;
  443. int    mode;
  444. {
  445.     int    fd;
  446.  
  447.     if( (fd = open(file, mode)) < 0)
  448.         return -1;
  449.     if( flock(fd, LOCK_EX) < 0)
  450.     {
  451.         (void) close(fd);
  452.         return -1;
  453.     }
  454.     return fd;
  455. }
  456.  
  457. lk_close( fd, file)
  458. int    fd;
  459. char    *file;
  460. {
  461. # ifdef lint
  462.     file = file;    /* now will you shut up lint???? */
  463. # endif
  464.     return close(fd);
  465. }
  466. # else
  467.  
  468. # define    LOCKTIME    (60)    /* 1 minute */
  469. # include    <sys/stat.h>
  470.  
  471. lk_open(file, mode)    /* lock a file by crude means */
  472. char    *file;
  473. int    mode;
  474. {
  475.     char    tfile[128], lfile[128];
  476.     struct    stat stbuf;
  477.     time_t    now;
  478.     int    fd;
  479.  
  480.     (void) sprintf(tfile, "%s.t", file);    /* temp file */
  481.     (void) sprintf(lfile, "%s.l", file);    /* lock file */
  482.  
  483.     if( close(creat(tfile, 0)) < 0)    /* make temp file */
  484.         return -1;
  485.     while( link(tfile, lfile) == -1)    /* now attempt the lock file */
  486.     {
  487.         if( stat(lfile, &stbuf) < 0)
  488.             continue;    /* uhh? -- try again */
  489.         time(&now);
  490.         /* OK - is this file old? */
  491.         if( stbuf.st_mtime + LOCKTIME < now)
  492.             unlink(lfile);    /* ok its old enough - junk it */
  493.         else    sleep(1);    /* snooze ... */
  494.     }
  495.     unlink(tfile);    /* tmp files done its job */
  496.     if((fd = open(file, mode)) < 0) {
  497.         unlink(lfile);
  498.         return -1;
  499.     }
  500.     return fd;
  501. }
  502.  
  503. lk_close(fd, fname)
  504. int    fd;
  505. char    *fname;
  506. {
  507.     char    lfile[128];
  508.  
  509.     (void) sprintf(lfile, "%s.l", fname);    /* recreate the lock file name */
  510.     if( unlink(lfile) == -1) /* blow it away */
  511.         perror(lfile);
  512.     return close(fd);
  513. }
  514. # endif
  515.  
  516. # ifdef TURBOC /* rfs */
  517. int getuid () {
  518.   return 0;
  519.   }
  520. # endif
  521.