move_v0_1.inc
Code: Select all
//////////////////////////////////////////////////////////////////////////////////////////////
// move_v0_2.inc 11.09.2008 //
// crafted by SevenAmber. e-mail: [email protected] //
// алгоритм прохода к указанной точке с обходом небольших препятствий //
/////////////////////////////////////////////////////////////////////////////////////////////
type
Dim8= Array[0..8] of integer;
T_Dir_XY=record
x:integer;
y:integer;
end;
var
Co_ord_X,Co_ord_Y: Array of integer;
Dir_Ch:array of string;
revDir:dim8;
IsInit:boolean;
Const
N=0;// North
NE=1;//NorthEast
E=2;//East
SE=3;//SouthEeast
S=4;//South
SW=5;//SouthWest
W=6;//West
NW=7;//NorthWest
SLF=8;//self
Procedure Init_GoXY; // инициализация
begin
Dir_Ch:=['N','NE','E','SE','S','SW','W','NW','SLF'];
Co_ord_X:=[0,1,1,1,0,-1,-1,-1,0];
Co_ord_Y:=[-1,-1,0,1,1,1,0,-1,0];
revDir[N]:=S;revDir[S]:=N;revDir[W]:=E; revDir[E]:=W;
revDir[NW]:=SE;revDir[SE]:=NW;revDir[NE]:=SW; revDir[SW]:=NE;
revDir[SLF]:=SLF;
IsInit:=true;
end;
function encode_dir(direction:integer):T_Dir_XY; // из направления получаем координаты
var
TempDir:T_Dir_XY;
begin
TempDir.X:=GetX(self)+Co_ord_X[direction];
TempDir.Y:=GetY(self)+Co_ord_Y[direction];
Result:=TempDir;
end;
function CrdToString(sx,sy:integer):string;// координаты в строку типа <X,Y>
begin
Result:='<'+IntToStr(sx)+','+IntToStr(sy)+'>'
end;
function DirToStr(direction:integer):string;// направление в строку типа <X,Y>
var
TempDir:T_Dir_XY;
begin
TempDir:= encode_dir(direction);
Result:=CrdToString(TempDir.X,TempDir.Y);
end;
function isCorrectDir(direction:integer;DirStr:string):boolean;// проверка правильности направления
// не пытался ли чар уже идти в данную точку
var
strDir:string;
begin
strDir:=DirToStr(direction);
if (Pos(strDir,DirStr)=0) then Result:=true else Result:=false;
end;
// персечение множества координат вокург себя с координатами в строке Pstr
function AroundSelf(Pstr:string):string;
var
i:integer;
rStr:string;
begin
rStr:='';
for i:=N to NW do
if (not isCorrectDir(i,Pstr)) then rStr:=DirToStr(i)+rStr;
Result:=rStr;
end;
function code_dir(fX,fY:integer):integer; // из координат назначения получаем направление
var
tx,ty,t,i:Longint;
begin
i:=0;
tx:=fX - GetX(self);
ty:=fY - GetY(self);
t:=Trunc(Abs(tx));
if tx<>0 then tx:=tx/t;
t:=Trunc(Abs(ty));
if ty<>0 then ty:=ty/t;
for i:=N to SLF do
if ((tx=Co_ord_X[i]) and(ty=Co_ord_Y[i])) then Result:=i;
end;
function detour(dir:integer;ClockWise:boolean):integer; // смена направления
// ClockWise = true - чар поворачивается по часовой стрелке
// ClockWise = false - чар поворачивается пhjnbd часовой стрелки
begin
if ClockWise then
if dir=7 then Result:=0 else Result:=dir+1
else
if dir=0 then Result:=7 else Result:=dir-1;
end;
function Move(Direction:integer):boolean;// Делает один шаг в указанном направлении
var
isNotStop, isMove:boolean;
mx,my:integer;
begin
mx:=GetX(self);
my:=GetY(self);
repeat
CheckSave;
isNotStop:=Raw_Move(Direction,false);
{ToDo- тут следует вставлять проверку на хайд}
if (((mx-GetX(self))<>0) or ((my-GetY(self))<>0)) then isMove:=true else isMove:=false;
if isMove then isNotStop:=false;
until not isNotStop;
Result:=isMove;
end;
procedure GotoXY(gX:integer;gY:integer;ClWi:boolean;acc:byte); // основная функция
// acc - точность подхода
// ClWi - используется в detour в качестве ClockWise
var
isGo:boolean;
TempDir:integer;
ReverseDir:integer;
DirStrNow,DirStrPre:string;
Begin
if not IsInit then Init_GoXY;
if ((Abs(GetX(self)-gX)<=acc) AND (Abs(GetY(self)-gY)<=acc)) then exit;
TempDir:= code_dir(gX,gY);
repeat
CheckSave;
if isCorrectDir(TempDir,DirStrNow) then isGo:=Move(TempDir) else isGo:=false;
if isGo then
begin
ReverseDir:= revDir[TempDir];
TempDir:= code_dir(gX,gY);
if ReverseDir=TempDir then TempDir:=detour(TempDir,ClWi);
DirStrPre:=DirStrNow;
DirStrNow:=AroundSelf(DirStrPre);
end
else
begin
DirStrNow:=DirStrNow+DirToStr(TempDir);
TempDir:= detour(TempDir,ClWi);
end;
until ((Abs(GetX(self)-gX)<=acc) AND (Abs(GetY(self)-gY)<=acc));
end;