Jump to content
IGNORED

The Legend of Beryl Reichardt


Opry99er

Recommended Posts

Yes, Lee. Willsy's SPRITE designer is awesome. :)

 

However, since that post, I have rediscovered TIdBiT for development. Take a look at this snippit of code.

          //BEGIN MENU LOOP//
MainMenu:          
REM  MENU
     CALL CLEAR :: CALL SCREEN(2):: CALL DELSPRITE(#1)
     CALL HCHAR(5,1,101,32):: CALL HCHAR(20,1,101,32):: CALL VCHAR(5,1,97,15):: CALL VCHAR(5,32,97,15)
     CALL HCHAR(5,1,98):: CALL HCHAR(5,32,100):: CALL HCHAR(20,1,99):: CALL HCHAR(20,32,96)
 
MainMenu-MiddleReturn:
 
     GOSUB ClearMenu :: GOSUB ReturnString
     DISPLAY AT(8,1):"1) ITEMS":"2) ARMOR":"3) WEAPONS":"4) SPELLS":"5) STATUS";
 
 
MidMenu-Keyscan:
 
     GOSUB Keyscan
     IF K=13 THEN CALL CLEAR :: GOTO DrawScreen !**BUG FIXED HERE** Case-sensitive labels
     IF K>54 THEN GOTO MidMenu-Keyscan ELSE IF K<49 THEN GOTO MidMenu-Keyscan
     ON K-48 GOTO ItemMenu,ArmorMenu,WeaponsMenu,SpellsMenu,StatusMenu
 
 
          //BEGIN Item Menu//
 

TIdBiT basically allows me to code using labels... which is just as easy as using SUBs, if not easier. I've noticed that my code is very recursive in nature these days... A product of the labels, I'm guessing.

 

The labels, when translated, produce line numbers and all references to that label in the source immediately become associated with that line number... So

 

 

GOSUB Label1

 

would reference the line number of Label 1 and GOSUB there.

 

GOSUB 3000

 

or whatever.

 

 

Truly an epiphany for me in the development of this game. More has happened in the last month than the last 3 years.

 

 

Hey Lee... thanks for posting to this thread. :) I hope you play the game... even if you hate it, still..... play it. LOL!!!

Edited by Opry99er
  • Like 1
Link to comment
Share on other sites

...

However, since that post, I have rediscovered TIdBiT for development. Take a look at this snippit of code.

...

TIdBiT basically allows me to code using labels... which is just as easy as using SUBs, if not easier. I've noticed that my code is very recursive in nature these days... A product of the labels, I'm guessing.

...

Truly an epiphany for me in the development of this game. More has happened in the last month than the last 3 years.

 

All that good stuff notwithstanding, subprograms make the resulting program easier to read. Though, the output from TIdBiT probably organizes the GOSUBs better than most of us often do when coding directly in Basic.

...

Hey Lee... thanks for posting to this thread. :) I hope you play the game... even if you hate it, still..... play it. LOL!!!

 

I am sure I won't hate it and I certainly will play it. Though, as you seem to remember my saying a long time ago, I would rather not spend a lot of time with games, I recognize that some of the most significant advances in computing have come from game programming.

 

...lee

  • Like 1
Link to comment
Share on other sites

That's definitely a possibility there, Greg... For sure.

 

I think the fella was asking if there was a way to autodetect the size of a disk system...

 

But yea, an ON ERROR GOSUB is a great way to handle that, assuming I have two versions of the game... One disk and multidisk. :)

 

@The t-shirt-- :lol: I need to buy one of those from you.

Edited by Opry99er
Link to comment
Share on other sites

TIdBiT basically allows me to code using labels... which is just as easy as using SUBs, if not easier.

You can use labels with subroutines (which I know you are aware), but subroutines help you keep you code organized and easier to understand and maintain. You should not write off subroutines because you have labels, they are not mutually exclusive. Code organization can also help you write bigger programs in the same amount of memory by realizing that you do many similar things over and over in a program, and bundling those up into subroutines means less duplication and less wasted memory.

 

I've noticed that my code is very recursive in nature these days... A product of the labels, I'm guessing.

 

Technically your code is not recursive. I don't even know if you could do recursion in XB (maybe if you simulated a stack). Your code loops a lot as a function of playing the game, which is also known as a "game loop". I think you will learn a lot from this exercise of writing you game.

  • Like 1
Link to comment
Share on other sites

Thanks Matthew. What I meant by that is that my program GOSUBS to a GOSUB to a GOSUB and then, once an outcome is reached in the final stage, it RETURNS and updates, RETURNS and updates, RETURNS and updates and finally returns back to the top... Particularly in the menus...

 

In the Syntax Error thread, that kind of process was referred to by someone as recursive.

 

If that is not what it is, then forgive my misuse of the term. :)

 

And yes, I am learning alot... Pretty cool to go into a project thinking you know how to do something, realizing you don't, and then actually learning what you have to do and then do it. :)

 

And what I meant by SUBroutines not being needed is that I don't have to define a sub and then CALL "whatevername"... I can reference the label and it acts similarly.

 

Thanks again for all your help, Matthew. :)

Link to comment
Share on other sites

A function is only recursive if it calls itself (very important distinction) and has a condition to eventually terminate and return back up through the calling chain. I was only clarifying for educational purposes. I did not read the Syntax Error thread, but it sounds like the initial comment misused the term.

 

Ah, now I see what you were referring to with the subroutines. Keep in mind that in XB, what is typically thought of in other languages as a "function", "subroutine", "method", or whatever is implemented with GOSUB and RETURN. XB also has a way for you to define (with the DEF keyword) what they call a "function" that you then subsequently use with CALL "function name". In that case the "function" can only be an expression and it is a confusing term when compared to more prevalent languages.

Link to comment
Share on other sites

Thanks for the clean-up there. :) I'm learning, so some terminology is a bit fuzzy in the ol' head over here. User defined FUNCTION, I guess, is what I meant by SUB. I think I got confused because in XB you finish the program listing out with the defined function by using something like

 

1040 SUB SCRWIPE

 

1050 CALL CLEAR

1060 CALL SCREEN(5)

 

1070 SUBEND

 

The "SUB" in there threw me a bit.

 

 

I've progressed with this program to a point of absolutely needing to define and implement a series of multi-dimensional arrays for data handling... I can continue without it, but it is crushing my PROGRAM size... This will also be new for me, as I've never used variable arrays in my programming previously. I know it was discussed early on in this thread with Codex, yourself, and a few others, but until NOW, I didn't need them, so I never implemented them. Now, especially with the minute details starting to come together, they will be crucial, I believe, to handling business in a compact and controlled manner. as an example from my own code...

 

 

 

 

 

 

MidItem-Keyscan:
 
     GOSUB Keyscan
     IF K=13 THEN GOTO MainMenu-MiddleReturn 
     IF K>52 THEN GOTO MidItem-Keyscan ELSE IF K<49 THEN GOTO MidItem-Keyscan
     ON K-48 GOSUB ItemBeryl,ItemRepto,ItemMarkus,ItemSkylar
     GOTO ItemMenu
 
 
 
          //ACN=name, ANSP=name starting point, ANL=name length//
 
ItemBeryl:
     REM BERYL
     GOSUB ActiveBeryl
     GOSUB ItemMenu2
     BHP=AHP :: BMP=AMP :: RETURN
 
ItemRepto:
     REM REPTO 
     GOSUB ActiveRepto
     GOSUB ItemMenu2
     RHP=AHP :: RMP=AMP :: RETURN
 
ItemMarkus:
     REM MARKUS
     GOSUB ActiveMarkus
     GOSUB ItemMenu2
     MHP=AHP :: MMP=AMP :: RETURN
 
ItemSkylar:
     REM SKYLAR
     GOSUB ActiveSkylar
     GOSUB ItemMenu2
     SHP=AHP:: SMP=AMP :: RETURN
 
 
     REM **THIS IS THE MEAT OF THE ITEM MENU CODE**
 
ItemMenu2:
 
 
     GOSUB ClearMenu :: DISPLAY AT(1,ANSP):ACN$;:: CALL HCHAR(2,ANSP+2,94,ANL)
     GOSUB ReturnString
 
ItemDisplay:
 
     DISPLAY AT(8,1):"1) POTION";HPO;:"2) ETHER";MPO;:"3) ELIXIR";ELI;
     DISPLAY AT(3,1):"HP:";AHP;"/";AMHP;:: DISPLAY AT(3,16):"MP:";AMP;"/";AMMP;
 
MidItem2-Keyscan:
     GOSUB Keyscan
     IF K=13 THEN GOTO ItemMenu
     IF K>51 THEN GOTO MidItem2-Keyscan ELSE IF K<49 THEN GOTO MidItem2-Keyscan
     ON K-48 GOSUB HealthPotion,MagicPotion,Elixir
     GOSUB Flash
     DISPLAY AT(3,1):"HP:";AHP;"/";AMHP;:: DISPLAY AT(3,16):"MP:";AMP;"/";AMMP;
     DISPLAY AT(8,1):"1) POTION";HPO;:"2) ETHER";MPO;:"3) ELIXIR";ELI;:: FOR I=1 TO 400 :: NEXT I
     RETURN
 
.
.
.
..
.
.
.

ActiveBeryl:
     AMHP=BMHP :: AHP=BHP :: AMMP=BMMP :: AMP=BMP :: ACN$="BERYL" :: ANSP=12 :: ANL=5 :: AMN=BMN
     RETURN
 
ActiveRepto:
     AMHP=RMHP :: AHP=RHP :: AMMP=RMMP :: AMP=RMP :: ACN$="REPTOSLICER" :: ANSP=9 :: ANL=11 :: AMN=RMN
     RETURN
 
 
ActiveMarkus:
     AMHP=MMHP :: AHP=MHP :: AMMP=MMMP :: AMP=MMP :: ACN$="MARKUS" :: ANSP=12 :: ANL=6 :: AMN=MMN
     RETURN
 
ActiveSkylar:
     AMHP=SMHP :: AHP=SHP :: AMMP=SMMP :: AMP=SMP :: ACN$="SKYLAR" :: ANSP=12 :: ANL=6 :: AMN=SMN
     RETURN
 
Link to comment
Share on other sites

As you can see, I'm using a WHOLE lot of similar variables. I'm also unnecessarily loading my static variables (RHP,RMHP,RMP,RMMP) whatever into a temporary set in the ActiveBeryl, Active Repto,...,... routines-- INTO a temporary variable set known as "A".... or Active. If all this crap were handled in arrays, I could eliminate that altogether and just use the keypress from the user to DIRECTLY indicate which of the 4 I'm addressing in a HP(4,2) array.

 

K-48 will determine which of the 4 in my first dimension will be addressed, and the program will dictate what to DO with that information onscreen. None of this extra garbage I've spent 2 weeks writing, trying to be clever... Just to find out that arrays were the answer all along. :) LOL!

 

I feel dumb, but smarter all at once. :)

Edited by Opry99er
Link to comment
Share on other sites

The non-Computer Science equivalent of recursion is a mirror image of a mirror image.

You see reflections of reflections of reflections...
The reflection of one mirror is passed to the other which is passed to the other which... you get the idea. The image is reduced in size each time it's reflected.

Ti BASIC doesn't really fully support recursion since it uses global variables for everything.
Recursion depends on a language where subroutines allocate new storage space for variables each time they are called and the ability to pass parameters to the subroutine.
Keeping that in mind, a recursive function calls itself from within itself.

Unlike the mirrors, computer recursion is limited by available memory.
An iterative (non-recursive) implementation of an algorithm requires a fixed amount of RAM where use of recursion requires allocation of RAM for new local variables with each recursive call as well as the return address

If you think that is as clear as mud, look up the Wiki definition for recursion (Computer Science).

A common use would be a recursive implementation of Quicksort. It might not be the best example because it might be tough to follow the logic.

 

// Free Pascal implementation of Quicksort. Sorts an array of integers
// calls itself again whenever it finds an array element out of order
procedure QuickSort(var A: array of Integer; iLo, iHi: Integer) ;
var Lo, Hi, Pivot, Tenp: Integer;
begin
  // make local copies of the array indexes
  Lo := iLo;
  Hi := iHi;
  // get the value of the array element at the half way point between array indexes
  Pivot := A[(Lo + Hi) div 2];

  // keep repeating until Lo index > Hi index (indexes cross)
  repeat
    // skip Lo array elements that are less than the Pivot value
    while A[Lo] < Pivot do Inc(Lo) ;
    // skip Hi array elements that are greater than the Pivot value
    while A[Hi] > Pivot do Dec(Hi) ;

    // fall through to here, check to see if it's because Lo and Hi are out of order
    if Lo <= Hi then
    // Swap array elements that are out of order
      begin
        Temp := A[Lo];
        A[Lo] := A[Hi];
        A[Hi] := Temp;
        Inc(Lo) ;
        Dec(Hi) ;
      end;
  until Lo > Hi;

  // make recursive call if we haven't traversed the entire array looking to see if array elements are out of order
  if Hi > iLo then QuickSort(A, iLo, Hi) ;
  if Lo < iHi then QuickSort(A, Lo, iHi) ;
end;

 

 

Edited by JamesD
Link to comment
Share on other sites

What about recursive backtracking for maze generators? I'm assuming these algorithms have similar traits..

 

Yes, you can absolutely use recursion for maze generation. I've written one before. :) That said, any recursive approach can also be done linearly by creating a stack structure to store whatever you're doing that is being copied. All a recursive function does is push the entire local stack of functional data onto the heap, it's easier to read in code but harder on the processor and memory.

 

One call out, Matt said that you use DEF to create subprograms you can CALL with, this isn't quite accurate.

 

DEF is used to create functions. An example:

 

DEF RND(N)=INT(N+.5)

 

This creates a new function you can call which will round a decimal value up if it's .5 or higher, otherwise round down.

 

I've found, though, that creating custom functions is really REALLY inefficient. They seem to really impact program speed hard-core, and are best left unused for anything to do with graphics or sprites.

 

You create subprograms by using SUB keywords, along with SUBEXIT and SUBEND to mark end points. Subprograms are nice in that they have local variables, so you don't have to worry about overriding globals. Arrays, though, are passed by reference into them, so they're trickier to use with subprograms.

Link to comment
Share on other sites

Recursion in computer science is typically not infinite, there is another term for that: infinite loop. Here is a classic example of recursion (ref: wikipedia):

 

unsigned int factorial(unsigned int n) {
    if (n == 0) {
        return 1;
    } else {
        return n * factorial(n - 1);
    }
}
Stack-based languages help make doing recursion easier, but are not necessary. In XB you could use an array, for example, to store the variables at each iteration.

 

Yes Owen, a recursive backtracking maze generator is a perfect example. In that case you can actually use the maze array itself as the storage space for each iteration.

 

As for arrays, for 1D and 2D implementations just think in terms of the screen or graph paper. Each cell can hold a value of you choice. However, for a game like this it might be easier to think in terms of records. In XB is gets really clunky because the language does not help you, but you can emulate them with arrays. For example, you have stats for each character like class, HP, strength, weapon, etc. So you could have an array that stores those value for each character like this:

 

num_players = 4
stats_per_player = 4

OPTION BASE 0

DIM stats[num_players * stats_per_player]

PRINT "Player Stats:"
FOR I = 0 TO num_players-1
  IDX = I * num_players
  PRINT "Player "; I+1
  PRINT "  Class: "; stats[IDX+0]
  PRINT "  HP: "; stats[IDX+1]
  PRINT "  Strength: "; stats[IDX+2]
  PRINT "  Weapon: "; stats[IDX+3]
  PRINT
NEXT I
Basically every "stats_per_player" subscripts in the array store the data for one character. You can as many characters as you want for the cost of the extra storage, and the code to deal with any given character will be the same.

 

You could also have an array of weapons (or use DATA statements for information that is static and read only), so the weapon value stored in a player's stats record would be an index into the weapon array, which could be yet another "record" array of weapons and their stats. This can be somewhat of a pain in XB because the language lacks support for even simple constructs like constants, but you have to get a handle on data management or your game will come to like and kill you. Hmm, I could probably add support of constants in TidBit easy enough.

 

As you work through you games you will start to realize that games are just data-management programs. You need to start thinking in terms of record storage vs fixed hard-coded variables. If you want an example let me know.

Link to comment
Share on other sites

What about recursive backtracking for maze generators? I'm assuming these algorithms have similar traits..

Similar but not identical.

 

What is most important is that recursive backtracking is a form of "perfect maze creation".

An obvious example of a perfect vs non-perfect maze is shown on this page:

http://www.mazeworks.com/mazegen/mazetut/

You can find many other approaches to perfect maze creation mentioned here:

http://www.astrolog.org/labyrnth/algrithm.htm

 

Pay attention to the table comparing maze generators.

Memory may be an issue for some of them.

The other issue is time. Interpreted BASIC is slow so you want something fast. 4 Algorithms require half the time of recursive backtracking.

Link to comment
Share on other sites

...

One call out, Matt said that you use DEF to create subprograms you can CALL with, this isn't quite accurate.

 

DEF is used to create functions. An example:

...

 

Actually, that is what Matthew said. The part that is not quite right is “CALL”. You call a function by referencing it, not by using a CALL statement. To use your example, which, by the way cannot be named “RND” (let’s call it “ROUND”):

10 DEF ROUND(N) = INT(N+.5)
20 INPUT X
...
100 Y = ROUND(X)
...

...lee

Edited by Lee Stewart
Link to comment
Share on other sites

I just did a review of DEF, CALL, and SUB. I did not realize XB has subroutines with static local variables! For some reason I had it in my head that all XB variables were global. You can even go so far as passing by reference or value. Owen, I think you should spend a little time understanding the use of SUB, although I better check that TidBit supports that keyword. Doh!

 

Subroutines and local variables are the bread and butter of almost any language and helps make your programs modular and manageable.

  • Like 2
Link to comment
Share on other sites

 

Yes, you can absolutely use recursion for maze generation. I've written one before. :) That said, any recursive approach can also be done linearly by creating a stack structure to store whatever you're doing that is being copied. All a recursive function does is push the entire local stack of functional data onto the heap, it's easier to read in code but harder on the processor and memory.

 

One call out, Matt said that you use DEF to create subprograms you can CALL with, this isn't quite accurate.

 

DEF is used to create functions. An example:

 

DEF RND(N)=INT(N+.5)

 

This creates a new function you can call which will round a decimal value up if it's .5 or higher, otherwise round down.

 

I've found, though, that creating custom functions is really REALLY inefficient. They seem to really impact program speed hard-core, and are best left unused for anything to do with graphics or sprites.

 

You create subprograms by using SUB keywords, along with SUBEXIT and SUBEND to mark end points. Subprograms are nice in that they have local variables, so you don't have to worry about overriding globals. Arrays, though, are passed by reference into them, so they're trickier to use with subprograms.

The reason mostly for this impact is DEF has to go back to that statement and re-allocate VDP memory then go back to that line and run the new variables into that formula.

One of the main problems is it MUST do a Garbage Collection of VDP memory as it is a unknown how much memory will be used before that Formula is solved.

If XB used RAM instead of VDP for Variables and Strings you would see a incredible speed increase of XB execution of programs.

 

Every single byte access has that delay on it in every VDP byte?

 

This is a huge cost in speed and efficiency.

Link to comment
Share on other sites

Typically? It can't be infinite, you'll run out of memory.

Exactly. I was referring to your mirror analogy which is infinite (there is no stopping condition or result that unwinds the process), and simply commenting that the use of recursion with computers is typically not infinite.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...