Пример #1
0
/*
 * Is the second cell the predecessor to the first one along the
 * solution path?  The "backwards" order of arguments is due to
 * the fact that we traverse the solution backwards when marking it.
 */
int maze_is_prev_cell(struct maze *mp, int row1, int col1, int row2, int col2,
		      int *nextrow, int *nextcol)
{
	if (!maze_cells_connected(mp, row1, col1, row2, col2) ||
	    !maze_same_tids(mp, row1, col1, row2, col2) ||
	    maze_get_cell_distance(mp, row1, col1) -
	    maze_get_cell_distance(mp, row2, col2) != 1)
		return 0;
	*nextrow = row2;
	*nextcol = col2;
	return 1;
}
Пример #2
0
/*
 * Find a boundary between the created and inchoate portions of the maze.
 * Return 0 if the maze is now fully created.
 */
int maze_find_boundary(struct maze *mp, int *prevrow, int *prevcol,
		       int *currow, int *curcol)
{
	int d;
	int cr;
	int cc;
	int pr;
	int pc;
	int vi;
	int vi_lim;
	int vi_start;

	if (mp->lastvi == -1 || drandom() > mp->revisit)
		vi = drandom() * mp->vi;
	else
		vi = mp->lastvi;
	vi_lim = mp->vi;
	vi_start = vi;
	do {
		pr = mp->visited[vi].row;
		pc = mp->visited[vi].col;
		cr = -1;
		if (!maze_cell_visited(mp, pr - 1, pc)) {
			cr = pr - 1;
			cc = pc;
		}
		if (!maze_cell_visited(mp, pr + 1, pc) &&
		    (cr == -1 || drandom() < 0.5)) {
			cr = pr + 1;
			cc = pc;
		}
		if (!maze_cell_visited(mp, pr, pc - 1) &&
		    (cr == -1 || drandom() < 0.5)) {
			cr = pr;
			cc = pc - 1;
		}
		if (!maze_cell_visited(mp, pr, pc + 1) &&
		    (cr == -1 || drandom() < 0.5)) {
			cr = pr;
			cc = pc + 1;
		}
		if (cr != -1) {
			d = maze_get_cell_distance(mp, pr, pc);
			maze_remove_wall(mp, pr, pc, cr, cc);
			maze_visit_cell(mp, cr, cc, d + 1);
			*prevrow = pr;
			*prevcol = pc;
			*currow = cr;
			*curcol = cc;
			mp->lastvi = vi;
			return 1;
		}
		vi++;
		if (vi >= mp->vi)
			vi = 0;
		if (vi_lim != mp->vi)
			ABORT();
	} while (vi != vi_start);
	return 0; /* Maze is now finished. */
}
Пример #3
0
/* Advance the solution marking by one cell. */
void maze_mark_advance_cell(struct maze *mp, int cr, int cc, int *nr, int *nc)
{
	cell_t *cp = maze_get_cell_addr(mp, cr, cc);

	*cp |= SOLUTION;
	if (maze_get_cell_distance(mp, cr, cc) == 1)
		ABORT();
	if (!maze_is_prev_cell(mp, cr, cc, cr - 1, cc, nr, nc) &&
	    !maze_is_prev_cell(mp, cr, cc, cr + 1, cc, nr, nc) &&
	    !maze_is_prev_cell(mp, cr, cc, cr, cc - 1, nr, nc) &&
	    !maze_is_prev_cell(mp, cr, cc, cr, cc + 1, nr, nc))
		ABORT();
}
Пример #4
0
/*
 * Mark the subsolution located by a interior thread, in other words, a
 * thread other than the ones that started at the beginning and end cells.
 */
int maze_mark_subsolution(struct maze *mp, int r1, int c1, int r2, int c2)
{
	int cr1 = r1;
	int cc1 = c1;
	int cr2 = r2;
	int cc2 = c2;
	cell_t *cp;
	int d1 = maze_get_cell_distance(mp, cr1, cc1);
	int d2 = maze_get_cell_distance(mp, cr2, cc2);
	int nr;
	int nc;
	int s = 0;

	for (;;) {
		if (maze_get_cell_tid(mp, cr1, cc1) !=
		    maze_get_cell_tid(mp, cr2, cc2))
		    	ABORT();
		if (cr1 == cr2 && cc1 == cc2) {
			cp = maze_get_cell_addr(mp, cr1, cc1);
			*cp |= SOLUTION;
			return s + 1;
		}
		if (d1 > d2) {
			maze_mark_advance_cell(mp, cr1, cc1, &nr, &nc);
			s++;
			cr1 = nr;
			cc1 = nc;
			d1 = maze_get_cell_distance(mp, cr1, cc1);
		} else if (d1 <= d2 && d2 != 1) {
			maze_mark_advance_cell(mp, cr2, cc2, &nr, &nc);
			s++;
			cr2 = nr;
			cc2 = nc;
			d2 = maze_get_cell_distance(mp, cr2, cc2);
		} else
			ABORT();
	}
}
Пример #5
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;
}
Пример #6
0
/*
 * Pick a next cell, no particular preference as to direction, so go
 * along a row if possible to take advantage of cache affinity by
 * default.  -DCOLFIRST if you want otherwise.
 *
 * Return 0 if there is no adjacent unvisited cell.
 */
int maze_find_any_next_cell(struct maze *mp, int cr, int cc, int *nr, int *nc)
{
	int d = maze_get_cell_distance(mp, cr, cc) + 1;

#ifndef COLFIRST
	if (!maze_try_visit_cell(mp, cr, cc, cr, cc - 1, nr, nc, d))
		return 1;
	if (!maze_try_visit_cell(mp, cr, cc, cr, cc + 1, nr, nc, d))
		return 1;
#endif /* #ifndef COLFIRST */
	if (!maze_try_visit_cell(mp, cr, cc, cr - 1, cc, nr, nc, d))
		return 1;
	if (!maze_try_visit_cell(mp, cr, cc, cr + 1, cc, nr, nc, d))
		return 1;
#ifdef COLFIRST
	if (!maze_try_visit_cell(mp, cr, cc, cr, cc - 1, nr, nc, d))
		return 1;
	if (!maze_try_visit_cell(mp, cr, cc, cr, cc + 1, nr, nc, d))
		return 1;
#endif /* #ifdef COLFIRST */
	return 0;
}
Пример #7
0
/*
 * Mark the maze's solution, working from the end to the beginning.
 * Returns the length of the solution, including the two endpoints.
 * A length of zero implies an unsolvable maze.
 */
int maze_mark_solution(struct maze *mp, int startrow, int startcol,
			int endrow, int endcol)
{
	int cr;
	int cc;
	cell_t *cp;
	int nr = endrow;
	int nc = endcol;

	for (;;) {
		cr = nr;
		cc = nc;
		cp = maze_get_cell_addr(mp, cr, cc);
		*cp |= SOLUTION;
		if (cr == startrow && cc == startcol)
			return maze_get_cell_distance(mp, endrow, endcol);
		if (!maze_is_prev_cell(mp, cr, cc, cr - 1, cc, &nr, &nc) &&
		    !maze_is_prev_cell(mp, cr, cc, cr + 1, cc, &nr, &nc) &&
		    !maze_is_prev_cell(mp, cr, cc, cr, cc - 1, &nr, &nc) &&
		    !maze_is_prev_cell(mp, cr, cc, cr, cc + 1, &nr, &nc))
			ABORT();
	}
}