home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
MM1
/
GRAPHICS
/
ssaver.lzh
/
SRC
/
saver_maze.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-10-31
|
18KB
|
719 lines
/* saver_maze.c */
#include <stdio.h>
#include <modes.h>
#include <types.h>
#include "saver.h"
int orgwin, win, twin;
int gotosleep = FALSE;
int sigcode = 0; /* storage to keep received signal(s) */
int sighandler(); /* this will use a signal handler function */
extern int errno;
void create_maze();
void solve_maze();
main()
{
int evID; /* event ID */
sigmask(1); /* mask signals */
intercept(sighandler); /* install signal handler */
if ((evID = _ev_link(EV_NAME)) == -1)
exit(1);
DWSet(STDOUT, 3, 0, 0, 40, 26, 0, 0, 0);
if (_gs_currscr(STDOUT,&orgwin) == -1)
exit(0);
CurOff(STDOUT);
BColor(STDOUT, 0);
_gs_wdev(STDOUT, &win); /* get our window device number */
_ss_select(STDOUT, win); /* now select it! */
/* init your screen here */
init_saver();
sigmask(0); /* unmask signals */
_ev_set(evID, 0, 0x8000); /* wake up everybody */
/* we unlink from the event since we are through with it */
_ev_unlink(evID);
while(!sigcode)
{
/* replace the sleep(0); call with your busy function.
*
* Make it return if sigcode is non-zero.
* Also let it sleep a few ticks after every iteration.
*/
if (gotosleep)
sleep(0);
else
do_maze();
}
Reset( STDOUT );
}
sighandler(signal)
int signal;
{
switch (signal) {
case SLEEP_SIG:
gotosleep = TRUE;
break;
case WAKE_SIG:
gotosleep = FALSE;
break;
case QUIT_SIG:
default:
gotosleep = FALSE;
sigcode = signal;
if (_gs_currscr(STDOUT,&twin) == -1)
exit(0);
if (twin == win) {
_ss_select(STDOUT, orgwin);
}
}
}
#if 0
static int rndval=10000;
/* rrand( val ) : return a pseudo-random value between 1 and val.
** IF val is -1, it is used as a seed.
** IF val is negative the better the seed.
*/
rrand( val )
int val;
{
int bit0, bit1, bit14, num, i;
/* see if -1 */
if ( val < 0 ) {
rndval = -val;
}
for ( i = 0; i < 10; i++ )
{
bit0 = rndval & 1;
bit1 = (rndval & 2) >> 1;
bit14 = bit0 ^ bit1;
rndval >>=1;
rndval |= (bit14 << 14);
}
num = rndval % val;
return( num ? num : val );
}
#endif
/* MAZE.C */
/* */
/* Generates a randomom binary tree maze, draws it and solves it */
/* graphically. The Solution employs a simple depth first search */
/* algorithm. */
/* */
/* This program was adapted for the HP workstation from one */
/* provided with the Sun 3 software release version ???. */
/* */
/* Converted to OS-9 and the Color Computer 3 by Brian C. White */
/* (Requires the truely wonderful Kreider C library) */
/* */
/* Converted to MM/1 on 09/20/90 Mike Haaland CIS UID# 72300,1433 */
/* (Requires the Haaland CGFX library) <blush> */
/* This makes the sleep the same length on all OSK machines */
#define _tsleep(x) tsleep(0x80000000 + (x))
#define BACKPAL 00 /* Background color (black) */
#define WRNGPAL 02 /* Wrong path color (dark grey) */
#define PATHPAL 10 /* Correct path color (white) */
#define MAZEPAL 15 /* Maze wall color (white) */
#define ENDPAUSE 720 /* Ticks to wait between mazes (4*60) */
#define XSQ_SIZE 16
#define YSQ_SIZE 8
#define XPATH_SIZE 8
#define YPATH_SIZE 4
#define XDIFF 8
#define YDIFF 4
#define XOFFSET 4
#define YOFFSET 2
#define XINCR_OFFSET 2
#define YINCR_OFFSET 1
#define X_MAZE_SIZE 39
#define Y_MAZE_SIZE 24
#define MAZE_X_LESS_1 (X_MAZE_SIZE - 1)
#define MAZE_Y_LESS_1 (Y_MAZE_SIZE - 1)
#define MOVE_LIST_SIZE (X_MAZE_SIZE * Y_MAZE_SIZE)
#define TOP (unsigned)0x8880
#define RIGHT (unsigned)0x4440
#define BOTTOM (unsigned)0x2220
#define LEFT (unsigned)0x1110
#define WALL_TOP (unsigned)0x8000
#define WALL_RIGHT (unsigned)0x4000
#define WALL_BOTTOM (unsigned)0x2000
#define WALL_LEFT (unsigned)0x1000
#define TOP_IN_DOOR (unsigned)0x800
#define RIGHT_IN_DOOR (unsigned)0x400
#define BOT_IN_DOOR (unsigned)0x200
#define LEFT_IN_DOOR (unsigned)0x100
#define ANY_IN_DOOR (unsigned)0xF00
#define TOP_OUT_DOOR (unsigned)0x80
#define RIGHT_OUT_DOOR (unsigned)0x40
#define BOT_OUT_DOOR (unsigned)0x20
#define LEFT_OUT_DOOR (unsigned)0x10
#define START_SQUARE (unsigned)0x2
#define END_SQUARE (unsigned)0x1
#define MAZEGROUND 255 /* 0 */
int PATHGROUND = 3; /* 1 */
int WRNGGROUND = 8; /* 2 */
#define BACKGROUND 0 /* 3 */
#ifndef STDIN
#define STDIN 0
#define STDOUT 1
#define STDERR 2
#endif
/*
#include <stdio.h>
*/
#include <sgstat.h>
#define ON 1
#define OFF 0
static struct sgbuf wbuforig, wbuf;
static unsigned short maze[X_MAZE_SIZE][Y_MAZE_SIZE];
static struct {
unsigned char x;
unsigned char y;
unsigned char dir;
} move_list[MOVE_LIST_SIZE], save_path[MOVE_LIST_SIZE], path[MOVE_LIST_SIZE];
static unsigned int sqnum, cur_sq_x, cur_sq_y, path_length;
static unsigned int start_x, start_y, start_dir, end_x, end_y, end_dir;
static unsigned int outpath, xoffset_count, yoffset_count;
init_saver()
{
xoffset_count = 4;
yoffset_count = 0;
outpath = STDOUT;
CurOff ( outpath );
pausesw ( outpath, OFF );
BColor ( outpath, BACKGROUND );
FColor ( outpath, MAZEGROUND );
}
do_maze()
{
srand(time(0));
getcolorset();
Clear ( outpath );
FColor ( outpath, MAZEGROUND );
initialize_maze();
if (! sigcode)
create_maze();
if (! sigcode)
solve_maze();
if (! sigcode)
_tsleep ( ENDPAUSE );
xoffset_count = ( xoffset_count + XINCR_OFFSET ) % XSQ_SIZE ;
yoffset_count = ( yoffset_count + YINCR_OFFSET ) % YSQ_SIZE ;
xoffset_count = (xoffset_count) ? xoffset_count : 4;
} /* end of maze() */
/* draw the surrounding wall and start/end squares */
initialize_maze()
{
register unsigned int i;
unsigned int j, wall;
unsigned int tempx, tempy;
/* initialize all squares */
FColor ( outpath, MAZEGROUND );
for ( i=0; i<X_MAZE_SIZE; i++)
{
for ( j=0; j<Y_MAZE_SIZE; j++)
{
maze[i][j] = 0;
}
}
/* top wall */
for ( i=0; i<X_MAZE_SIZE; i++ )
{
maze[i][0] = maze[i][0] | WALL_TOP;
}
/* right wall */
for ( j=0; j<Y_MAZE_SIZE; j++ )
{
maze[MAZE_X_LESS_1][j] = maze[MAZE_X_LESS_1][j] | WALL_RIGHT;
}
/* bottom wall */
for ( i=0; i<X_MAZE_SIZE; i++ )
{
maze[i][MAZE_Y_LESS_1] = maze[i][MAZE_Y_LESS_1] | WALL_BOTTOM;
}
/* left wall */
for ( j=0; j<Y_MAZE_SIZE; j++ )
{
maze[0][j] = maze[0][j] | WALL_LEFT;
}
/* set start square */
wall = random(4);
switch (wall) {
case 0:
i = random(X_MAZE_SIZE);
j = 0;
break;
case 1:
i = MAZE_X_LESS_1;
j = random(Y_MAZE_SIZE);
break;
case 2:
i = random(X_MAZE_SIZE);
j = MAZE_Y_LESS_1;
break;
case 3:
i = 0;
j = random(Y_MAZE_SIZE);
break;
}
maze[i][j] = maze[i][j] | START_SQUARE;
maze[i][j] = maze[i][j] | ( TOP_IN_DOOR >> wall );
maze[i][j] = maze[i][j] & ~( WALL_TOP >> wall );
cur_sq_x = i;
cur_sq_y = j;
start_x = i;
start_y = j;
start_dir = wall;
sqnum = 0;
/* set end square */
wall = (wall + 2)%4;
switch (wall) {
case 0:
i = random(X_MAZE_SIZE);
j = 0;
break;
case 1:
i = MAZE_X_LESS_1;
j = random(Y_MAZE_SIZE);
break;
case 2:
i = random(X_MAZE_SIZE);
j = MAZE_Y_LESS_1;
break;
case 3:
i = 0;
j = random(Y_MAZE_SIZE);
break;
}
maze[i][j] = maze[i][j] | END_SQUARE;
maze[i][j] = maze[i][j] | ( TOP_OUT_DOOR >> wall );
maze[i][j] = maze[i][j] & ~( WALL_TOP >> wall );
end_x = i;
end_y = j;
end_dir = wall;
/* draw the border */
for ( i=0; i<X_MAZE_SIZE && !sigcode ; i++)
{
if ( maze[i][0] & WALL_TOP )
{
tempx = xoffset_count + XSQ_SIZE * i;
tempy = yoffset_count;
XDrawLine ( tempx, tempy, tempx + XSQ_SIZE, tempy );
}
if ((maze[i][MAZE_Y_LESS_1] & WALL_BOTTOM))
{
tempx = xoffset_count + XSQ_SIZE * i;
tempy = yoffset_count + Y_MAZE_SIZE * YSQ_SIZE;
XDrawLine ( tempx, tempy, tempx + XSQ_SIZE, tempy );
}
}
for ( j=0; j<Y_MAZE_SIZE && !sigcode; j++)
{
if ( maze[MAZE_X_LESS_1][j] & WALL_RIGHT )
{
tempx = xoffset_count + X_MAZE_SIZE * XSQ_SIZE;
tempy = yoffset_count + YSQ_SIZE * j;
XDrawLine ( tempx, tempy, tempx, tempy + YSQ_SIZE );
}
if ( maze[0][j] & WALL_LEFT )
{
tempx = xoffset_count;
tempy = yoffset_count + YSQ_SIZE * j;
XDrawLine ( tempx, tempy, tempx, tempy + YSQ_SIZE );
}
}
circle_draw_solid ( start_x, start_y, start_dir );
square_draw_solid ( end_x, end_y, end_dir );
} /* end of initialize_maze() */
/* create a maze layout given the intiialized maze */
void
create_maze()
{
register unsigned int i;
unsigned int newdoor;
if (gotosleep)
sleep(0);
FColor ( outpath, MAZEGROUND );
do {
move_list[sqnum].x = cur_sq_x;
move_list[sqnum].y = cur_sq_y;
move_list[sqnum].dir = newdoor;
/* pick a door */
while ( ( newdoor = choose_door() ) == -1 )
{
/* no more doors ... backup */
if ( backup() == -1 )
{
/* done ... return */
return;
}
}
/* mark the out door */
maze[cur_sq_x][cur_sq_y] = maze[cur_sq_x][cur_sq_y] | ( TOP_OUT_DOOR >> newdoor );
switch (newdoor) {
case 0:
cur_sq_y--;
break;
case 1:
cur_sq_x++;
break;
case 2:
cur_sq_y++;
break;
case 3:
cur_sq_x--;
break;
}
sqnum++;
/* mark the in door */
maze[cur_sq_x][cur_sq_y] = maze[cur_sq_x][cur_sq_y] | ( TOP_IN_DOOR >> ((newdoor+2)%4) );
/* if end square set path length and save path */
if ( maze[cur_sq_x][cur_sq_y] & END_SQUARE )
{
path_length = sqnum;
for ( i=0; i<path_length; i++)
{
save_path[i].x = move_list[i].x;
save_path[i].y = move_list[i].y;
save_path[i].dir = move_list[i].dir;
}
}
} while ( ! sigcode);
} /* end of create_maze() */
/* pick a new path */
choose_door()
{
unsigned int candidates[3];
register unsigned int num_candidates;
num_candidates = 0;
topwall:
/* top wall */
if ( maze[cur_sq_x][cur_sq_y] & TOP )
goto rightwall;
if ( maze[cur_sq_x][cur_sq_y - 1] & ANY_IN_DOOR )
{
maze[cur_sq_x][cur_sq_y] = maze[cur_sq_x][cur_sq_y] | WALL_TOP;
maze[cur_sq_x][cur_sq_y - 1] = maze[cur_sq_x][cur_sq_y - 1] | WALL_BOTTOM;
draw_wall(cur_sq_x, cur_sq_y, 0 );
goto rightwall;
}
candidates[num_candidates++] = 0;
rightwall:
/* right wall */
if ( maze[cur_sq_x][cur_sq_y] & RIGHT )
goto bottomwall;
if ( maze[cur_sq_x + 1][cur_sq_y] & ANY_IN_DOOR )
{
maze[cur_sq_x][cur_sq_y] = maze[cur_sq_x][cur_sq_y] | WALL_RIGHT;
maze[cur_sq_x + 1][cur_sq_y] = maze[cur_sq_x + 1][cur_sq_y] | WALL_LEFT;
draw_wall(cur_sq_x, cur_sq_y, 1 );
goto bottomwall;
}
candidates[num_candidates++] = 1;
bottomwall:
/* bottom wall */
if ( maze[cur_sq_x][cur_sq_y] & BOTTOM )
goto leftwall;
if ( maze[cur_sq_x][cur_sq_y + 1] & ANY_IN_DOOR )
{
maze[cur_sq_x][cur_sq_y] = maze[cur_sq_x][cur_sq_y] | WALL_BOTTOM;
maze[cur_sq_x][cur_sq_y + 1] = maze[cur_sq_x][cur_sq_y + 1] | WALL_TOP;
draw_wall(cur_sq_x, cur_sq_y, 2 );
goto leftwall;
}
candidates[num_candidates++] = 2;
leftwall:
/* left wall */
if ( maze[cur_sq_x][cur_sq_y] & LEFT )
goto donewall;
if ( maze[cur_sq_x - 1][cur_sq_y] & ANY_IN_DOOR )
{
maze[cur_sq_x][cur_sq_y] = maze[cur_sq_x][cur_sq_y] | WALL_LEFT;
maze[cur_sq_x - 1][cur_sq_y] = maze[cur_sq_x - 1][cur_sq_y] | WALL_RIGHT;
draw_wall(cur_sq_x, cur_sq_y, 3 );
goto donewall;
}
candidates[num_candidates++] = 3;
donewall:
if (num_candidates == 0)
return ( -1 );
if (num_candidates == 1)
return ( candidates[0] );
return ( candidates[ random(num_candidates) ] );
} /* end of choose_door() */
backup() /* back up a move */
{
sqnum--;
cur_sq_x = move_list[sqnum].x;
cur_sq_y = move_list[sqnum].y;
return ( sqnum );
} /* end of backup() */
/* draw a single wall */
draw_wall(i, j, dir )
unsigned int i, j, dir;
{
unsigned int tempx, tempy;
switch (dir) {
case 0: /* top */
tempx = xoffset_count + XSQ_SIZE * i;
tempy = yoffset_count + YSQ_SIZE * j;
XDrawLine( tempx, tempy, tempx + XSQ_SIZE, tempy );
break;
case 1: /* right */
tempx = xoffset_count + XSQ_SIZE * (i+1);
tempy = yoffset_count + YSQ_SIZE * j;
XDrawLine( tempx, tempy, tempx, tempy + YSQ_SIZE );
break;
case 2: /* bottom */
tempx = xoffset_count + XSQ_SIZE * i;
tempy = yoffset_count + YSQ_SIZE * (j+1);
XDrawLine( tempx, tempy, tempx + XSQ_SIZE, tempy );
break;
case 3: /* left */
tempx = xoffset_count + XSQ_SIZE * i;
tempy = yoffset_count + YSQ_SIZE * j;
XDrawLine( tempx, tempy, tempx, tempy + YSQ_SIZE );
break;
}
} /* end of draw_wall */
/* draw a solid circle in a square */
circle_draw_solid(i, j, dir )
unsigned int i, j, dir;
{
unsigned int tempx, tempy;
tempx = xoffset_count + 2 + XSQ_SIZE * i;
tempy = yoffset_count + 2 + YSQ_SIZE * j;
XDrawCircle( tempx + (int)(XOFFSET * 1.5 ), tempy + YOFFSET, YPATH_SIZE );
} /* end of circle_draw_solid() */
/* draw a solid square in a square */
square_draw_solid(i, j, dir )
unsigned int i, j, dir;
{
unsigned int tempx, tempy;
tempx = xoffset_count + XOFFSET + XSQ_SIZE * i;
tempy = yoffset_count + YOFFSET + YSQ_SIZE * j;
switch (dir) {
case 0: /* up */
XFillRectangle ( tempx, tempy - YDIFF, XPATH_SIZE, YPATH_SIZE + YDIFF);
break;
case 1: /* right */
XFillRectangle ( tempx, tempy, XPATH_SIZE + XDIFF, YPATH_SIZE);
break;
case 2: /* down */
XFillRectangle ( tempx, tempy, XPATH_SIZE, YPATH_SIZE + YDIFF);
break;
case 3: /* left */
XFillRectangle ( tempx - XDIFF, tempy, XPATH_SIZE + XDIFF, YPATH_SIZE);
break;
}
} /* end of square_draw_solid() */
/* solve it with graphical feedback */
void
solve_maze()
{
register unsigned int i;
FColor ( outpath, PATHGROUND );
/* plug up the surrounding wall */
maze[start_x][start_y] = maze[start_x][start_y] | (WALL_TOP >> start_dir);
maze[end_x][end_y] = maze[end_x][end_y] |(WALL_TOP >> end_dir);
/* initialize search path */
i = 0;
path[i].x = end_x;
path[i].y = end_y;
path[i].dir = -1;
/* do it */
while (! sigcode) {
if ( ++path[i].dir >= 4 )
{
/*
XSetTile ( display , gc, tile25 );
XSetFillStyle ( display , gc, FillTiled );
*/
FColor ( outpath, WRNGGROUND );
i--;
square_draw_solid((int)(path[i].x),(int)(path[i].y),(int)(path[i].dir));
FColor ( outpath, PATHGROUND );
}
else if ( !((maze[path[i].x][path[i].y] & (WALL_TOP >> path[i].dir))) &&
( (i == 0) || ( (path[i].dir != (path[i-1].dir+2)%4) ) ) )
{
enter_square( i );
i++;
if ( maze[path[i].x][path[i].y] & START_SQUARE )
{
return;
}
}
}
} /* end of solve_maze() */
/* move into a neighboring square */
enter_square( n )
unsigned int n;
{
square_draw_solid( (int)path[n].x, (int)path[n].y, (int)path[n].dir );
path[n+1].dir = -1;
switch (path[n].dir) {
case 0:
path[n+1].x = path[n].x;
path[n+1].y = path[n].y - 1;
break;
case 1:
path[n+1].x = path[n].x + 1;
path[n+1].y = path[n].y;
break;
case 2:
path[n+1].x = path[n].x;
path[n+1].y = path[n].y + 1;
break;
case 3:
path[n+1].x = path[n].x - 1;
path[n+1].y = path[n].y;
break;
}
} /* end of enter_square() */
XDrawLine ( sx, sy, ex, ey )
unsigned int sx, sy, ex, ey;
{
if (gotosleep)
sleep(0);
SetDPtr ( outpath, sx, sy );
Line ( outpath, ex, ey );
}
XFillRectangle ( sx, sy, ex, ey )
unsigned int sx, sy, ex, ey;
{
if (gotosleep)
sleep(0);
SetDPtr ( outpath, sx, sy );
RBar ( outpath, ex, ey );
}
XDrawCircle ( sx, sy, rad )
unsigned int sx, sy, rad ;
{
if (gotosleep)
sleep(0);
SetDPtr ( outpath, sx, sy );
Circle ( outpath, rad );
FFill ( outpath );
}
random ( num )
unsigned int num;
{
return ( abs(rand (num)%num) );
}
getcolorset()
{
int color;
WRNGGROUND = random(255);
PATHGROUND = ((color = random(254) + 1) % 16) ? color : color + 1;
while (PATHGROUND == WRNGGROUND)
WRNGGROUND = random(255);
}
GetWOpts()
{
_gs_opt(0,&wbuforig);
}
pausesw(path,sw_pause)
int path, sw_pause;
{
_gs_opt(path, &wbuf);
wbuf.sg_pause = (sw_pause) ? ON : OFF;
_ss_opt (path, &wbuf);
}
Reset()
{
_ss_opt(0, &wbuforig);
}