Example #1
0
/* Build a wall if appropriate. */
void maze_build_one_cell_wall(struct maze *mp, int wallrow, int wallcol,
			      int prevrow, int prevcol, int currow, int curcol,
			      int nextrow, int nextcol)
{
	cell_t wallbit;
	cell_t *cp;

	/* If the candidate cell is either prev or next, no wall. */
	if (wallrow == prevrow && wallcol == prevcol)
		return;
	if (wallrow == nextrow && wallcol == nextcol)
		return;

	/* If the wall cell actually exists, we need a wall. */
	if (maze_cell_exists(mp, wallrow, wallcol)) {
		/* Wall in other cell. */
		wallbit = maze_find_wallbit(wallrow, wallcol, currow, curcol);
		cp = maze_get_cell_addr(mp, wallrow, wallcol);
		*cp |= wallbit;
		/* Wall in current cell. */
		wallbit = maze_find_wallbit(currow, curcol, wallrow, wallcol);
		cp = maze_get_cell_addr(mp, currow, curcol);
		*cp |= wallbit;
	}
}
Example #2
0
/* Remove a wall to allow another maze segment to be constructed. */
void maze_remove_wall(struct maze *mp, int currow, int curcol,
		      int otherrow, int othercol)
{
	cell_t *cp;

	cp = maze_get_cell_addr(mp, currow, curcol);
	*cp &= ~maze_find_wallbit(currow, curcol, otherrow, othercol);
	cp = maze_get_cell_addr(mp, otherrow, othercol);
	*cp &= ~maze_find_wallbit(otherrow, othercol, currow, curcol);
}
Example #3
0
/*
 * Assign a child-thread starting point within the maze.  Return 1 if
 * successful, return 0 if not.  For example, if some other thread
 * already is starting at the desired point, a second attempt to assign
 * that same point will fail.  Just ABORT() if invalid starting point
 * given.
 */
int maze_solve_start_assign(struct maze *mp, int tid, int r, int c)
{
	cell_t *cp;
	int i;
	struct maze_child *mcp = mp->msp->mcp;

	/* Die if the point lies outside of the maze. */
	if (!maze_cell_exists(mp, r, c) || tid >= nthreads)
		ABORT();

	/*
	 * Return 0 if this point is already assigned to some other thread.
	 * Or if some other point is already assigned to this thread, for
	 * that matter.
	 */
	cp = maze_get_cell_addr(mp, r, c);
	if (*cp & VISITED || mcp[tid].startrow != -1)
		return 0;

	/* Assign the point. */
	mcp[tid].startrow = r;
	mcp[tid].startcol = c;
	mcp[tid].visited[0].row = r;
	mcp[tid].visited[0].col = c;
	mcp[tid].vi = 1;
	*cp |= VISITED | tid;
	maze_set_cell_distance(mp, r, c, 1);
	return 1;
}
Example #4
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();
}
Example #5
0
/* Remove visitation, solution, and distance tags to allow maze to be solved. */
void maze_unvisit_all(struct maze *mp)
{
	cell_t *cp;
	int i;
	int j;

	for (i = 0; i < mp->nrows; i++)
		for (j = 0; j < mp->ncols; j++) {
			cp = maze_get_cell_addr(mp, i, j);
			*cp &= ~(VISITED | SOLUTION | COOKIE);
			maze_set_cell_distance(mp, i, j, 0);
		}
	mp->vi = 0;
}
Example #6
0
/* Visit the specified cell.  Die if already visited. */
void maze_visit_cell(struct maze *mp, int row, int col, int distance)
{
	cell_t *cp = maze_get_cell_addr(mp, row, col);

	if (*cp & VISITED)
		ABORT();
	if (mp->visited != NULL) {
		if (mp->vi >= mp->nrows * mp->ncols)
			ABORT();
		mp->visited[mp->vi].row = row;
		mp->visited[mp->vi].col = col;
		mp->vi++;
	}
	*cp |= VISITED;
	maze_set_cell_distance(mp, row, col, distance);
}
Example #7
0
/* Input a maze in binary form. */
struct maze *maze_binary_in(char *path)
{
	char buf[8];
	FILE *fp = fopen(path, "r");
	int i;
	int j;
	struct maze maze_raw;
	struct maze *mp;
	int t;

	if (fp == NULL) {
		perror("maze_binary_in:");
		fprintf(stderr, "Unable to open %s\n", path);
		return NULL;
	}
	t = fread(buf, sizeof(buf), 1, fp);
	if (strncmp(buf, bin_file_header, sizeof(buf)) != 0) {
		fprintf(stderr, "Bad header in maze_binary_in()\n");
		return NULL;
	}
	t = fread(&maze_raw, sizeof(maze_raw), 1, fp);
	mp = (struct maze *)malloc(sizeof(*mp) +
				   maze_raw.nrows * maze_raw.ncols *
				   sizeof(struct cell));
	if (mp == NULL) {
		fprintf(stderr, "Out of memory\n");
		ABORT();
	}
	*mp = maze_raw;
	mp->visited = (struct rowcol *)malloc(mp->nrows * mp->ncols *
					      sizeof(*mp->visited));
	if (mp->visited == NULL) {
		fprintf(stderr, "Out of memory");
		ABORT();
	}
	mp->vi = 0;
	mp->lastvi = -1;
	for (i = 0; i < mp->nrows; i++)
		for (j = 0; j < mp->ncols; j++)
			t = fread(maze_get_cell_addr(mp, i, j),
				  sizeof(cell_t), 1, fp);
	new_empty_maze_solve(mp);
	return mp;
}
Example #8
0
/*
 * Output a maze in binary form.  This allows different solvers to be
 * compared on an equal footing, particularly when testing cache
 * alignment.  Differences in mazes can wash out large effects, so the
 * ability to compare algorithms running on exactly the same maze
 * can be quite important.
 */
int maze_binary_out(char *path, struct maze *mp)
{
	FILE *fp = fopen(path, "w");
	int i;
	int j;

	if (fp == NULL) {
		perror("maze_binary_out:");
		fprintf(stderr, "Unable to open %s\n", path);
		return 0;
	}
	fwrite(bin_file_header, strlen(bin_file_header) + 1, 1, fp);
	fwrite(mp, sizeof(*mp), 1, fp);
	for (i = 0; i < mp->nrows; i++)
		for (j = 0; j < mp->ncols; j++)
			fwrite(maze_get_cell_addr(mp, i, j), sizeof(cell_t),
			       1, fp);
	return 1;
}
Example #9
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();
	}
}
Example #10
0
/* Attempt to visit a cell, return 0 if it has already been visited.  */
int maze_try_visit_cell(struct maze *mp, int cr, int cc, int tr, int tc,
			int *nextrow, int *nextcol, int distance)
{
	cell_t t;
	cell_t *tp;
	int vi;

	if (!maze_cells_connected(mp, cr, cc, tr, tc))
		return -1;
	tp = maze_get_cell_addr(mp, tr, tc);
	do {
		t = ACCESS_ONCE(*tp);
		if (t & VISITED) {
			record_encounter(mp, cr, cc, tr, tc);
			return 1;
		}
	} while (!__sync_bool_compare_and_swap(tp, t, t | VISITED | myid));
	maze_set_cell_distance(mp, tr, tc, distance);
	*nextrow = tr;
	*nextcol = tc;

	/* If we are solving the maze, mymcp is non-NULL.  */
	if (mymcp != NULL) {
		/* Use this thread's state. */
		vi = mymcp->vi++;
		mymcp->visited[vi].row = tr;
		mymcp->visited[vi].col = tc;
		if (nthreads == 1 &&
		    tr == mymcp->mcsp->endrow && tc == mymcp->mcsp->endcol)
			mymcp->mcsp->done = 1;
	} else {
		/* Use global state. */
		vi = mp->vi++;
		mp->visited[vi].row = tr;
		mp->visited[vi].col = tc;
	}
	return 0;
}
Example #11
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();
	}
}