|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T m
Length: 16273 (0x3f91) Types: TextFile Names: »main.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987 └─⟦this⟧ »EUUGD18/X/Qix/main.c«
/* * The game of Qix for the Sun3 workstation running Sunview (probably 3.0)-- * X11 version updated by Dan Heller June 1988. * Appearance ONLY shamelessly stolen from the real video game wonderfully * and admirably written by individual(s) unknown at Taito Corp (I think). * * Copyright 1987 by Dan Heller * island!argv@sun.com * dheller@dheller@ucbcory.berkeley.edu * * Various polygon filling routines written by * -- Dan "Sky" Shultz * -- Don Hatch (ardent!hatch@ucbcad.berkeley.edu) * additional help (general debugging, recursive polyfill) * * Move mouse to go in direction. Left button does fast draw. Middle does * slow draw. Rogue/vi keys moves -- upper case draws. There is no slow * draw for keyboard input. */ #include "qix.h" #ifndef X11 /* the main icon for when the tool is closed */ short qix_icon_dat[] = { #include "qix.icon" }; DEFINE_ICON_FROM_IMAGE(qix_icon, qix_icon_dat); #endif /* X11 */ int (*old_repaint_func)(); int qix_mask = 0x7; int text_mask = TEXT_COLOR; int fast_draw_mask = FAST_DRAW_COLOR; int slow_draw_mask = SLOW_DRAW_COLOR; int border_mask = BORDER_COLOR; int all_mask = 0xff; #ifndef X11 redraw(args) { stop_timer(); (*old_repaint_func)(&args); start_timer(); } #endif /* X11 */ main(argc, argv) char *argv[]; { int catch(); char **newargv = argv; (void) signal(SIGBUS, catch); (void) signal(SIGSEGV, catch); (void) signal(SIGXCPU, catch); /* * specify debug levels "-d level" * a level of 2 prints polygon fill info. 4 disables spark-generation * but doesn't kill current sparks. debug level 1 does prints things... */ while (*++newargv) if (!strcmp(*newargv, "-s")) if (!*++newargv) puts("usage: qix [-s timeout] (in milliseconds)"), exit(1); else { if ((interval = atoi(*newargv)) < 15000 || interval > 60000) puts("delay must be between 15000 and 60000"), exit(1); } #ifdef DEBUG else if (!strcmp(*newargv, "-q")) no_qix_kill = 1; else if (!strcmp(*newargv, "-d")) debug = (*++newargv) ? atoi(*newargv) : 1; #endif DEBUG init_win(argc, argv); level = -2; /* two screens before player may split two qix */ moving = NO_MOVE; fast = 1, srandom(time(0)); srand(time(0)); init_qix(); draw_joystick(); play_mode = SHOW_SCORES; (void) score_board(TRUE, FALSE); time_left = 300; /* timeout before next demo mode switch */ (void) signal(SIGALRM, move_pen); start_timer(); window_main_loop(frame); /* main loop to read input */ exit(0); } clear_board() { register int x, y; clear_sparks(); area_closed = 0; pen_x = (BOARD_WIDTH-1)/2, pen_y = BOARD_HEIGHT-1; remove_msgs(1); pw_putattributes(draw_win, &all_mask); /* give left->right sweeping effect like the real game */ for (x = 0; x < BOARD_WIDTH_IN_PIXELS; x++) draw(x, 0, x, BOARD_HEIGHT_IN_PIXELS-1, PIX_CLR); pw_putattributes(draw_win, &border_mask); box(convert_x(0), convert_y(0), convert_x(BOARD_WIDTH-1), convert_y(BOARD_HEIGHT-1), PIX_SRC|PIX_COLOR(BORDER_COLOR)); update_score(); /* clear the interior of the board */ for (x = 1; x < BOARD_WIDTH-1; x++) for (y = 1; y < BOARD_HEIGHT-1; y++) board[x][y] = 0; for (x = 1; x < BOARD_WIDTH-1; x++) { board[x][0] = CL_LN_LF | CL_LN_RT | OLD_LINE | CL_PNT_TOP; board[x][BOARD_HEIGHT-1] = CL_LN_LF | CL_LN_RT | OLD_LINE | CL_PNT_BOT; } for (y = 1; y < BOARD_HEIGHT-1; y++) { board[0][y] = CL_LN_UP | CL_LN_DN | OLD_LINE | CL_PNT_LEFT; board[BOARD_WIDTH-1][y] = CL_LN_UP | CL_LN_DN | OLD_LINE | CL_PNT_RIGHT; } /* set the corners explicitly */ board[0][0] = (CL_LN_DN | CL_LN_RT | CL_PNT_TOP | CL_PNT_LEFT | OLD_LINE); board[0][BOARD_HEIGHT-1] = (CL_LN_UP | CL_LN_RT | CL_PNT_BOT | CL_PNT_LEFT | OLD_LINE); board[BOARD_WIDTH-1][0] = (CL_LN_DN | CL_LN_LF | CL_PNT_TOP | CL_PNT_RIGHT | OLD_LINE); board[BOARD_WIDTH-1][BOARD_HEIGHT-1] = (CL_LN_UP | CL_LN_LF | CL_PNT_BOT | CL_PNT_RIGHT | OLD_LINE); } /* * change the status of the player. If he's living, we add special * effects and do the cleanup from the last game. setup the right icons * and grab all the io on the screen. If he's dead, release the IO * from the screen and reset critical values. */ change_life(live_or_die) { register int x, n, m = (live_or_die == -1)? 40 : 300; stop_timer(); if (live_or_die == LIVE) { move_fuse(fuse = (struct region *)NULL); /* erase the last fuse */ if (region) { pen_x = region->x, pen_y = region->y; rm_cur_line(PIX_CLR); /* remove the current line drawn */ } if (lives <= 0) { if (play_mode == DEMO) lives = 1; else lives = MAX_LIVES; clear_board(); /* resets pen_x, pen_y (changes plane mask) */ level = -2, score = 0; } else { extern int qix1_x0[], qix1_x1[], qix1_y0[], qix1_y1[]; extern int qix2_x0[], qix2_x1[], qix2_y0[], qix2_y1[]; draw(convert_x(qix1_x0[0]), convert_y(qix1_y0[0]), convert_x(qix1_x1[0]), convert_y(qix1_y1[0]), PIX_CLR); if (level >= 0) draw(convert_x(qix2_x0[0]), convert_y(qix2_y0[0]), convert_x(qix2_x1[0]), convert_y(qix2_y1[0]), PIX_CLR); } Speed = 3 + min(level/3, 3); #ifdef DEBUG if (debug) printf("Speed = %d\n", Speed); #endif DEBUG clear_sparks(); update_score(); moving = STOP; drawing = FALSE; if (level > 0) { msg("All scores now\n%d times\ntheir original value.", level+1); Sleep(3); remove_msgs(0); } place_pen(); /* make pen appear */ } pw_putattributes(draw_win, &border_mask); for (x = 0; x < 2; x++) for (n = m; n >= 40 && n <= 300; n -= 5 * live_or_die) box(pen_coord_x(pen_x)-n/2, pen_coord_y(pen_y)-n/2, pen_coord_x(pen_x)+n/2, pen_coord_y(pen_y)+n/2, XOR | PIX_COLOR(BORDER_COLOR)); if (live_or_die == DIE) { is_alive = FALSE; if (--lives <= 0) { int do_scores = TRUE; reset_joystick_win(TRUE); msg("Game Over."); Sleep(2); /* if he got on the scoreboard, let him put his initials up */ if (play_mode == REAL_PLAY) do_scores = (score_board(FALSE, FALSE) == 0); if (play_mode == SHOW_SPIRAL) time_left = 50; /* demo mode comes after spiral death trap */ else { play_mode = SHOW_SCORES; if (do_scores) (void) score_board(TRUE, FALSE), time_left = 300; else time_left = 100; } moving = NO_MOVE; } else { moving = STOP; drawing = 0; } place_pen(); /* erase pen */ } else { is_alive = TRUE; reset_joystick_win(FALSE); } start_timer(); } update_score() { char buf[128]; int x; (void) sprintf(buf, "Score: %6d", score); pw_putattributes(joystick_win, &text_mask); pw_text(joystick_win, 500, 22, PIX_SRC|PIX_COLOR(TEXT_COLOR), big_font, buf); if (play_mode != REAL_PLAY) pw_text(draw_win, 105, 12, PIX_SRC|PIX_COLOR(TEXT_COLOR), small_font, "Click RIGHT mouse button or use <spacebar> to start new game."); else { pw_text(joystick_win, 500, 45, PIX_SRC|PIX_COLOR(TEXT_COLOR), big_font, "Lives: "); pw_putattributes(joystick_win, &border_mask); for (x = 0; x < MAX_LIVES; x++) pw_rop(joystick_win, 575+(x*20), 32, 16,16, ((x < lives-1)? PIX_SRC:PIX_CLR)|PIX_COLOR(BORDER_COLOR), pen_image, 0, 0); sprintf(buf, "Filled: %d%%",(int)((double)area_closed/TOTAL_AREA*100)); pw_putattributes(draw_win, &text_mask); pw_text(draw_win, 280, 12, PIX_SRC|PIX_COLOR(TEXT_COLOR), small_font, buf); pw_text(draw_win, 281, 12, SRC_OR_DST|PIX_COLOR(TEXT_COLOR), small_font, buf); } } #ifdef X11 XImage *save[15]; /* area under text to be redisplayed upon removal of text */ #else Pixrect *save[15]; /* area under text to be redisplayed upon removal of text */ #endif /* X11 */ int x_save[15], y_save, x_pos[15], y_pos[15]; static int msgs; /* the number of text lines displayed on the board */ /*VARARGS1*/ msg(fmt, args) char *fmt; { char buf[BUFSIZ], *index(); register char *p2, *p = buf; if (y_save == 0) y_save = l_height(big_font) + 1; (void) vsprintf(buf, fmt, &args); #ifdef DEBUG if (debug) puts(buf); #endif DEBUG pw_putattributes(draw_win, &text_mask); do { if (p2 = index(p, '\n')) *p2 = 0; x_save[msgs] = strlen(p) * l_width(big_font) + 1; x_pos[msgs] = BOARD_WIDTH_IN_PIXELS/2 - x_save[msgs]/2; y_pos[msgs] = TOP_BORDER + (1+msgs) * 2 * y_save; #ifdef X11 /* save_under */ save[msgs] = XGetImage(dpy, draw_win, x_pos[msgs], y_pos[msgs]-4, x_save[msgs], y_save+4, /* width/height */ AllPlanes, XYPixmap); #else save[msgs] = mem_create(x_save[msgs], y_save, 1); #endif /* X11 */ if (!(save[msgs])) { puts("whoops! Out of memory... no sense going on with this."); exit(1); } #ifndef X11 /* sunview save_under */ pr_rop(save[msgs], 0, 0, x_save[msgs], y_save, PIX_SRC, draw_win->pw_prretained, x_pos[msgs], y_pos[msgs]); #endif /* X11 */ pw_text(draw_win, x_pos[msgs], y_pos[msgs]+l_height(big_font)-5, PIX_SRC | PIX_COLOR(TEXT_COLOR), big_font, p); pw_text(draw_win, x_pos[msgs]+1, y_pos[msgs]+l_height(big_font)-5, SRC_OR_DST | PIX_COLOR(TEXT_COLOR), big_font, p); } while (++msgs < 15 && p2 && *(p = p2+1)); #ifdef X11 XFlush(dpy); #endif /* X11 */ } /* remove all messages from the board and put back the images underneith */ remove_msgs(clearing) { pw_putattributes(draw_win, &text_mask); while (msgs--) { #ifdef X11 if (!clearing) { XPutImage(dpy, draw_win, src_gc, save[msgs], 0, 0, x_pos[msgs], y_pos[msgs]-4, x_save[msgs], y_save+4); } XDestroyImage(save[msgs]); #else if (!clearing) pw_rop(draw_win, x_pos[msgs], y_pos[msgs], x_save[msgs], y_save, PIX_SRC | PIX_COLOR(TEXT_COLOR), save[msgs], 0, 0); pr_destroy(save[msgs]); #endif /* X11 */ } msgs = 0; #ifdef X11 XFlush(dpy); #endif /* X11 */ } catch(sig) { stop_timer(); if (sig == SIGXCPU) { msg("CPU timelimit exceeded. Go home and eat dinner."); Sleep(2); remove_msgs(0); return; } change_life(DIE); if (sig == SIGSEGV) fprintf(stderr, "Segmentation fault.\n"); else fprintf(stderr, "Bus Error\n"); abort(); } void flush_events() { #ifdef X11 XEvent event; XSync(dpy, 0); /* throw away all queued events */ while (XPending(dpy)) XNextEvent(dpy, &event); #else struct timeval dummy; Event event; int readfd = 1 << (int)window_get(Draw, WIN_FD); timerclear(&dummy); while (select(readfd+1, &readfd, 0, 0, &dummy) > 0) window_read_event(Draw, &event); #endif /* X11 */ } Sleep(n) { flush_events(); sleep(n); flush_events(); } #ifdef X11 init_win(argc, argv) char *argv[]; { XSetWindowAttributes attr; XSizeHints size; XGCValues gcvalues; unsigned long mask = GCFunction | GCGraphicsExposures | GCForeground | GCBackground; unsigned long foreground, background; int reverse = 0; #define screen DefaultScreen(dpy) interval = 50000; while (*++argv) /* X11 mode options only */ if (!strcmp(*argv, "-r")) reverse = 1; if (!(dpy = XOpenDisplay(getenv("DISPLAY")))) perror("can't open display"), exit(1); if (!(small_font = XLoadQueryFont(dpy, "r14")) || !(big_font = XLoadQueryFont(dpy, "9x15"))) perror("can't open default font"), exit(1); attr.override_redirect = TRUE; attr.event_mask = KeyPressMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask; foreground = BlackPixel(dpy, screen); background = WhitePixel(dpy, screen); #ifdef NOT_NOW if (reverse == TRUE) attr.background_pixel = foreground; else #endif /* NOT_NOW */ attr.background_pixel = background; /* Set position and size of main window */ size.flags = PMinSize | PMaxSize | USPosition; size.x = (DisplayWidth(dpy, screen) - BOARD_WIDTH_IN_PIXELS) / 2; size.y = 30; size.min_width = size.width = BOARD_WIDTH_IN_PIXELS; size.min_height = size.height = BOARD_HEIGHT_IN_PIXELS + 70; draw_win = XCreateWindow(dpy, RootWindow(dpy, screen), size.x, size.y, size.width, size.height, 1, DefaultDepth(dpy, screen), InputOutput, DefaultVisual(dpy, screen), CWOverrideRedirect | CWEventMask | CWBackPixel, &attr); XSetNormalHints(dpy, draw_win, &size); XChangeProperty(dpy, draw_win, XA_WM_NAME, XA_STRING, 8, PropModeReplace, "Qix", 3); /* Set position and size of main window */ joystick_win = XCreateWindow(dpy, draw_win, 1, size.height - 68, size.width-4, 65, 1, DefaultDepth(dpy, screen), InputOutput, DefaultVisual(dpy, screen), CWBackPixel, &attr); gcvalues.foreground = reverse? background : foreground; gcvalues.background = reverse? foreground : background; gcvalues.graphics_exposures = False; gcvalues.function = GXcopy; src_gc = XCreateGC(dpy, draw_win, mask, &gcvalues); gcvalues.function = GXclear; clr_gc = XCreateGC(dpy, draw_win, mask, &gcvalues); gcvalues.function = GXxor; gcvalues.foreground = foreground; gcvalues.background = background; gcvalues.plane_mask = background ^ foreground; xor_gc = XCreateGC(dpy, draw_win, mask | GCPlaneMask, &gcvalues); init_images(); XMapWindow(dpy, draw_win); XMapWindow(dpy, joystick_win); XSync(dpy, 0); } window_main_loop() { XEvent event; for (;;) { if (XPending(dpy)) { XNextEvent(dpy, &event); move_joystick(event.xany.window, &event); } else move_pen(); } } pw_text(win, x, y, op, font, string) Window win; XFontStruct *font; char *string; { XSetFont(dpy, src_gc, font->fid); if (op != GXcopy) { XSetFunction(dpy, src_gc, op); XDrawString(dpy, win, src_gc, x, y, string, strlen(string)); XSetFunction(dpy, src_gc, GXcopy); } else XDrawImageString(dpy, win, src_gc, x, y, string, strlen(string)); } #else /* USE SUNVIEW */ init_win(argc, argv) char *argv[]; { frame = window_create(NULL, FRAME, FRAME_LABEL, argv[0], WIN_X, FRAME_X, WIN_Y, FRAME_Y, FRAME_ICON, &qix_icon, FRAME_ARGS, argc, argv, FRAME_NO_CONFIRM, TRUE, 0); Draw = window_create(frame, CANVAS, WIN_HEIGHT, BOARD_HEIGHT_IN_PIXELS, WIN_WIDTH, BOARD_WIDTH_IN_PIXELS, WIN_EVENT_PROC, move_joystick, 0); draw_win = canvas_pixwin(Draw); if (interval == 0) interval = (draw_win->pw_pixrect->pr_depth == 8)? 35000 : 50000; window_set(Draw, CANVAS_FAST_MONO, TRUE, WIN_CONSUME_PICK_EVENTS, WIN_MOUSE_BUTTONS, 0, WIN_CONSUME_KBD_EVENTS, WIN_ASCII_EVENTS, SHIFT_CTRL, SHIFT_META, 0, WIN_INPUT_DESIGNEE, window_get(Draw, WIN_DEVICE_NUMBER), 0); Joystick = window_create(frame, CANVAS, WIN_X, 0, WIN_BELOW, Draw, WIN_HEIGHT, 68, WIN_WIDTH, WIN_EXTEND_TO_EDGE, 0); joystick_win = canvas_pixwin(Joystick); /* * set color map segment name and load color map */ { static char cmsname[CMS_NAMESIZE]; static char r[QIX_CMS_SIZE],g[QIX_CMS_SIZE],b[QIX_CMS_SIZE]; (void) strcpy(cmsname, QIX_CMS_NAME); pw_setcmsname(draw_win, cmsname); pw_setcmsname(joystick_win, cmsname); /* blueish */ r[FAST_DRAW_COLOR] = 40; g[FAST_DRAW_COLOR] = 170; b[FAST_DRAW_COLOR] = 213; /* brownish */ r[SLOW_DRAW_COLOR] = 213; g[SLOW_DRAW_COLOR] = 170; b[SLOW_DRAW_COLOR] = 0; /* dark something */ r[TEXT_COLOR] = 0; g[TEXT_COLOR] = 80; b[TEXT_COLOR] = 190; /* red sparks when not aggressive */ r[SPARKS_COLOR] = 255; g[SPARKS_COLOR] = 0; b[SPARKS_COLOR] = 0; /* blue sparks when aggressive */ r[AGGR_SPARK_COLOR] = 0; g[AGGR_SPARK_COLOR] = 0; b[AGGR_SPARK_COLOR] = 255; cms_rainbowsetup(&r[QIX_COLOR_BASE], &g[QIX_COLOR_BASE], &b[QIX_COLOR_BASE]); pw_putcolormap(draw_win, 0, QIX_CMS_SIZE, r, g, b); pw_putcolormap(joystick_win, 0, QIX_CMS_SIZE, r, g, b); } window_fit(frame); if (!(small_font = pf_open("/usr/people/argv/computer.14")) && !(small_font = pf_default()) || !(big_font = pf_open("/usr/lib/fonts/fixedwidthfonts/serif.r.16")) && !(big_font = pf_default())) perror("can't open default font"), exit(1); pw_text(joystick_win, 92, 24, PIX_SRC, small_font, "Fast Slow"); old_repaint_func = (int(*)())window_get(frame, CANVAS_REPAINT_PROC); window_set(frame, CANVAS_REPAINT_PROC, redraw, 0); } #endif /* X11 */