Point _get_aiPath(const FathomData* fathom, Point start, Point end) { Point move = NULL_POINT; _aStarFathom = fathom; _aStarStartPoint = start; _aStarFinishPoint = end; astar_t *as = astar_new(TILEMAP_WIDTH, TILEMAP_HEIGHT, _get_map_cost, NULL); astar_set_origin (as, 0, 0); astar_set_steering_penalty (as, 0); astar_set_movement_mode (as, DIR_CARDINAL); astar_run (as, start.x, start.y, end.x, end.y); if(astar_have_route(as)) { direction_t * directions, * dir; astar_get_directions (as, &directions); dir = directions; move.x += astar_get_dx(as, *dir); move.y += astar_get_dy(as, *dir); astar_free_directions (directions); } return move; }
int astar_test_main() { astar_t * as; int x0, y0, x1, y1; int result; srand(time(NULL)); // Initialise the map. map_init(); // Allocate an A* context. as = astar_new (WIDTH, HEIGHT, get_map_cost, NULL); // Set the map origin. This allows us to look for a route in // an area smaller than the full game map (by setting the // origin to the origin of that area, and giving astar_new() a // width and height smaller than the full map's. It's // mandatory to set this, even if it's just zero. If you don't set it, // the algorithm will fail with an ASTAR_ORIGIN_NOT_SET error. astar_set_origin (as, 0, 0); // By setting the steering penalty, you penalise direction // changes. This can lead in more direct routes, but it can also make // the algorithm work harder to find a route. The default pre-bundled // value for this cost is 5 (5 less than the cost of moving in the four // cardinal directions). Set it to zero, and the route can meander // more. // astar_set_steering_penalty (as, 5); // If you have a preference for movement in the cardinal directions // only, assign a high cost to the other four directions. If the only // way to get from A to B is to move dianogally, a diagonal move will // still be used though. // astar_set_cost (as, DIR_NE, 100); // astar_set_cost (as, DIR_NW, 100); // astar_set_cost (as, DIR_SW, 100); // astar_set_cost (as, DIR_SE, 100); // Instead, if you want to only route using the four cardinal // directions, say this: // astar_set_movement_mode (as, DIR_CARDINAL); // astar_set_movement_mode (as, DIR_8WAY); // This is the default. // Starting near the upper left corner of the map. x0 = 2; y0 = 1; // Destination near the lower right corner. x1 = WIDTH - 3; y1 = HEIGHT - 1; // Look for a route. result = astar_run (as, x0, y0, x1, y1); // What's the result? printf ("Route from (%d, %d) to (%d, %d). Result: %s (%d)\n", as->x0, as->y0, as->x1, as->y1, as->str_result, result); // Do we have a route? We don't care if the route is partial // or full here. If you need a full route, you must ensure the return // value of astar_run is ASTAR_FOUND. If it isn't, and // astar_have_route() returns non-zero, there's a (possibly partial) // route. if (astar_have_route (as)) { direction_t * directions, * dir; uint32_t i, num_steps; int x, y; num_steps = astar_get_directions (as, &directions); if (result == ASTAR_FOUND) { printf ("We have a route. It has %d step(s).\n", num_steps); } else { printf ("The best compromise route has %d step(s).\n", num_steps); } // The directions start at our (x0, y0) and give us // step-by-step directions (e.g. N, E, NE, N) to // either our (x1, y1) in the case of a full route, or // the best compromise. x = x0; y = y0; dir = directions; for (i = 0; i < num_steps; i++, dir++) { // Convince ourselves that A* never made us go through walls. assert (get_map (x, y) != MAP_WALL); // Mark the route on the map. set_map (x, y, MAP_ROUTE); // Get the next (x, y) co-ordinates of the map. x += astar_get_dx (as, *dir); y += astar_get_dy (as, *dir); } // Mark the starting and ending squares on the map. Do this last. set_map (x0, y0, MAP_START); set_map (x1, y1, MAP_END); // VERY IMPORTANT: MEMORY LEAKS OTHERWISE! astar_free_directions (directions); } // Print the map. map_print(); // Dellocate the A* algorithm context. astar_destroy (as); return 0; }