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 r

⟦30c0e7ace⟧ TextFile

    Length: 11697 (0x2db1)
    Types: TextFile
    Names: »regions.c«

Derivation

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

TextFile

#include "qix.h"

#ifdef X11
#include <X11/bitmaps/gray1> 
#include <X11/bitmaps/gray3> 

static Pixmap fast_gray, slow_gray;

init_gray()
{
    if (!(fast_gray = XCreateBitmapFromData(dpy, draw_win,
	gray1_bits, gray1_width, gray1_height)))
	perror("gray1");
    if (!(slow_gray = XCreateBitmapFromData(dpy, draw_win,
	gray3_bits, gray3_width, gray3_height)))
	perror("gray3");
}

#else

short slow_gray_dat[] = {
#include <images/square_25.pr>
};
mpr_static(slow_gray,       16, 16, 1, slow_gray_dat);

short fast_gray_dat[] = {
#include <images/square_50.pr>
};
mpr_static(fast_gray,       16, 16, 1, fast_gray_dat);
#endif /* X11 */

/*
 * Ther user is drawing a line ... store each move as a doubly linked
 * list of x/y coords.  When the region is completed, the list is completed
 * resulting in a closed polygon.
 */
add_to_line(x, y)
register int x,y;
{
    struct region *new;

    if(!(new = (struct region *)malloc(sizeof(struct region)))) {
	change_life(DIE);
	fprintf(stderr, "%s, line %d: malloc failed\n", __FILE__, __LINE__);
	abort();
    }
    new->x = x;
    new->y = y;
    new->next = (struct region *) NULL;
    new->prev = cur_coord;
    if (nitems++)
	cur_coord->next = new, cur_coord = new;
    else
	region = new, cur_coord = region;
}

/*
 * close region means that the user has successfully drawn from
 * one point to another closing a "region" of territory.  We *should*
 *    Kill the current fuse.
 *    Determine where the qix is and determine the
 *    	region that does NOT enclose the qix (get_edge()).
 *    Call polyfill to fill region and tally up points.
 *    Fill the the region with the appropriate "shade".
 * If there are two qix, check to see that get_edge returns the same edge.
 * If they are different, then the user split the two qix.  If they're the
 * same, close the region as usual.
 *
 * return 0 if normal region closed.  return 1 on error or splitting 2 qix.
 */
close_region(x,y)
{
    int npts[1], n, edge, region_score;
    Point *calloc(), *new_area, save_pt;

    fuse = NULL;

    if (level > -1 && (n = get_edge(moving, x, y, 1)) == -1)
	return -1;
    if ((edge = get_edge(moving, x, y, 0)) == -1)
	return -1;
    if (level > -1 && edge != n) {
	msg("You split the two qix!");
	Sleep(2);
	/* don't erase it, but free it up */
	rm_cur_line(PIX_SRC|PIX_COLOR(BORDER_COLOR)); 
	moving = STOP;
	return 1;
    }

#ifdef DEBUG
    if (debug && edge)
	printf("moving = %s, edge = %s\n",
	    (moving == UP)? "UP" : (moving == DOWN)? "DOWN" :
	    (moving == LEFT)? "LEFT" : "RIGHT",
	    (edge == UP)? "UP" : (edge == DOWN)? "DOWN" :
	    (edge == LEFT)? "LEFT" : "RIGHT");
#endif DEBUG

    if (moving == UP && edge == LEFT || moving == LEFT && edge == UP)
	region_score = polyfill(x*2 + 1, y*2 + 1);
    else if (moving == RIGHT && edge == DOWN
	  || moving == DOWN && edge == RIGHT)
	region_score = polyfill(x*2 - 1, y*2 - 1);
    else if (moving == UP && edge == RIGHT
	  || moving == RIGHT && edge == UP)
	region_score = polyfill(x*2 - 1, y*2 + 1);
    else if (moving == LEFT && edge == DOWN
	  || moving == DOWN && edge == LEFT)
	region_score = polyfill(x*2 + 1, y*2 - 1);
    else
	region_score = 0;

    /* region_score is number of board locations closed * 4 since there
     * are 4 quads per square. divide region_score by 4.
     */
    region_score /= 4;

    /* level shows bonus multipliers -- !fast is a slow draw (double score)
     * 1/2 point per board location, so divide region_score by 2.
     */
    score += (region_score * ((level>-1)? (level+1) : 1) * (!fast + 1))/2;
    area_closed += region_score;

    save_pt.x = x, save_pt.y = y;
    while (x != region->x || y != region->y) {
	if (nitems > 10000) {
	    msg("can't fill region; over 10000 positions");
	    pen_x = region->x, pen_y = region->y;
	    msg("removing bad line ...(takes a while)");
	    /* causes dotted line effect */
	    rm_cur_line(XOR|PIX_COLOR(BORDER_COLOR)); 
	    remove_msgs(0);
	    return -1;
	}
	/* if we came from up, we check left-right */
	add_to_line(x, y);
#ifdef DEBUG
	if (debug > 2)
	    show_bert(x, y);
#endif DEBUG

	switch (moving) {
	    when UP :
		switch (edge) {
		    /* Edge is on our left, sweep counter-clockwise */
		    when LEFT :
			if (board[x][y] & CL_LN_RT)
			    x++, moving = RIGHT, edge = UP;
			else if (board[x][y] & CL_LN_UP)
			    y--;
			else if (board[x][y] & CL_LN_LF)
			    x--, moving = LEFT, edge = DOWN;
#ifdef DEBUG
			else
			    bad_fill_cell(x,y, edge, moving);
#endif DEBUG
		    /* Edge is on our right, sweep clockwise */
		    when RIGHT :
			if (board[x][y] & CL_LN_LF)
			    x--, moving = LEFT, edge = UP;
			else if (board[x][y] & CL_LN_UP)
			    y--;
			else if (board[x][y] & CL_LN_RT)
			    x++, moving = RIGHT, edge = DOWN;
#ifdef DEBUG
			else
			    bad_fill_cell(x,y, edge, moving);
#endif DEBUG
		}

	    when LEFT :
		switch (edge) {
		    /* Edge is above, sweep counter-clockwise */
		    when UP :
			if (board[x][y] & CL_LN_DN)
			    y++, moving = DOWN, edge = LEFT;
			else if (board[x][y] & CL_LN_LF)
			    x--;
			else if (board[x][y] & CL_LN_UP)
			    y--, moving = UP, edge = RIGHT;
#ifdef DEBUG
			else
			    bad_fill_cell(x,y, edge, moving);
#endif DEBUG
		    /* Edge is below, sweep clockwise */
		    when DOWN :
			if (board[x][y] & CL_LN_UP)
			    y--, moving = UP, edge = LEFT;
			else if (board[x][y] & CL_LN_LF)
			    x--;
			else if (board[x][y] & CL_LN_DN)
			    y++, moving = DOWN, edge = RIGHT;
#ifdef DEBUG
			else
			    bad_fill_cell(x,y, edge, moving);
#endif DEBUG
		}

	    when DOWN :
		switch (edge) {
		    /* Edge is on our left, sweep clockwise */
		    when LEFT :
			if (board[x][y] & CL_LN_RT)
			    x++, moving = RIGHT, edge = DOWN;
			else if (board[x][y] & CL_LN_DN)
			    y++;
			else if (board[x][y] & CL_LN_LF)
			    x--, moving = LEFT, edge = UP;
#ifdef DEBUG
			else
			    bad_fill_cell(x,y, edge, moving);
#endif DEBUG
		    /* Edge is on our right, sweep counter-clockwise */
		    when RIGHT :
			if (board[x][y] & CL_LN_LF)
			    x--, moving = LEFT, edge = DOWN;
			else if (board[x][y] & CL_LN_DN)
			    y++;
			else if (board[x][y] & CL_LN_RT)
			    x++, moving = RIGHT, edge = UP;
#ifdef DEBUG
			else
			    bad_fill_cell(x,y, edge, moving);
#endif DEBUG
		}

	    when RIGHT :
		switch (edge) {
		    /* Edge is above, sweep clockwise */
		    when UP :
			if (board[x][y] & CL_LN_DN)
			    y++, moving = DOWN, edge = RIGHT;
			else if (board[x][y] & CL_LN_RT)
			    x++;
			else if (board[x][y] & CL_LN_UP)
			    y--, moving = UP, edge = LEFT;
#ifdef DEBUG
			else
			    bad_fill_cell(x,y, edge, moving);
#endif DEBUG
		    /* Edge is below, sweep counter-clockwise */
		    when DOWN :
			if (board[x][y] & CL_LN_UP)
			    y--, moving = UP, edge = RIGHT;
			else if (board[x][y] & CL_LN_RT)
			    x++;
			else if (board[x][y] & CL_LN_DN)
			    y++, moving = DOWN, edge = LEFT;
#ifdef DEBUG
			else
			    bad_fill_cell(x,y, edge, moving);
#endif DEBUG
		}
	}
    }

    if (!(new_area = calloc(nitems, sizeof(Point)))) {
	change_life(DIE);
	fprintf(stderr, "%s, line %d: malloc failed\n", __FILE__, __LINE__);
	abort();
    }

    /* we CAN move onto endpoints, but nothing inside */
    npts[0] = nitems;
    for (n = 0; region; n++) {
	new_area[n].x = convert_x(region->x);
	new_area[n].y = convert_y(region->y);
	board[region->x][region->y] &= ~NEW_LINE;
	board[region->x][region->y] |= OLD_LINE;
	cur_coord = region->next;
	free(region);
	region = cur_coord;
    }
#if 0
    if (debug > 1)
	printf("polyfill(): %d; polygon_area(): %d\n", region_score,
		polygon_area(new_area, nitems) / LINE_SPACE / LINE_SPACE);
#endif

    toggle_sparks();
    pw_putattributes(draw_win, fast ? &fast_draw_mask: &slow_draw_mask);
#ifdef X11
    /* When filling with a pattern, use stipple -- I don't know how to color */
    XFlush(dpy); /* appear to close the region */
    XSetFillStyle(dpy, src_gc, FillStippled);
    XSetStipple(dpy, src_gc, fast? fast_gray : slow_gray);
    XFillPolygon(dpy, draw_win, src_gc, new_area, nitems,
		 Nonconvex,CoordModeOrigin);
    XFlush(dpy);
    XSetFillStyle(dpy, src_gc, FillSolid);
#else
    pw_polygon_2(draw_win, 0,0,1, npts, new_area, 
	PIX_SRC | PIX_DST | PIX_COLOR(fast ? FAST_DRAW_COLOR: SLOW_DRAW_COLOR),
	draw_win->pw_pixrect->pr_depth == 8? NULL :
	fast? &fast_gray : &slow_gray, 0, 0);
#endif /* X11 */
    toggle_sparks();

    free(new_area);
    nitems = 0, moving = STOP;
    if (play_mode == DEMO)
	time_left = 1;
    return 0;
}

#ifdef DEBUG
bad_fill_cell(x, y, edge, moving)
register int x, y, edge, moving;
{
    msg("fail at %d, %d (%x) moving = %s, edge on %s", x,y,board[x][y],
	(moving == UP)? "up" : (moving == DOWN)? "down" :
	(moving == RIGHT)? "right" : "left",
	(edge == UP)? "up" : (edge == DOWN)? "down" :
	(edge == RIGHT)? "right" : "left");
    Sleep(2);
    remove_msgs(0);
}
#endif DEBUG

rm_cur_line(op)
{
    pw_putattributes(draw_win, &border_mask);
    if (region)
	board[region->x][region->y] = saved_edge;
    while (cur_coord)
	if (cur_coord = cur_coord->prev) {
	    board[cur_coord->next->x][cur_coord->next->y] = 0;
	    draw(convert_x(cur_coord->next->x),
		 convert_y(cur_coord->next->y),
		 convert_x(cur_coord->x), convert_y(cur_coord->y), op);
	    free(cur_coord->next);
	}
    region = (struct region *)NULL;
    cur_coord = (struct region *)NULL;
    nitems = 0;
}

/* cmp: returns 0, 1, or 2 depending on whether
	a is    <, =, or > b */
#define cmp(a,b) ((a > b) + (a >= b))
/* which way bert should start, depending on where person is w.r.t qix */
char dirtable[3][3] ={	{ LEFT, UP, UP },
			{ LEFT, 0, RIGHT},
			{ DOWN, DOWN, RIGHT} };
get_edge(person_moving, person_x, person_y, which_qix)
{
    int dx, dy;
    int x, y, moving;

    if (get_qix_pos(which_qix, &x, &y) == -1)
	return -1;

    /* move from the qix until we find a line or the edge of the board */
    moving = dirtable[cmp(person_y, y)][cmp(person_x, x)];
    if (moving == 0) {
	change_life(DIE);
	msg("You fucked up so incredibly badly that you must die\n");
	exit(1);
    }
    dx = dy = 0;
    switch (moving) {
	when UP: dy = -1;
	when DOWN: dy = 1;
	when LEFT: dx = -1;
	when RIGHT: dx = 1;
    }
    while (!board[x][y]) {
#ifdef DEBUG
	show_bert(x, y);
#endif DEBUG
	x += dx;
	y += dy;
    }

    /* now traverse the interior clockwise until bert hits the person */
    for (;;) {
	int on_person = person_x == x && person_y == y;
#ifdef DEBUG
	show_bert(x, y);
#endif DEBUG
	/* always sweep clockwise around the edges till we find the player */
	if (on_person && moving == person_moving)
	    /* the bert just rear-ended player */
       /* qix on on the "right" of the player (with respect to player facing) */
	    return RIGHT_OF(person_moving);

	switch (moving) {
	    when UP :
		if (board[x][y] & CL_LN_RT)
		    x++, moving = RIGHT;
		else if (board[x][y] & CL_LN_UP)
		    y--;
		else if (board[x][y] & CL_LN_LF)
		    x--, moving = LEFT;

	    when LEFT :
		if (board[x][y] & CL_LN_UP)
		    y--, moving = UP;
		else if (board[x][y] & CL_LN_LF)
		    x--;
		else if (board[x][y] & CL_LN_DN)
		    y++, moving = DOWN;

	    when DOWN :
		if (board[x][y] & CL_LN_LF)
		    x--, moving = LEFT;
		else if (board[x][y] & CL_LN_DN)
		    y++;
		else if (board[x][y] & CL_LN_RT)
		    x++, moving = RIGHT;

	    when RIGHT :
		if (board[x][y] & CL_LN_DN)
		    y++, moving = DOWN;
		else if (board[x][y] & CL_LN_RT)
		    x++;
		else if (board[x][y] & CL_LN_UP)
		    y--, moving = UP;
	}
	if (on_person && moving == OPP_OF(person_moving)) {
	    /* then bert just ran over player */
       /* qix on on the "left" of the player (with respect to player facing) */
	    return LEFT_OF(person_moving);
        }
    }
}