Exemple #1
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;
}
Exemple #2
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;
	}
}
Exemple #3
0
/*
 * Wall in the specified cell.  This allows easy construction of
 * unsolvable mazes.  Returns 1 on success, and 0 if the specified
 * cell was not in the maze.
 */
int maze_wall_in(struct maze *mp, int row, int col)
{
	if (!maze_cell_exists(mp, row, col))
		return 0;
	if (maze_cells_connected(mp, row, col, row - 1, col))
		maze_build_one_cell_wall(mp, row - 1, col,
					 row, col, row, col, row, col);
	if (maze_cells_connected(mp, row, col, row + 1, col))
		maze_build_one_cell_wall(mp, row + 1, col,
					 row, col, row, col, row, col);
	if (maze_cells_connected(mp, row, col, row, col - 1))
		maze_build_one_cell_wall(mp, row, col - 1,
					 row, col, row, col, row, col);
	if (maze_cells_connected(mp, row, col, row, col + 1))
		maze_build_one_cell_wall(mp, row, col + 1,
					 row, col, row, col, row, col);
	return 1;
}
Exemple #4
0
int main(int argc, char *argv[])
{
	unsigned long long dt;
	int i = 1;
	struct maze *mp;
	double q;
	int solved = 1;
	char *binin = NULL;
	char *binout = NULL;
	FILE *figfp = stdout;
	char *figout = NULL;
	int figupc = 300;
	int figupcgiven = 0;
	int figvisit = 0;
	int generate = 0;
	int rows = 41;
	int cols = 32;
	double straightfrac = 0.2;
	double segbends = 4;
	double revisit = 0.2;
	unsigned long seed = current_time();
	int startrow = 0;
	int startcol = 0;
	int endrow = -1;
	int endcol = -1;
	int wallin = 0;
	int wallinrow;
	int wallincol;
	int solve = 1;
	int clear = 0;

	/* Parse arguments. */
	while (i < argc) {
		if (strcmp(argv[i], "--input") == 0) {
			if (generate)
				usage(argv[0],
				      "Conflict: --input and --generate\n");
			if (i >= argc - 1)
				usage(argv[0], "--input requires path name\n");
			binin = argv[++i];
		} else if (strcmp(argv[i], "--output") == 0) {
			if (i >= argc - 1)
				usage(argv[0], "--output requires path name\n");
			binout = argv[++i];
		} else if (strcmp(argv[i], "--fig") == 0) {
			if (i >= argc - 1)
				usage(argv[0], "--fig requires path name\n");
			figout = argv[++i];
			figfp = fopen(figout, "w");
			if (figfp == NULL)
				usage(argv[0], "--fig file unwriteable\n");
		} else if (strcmp(argv[i], "--figupc") == 0) {
			if (i >= argc - 1)
				usage(argv[0],
				      "--figupc requires fig units per cell\n");
			figupc = strtol(argv[++i], NULL, 0);
			if (figupc <= 0)
				usage(argv[0],
				      "--figupc must be non-negative\n");
			figupcgiven = 1;
		} else if (strcmp(argv[i], "--figlinethickness") == 0) {
			if (i >= argc - 1)
				usage(argv[0],
				      "--figlinethickness requires number\n");
			line_thickness = strtol(argv[++i], NULL, 0);
			if (line_thickness <= 0)
				usage(argv[0],
				      "--figlinethickness must be "
				      "non-negative\n");
		} else if (strcmp(argv[i], "--figvisit") == 0) {
			figvisit = 1;
		} else if (strcmp(argv[i], "--nofig") == 0) {
			if (figfp != stdout)
				usage(argv[0], "Conflict: --fig and --nofig\n");
			figfp = NULL;
		} else if (strcmp(argv[i], "--generate") == 0) {
			generate = 1;
			if (binin)
				usage(argv[0],
				      "Conflict: --generate and --input\n");
			if (i < argc - 1 && argv[i + 1][0] != '-') {
				rows = strtol(argv[++i], NULL, 0);
				cols = rows;
			}
			if (i < argc - 1 && argv[i + 1][0] != '-')
				cols = strtol(argv[++i], NULL, 0);
		} else if (strcmp(argv[i], "--gen_sf") == 0) {
			if (i >= argc - 1)
				usage(argv[0],
				      "--gen_sf requires straightfrac\n");
			straightfrac = strtod(argv[++i], NULL);
			if (straightfrac <= 0.0)
				usage(argv[0],
				      "--gen_sf requires straightfrac > 0");
		} else if (strcmp(argv[i], "--gen_sb") == 0) {
			if (i >= argc - 1)
				usage(argv[0], "--gen_sb requires segbends\n");
			segbends = strtod(argv[++i], NULL);
			if (segbends < 0.0)
				usage(argv[0],
				      "--gen_sb requires segbends >= 0\n");
		} else if (strcmp(argv[i], "--gen_rv") == 0) {
			if (i >= argc - 1)
				usage(argv[0], "--gen_rv requires revisit\n");
			revisit = strtod(argv[++i], NULL);
			if (revisit < 0.0 || revisit > 1.0)
				usage(argv[0], "--gen_rv: 0 <= revisit <= 1\n");
		} else if (strcmp(argv[i], "--seed") == 0) {
			if (i >= argc - 1)
				usage(argv[0], "--seed requires integer\n");
			seed = strtol(argv[++i], NULL, 0);
		} else if (strcmp(argv[i], "--solve") == 0) {
			solve = 1;
		} else if (strcmp(argv[i], "--start") == 0) {
			if (i >= argc - 2)
				usage(argv[0], "--start requires position\n");
			startrow = strtol(argv[++i], NULL, 0);
			startcol = strtol(argv[++i], NULL, 0);
		} else if (strcmp(argv[i], "--end") == 0) {
			if (i >= argc - 2)
				usage(argv[0], "--end requires position\n");
			endrow = strtol(argv[++i], NULL, 0);
			endcol = strtol(argv[++i], NULL, 0);
		} else if (strcmp(argv[i], "--wall-in") == 0) {
			if (i >= argc - 2)
				usage(argv[0], "--wall-in requires position\n");
			if (wallin)
				usage(argv[0], "Multiple --wall-in commands\n");
			wallin = 1;
			wallinrow = strtol(argv[++i], NULL, 0);
			wallincol = strtol(argv[++i], NULL, 0);
		} else if (strcmp(argv[i], "--nosolve") == 0) {
			solve = 0;
		} else if (strcmp(argv[i], "--clear") == 0) {
			clear = 1;
		} else if (strcmp(argv[i], "--help") == 0) {
			usage(argv[0], "");
		} else {
			int j = maze_solve_parse(i, argc, argv);

			if (i == j)
				usage(argv[0], "Unrecognized argument: %s\n",
				      argv[i]);
			i = j - 1;
		}
		i++;
	}

	/* Get maze. */
	srandom(seed);
	if (generate) {
		if (startrow < 0)
			startrow = maze_row_col_frac(rows, 1, -startrow);
		if (startcol < 0)
			startcol = maze_row_col_frac(cols, 1, -startcol);
		if (endrow < 0)
			endrow = maze_row_col_frac(rows, 1, -endrow);
		if (endcol < 0)
			endcol = maze_row_col_frac(cols, 1, -endcol);
		mp = maze_create(rows, cols, startrow, startcol,
				 straightfrac, segbends, revisit);
	} else if (binin != NULL) {
		mp = maze_binary_in(binin);
		if (mp == NULL)
			usage(argv[0], "Bad --input file\n");
		if (clear)
			maze_unvisit_all(mp);
		if (startrow < 0)
			startrow = maze_row_col_frac(mp->nrows, 1, -startrow);
		if (startcol < 0)
			startcol = maze_row_col_frac(mp->ncols, 1, -startcol);
		if (endrow < 0)
			endrow = maze_row_col_frac(mp->nrows, 1, -endrow);
		if (endcol < 0)
			endcol = maze_row_col_frac(mp->ncols, 1, -endcol);
	} else {
		usage(argv[0], "Must specify one of --input and --generate\n");
	}
	if (startrow == endrow && startcol == endcol)
		usage(argv[0], "--start and --end both (%d, %d)\n",
		      startrow, startcol);

	/* Wall-in the specified cell. */
	if (wallin) {
		if (wallinrow < 0)
			wallinrow = maze_row_col_frac(mp->nrows, 1, -wallinrow);
		if (wallincol < 0)
			wallincol = maze_row_col_frac(mp->ncols, 1, -wallincol);
		if (!maze_wall_in(mp, wallinrow, wallincol))
			usage(argv[0],
			      "--wall-in %d %d must be within maze, "
			      "limits: %d %d.\n",
			      wallinrow, wallincol, mp->nrows, mp->ncols);
	}

	/* Solve maze. */
	if (solve) {
		maze_unvisit_all(mp);  /* Erase any prior solution. */
		if (!maze_cell_exists(mp, startrow, startcol)) {
			fprintf(stderr,
				"Start position %d %d must be within maze: "
				"(0-%d, 0-%d)\n",
				startrow, startcol,
				mp->nrows - 1, mp->ncols - 1);
			exit(EXIT_FAILURE);
		}
		if (!maze_cell_exists(mp, endrow, endcol)) {
			fprintf(stderr,
				"End position %d %d must be within maze: "
				"(0-%d, 0-%d)\n",
				endrow, endcol, mp->nrows - 1, mp->ncols - 1);
			exit(EXIT_FAILURE);
		}
		q = maze_solve(mp, startrow, startcol, endrow, endcol, &dt);
		if (q == 0) {
			fprintf(stderr, "Maze has no solution\n");
			solved = 0;
		}
		q = q / (double)(abs(endrow - startrow) +
				 abs(endcol - startcol) + 1);
		fprintf(stderr,
			"Maze quality: %g  dt = %g visits = %d/%d (%g%%)\n",
			q, ((double)dt) / (double)1000000, mp->vi,
			mp->nrows * mp->ncols,
			mp->vi * 100. / (double)(mp->nrows * mp->ncols));
	}

	/* Output binary, if requested. */
	if (binout != NULL)
		maze_binary_out(binout, mp);

	/* Output fig, if requested. */
	if (figfp != NULL) {
		if (!figupcgiven) {  /* Set up for US Letter. */
			int fr = 300 * 41 / mp->nrows;
			int fc = 300 * 32 / mp->ncols;

			if (fr < fc)
				figupc = fr;
			else
				figupc = fc;
		}
		maze_to_fig(figfp, mp, figupc, !solved || figvisit);
	}

	return EXIT_SUCCESS;
}
Exemple #5
0
/*
 * Has the specified cell been visited?  If it does not exist, that
 * counts as having been visited.
 */
int maze_cell_visited(struct maze *mp, int row, int col)
{
	if (!maze_cell_exists(mp, row, col))
		return 1;
	return !!(maze_get_cell(mp, row, col) & VISITED);
}