home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / XAP / XGAMES / XHEXTRIS.TAR / xio.c < prev   
Encoding:
C/C++ Source or Header  |  1990-04-27  |  13.3 KB  |  493 lines

  1. /*
  2.  * xhextris Copyright 1990 David Markley, dm3e@+andrew.cmu.edu, dam@cs.cmu.edu
  3.  *
  4.  * Permission to use, copy, modify, and distribute, this software and its
  5.  * documentation for any purpose is hereby granted without fee, provided that
  6.  * the above copyright notice appear in all copies and that both that
  7.  * copyright notice and this permission notice appear in supporting
  8.  * documentation, and that the name of the copyright holders be used in
  9.  * advertising or publicity pertaining to distribution of the software with
  10.  * specific, written prior permission, and that no fee is charged for further
  11.  * distribution of this software, or any modifications thereof.  The copyright
  12.  * holder make no representations about the suitability of this software for
  13.  * any purpose.  It is provided "as is" without express or implied warranty.
  14.  *
  15.  * THE COPYRIGHT HOLDER DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  16.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  17.  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  18.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  19.  * DATA, PROFITS, QPA OR GPA, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 
  20.  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  21.  * PERFORMANCE OF THIS SOFTWARE.
  22.  */
  23.  
  24. /* This file contains the X I/O handling routines for hextris.
  25.  */
  26.  
  27. #include <stdio.h>
  28. #include <strings.h>
  29. #include <X11/Xlib.h>
  30. #include <X11/Xutil.h>
  31. #include <sys/types.h>
  32. #include <sys/dir.h>
  33. #include <sys/time.h>
  34. #include <pwd.h>
  35.  
  36. #ifdef LOG
  37. #include <system.h>
  38. #endif
  39.  
  40. #include "header.h"
  41.  
  42. /* Macros to make 4.2 BSD select compatible with 4.3 BSD select */
  43. #ifndef FD_SET
  44. #define fd_set int
  45. #define FD_SET(fd,fdset) (*(fdset) |= (1<<(fd)))
  46. #define FD_CLR(fd,fdset) (*(fdset) &= ~(1<<(fd)))
  47. #define FD_ISSET(fd, fdset) (*(fdset) & (1<<(fd)))
  48. #define FD_ZERO(fdset) (*(fdset) = 0)
  49. #endif
  50.  
  51. /* I dislike global variables, but this made it much simpler */
  52. Display *display;
  53. int screen;
  54. Window win;
  55. GC gc, hexgc;
  56. XFontStruct *font_info, *hexfont_info;
  57. Pixmap black, white;
  58. #ifdef AFS
  59. extern int PlayerUID;
  60. #endif
  61.  
  62. /* This is the big, ugly main X procedure...
  63.  */
  64. void main(argc, argv)
  65. int argc;
  66. char **argv;
  67. {
  68.     char buffer[20];
  69.     int width, height, i, bufsize=20, inverse=0, pleasure=0, window_size = 0;
  70.     XSizeHints size_hints;
  71.     XEvent report;
  72.     KeySym key;
  73.     XComposeStatus compose;
  74.     struct timeval tp, ltp;
  75.     struct timezone tzp;
  76.     double intvl = 0, newintvl;
  77.     fd_set fdst;
  78.     struct passwd  *pwent;
  79. /* The following variables are required by hextris */
  80.     int score = 0, rows = 0, game_over = 1, game_view = 1, oldscore = 0;
  81.     high_score_t high_scores[MAXHIGHSCORES];
  82.     position_t grid[MAXROW][MAXCOLUMN];
  83.     piece_t npiece, piece;
  84.     char *name, *log_name;
  85.     
  86. #ifdef AFS
  87.     Authenticate();
  88.     bePlayer();
  89.     pwent = getpwuid(PlayerUID);
  90.     if (pwent == (struct passwd *) NULL) {
  91.       if ((log_name = (char *)getenv("USER")) == NULL)
  92.     log_name = "anon";
  93.     } else
  94.       log_name = pwent->pw_name;
  95. #else
  96.     pwent = getpwuid(getuid());
  97.     if (pwent == (struct passwd *) NULL) {
  98.       if ((log_name = (char *)getenv("USER")) == NULL)
  99.     log_name = "anon";
  100.     } else
  101.       log_name = pwent->pw_name;
  102. #endif
  103.     for (i = 1; i < argc; i++) {
  104.     if (! strcmp(argv[i],"-rv")) {
  105.         inverse = 1;
  106.         continue;
  107.     }
  108.     if (! strcmp(argv[i],"-p"))
  109.       pleasure = 1;
  110.     }
  111.     if ((name = (char *)getenv("XHEXNAME")) == NULL)
  112.       name = log_name;
  113.     printf("\nWelcome, %s...\n",name);
  114.     gettimeofday(&tp, &tzp);
  115.     srandom((int)(tp.tv_usec));
  116. #ifdef LOG
  117.     strcpy(log_message,log_name);
  118.     strcat(log_message,"\t");
  119.     strcat(log_message,SYS_NAME);
  120.     strcat(log_message,"\t1.00");
  121. #endif
  122.     set_up_display(inverse);
  123.     set_up_window(&width,&height,&size_hints,argv,argc);
  124.     XSync(display,True);
  125.     while(1) {
  126.     if (pleasure) {
  127.         score = 0;
  128.         intvl = 400000;
  129.     } else
  130.       intvl = 100000+(200000-((rows > 40) ? 20 : (rows/2))*10000);
  131.     oldscore = score;
  132.     if (! game_over)
  133.       if ((game_over = update_drop(grid,&npiece,&piece,&score,&rows))) {
  134.           read_high_scores(high_scores);
  135.           if (is_high_score(name, log_name, score, rows, high_scores))
  136.         write_high_scores(high_scores,log_name);
  137.           read_high_scores(high_scores);
  138.       }
  139.     if (score != oldscore) {
  140.         XSync(display,True);
  141.         intvl = 400000;
  142.     }
  143.     gettimeofday(<p, NULL);
  144.     while (1) {
  145.         gettimeofday(&tp, NULL);
  146.         newintvl = intvl - (((tp.tv_sec - ltp.tv_sec)*1000000)+
  147.           (tp.tv_usec - ltp.tv_usec));
  148.         if (newintvl <= 0)
  149.           break;
  150.         tp.tv_sec = 0;
  151.         tp.tv_usec = newintvl;
  152.         FD_ZERO(&fdst);
  153.         FD_SET(ConnectionNumber(display),&fdst);
  154.         select(ConnectionNumber(display)+1,&fdst,0,0,&tp);
  155.         while (XPending(display)) {
  156.         XNextEvent(display, &report);
  157.         switch (report.type) {
  158.         case Expose:
  159.             while (XCheckTypedEvent(display, Expose, &report));
  160.             if (window_size)
  161.               TooSmall();
  162.             redraw_game(grid,&npiece,&piece,&score,&rows,game_view,
  163.                 high_scores);
  164.             break;
  165.         case ConfigureNotify:
  166.             while (XCheckTypedEvent(display,ConfigureNotify,&report));
  167.             width = report.xconfigure.width;
  168.             height = report.xconfigure.height;
  169.             if ((width < size_hints.min_width) ||
  170.             (height < size_hints.min_height))
  171.               window_size = 1;
  172.             else
  173.               window_size = 0;
  174.             redraw_game(grid,&npiece,&piece,&score,&rows,game_view,
  175.                 high_scores);
  176.             break;
  177.         case EnterNotify:
  178.             break;
  179.         case LeaveNotify:
  180.             break;
  181.         case ButtonPress:
  182.             XBell(display,50);
  183.             break;
  184.         case KeyPress:
  185.             XLookupString(&report, buffer, bufsize, &key, &compose);
  186.             oldscore = score;
  187.             do_choice(buffer[0],grid,&npiece,&piece,&score,&rows,
  188.                   &game_over, &game_view, high_scores);
  189.             if ((score != oldscore) || (! score)) {
  190.             XSync(display,True);
  191.             intvl = 400000;
  192.             gettimeofday(<p, NULL);
  193.             }
  194.             break;
  195.         default:
  196.             break;
  197.         }
  198.         }
  199.     }
  200.     }
  201. }
  202.  
  203. /* This sets up the basic connections to the X server, the fonts, and
  204.  * which colors are to be foreground and background.
  205.  */
  206. set_up_display(inverse)
  207. int inverse;
  208. {
  209.     Pixmap temp;
  210.  
  211.     if ( (display = XOpenDisplay(NULL)) == NULL) {
  212.         fprintf(stderr, "xhextris: cannot connect to X server.\n");
  213.         exit(-1);
  214.     }
  215.     screen = DefaultScreen(display);
  216.     black = BlackPixel(display, screen);
  217.     white = WhitePixel(display, screen);
  218.     if (inverse) {
  219.     temp = black;
  220.     black = white;
  221.     white = temp;
  222.     }
  223.     set_font_path(HEXFONTDIR);
  224.     set_font_path(FONTDIR);
  225. }
  226.  
  227. /* This sets up the font path to contain the directories that have the
  228.  * fonts this program needs.
  229.  */
  230. set_font_path(fontdir)
  231. char *fontdir;
  232. {
  233.     int i, font_length;
  234.     char **font_path = XGetFontPath(display, &font_length);
  235.  
  236.     for (i = 0; (i < font_length) && strcmp(font_path[i],fontdir); i++);
  237.  
  238.     if (i >= font_length) {
  239.     char **new_font_path;
  240.  
  241.     if (new_font_path = (char **) malloc((font_length+1)*sizeof(char *))) {
  242.         for(i = 0; i < font_length; i++)
  243.           new_font_path[i] = font_path[i];
  244.         new_font_path[i] = fontdir;
  245.         XSetFontPath(display, new_font_path, font_length + 1);
  246.         free(new_font_path);
  247.     }
  248.     }
  249.     if (font_path)
  250.       XFreeFontPath(font_path);
  251. }
  252.  
  253. /* This sets up the window position, size, fonts, and gcs.
  254.  */
  255. set_up_window(width,height,size_hints,argv,argc)
  256. int *width, *height;
  257. XSizeHints *size_hints;
  258. char *argv[];
  259. int argc;
  260. {
  261.     *width = MAXCOLUMN*40;
  262.     *height = (MAXROW+4)*26;
  263.     win = XCreateSimpleWindow(display,RootWindow(display, screen),50,50,
  264.                   *width, *height, 4, black, white);
  265.     size_hints->flags = PPosition | PSize | PMinSize;
  266.     size_hints->x = 50;
  267.     size_hints->y = 50;
  268.     size_hints->width = *width;
  269.     size_hints->height = *height;
  270.     size_hints->min_width = 300;
  271.     size_hints->min_height = 700;
  272.     XSetStandardProperties(display, win, WINDOWNAME, ICONNAME, NULL, argv,
  273.                argc, size_hints);
  274.     XSelectInput(display, win, ExposureMask | KeyPressMask | ButtonPressMask |
  275.          StructureNotifyMask | EnterWindowMask | LeaveWindowMask);
  276.     load_font(&font_info, FONTNAME);
  277.     get_GC(win, &gc, font_info);
  278.     load_font(&hexfont_info, HEXFONTNAME);
  279.     get_GC(win, &hexgc, hexfont_info);
  280.     XMapWindow(display, win);
  281.     XFlush(display);
  282. }
  283.  
  284. /* This sets up a gc
  285.  */
  286. get_GC(win, tgc, tfont_info)
  287. Window win;
  288. GC *tgc;
  289. XFontStruct *tfont_info;
  290. {
  291.     unsigned long valuemask = 0;
  292.     XGCValues values;
  293.     unsigned int line_width = 2;
  294.     int line_style = LineSolid;
  295.     int cap_style = CapRound;
  296.     int join_style = JoinRound;
  297.     int dash_offset = 0;
  298.     static char dash_list[] = { 12, 24 };
  299.     int list_length = 2;
  300.  
  301.     *tgc = XCreateGC(display, win, valuemask, &values);
  302.     XSetFont(display, *tgc, tfont_info->fid);
  303.     XSetForeground(display, *tgc, black);
  304.     XSetLineAttributes(display, *tgc, line_width, line_style, cap_style,
  305.            join_style);
  306.     XSetDashes(display, *tgc, dash_offset, dash_list, list_length);
  307. }
  308.  
  309. /* This loads a font
  310.  */
  311. load_font(tfont_info, font_name)
  312. XFontStruct **tfont_info;
  313. char *font_name;
  314. {
  315.     if ((*tfont_info = XLoadQueryFont(display, font_name)) == NULL) {
  316.     (void)fprintf(stderr, "xhextris: Cannot open %s font.\n",font_name);
  317.     exit(-1);
  318.     }
  319. }
  320.  
  321. /* This yells if the window is too small.
  322.  */
  323. TooSmall()
  324. {
  325.     char *string1 = "Too Small";
  326.     int y_offset, x_offset;
  327.  
  328.     y_offset = font_info->max_bounds.ascent + 2;
  329.     x_offset = 2;
  330.     XDrawString(display, win, gc, x_offset, y_offset, string1,
  331.         strlen(string1));
  332. }
  333.  
  334. /* This is required by hextris!
  335.  *
  336.  * This clears the window.
  337.  */
  338. clear_display()
  339. {
  340.     XClearWindow(display,win);
  341. }
  342.  
  343. /* This is required by hextris!
  344.  *
  345.  * This displays the current score and rows completed.
  346.  */
  347. display_scores(score,rows)
  348. int *score, *rows;
  349. {
  350.     int y_offset, x_offset;
  351.     char scores[40];
  352.  
  353.     XSetFillStyle(display, gc, FillSolid);
  354.     sprintf(scores,"Score: %6d", *score);
  355.     y_offset = 250;
  356.     x_offset = (MAXCOLUMN + 5) * 20;
  357.     XClearArea(display,win,x_offset,y_offset-20,MAXCOLUMN*20, 50, False);
  358.     XDrawString(display, win, gc, x_offset, y_offset, scores,strlen(scores));
  359.     sprintf(scores,"Rows: %3d", *rows);
  360.     y_offset += 20;
  361.     XDrawString(display, win, gc, x_offset, y_offset, scores,strlen(scores));
  362.     XFlush(display);
  363. }
  364.  
  365. /* This is required by hextris!
  366.  *
  367.  * This displays the help information.
  368.  */
  369. display_help()
  370. {
  371.     int y_offset, x_offset, i;
  372.     static char *message[] = { "The keys to press are:",
  373.                  "J,j,4 - move left.",
  374.                  "L,l,6 - move right.",
  375.                  "K,k,5 - rotate ccw.",
  376.                  "I,i,8 - rotate cw.",
  377.                  "space,0 - drop.",
  378.                  "N,n - new game.",
  379.                  "P,p - pause game.",
  380.                  "U,u - unpause game.",
  381.                  "R,r - redisplay game.",
  382.                  "H,h - show high scores.",
  383.                  "G,g - show game.",
  384.                  "Q,q - quit game.",
  385.                  " ",
  386.                  "--------------------",
  387.                  "Created By:",
  388.                  "  David Markley",
  389.                  "Font By:",
  390.                  "  Jon Slenk" };
  391.  
  392.  
  393.     XSetFillStyle(display, gc, FillSolid);
  394.     y_offset = 315;
  395.     x_offset = (MAXCOLUMN + 4) * 20;
  396.     for (i = 0; i < 19; i++)
  397.     XDrawString(display, win, gc, x_offset, y_offset+(i*17), message[i],
  398.             strlen(message[i]));
  399.     XFlush(display);
  400. }
  401.  
  402. /* This is required by hextris!
  403.  *
  404.  * This displays the high score list.
  405.  */
  406. display_high_scores(high_scores)
  407. high_score_t high_scores[MAXHIGHSCORES];
  408. {
  409.     int y_offset, i;
  410.     static int x_offset[5] = {5,30,150,200,300};
  411.     static char *header[] = {"#","Name","UID","Score","Rows"};
  412.     char message[40];
  413.  
  414.     XClearWindow(display,win);
  415.     XSetFillStyle(display, gc, FillSolid);
  416.     y_offset = 40;
  417.     for (i = 0; i < 5; i++)
  418.       XDrawString(display, win, gc, x_offset[i], y_offset,
  419.           header[i],strlen(header[i]));
  420.     y_offset = 60;
  421.     for (i = 0; i < ((MAXHIGHSCORES > 40) ? 40 : MAXHIGHSCORES); i++) {
  422.     itoa(i+1,message);
  423.     XDrawString(display, win, gc, x_offset[0], y_offset+(i*17),
  424.             message,strlen(message));
  425.     XDrawString(display, win, gc, x_offset[1], y_offset+(i*17),
  426.             high_scores[i].name,strlen(high_scores[i].name));
  427.     XDrawString(display, win, gc, x_offset[2], y_offset+(i*17),
  428.             high_scores[i].userid,strlen(high_scores[i].userid));
  429.     itoa(high_scores[i].score,message);
  430.     XDrawString(display, win, gc, x_offset[3], y_offset+(i*17),
  431.             message,strlen(message));
  432.     itoa(high_scores[i].rows,message);
  433.     XDrawString(display, win, gc, x_offset[4], y_offset+(i*17),
  434.             message,strlen(message));
  435.     }
  436.     XFlush(display);
  437. }
  438.  
  439. /* This is required by hextris!
  440.  *
  441.  * This displays the next piece to be dropped.
  442.  */
  443. show_next_piece(npiece)
  444. piece_t *npiece;
  445. {
  446.     piece_t tpiece;
  447.  
  448.     tpiece.type = npiece->type;
  449.     tpiece.rotation = npiece->rotation;
  450.     tpiece.row = 4;
  451.     tpiece.column = MAXCOLUMN+6;
  452.     XClearArea(display,win,(MAXCOLUMN+3)*20,0,200,230, False);
  453.     init_piece(&tpiece);
  454.     XFlush(display);
  455. }
  456.  
  457. /* This is required by hextris!
  458.  *
  459.  * This draws one hex at the specified row and column specified.
  460.  */
  461. draw_hex(row,column,fill,type)
  462. int row,column,fill,type;
  463. {
  464.     int y_offset, x_offset;
  465.     char hex[2];
  466.  
  467.     x_offset = 20 + column * 20;
  468.     y_offset = 20 + row * 26 + (column & 1) * 13;
  469.     hex[0] = 'b' + type;
  470.     hex[1] = '\0';
  471.     if (fill) {
  472.     XSetForeground(display,hexgc,black);
  473.     } else {
  474.     XSetForeground(display,hexgc,white);
  475.     strcpy(hex,"a");
  476.     }
  477.     XDrawString(display, win, hexgc, x_offset, y_offset, hex, strlen(hex));
  478.     XFlush(display);
  479. }
  480.  
  481. /* This is required by hextris!
  482.  *
  483.  * This ends the game by closing everything down and exiting.
  484.  */
  485. end_game()
  486. {
  487.     XFreeGC (display, gc);
  488.     XFreeGC (display, hexgc);
  489.     XDestroyWindow (display, win);
  490.     XCloseDisplay (display);
  491.     exit(0);
  492. }
  493.