Exemplo n.º 1
0
/* Randomly choose a next cell to build the current maze segment. */
int maze_choose_next_cell(struct maze *mp, int prevrow, int prevcol,
			  int currow, int curcol, int *nextrow, int *nextcol)
{
	int d;  /* Distance. */
	int dr; /* Delta rows. */
	int dc; /* Delta columns. */
	int nr; /* Next row. */
	int nc; /* Next column. */
	struct segment_weights *swp = &mp->weights[prevrow != currow];
	double w = drandom();

	d = maze_get_cell_distance(mp, currow, curcol);
	if (w > swp->randweight) {
		/* Time to stop. */
		return MAZE_END_SEGMENT;
	}
	if (w > swp->contweight && (prevrow != currow || prevcol != curcol)) {
		/* Erect a perpendicular vector. */
		dr = -(curcol - prevcol);
		dc = currow - prevrow;
		/* Flip the vector if randomly required. */
		if (pmrandom()) {
			dr = -dr;
			dc = -dc;
		}
		/* Try out the corresponding cell. */
		nr = currow + dr;
		nc = curcol + dc;
		if (!maze_try_visit_cell(mp, currow, curcol, nr, nc,
					nextrow, nextcol, d + 1))
			return MAZE_CONTINUE_SEGMENT;
		/* No go, try turning the opposite direction. */
		nr = currow - dr;
		nc = curcol - dc;
		if (!maze_try_visit_cell(mp, currow, curcol, nr, nc,
					nextrow, nextcol, d + 1))
			return MAZE_CONTINUE_SEGMENT;
		/* Neither worked, drop through and try straight. */
	}
	nr = currow + (currow - prevrow);
	nc = curcol + (curcol - prevcol);
	if (!maze_try_visit_cell(mp, currow, curcol, nr, nc,
				nextrow, nextcol, d + 1))
		return MAZE_CONTINUE_SEGMENT;
	/* No go, check all possibilities.  Done being picky! */
	if (maze_find_any_next_cell(mp, currow, curcol, nextrow, nextcol))
		return MAZE_CONTINUE_SEGMENT;
	/* Nowhere left to go. */
	return MAZE_STUCK_SEGMENT;
}
Exemplo n.º 2
0
/* Construct one segment (or passage) in the maze. */
void maze_construct_segment(struct maze *mp, int row1, int col1,
			    int row2, int col2)
{
	int prevrow = row1;
	int prevcol = col1;
	int currow = row2;
	int curcol = col2;
	int nextrow;
	int nextcol;

	/* If starting, pick an initial direction. */
	if (prevrow == currow && prevcol == curcol) {
		if (!maze_find_any_next_cell(mp, currow, curcol,
					     &nextrow, &nextcol))
			return;
		maze_build_cell_walls(mp, prevrow, prevcol, currow, curcol,
				      nextrow, nextcol);
		prevrow = currow;
		prevcol = curcol;
		currow = nextrow;
		curcol = nextcol;
	}

	/* Each pass through the following loop advances one cell. */
	for (;;) {
		switch (maze_choose_next_cell(mp, prevrow, prevcol,
					      currow, curcol,
					      &nextrow, &nextcol)) {
		case MAZE_CONTINUE_SEGMENT:
			maze_build_cell_walls(mp, prevrow, prevcol,
					      currow, curcol, nextrow, nextcol);
			prevrow = currow;
			prevcol = curcol;
			currow = nextrow;
			curcol = nextcol;
			break;
		case MAZE_END_SEGMENT:
			maze_build_cell_walls(mp, prevrow, prevcol,
					      currow, curcol, prevrow, prevcol);
		case MAZE_STUCK_SEGMENT:
			return;
		}
	}
}
Exemplo n.º 3
0
/*
 * Child maze-solver process.  Each child maintains its own ->visited[]
 * array, and the maze data structure is used to handle contention for
 * the same cell.  Such contention indicates that a pair of child threads
 * has found a path to each other.
 */
void *maze_solve_child(void *arg)
{
	int cr;
	int cc;
	int nr;
	int nc;
	cpu_set_t mask;
	int vi = 0;
	struct maze_child *mcp = (struct maze_child *)arg;
	struct maze_child_shared *mcsp = mcp->mcsp;
	struct maze *mp = mcsp->mp;
	static const struct timespec ts = { .tv_sec = 0, .tv_nsec = 3000 };
	unsigned long long tstart = current_time();

	mymcp = mcp;
	myid = mcp->myid;
	CPU_ZERO(&mask);
	CPU_SET(myid, &mask);
	sched_setaffinity(0, sizeof(mask), &mask);
	cr = mcp->visited[vi].row;
	cc = mcp->visited[vi].col;
	do {
		/*
		 * Each pass through the following loop checks one cell
		 * that has already been visited.  When a cell is found
		 * that has at least one remaining unexplored neighbor,
		 * go to the following loop to do the exploration.
		 */
		while (!maze_find_any_next_cell(mp, cr, cc, &nr, &nc)) {
			if (++vi >= mcp->vi || ACCESS_ONCE(mcsp->done))
				goto done;
			cr = mcp->visited[vi].row;
			cc = mcp->visited[vi].col;
		}

		/*
		 * Each pass through the following loop attempts to extend
		 * the current path one cell.
		 */
		do {
			if (ACCESS_ONCE(mcsp->done))
				goto done;
			cr = nr;
			cc = nc;
		} while (maze_find_any_next_cell(mp, cr, cc, &nr, &nc));

		/*
		 * Reset back to the start of this path in case there is
		 * another unexplored cell adjacent to it.
		 */
		cr = mcp->visited[vi].row;
		cc = mcp->visited[vi].col;
	} while (!maze_solve_child_done_check());
done:

	/* Capture time, and act as passthrough for visibility information. */
	mcp->dt = current_time() - tstart;
	if (nthreads > 2)
		while (!maze_solve_child_done_check())
			nanosleep(&ts, NULL); /* In case hardware bus-locks. */
	return NULL;
}

/*
 * The thread encounters are stored, but only by the thread that discovered
 * the encounter.  Copy any encounters to the location that the other
 * thread would have recorded them.
 */
void maze_solve_map_adj(struct maze *mp)
{
	int i;
	int j;
	struct maze_child *mcp = mp->msp->mcp;

	for (i = 0; i < nthreads; i++)
		for (j = 0; j < nthreads; j++)
			if (mcp[i].adj[j].mr == -1) {
				mcp[i].adj[j].mr = mcp[j].adj[i].tr;
				mcp[i].adj[j].mc = mcp[j].adj[i].tc;
				mcp[i].adj[j].tr = mcp[j].adj[i].mr;
				mcp[i].adj[j].tc = mcp[j].adj[i].mc;
			}
}