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