mIRC Home    About    Download    Register    News    Help

Print Thread
#125191 15/07/05 12:51 PM
Joined: Sep 2004
Posts: 73
S
SteeleR Offline OP
Babel fish
OP Offline
Babel fish
S
Joined: Sep 2004
Posts: 73
i'm trying to make a pathfindin script ... useing A* method .. but i must have mess it up somewhere .. so i need help ...

basicly i don't need the hole path .. just the next noddle ... assuming i got the map, starting point and target point ...

Code:
alias setcurrent {
  set %i 1 
  set %min 1
  while %i <= %olistitems {
    if $calc(%olist.g [ $+ [ %min ] ] + %olist.h [ $+ [ %min ] ]) > $calc(%olist.h [ $+ [ %i ] ] + %olist.g [ $+ [ %i ] ]) { set %min %i }
    inc %i
  }
  set %current.x %olist.x [ $+ [ %min ] ]
  set %current.y %olist.y [ $+ [ %min ] ]
  set %current.g %olist.g [ $+ [ %min ] ]
  set %current.h %olist.h [ $+ [ %min ] ]
  set %olist.x [ $+ [ %min ] ] %olist.x [ $+ [ %olistitems ] ]
  set %olist.y [ $+ [ %min ] ] %olist.y [ $+ [ %olistitems ] ]
  set %olist.g [ $+ [ %min ] ] %olist.g [ $+ [ %olistitems ] ]
  set %olist.h [ $+ [ %min ] ] %olist.h [ $+ [ %olistitems ] ]
  dec %olistitems
}

alias clistadd {
  inc %clistitems
  set %clist.x [ $+ [ %clistitems ] ] $1
  set %clist.y [ $+ [ %clistitems ] ] $2
  set %clist.g [ $+ [ %clistitems ] ] $3
  set %clist.h [ $+ [ %clistitems ] ] $calc($abs(%current.x - %d.x) + $abs(%current.y - %d.y))
  set %clist.px [ $+ [ %clistitems ] ] $4
  set %clist.py [ $+ [ %clistitems ] ] $5
  return 1
}

alias clistexists {
  set %i 1
  while %i <= %clistitems {
    if (%clist.x [ $+ [ %i ] ] == $1 && %clist.y [ $+ [ %i ] ] == $2) { return 1 }
    inc %i
  }
  return 0
}

alias olistexists {
  set %i 1
  while %i <= %olistitems {
    if (%olist.x [ $+ [ %i ] ] == $1 && %olist.y [ $+ [ %i ] ] == $2) { return 1 }
    inc %i
  }
  return 0
}

alias olistadd {
  inc %olistitems
  set %olist.x [ $+ [ %olistitems ] ] $1
  set %olist.y [ $+ [ %olistitems ] ] $2
  set %olist.g [ $+ [ %olistitems ] ] $3
  set %olist.h [ $+ [ %olistitems ] ] $calc($abs(%current.x - %d.x) + $abs(%current.y - %d.y))
  set %olist.px [ $+ [ %olistitems ] ] $4
  set %olist.py [ $+ [ %olistitems ] ] $5
  return 1
}

;**************************************************************************************
alias findpath {
  set %olistitems 0 | set %clistitems 0
  set %start.x $1 | set %start.y $2
  .echo -a $olistadd($1,$2,0,$1,$2)
  set %current.x $1 | set %current.y $2
  while (%current.x != %d.x && %current.y != %d.y) {
    setcurrent ;;removes from open list :)
    .echo -a $clistadd(%current.x,%current.y,%current.g,%current.px,%current.py)
    set %a -1 | 
    while %a <= 1 {
      set %b -2
      while %b <= 0 {
        inc %b
        if (%a == 0 && %b == 0) { continue }
        if (%a != 0 && %b != 0) { continue }
        if $clistexists($calc(%current.x + %a),$calc(%current.y + %b)) == 1 { continue }
        if (%diggermap [ $+ [ $calc(%current.x + %a) ] ] [ $+ [ $calc(%current.y + %b) ] ] == enemy || %diggermap [ $+ [ $calc(%current.x + %a) ] ] [ $+ [ $calc(%current.y + %b) ] ] == empty || %diggermap [ $+ [ $calc(%current.x + %a) ] ] [ $+ [ $calc(%current.y + %b) ] ] == digger) { 
          ;*****************************************************************************************************************************************
          if ($olistexists($calc(%current.x + %a),$calc(%current.y + %b)) == 0) { .echo -a $olistadd($calc(%current.x + %a),$calc(%current.y + %b),$calc(%current.g + 10),%current.x,%current.y) }
                    ;*****************************************************************************************************************************************
        }
      }
      inc %a
    }
if ($calc(%current.x + %a) == %d.x && $calc(%current.y + %b) == %d.y) { return 1 }
          if %olistitems == 0 { return 0 }
  }
}



%diggermap [] [] is the 2D map ... %d.x/%d.y is the finishing point ... and the findpath function takes 2 parameter -> the start point smile


plz ...help smile))))))))))

Last edited by SteeleR; 15/07/05 01:30 PM.

HanPeg HanPeg u BuHaru HanPeg nPu noPa}|{eHue kParoM u nAk HanPeg
#125192 15/07/05 01:35 PM
Joined: Dec 2002
Posts: 83
D
Babel fish
Offline
Babel fish
D
Joined: Dec 2002
Posts: 83
$nopath can't help you ?

#125193 15/07/05 01:45 PM
Joined: Sep 2004
Posts: 73
S
SteeleR Offline OP
Babel fish
OP Offline
Babel fish
S
Joined: Sep 2004
Posts: 73
it's not the path of a filename ...
it's 2D / 3D map with obsticles and searching the shortest ( or in my case any ) way fpom the starting pint to the finishing one smile


HanPeg HanPeg u BuHaru HanPeg nPu noPa}|{eHue kParoM u nAk HanPeg
#125194 15/07/05 02:22 PM
Joined: Oct 2004
Posts: 8,330
Hoopy frood
Offline
Hoopy frood
Joined: Oct 2004
Posts: 8,330
Hehe... This looks fun. laugh

Commercial games written in major programming languages often have pathfinding problems. It should be interesting if mIRC scripting can handle pathfinding well enough.

Without doing the code, I'd try this sort of thing.

1) Check if a straight path works. If so, it's easy. If not, continue.

2) Find the first thing in your path. Find the right and left edges of the object (you should have these values already).

3) Calculate distance in straight line from the starting point to the right edge of that object. Then see if there is a straight line from there to your targe. If there is, then calculate total distance from start to right edge to target.

If not, keep that information, but try the left edge of the object. If there is a straight line from there, then calculate the total distance from the start to the left edge to the target.

Assuming that there is a straight line from either edge to the target, then determine which distance is shorter and use that.

If there is not a straight line from the edges, then you need to repeat this for the next object(s) in your path. Check both edges, find distance, etc.

Code:
                     (t)

                  <------>

                     (s)


In this example (I can't draw well here, but you'll get the idea), you can see (s) = start, (t) = target, and the <-----> is the wall. This one is easy... go from start to left corner to target. Then from start to right corner to target. Find shortest path.

HINT: By "edge" I am not regerring to the front corners of an object as that won't work well. You need to go in a line that touches a front corner and stops halfway between the front and back of the object.


Invision Support
#Invision on irc.irchighway.net
#125195 15/07/05 02:27 PM
Joined: Sep 2004
Posts: 73
S
SteeleR Offline OP
Babel fish
OP Offline
Babel fish
S
Joined: Sep 2004
Posts: 73
mine script works.. but only when the starting point is in the corner of the target :
Code:

        (p)(t)
        (s)



and then it move the pointer to the (p) point ...
have no idea why it doesn't go to the target after that .. or why it works only in that way ...

Last edited by SteeleR; 15/07/05 02:28 PM.

HanPeg HanPeg u BuHaru HanPeg nPu noPa}|{eHue kParoM u nAk HanPeg
#125196 15/07/05 02:45 PM
Joined: Oct 2004
Posts: 8,330
Hoopy frood
Offline
Hoopy frood
Joined: Oct 2004
Posts: 8,330
I can't actually work on the script and find what's up with it right now, so I know I'm not going to be a great help, but I'm trying. smile

If the pointer goes to (p) instead of (t), then it seems as if you are saving the Y location, but not the X location. That, or you are passing your X location the wrong variable (that of the corner).

Since you are finding a path to (t), then you already have those values... I'd make sure that your new target ends up having the same values.

Just as a note... If you go from just point to point individually, you won't always find the shortest path (in most cases, you won't). That's why I mentioned trying to complete the path first and see which is the shortest.

So things don't get out of hand, I'd set a limit for how many "waypoints" to check, though. For example, you might want to limit the number of objects you'll try to pass when finding the shortest distance to 5 or 10. If there are more objects in the way, then take the shortest distance to there and repeat. The reason being, that you need to store data on all the paths to find which is the shortest. And for every object you encounter, you are adding another 2 paths.

Example using an outline (best way to show it here, I think):

1. Start
1.1 Left of Object #1
1.1.1 Left of Object #2 after going left of Object #1
1.1.1.1 Left of Object #3 after going left of Object #2
1.1.1.2 Right of Object #3 after going left of Object #2
1.1.2.1 Left of Object #3 after going right of Object #2
1.1.2.2 Right of Object #3 after going right of Object #2

Etc.

As you can see, this gets exponentially difficult, the more objects you try to check at once. It becomes a matter of which is more important --- Best path or Fewest calculations.

By doing more than one point at a time, you will get a better path. The greater number of points at a time, the better the path.

However, more points also equals more data to store and compare. 5-10 limit should work best for giving an quality route without getting too crazy with path data.

Btw, for calculating the distance, I'd use geometry... SIN/COS/TAN for caluclating the hypoteneus. laugh

That makes it much easy to get distance from point to point using X/Y points.


Invision Support
#Invision on irc.irchighway.net
#125197 15/07/05 02:52 PM
Joined: Sep 2004
Posts: 73
S
SteeleR Offline OP
Babel fish
OP Offline
Babel fish
S
Joined: Sep 2004
Posts: 73
10x for trying to help but .... i want to know just the next nobble cause that's the most occurate method when the objects are moving ( as in my case ) ... the A* alrorithm is one of the bests ... i have wrote it successfully several times in VC++ but in mIRC Scripting .. it's hard to copy from an Object languagle ... sinse the principle is the same ... i guess i got a technical error somewhere ... that i can't see ...
Guess haveing this script .. and rewriting it may fix the problem ...and increese the speed of the script ... cause i want to run it once per 0.5 secs ...


HanPeg HanPeg u BuHaru HanPeg nPu noPa}|{eHue kParoM u nAk HanPeg
#125198 15/07/05 03:11 PM
Joined: Oct 2004
Posts: 8,330
Hoopy frood
Offline
Hoopy frood
Joined: Oct 2004
Posts: 8,330
Ah... moving objects. smile


Invision Support
#Invision on irc.irchighway.net
#125199 15/07/05 03:47 PM
Joined: Apr 2004
Posts: 871
Sat Offline
Hoopy frood
Offline
Hoopy frood
Joined: Apr 2004
Posts: 871
A few points, which should help you but do not necessarily solve all your problems:

1) In the outer loop condition,
Quote:
while (%current.x != %d.x && %current.y != %d.y) {

I'm sure you'll want to use OR instead of AND here, otherwise the algorithm will stop as soon as it hits the row or column that the end position is in (as opposed to the end position itself).

2) I think you moved around the test,
Quote:
if ($calc(%current.x + %a) == %d.x && $calc(%current.y + %b) == %d.y) { return 1 }

since you first posted the algorithm; it is now in the incorrect place, it should be in the most inner loop, for example right before the $clistexists test.

3) You're using %current.px and %current.py in /findpath, but these aren't set anywhere. Also, you're not moving the .px and .py variables along with the rest in /setcurrent. Both of these things will make it impossible to find out which path you actually took, when the algorithm is done (I assume that the code for that is not part of what you posted here).

4) In general, adding alot of /echo statements to see what's going on exactly, will help tremendously in the debugging process.

5) Use of hashtables will most likely speed up the whole algorithm considerably, although that will only be effective if you redesign the helper functions a bit.


Saturn, QuakeNet staff
#125200 15/07/05 04:00 PM
Joined: Sep 2004
Posts: 73
S
SteeleR Offline OP
Babel fish
OP Offline
Babel fish
S
Joined: Sep 2004
Posts: 73
Quote:
1) In the outer loop condition,

Quote:
while (%current.x != %d.x && %current.y != %d.y) {


I'm sure you'll want to use OR instead of AND here, otherwise the algorithm will stop as soon as it hits the row or column that the end position is in (as opposed to the end position itself).


10q @Sat ... that was the problem smile
if i ever met u ... u've got a beer from me smile




just one more question ....
when i use parametrized functions ... line $zzz(aaa,bbb)
I must echo them ... otherwise an error appears ...
using .echo $func() in the upper script doesn't help ... an error continued to occure ... what to do ? smile

Last edited by SteeleR; 15/07/05 04:03 PM.

HanPeg HanPeg u BuHaru HanPeg nPu noPa}|{eHue kParoM u nAk HanPeg
#125201 15/07/05 04:06 PM
Joined: Sep 2003
Posts: 4,230
D
Hoopy frood
Offline
Hoopy frood
D
Joined: Sep 2003
Posts: 4,230
I dont really have a slightest idea what a path finder programs ment to do, well i do but im tired, but i saw two things that maybe causing problems.

Code:
alias findpath {
  set %olistitems 0 | set %clistitems 0
  set %start.x $1 | set %start.y $2
  [color:blue].echo -a $olistadd($1,$2,0,$1,$2)
  set %current.x $1 | set %current.y $2 .............................. Your initially setting these but have already refrenced them in the above $identifier [/color]
  while (%current.x != %d.x &amp;&amp; %current.y != %d.y) {
    setcurrent ;;removes from open list :)
    .echo -a $clistadd(%current.x,%current.y,%current.g,%current.px,%current.py)
    set %a -1 | 
    while %a &lt;= 1 {
      set %b -2
      while %b &lt;= 0 {
        inc %b
        if (%a == 0 &amp;&amp; %b == 0) { continue }
        if (%a != 0 &amp;&amp; %b != 0) { continue }
        if $clistexists($calc(%current.x + %a),$calc(%current.y + %b)) == 1 { continue }
        if ([color:blue]%diggermap [ $+ [ $calc(%current.x + %a) ] ] [ $+ [ $calc(%current.y + %b) ] ][/color] == enemy || [color:blue]%diggermap [ $+ [ $calc(%current.x + %a) ] ] [ $+ [ $calc(%current.y + %b) ] ][/color] == empty || [color:blue]%diggermap [ $+ [ $calc(%current.x + %a) ] ] [ $+ [ $calc(%current.y + %b) ] ][/color] == digger) {
        [color:blue]This is ment to represent a 2 dimentional array, however the location (1,13) makes %diggermap113 and location (11,3) also makes %diggermap113
        this could be corrected by using %diggermap [ $+ [ Xn ] $+ ] ~ [ $+ [ Yn ] ] producing %diggermapXn~Yn aka %diggermap1~13 &amp; %diggermap11~3[/color]


Beyond these things i dont know what might be right or wrong.

#125202 15/07/05 04:08 PM
Joined: Apr 2004
Posts: 871
Sat Offline
Hoopy frood
Offline
Hoopy frood
Joined: Apr 2004
Posts: 871
You could use /.echo -q $zzz(aaa,bbb), that will basically just throw away the result of the identifier.

Or, you can simply call them as aliases. /zzz aaa bbb style. That will also just execute them and do nothing with the result - in this case the slight difference between parsing of parameters when calling zzz as alias or identifier, won't affect the outcome.


Saturn, QuakeNet staff
#125203 15/07/05 04:10 PM
Joined: Sep 2004
Posts: 73
S
SteeleR Offline OP
Babel fish
OP Offline
Babel fish
S
Joined: Sep 2004
Posts: 73
10x to both smile


HanPeg HanPeg u BuHaru HanPeg nPu noPa}|{eHue kParoM u nAk HanPeg
#125204 15/07/05 04:13 PM
Joined: Sep 2003
Posts: 4,230
D
Hoopy frood
Offline
Hoopy frood
D
Joined: Sep 2003
Posts: 4,230
Quote:
when i use parametrized functions ... line $zzz(aaa,bbb)
I must echo them ... otherwise an error appears ...
using .echo $func() in the upper script doesn't help ... an error continued to occure ... what to do ? smile


for you just dont return anything

Code:
alias blah { 
  .... code here ....
  return
}

alias glob {
  echo glob
  $blah($1,2,3,4)
  echo goes
  $blah($1,2,3,4)
  echo blob
}



If u want to return something then use this
!.echo -q $blah(x,y,z)

! to ensure its really echo
. to make its output quite
-q dont display any output if its quite
The functions are still carried out, just not echoed.


Link Copied to Clipboard