|
|
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);
}
}
}