Author Topic: Djkstra's Pathfinding in QBASIC 4.5  (Read 16668 times)

TheIronPainter

  • Newcomer
  • Posts: 7
  • Karma: +0/-0
    • View Profile
    • Email
Djkstra's Pathfinding in QBASIC 4.5
« on: May 02, 2012, 07:15:45 PM »
Hello, I'm new to the forum so be gentle.

I have chosen QuickBasic 4.5 as my programming language. Now before you all moan and groan hear me out.

I started programming at 12 and QBasic was what I learned on. For years and years I made tid-bits of games for Qbasic but never followed through. I now want to prove to myself and the world that you CAN make a decent Roguelike in this language even if it cannot come close to the complexity of a C# or C++ game.

Anyway... my real question is that I am converting the Djkstra's pathfinding pseudo-code into Qbasic but I ran into a problem. The step is here:

3.) If the successor doesn't exist on either the OPEN list or the CLOSED list, add it to the OPEN list.

We're fine.... but further...

Otherwise, if the successor's movement cost is lower than the movement cost of the same tile on one of the lists, delete the occurrences of the successor from the lists and add the successor to the OPEN list.

Problem!

I A.) Don't know what that means exactly, and B.) Have a problem deleting from my lists because instead of pointer stacks they are arrays (since qbasic doesn't use pointers)

I have samples of code for anybody that are commented out the ying yang if anybody cares to help me out.

Thanks in advance :)

konijn_

  • Newcomer
  • Posts: 29
  • Karma: +0/-0
    • View Profile
    • Email
Re: Djkstra's Pathfinding in QBASIC 4.5
« Reply #1 on: May 02, 2012, 08:14:56 PM »
Greetings,

This list of not very coherent thoughts popped up :

 * I understand your quest, but it might get rough ;)
 * What OS are you running, where did you even find the binary ?
 * I did once the same, the problem for me was the limit of code you can have and the size-limit of arrays :
http://www.qbasicnews.com/qboho/qckadvr@l8206.shtml

For your particular question, it should be relatively easy to build a subroutine where you pass the array and the index of the element to remove.
You then rebuild a new array from the old array, leaving out that one index..
Or ( bad idea given how limited your memory is ) you could set the value to -1 or something that means 'this element is deleted'

T.


requerent

  • Rogueliker
  • ***
  • Posts: 355
  • Karma: +0/-0
    • View Profile
Re: Djkstra's Pathfinding in QBASIC 4.5
« Reply #2 on: May 02, 2012, 10:34:59 PM »
Quote
Otherwise, if the successor's movement cost is lower than the movement cost of the same tile on one of the lists, delete the occurrences of the successor from the lists and add the successor to the OPEN list.

Okay-- I don't like this OPEN and CLOSED business, but basically you've got your connected graph. The Dijsktra's traversal always takes the shortest total path to get to nodes.

The order of nodes on the frontier corresponds to the distance from the origin. All that quote is saying is that if a node already exists on the frontier but a shorter path is found, ditch the original and add the new one. I don't like that wording though-- you should be updating the known distance.

We have an array that stores the distance from origin to each node. Since we don't know the total distance, we set each node's distance to default at infinity (or max integer), with the origin at 0. We know what nodes connect to origin, so we update total distances of each node.

We then have an array of booleans that stores whether we've visited a node or not. Nodes that have a non-infinite distance but have yet to be visited are on the 'frontier.' We take the node with the smallest distance on the frontier and visit it, updating the distances of each node visited. If a node already has a distance, we need to replace it with the new one if it is shorter.

Dijsktra's never needs to think about nodes that are already visited. Once visited, their distance is never changed.

Ancient

  • Rogueliker
  • ***
  • Posts: 453
  • Karma: +0/-0
    • View Profile
Re: Djkstra's Pathfinding in QBASIC 4.5
« Reply #3 on: May 04, 2012, 07:01:07 PM »
Not directly related but there is a tiny fun roguelike in FreeBASIC. About time

That said problem B can be solved by shifting the arrays or making a pass similar to what FreePascal does. FP implements lists as arrays.

To delete X elements from the list do the following:

Pass through the list maintaining two variables: current position and number of deleted elements.

1. Set position to first element and deleted to zero.

2. If you stumble on a element to be kept, copy it to list position [position - deleted]. Until you have deleted something this will overwrite elements with themselves -- in other words do nothing.

3. If you stumble on a element to be deleted increase deleted by one.

4. Increase position by one.

5. Loop to step 2 if you have not reached end of the list yet.

The effect will be copying elements 1 to 1, 2 to 2, 3 to 3. Lets say element 4 you want deleted. In point 2. nothing is done. Point 3. assures copying will be shifted from now on. So copying continues with element 5 to 4, 6 to 5 etc. After the pass finishes you need to subtract deleted from number of elements in your list. Done!

For problem A I need more detailed explanation from you to really be able to help.
Michał Bieliński, reviewer for Temple of the Roguelike

jocke the beast

  • Rogueliker
  • ***
  • Posts: 103
  • Karma: +0/-0
    • View Profile
Re: Djkstra's Pathfinding in QBASIC 4.5
« Reply #4 on: May 04, 2012, 07:44:56 PM »
Fellow basic-coder! I urge you to check out the http://freebasic.net/forum. Trafficed and helpfull coders.
http://www.freebasic.net/forum/viewtopic.php?f=15&t=9952&hilit=Pathfinding covers a pretty good A*pathfinding example...
Good luck!

TheIronPainter

  • Newcomer
  • Posts: 7
  • Karma: +0/-0
    • View Profile
    • Email
Re: Djkstra's Pathfinding in QBASIC 4.5
« Reply #5 on: May 04, 2012, 11:20:21 PM »
Wow... I was not expecting the kind replies like this. A great thanks is in order. Thanks!

You all have solved my problem, in one way or another. And I greatly appreciate the clarification of the pseudo-code as well as a good delete alternative for non-pointered stacks. Already converted and implemented!

What I have feared is happening, however. I have a 40kb program before combat and sound... perhaps it is just time to tuck tail and convert it all to C++. The last thing I want to do is keep putting more time into this project and then get held back at the last second by a measly few kbs of code.

To answer a few other questions. I don't have the binary, and I'm running in the emulated console DosBox. I like DosBox because you can crank up the frame-rate making an already slow Qbasic program run almost as if it were programmed by a better programmer  ;)

In the next few coming months I look forward to sharing with you all my version of a roguelike I have been wanting to program for AGES... thankfully none of you have thought about the idea yet so I'm eager to implement and be the first! It was a good fight but I think I've reached my limit with QBasic 4.5....

*sigh*

jocke the beast

  • Rogueliker
  • ***
  • Posts: 103
  • Karma: +0/-0
    • View Profile
Re: Djkstra's Pathfinding in QBASIC 4.5
« Reply #6 on: May 05, 2012, 08:05:12 AM »

What I have feared is happening, however. I have a 40kb program before combat and sound... perhaps it is just time to tuck tail and convert it all to C++. The last thing I want to do is keep putting more time into this project and then get held back at the last second by a measly few kbs of code.


Why not give Freebasic a try. If you're used to Qbasic 4.5 it's really simple to start using Freebasic. Same thing but better/faster/stronger  :)
Anyway you choose, good luck man!!!!

Ancient

  • Rogueliker
  • ***
  • Posts: 453
  • Karma: +0/-0
    • View Profile
Re: Djkstra's Pathfinding in QBASIC 4.5
« Reply #7 on: May 06, 2012, 09:30:29 PM »
Yes, good luck and don't forget to tell us when you have something for us to try!

Like Jocke says try Free BASIC first. C++ is not magic pixie dust (no programming language is) and trying out something familiar before you go check out other stuff is good idea.
Michał Bieliński, reviewer for Temple of the Roguelike

TheIronPainter

  • Newcomer
  • Posts: 7
  • Karma: +0/-0
    • View Profile
    • Email
Re: Djkstra's Pathfinding in QBASIC 4.5
« Reply #8 on: May 07, 2012, 07:32:27 PM »
You have made somebody really happy and for that I thank you Jocke. Already chugging away now under the new editor, FBIde. Happy they even have a "borland" graphics theme.

For YEARS I always had the desire to build a respectable QBASIC game even without objects, etc... call it a touch of nostalgia, call it what you will. I mean, let's face it, GW-BASIC has a place in history, however small.

If I have any further questions (which I will) should I append them to this subject or start a new thread. As I am new to the forum I don't want to be that guy, we all know who 'that guy' is, who doesn't play by the rules and invariably becomes a pest.

Thanks again, really.

One question. Whenever I load an old .bas file I get a blank screen with "ü" on line 1 and nothing else...
« Last Edit: May 07, 2012, 07:35:48 PM by TheIronPainter »

jocke the beast

  • Rogueliker
  • ***
  • Posts: 103
  • Karma: +0/-0
    • View Profile
Re: Djkstra's Pathfinding in QBASIC 4.5
« Reply #9 on: May 08, 2012, 09:35:24 AM »
Hmm... Is the old .bas file saved usling Qbasic 4.5 or a texteditor? If u saved it using Qbasic you might saved it as ansi. Try open the .bas in a texteditor save it there.

Btw, now while you use freebasic I strongly suggest you to check out this great roguelike tutorial made by Rick Clark. Covers the most from dungeon generation,LOS, items, melee, ranger attacks, magic, shops etc.

http://users.freebasic-portal.de/rdc/tutorials.html

Good luck!!!

TheIronPainter

  • Newcomer
  • Posts: 7
  • Karma: +0/-0
    • View Profile
    • Email
Re: Djkstra's Pathfinding in QBASIC 4.5
« Reply #10 on: May 08, 2012, 10:03:50 PM »
Jocke,

Got it to work. Thanks a ton. I'm having some cross-over problems though.

Here is a small sample of code. Hopefully.

I am having scope issues that I never had in QuickBasic 4.5...  for some reason the array Map$ is not getting translated to either of the sub-routines... I have no idea what's the problem other than a potential FreeBASIC related issue. Thanks,


Quote
'$lang: "fblite"

''----------------Program Initialization-------------------------
CLS
SCREEN 18, 32
WIDTH 80, 60
RANDOMIZE TIMER

''-----------------Cavern Subroutines----------------------------

DECLARE SUB CavernInit
DECLARE SUB FirstCavernRoomInit
DECLARE SUB BuildCavern(RoomCenterX as Integer, RoomCenterY as Integer, RoomWidth as Integer, RoomHeight as Integer)

''-----------------Map-Related Subroutines-----------------------

DECLARE SUB PrintTile(X as Integer, Y as Integer)

''-------------Map-Related Variable Declarations-----------------

DIM SHARED Map$()   'The main dungeon map
DIM SHARED Item$()  'The main "item" map
DIM SHARED Monster$() 'The main "monster" map


DIM Shared MaxScreenWidth = 50
DIM Shared MaxScreenHeight = 50
ReDIM Map$(1 to MaxScreenWidth, 1 to MaxScreenHeight)
ReDIM Item$(1 to MaxScreenWidth, 1 to MaxScreenHeight)

''---------------------------------------------------------------

''XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
''X                     MAIN PROGRAM MODULE                     X
''XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX


''----------------Fill the whole map in with rock----------------

CavernInit
sleep

FirstCavernRoomInit
sleep



'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
'/ Fill the entire map in with solid rock     \
'----------------------------------------------
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

SUB CavernInit
   
FOR X = 1 TO MaxScreenWIDTH
   FOR Y = 1 TO MaxScreenHEIGHT
      Map$(X, Y) = "0"     
   NEXT Y
NEXT X

FOR X = 1 TO MaxScreenWIDTH
   FOR Y = 1 TO MaxScreenHEIGHT
      Item$(X, Y) = "0"
   NEXT Y
NEXT X

END SUB


SUB FirstCavernRoomInit

'-----------------Randomly determine the room size------------------

RoomWIDTH = INT(RND * 3) + 1
RoomHEIGHT = INT(RND * 3) + 1


RoomCenterX = MaxScreenWIDTH / 2     
RoomCenterY = MaxScreenHEIGHT / 2   

Map$(RoomCenterX, RoomCenterY) = "1"

'-----------------Dig out the first room from the rock--------------

BuildCavern (RoomCenterX, RoomCenterY, RoomWIDTH, RoomHEIGHT)

END SUB


SUB BuildCavern (RoomCenterX, RoomCenterY, RoomWIDTH, RoomHEIGHT)

'-----------------FIRST FILL IN THE FLOORING------------------------------

FOR X = (RoomCenterX - RoomWIDTH) TO (RoomCenterX + RoomWIDTH)
   FOR Y = (RoomCenterY + -RoomHEIGHT) TO (RoomCenterY + RoomHEIGHT)
      Map$(X, Y) = "·"     
      PrintTile X, Y
   NEXT Y
NEXT X

'-----------------NOW FILL IN THE WALLS-----------------------------------

'-----------------MAKE THE RIGHT WALL-------------------------------------
X = RoomCenterX + RoomWIDTH + 1
FOR Y = (RoomCenterY - RoomHEIGHT - 1) TO (RoomCenterY + RoomHEIGHT + 1)
   Map$(X, Y) = "#"
   PrintTile X, Y
NEXT Y

'-----------------MAKE THE LEFT WALL--------------------------------------
X = RoomCenterX - RoomWIDTH - 1
FOR Y = (RoomCenterY - RoomHEIGHT - 1) TO (RoomCenterY + RoomHEIGHT + 1)
   Map$(X, Y) = "#"
   PrintTile X, Y
NEXT Y

'-----------------MAKE THE BOTTOM WALL------------------------------------
Y = RoomCenterY + RoomHEIGHT + 1
FOR X = (RoomCenterX - RoomWIDTH - 1) TO (RoomCenterX + RoomWIDTH + 1)
   Map$(X, Y) = "#"
   PrintTile X, Y
NEXT X

'-----------------MAKE THE TOP WALL---------------------------------------
Y = RoomCenterY - RoomHEIGHT - 1
FOR X = (RoomCenterX - RoomWIDTH - 1) TO (RoomCenterX + RoomWIDTH + 1)
   Map$(X, Y) = "#"
   PrintTile X, Y
NEXT X

END SUB


SUB PrintTile (X, Y)

IF Item$(X, Y) <> "0" THEN GOTO PrintItem  'If there is an item here print that
                                           'first.
SELECT CASE Map$(X, Y)

        CASE "#"                  'A stone wall
          COLOR 8
          LOCATE Y, X: PRINT "#"
       
        CASE "·"                  'A stone floor
          COLOR 15
          LOCATE Y, X: PRINT "·"
       
        CASE "+"                  'A stone door
          COLOR 7
          LOCATE Y, X: PRINT "+"
       
        CASE ">"                  'Stairs Down
          COLOR 7
          LOCATE Y, X: PRINT ">"

        CASE "<"                  'Stairs Up
          COLOR 7
          LOCATE Y, X: PRINT "<"

        CASE "þ"                  'Wooden Crate
          COLOR 6
          LOCATE Y, X: PRINT "þ"
       
        CASE "_"                  'Spawn Portal
          COLOR 13
          LOCATE Y, X: PRINT "_"

        CASE "$"                  'Gold Coins
          COLOR 14
          LOCATE Y, X: PRINT "$"

        CASE "-"
          COLOR 7
          LOCATE Y, X: PRINT "-"  'Open Up/Down Stone Door

        CASE "/"
          COLOR 7
          LOCATE Y, X: PRINT "/"  'Open Right/Left Stone Door
     
        CASE "3"
          COLOR 8, 2
          LOCATE Y, X: PRINT "²"  'Mossy Wall

        CASE "'"
          COLOR 2
          LOCATE Y, X: PRINT "ú"   'Mossy floor

        CASE ELSE

END SELECT
COLOR 0, 0

PrintItem:
SELECT CASE Item$(X, Y)

        CASE "c"                  'A wooden crate
          COLOR 6
          LOCATE Y, X: PRINT "þ"
     
        CASE "$"                  'Gold Coins
          COLOR 14
          LOCATE Y, X: PRINT "$"

END SELECT
COLOR 0, 0
END SUB




guest509

  • Guest
Re: Djkstra's Pathfinding in QBASIC 4.5
« Reply #11 on: May 09, 2012, 03:23:57 AM »
  I keep kicking around the idea of making a game in Turbo Pascal...those were the days!

TheIronPainter

  • Newcomer
  • Posts: 7
  • Karma: +0/-0
    • View Profile
    • Email
Re: Djkstra's Pathfinding in QBASIC 4.5
« Reply #12 on: May 09, 2012, 08:55:27 PM »
Nostalgia... it gets the best of us  ;)

Ancient

  • Rogueliker
  • ***
  • Posts: 453
  • Karma: +0/-0
    • View Profile
Re: Djkstra's Pathfinding in QBASIC 4.5
« Reply #13 on: May 11, 2012, 06:54:57 PM »
Here is a small sample of code. Hopefully.

I am having scope issues that I never had in QuickBasic 4.5...  for some reason the array Map$ is not getting translated to either of the sub-routines... I have no idea what's the problem other than a potential FreeBASIC related issue. Thanks,

I had a look today. After installing fbc your program compiles and displays a randomized size room. I wondered whats wrong until I tried to execute the program in a terminal under graphical environment. True Linux console has properties of DOS console which allows your program to perform adequately. To have it working in xterm I had to comment out your SCREEN statement. It worked but without color. The Map$ is handed over properly. The problem is in screen handling. I think you need to feed other values to SCREEN and everything should start to work.

Ah, in future please put code between [code] [/code] tags. It renders the text in monospace font.
Michał Bieliński, reviewer for Temple of the Roguelike