mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-28 12:46:56 +00:00
361 lines
8.6 KiB
C++
361 lines
8.6 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include "kyra/kyra_v1.h"
|
|
|
|
namespace Kyra {
|
|
|
|
int KyraEngine_v1::findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize) {
|
|
x &= 0xFFFC; toX &= 0xFFFC;
|
|
y &= 0xFFFE; toY &= 0xFFFE;
|
|
x = (int16)x; y = (int16)y; toX = (int16)toX; toY = (int16)toY;
|
|
|
|
if (x == toY && y == toY) {
|
|
moveTable[0] = 8;
|
|
return 0;
|
|
}
|
|
|
|
int curX = x;
|
|
int curY = y;
|
|
int tempValue = 0;
|
|
int lastUsedEntry = 0;
|
|
int *pathTable1 = new int[0x7D0];
|
|
int *pathTable2 = new int[0x7D0];
|
|
assert(pathTable1 && pathTable2);
|
|
|
|
while (true) {
|
|
int newFacing = getFacingFromPointToPoint(x, y, toX, toY);
|
|
changePosTowardsFacing(curX, curY, newFacing);
|
|
|
|
if (curX == toX && curY == toY) {
|
|
if (!lineIsPassable(curX, curY))
|
|
break;
|
|
moveTable[lastUsedEntry++] = newFacing;
|
|
break;
|
|
}
|
|
|
|
if (lineIsPassable(curX, curY)) {
|
|
if (lastUsedEntry == moveTableSize) {
|
|
delete[] pathTable1;
|
|
delete[] pathTable2;
|
|
return 0x7D00;
|
|
}
|
|
// debug drawing
|
|
/*if (curX >= 0 && curY >= 0 && curX < 320 && curY < 200) {
|
|
screen()->setPagePixel(0, curX, curY, 11);
|
|
screen()->updateScreen();
|
|
delayWithTicks(5);
|
|
}*/
|
|
moveTable[lastUsedEntry++] = newFacing;
|
|
x = curX;
|
|
y = curY;
|
|
continue;
|
|
}
|
|
|
|
int temp = 0;
|
|
while (true) {
|
|
newFacing = getFacingFromPointToPoint(curX, curY, toX, toY);
|
|
changePosTowardsFacing(curX, curY, newFacing);
|
|
// debug drawing
|
|
/*if (curX >= 0 && curY >= 0 && curX < 320 && curY < 200) {
|
|
screen()->setPagePixel(0, curX, curY, 8);
|
|
screen()->updateScreen();
|
|
delayWithTicks(5);
|
|
}*/
|
|
|
|
if (!lineIsPassable(curX, curY)) {
|
|
if (curX != toX || curY != toY)
|
|
continue;
|
|
}
|
|
|
|
if (curX == toX && curY == toY) {
|
|
if (!lineIsPassable(curX, curY)) {
|
|
tempValue = 0;
|
|
temp = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
temp = findSubPath(x, y, curX, curY, pathTable1, 1, 0x7D0);
|
|
tempValue = findSubPath(x, y, curX, curY, pathTable2, 0, 0x7D0);
|
|
if (curX == toX && curY == toY) {
|
|
if (temp == 0x7D00 && tempValue == 0x7D00) {
|
|
delete[] pathTable1;
|
|
delete[] pathTable2;
|
|
return 0x7D00;
|
|
}
|
|
}
|
|
|
|
if (temp != 0x7D00 || tempValue != 0x7D00)
|
|
break;
|
|
}
|
|
|
|
if (temp < tempValue) {
|
|
if (lastUsedEntry + temp > moveTableSize) {
|
|
delete[] pathTable1;
|
|
delete[] pathTable2;
|
|
return 0x7D00;
|
|
}
|
|
memcpy(&moveTable[lastUsedEntry], pathTable1, temp * sizeof(int));
|
|
lastUsedEntry += temp;
|
|
} else {
|
|
if (lastUsedEntry + tempValue > moveTableSize) {
|
|
delete[] pathTable1;
|
|
delete[] pathTable2;
|
|
return 0x7D00;
|
|
}
|
|
memcpy(&moveTable[lastUsedEntry], pathTable2, tempValue * sizeof(int));
|
|
lastUsedEntry += tempValue;
|
|
}
|
|
x = curX;
|
|
y = curY;
|
|
if (curX == toX && curY == toY)
|
|
break;
|
|
}
|
|
|
|
delete[] pathTable1;
|
|
delete[] pathTable2;
|
|
moveTable[lastUsedEntry] = 8;
|
|
return lastUsedEntry;
|
|
}
|
|
|
|
int KyraEngine_v1::findSubPath(int x, int y, int toX, int toY, int *moveTable, int start, int end) {
|
|
// only used for debug specific code
|
|
//static uint16 unkTable[] = { 8, 5 };
|
|
static const int8 facingTable1[] = { 7, 0, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 0 };
|
|
static const int8 facingTable2[] = { -1, 0, -1, 2, -1, 4, -1, 6, -1, 2, -1, 4, -1, 6, -1, 0 };
|
|
static const int8 facingTable3[] = { 2, 4, 4, 6, 6, 0, 0, 2, 6, 6, 0, 0, 2, 2, 4, 4 };
|
|
static const int8 addPosTableX[] = { -1, 0, -1, 4, -1, 0, -1, -4, -1, -4, -1, 0, -1, 4, -1, 0 };
|
|
static const int8 addPosTableY[] = { -1, 2, -1, 0, -1, -2, -1, 0, -1, 0, -1, 2, -1, 0, -1, -2 };
|
|
|
|
// debug specific
|
|
/*++unkTable[start];
|
|
while (screen()->getPalette(0)[unkTable[start]] != 0x0F) {
|
|
++unkTable[start];
|
|
}*/
|
|
|
|
int xpos1 = x, xpos2 = x;
|
|
int ypos1 = y, ypos2 = y;
|
|
int newFacing = getFacingFromPointToPoint(x, y, toX, toY);
|
|
int position = 0;
|
|
|
|
while (position != end) {
|
|
int newFacing2 = newFacing;
|
|
while (true) {
|
|
changePosTowardsFacing(xpos1, ypos1, facingTable1[start * 8 + newFacing2]);
|
|
if (!lineIsPassable(xpos1, ypos1)) {
|
|
if (facingTable1[start * 8 + newFacing2] == newFacing)
|
|
return 0x7D00;
|
|
newFacing2 = facingTable1[start * 8 + newFacing2];
|
|
xpos1 = x;
|
|
ypos1 = y;
|
|
continue;
|
|
}
|
|
newFacing = facingTable1[start * 8 + newFacing2];
|
|
break;
|
|
}
|
|
// debug drawing
|
|
/*if (xpos1 >= 0 && ypos1 >= 0 && xpos1 < 320 && ypos1 < 200) {
|
|
screen()->setPagePixel(0, xpos1, ypos1, unkTable[start]);
|
|
screen()->updateScreen();
|
|
delayWithTicks(5);
|
|
}*/
|
|
if (newFacing & 1) {
|
|
int temp = xpos1 + addPosTableX[newFacing + start * 8];
|
|
if (toX == temp) {
|
|
temp = ypos1 + addPosTableY[newFacing + start * 8];
|
|
if (toY == temp) {
|
|
moveTable[position++] = facingTable2[newFacing + start * 8];
|
|
return position;
|
|
}
|
|
}
|
|
}
|
|
|
|
moveTable[position++] = newFacing;
|
|
x = xpos1;
|
|
y = ypos1;
|
|
|
|
if (x == toX && y == toY)
|
|
return position;
|
|
|
|
if (xpos1 == xpos2 && ypos1 == ypos2)
|
|
break;
|
|
|
|
newFacing = facingTable3[start * 8 + newFacing];
|
|
}
|
|
|
|
return 0x7D00;
|
|
}
|
|
|
|
int KyraEngine_v1::getFacingFromPointToPoint(int x, int y, int toX, int toY) {
|
|
static const int facingTable[] = {
|
|
1, 0, 1, 2, 3, 4, 3, 2, 7, 0, 7, 6, 5, 4, 5, 6
|
|
};
|
|
|
|
int facingEntry = 0;
|
|
int ydiff = y - toY;
|
|
if (ydiff < 0) {
|
|
++facingEntry;
|
|
ydiff = -ydiff;
|
|
}
|
|
facingEntry <<= 1;
|
|
|
|
int xdiff = toX - x;
|
|
if (xdiff < 0) {
|
|
++facingEntry;
|
|
xdiff = -xdiff;
|
|
}
|
|
|
|
if (xdiff >= ydiff) {
|
|
int temp = ydiff;
|
|
ydiff = xdiff;
|
|
xdiff = temp;
|
|
|
|
facingEntry <<= 1;
|
|
} else {
|
|
facingEntry <<= 1;
|
|
facingEntry += 1;
|
|
}
|
|
int temp = (ydiff + 1) >> 1;
|
|
|
|
if (xdiff < temp) {
|
|
facingEntry <<= 1;
|
|
facingEntry += 1;
|
|
} else {
|
|
facingEntry <<= 1;
|
|
}
|
|
|
|
assert(facingEntry < ARRAYSIZE(facingTable));
|
|
return facingTable[facingEntry];
|
|
}
|
|
|
|
|
|
int KyraEngine_v1::getOppositeFacingDirection(int dir) {
|
|
switch (dir) {
|
|
case 0:
|
|
return 2;
|
|
case 1:
|
|
return 1;
|
|
case 3:
|
|
return 7;
|
|
case 4:
|
|
return 6;
|
|
case 5:
|
|
return 5;
|
|
case 6:
|
|
return 4;
|
|
case 7:
|
|
return 3;
|
|
default:
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void KyraEngine_v1::changePosTowardsFacing(int &x, int &y, int facing) {
|
|
x += _addXPosTable[facing];
|
|
y += _addYPosTable[facing];
|
|
}
|
|
|
|
int KyraEngine_v1::getMoveTableSize(int *moveTable) {
|
|
int tableSize = 0;
|
|
if (moveTable[0] == 8)
|
|
return 0;
|
|
|
|
static const int facingTable[] = {
|
|
4, 5, 6, 7, 0, 1, 2, 3
|
|
};
|
|
static const int unkTable[] = {
|
|
-1, -1, 1, 2, -1, 6, 7, -1,
|
|
-1, -1, -1, -1, 2, -1, 0, -1,
|
|
1, -1, -1, -1, 3, 4, -1, 0,
|
|
2, -1, -1, -1, -1, -1, 4, -1,
|
|
-1, 2, 3, -1, -1, -1, 5, 6,
|
|
6, -1, 4, -1, -1, -1, -1, -1,
|
|
7, 0, -1, 4, 5, -1, -1, -1,
|
|
-1, -1, 0, -1, 6, -1, -1, -1
|
|
};
|
|
|
|
int *oldPosition = moveTable;
|
|
int *tempPosition = moveTable;
|
|
int *curPosition = moveTable + 1;
|
|
tableSize = 1;
|
|
|
|
while (*curPosition != 8) {
|
|
if (*oldPosition == facingTable[*curPosition]) {
|
|
tableSize -= 2;
|
|
*oldPosition = 9;
|
|
*curPosition = 9;
|
|
|
|
while (tempPosition != moveTable) {
|
|
--tempPosition;
|
|
if (*tempPosition != 9)
|
|
break;
|
|
}
|
|
|
|
if (tempPosition == moveTable && *tempPosition == 9) {
|
|
while (*tempPosition == 9)
|
|
++tempPosition;
|
|
|
|
if (*tempPosition == 8)
|
|
return 0;
|
|
}
|
|
|
|
oldPosition = tempPosition;
|
|
curPosition = oldPosition + 1;
|
|
|
|
while (*curPosition == 9)
|
|
++curPosition;
|
|
} else if (unkTable[*curPosition + *oldPosition * 8] != -1) {
|
|
--tableSize;
|
|
*oldPosition = unkTable[*curPosition + *oldPosition * 8];
|
|
*curPosition = 9;
|
|
|
|
if (tempPosition != oldPosition) {
|
|
curPosition = oldPosition;
|
|
oldPosition = tempPosition;
|
|
while (tempPosition != moveTable) {
|
|
--tempPosition;
|
|
if (*tempPosition != 9)
|
|
break;
|
|
}
|
|
} else {
|
|
do {
|
|
++curPosition;
|
|
} while (*curPosition == 9);
|
|
}
|
|
} else {
|
|
tempPosition = oldPosition;
|
|
oldPosition = curPosition;
|
|
++tableSize;
|
|
|
|
do {
|
|
++curPosition;
|
|
} while (*curPosition == 9);
|
|
}
|
|
}
|
|
|
|
return tableSize;
|
|
}
|
|
|
|
} // End of namespace Kyra
|