home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume4 / xfish / part01 / xfish.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-07-19  |  13.2 KB  |  463 lines

  1. /*
  2.  * xfish.c  -  serves no useful purpose whatsoever
  3.  *
  4.  *  Author:    John H. Bradley, University of Pennsylvania
  5.  *                (bradley@cis.upenn.edu)
  6.  *                     October, 1987
  7.  *
  8.  *  For 4.3ish Unix systems running X V11
  9.  *
  10.  *  Modified by Jon Greenblatt (jonnyg@rover.umd.edu):
  11.  *
  12.  *    1: Improved event handeling.
  13.  *    2: Added the -root option (xerror occurs with window managers running).
  14.  *    3: Added the -rv reverse video option.
  15.  *
  16.  *  Modified by Lars Huttar (huttar@svax.cs.cornell.edu) 7/89:
  17.  *
  18.  *    1: Added the -nobell option.
  19.  *    2: Allowed for two fish to be hit by one shot.
  20.  *    3: Added the -bitmap option for using your own bitmaps.
  21.  *
  22.  */
  23.  
  24.  
  25. #include <stdio.h>
  26. #include <math.h>
  27. #include <strings.h>
  28. #include <signal.h>
  29. #include <X11/Xlib.h>
  30. #include <X11/Xutil.h>
  31. #include <X11/cursorfont.h>
  32. #include <sys/time.h>
  33. #include <sys/types.h>
  34. #include <sys/timeb.h>
  35.  
  36. #define DEFAULTDIR "/usr/public/sun3/games/lib/xfish_bitmaps/"
  37.  
  38. /* handy-dandy functions */
  39. #define max(a, b) ((a) > (b) ? (a) : (b))
  40. #define min(a, b) ((a) < (b) ? (a) : (b))
  41. #define abs(a) ((a) < 0 ? -(a) : (a))
  42.  
  43.  
  44. /* objects */
  45. Display   *disp;
  46. Window    theWindow;
  47. Pixmap    stipP, lfishP, rfishP, lfishmaskP, rfishmaskP;
  48. GC      gc,lgc,rgc;
  49. XGCValues xgcv;
  50. XSetWindowAttributes xswa;
  51. #define root_weave_width 16
  52. #define root_weave_height 16
  53. static char root_weave_bits[] = {
  54.    0x77, 0x77, 0xdd, 0xdd, 0xbb, 0xbb, 0xee, 0xee, 0x77, 0x77, 0xdd, 0xdd,
  55.    0xbb, 0xbb, 0xee, 0xee, 0x77, 0x77, 0xdd, 0xdd, 0xbb, 0xbb, 0xee, 0xee,
  56.    0x77, 0x77, 0xdd, 0xdd, 0xbb, 0xbb, 0xee, 0xee};
  57.  
  58. static char iroot_weave_bits[] = {
  59.    0x88, 0x88, 0x22, 0x22, 0x44, 0x44, 0x11, 0x11, 0x88, 0x88, 0x22, 0x22,
  60.    0x44, 0x44, 0x11, 0x11, 0x88, 0x88, 0x22, 0x22, 0x44, 0x44, 0x11, 0x11,
  61.    0x88, 0x88, 0x22, 0x22, 0x44, 0x44, 0x11, 0x11};
  62.  
  63. int fish_width=32, fish_height=16;
  64.  
  65. static char lfish_bits[] = {
  66.    0x00, 0xc0, 0x07, 0x00, 0x00, 0xb0, 0x06, 0x00, 0x80, 0x7f, 0x03, 0xe0,
  67.    0x60, 0x82, 0x03, 0xb0, 0x18, 0x00, 0x0c, 0x68, 0x64, 0x02, 0xf0, 0x37,
  68.    0x62, 0x00, 0x00, 0x28, 0x01, 0xaa, 0xaa, 0x36, 0x46, 0x00, 0x00, 0x28,
  69.    0x38, 0x03, 0xc0, 0x5f, 0xb0, 0x28, 0x30, 0xb0, 0xc0, 0x39, 0x0e, 0xe0,
  70.    0x00, 0xee, 0x01, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00,
  71.    0x00, 0xc0, 0x00, 0x00};
  72.  
  73. static char lfishmask_bits[] = {
  74.    0x00, 0xc0, 0x07, 0x00, 0x00, 0xf0, 0x07, 0x00, 0x80, 0xff, 0x03, 0xe0,
  75.    0xe0, 0xff, 0x03, 0xf0, 0xf8, 0xff, 0x0f, 0x78, 0xfc, 0xff, 0xff, 0x3f,
  76.    0xfe, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x3f,
  77.    0xf8, 0xff, 0xff, 0x7f, 0xf0, 0xff, 0x3f, 0xf0, 0xc0, 0xff, 0x0f, 0xe0,
  78.    0x00, 0xfe, 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00,
  79.    0x00, 0xc0, 0x00, 0x00};
  80.  
  81. static char rfish_bits[] = {
  82.    0x00, 0xe0, 0x03, 0x00, 0x00, 0x60, 0x0d, 0x00, 0x07, 0xc0, 0xfe, 0x01,
  83.    0x0d, 0xc0, 0x41, 0x06, 0x12, 0x30, 0x00, 0x18, 0xec, 0x0f, 0x40, 0x26,
  84.    0x14, 0x00, 0x00, 0x46, 0xac, 0xaa, 0x4a, 0x80, 0x14, 0x00, 0x00, 0x62,
  85.    0xfa, 0x03, 0xc0, 0x1c, 0x0d, 0x0c, 0x14, 0x0d, 0x07, 0x70, 0x9c, 0x03,
  86.    0x00, 0x80, 0x77, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x05, 0x00,
  87.    0x00, 0x00, 0x03, 0x00};
  88.  
  89. static char rfishmask_bits[] = {
  90.    0x00, 0xe0, 0x03, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x07, 0xc0, 0xff, 0x01,
  91.    0x0f, 0xc0, 0xff, 0x07, 0x1e, 0xf0, 0xff, 0x1f, 0xfc, 0xff, 0xff, 0x3f,
  92.    0xfc, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0x7f,
  93.    0xfe, 0xff, 0xff, 0x1f, 0x0f, 0xfc, 0xff, 0x0f, 0x07, 0xf0, 0xff, 0x03,
  94.    0x00, 0x80, 0x7f, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x07, 0x00,
  95.    0x00, 0x00, 0x03, 0x00};
  96.  
  97.  
  98. #define MAXFISH 100
  99. struct fishstr {  short x,y,dx,dy;  } fish[MAXFISH];
  100.  
  101. int NUMFISH=20, startnfish=20, shots=0, no_bell=0, use_root=0,
  102.     reverse_video=0, load_bitmap=0, screen;
  103. #define MAXFNLEN 51
  104. char filename[MAXFNLEN];
  105.  
  106.  
  107. long starttime;
  108.  
  109. /**************/
  110. main(argc, argv)
  111.     int   argc;
  112.     char *argv[];
  113. /**************/
  114. {
  115.     int i,dpcs,n,fcnt;
  116.     char *strind;
  117.  
  118.     char *fc, *bc;
  119.     char *display = NULL;
  120.  
  121.     char *def;
  122.     short bot,right;
  123.     XSizeHints xsh;
  124.  
  125.  
  126.     /*********************Options*********************/
  127.  
  128.     for (i = 1; i < argc; i++) {
  129.  
  130.         strind = index(argv[i], ':');       /* is it display address? */
  131.         if(strind != NULL) {
  132.             display = argv[i];
  133.             continue;
  134.             }
  135.  
  136.         if (n=atoi(argv[i])) {
  137.             if (n<1) n=1;
  138.             if (n>100) n=100;
  139.             NUMFISH=startnfish=n;
  140.             continue;
  141.             }
  142.  
  143.     if (*argv[i] == '-') {
  144.         if (strcmp(argv[i],"-root") == 0) {
  145.             use_root = 1;
  146.             continue;
  147.             }
  148.         if (strcmp(argv[i],"-rv") == 0) {
  149.             reverse_video = 1;
  150.             continue;
  151.             }
  152.         if (strncmp(argv[i],"-n",2) == 0) {  /* -nobell */
  153.             no_bell = 1;
  154.             continue;
  155.             }
  156.         if (strncmp(argv[i],"-b",2) == 0 && argc>i+1 /* -bitmap */
  157.             && sscanf(argv[++i], "%50s", filename)==1) {
  158.             load_bitmap = 1;
  159.             continue;
  160.             }
  161.         }
  162.  
  163.         Syntax(argv[0]);
  164.     }
  165.  
  166.  
  167.     /*****************************************************/
  168.  
  169.     /* Open up the display. */
  170.  
  171.     if ((disp=XOpenDisplay(display)) == NULL) {
  172.         fprintf(stderr, "%s: Can't open display ''\n",argv[0],display);
  173.         exit(1);
  174.         }
  175.  
  176.  
  177.     bot  =DisplayHeight(disp,DefaultScreen(disp));
  178.     right=DisplayWidth (disp,DefaultScreen(disp));
  179.  
  180.     xsh.flags = USSize | USPosition;
  181.     xsh.x = xsh.y = 0;
  182.     xsh.width = right;
  183.     xsh.height= bot;
  184.  
  185.     xswa.event_mask = ButtonPressMask;
  186.     if (use_root)
  187.     theWindow = RootWindow(disp,DefaultScreen(disp));
  188.     else
  189.     theWindow = XCreateWindow(disp, DefaultRootWindow(disp), 0,0,
  190.             right,bot,0,1,InputOutput,
  191.             DefaultVisual(disp,DefaultScreen(disp)),
  192.             CWEventMask,&xswa);
  193.  
  194.     
  195.     stipP=XCreateBitmapFromData(disp,theWindow,
  196.              iroot_weave_bits, root_weave_width, root_weave_height);
  197.  
  198.     if (load_bitmap) load_bitmaps();
  199.     else {
  200.     lfishP=XCreateBitmapFromData(disp,theWindow,
  201.                 lfish_bits,fish_width,fish_height);
  202.         rfishP=XCreateBitmapFromData(disp,theWindow,
  203.                 rfish_bits,fish_width,fish_height);
  204.         lfishmaskP=XCreateBitmapFromData(disp,theWindow,
  205.                 lfishmask_bits,fish_width,fish_height);
  206.         rfishmaskP=XCreateBitmapFromData(disp,theWindow,
  207.                 rfishmask_bits,fish_width,fish_height);
  208.     }
  209.  
  210.     if (!use_root) {
  211.     XSetWindowBackgroundPixmap(disp,theWindow,stipP);
  212.     XSetNormalHints(disp,theWindow,&xsh);
  213.     XSetStandardProperties(disp,theWindow,"fish","fish",None,0,0,&xsh);
  214.     XMapWindow(disp,theWindow);
  215.     XLowerWindow(disp, theWindow);
  216.     }
  217.  
  218.     /* init fish */
  219.     for (i=0; i<NUMFISH; i++) {
  220.         fish[i].x=rand()%(right-100)+50;
  221.         fish[i].y=rand()%(bot-100)+50;
  222.         fish[i].dx = (abs(rand()%10)+4);
  223.  
  224.         /* switch direction based on a higher-order bit.  the low-order bit
  225.            tended to be useless */
  226.         if (rand()&0x10) fish[i].dx = -fish[i].dx;  
  227.  
  228.         fish[i].dy=rand()%7-3;  if (fish[i].dy==0) fish[i].dy=1;
  229.         }
  230.  
  231.  
  232.     xgcv.tile=stipP;
  233.     xgcv.graphics_exposures = False;
  234.  
  235.     gc = XCreateGC(disp,theWindow,GCTile|GCGraphicsExposures,&xgcv);
  236.     lgc= XCreateGC(disp,theWindow,GCTile|GCGraphicsExposures,&xgcv);
  237.     rgc= XCreateGC(disp,theWindow,GCTile|GCGraphicsExposures,&xgcv);
  238.  
  239.     xgcv.fill_style= FillTiled;
  240.  
  241.     xgcv.clip_mask = None;
  242.  
  243.     screen = DefaultScreen(disp);
  244.     if (reverse_video) {
  245.     xgcv.foreground = WhitePixel(disp,screen);
  246.     xgcv.background = BlackPixel(disp,screen);
  247.     }
  248.     else {
  249.     xgcv.foreground = BlackPixel(disp,screen);
  250.     xgcv.background = WhitePixel(disp,screen);
  251.     }
  252.     xgcv.clip_mask = lfishmaskP;
  253.     XChangeGC(disp,lgc,GCClipMask|GCFillStyle|GCForeground|GCBackground,&xgcv);
  254.  
  255.     xgcv.clip_mask = rfishmaskP;
  256.     XChangeGC(disp,rgc,GCClipMask|GCFillStyle|GCForeground|GCBackground,&xgcv);
  257.  
  258.     starttime=time(0);
  259.  
  260.  
  261.     /**************** Main loop *****************/
  262.  
  263.     fcnt = 0;
  264.     if (use_root)
  265.     XSelectInput(disp,theWindow,ButtonPressMask);
  266.     while (1) {
  267.         XEvent event;
  268.         short  x,y,bnum;
  269.  
  270.       if (XCheckMaskEvent(disp,ButtonPressMask,&event)) {
  271.             if (event.type == ButtonPress) {
  272.                 XButtonEvent *butevent = (XButtonEvent *) &event;
  273.  
  274.                 bnum = butevent->button;
  275.                 if ((bnum == Button1) || (bnum == Button3)) {
  276.  
  277.                     if (bnum == Button3) shots++;
  278.  
  279.                     x = butevent->x;  y = butevent->y;
  280.                     for (i=0; i<NUMFISH; i++) {
  281.                         if ( (x >= fish[i].x) &&
  282.                              (x <= fish[i].x+fish_width) &&
  283.                              (y >= fish[i].y) &&
  284.                              (y <= fish[i].y+fish_height) )
  285.  
  286.                             if (i!=NUMFISH) {
  287.                             if (!no_bell) XBell(disp,25);
  288.                                 EraseFish(i);
  289.                                 if (bnum == Button1) {
  290.                                     fish[i].dx = -fish[i].dx;
  291.                                     fish[i].dy = -fish[i].dy;
  292.                                     DrawFish(i);
  293.                                     }
  294.                                 else {
  295.                                     if (NUMFISH==1) Stats();
  296.                                     bcopy(&fish[NUMFISH-1],&fish[i],
  297.                                       sizeof(struct fishstr));
  298.                                     NUMFISH--;
  299.                     }
  300.                 }
  301.                         }
  302.                     }
  303.                 }
  304.            }
  305.  
  306.         if (fcnt>=NUMFISH) fcnt=0;  /* since it's possible NUMFISH decreased */
  307.  
  308.         EraseFish(fcnt);
  309.  
  310.         fish[fcnt].x += fish[fcnt].dx;
  311.         fish[fcnt].y += fish[fcnt].dy;
  312.         if (fish[fcnt].x < -50 || fish[fcnt].x > (right+50))
  313.             fish[fcnt].dx = -fish[fcnt].dx;
  314.         if (fish[fcnt].y < 0 || fish[fcnt].y > (bot-16))
  315.             fish[fcnt].dy = -fish[fcnt].dy;
  316.  
  317.         DrawFish(fcnt);
  318.  
  319.         fcnt++;
  320.         if (fcnt>=NUMFISH) { fcnt=0; Timer(250000L); }
  321.  
  322.     }  /* end main loop */
  323. }
  324.  
  325. /*****************/
  326. EraseFish(i)
  327.       int i;
  328. {
  329.      XClearArea(disp,theWindow,fish[i].x,fish[i].y,fish_width,fish_height,0);
  330. }
  331.  
  332. /*****************/
  333. DrawFish(i)
  334.      int i;
  335. {
  336.     xgcv.clip_x_origin = fish[i].x;
  337.     xgcv.clip_y_origin = fish[i].y;
  338.  
  339.     if (fish[i].dx<0) {
  340.         XChangeGC(disp,lgc,GCClipXOrigin|GCClipYOrigin,&xgcv);
  341.         XCopyPlane(disp,lfishP,theWindow,lgc,0,0,fish_width,fish_height,
  342.                     fish[i].x,fish[i].y,1);
  343.         }
  344.     else {
  345.         XChangeGC(disp,rgc,GCClipXOrigin|GCClipYOrigin,&xgcv);
  346.         XCopyPlane(disp,rfishP,theWindow,rgc,0,0,fish_width,fish_height,
  347.                 fish[i].x,fish[i].y,1);
  348.         }
  349. }
  350.  
  351.  
  352. /***********************************/
  353. Syntax(call)
  354.  char *call;
  355. {
  356.     printf ("Usage: %s [-root -rv -nobell -bitmap bitmapfile]\n",call);
  357.     puts("\t\t[host:display] [number of fish]\n");
  358.     exit(1);
  359. }
  360.  
  361.  
  362. /***********************************/
  363. XFishError (identifier)
  364.        char *identifier;
  365. {
  366.     fprintf(stderr, "xfish: %s\n", identifier);
  367.     exit(1);
  368. }
  369.  
  370.  
  371.  
  372. /*******/
  373. Stats()
  374. {
  375.     long curtime;
  376.     float acc;
  377.  
  378.     curtime=time(0);
  379.     acc = (float) shots  / (float) startnfish;
  380.     if (!no_bell) puts("\007\007\007");
  381.     printf("You used %d shots to hit %d fish.  (in %d seconds)\n",
  382.             shots,startnfish,curtime-starttime);
  383.     printf("  For an accuracy ratio of: %f\n", acc);
  384.  
  385.     if (acc < 1.0) printf("Tex, you're a whiz!\n");
  386.     else if (acc < 1.5) printf("Nice shootin', Tex!\n");
  387.     XPending(disp);
  388.     exit(0);
  389. }
  390.  
  391.  
  392.  
  393. static int timerdone;
  394.  
  395. /*******/
  396. onalarm()
  397. /*******/
  398. {
  399.   timerdone=1;
  400. }
  401.  
  402. /*******/
  403. Timer(val,n)
  404.  long val;
  405. /*******/
  406. {
  407.     /* waits 'val' microseconds */
  408.  
  409.     struct itimerval it;
  410.  
  411.     bzero(&it, sizeof(it));
  412.     it.it_value.tv_usec = val;
  413.     timerdone=0;
  414.     signal(SIGALRM,onalarm);
  415.     setitimer(ITIMER_REAL, &it, (struct itimerval *)0);
  416.     while (1) {
  417.     sigblock(sigmask(SIGALRM)); /* note:  have to block, so that ALRM */
  418.         if (timerdone) break;    /* doesn't occur between 'if (timerdone)'*/
  419.         else sigpause(0);        /* and calling sigpause(0) */
  420.         }
  421.     sigblock(0);                    /* turn ALRM blocking off */
  422.     signal(SIGALRM,SIG_DFL);
  423. }
  424.  
  425. load_bitmaps()
  426. {   int dummy;
  427.     register int i, status;
  428.     char nufilename[MAXFNLEN+3], temp[MAXFNLEN+3];
  429.     static char extensions[4][4]={".li", ".lm", ".ri", ".rm"};
  430.     static Pixmap *pixmaps[4] = {&lfishP, &lfishmaskP, &rfishP, &rfishmaskP};
  431.  
  432.     for (i=0; i<4; i++) {
  433.     strcpy(nufilename, filename);
  434.     strcat(nufilename, extensions[i]); /* Add extension... */
  435.  
  436.     /* Load in the bitmap.  If unsuccessful... */
  437.     if ((status=XReadBitmapFile(disp, RootWindow(disp, DefaultScreen(disp)),
  438.         nufilename, &fish_width, &fish_height, pixmaps[i],
  439.         &dummy, &dummy)) != BitmapSuccess) {
  440.  
  441.         /* If the file couldn't be opened, try the default directory. */
  442.         if (status==BitmapOpenFailed && filename[0]!='/') {
  443.         strcpy(nufilename, DEFAULTDIR);
  444.         strcat(nufilename, filename);    /* Add default path to front */
  445.         strcpy(filename, nufilename);    /* of filename. */
  446.         strcat(nufilename, extensions[i]);
  447.         if ((status=XReadBitmapFile(disp,
  448.             RootWindow(disp, DefaultScreen(disp)),
  449.                     nufilename, &fish_width, &fish_height, pixmaps[i],
  450.                     &dummy, &dummy)) == BitmapSuccess) continue;
  451.             /* If the default dir worked, go load next bitmap. */
  452.         }
  453.  
  454.         /* Explain failure and quit. */
  455.         fputs("Invalid bitmap files.  There should be four,\n", stderr);
  456.         fputs("with extensions .li, .lm, .ri, and .rm.\n", stderr);
  457.         fputs("They are used for left and right images ", stderr);
  458.         fputs("and masks.\n", stderr);
  459.         exit(1);
  460.         }
  461.     }
  462. }
  463.