Iamadam
2011-04-27 20:52:08
program canReacher;
{$DEFINE SMART}
{$i SRL\SRL.scar}
{$i Reflection\Reflection.simba}
function getGroundBlocks: array of array of integer;
var rsObject : Integer;
xCount, yCount, xMax, yMax, i, markTime1 : Integer;
blockArray : array of array of integer;
begin
rsObject := SmartGetFieldArrayObject(0, 'uha.a', getPlaneIndex);
xMax := SmartGetFieldArraySize(rsObject, 'o', 1);
yMax := SmartGetFieldArraySize(rsObject, 'o', 2);
SetLength(blockArray, xMax - 4);
for i := low(blockArray) to high(blockArray) do
begin
setLength(blockArray[i], yMax - 4);
end;
//~330 ms to do this... (fyi, this would be unnesessary in java...)
markTime1 := getSystemTime;
for xCount := 0 to xMax - 5 do
begin
for yCount := 0 to yMax - 5 do
begin
blockArray[xCount][yCount] := smartGetFieldArray2DInt(rsObject, 'o', xCount, yCount);
end;
end;
smartFreeObject(rsObject);
result := blockArray;
end;
function dijkstraDistance(startX, startY, destX, destY: Integer; searchAllPaths : boolean) : Integer;
var via, cost, blocks: array of array of Integer;
tileQueueX, tileQueueY : array of Integer;
curX, curY, head, tail, pathLength, i1, newCost, i, j : Integer;
begin
SetLength(via, 104);
for i := low(via) to high(via) do
setLength(via[i], 104);
SetLength(cost, 104);
for i := low(cost) to high(cost) do
setLength(cost[i], 104);
SetLength(tileQueueX, 4000);
SetLength(tileQueueY, 4000);
for i := 0 to 103 do
for j := 0 to 103 do
begin
via[i][j] := 0;
cost[i][j] := 99999999;
end;
curX := startX;
curY := startY;
via[startX][startY] := 99;
cost[startX][startY] := 0;
head := 0;
tail := 0;
tileQueueX[head] := startX;
tileQueueY[(head)] := startY;
inc(head);
blocks := getGroundBlocks;
pathLength := 4000;
i1 := 0;
while (tail <> head) do
begin
curX := tileQueueX[tail];
curY := tileQueueY[tail];
if ((curX = destX) and (curY = destY)) then
i1 := 1;
if(not searchAllPaths) then
if (((curX = destX) and (curY = destY + 1)) or ((curX = destX) and (curY = destY - 1)) or ((curX = destX + 1) and (curY = destY)) or ((curX = destX - 1) and (curY = destY))) then
begin
i1 := 1;
break;
end;
tail := (tail + 1) mod pathLength;
newCost := cost[curX][curY] + 1;
if ((curY > 0) and (via[curX][(curY - 1)] = 0) and ((blocks[(curX + 1)][curY] and $1280102) = 0)) then
begin
tileQueueX[head] := curX;
tileQueueY[head] := (curY - 1);
head := (head + 1) mod pathLength;
via[curX][(curY - 1)] := 1;
cost[curX][(curY - 1)] := newCost;
end;
if ((curX > 0) and (via[(curX - 1)][curY] = 0) and ((blocks[curX][(curY + 1)] and $1280108) = 0)) then
begin
tileQueueX[head] := (curX - 1);
tileQueueY[head] := curY;
head := (head + 1) mod pathLength;
via[(curX - 1)][curY] := 2;
cost[(curX - 1)][curY] := newCost;
end;
if ((curY < 103) and (via[curX][(curY + 1)] = 0) and ((blocks[(curX + 1)][(curY + 2)] and $1280120) = 0))then
begin
tileQueueX[head] := curX;
tileQueueY[head] := (curY + 1);
head := (head + 1) mod pathLength;
via[curX][(curY + 1)] := 4;
cost[curX][(curY + 1)] := newCost;
end;
if ((curX < 103) and (via[(curX + 1)][curY] = 0) and ((blocks[(curX + 2)][(curY + 1)] and $1280180) = 0))then
begin
tileQueueX[head] := (curX + 1);
tileQueueY[head] := curY;
head := (head + 1) mod pathLength;
via[(curX + 1)][curY] := 8;
cost[(curX + 1)][curY] := newCost;
end;
if ((curX > 0) and (curY > 0) and (via[(curX - 1)][(curY - 1)] = 0)
and ((blocks[curX][curY] and $128010E) = 0) and ((blocks[curX][(curY + 1)] and $1280108) = 0)
and ((blocks[(curX + 1)][curY] and $1280102) = 0)) then
begin
tileQueueX[head] := (curX - 1);
tileQueueY[head] := (curY - 1);
head := (head + 1) mod pathLength;
via[(curX - 1)][(curY - 1)] := 3;
cost[(curX - 1)][(curY - 1)] := newCost;
end;
if ((curX > 0) and (curY < 103) and (via[(curX - 1)][(curY + 1)] = 0)
and ((blocks[curX][(curY + 2)] and $1280138) = 0) and ((blocks[curX][(curY + 1)]
and $1280108) = 0) and ((blocks[(curX + 1)][(curY + 2)] and $1280120) = 0)) then
begin
tileQueueX[head] := (curX - 1);
tileQueueY[head] := (curY + 1);
head := (head + 1) mod pathLength;
via[(curX - 1)][(curY + 1)] := 6;
cost[(curX - 1)][(curY + 1)] := newCost;
end;
if ((curX < 103) and (curY > 0) and (via[(curX + 1)][(curY - 1)] = 0)
and ((blocks[(curX + 2)][curY] and $1280183) = 0)
and ((blocks[(curX + 2)][(curY + 1)] and $1280180) = 0)
and ((blocks[(curX + 1)][curY] and $1280102) = 0)) then
begin
tileQueueX[head] := (curX + 1);
tileQueueY[head] := (curY - 1);
head := (head + 1) mod pathLength;
via[(curX + 1)][(curY - 1)] := 9;
cost[(curX + 1)][(curY - 1)] := newCost;
end;
if ((curX < 103) and (curY < 103) and (via[(curX + 1)][(curY + 1)] = 0)
and ((blocks[(curX + 2)][(curY + 2)] and $12801E0) = 0)
and ((blocks[(curX + 2)][(curY + 1)] and $1280180) = 0)
and ((blocks[(curX + 1)][(curY + 2)] and $1280120) = 0)) then
begin
tileQueueX[head] := (curX + 1);
tileQueueY[head] := (curY + 1);
head := (head + 1) mod pathLength;
via[(curX + 1)][(curY + 1)] := 12;
cost[(curX + 1)][(curY + 1)] := newCost;
end;
end;
if(i1 <> 0) then
result := cost[curX][curY]
else
result := -1;
end;
function GetMyLocalPos: TTile;
var
me: Integer;
begin
me := SmartGetFieldObject(0, hook_static_MyPlayer);
Result.x := SmartGetFieldInt(me, hook_animable_PixelX) / 512;
Result.y := SmartGetFieldInt(me, hook_animable_PixelY) / 512;
SmartFreeObject(me);
end;
function canReach(dest : TTile) : boolean;
var pathDist, baseX, baseY : Integer;
localPos : TTile;
begin
writeln('canReach called');
baseX := SmartGetFieldInt(0, hook_static_BaseX);
baseY := SmartGetFieldInt(0, hook_static_BaseY);
localPos := getMyLocalPos;
pathDist := dijkstraDistance(localPos.x, localPos.y, dest.x - baseX, dest.y - baseY, false);
writeln(toStr(pathDist));
if(pathDist <> -1) then
result := true;
end;
procedure setup;
begin
clearDebug;
smart_server := 1;
smart_signed := true;
smart_members := true;
setupSRL;
setupReflection;
end;
begin
setup;
repeat
if(canReach(Tile(3162,3434))) then
writeln('Can reach!');
wait(1000);
until(false);
end.Obviously a VERY useful function for us. I have ported the one we used in ARGA to pascal, and found the necessary hooks. It works brilliantly, BUT is incredibly slow because of pascal script.
we need to:
1. Port the DijkstraDistance function to a plugin
2. Add the requierd hooks to the hooks file. I will write a search and give it to pyro (unless you want to write your own??).
This is great to see if there is a closed door in the way (or any other impassable obstacle).
Anyone willing to get on board with this? Other wise I'll do it myself. :)