|
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 s
Length: 8809 (0x2269) Types: TextFile Names: »sparks.c.orig«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987 └─⟦this⟧ »EUUGD18/Sun/Qix/sparks.c.orig«
#include "qix.h" /* * This file deals with the sparks excplicitely. A fuse is a spark, but * travels along the the line the user is drawing. */ short spark1_dat[] = { #include "spark1.pr" }; mpr_static(spark1, 16, 16, 1, spark1_dat); short spark2_dat[] = { #include "spark2.pr" }; mpr_static(spark2, 16, 16, 1, spark2_dat); short spark3_dat[] = { #include "spark3.pr" }; mpr_static(spark3, 16, 16, 1, spark3_dat); short spark4_dat[] = { #include "spark4.pr" }; mpr_static(spark4, 16, 16, 1, spark4_dat); static Pixrect *spark_icons[4] = { &spark1, &spark2, &spark3, &spark4 }; static int spark_time, aggressive; /* * Macor to draw a spark at x,y -- intended to call this macro twice with * the same x,y coords to remove the first spark icon. There are four spark * icons to give a "sparkling" effect when it moves. Since sparks can only * move left-right or up-down the formula given finds which icon to use to * to guarantee that it's not the last one used. */ #define draw_spark(x, y) \ pw_rop(draw_win, pen_coord_x(x), pen_coord_y(y), 16,16, \ XOR, spark_icons[(x + y) & 3], 0,0) struct spark { int x, y, oldx, oldy; } sparks[] = { { -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 }, { -1, -1, -1, -1 } }; int MAX_SPARKS = sizeof (sparks) / sizeof (struct spark); #define CLOCKWISE(spark_number) (spark_number & 1) /* start a new spark at this x,y coord. Since sparks are released in * pairs, odd spark goes left, even spark goes right, and those directions * are [supposed] to remain with the spark thruout its life. */ start_spark(x, y) { register int sp; #ifdef DEBUG if (debug > 1) return; #endif DEBUG for (sp = 0; sp < MAX_SPARKS; sp++) if (sparks[sp].x < 0) { if (CLOCKWISE(sp)) /* odd number spark */ sparks[sp].oldx = x-1, sparks[sp].oldy = y; else sparks[sp].oldx = x+1, sparks[sp].oldy = y; sparks[sp].x = x, sparks[sp].y = y; return; } } /* * Spark movement checks... can't move back onto himself... must only move * onto a square which has a connecting line. If it's on a square which * is completely painted, it may move anywhere. Otherwise, the square has * to have at least one quad which is not painted. Sparks may only move * on "old" (not currently being drawn) lines unless they are aggressive. */ #define check_up(curx, cury, newx, newy, oldy) \ (newy != oldy && (board[curx][cury] & CL_LN_UP) && \ (aggressive || (board[newx][newy] & OLD_LINE) && \ (!check_painted(newx, newy, PAINTED) || check_painted(curx, cury,PAINTED)))) #define check_down(curx, cury, newx, newy, oldy) \ (newy != oldy && (board[curx][cury] & CL_LN_DN) && \ (aggressive || (board[newx][newy] & OLD_LINE) && \ (!check_painted(newx, newy, PAINTED) || check_painted(curx, cury,PAINTED)))) #define check_left(curx, cury, newx, newy, oldx) \ (newx != oldx && (board[curx][cury] & CL_LN_LF) && \ (aggressive || (board[newx][newy] & OLD_LINE) && \ (!check_painted(newx, newy, PAINTED) || check_painted(curx, cury,PAINTED)))) #define check_right(curx, cury, newx, newy, oldx) \ (newx != oldx && (board[curx][cury] & CL_LN_RT) && \ (aggressive || (board[newx][newy] & OLD_LINE) && \ (!check_painted(newx, newy, PAINTED) || check_painted(curx, cury,PAINTED)))) /* return -1 if player dies. 0 otherwise. */ move_sparks() { register int x, y, sp, move_clockwise, came_from, dir; /* new spark x and y coord */ for (sp = 0; sp < MAX_SPARKS; sp++) { if (sparks[sp].x < 0) break; /* if the spark was just introduced, this will not erase the spark, * but actually create two images. however, since sparks are intro- * duced in pairs, the second spark will have the same coords and * erase this mark. (clever, huh?) */ draw_spark(sparks[sp].x, sparks[sp].y); x = sparks[sp].x, y = sparks[sp].y; /* user bit the big one */ if (x == pen_x && y == pen_y) { draw_spark(sparks[sp].x, sparks[sp].y); /* redraw the spark */ change_life(DIE); return -1; } came_from = (x > sparks[sp].oldx)? LEFT : (x < sparks[sp].oldx)? RIGHT : (y > sparks[sp].oldy)? UP : DOWN; if (check_painted(x, y, PAINTED)) move_clockwise = (random() & 1); else { move_clockwise = (CLOCKWISE(sp)); if (check_painted(sparks[sp].oldx, sparks[sp].oldy, PAINTED)) /* we just exited a painted region onto open territory. * pretend we came from along a border, as usual. */ while (came_from == UP && check_painted(x,y, CL_PNT_TOP) || came_from == DOWN && check_painted(x,y, CL_PNT_BOT) || came_from == LEFT && check_painted(x,y, CL_PNT_LEFT) || came_from == RIGHT && check_painted(x,y, CL_PNT_RIGHT)) if (CLOCKWISE(sp)) came_from = LEFT_OF(came_from); else came_from = RIGHT_OF(came_from); } dir = came_from; /* if we are not on a border (surrounded by painted quads) */ do { if (move_clockwise) dir = LEFT_OF(dir); /* this is right, don't argue */ else dir = RIGHT_OF(dir); #ifdef DEBUG if (dir == came_from) { box(convert_x(x)-10, convert_y(y)-10, convert_x(x)+10, convert_y(y)+10, XOR); msg("HALT! infinite-loop police! [y] (%d, %d)", x, y); sleep(2); remove_msgs(0); box(convert_x(x)-10, convert_y(y)-10, convert_x(x)+10, convert_y(y)+10, XOR); break; } #endif DEBUG switch (dir) { when LEFT: if (check_left(x, y, x - 1, y, sparks[sp].oldx)) x--; when RIGHT: if (check_right(x,y,x+1,y,sparks[sp].oldx)) x++; when UP: if (check_up(x,y,x,y-1,sparks[sp].oldy)) y--; when DOWN: if (check_down(x, y, x, y+1, sparks[sp].oldy)) y++; } } while (x == sparks[sp].x && y == sparks[sp].y); sparks[sp].oldx = sparks[sp].x, sparks[sp].oldy = sparks[sp].y; /* draw the new spark */ draw_spark(x, y); sparks[sp].x = x, sparks[sp].y = y; if (x == pen_x && y == pen_y) { change_life(DIE); return -1; } } /* if the timeout has occured, release two sparks */ if (spark_time-- <= 0) { spark_time = SPARK_TIME; if (sp >= MAX_SPARKS/2) { if (!aggressive) { /* give the only warning we can without a sound chip :-) */ fputc(7, stderr), fflush(stderr); msg("Sparx are now aggressive."); sleep(2); remove_msgs(0); aggressive = 1; } if (sp == MAX_SPARKS) return 0; /* no sparks left to start, so don't do a countdown */ } start_spark(BOARD_WIDTH/2, 0, TRUE); start_spark(BOARD_WIDTH/2, 0, FALSE); draw(BORDER, 20, BOARD_WIDTH_IN_PIXELS-BORDER, 20, PIX_SRC); draw(BORDER, 21, BOARD_WIDTH_IN_PIXELS-BORDER, 21, PIX_SRC); } if (sp < MAX_SPARKS) { /* calculate the percentage of the width of the board in pixels */ register int len = (((spark_time*100)/SPARK_TIME)) * (BOARD_WIDTH_IN_PIXELS-2*BORDER)/200; draw(BORDER, 20, BOARD_WIDTH_IN_PIXELS/2 - len, 20, PIX_CLR); draw(BORDER, 21, BOARD_WIDTH_IN_PIXELS/2 - len, 21, PIX_CLR); draw(BOARD_WIDTH_IN_PIXELS/2 + len, 20, BOARD_WIDTH_IN_PIXELS-BORDER, 20, PIX_CLR); draw(BOARD_WIDTH_IN_PIXELS/2 + len, 21, BOARD_WIDTH_IN_PIXELS-BORDER, 21, PIX_CLR); } return 0; } /* * move fuse -- first, remove the last location (if applicable). If * the fuse has burned out, then programmer just wants to erase last one. * next, since the fuse only travels along new lines, move down the list. */ move_fuse(pos) register struct region **pos; { static x = -1, y; int n; if (x > -1) draw_spark(x, y); if (!pos || !*pos) { x = -1; return 0; } draw_spark((*pos)->x, (*pos)->y); x = (*pos)->x, y = (*pos)->y; if ((*pos)->x == pen_x && (*pos)->y == pen_y) { change_life(DIE); pen_x = region->x, pen_y = region->y; return -1; } if (!(*pos = (*pos)->next)) *pos = NULL, x = -1; return 0; } /* * removes all sparks from the screen and their x/y coords. * reset the sparktime value and draw the timeout line. */ clear_sparks() { int n; /* for each spark, if active, make it go away and reset to -1 */ for (n = 0; n < MAX_SPARKS; n++) if (sparks[n].x > -1) { draw_spark(sparks[n].x, sparks[n].y); sparks[n].oldx = sparks[n].x = -1; } draw(BORDER, 20, BOARD_WIDTH_IN_PIXELS-BORDER, 20, PIX_CLR); draw(BORDER, 21, BOARD_WIDTH_IN_PIXELS-BORDER, 21, PIX_CLR); aggressive = spark_time = 0; } /* routine to turn on/off all sparks. When user closes a region, call * this routine to turn off sparks so when the region is filled, the * spark doesn't leave it's mark once it starts moving again. */ toggle_sparks() { register int sp; for (sp = 0; sp < MAX_SPARKS; sp++) { if (sparks[sp].x < 0) break; draw_spark(sparks[sp].x, sparks[sp].y); } }