Author Topic: A* pathfinding in QB64  (Read 6013 times)

0 Members and 1 Guest are viewing this topic.

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
A* pathfinding in QB64
« on: August 11, 2018, 12:30:44 pm »
Does anybody know of someone trying to implement an A* Pathfinding routine in QB64. the examples I've found are in other languages and trying to convert it to QB64 just isn't happening for me. I think I understand it but for some reason my mind just wont convert it to basic code. its probably easier than I think it should be and thats why but its just not happening for me yet.
Granted after becoming radioactive I only have a half-life!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: A* pathfinding in QB64
« Reply #1 on: August 11, 2018, 12:57:25 pm »
HiCobalt,

I remember a discussion not long ago:
https://www.qb64.org/forum/index.php?topic=321.0

There is a method for Windows of creating a temp file in a shell of a directory listing from which you can get files and/or folders from which you access from QB64 for purposes of getting file(s) or subFolder lists. It is also possible to build a navigator from that. There is a fine example in Wiki from which I created a file retriever.

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: A* pathfinding in QB64
« Reply #2 on: August 11, 2018, 01:03:59 pm »
Wrong pathfinding bplus.
I mean from Point A to Point B on a map going around obstructions.
Granted after becoming radioactive I only have a half-life!

FellippeHeitor

  • Guest
Re: A* pathfinding in QB64
« Reply #3 on: August 11, 2018, 02:42:07 pm »
Perhaps from Javascript and with a good tutor you can convert it easier:

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: A* pathfinding in QB64
« Reply #4 on: August 11, 2018, 02:47:58 pm »
Would a map be a listing of which point connects to which point?

And a path be a string of points from a to b?

And do you want the shortest path or any old path that gets you there?
« Last Edit: August 11, 2018, 03:00:41 pm by bplus »

FellippeHeitor

  • Guest
Re: A* pathfinding in QB64
« Reply #5 on: August 11, 2018, 03:28:30 pm »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: A* pathfinding in QB64
« Reply #6 on: August 11, 2018, 03:53:15 pm »
Thanks I found this


Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: A* pathfinding in QB64
« Reply #7 on: August 11, 2018, 04:21:04 pm »
Maybe it help.... works not full correctly... press key for move. It is different solution. I use many IF conditions...

Code: QB64: [Select]
  1.  
  2. 'maze demo - quad go from sector A to sector B and respect walls:
  3.  
  4. DIM maze(99, 99) AS _BYTE
  5. FOR Wall = 1 TO 1000
  6.     begin:
  7.     x = RND * 99
  8.     y = RND * 99
  9.     IF x > 99 OR y > 99 THEN GOTO begin
  10.     IF maze(x, y) = 0 THEN maze(x, y) = 1 ELSE GOTO begin
  11. NEXT Wall
  12.  
  13. 'let say, start position for point is 1,1, end position is 100,100
  14. maze(1, 1) = 2: x = 0: y = 0
  15. SCREEN _NEWIMAGE(1000, 1000, 256)
  16.  
  17. FOR x = 0 TO 99
  18.     FOR y = 0 TO 99
  19.  
  20.         IF maze(x, y) = 2 THEN clr = 15
  21.         IF maze(x, y) = 1 THEN clr = 9
  22.         IF maze(x, y) = 0 THEN clr = 0
  23.         LINE (x * 10, y * 10)-((x * 10) - 9, (y * 10) - 9), clr, B 'show map
  24. NEXT y, x
  25. mX = 1
  26. mY = 1
  27.  
  28.     s:
  29.  
  30.     IF posX + mX > 98 OR posX + mX < 1 THEN mX = -1 * mX
  31.     IF posY + mY > 98 OR posY + mY < 1 THEN mY = -1 * mY
  32.  
  33.  
  34.     oldX = posX
  35.     oldY = posY
  36.  
  37.     oldmx = mX
  38.     oldmy = mY
  39.  
  40.  
  41.     IF maze(posX + mX, posY + mY) <> 1 THEN
  42.         posX = posX + mX
  43.         posY = posY + mY
  44.     END IF
  45.  
  46.     LINE (posX * 10, posY * 10)-((posX * 10) - 9, (posY * 10) - 9), 15, B 'show map
  47.     LINE (oldX * 10, oldY * 10)-((oldX * 10) - 9, (oldY * 10) - 9), 0, B 'show map
  48.  
  49.  
  50.  
  51.  
  52.  
  53.  
  54.  
  55.     IF posX + mX > 0 AND posX + mX < 99 AND posY + mY > 0 AND posY + mY < 99 THEN
  56.  
  57.         t = RND * 10
  58.         IF t > .55 THEN
  59.  
  60.             IF posY > 0 AND posY < 98 THEN
  61.                 IF oldmx = mX AND maze(posX, posY - 1) <> 1 THEN mY = -1
  62.                 IF oldmx = mX AND maze(posX, posY + 1) <> 1 THEN mY = 1
  63.             END IF
  64.  
  65.             IF posX > 0 AND posX < 98 THEN
  66.                 IF oldmy = mY AND maze(posX - 1, posY) <> 1 THEN mX = -1
  67.                 IF oldmy = mY AND maze(posX + 1, posY) <> 1 THEN mX = 1
  68.             END IF
  69.  
  70.         END IF
  71.  
  72.  
  73.  
  74.         IF maze(posX, posY - 1) <> 1 AND mY = 0 THEN mY = -1
  75.         IF maze(posX, posY + 1) <> 1 AND mY = 0 THEN mY = 1
  76.         IF maze(posX - 1, posY) <> 1 AND mX = 0 THEN mX = -1
  77.         IF maze(posX + 1, posY) <> 1 AND mX = 0 THEN mX = 1
  78.  
  79.  
  80.         IF maze(posX + mX, posY + mY) = 1 THEN
  81.             BEEP
  82.             IF maze(posX + 1, posY) <> 1 THEN mX = 1: mY = 0: GOTO s
  83.             IF maze(posX, posY + 1) <> 1 THEN mX = 0: mY = 1: GOTO s
  84.             IF maze(posX - 1, posY) <> 1 THEN mX = -1: mY = 0: GOTO s
  85.             IF maze(posX, posY - 1) <> 1 THEN mX = 0: mY = -1: GOTO s
  86.         END IF
  87.  
  88.     END IF
  89.     SLEEP
  90.  
  91.  

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: A* pathfinding in QB64
« Reply #8 on: August 11, 2018, 04:44:09 pm »
But if  you meant way, how to draw lines between two points (as LINE, but step by step with PSET), so i have writed program for it, he works correctly now in all directions,

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: A* pathfinding in QB64
« Reply #9 on: August 11, 2018, 05:08:06 pm »
Fellippe, thank you for link. This way can be used for new PAINT program - not limited to 1 border color.

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: A* pathfinding in QB64
« Reply #10 on: August 12, 2018, 10:51:38 am »
Thanks guys. I think I'm finally getting my head wrapped round this.
And somehow I managed to find this bit of code actually written in QB64.

 by u/ybycomh around 4 years ago.
Code: QB64: [Select]
  1.  
  2.  
  3. TYPE PathCoord
  4.     pos AS Coord ' Coordinates of position on map
  5.     parent AS Coord ' Coordinates of previous position on path
  6.     g AS INTEGER ' G cost value
  7.     h AS INTEGER ' H cost value
  8.     f AS INTEGER ' F = G + H (total movement cost)
  9.     status AS INTEGER ' 0 for unsearched, 1 for open, 2 for closed (explored)
  10.  
  11. DIM SHARED TargetFound
  12. DIM Start AS Coord, Target AS Coord
  13.  
  14. CONST RandomSearch = 1 ' 1 => Randomly decide intesnity of search estimations (rush)
  15. CONST DEBUG = 50 ' 0 => Debug mode off
  16. '''''''''''''''''' DEBUG > 0 => Debug mode on, where DEBUG is animation speed
  17. '''''''''''''''''' -1 => Debug mode on with SLEEPs between frames
  18. CONST Resx = 1024 ' Set Screen Resolution
  19. CONST Resy = 768 ' If you change it, the map will automatically fill the screen
  20. CONST FPS = 20 ' Animation Speed
  21. CONST TileSize = 10 ' Set size of square tiles
  22. CONST MinMapDensity = 10 ' Set range of density to fill generated maps with walls
  23. CONST MaxMapDensity = 35
  24. CONST MinWallLength = MinMapDensity / 2
  25. CONST MaxWallLength = MaxMapDensity / 2
  26.  
  27. Mapx = INT((Resx * .95) / TileSize) ' Dimension SampleMap to fit to screen
  28. Mapy = INT((Resy * .95) / TileSize)
  29. DIM SampleMap(Mapx, Mapy)
  30.  
  31. MaxPathLength = Mapx * Mapy * 0.5 ' Max number of saved path positions
  32. DIM Path(MaxPathLength) AS Coord '' Dimension array of path coords to be filled in later
  33.  
  34. CLS: SCREEN _NEWIMAGE(Resx, Resy, 256)
  35.  
  36.     REDIM Path(MaxPathLength) AS Coord, SampleMap(Mapx, Mapy)
  37.  
  38.     FOR ix = 0 TO Mapx
  39.         SampleMap(ix, 0) = 1: SampleMap(ix, Mapy) = 1
  40.     NEXT
  41.     FOR iy = 0 TO Mapy
  42.         SampleMap(0, iy) = 1: SampleMap(Mapx, iy) = 1
  43.     NEXT
  44.  
  45.     MapDensity = INT((MaxMapDensity - MinMapDensity) * RND) + MinMapDensity
  46.     FOR ix = 0 TO Mapx
  47.         FOR iy = 0 TO Mapy
  48.             RandNumber = INT(100 * RND) + 1
  49.             IF RandNumber < MapDensity THEN SampleMap(ix, iy) = 1
  50.         NEXT
  51.     NEXT
  52.  
  53.     FOR i = 0 TO (MapDensity * 2)
  54.         WallDirection = INT(2 * RND) + 1
  55.         WallLength = INT((MaxWallLength - MinWallLength) * RND) + MinWallLength
  56.  
  57.         IF WallDirection = 1 THEN
  58.             WallX = INT((Mapx) * RND)
  59.             IF WallX + WallLength > Mapx THEN WallX = Mapx - WallLength
  60.             iy = INT(Mapy * RND)
  61.             FOR ix = WallX TO (WallX + WallLength)
  62.                 SampleMap(ix, iy) = 1
  63.             NEXT
  64.         END IF
  65.  
  66.         IF WallDirection = 2 THEN
  67.             WallY = INT((Mapy) * RND)
  68.             IF WallY + WallLength > Mapy THEN WallY = Mapy - WallLength
  69.             ix = INT(Mapx * RND)
  70.             FOR iy = WallY TO (WallY + WallLength)
  71.                 SampleMap(ix, iy) = 1
  72.             NEXT
  73.         END IF
  74.     NEXT
  75.  
  76.     DO
  77.         Start.x = INT((Mapx - 2) * RND) + 2 ' Set start position
  78.         Start.y = INT((Mapy - 2) * RND) + 2
  79.         IF Collision(Start, SampleMap()) = 0 THEN EXIT DO
  80.     LOOP
  81.     DO
  82.         Target.x = INT((Mapx - 2) * RND) + 2 ' Set target position
  83.         Target.y = INT((Mapy - 2) * RND) + 2
  84.         IF Collision(Target, SampleMap()) = 0 THEN EXIT DO
  85.     LOOP
  86.  
  87.     CALL SetPath(Path(), Start, Target, SampleMap())
  88.  
  89.     i = 0
  90.     DO: _LIMIT FPS: CLS
  91.  
  92.         FOR ix = 0 TO Mapx
  93.             FOR iy = 0 TO Mapy
  94.                 IF SampleMap(ix, iy) = 1 THEN CALL DrawBlock(ix, iy, 15)
  95.             NEXT
  96.         NEXT
  97.  
  98.         COLOR 4
  99.         IF TargetFound = 0 THEN LOCATE 5, 5: PRINT "TARGET CANNOT BE REACHED": _DISPLAY: _DELAY 2: EXIT DO
  100.  
  101.         i = i + 1
  102.         CALL DrawBlock(Path(i).x, Path(i).y, 10)
  103.         CALL DrawBlock(Target.x, Target.y, 4)
  104.  
  105.         IF Path(i).x = Target.x AND Path(i).y = Target.y THEN EXIT DO
  106.         IF i = MaxPathLength THEN EXIT DO
  107.         IF INKEY$ = CHR$(27) THEN END
  108.         _DISPLAY
  109.     LOOP
  110.     i = 0
  111.     ERASE Path
  112.     ERASE SampleMap
  113.     TargetFound = 0
  114.     IF INKEY$ = CHR$(27) THEN END
  115.  
  116. SUB SetPath (Path() AS Coord, StartPos AS Coord, TargetPos AS Coord, Map())
  117.  
  118. MaxPathLength = UBOUND(path)
  119. Mapx = UBOUND(Map, 1)
  120. Mapy = UBOUND(Map, 2)
  121.  
  122. DIM PathMap(Mapx, Mapy) AS PathCoord
  123.  
  124. FOR ix = 0 TO Mapx
  125.     FOR iy = 0 TO Mapy
  126.         PathMap(ix, iy).pos.x = ix
  127.         PathMap(ix, iy).pos.y = iy
  128.     NEXT
  129.  
  130. DIM Cpos AS Coord: Cpos = StartPos
  131. DIM SearchPathSet(4) AS PathCoord, OpenPathSet(MaxPathLength) AS PathCoord
  132.  
  133.  
  134.     PathMap(Cpos.x, Cpos.y).status = 2
  135.     count = count + 1
  136.  
  137.     IF PathMap(TargetPos.x, TargetPos.y).status = 2 THEN TargetFound = 1: EXIT DO
  138.     IF count > MaxPathLength THEN EXIT DO
  139.  
  140.     SearchPathSet(0) = PathMap(Cpos.x, Cpos.y)
  141.     SearchPathSet(1) = PathMap(Cpos.x + 1, Cpos.y)
  142.     SearchPathSet(2) = PathMap(Cpos.x - 1, Cpos.y)
  143.     SearchPathSet(3) = PathMap(Cpos.x, Cpos.y + 1)
  144.     SearchPathSet(4) = PathMap(Cpos.x, Cpos.y - 1)
  145.  
  146.     FOR i = 1 TO 4
  147.         IF Collision(SearchPathSet(i).pos, Map()) <> 1 THEN
  148.  
  149.             IF SearchPathSet(i).status = 1 THEN
  150.                 NewG = PathGCost(SearchPathSet(0).g)
  151.                 IF NewG < SearchPathSet(i).g THEN SearchPathSet(i).g = NewG
  152.             END IF
  153.  
  154.             IF SearchPathSet(i).status = 0 THEN
  155.                 SearchPathSet(i).parent = SearchPathSet(0).pos
  156.                 SearchPathSet(i).status = 1
  157.                 SearchPathSet(i).g = PathGCost(SearchPathSet(0).g)
  158.                 SearchPathSet(i).h = PathHCost(SearchPathSet(i), TargetPos)
  159.                 SearchPathSet(i).f = SearchPathSet(i).g + SearchPathSet(i).h
  160.  
  161.                 OpenPathSet(OpenPathCount) = SearchPathSet(i)
  162.                 OpenPathCount = OpenPathCount + 1
  163.             END IF
  164.         END IF
  165.     NEXT
  166.  
  167.     PathMap(Cpos.x + 1, Cpos.y) = SearchPathSet(1)
  168.     PathMap(Cpos.x - 1, Cpos.y) = SearchPathSet(2)
  169.     PathMap(Cpos.x, Cpos.y + 1) = SearchPathSet(3)
  170.     PathMap(Cpos.x, Cpos.y - 1) = SearchPathSet(4)
  171.  
  172.     IF OpenPathCount > (MaxPathLength - 4) THEN EXIT DO
  173.  
  174.     LowF = 32000: ixOptimal = 0: iyOptimal = 0
  175.     FOR i = 0 TO OpenPathCount
  176.         IF OpenPathSet(i).status = 1 AND OpenPathSet(i).f <> 0 THEN
  177.             IF OpenPathSet(i).f < LowF THEN
  178.                 LowF = OpenPathSet(i).f
  179.                 ixOptimal = OpenPathSet(i).pos.x
  180.                 iyOptimal = OpenPathSet(i).pos.y
  181.                 OptimalPath_i = i
  182.             END IF
  183.         END IF
  184.     NEXT
  185.  
  186.     IF ixOptimal = 0 AND iyOptimal = 0 THEN EXIT DO
  187.     Cpos = PathMap(ixOptimal, iyOptimal).pos
  188.     OpenPathSet(OptimalPath_i).status = 2
  189.  
  190.     IF DEBUG <> 0 THEN
  191.         CLS
  192.         FOR ix = 0 TO Mapx
  193.             FOR iy = 0 TO Mapy
  194.                 IF Map(ix, iy) = 1 THEN CALL DrawBlock(ix, iy, 15)
  195.             NEXT
  196.         NEXT
  197.         CALL DrawBlock(TargetPos.x, TargetPos.y, 4)
  198.         FOR ix = 0 TO Mapx
  199.             FOR iy = 0 TO Mapy
  200.                 IF PathMap(ix, iy).status = 1 THEN CALL DrawBlock(ix, iy, 3)
  201.                 IF PathMap(ix, iy).status = 2 THEN CALL DrawBlock(ix, iy, 10)
  202.             NEXT
  203.         NEXT
  204.         _DISPLAY
  205.         IF INKEY$ = CHR$(27) THEN END
  206.         IF DEBUG > 0 THEN _DELAY (.2 * (1 / DEBUG))
  207.         IF DEBUG = -1 THEN SLEEP
  208.     END IF
  209.  
  210. IF TargetFound = 1 THEN
  211.  
  212.     DIM backpath(MaxPathLength) AS PathCoord
  213.     backpath(0).pos = PathMap(TargetPos.x, TargetPos.y).pos
  214.  
  215.     FOR i = 1 TO count
  216.         backpath(i).pos = PathMap(backpath(i - 1).pos.x, backpath(i - 1).pos.y).parent
  217.         IF (startreached = 0) AND (backpath(i).pos.x = Start.Pos.x) AND (backpath(i).pos.y = Start.Pos.y) THEN
  218.             pathlength = i: startreached = 1
  219.         END IF
  220.     NEXT
  221.  
  222.     i = 0: startreached = 0
  223.     FOR iback = pathlength TO 0 STEP -1
  224.         IF startreached = 1 THEN i = i + 1: Path(i) = backpath(iback).pos
  225.         IF (startreached = 0) AND (backpath(iback).pos.x = Start.Pos.x) AND (backpath(iback).pos.y = Start.Pos.y) THEN
  226.             Path(i) = backpath(iback).pos
  227.             startreached = 1
  228.         END IF
  229.     NEXT iback
  230.  
  231.  
  232. FUNCTION PathGCost (ParentG)
  233. PathGCost = ParentG + 10
  234.  
  235. FUNCTION PathHCost (TilePath AS PathCoord, TargetPos AS Coord)
  236. dx = ABS(TilePath.pos.x - TargetPos.x)
  237. dy = ABS(TilePath.pos.y - TargetPos.y)
  238. distance = SQR((TargetPos.x - TilePath.pos.x) ^ 2 + (TargetPos.y - TilePath.pos.y) ^ 2)
  239. IF RandomSearch = 1 THEN SearchIntensity = INT(RND * 10)
  240. PathHCost = ((SearchIntensity / 20) + 10) * (dx + dy + ((SearchIntensity / 10) * distance))
  241.  
  242. FUNCTION Collision (Position AS Coord, Map())
  243. IF Map(Position.x, Position.y) <> 0 THEN c = 1
  244. Collision = c
  245.  
  246. SUB DrawBlock (x, y, blockcolor)
  247. x0 = ((x * TileSize) - (TileSize / 2)) + TileSize + 20
  248. y0 = ((y * TileSize) - (TileSize / 2)) + TileSize
  249. x1 = ((x * TileSize) + (TileSize / 2)) + TileSize + 20
  250. y1 = ((y * TileSize) + (TileSize / 2)) + TileSize
  251. LINE (x0, y0)-(x1, y1), blockcolor, BF
Granted after becoming radioactive I only have a half-life!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: A* pathfinding in QB64
« Reply #11 on: August 12, 2018, 12:31:07 pm »
That is pretty cool!

Alas, I have started to reinvent the wheel. Now I have something to compare my experiments with. Thanks!

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: A* pathfinding in QB64
« Reply #12 on: August 12, 2018, 01:37:02 pm »
So that's something! Thank you for sharing, I have what to study.