DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T m

⟦2c0de87f3⟧ TextFile

    Length: 16273 (0x3f91)
    Types: TextFile
    Names: »main.c«

Derivation

└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
    └─⟦this⟧ »EUUGD18/X/Qix/main.c« 

TextFile

/*
 * 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 */