diff options
author | Max Horn | 2009-02-24 05:23:42 +0000 |
---|---|---|
committer | Max Horn | 2009-02-24 05:23:42 +0000 |
commit | 325d2ec66b15d63f44e5e11239c18503e7021942 (patch) | |
tree | 3cc1301b037dcda54cac27cfa0fc26d50215f7c3 /engines | |
parent | 8c9bd00b510cf6f4b014927223690ea5001d151d (diff) | |
download | scummvm-rg350-325d2ec66b15d63f44e5e11239c18503e7021942.tar.gz scummvm-rg350-325d2ec66b15d63f44e5e11239c18503e7021942.tar.bz2 scummvm-rg350-325d2ec66b15d63f44e5e11239c18503e7021942.zip |
SCI: More pathfinding cleanup
svn-id: r38830
Diffstat (limited to 'engines')
-rw-r--r-- | engines/sci/engine/kpathing.cpp | 208 |
1 files changed, 101 insertions, 107 deletions
diff --git a/engines/sci/engine/kpathing.cpp b/engines/sci/engine/kpathing.cpp index 45bd19a32d..1fc3227eb7 100644 --- a/engines/sci/engine/kpathing.cpp +++ b/engines/sci/engine/kpathing.cpp @@ -38,36 +38,35 @@ namespace Sci { #define POLY_LAST_POINT 0x7777 #define POLY_POINT_SIZE 4 -#define POLY_GET_POINT(p, i, x, y) \ - do { \ - x = getInt16((p) + (i) * POLY_POINT_SIZE); \ - y = getInt16((p) + (i) * POLY_POINT_SIZE + 2); \ - } while (0) - -#define POLY_SET_POINT(p, i, x, y) \ - do { \ - putInt16((p) + (i) * POLY_POINT_SIZE, x); \ - putInt16((p) + (i) * POLY_POINT_SIZE + 2, y); \ - } while (0) - -#define POLY_GET_POINT_REG_T(p, i, x, y) \ - do { \ - x = KP_SINT((p)[(i) * 2]); \ - y = KP_SINT((p)[(i) * 2 + 1]); \ - } while (0) +static void POLY_GET_POINT(byte *p, int i, Common::Point &pt) { + pt.x = getInt16((p) + (i) * POLY_POINT_SIZE); + pt.y = getInt16((p) + (i) * POLY_POINT_SIZE + 2); +} + +static void POLY_SET_POINT(byte *p, int i, const Common::Point &pt) { + putInt16((p) + (i) * POLY_POINT_SIZE, pt.x); + putInt16((p) + (i) * POLY_POINT_SIZE + 2, pt.y); +} + +static void POLY_GET_POINT_REG_T(reg_t *p, int i, Common::Point &pt) { + pt.x = KP_SINT((p)[(i) * 2]); + pt.y = KP_SINT((p)[(i) * 2 + 1]); +} // SCI-defined polygon types -#define POLY_TOTAL_ACCESS 0 -#define POLY_NEAREST_ACCESS 1 -#define POLY_BARRED_ACCESS 2 -#define POLY_CONTAINED_ACCESS 3 +enum { + POLY_TOTAL_ACCESS = 0, + POLY_NEAREST_ACCESS = 1, + POLY_BARRED_ACCESS = 2, + POLY_CONTAINED_ACCESS = 3 +}; // Polygon containment types -#define CONT_OUTSIDE 0 -#define CONT_ON_EDGE 1 -#define CONT_INSIDE 2 - -#define POINT_EQUAL(A, B) (((A).x == (B).x) && ((A).y == (B).y)) +enum { + CONT_OUTSIDE = 0, + CONT_ON_EDGE = 1, + CONT_INSIDE = 2 +}; #define HUGE_DISTANCE 1e10 @@ -78,12 +77,14 @@ namespace Sci { #define IS_VISIBLE(S, P, Q) (((S)->vis_matrix[(P) * VIS_MATRIX_ROW_SIZE((S)->vertices) \ + (Q) / 8] & (1 << ((Q) % 8))) != 0) -#define VERTEX_HAS_EDGES(V) ((V) != CLIST_NEXT(V, entries)) +#define VERTEX_HAS_EDGES(V) ((V) != CLIST_NEXT(V)) // Error codes -#define PF_OK 0 -#define PF_ERROR -1 -#define PF_FATAL -2 +enum { + PF_OK = 0, + PF_ERROR = -1, + PF_FATAL = -2 +}; // Floating point struct struct FloatPoint { @@ -168,15 +169,15 @@ public: /* Circular list definitions. */ -#define CLIST_FOREACH(var, head, field) \ +#define CLIST_FOREACH(var, head) \ for ((var) = (head)->first(); \ (var); \ - (var) = ((var)->field.cle_next == (head)->first() ? \ - NULL : (var)->field.cle_next)) + (var) = ((var)->entries.cle_next == (head)->first() ? \ + NULL : (var)->entries.cle_next)) /* Circular list access methods. */ -#define CLIST_NEXT(elm, field) ((elm)->field.cle_next) -#define CLIST_PREV(elm, field) ((elm)->field.cle_prev) +#define CLIST_NEXT(elm) ((elm)->entries.cle_next) +#define CLIST_PREV(elm) ((elm)->entries.cle_prev) struct Polygon { @@ -243,9 +244,9 @@ static Common::Point read_point(unsigned char *list, int is_reg_t, int offset) { Common::Point point; if (!is_reg_t) { - POLY_GET_POINT(list, offset, point.x, point.y); + POLY_GET_POINT(list, offset, point); } else { - POLY_GET_POINT_REG_T((reg_t *)list, offset, point.x, point.y); + POLY_GET_POINT_REG_T((reg_t *)list, offset, point); } return point; @@ -496,15 +497,15 @@ static int contained(Common::Point p, Polygon *polygon) { Vertex *vertex; // Iterate over edges - CLIST_FOREACH(vertex, &polygon->vertices, entries) { + CLIST_FOREACH(vertex, &polygon->vertices) { Common::Point v1 = vertex->v; - Common::Point v2 = CLIST_NEXT(vertex, entries)->v; + Common::Point v2 = CLIST_NEXT(vertex)->v; // Flags for ray straddling left and right int rstrad, lstrad; // Check if p is a vertex - if (POINT_EQUAL(p, v1)) + if (p == v1) return CONT_ON_EDGE; // Check if edge straddles the ray @@ -557,11 +558,11 @@ static int polygon_area(Polygon *polygon) { Vertex *v; int size = 0; - v = CLIST_NEXT(first, entries); + v = CLIST_NEXT(first); - while (CLIST_NEXT(v, entries) != first) { - size += area(first->v, v->v, CLIST_NEXT(v, entries)->v); - v = CLIST_NEXT(v, entries); + while (CLIST_NEXT(v) != first) { + size += area(first->v, v->v, CLIST_NEXT(v)->v); + v = CLIST_NEXT(v); } return size; @@ -572,7 +573,6 @@ static void fix_vertex_order(Polygon *polygon) { // polygons should have their vertices ordered clockwise, all other types // anti-clockwise // Parameters: (Polygon *) polygon: The polygon - // Returns : (void) int area = polygon_area(polygon); // When the polygon area is positive the vertices are ordered @@ -606,7 +606,7 @@ static int vertex_compare(const void *a, const void *b) { Common::Point p1 = (*(Vertex **) a)->v; Common::Point p2 = (*(Vertex **) b)->v; - if (POINT_EQUAL(p1, p2)) + if (p1 == p2) return 0; // Points above p0 have larger angle than points below p0 @@ -650,17 +650,15 @@ static void clockwise(Vertex *v, Common::Point *p1, Common::Point *p2) { // Returns : (void) // (Common::Point) *p1: The first point in clockwise order // (Common::Point) *p2: The second point in clockwise order - Vertex *w = CLIST_NEXT(v, entries); + Vertex *w = CLIST_NEXT(v); if (left_on(vertex_cur->v, w->v, v->v)) { *p1 = v->v; *p2 = w->v; - return; + } else { + *p1 = w->v; + *p2 = v->v; } - - *p1 = w->v; - *p2 = v->v; - return; } static int edge_compare(const void *a, const void *b) { @@ -679,8 +677,8 @@ static int edge_compare(const void *a, const void *b) { // Order vertices clockwise so we know vertex_cur is to the right of // directed edges (v1, v2) and (w1, w2) - clockwise((Vertex *) a, &v1, &v2); - clockwise((Vertex *) b, &w1, &w2); + clockwise((Vertex *)a, &v1, &v2); + clockwise((Vertex *)b, &w1, &w2); // As the edges do not properly intersect one edge must lie entirely // to one side of another. Note that the special case where edges are @@ -712,8 +710,8 @@ static int inside(Common::Point p, Vertex *vertex) { // the polygon, locally at the vertex. 0 otherwise // Check that it's not a single-vertex polygon if (VERTEX_HAS_EDGES(vertex)) { - Common::Point prev = CLIST_PREV(vertex, entries)->v; - Common::Point next = CLIST_NEXT(vertex, entries)->v; + Common::Point prev = CLIST_PREV(vertex)->v; + Common::Point next = CLIST_NEXT(vertex)->v; Common::Point cur = vertex->v; if (left(prev, cur, next)) { @@ -779,7 +777,6 @@ static void visible_vertices(PathfindingState *s, Vertex *vert) { // updates the visibility matrix // Parameters: (PathfindingState *) s: The pathfinding state // (Vertex *) vert: The vertex - // Returns : (void) aatree_t *tree = aatree_new(); Common::Point p = vert->v; Polygon *polygon; @@ -799,13 +796,13 @@ static void visible_vertices(PathfindingState *s, Vertex *vert) { // Check that there is more than one vertex. if (VERTEX_HAS_EDGES(vertex)) - CLIST_FOREACH(vertex, &polygon->vertices, entries) { + CLIST_FOREACH(vertex, &polygon->vertices) { Common::Point high, low; // Add edges that intersect the initial position of the sweeping line clockwise(vertex, &high, &low); - if ((high.y < p.y) && (low.y >= p.y) && !POINT_EQUAL(low, p)) + if ((high.y < p.y) && (low.y >= p.y) && (low != p)) aatree_insert(vertex, &tree, edge_compare); } } @@ -824,13 +821,13 @@ static void visible_vertices(PathfindingState *s, Vertex *vert) { SET_VISIBLE(s, vert->idx, vert_sorted[i]->idx); // Delete anti-clockwise edges from tree - v1 = CLIST_PREV(vert_sorted[i], entries); + v1 = CLIST_PREV(vert_sorted[i]); if (left(p, vert_sorted[i]->v, v1->v)) { if (aatree_delete(v1, &tree, edge_compare)) sciprintf("[avoidpath] Error: failed to remove edge from tree\n"); } - v1 = CLIST_NEXT(vert_sorted[i], entries); + v1 = CLIST_NEXT(vert_sorted[i]); if (left(p, vert_sorted[i]->v, v1->v)) { if (aatree_delete(vert_sorted[i], &tree, edge_compare)) sciprintf("[avoidpath] Error: failed to remove edge from tree\n"); @@ -840,11 +837,11 @@ static void visible_vertices(PathfindingState *s, Vertex *vert) { if ((i < s->vertices - 1) && !collinear(p, vert_sorted[i]->v, vert_sorted[i + 1]->v)) { int j; for (j = i; (j >= 1) && collinear(p, vert_sorted[i]->v, vert_sorted[j]->v); j--) { - v1 = CLIST_PREV(vert_sorted[j], entries); + v1 = CLIST_PREV(vert_sorted[j]); if (left(vert_sorted[j]->v, p, v1->v)) aatree_insert(v1, &tree, edge_compare); - v1 = CLIST_NEXT(vert_sorted[j], entries); + v1 = CLIST_NEXT(vert_sorted[j]); if (left(vert_sorted[j]->v, p, v1->v)) aatree_insert(vert_sorted[j], &tree, edge_compare); } @@ -928,9 +925,9 @@ static int near_point(Common::Point p, Polygon *polygon, Common::Point *ret) { FloatPoint near_p; float dist = HUGE_DISTANCE; - CLIST_FOREACH(vertex, &polygon->vertices, entries) { + CLIST_FOREACH(vertex, &polygon->vertices) { Common::Point p1 = vertex->v; - Common::Point p2 = CLIST_NEXT(vertex, entries)->v; + Common::Point p2 = CLIST_NEXT(vertex)->v; float w, h, l, u; FloatPoint new_point; float new_dist; @@ -978,7 +975,7 @@ static int intersection(Common::Point a, Common::Point b, Vertex *vertex, FloatP // Numerator and denominator of equations float num, denom; Common::Point c = vertex->v; - Common::Point d = CLIST_NEXT(vertex, entries)->v; + Common::Point d = CLIST_NEXT(vertex)->v; denom = a.x * (float)(d.y - c.y) + b.x * (float)(c.y - d.y) + d.x * (float)(b.y - a.y) + c.x * (float)(a.y - b.y); @@ -1024,7 +1021,7 @@ static int nearest_intersection(PathfindingState *s, Common::Point p, Common::Po polygon = *it; Vertex *vertex; - CLIST_FOREACH(vertex, &polygon->vertices, entries) { + CLIST_FOREACH(vertex, &polygon->vertices) { float new_dist; FloatPoint new_isec; @@ -1042,7 +1039,7 @@ static int nearest_intersection(PathfindingState *s, Common::Point p, Common::Po // Skip this edge if we hit it from the // inside of the polygon - if (!left(vertex->v, CLIST_NEXT(vertex, entries)->v, q)) + if (!left(vertex->v, CLIST_NEXT(vertex)->v, q)) continue; if (intersection(p, q, vertex, &new_isec) != PF_OK) @@ -1099,7 +1096,7 @@ static int fix_point(PathfindingState *s, Common::Point p, Common::Point *ret, P if (near_point(p, (*it), &near_p) == PF_OK) { *ret = near_p; - if (!POINT_EQUAL(p, *ret)) + if (p != *ret) *ret_pol = *it; return PF_OK; @@ -1128,9 +1125,10 @@ static Vertex *merge_point(PathfindingState *s, Common::Point v) { // Check for already existing vertex for (PolygonList::iterator it = s->polygons.begin(); it != s->polygons.end(); ++it) { polygon = *it; - CLIST_FOREACH(vertex, &polygon->vertices, entries) - if (POINT_EQUAL(vertex->v, v)) - return vertex; + CLIST_FOREACH(vertex, &polygon->vertices) { + if (vertex->v == v) + return vertex; + } } v_new = vertex_new(v); @@ -1139,14 +1137,15 @@ static Vertex *merge_point(PathfindingState *s, Common::Point v) { for (PolygonList::iterator it = s->polygons.begin(); it != s->polygons.end(); ++it) { polygon = *it; // Skip single-vertex polygons - if (VERTEX_HAS_EDGES(polygon->vertices.first())) - CLIST_FOREACH(vertex, &polygon->vertices, entries) { - Vertex *next = CLIST_NEXT(vertex, entries); - - if (between(vertex->v, next->v, v)) { - // Split edge by adding vertex - polygon->vertices.insertAfter(vertex, v_new); - return v_new; + if (VERTEX_HAS_EDGES(polygon->vertices.first())) { + CLIST_FOREACH(vertex, &polygon->vertices) { + Vertex *next = CLIST_NEXT(vertex); + + if (between(vertex->v, next->v, v)) { + // Split edge by adding vertex + polygon->vertices.insertAfter(vertex, v_new); + return v_new; + } } } } @@ -1184,7 +1183,6 @@ static Polygon *convert_polygon(EngineState *s, reg_t polygon) { static void free_polygon(Polygon *polygon) { // Frees a polygon and its vertices // Parameters: (Polygon *) polygons: The polygon - // Returns : (void) while (!polygon->vertices.empty()) { Vertex *vertex = polygon->vertices.first(); polygon->vertices.remove(vertex); @@ -1197,7 +1195,6 @@ static void free_polygon(Polygon *polygon) { static void free_pf_state(PathfindingState *p) { // Frees a pathfinding state // Parameters: (PathfindingState *) p: The pathfinding state - // Returns : (void) free(p->vertex_index); free(p->vis_matrix); @@ -1213,7 +1210,6 @@ static void change_polygons_opt_0(PathfindingState *s) { // support). Totally accessible polygons are removed and near-point // accessible polygons are changed into totally accessible polygons. // Parameters: (PathfindingState *) s: The pathfinding state - // Returns : (void) PolygonList::iterator it = s->polygons.begin(); while (it != s->polygons.end()) { @@ -1309,7 +1305,7 @@ static PathfindingState *convert_polygon_set(EngineState *s, reg_t poly_list, Co polygon = *it; Vertex *vertex; - CLIST_FOREACH(vertex, &polygon->vertices, entries) { + CLIST_FOREACH(vertex, &polygon->vertices) { vertex->idx = count; pf_s->vertex_index[count++] = vertex; } @@ -1326,15 +1322,15 @@ static PathfindingState *convert_polygon_set(EngineState *s, reg_t poly_list, Co static void visibility_graph(PathfindingState *s) { // Computes the visibility graph // Parameters: (PathfindingState *) s: The pathfinding state - // Returns : (void) Polygon *polygon; for (PolygonList::iterator it = s->polygons.begin(); it != s->polygons.end(); ++it) { polygon = *it; Vertex *vertex; - CLIST_FOREACH(vertex, &polygon->vertices, entries) - visible_vertices(s, vertex); + CLIST_FOREACH(vertex, &polygon->vertices) { + visible_vertices(s, vertex); + } } } @@ -1354,12 +1350,11 @@ static int intersecting_polygons(PathfindingState *s) { continue; // Skip neighbouring edges - if ((CLIST_NEXT(v1, entries) == v2) - || CLIST_PREV(v1, entries) == v2) + if ((CLIST_NEXT(v1) == v2) || CLIST_PREV(v1) == v2) continue; - if (intersect(v1->v, CLIST_NEXT(v1, entries)->v, - v2->v, CLIST_NEXT(v2, entries)->v)) + if (intersect(v1->v, CLIST_NEXT(v1)->v, + v2->v, CLIST_NEXT(v2)->v)) return 1; } } @@ -1373,7 +1368,6 @@ static void dijkstra(PathfindingState *s) { // vertex_end back to vertex_start. If no path exists vertex_end->path_prev // will be NULL // Parameters: (PathfindingState *) s: The pathfinding state - // Returns : (void) Polygon *polygon; // Vertices of which the shortest path is known @@ -1387,7 +1381,7 @@ static void dijkstra(PathfindingState *s) { polygon = *it; Vertex *vertex; - CLIST_FOREACH(vertex, &polygon->vertices, entries) { + CLIST_FOREACH(vertex, &polygon->vertices) { remain.push_front(vertex); } } @@ -1459,12 +1453,12 @@ static reg_t output_path(PathfindingState *p, EngineState *s) { oref = s->seg_manager->allocDynmem(POLY_POINT_SIZE * 3, AVOIDPATH_DYNMEM_STRING, &output); if (p->keep_start) - POLY_SET_POINT(oref, 0, p->start.x, p->start.y); + POLY_SET_POINT(oref, 0, p->start); else - POLY_SET_POINT(oref, 0, p->vertex_start->v.x, p->vertex_start->v.y); + POLY_SET_POINT(oref, 0, p->vertex_start->v); - POLY_SET_POINT(oref, 1, p->vertex_start->v.x, p->vertex_start->v.y); - POLY_SET_POINT(oref, 2, POLY_LAST_POINT, POLY_LAST_POINT); + POLY_SET_POINT(oref, 1, p->vertex_start->v); + POLY_SET_POINT(oref, 2, Common::Point(POLY_LAST_POINT, POLY_LAST_POINT)); return output; } @@ -1478,26 +1472,26 @@ static reg_t output_path(PathfindingState *p, EngineState *s) { oref = s->seg_manager->allocDynmem(POLY_POINT_SIZE * (path_len + 1 + p->keep_start + p->keep_end), AVOIDPATH_DYNMEM_STRING, &output); // Sentinel - POLY_SET_POINT(oref, path_len + p->keep_start + p->keep_end, POLY_LAST_POINT, POLY_LAST_POINT); + POLY_SET_POINT(oref, path_len + p->keep_start + p->keep_end, Common::Point(POLY_LAST_POINT, POLY_LAST_POINT)); // Add original start and end points if needed if (p->keep_end) - POLY_SET_POINT(oref, path_len + p->keep_start, p->end.x, p->end.y); + POLY_SET_POINT(oref, path_len + p->keep_start, p->end); if (p->keep_start) - POLY_SET_POINT(oref, 0, p->start.x, p->start.y); + POLY_SET_POINT(oref, 0, p->start); i = path_len + p->keep_start - 1; if (unreachable) { // Return straight trajectory from start to end - POLY_SET_POINT(oref, i - 1, p->vertex_start->v.x, p->vertex_start->v.y); - POLY_SET_POINT(oref, i, p->vertex_end->v.x, p->vertex_end->v.y); + POLY_SET_POINT(oref, i - 1, p->vertex_start->v); + POLY_SET_POINT(oref, i, p->vertex_end->v); return output; } vertex = p->vertex_end; while (vertex) { - POLY_SET_POINT(oref, i, vertex->v.x, vertex->v.y); + POLY_SET_POINT(oref, i, vertex->v); vertex = vertex->path_prev; i--; } @@ -1506,7 +1500,7 @@ static reg_t output_path(PathfindingState *p, EngineState *s) { sciprintf("[avoidpath] Returning path:"); for (i = 0; i < path_len + p->keep_start + p->keep_end; i++) { Common::Point pt; - POLY_GET_POINT(oref, i, pt.x, pt.y); + POLY_GET_POINT(oref, i, pt); sciprintf(" (%i, %i)", pt.x, pt.y); } sciprintf("\n"); @@ -1582,9 +1576,9 @@ reg_t kAvoidPath(EngineState *s, int funct_nr, int argc, reg_t *argv) { oref = s->seg_manager->allocDynmem(POLY_POINT_SIZE * 3, AVOIDPATH_DYNMEM_STRING, &output); - POLY_SET_POINT(oref, 0, start.x, start.y); - POLY_SET_POINT(oref, 1, end.x, end.y); - POLY_SET_POINT(oref, 2, POLY_LAST_POINT, POLY_LAST_POINT); + POLY_SET_POINT(oref, 0, start); + POLY_SET_POINT(oref, 1, end); + POLY_SET_POINT(oref, 2, Common::Point(POLY_LAST_POINT, POLY_LAST_POINT)); return output; } |