Author Topic: B+ Pathfinder  (Read 13730 times)

0 Members and 1 Guest are viewing this topic.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
B+ Pathfinder
« on: August 13, 2018, 09:38:26 pm »
This uses no awareness of where B is until it hits it! Therefore you could find all the B's you want on a map, not just one.

And yet, can you find a path that takes less squares?

Sure this thing zigs when no zig or zag is needed but the square counts are the same.

 
B+ Pathfinder.PNG


Code: QB64: [Select]
  1. _TITLE "PathFinder 1a, press spacebar to continue whenever it stops, press esc to quit"
  2. 'QB64 X 64 version 1.2 20180228/86  from git b301f92
  3. 'started 2018-08-11 when Colbalt asked about A* pathfinder
  4. ' He has now 2018-08-12 posted a QB64 version that is nice!
  5.  
  6. ' 2018-08-11 started PathFinder 1
  7. ' 2018-08-12 almost working but buggy backtract to point A after point B is found.
  8. ' 2018-08-13 PathFinder 1a.bas I think I have a fix for buggy path BackTrack but major surgery so this new version
  9. ' 8:38 PM 28 times in a row it worked, now diddle the size of array and loose the board text view
  10. ' 9:09 PM I have run 2 dozen tests more at least and zero bugs! on smaller and more squares.
  11. ' 9:25 PM Still no failures! Ready to show the world.
  12.  
  13.  
  14. DEFINT A-Z
  15. CONST ww = 800
  16. CONST wh = 600
  17. CONST sq = 10
  18. CONST maxx = 80
  19. CONST maxy = 60
  20.  
  21. SCREEN _NEWIMAGE(ww, wh, 32)
  22. _SCREENMOVE (1280 - ww) / 2 + 30, (760 - wh) / 2
  23.  
  24. TYPE xytype
  25.     x AS INTEGER
  26.     y AS INTEGER
  27. DIM SHARED ax, ay, bx, by
  28. DIM SHARED board(1 TO maxx, 1 TO maxy) AS STRING * 6
  29.     FOR y = 1 TO maxy
  30.         FOR x = 1 TO maxx
  31.             board(x, y) = " "
  32.         NEXT
  33.     NEXT
  34.     'with these obstacles there is no guarantee a path will exist
  35.     FOR i = 1 TO maxx * maxy * .8
  36.         ox = rand(1, maxx): oy = rand(1, maxy)
  37.         WHILE (ox = ax AND oy = ay) OR (ox = bx AND ox = by)
  38.             ox = rand(1, maxx): oy = rand(1, maxy)
  39.         WEND
  40.         board(ox, oy) = "O"
  41.     NEXT
  42.     ax = rand(1, maxx): ay = rand(1, maxy)
  43.     bx = rand(1, maxx): by = rand(1, maxy)
  44.     WHILE ax = bx AND ay = by
  45.         bx = rand(1, maxx): by = rand(1, maxy)
  46.     WEND
  47.     board(ax, ay) = "A"
  48.     board(bx, by) = "B"
  49.     displayB
  50.     WHILE NOT _KEYDOWN(32): _LIMIT 100: WEND
  51.     WHILE _KEYDOWN(32): _LIMIT 100: WEND
  52.     parentF = 1: tick = 0: parentx = 0
  53.     WHILE parentF = 1 AND parentx = 0
  54.         parentF = 0: tick = tick + 1: changes$ = ""
  55.         'IF tick > maxx * maxy THEN EXIT WHILE   'this was crude infinite loop stopper
  56.         ystart = max(ay - tick, 1): ystop = min(ay + tick, maxy)
  57.         FOR y = ystart TO ystop
  58.             xstart = max(ax - tick, 1): xstop = min(ax + tick, maxx)
  59.             'PRINT ystart, ystop, xstart, xstop
  60.             'END
  61.             FOR x = xstart TO xstop
  62.                 'check out the neighbors
  63.                 IF x - 1 >= 1 THEN xxstart = x - 1 ELSE xxstart = x
  64.                 IF x + 1 <= maxx THEN xxstop = x + 1 ELSE xxstop = x
  65.                 IF y - 1 >= 1 THEN yystart = y - 1 ELSE yystart = y
  66.                 IF y + 1 <= maxy THEN yystop = y + 1 ELSE yystop = y
  67.                 IF RTRIM$(board(x, y)) = "" THEN
  68.                     cf = 0
  69.                     FOR yy = yystart TO yystop
  70.                         FOR xx = xxstart TO xxstop
  71.                             IF xx <> x OR yy <> y THEN
  72.                                 IF RTRIM$(board(xx, yy)) = "A" OR INSTR(RTRIM$(board(xx, yy)), ",") > 0 THEN 'found a parent to assign to cell
  73.  
  74.                                     '          This had ne stuck for awhile!
  75.                                     'LOGIC BUG   board(x, y) = LTRIM$(STR$(xx)) + "," + LTRIM$(STR$(yy))
  76.                                     'can't change board until all are checked!!!!   so save up changes
  77.                                     changes$ = changes$ + LTRIM$(STR$(x)) + "," + LTRIM$(STR$(y)) + "{" + LTRIM$(STR$(xx)) + "," + LTRIM$(STR$(yy)) + "}"
  78.                                     rec (x - 1) * sq + 3, (y - 1) * sq + 3, x * sq - 3, y * sq - 3, 555
  79.                                     parentF = 1 'so will continue looping
  80.                                     cf = 1: EXIT FOR
  81.                                 END IF
  82.                             END IF
  83.                         NEXT
  84.                         IF cf THEN EXIT FOR
  85.                     NEXT
  86.                 ELSEIF RTRIM$(board(x, y)) = "A" OR INSTR(board(x, y), ",") > 0 THEN 'see if B is a neighbor
  87.                     FOR yy = yystart TO yystop
  88.                         FOR xx = xxstart TO xxstop
  89.                             IF xx <> x OR yy <> y THEN
  90.                                 IF RTRIM$(board(xx, yy)) = "B" THEN 'B conects to x, y
  91.                                     parentx = x: parenty = y 'from this we should be able to backtrack to A
  92.                                     GOTO jump1
  93.                                 END IF
  94.                             END IF
  95.                         NEXT
  96.                     NEXT
  97.                 END IF
  98.             NEXT
  99.         NEXT
  100.         jump1:
  101.         'update board with cells assigned parents
  102.         WHILE changes$ <> ""
  103.             new$ = leftOf$(changes$, "}")
  104.             changes$ = rightOf$(changes$, "}")
  105.             newxy$ = leftOf$(new$, "{")
  106.             newParent$ = rightOf$(new$, "{")
  107.             u = VAL(leftOf$(newxy$, ",")): v = VAL(rightOf$(newxy$, ","))
  108.             board(u, v) = leftOf$(newParent$, ",") + "," + rightOf$(newParent$, ",")
  109.         WEND
  110.  
  111.         '_DISPLAY
  112.         _LIMIT 10
  113.     WEND
  114.     'displayB
  115.     'either parentF = 0, no parents found for all the cells in tick or parentbx was found and we have a path to backtrack to A
  116.     BackTrack$ = ""
  117.     IF parentx THEN 'backtrack to A   note: B could be right next to A!!!
  118.         'IF parentx <> ax AND parenty <> ay THEN
  119.         frec (parentx - 1) * sq + 3, (parenty - 1) * sq + 3, sq - 6, sq - 6, 990
  120.         'END IF
  121.  
  122.         'this had me stuck for the longest time! parentx was the fix! (along with removal of blunders)
  123.         WHILE parentx 'trace the path back
  124.             ps$ = board(parentx, parenty)
  125.             parentx = VAL(leftOf$(ps$, ","))
  126.             parenty = VAL(rightOf$(ps$, ","))
  127.  
  128.             'IF parentx <> ax AND parenty <> ay THEN
  129.             frec (parentx - 1) * sq + 3, (parenty - 1) * sq + 3, sq - 6, sq - 6, 990
  130.             'END IF
  131.             'IF parentx <> ax AND parenty <> ay THEN EXIT WHILE
  132.             '_DISPLAY
  133.             _LIMIT 10
  134.         WEND
  135.         WHILE NOT _KEYDOWN(32)
  136.             IF _KEYDOWN(27) THEN END
  137.             _LIMIT 100
  138.         WEND
  139.         WHILE _KEYDOWN(32): _LIMIT 100: WEND
  140.     ELSE
  141.         rgb 999
  142.         LOCATE 15, 10: PRINT "Did not connect to B"
  143.         _DELAY 3
  144.     END IF
  145.  
  146.     'for this to be of any use, I need to format the print to exact same size, well thats easy
  147.     '
  148.     '                      this is why board is string * 6 type
  149.     '                          maxx = 16 maxy = 12  or less
  150.     'rgb 999
  151.     'CLS
  152.     'FOR y = 1 TO maxy
  153.     '    FOR x = 1 TO maxx
  154.     '        PRINT board(x, y);
  155.     '    NEXT
  156.     '    PRINT: PRINT
  157.     'NEXT
  158.     'WHILE NOT _KEYDOWN(32)
  159.     '    IF _KEYDOWN(27) THEN END
  160.     '    _LIMIT 100
  161.     'WEND
  162.     'WHILE _KEYDOWN(32): _LIMIT 100: WEND
  163. SUB displayB
  164.     FOR y = 1 TO maxy
  165.         FOR x = 1 TO maxx
  166.             SELECT CASE RTRIM$(board(x, y))
  167.                 CASE IS = "": k = 0
  168.                 CASE IS = "A": k = 9
  169.                 CASE IS = "B": k = 999
  170.                 CASE IS = "O": k = 50
  171.                     'CASE ELSE: k = 30
  172.             END SELECT
  173.             frec (x - 1) * sq, (y - 1) * sq, sq, sq, k
  174.         NEXT
  175.     NEXT
  176. SUB rec (x1, y1, x2, y2, rgbN)
  177.     rgb rgbN
  178.     LINE (x1, y1)-(x2, y2), , B
  179. SUB frec (x1, y1, w, h, rgbN)
  180.     rgb rgbN
  181.     LINE (x1, y1)-STEP(w, h), , BF
  182. SUB rgb (n) ' New (even less typing!) New Color System 1000 colors with up to 3 digits
  183.     s3$ = RIGHT$("000" + LTRIM$(STR$(n)), 3)
  184.     r = VAL(MID$(s3$, 1, 1)): IF r THEN r = 28 * r + 3
  185.     g = VAL(MID$(s3$, 2, 1)): IF g THEN g = 28 * g + 3
  186.     b = VAL(MID$(s3$, 3, 1)): IF b THEN b = 28 * b + 3
  187.     COLOR _RGB32(r, g, b)
  188. FUNCTION rand% (lo%, hi%)
  189.     rand% = INT(RND * (hi% - lo% + 1)) + lo%
  190. FUNCTION min (n1, n2)
  191.     IF n1 > n2 THEN min = n2 ELSE min = n1
  192. FUNCTION max (n1, n2)
  193.     IF n1 < n2 THEN max = n2 ELSE max = n1
  194. FUNCTION leftOf$ (source$, of$)
  195.     posOf = INSTR(source$, of$)
  196.     IF posOf > 0 THEN leftOf$ = MID$(source$, 1, posOf - 1)
  197. FUNCTION rightOf$ (source$, of$)
  198.     posOf = INSTR(source$, of$)
  199.     IF posOf > 0 THEN rightOf$ = MID$(source$, posOf + LEN(of$))
  200.  

FellippeHeitor

  • Guest
Re: B+ Pathfinder
« Reply #1 on: August 13, 2018, 09:55:01 pm »
Very much amusing to watch, Mark.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: B+ Pathfinder
« Reply #2 on: August 13, 2018, 10:18:52 pm »
Must be the zig zags! :)

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: B+ Pathfinder
« Reply #3 on: August 13, 2018, 11:10:21 pm »
I have noticed, when it does not find connection to B, I want more time to see for myself:

Mod for that (fits just before the end of the main loop):
Code: QB64: [Select]
  1.     ELSE
  2.         rgb 999
  3.         LOCATE 15, 10: PRINT "Did not connect to B"
  4.         WHILE NOT _KEYDOWN(32)
  5.             IF _KEYDOWN(27) THEN END
  6.             _LIMIT 100
  7.         WEND
  8.         WHILE _KEYDOWN(32): _LIMIT 100: WEND  '<<< BTW using spacebar several times in a row to restart the code, needs to be cleared from buffer
  9.  
  10.     END IF
  11.  

The trick to this backtracking idea was learned from coding many versions of the Snake Game.
« Last Edit: August 13, 2018, 11:13:14 pm by bplus »

Offline johnno56

  • Forum Resident
  • Posts: 1270
  • Live long and prosper.
    • View Profile
Re: B+ Pathfinder
« Reply #4 on: August 14, 2018, 04:07:23 am »
Completely off topic.... I like your colour scheme... Care to share the settings?

J
Logic is the beginning of wisdom.

FellippeHeitor

  • Guest
Re: B+ Pathfinder
« Reply #5 on: August 14, 2018, 06:19:41 am »
I believe that's preset scheme Camouflage, though I could be wrong.

Offline johnno56

  • Forum Resident
  • Posts: 1270
  • Live long and prosper.
    • View Profile
Re: B+ Pathfinder
« Reply #6 on: August 14, 2018, 06:30:00 am »
Yep. Looks like Camouflage to me too... Thanks for that...

J
Logic is the beginning of wisdom.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: B+ Pathfinder
« Reply #7 on: August 14, 2018, 06:49:55 am »
Confirmed, Camouflage, I think I remember someone recommending it, Fellippe?

Holy Son of the Universal Machine! This Pathfinder technique can be generalized to every point on the map with the same one time calculation from a given point A!

stay tuned...

Offline Ashish

  • Forum Resident
  • Posts: 630
  • Never Give Up!
    • View Profile
Re: B+ Pathfinder
« Reply #8 on: August 14, 2018, 10:44:06 am »
Nice work bplus!
This can be useful for me.
if (Me.success) {Me.improve()} else {Me.tryAgain()}


My Projects - https://github.com/AshishKingdom?tab=repositories
OpenGL tutorials - https://ashishkingdom.github.io/OpenGL-Tutorials

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: B+ Pathfinder
« Reply #9 on: August 14, 2018, 10:56:37 am »
Hi Ashish,

Actually, I could use some examples of maps to work out more practical uses.


Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: B+ Pathfinder
« Reply #10 on: August 14, 2018, 10:22:30 pm »
B+ Pathfinder 2, shows that once the map has been setup, you can find a path from any part of the map. To me, this is more powerful than what an A star Pathfinder can do.
Code: QB64: [Select]
  1. _TITLE "PathFinder 2, prepping maze as you read this."
  2. 'QB64 X 64 version 1.2 20180228/86  from git b301f92
  3. 'started 2018-08-11 when Colbalt asked about A* pathfinder
  4. ' He has now 2018-08-12 posted a QB64 version that is nice!
  5.  
  6. ' 2018-08-11 started PathFinder 1
  7. ' 2018-08-12 almost working but buggy backtract to point A after point B is found.
  8. ' 2018-08-13 PathFinder 1a.bas I think I have a fix for buggy path BackTrack but major surgery so this new version
  9. ' 2018-08-14 Pathfinder 2:  2 parts
  10. ' Part 1: creates a map, a random Home point and backtracts all the points available to move over.
  11. ' Part 2: allows clicking variaous points of map to see if path is found.
  12.  
  13. DEFINT A-Z
  14. CONST ww = 800
  15. CONST wh = 600
  16. CONST sq = 10
  17. CONST mapw = 80
  18. CONST maph = 60
  19.  
  20. SCREEN _NEWIMAGE(ww, wh, 32)
  21. _SCREENMOVE (1280 - ww) / 2 + 30, (760 - wh) / 2
  22.  
  23. DIM SHARED ax, ay, bx, by
  24. DIM SHARED board(1 TO mapw, 1 TO maph) AS STRING * 6
  25.  
  26.     'this part sets up a sample map and get's the Backtracking build into map
  27.  
  28.     FOR y = 1 TO maph
  29.         FOR x = 1 TO mapw
  30.             board(x, y) = " "
  31.         NEXT
  32.     NEXT
  33.     'with these obstacles there is no guarantee a path will exist
  34.     FOR i = 1 TO mapw * maph * .7
  35.         ox = rand(1, mapw): oy = rand(1, maph)
  36.         board(ox, oy) = "O"
  37.     NEXT
  38.     ax = rand(1, mapw): ay = rand(1, maph)
  39.     board(ax, ay) = "A"
  40.     parentF = 1: tick = 0: parentx = 0
  41.     WHILE parentF = 1 AND parentx = 0
  42.         parentF = 0: tick = tick + 1: changes$ = ""
  43.         ystart = max(ay - tick, 1): ystop = min(ay + tick, maph)
  44.         FOR y = ystart TO ystop
  45.             xstart = max(ax - tick, 1): xstop = min(ax + tick, mapw)
  46.             FOR x = xstart TO xstop
  47.                 'check out the neighbors
  48.                 IF x - 1 >= 1 THEN xxstart = x - 1 ELSE xxstart = x
  49.                 IF x + 1 <= mapw THEN xxstop = x + 1 ELSE xxstop = x
  50.                 IF y - 1 >= 1 THEN yystart = y - 1 ELSE yystart = y
  51.                 IF y + 1 <= maph THEN yystop = y + 1 ELSE yystop = y
  52.                 IF RTRIM$(board(x, y)) = "" THEN
  53.                     cf = 0
  54.                     FOR yy = yystart TO yystop
  55.                         FOR xx = xxstart TO xxstop
  56.                             IF xx <> x OR yy <> y THEN
  57.                                 IF RTRIM$(board(xx, yy)) = "A" OR INSTR(RTRIM$(board(xx, yy)), ",") > 0 THEN 'found a parent to assign to cell
  58.                                     changes$ = changes$ + LTRIM$(STR$(x)) + "," + LTRIM$(STR$(y)) + "{" + LTRIM$(STR$(xx)) + "," + LTRIM$(STR$(yy)) + "}"
  59.                                     parentF = 1 'so will continue looping
  60.                                     cf = 1: EXIT FOR
  61.                                 END IF
  62.                             END IF
  63.                         NEXT
  64.                         IF cf THEN EXIT FOR
  65.                     NEXT
  66.                 END IF
  67.             NEXT
  68.         NEXT
  69.         'update board with cells assigned parents
  70.         WHILE changes$ <> ""
  71.             new$ = leftOf$(changes$, "}")
  72.             changes$ = rightOf$(changes$, "}")
  73.             newxy$ = leftOf$(new$, "{")
  74.             newParent$ = rightOf$(new$, "{")
  75.             u = VAL(leftOf$(newxy$, ",")): v = VAL(rightOf$(newxy$, ","))
  76.             board(u, v) = leftOf$(newParent$, ",") + "," + rightOf$(newParent$, ",")
  77.         WEND
  78.         _LIMIT 300
  79.     WEND
  80.  
  81.  
  82.     'this parts displays the ability to find a path to blue square anywhere in the maze
  83.  
  84.     _TITLE "Click maze to find a path to blue square (if any), c = clear, n = new map, esc = quit"
  85.     displayB
  86.     DO
  87.         'CLS
  88.         'displayB
  89.         WHILE _MOUSEINPUT: WEND
  90.         IF _MOUSEBUTTON(1) THEN
  91.             mx = _MOUSEX - .5 * sq: my = _MOUSEY - .5 * sq
  92.             bx = mx / sq + 1: by = my / sq + 1
  93.             IF bx >= 1 AND bx <= mapw AND by >= 1 AND by <= maph THEN
  94.                 frec (bx - 1) * sq + 2, (by - 1) * sq + 2, sq - 4, sq - 4, 990
  95.                 ps$ = board(bx, by)
  96.                 parentx = VAL(leftOf$(ps$, ","))
  97.                 parenty = VAL(rightOf$(ps$, ","))
  98.                 IF parentx THEN 'backtrack to A   note: B could be right next to A!!!
  99.                     frec (parentx - 1) * sq + 3, (parenty - 1) * sq + 3, sq - 6, sq - 6, 999
  100.                     WHILE parentx 'trace the path back
  101.                         ps$ = board(parentx, parenty)
  102.                         parentx = VAL(leftOf$(ps$, ","))
  103.                         parenty = VAL(rightOf$(ps$, ","))
  104.                         frec (parentx - 1) * sq + 3, (parenty - 1) * sq + 3, sq - 6, sq - 6, 999
  105.                         _LIMIT 10
  106.                         _DISPLAY
  107.                     WEND
  108.                 ELSE
  109.                     rgb 999
  110.                     LOCATE 15, 10: PRINT "Did not connect to B"
  111.                     _DISPLAY
  112.                     _DELAY 3
  113.                     displayB
  114.                 END IF
  115.             END IF
  116.         END IF
  117.         IF _KEYDOWN(27) THEN END
  118.         IF _KEYDOWN(ASC("n")) THEN EXIT DO
  119.         IF _KEYDOWN(ASC("c")) THEN displayB
  120.         _DISPLAY
  121.         _LIMIT 100
  122.     LOOP
  123.  
  124. SUB displayB
  125.     FOR y = 1 TO maph
  126.         FOR x = 1 TO mapw
  127.             SELECT CASE RTRIM$(board(x, y))
  128.                 CASE "A": k = 9
  129.                 CASE "B": k = 905
  130.                 CASE "O": k = 50
  131.                 CASE ELSE: k = 0
  132.             END SELECT
  133.             frec (x - 1) * sq, (y - 1) * sq, sq, sq, k
  134.         NEXT
  135.     NEXT
  136. SUB rec (x1, y1, x2, y2, rgbN)
  137.     rgb rgbN
  138.     LINE (x1, y1)-(x2, y2), , B
  139. SUB frec (x1, y1, w, h, rgbN)
  140.     rgb rgbN
  141.     LINE (x1, y1)-STEP(w, h), , BF
  142. SUB rgb (n) ' New (even less typing!) New Color System 1000 colors with up to 3 digits
  143.     s3$ = RIGHT$("000" + LTRIM$(STR$(n)), 3)
  144.     r = VAL(MID$(s3$, 1, 1)): IF r THEN r = 28 * r + 3
  145.     g = VAL(MID$(s3$, 2, 1)): IF g THEN g = 28 * g + 3
  146.     b = VAL(MID$(s3$, 3, 1)): IF b THEN b = 28 * b + 3
  147.     COLOR _RGB32(r, g, b)
  148. FUNCTION rand% (lo%, hi%)
  149.     rand% = INT(RND * (hi% - lo% + 1)) + lo%
  150. FUNCTION min (n1, n2)
  151.     IF n1 > n2 THEN min = n2 ELSE min = n1
  152. FUNCTION max (n1, n2)
  153.     IF n1 < n2 THEN max = n2 ELSE max = n1
  154. FUNCTION leftOf$ (source$, of$)
  155.     posOf = INSTR(source$, of$)
  156.     IF posOf > 0 THEN leftOf$ = MID$(source$, 1, posOf - 1)
  157. FUNCTION rightOf$ (source$, of$)
  158.     posOf = INSTR(source$, of$)
  159.     IF posOf > 0 THEN rightOf$ = MID$(source$, posOf + LEN(of$))
  160.  
 
Pathfinder 2.PNG
 
Blue square is Point A the start point. Yellow squares are different destinations from A.
« Last Edit: August 14, 2018, 10:26:38 pm by bplus »

Offline johnno56

  • Forum Resident
  • Posts: 1270
  • Live long and prosper.
    • View Profile
Re: B+ Pathfinder
« Reply #11 on: August 15, 2018, 05:05:00 am »
... Riddle me this one, Batman...

J
Screenshot from 2018-08-15 19-02-48.png
* Screenshot from 2018-08-15 19-02-48.png (Filesize: 17.62 KB, Dimensions: 802x626, Views: 409)
Logic is the beginning of wisdom.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: B+ Pathfinder
« Reply #12 on: August 15, 2018, 07:06:45 am »
There you have clicked the hedge, the black is the free space on which paths are stepped through.

Also I was not satisfied when I clicked a spot that it was clicking the right square, so I adjusted the mouseX, mouseY by .5*sq = half the square size. For me it was better, for your pointer maybe worse,

Here is the line to diddle:
mx = _MOUSEX - .5 * sq: my = _MOUSEY - .5 * sq

maybe just leave it to mouse x, y no adjustments? Maybe adjust a whole square?

But you should be definitely attempting to click a black square. And some places will not connect to A the blue rectangle because the hedge completely surrounds the spot clicked.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: B+ Pathfinder
« Reply #13 on: August 15, 2018, 07:45:21 am »
Now the next logical step is to write a function that returns the actual path to take from A to B, step by step.

I am inclined to make this function a string. Can functions return arrays?

I think I have always used a sub for array building.

Better would be to have real map problems to work on now that I have proof of concept.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: B+ Pathfinder
« Reply #14 on: August 15, 2018, 10:19:36 am »
Now the next logical step is to write a function that returns the actual path to take from A to B, step by step.

I am inclined to make this function a string. Can functions return arrays?

I think I have always used a sub for array building.

Better would be to have real map problems to work on now that I have proof of concept.

I tend to do something like this with an array of steps needed to move from point A to point B.

Code: QB64: [Select]
  1. CONST StepByStep = -1 '-1 for TRUE, 0 for FALSE
  2.  
  3.  
  4.  
  5. SCREEN _NEWIMAGE(800, 600, 32)
  6. DIM SHARED Map(0 TO 26, 0 TO 26) AS INTEGER
  7.  
  8. TYPE Coordinate
  9.     x AS INTEGER
  10.     y AS INTEGER
  11.  
  12. DIM SHARED HeroPosition AS Coordinate
  13. DIM SHARED TargetPosition AS Coordinate
  14.  
  15. f = _LOADFONT(".\cyberbit.ttf", 8, "monospace")
  16.  
  17.     'Clear Variables for a second run
  18.     _FONT 16
  19.     FOR x = 0 TO 26
  20.         FOR y = 0 TO 26
  21.             Map(x, y) = -1
  22.     NEXT y, x
  23.     HeroPosition.x = 0
  24.     HeroPosition.y = 0
  25.     TargetPosition.x = 0
  26.     TargetPosition.y = 0
  27.  
  28.     FOR i = 0 TO 26 'Create Border
  29.         Map(i, 0) = -2: Map(i, 26) = -2 'Filled
  30.         Map(0, i) = -2: Map(26, i) = -2 'Filled
  31.     NEXT
  32.  
  33.     FOR i = 1 TO 200 'Create Obsticals
  34.         x = INT(RND * 26) + 1
  35.         y = INT(RND * 26) + 1
  36.         Map(x, y) = -2 'Filled
  37.     NEXT
  38.  
  39.     'Place Hero
  40.  
  41.  
  42.     DrawMap
  43.     LOCATE 20, 70: PRINT "Use Mouse to place Hero"
  44.     DO
  45.         _LIMIT 30
  46.         WHILE _MOUSEINPUT: WEND
  47.         XPos = (_MOUSEX - 20) \ 20
  48.         YPos = (_MOUSEY - 20) \ 20
  49.         IF XPos > 0 AND XPos < 26 AND YPos > 0 AND YPos < 26 THEN
  50.             IF _MOUSEBUTTON(1) AND (Map(XPos, YPos) <> -2) THEN
  51.                 HeroPosition.x = XPos
  52.                 HeroPosition.y = YPos
  53.                 EXIT DO
  54.             ELSEIF _MOUSEBUTTON(2) THEN GOTO redo
  55.             END IF
  56.         END IF
  57.     LOOP
  58.     DrawMap
  59.  
  60.     LOCATE 20, 70: PRINT "Use Mouse to place Target"
  61.     DO
  62.         _LIMIT 30
  63.         WHILE _MOUSEINPUT: WEND
  64.         XPos = (_MOUSEX - 20) \ 20
  65.         YPos = (_MOUSEY - 20) \ 20
  66.         IF XPos > 0 AND XPos < 26 AND YPos > 0 AND YPos < 26 THEN
  67.             IF _MOUSEBUTTON(1) AND (Map(XPos, YPos) <> -2) AND XPos <> HeroPosition.x AND YPos <> HeroPosition.y THEN
  68.                 TargetPosition.x = XPos
  69.                 TargetPosition.y = YPos
  70.                 EXIT DO
  71.             END IF
  72.         END IF
  73.     LOOP
  74.     _FONT f
  75.  
  76.     CalculateTravel
  77.     DrawMap
  78.  
  79.     DO
  80.         _LIMIT 30
  81.         i$ = INKEY$
  82.         IF i$ = CHR$(27) THEN SYSTEM
  83.     LOOP UNTIL i$ <> ""
  84.  
  85.  
  86.     redo:
  87.  
  88.  
  89.  
  90.  
  91.  
  92.  
  93. SUB DrawMap
  94.     CLS
  95.     IF HeroPosition.x <> 0 AND HeroPosition.y <> 0 THEN LINE (20 * HeroPosition.x + 20, 20 * HeroPosition.y + 20)-STEP(20, 20), &HFFFF0000, BF
  96.     IF TargetPosition.x <> 0 AND TargetPosition.y <> 0 THEN LINE (20 * TargetPosition.x + 20, 20 * TargetPosition.y + 20)-STEP(20, 20), &HFFFFFF00, BF
  97.     FOR x = 0 TO 26
  98.         FOR y = 0 TO 26
  99.             IF Map(x, y) = -2 THEN
  100.                 LINE (20 * x + 20, 20 * y + 20)-STEP(20, 20), -1, BF
  101.             ELSE
  102.                 LINE (20 * x + 20, 20 * y + 20)-STEP(20, 20), -1, B
  103.                 IF Map(x, y) > 0 THEN _PRINTSTRING (20 * x + 21, 20 * y + 21), _TRIM$(STR$(Map(x, y)))
  104.             END IF
  105.     NEXT y, x
  106.  
  107. SUB CalculateTravel
  108.     'Start at  TargetDestination
  109.     Map(TargetPosition.x, TargetPosition.y) = 0
  110.     FOR i = 0 TO 26
  111.         mapchanged = 0
  112.         FOR x = 1 TO 25
  113.             FOR y = 1 TO 25
  114.                 IF Map(x, y) = i THEN
  115.                     IF Map(x - 1, y - 1) = -1 THEN Map(x - 1, y - 1) = i + 1: mapchanged = -1
  116.                     IF Map(x, y - 1) = -1 THEN Map(x, y - 1) = i + 1: mapchanged = -1
  117.                     IF Map(x + 1, y - 1) = -1 THEN Map(x + 1, y - 1) = i + 1: mapchanged = -1
  118.                     IF Map(x - 1, y) = -1 THEN Map(x - 1, y) = i + 1: mapchanged = -1
  119.                     IF Map(x + 1, y) = -1 THEN Map(x + 1, y) = i + 1: mapchanged = -1
  120.                     IF Map(x - 1, y + 1) = -1 THEN Map(x - 1, y + 1) = i + 1: mapchanged = -1
  121.                     IF Map(x, y + 1) = -1 THEN Map(x, y + 1) = i + 1: mapchanged = -1
  122.                     IF Map(x + 1, y + 1) = -1 THEN Map(x + 1, y + 1) = i + 1: mapchanged = -1
  123.                 END IF
  124.                 IF Map(HeroPosition.x, HeroPosition.y) <> -1 THEN EXIT SUB
  125.             NEXT
  126.         NEXT
  127.         IF StepByStep THEN
  128.             DrawMap
  129.             _DELAY 1 'A second delay so the user can watch us find the path
  130.         END IF
  131.         IF mapchanged = 0 THEN EXIT SUB
  132.     NEXT
  133.  

Place Hero with mouse, then target with mouse, then watch as it tries to build you a path from one point to the other.  Hit ESC after that to quit, or any other key to go again on a second map.

Not only does this give you a path to the "hero", but it also tells you how many steps would be required to reach ANY point available on the map.

EDIT:  Minor modification where I changed total map size just so it could display fully on machines running a smaller resolution than mine is.

Also note:  To get back from the Target to the Hero (as if the target was a monster chasing the hero), simply count down from the largest number at the hero to the adjacent square with the next smaller number.    To path find from the hero to the target, we'd just swap their search order and then trace back from highest square to lowest, same as before.  (Basically, just swap the values for the two targets...)
« Last Edit: August 15, 2018, 10:27:38 am by SMcNeill »
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!