Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.09.25;
Скачать: CL | DM;

Вниз

Lines   Найти похожие ветки 

 
Grell ©   (2005-05-06 17:27) [0]

Как в играх типа Lines реализован поиск пути?


 
XProger ©   (2005-05-06 17:30) [1]

Астар (A*)


 
Sphinx ©   (2005-05-07 12:13) [2]

Волновой :)


 
Darth   (2005-05-09 23:31) [3]

ИМХО нечего мудрить с астаром. Волновой и все дела. Волна небольшая, так что считай хоть по 100 раз в секунду. Скорости это сильно не сбавит.


 
Kerk ©   (2005-05-11 21:24) [4]

Алгоритм Дейкстры тоже пока никто не отменял.. экономичнее волнового по памяти.


 
Zer0 ©   (2005-05-11 21:56) [5]

можно извратиться и написать поиск наидлиннейшего непересекающегося пути =)
самый простой без извратов - рекурсия с отметками на карте "был, дошел за N шагов","не был".


 
Kerk ©   (2005-05-11 22:14) [6]

Zer0 ©   (11.05.05 21:56) [5]
можно извратиться и написать поиск наидлиннейшего непересекающегося пути =)


Диаметр графа?


 
П7   (2005-05-11 23:27) [7]

Очень актуальная тема (:


 
Kerk ©   (2005-05-12 10:55) [8]

mason1.zip
Вывод формулы Мэйсона. Данные - матрица смежности или граф (редактор графов прилагается). Программа анализирует граф, в том числе, ищет все пути из одной вершины в другую. Есть описание в .doc, немного урезанное. Писал давно, ногами не бейте %-)

http://kladovka.net.ru/index.php?action=downloadfile&filename=mason1.zip&directory=Students


 
Zer0 ©   (2005-05-14 13:02) [9]

Есть у меня быстрый астар++ со скоростью близкой к O(n):

type
    pelement = ^telement;
    telement = record
      kind              : char;
      parameters        : word;
      g,depth,
      h,position,
      ai_parameters     : integer;
      blocked           : word;
      parent,left,right : pelement;
      id                : byte;
    end;

    tcoord = record
      x,y : integer
    end;

    tcarray = array of tcoord;

    tgrid = array of telement;

    tgamelevel = class
      imagename : string;
      name : string;
      fname : string;
      grid : tgrid;
      h,w  : integer;
      changed : boolean;

      constructor create;
      destructor destroy; override;

      procedure cleargrid;
      procedure clear;
      procedure setsize( _w,_h : integer );
      procedure load( str : tstream );
      procedure save( str : tstream );

      function getcell(x,y:integer):char;
      procedure setcell(x,y:integer; value : char);

      function findpath(sx,sy,xd,yd : integer; search_mask:word):tcarray;
    public
      property cell[x,y:integer] : char read getcell write setcell;
    end;


 
Zer0 ©   (2005-05-14 13:03) [10]


constructor tgamelevel.create;
begin
 imagename := ""; name := ""; fname := ""; changed := false;
 h:=0; w:=0;
end;

procedure tgamelevel.cleargrid;
begin
 h:=0; w:=0; setlength(grid,0);
end;

procedure tgamelevel.clear;
begin
 cleargrid; imagename := ""; name := ""; fname := "";
end;

procedure tgamelevel.setsize( _w,_h : integer );
var i:integer;
begin
 if h<>0 then cleargrid;
 h:=_h; w:=_w;
 setlength(grid,w*h);
 for i:=0 to w*h-1 do
 begin
   grid[i].kind:="0";
   grid[i].position := i;
 end;

 changed := true;
end;

function tgamelevel.getcell(x,y:integer):char;
begin
 result:=#0;
 if (x>=0) and (x<w) then
   if (y>=0) and (y<h) then
     result:=grid[x+y*w].kind
end;

procedure tgamelevel.setcell(x,y:integer; value : char);
begin
 if (x>=0) and (x<w) then
   if (y>=0) and (y<h) then
     grid[x+y*w].kind:=value;
end;


 
Zer0 ©   (2005-05-14 13:08) [11]


function tgamelevel.findpath(sx,sy,xd,yd : integer; search_mask:word):tcarray;
//This is a version of A* which uses the searchspace for storing its
//nodes. The big advantage is that one iteration takes O(1) instead of
//O(n).  For n iterations this then comes to O(n) instead of O(n^2) which
//is decidedly faster.
//xd and yd are tile coordinates

  function HEURISTIC(const x1,y1,x2,y2 : integer) : integer;
  begin
    result:=round(sqrt(sqr(x1-x2)+sqr(y1-y2))*6);
  end;

  function is_tile_busy(const x,y : integer) : boolean;
  begin
    result := false;
  end;

  function is_tile_blocked(const x,y : integer) : boolean;
  begin
    result :=  (grid[x+y*w].kind in ["b","f"]);
  end;

var i : integer;
   open,closed,current,previous,best_node,succ : pelement;
   path : tcarray;
   goal_index,cx,cy,xx,yy,index,g,_h,{iterations,sorts,}position : integer;
begin
  setlength(result,0);

  if (sx<0) or (sx>=w) or (sy<0) or (sy>=h) or
     (xd<0) or (xd>=w) or (yd<0) or (yd>=h) then
    exit;

  for i:=0 to w*h-1 do
  begin
    grid[i].id := 0;
  end;

  {iterations:=0; sorts :=0;} position:=sx+sy*w;

  //This is a new search
  goal_index:=xd+yd*w;
  //Create root node
  open:=@grid[position];
  open^.parent:=nil; open^.right:=nil; open^.left:=nil;
  open^.g:=0; open^.h:=HEURISTIC(sx,sy,xd,yd);
  open^.depth:=0;
  open^.id:=1;
  open^.ai_parameters:=ON_OPEN;

  //Start the search.
  while (true) do
  if open = nil then
  //No solution
    exit
  else
  begin
    //Take best node from open and place it on closed
    best_node:=open;
    open:=open^.right;
    if (open<>nil) then
      open^.left:=nil;
    best_node^.ai_parameters:=ON_CLOSED;
    //Check if bestnode is the goal
    if (best_node^.position=goal_index) then
    begin
      //FOUND GOAL
      current:=best_node;
      setlength(path,best_node^.depth+1);
      i:=best_node^.depth;
      while(current<>nil) do
      begin
        //Opposite since A* caused a reversed path
        path[i].x:=current^.position mod w;
        path[i].y:=current^.position div w;
        dec(i);
        current:=current^.parent;
      end;
      result := path;
      exit;
    end;

    //Generate successors
    cx:=best_node^.position mod w;
    cy:=best_node^.position div w;
    for i:=0 to 7 do
    begin
      //Do not exceed maximum allowed iterations
      {inc(iterations);}
      //Check if succesor is valid
      xx:=cx+direction_delta[i][0];
      yy:=cy+direction_delta[i][1];

      if (xx<0) or (xx>=w) or (yy<0) or (yy>=h) then
        continue;

      index:=xx+yy*w;

      if (search_mask and AVOID_OBSTACLES)>0 then
        if (is_tile_blocked(xx,yy)) then
          continue;//Skip

      if (search_mask and AVOID_UNITS)>0 then
        if (is_tile_busy(xx,yy)) then
          continue;//Skip

      //Create succesor
      succ:=@grid[index];

      //Calculate path value
      //(тут вычисляется проходимость блока в зависимости от его типа)
      case succ^.kind of
      "0" : g:=2;
      "1" : g:=9;
      "2" : g:=13;
      "3" : g:=17;
      else
      //  крайне труднопроходимый блок блок
       g:=100000;
      end;

      g:=g+best_node^.g+direction_cost[i];
      _h:=HEURISTIC(xx,yy,xd,yd);
      //Has this node been generated during this search
      //Due to the way we store these things these are all
      //O(1) operations rather than O(n) operations so that
      //overall time complexity is O(n) instead of O(n^2)
      //(Actually it used to be 2*(n(n+1)/2):=n(n+1):=n^2+n:=O(n^2))
      if (succ^.id=1) then
      begin
        //Yes, it has been generated already
        //Check if already on open
        if (succ^.ai_parameters and ON_OPEN)>0 then
        begin
          //It is on open
          if (g<succ^.g) then
          begin
            //Better path found to open
            succ^.parent:=best_node;
            succ^.g:=g;
            succ^.depth:=best_node^.depth+1;
            //Remove it from queue
            if (succ^.left<>nil) then
              succ^.left^.right:=succ^.right
            else
              open:=nil;//It was the first node
            if (succ^.right<>nil) then
              succ^.right^.left:=succ^.left;
          end
          else
            //If it is on open but is g value is better
            //than the current g value we do not
            //generate the succesor
            continue
        end
        else
          if (succ^.ai_parameters and ON_CLOSED)>0 then
          //It is on closed. Let"s throw it away since
          //we don"t want to propagate
          continue;
      end
      else
      begin
        //Succesor wasn"t generated yet during this search
        succ^.id:=1;
        succ^.g:=g;
        succ^.parent:=best_node;
        succ^.depth:=best_node^.depth+1;
        succ^.h:=_h;
        succ^.ai_parameters:=ON_OPEN;
      end;

      //Insert succesor in open
      if (open=nil) then
      begin
        open:=succ; open^.right:=nil; open^.left:=nil;
      end
      else
      begin
        current:=open; previous:=nil;
        while(current<>nil) do
        begin
          {inc(sorts);}
          if (current^.g+current^.h<succ^.g+succ^.h) then
          begin
            previous:=current; current:=current^.right;
          end
          else
            break;
        end;
        if (previous<>nil) then
        begin
          succ^.right:=previous^.right;
          if (succ^.right<>nil) then
            succ^.right^.left:=succ;
          previous^.right:=succ;
          succ^.left:=previous;
        end
        else
        begin
          succ^.right:=open;
          succ^.left:=nil;
          open^.left:=succ;
          open:=succ;
        end;
      end;
   end;
end;


 
Zer0 ©   (2005-05-14 13:11) [12]

const direction_cost:array[0..7] of integer=(4,6,4,6,4,6,4,6);
     direction_delta:array[0..7] of array[0..1] of integer=((0,-1),(-1,-1),(-1,0),(-1,1),(0,1),(1,1),(1,0),(1,-1));

{const direction_cost:array[0..7] of integer=(4,4,4,4,6,6,6,6);
     direction_delta:array[0..7] of array[0..1] of integer=((0,-1),(-1,0),(0,1),(1,0),(-1,-1),(-1,1),(1,1),(1,-1));}

     ON_OPEN=1;
     ON_CLOSED=2;

     AVOID_UNITS=1;
     AVOID_OBSTACLES=2;


 
Kerk ©   (2005-05-14 18:40) [13]

А мог бы просто ссылку кинуть.... :)


 
Zer0 ©   (2005-05-14 22:01) [14]

ссылки на это не существует
ну а если бы и была то прожила бы недолго, я не люблю на долго файлы в сеть выкладывать - а в форуме будет жыть вечно =)


 
Kerk ©   (2005-05-14 22:36) [15]

Zer0 ©   (14.05.05 22:01) [14]

не хочешь ложить к себе, есть специализированные ресурсы..
http://delphibase.sbp.ru
http://kladovka.net.ru
это из тех, что с мастаками рядом.. а так вообще дофига :)

ну ладно.. это я уж придираюсь и пытаюсь рекламировать :))))


 
OSokin ©   (2005-05-15 16:06) [16]

Мне Сервелат волновой высылал, могу тебе переслать. А так, лучше подождать окончания конкурса, куча примеров будет...


 
Zak3D[@Tm] ©   (2005-05-24 14:09) [17]

OSokin
Он наверно на конкурс и спрашивал =)


 
keal   (2005-05-27 13:42) [18]

волновой - ресурсоемкий
астар - путь на карте некрасивый и глючит

можли ли сделать гибрид этих алгоритмов?

что за конкурс? O_O


 
XProger ©   (2005-05-27 14:52) [19]

keal, сам ты некрасивый и глючный


 
keal   (2005-05-27 14:55) [20]

XProger, а ты меня видел?

астар обходит преграды десятой дорогой, и при этом делает невероятные зигзаги.


 
XProger ©   (2005-05-27 15:06) [21]

keal, обходит он по самому дешёвому пути! А в том что ты перечислил виноваты только твоя голова и руки...


 
keal   (2005-05-27 15:15) [22]

XProger
> keal, обходит он по самому дешёвому пути! А в том что ты
> перечислил виноваты только твоя голова и руки...


руки у меня не кривые, и голова в порядке.
а астар из всех самых дешевых выбирает самый заковыристый.


 
П7   (2005-05-27 16:15) [23]


> keal   (27.05.05 15:15) [22]

сам-то понял чё сказл? (:


 
keal   (2005-05-27 16:21) [24]

если нашел тайный смылс в моих словах, то поделись


 
keal   (2005-05-27 16:52) [25]

http://www.keal21.narod.ru/index.html


 
XProger ©   (2005-05-27 17:19) [26]

Да скорее всего это кастрированный (может и тобою) астар, т.е. без учёта расстояния и весов на вершинах графа :) Это и объясняет кривизну твоего примера...


 
keal   (2005-05-27 17:21) [27]

я его не изменял.


 
keal   (2005-05-27 17:32) [28]

это все же мои глюки :(
загрузил новый рисунок с нормальной проги, пить все же не самый короткий.


 
OSokin ©   (2005-05-27 21:33) [29]

ЗЫ конкурс на code.rpro.ru. Там как раз сейчас Lines делаем.


 
XProger ©   (2005-05-27 22:41) [30]

keal, ты сначала почитай про сам алгоритм, потом напиши его реализацию САМ! А затем прийди и скажи, что тебя не устраивает...


 
Zer0 ©   (2005-05-28 17:49) [31]

[18] keal
у тебя в проге плохо подобран вес функции heuristic, если его уменьшить то путь станет заметно лучше, однако длительность поиска возрастет.


 
XProger ©   (2005-05-28 17:54) [32]

У него в проге просто расстояние (вес) по диагонали равно расстоянию по горизонтали (вертикали) всего-навсего...
Но для диагоналей надо бы на sqrt(2) домножать вес +)


 
Zer0 ©   (2005-05-28 18:40) [33]

точно =)

похожая ситуация когда путь "притягивается" к конечной точке возникала и у меня в время экспериментов с эвристической функцией.



Страницы: 1 вся ветка

Текущий архив: 2005.09.25;
Скачать: CL | DM;

Наверх




Память: 0.56 MB
Время: 0.034 c
14-1125280392
Булат
2005-08-29 05:53
2005.09.25
справочник


14-1125744307
Cardinal
2005-09-03 14:45
2005.09.25
! Пятна на дисплее сквозь солнечные очки


1-1125317950
Cherrex
2005-08-29 16:19
2005.09.25
Как динамически добавить компонент на форму


14-1125978782
Ozone
2005-09-06 07:53
2005.09.25
VideoAssm Home Edition :) (зацените)


14-1125250066
Ксардас
2005-08-28 21:27
2005.09.25
Что это за сетевая атака такая Helkern?