lpc-astar-2.0.0/
// Sample implementation of A* search on a simple 2D Cartesian space
//
// v1.0   2007-10-06, Chaos of Lost Souls MUD, http://lostsouls.org/
// v1.1   2013-08-18, Chaos; graph terminology update
// v2.0   2015-06-17, Chaos: adapt for interface changes, improve style

#include <astar.h>

inherit "/mod/algorithm/astar";

#define Map_Min_X   1
#define Map_Max_X   20
#define Map_Min_Y   1
#define Map_Max_Y   10
#define X           0
#define Y           1

// Neighbors rule produces nodes and edges for the points adjacent to us.

mixed * astar_neighbors_rule(mixed * pathfind) {
	int * node = pathfind[Astar_Pathfind_Active_Node];
	mixed * out = ({});
	if(node[X] > Map_Min_X)
		out += ({
		    ({
				({ node[X] - 1, node[Y] }),     // Adjacent node
				({ -1, 0 }),                    // Edge to adjacent node
				1,                              // Cost of edge
			})
		});
	if(node[X] < Map_Max_X)
		out += ({
		    ({
				({ node[X] + 1, node[Y] }),     // Adjacent node
				({ 1, 0 }),                     // Edge to adjacent node
				1,                              // Cost of edge
			}),
		});
	if(node[Y] > Map_Min_Y)
		out += ({
		    ({
				({ node[X], node[Y] - 1 }),     // Adjacent node
				({ 0, -1 }),                    // Edge to adjacent node
				1,                              // Cost of edge
			}),
		});
	if(node[Y] < Map_Max_Y)
		out += ({
		    ({
				({ node[X], node[Y] + 1 }),     // Adjacent node
				({ 0, 1 }),                     // Edge to adjacent node
				1,                              // Cost of edge
			}),
		});
	return out;
}

// Distance rule calculates the distance from a point to the target
// node.  Using the Pythagorean Theorem, yo.

float astar_distance_rule(mixed * pathfind) {
	int * a = pathfind[Astar_Pathfind_Active_Node];
	int * b = pathfind[Astar_Pathfind_To];
	int dx = a[X] - b[X];
	int dy = a[Y] - b[Y];
	return sqrt(dx * dx + dy * dy);
}

// Node key rule gives us a unique value corresponding to a node that
// can be reliably used as a mapping key.  Since we're using arbitrary
// two-element arrays as nodes, and arrays are pointers that will give
// unpredictable behavior when used as mapping keys, we need to use this
// so the algorithm can tell where it's been.

int astar_node_key_rule(int * node) {
	return (node[X] << 16) | node[Y];
}

// Run limit rule tells the algorithm when to stop running and continue
// on a call_out.

int astar_run_limit_rule(mixed * pathfind) {
	return get_eval_cost() < __MAX_EVAL_COST__ / 2;
}

// Set up the A* module.

void create() {
	set_astar_neighbors_rule(#'astar_neighbors_rule);
	set_astar_distance_rule(#'astar_distance_rule);
	set_astar_node_key_rule(#'astar_node_key_rule);
	set_astar_run_limit_rule(#'astar_run_limit_rule);
	set_astar_caching(1);
}

// This is our callback when pathfinding completes (for better or worse);
// it displays the path to this_player().

void end_random_pathfind(mixed * pathfind) {
	mixed res = pathfind[Astar_Pathfind_Result];
	if(pointerp(res)) {
		mixed * path = res;
		mixed * nodes = path[Astar_Path_Nodes];
		int last = path[Astar_Path_Length] - 1;
		write("Path from " + nodes[0][X] + "," + nodes[0][Y] + " to " +
			nodes[last][X] + "," + nodes[last][Y] + ":\n");
		for(int ix = 0; ix <= last; ix++) {
			mixed * node = nodes[ix];
			write("    " + node[X] + "," + node[Y] + "\n");
		}
	} else {
		write("Cannot find path: result " + res + "\n");
	}
}

// Picks two random points in our coordinate space and pathfinds between
// them.

void start_random_pathfind() {
	int * start = ({
	    Map_Min_X + random(Map_Max_X - Map_Min_X + 1),
		Map_Min_Y + random(Map_Max_Y - Map_Min_Y + 1),
	});
	int * target = ({
	    Map_Min_X + random(Map_Max_X - Map_Min_X + 1),
		Map_Min_Y + random(Map_Max_Y - Map_Min_Y + 1),
	});
	astar_find_path(start, target, 0, #'end_random_pathfind);
}