|
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 r
Length: 11697 (0x2db1) Types: TextFile Names: »regions.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987 └─⟦this⟧ »EUUGD18/X/Qix/regions.c«
#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); } } }