aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/saga/actor.cpp7
-rw-r--r--engines/saga/actor.h33
-rw-r--r--engines/saga/actor_path.cpp161
3 files changed, 93 insertions, 108 deletions
diff --git a/engines/saga/actor.cpp b/engines/saga/actor.cpp
index c6d3e38732..6ca96c46e9 100644
--- a/engines/saga/actor.cpp
+++ b/engines/saga/actor.cpp
@@ -233,10 +233,9 @@ Actor::Actor(SagaEngine *vm) : _vm(vm) {
_protagStates = NULL;
_protagStatesCount = 0;
- _pathNodeList = _newPathNodeList = NULL;
_pathList = NULL;
- _pathListAlloced = _pathNodeListAlloced = _newPathNodeListAlloced = 0;
- _pathListIndex = _pathNodeListIndex = _newPathNodeListIndex = -1;
+ _pathListAlloced = 0;
+ _pathListIndex = -1;
_centerActor = _protagonist = NULL;
_protagState = 0;
@@ -325,8 +324,6 @@ Actor::~Actor() {
#ifdef ACTOR_DEBUG
free(_debugPoints);
#endif
- free(_pathNodeList);
- free(_newPathNodeList);
free(_pathList);
free(_pathCell);
_actorsStrings.freeMem();
diff --git a/engines/saga/actor.h b/engines/saga/actor.h
index 263ba8a3e7..85df356cec 100644
--- a/engines/saga/actor.h
+++ b/engines/saga/actor.h
@@ -620,6 +620,10 @@ private:
struct PathNode {
Point point;
int link;
+
+ PathNode() : link(0) {}
+ PathNode(const Point &p) : point(p), link(0) {}
+ PathNode(const Point &p, int l) : point(p), link(l) {}
};
Rect _barrierList[ACTOR_BARRIERS_MAX];
@@ -643,34 +647,7 @@ private:
_pathList[_pathListIndex] = point;
}
- int _pathNodeListIndex;
- int _pathNodeListAlloced;
- PathNode *_pathNodeList;
- void addPathNodeListPoint(const Point &point) {
- ++_pathNodeListIndex;
- if (_pathNodeListIndex >= _pathNodeListAlloced) {
- _pathNodeListAlloced += 100;
- _pathNodeList = (PathNode*) realloc(_pathNodeList, _pathNodeListAlloced * sizeof(*_pathNodeList));
-
- }
- _pathNodeList[_pathNodeListIndex].point = point;
- }
-
- int _newPathNodeListIndex;
- int _newPathNodeListAlloced;
- PathNode *_newPathNodeList;
- void incrementNewPathNodeListIndex() {
- ++_newPathNodeListIndex;
- if (_newPathNodeListIndex >= _newPathNodeListAlloced) {
- _newPathNodeListAlloced += 100;
- _newPathNodeList = (PathNode*) realloc(_newPathNodeList, _newPathNodeListAlloced * sizeof(*_newPathNodeList));
-
- }
- }
- void addNewPathNodeListPoint(const PathNode &pathNode) {
- incrementNewPathNodeListIndex();
- _newPathNodeList[_newPathNodeListIndex] = pathNode;
- }
+ Common::Array<PathNode> _pathNodeList;
public:
#ifdef ACTOR_DEBUG
diff --git a/engines/saga/actor_path.cpp b/engines/saga/actor_path.cpp
index 1112f4d853..ad3b0413df 100644
--- a/engines/saga/actor_path.cpp
+++ b/engines/saga/actor_path.cpp
@@ -295,7 +295,6 @@ int Actor::fillPathArray(const Point &fromPoint, const Point &toPoint, Point &be
void Actor::setActorPath(ActorData *actor, const Point &fromPoint, const Point &toPoint) {
Point nextPoint;
int8 direction;
- int i;
_pathListIndex = -1;
addPathListPoint(toPoint);
@@ -320,7 +319,7 @@ void Actor::setActorPath(ActorData *actor, const Point &fromPoint, const Point &
nodeToPath();
removePathPoints();
- for (i = 0; i <= _pathNodeListIndex; i++) {
+ for (uint i = 0; i < _pathNodeList.size(); i++) {
actor->addWalkStepPoint(_pathNodeList[i].point);
}
}
@@ -334,8 +333,8 @@ void Actor::pathToNode() {
point= &_pathList[_pathListIndex];
direction = 0;
- _pathNodeListIndex = -1;
- addPathNodeListPoint(*point);
+ _pathNodeList.clear();
+ _pathNodeList.push_back(PathNode(*point));
for (i = _pathListIndex; i > 0; i--) {
point1 = *point;
@@ -347,13 +346,13 @@ void Actor::pathToNode() {
direction++;
}
if ((point1.x + delta.x != point2.x) || (point1.y + delta.y != point2.y)) {
- addPathNodeListPoint(point1);
+ _pathNodeList.push_back(PathNode(point1));
direction--;
i++;
point++;
}
}
- addPathNodeListPoint(*_pathList);
+ _pathNodeList.push_back(PathNode(*_pathList));
}
int pathLine(Point *pointList, const Point &point1, const Point &point2) {
@@ -414,7 +413,6 @@ int pathLine(Point *pointList, const Point &point1, const Point &point2) {
void Actor::nodeToPath() {
int i;
Point point1, point2;
- PathNode *node;
Point *point;
for (i = 0, point = _pathList; i < _pathListAlloced; i++, point++) {
@@ -424,69 +422,81 @@ void Actor::nodeToPath() {
_pathListIndex = 1;
_pathList[0] = _pathNodeList[0].point;
_pathNodeList[0].link = 0;
- for (i = 0, node = _pathNodeList; i < _pathNodeListIndex; i++) {
- point1 = node->point;
- node++;
- point2 = node->point;
+ for (i = 0; i < (int)_pathNodeList.size() - 1; i++) {
+ point1 = _pathNodeList[i].point;
+ point2 = _pathNodeList[i+1].point;
_pathListIndex += pathLine(&_pathList[_pathListIndex], point1, point2);
- node->link = _pathListIndex - 1;
+ _pathNodeList[i+1].link = _pathListIndex - 1;
}
_pathListIndex--;
- _pathNodeList[_pathNodeListIndex].link = _pathListIndex;
+ _pathNodeList.back().link = _pathListIndex;
}
void Actor::removeNodes() {
- int i, j, k;
- PathNode *iNode, *jNode, *kNode, *fNode;
- fNode = &_pathNodeList[_pathNodeListIndex];
+ uint i, j, k;
+
+ // If there are only two nodes, nothing to be done
+ if (_pathNodeList.size() <= 2)
+ return;
- if (scanPathLine(_pathNodeList[0].point, fNode->point)) {
- _pathNodeList[1] = *fNode;
- _pathNodeListIndex = 1;
+ // If there is a direct connection between the first and last node, we can
+ // remove all nodes in between and are done.
+ if (scanPathLine(_pathNodeList.front().point, _pathNodeList.back().point)) {
+ _pathNodeList[1] = _pathNodeList.back();
+ _pathNodeList.resize(2);
}
- if (_pathNodeListIndex < 4) {
+ if (_pathNodeList.size() <= 4)
return;
- }
- for (i = _pathNodeListIndex - 1, iNode = fNode-1; i > 1 ; i--, iNode--) {
- if (iNode->point.x == PATH_NODE_EMPTY) {
+ // Scan the nodes in reverse order, and look for a node which can be
+ // directly reached from the first node. If we find any, skip directly
+ // from the first node to that node (by marking all nodes in between as
+ // empty).
+ for (i = _pathNodeList.size() - 2; i > 1 ; i--) {
+ if (_pathNodeList[i].point.x == PATH_NODE_EMPTY) {
continue;
}
- if (scanPathLine(_pathNodeList[0].point, iNode->point)) {
- for (j = 1, jNode = _pathNodeList + 1; j < i; j++, jNode++) {
- jNode->point.x = PATH_NODE_EMPTY;
+ if (scanPathLine(_pathNodeList.front().point, _pathNodeList[i].point)) {
+ for (j = 1; j < i; j++) {
+ _pathNodeList[j].point.x = PATH_NODE_EMPTY;
}
+ break;
}
}
- for (i = 1, iNode = _pathNodeList + 1; i < _pathNodeListIndex - 1; i++, iNode++) {
- if (iNode->point.x == PATH_NODE_EMPTY) {
+ // Now do the reverse: Find the first node which is directly connected
+ // to the end node; if we find any, skip over all nodes in between.
+ for (i = 1; i < _pathNodeList.size() - 2; i++) {
+ if (_pathNodeList[i].point.x == PATH_NODE_EMPTY) {
continue;
}
- if (scanPathLine(fNode->point, iNode->point)) {
- for (j = i + 1, jNode = iNode + 1; j < _pathNodeListIndex; j++, jNode++) {
- jNode->point.x = PATH_NODE_EMPTY;
+ if (scanPathLine(_pathNodeList.back().point, _pathNodeList[i].point)) {
+ for (j = i + 1; j < _pathNodeList.size()-1; j++) {
+ _pathNodeList[j].point.x = PATH_NODE_EMPTY;
}
+ break;
}
}
condenseNodeList();
- for (i = 1, iNode = _pathNodeList + 1; i < _pathNodeListIndex - 1; i++, iNode++) {
- if (iNode->point.x == PATH_NODE_EMPTY) {
+ // Finally, try arbitrary combinations of non-adjacent nodes and see
+ // if we can skip over any of them.
+ for (i = 1; i < _pathNodeList.size()-1 - 1; i++) {
+ if (_pathNodeList[i].point.x == PATH_NODE_EMPTY) {
continue;
}
- for (j = i + 2, jNode = iNode + 2; j < _pathNodeListIndex; j++, jNode++) {
- if (jNode->point.x == PATH_NODE_EMPTY) {
+ for (j = i + 2; j < _pathNodeList.size()-1; j++) {
+ if (_pathNodeList[j].point.x == PATH_NODE_EMPTY) {
continue;
}
- if (scanPathLine(iNode->point, jNode->point)) {
- for (k = i + 1,kNode = iNode + 1; k < j; k++, kNode++) {
- kNode->point.x = PATH_NODE_EMPTY;
+ if (scanPathLine(_pathNodeList[i].point, _pathNodeList[j].point)) {
+ for (k = i + 1; k < j; k++) {
+ _pathNodeList[k].point.x = PATH_NODE_EMPTY;
}
}
}
@@ -494,50 +504,49 @@ void Actor::removeNodes() {
condenseNodeList();
}
+/** Remove all empty nodes from _pathNodeList. */
void Actor::condenseNodeList() {
- int i, j, count;
- PathNode *iNode, *jNode;
-
- count = _pathNodeListIndex;
+ uint i, j, count;
- for (i = 1, iNode = _pathNodeList + 1; i < _pathNodeListIndex; i++, iNode++) {
- if (iNode->point.x == PATH_NODE_EMPTY) {
+ count = _pathNodeList.size();
+ for (i = 1; i < _pathNodeList.size()-1; i++) {
+ if (_pathNodeList[i].point.x == PATH_NODE_EMPTY) {
j = i + 1;
- jNode = iNode + 1;
- while (jNode->point.x == PATH_NODE_EMPTY) {
+ while (_pathNodeList[j].point.x == PATH_NODE_EMPTY) {
j++;
- jNode++;
}
- *iNode = *jNode;
- count = i;
- jNode->point.x = PATH_NODE_EMPTY;
- if (j == _pathNodeListIndex) {
+ _pathNodeList[i] = _pathNodeList[j];
+ count = i + 1;
+ _pathNodeList[j].point.x = PATH_NODE_EMPTY;
+ if (j == _pathNodeList.size()-1) {
break;
}
}
}
- _pathNodeListIndex = count;
+ _pathNodeList.resize(count);
}
void Actor::removePathPoints() {
- int i, j, k, l;
- PathNode *node;
+ uint i, j, l;
int start;
int end;
Point point1, point2;
- if (_pathNodeListIndex < 2)
+ if (_pathNodeList.size() <= 2)
return;
- _newPathNodeListIndex = -1;
- addNewPathNodeListPoint(_pathNodeList[0]);
+ Common::Array<PathNode> newPathNodeList;
+
+ // Add the first node
+ newPathNodeList.push_back(_pathNodeList.front());
- for (i = 1, node = _pathNodeList + 1; i < _pathNodeListIndex; i++, node++) {
- addNewPathNodeListPoint(*node);
+ // Process all nodes between the first and the last.
+ for (i = 1; i < _pathNodeList.size()-1; i++) {
+ newPathNodeList.push_back(_pathNodeList[i]);
for (j = 5; j > 0; j--) {
- start = node->link - j;
- end = node->link + j;
+ start = _pathNodeList[i].link - j;
+ end = _pathNodeList[i].link + j;
if (start < 0 || end > _pathListIndex) {
continue;
@@ -550,19 +559,19 @@ void Actor::removePathPoints() {
}
if (scanPathLine(point1, point2)) {
- for (l = 1; l <= _newPathNodeListIndex; l++) {
- if (start <= _newPathNodeList[l].link) {
- _newPathNodeListIndex = l;
- _newPathNodeList[_newPathNodeListIndex].point = point1;
- _newPathNodeList[_newPathNodeListIndex].link = start;
- incrementNewPathNodeListIndex();
+ for (l = 1; l < newPathNodeList.size(); l++) {
+ if (start <= newPathNodeList[l].link) {
+ newPathNodeList.resize(l+1);
+ newPathNodeList.back().point = point1;
+ newPathNodeList.back().link = start;
+ newPathNodeList.resize(l+2);
break;
}
}
- _newPathNodeList[_newPathNodeListIndex].point = point2;
- _newPathNodeList[_newPathNodeListIndex].link = end;
+ newPathNodeList.back().point = point2;
+ newPathNodeList.back().link = end;
- for (k = start + 1; k < end; k++) {
+ for (int k = start + 1; k < end; k++) {
_pathList[k].x = PATH_NODE_EMPTY;
}
break;
@@ -570,14 +579,16 @@ void Actor::removePathPoints() {
}
}
- addNewPathNodeListPoint(_pathNodeList[_pathNodeListIndex]);
+ // Add the last node
+ newPathNodeList.push_back(_pathNodeList.back());
- for (i = 0, j = 0; i <= _newPathNodeListIndex; i++) {
- if (_newPathNodeListIndex == i || (_newPathNodeList[i].point != _newPathNodeList[i+1].point)) {
- _pathNodeList[j++] = _newPathNodeList[i];
+ // Copy newPathNodeList into _pathNodeList, skipping any duplicate points
+ _pathNodeList.clear();
+ for (i = 0; i < newPathNodeList.size(); i++) {
+ if (newPathNodeList.size()-1 == i || (newPathNodeList[i].point != newPathNodeList[i+1].point)) {
+ _pathNodeList.push_back(newPathNodeList[i]);
}
}
- _pathNodeListIndex = j - 1;
}
#ifdef ACTOR_DEBUG