Page 1 of 2

Ходилка SomeBody.

Posted: 17.03.2008 22:25
by grundick
Чутка поправил. Теперь правильно считается расстояние и ходит по прямой(Спасиб Beyonderu ).

Code: Select all

// написал Somebody. ICQ: 475728522 e-mail: [email protected]

// Реализация алгоритма "надёжной трассировки"
// http://pmg.org.ru/ai/stout.htm#robust_trace

const 
FMoveArrMax = 300; // ставь здесь больше, если твой чар ходит на дистанции больше 13 тайлов или вокруг чара очень много препятствий. Если препятствий на пути мало, то можно оставить как есть. 
var 
PrognosisX, PrognosisY, FMoveArrCount : integer; 
FMoveArr : array [1..FMoveArrMax] of array [1..2] of smallint; 


Function Abs(A: integer): integer;
Begin
If A>=0 then result:=A 
Else result:=0-A;
End;

function SetDirection(x, y : integer) : integer; 
var
   MyX,MyY,DiffX,DiffY,GoDir: integer;
Begin
MyX:=GetX(self);
MyY:=GetY(self);
DiffX:=Abs(MyX-x);
DiffY:=Abs(MyY-y);

if (DiffX/(DiffY+0.1))>=2 then 
   begin
   if (MyX>X) then 
      GoDir:=6 
   else 
      GoDir:=2; 
   end  
else 
   
   if (DiffY/(DiffX+0.1))>=2 then 
      begin
      if (MyY>Y) then 
         GoDir:=0 
      else 
         GoDir:=4;
      end  
   else 
        
      if (MyX>X) and (MyY>Y) then  GoDir:=7
      else 

        if (MyX>X) and (MyY<Y) then  GoDir:=5 
        else 

           if (MyX<X) and (MyY>Y) then  GoDir:=1 
           else 

             if (MyX<X) and (MyY<Y) then  GoDir:=3; 
             
result:=GoDir;
end;


procedure CalcPrognosis(Dir : integer); 
begin 
   if (Dir = 1) or (Dir = 2) or (Dir = 3) then PrognosisX := GetX(self) + 1; 
   if (Dir = 5) or (Dir = 6) or (Dir = 7) then PrognosisX := GetX(self) - 1; 
   if (Dir = 0) or (Dir = 4) then PrognosisX := GetX(self); 

   if (Dir = 3) or (Dir = 4) or (Dir = 5) then PrognosisY := GetY(self) + 1; 
   if (Dir = 7) or (Dir = 0) or (Dir = 1) then PrognosisY := GetY(self) - 1; 
   if (Dir = 2) or (Dir = 6) then PrognosisY := GetY(self); 
end; 

function TryToMove(Direction : integer; RunFlag : boolean) : boolean; 
begin 
   if GetDirection(self) <> Direction then Raw_Move(Direction, RunFlag); 
   result := Raw_Move(Direction, RunFlag); 
end; 

function WrongMove(x, y : integer) : boolean; 
var 
i : integer; 
begin 
   result := false; 
   if FMoveArrCount = 0 then exit; 
   for i := 1 to FMoveArrCount do 
      begin 
      if (x = FMoveArr[i][1]) and (y = FMoveArr[i][2]) then 
         begin 
         result := true; 
         exit; 
         end; 
      end; 
end; 


function Min(x,y: integer): integer;
begin
 if x>y then Result:=y else Result:=x;
end;

function HEst(x,y: integer): integer;
var dx,dy,Ddx : integer;
begin
  dx:= GetX(self)-x;
  dy:= GetY(self)-y;
  Ddx:= dx-dy;
  If dx<0 then dx:=0-dx;
  If dy<0 then dy:=0-dy;
  If Ddx<0 then Ddx:=0-Ddx;
  Result:= min(dx,dy)+Ddx;
end;

procedure SetWrongMove(x, y : integer); 
begin 
   FMoveArrCount := FMoveArrCount + 1; 
   FMoveArr[FMoveArrCount][1] := x; 
   FMoveArr[FMoveArrCount][2] := y; 
end; 

function RewindDir(Dir, c : integer) : integer; 
begin 
   result := Dir + c; 
   if result < 0 then result := result + 8; 
   if result > 7 then result := result - 8; 
end; 

function Move(x, y, tolerance : integer) : boolean; 
var 
Dir, Dist, lastX, lastY, t, i, timeout : integer; 
begin 
   FMoveArrCount := 0; 
   Dist := HEst(x, y); 
   timeout := Dist * 13000; // 13 секунд времени на шаг 
   t := timer; 
   while true do 
      begin 
      Dist := HEst(x, y); 
      if Dist <= tolerance then // пришёл 
         begin 
         result := true; 
         exit; 
      end; 
      if timer - t > timeout then // провал по таймауту 
      begin 
         AddToSystemJournal('Move: Time moved out!'); 
         result := false; 
         exit; 
      end; 
      Dir := SetDirection(x, y); 
      CalcPrognosis(Dir); 
      if WrongMove(PrognosisX, PrognosisY) then 
         begin 
         for i := 1 to 7 do 
            begin 
            Dir := RewindDir(Dir, 1); 
            CalcPrognosis(Dir); 
            if not WrongMove(PrognosisX, PrognosisY) then break; 
            end; 
      if i = 8 then 
         begin 
         AddToSystemJournal('Move: Cannot move'); 
         result := false; 
         exit; 
         end; 
      end; 
      timeout := timeout + CheckFlow; 
      lastX := GetX(self); lastY := GetY(self); 
      if TryToMove(Dir, false) then SetWrongMove(lastX, lastY) // отсюда чар пришёл 
      else SetWrongMove(PrognosisX, PrognosisY); 
      end; 
end; 

procedure _move(x, y, tolerance : integer); 
begin 
while not Move(x, y, tolerance) do wait(100); 
end;

Posted: 18.03.2008 22:55
by Edred
Неплохо было бы снабдить подобный пост комментариями и инструкциями. Для чайников. Типа: "Вставьте этот код в текст своего файла скрипта в раздел функций. Вызывать процедуру _move с такими-то параметрами".

Posted: 20.03.2008 21:05
by grundick
Дык чуть выше (Sticky: Ходилка с обходом препятствий) всё есть.Эхх, выложили б пока релиз с проверкой тайлов на проходимость... : :roll:

Posted: 21.03.2008 1:00
by Edred
Не, так не пойдет. Возьми из прилепленной темы все описание и внеси его в первый пост.

После этого я перенесу из прилепленной темы все обсуждение в этот топик. Прилепленную тему удалю, а эту - прилеплю.

Posted: 13.07.2008 15:55
by RaTaMaHaTTa
Как юзать её :roll:

Posted: 13.07.2008 16:14
by -=JoKeR=-
RaTaMaHaTTa wrote:Как юзать её :roll:
Почитай =)
http://stealth.od.ua/forum/viewtopic.php?t=996

Posted: 13.07.2008 19:12
by RaTaMaHaTTa
-=JoKeR=- wrote:
RaTaMaHaTTa wrote:Как юзать её :roll:
Почитай =)
http://stealth.od.ua/forum/viewtopic.php?t=996
Да я то почитал но там всё кусками так брр
понел токо из скрипта вызвать можно процедурой

Code: Select all

procedure _move(1234, 1234, 0); 
Но вот чёто у меня не получилось Ш (

Posted: 16.07.2008 14:44
by -=JoKeR=-
так не, зачем

Code: Select all

procedure _move(1234, 1234, 0);
нужно

Code: Select all

move(1234,1234,0)
или

Code: Select all

_move(1234,1234,0)
не знаю, не пользовался этой ходилой, вот сейчас пишу програмку себе и проверю заодно как она себя ведёт, эта ходилка

PS
кто-то юзал её? как она в действии?

Posted: 16.07.2008 16:57
by v26RuS
Я пользуюсь это ходилкой для лумбера нормально ходить обходит все препятствия и вообще норм ходилка меня во всем устраивает...

Posted: 16.07.2008 17:19
by -=JoKeR=-
юзать так:

Code: Select all

_move(CoordX,CoordY,1/0)
классная ходилкО =)

Posted: 16.07.2008 17:57
by Unholy
_move(CoordX,CoordY,1/0)
За что отвечает этот переключатель?

Posted: 16.07.2008 18:22
by -=JoKeR=-
Извиняюсь, не 1\0, а вот как:
_move(x, y, tolerance);
tolerance - дистанция, на которую чар подойдёт к (x, y)

Posted: 16.07.2008 18:52
by grundick
не знаю как у вас ,но меня этот 13ти секукндный таймаут при столкновении с препятствием просто убивал :( зачастую в буквальном смысле слова!

Posted: 16.07.2008 18:53
by -=JoKeR=-
незнаю...
у меня нет препятствий =)

Posted: 16.07.2008 20:01
by v26RuS
Пользоваться ходилкой можно двумя способами
1-й
move(Кордината x, Кордината y, Количество погрешности тайла*);
В данном случаи может слететь по таймауту на переход

или 2-й вариант
_move(Кордината x, Кордината y, Количество погрешности тайла*);
Будет идти до цели не обращая внимание на таймаут


*Количество тайлов за которое остановиться не доходя до цели. Очень удобно для лумбера ставим 1 и берем из файла кориднаты именно дерева и он не будет лезть на дерево а остановиться перед ним.

Вроде доступно описал)) Если что-то не так написал извените)