💾 Archived View for spam.works › mirrors › textfiles › programming › qbasgdc1.002 captured on 2023-07-22 at 20:45:33.

View Raw

More Information

⬅️ Previous capture (2023-06-16)

-=-=-=-=-=-=-

?????????????????
? Week 2, Day 1 ?
?????????????????

Our RPG will be simple, requiring you to navigate a maze and find the exit.
To make things more interesting the maze will be populated with creatures that
attack you.
Defeat them and you will be rewarded in gold coins.
Food, weapons and other useful items will be present in some rooms.
Only one room has the exit but you must pay a toll of 100 gold pieces to use 
it.

Lets begin by defining the maze and letting the player walk through it.
(Entering "q" during play will stop the program.)
Type (or edit) and RUN:

CLS
row = 5
column = 5
moveErr$ = "You cannot move in that direction!"

LOCATE 14,1
PRINT "Commands:   n - north"
PRINT "            s - south"
PRINT "            e - east"
PRINT "            w - west"
PRINT
PRINT "            q - quit"

DO
 LOCATE 1, 1
 PRINT "Your position:"; row; column
 LOCATE 8, 1
 INPUT "What now"; reply$
 LOCATE 10, 1
 PRINT SPACE$(79)

 SELECT CASE reply$
        CASE IS = "n"
         IF row = 1 THEN
          LOCATE 10, 1
          PRINT moveErr$
         ELSE
          row = row - 1
          LOCATE 10, 1
          PRINT "You go north."
         END IF
        CASE IS = "s"
         IF row = 10 THEN
          LOCATE 10, 1
          PRINT moveErr$
         ELSE
          row = row + 1
          LOCATE 10, 1
          PRINT "You go south."
         END IF
        CASE IS = "w"
         IF column = 1 THEN
          LOCATE 10, 1
          PRINT moveErr$
         ELSE
          column = column - 1
          LOCATE 10, 1
          PRINT "You go west."
         END IF
        CASE IS = "e"
         IF column = 10 THEN
          LOCATE 10, 1
          PRINT moveErr$
         ELSE
          column = column + 1
          LOCATE 10, 1
          PRINT "You go east."
         END IF
        CASE IS = "q"
         LOCATE 10, 1
         PRINT "Bye!"
         END 
 END SELECT

LOOP

You'll notice that the maze is 10 by 10 rooms in size.
I you try to move outside its boundaries you are stopped and an error message
appears (I stored it in variable "moveErr$" so there's less typing).

The command INPUT prompts the user for a value and stores it in a variable
(reply$).
As a bonus you can display some text at the same time ("What now").

SPACE$ is a function that provides spaces; SPACE$(2) gives you "  ".
What the program does at that point is to overwrite any error messages that 
resulted from the previous user input.  

"INT(RND * 10) + 1" gives a whole number ranging from 1 to 10.
How does it work?
INT gives the integer value of a variable, e.g. INT(1.9) gives 1.
Because RND gives a value between 0 and 1, RND * 10 will give a value between
0 and 10.
And because INT(0.99) = 0 and INT(9.99) = 9, it is necessary to add 1 to the 
result.  

Now to add an exit to the maze:
  
CLS
row = 5
column = 5
moveErr$ = "You cannot move in that direction!"
exitRow = INT(RND * 10) + 1                       :REM  <??? new
exitColumn = INT(RND * 10) + 1                    :REM    ?
gold = 0                                          :REM   ??

LOCATE 14, 1
PRINT "Commands:   n - north"
PRINT "            s - south"
PRINT "            e - east"
PRINT "            w - west"
PRINT "            x - use exit"                 :REM  <??- new
PRINT
PRINT "            q - quit"

DO
 LOCATE 1, 1
 PRINT "Your position:"; row; column
                                                         :REM  <??? new
 IF ((row = exitRow) AND (column = exitColumn)) THEN
  LOCATE 2, 1                                            :REM    ?
  PRINT "You are at the exit!"                           :REM    ?
 ELSE                                                    :REM    ?
  LOCATE 2, 1                                            :REM    ?
  PRINT SPACE$(79)                                       :REM    ?
 END IF                                                  :REM   ??
 LOCATE 8, 1
 INPUT "What now"; reply$
 LOCATE 10, 1
 PRINT SPACE$(79)

 SELECT CASE reply$
        CASE IS = "n"
         IF row = 1 THEN
          LOCATE 10, 1
          PRINT moveErr$
         ELSE
          row = row - 1
          LOCATE 10, 1
          PRINT "You go north."
         END IF
        CASE IS = "s"
         IF row = 10 THEN
          LOCATE 10, 1
          PRINT moveErr$
         ELSE
          row = row + 1
          LOCATE 10, 1
          PRINT "You go south."
         END IF
        CASE IS = "w"
         IF column = 1 THEN
          LOCATE 10, 1
          PRINT moveErr$
         ELSE
          column = column - 1
          LOCATE 10, 1
          PRINT "You go west."
         END IF
        CASE IS = "e"
         IF column = 10 THEN
          LOCATE 10, 1
          PRINT moveErr$
         ELSE
          column = column + 1
          LOCATE 10, 1
          PRINT "You go east."
         END IF
        CASE IS = "x"                                           :REM  <??? new
         IF ((row = exitRow) AND (column = exitColumn)) THEN
                                                                :REM    ?
          IF gold < 100 THEN
           LOCATE 10, 1                                         :REM    ?
           PRINT "You dont have enough gold!"                   :REM    ?
          ELSE                                                  :REM    ?
           LOCATE 10, 1                                         :REM    ?
           PRINT "You have escaped! Well done!"                 :REM    ?
           END                                                  :REM    ?
          END IF                                                :REM    ?
         END IF                                                 :REM   ??
        CASE IS = "q"
         LOCATE 10, 1
         PRINT "Bye!"
         END
 END SELECT

LOOP

Thought you could escape?
Maybe tomorrow when we add monsters and gold!

-------------------------------------------------------------------------------
?????????????????
? Week 2, Day 2 ?
?????????????????

To make things interesting we'll use RND to scatter a variety of monsters
throughout the maze.
The amount of gold present in a room will depend on how difficult the monster
is to beat.
Type (or edit) and RUN:

CLS
DIM monster(10, 10)                             :REM  <??- new
FOR count1 = 1 TO 10                            :REM    ?
 FOR count2 = 1 TO 10                           :REM    ?
  monster(count1, count2) = INT(RND * 11)       :REM    ?
 NEXT count2                                    :REM    ?
NEXT count1                                     :REM   ??

row = 5
column = 5
moveErr$ = "You cannot move in that direction!"
exitRow = INT(RND * 10) + 1
exitColumn = INT(RND * 10) + 1
gold = 0                 

DIM monster$(10)                            :REM  <??? new
RESTORE monsterData                         :REM    ?
FOR count = 1 TO 10                         :REM    ?
 READ monster$(count)                       :REM    ?
NEXT count                                  :REM   ??

LOCATE 14, 1
PRINT "Commands:   n - north"
PRINT "            s - south"
PRINT "            e - east"
PRINT "            w - west"
PRINT "            x - use exit"
PRINT
PRINT "            q - quit"

DO
 LOCATE 1, 1
 PRINT "Your position:"; row; column
 IF ((row = exitRow) AND (column = exitColumn)) THEN
  LOCATE 2, 1
  PRINT "You are at the exit!"
 ELSE
  LOCATE 2, 1
  PRINT SPACE$(79)
 END IF
 LOCATE 3, 1                                         :REM  <??? new
 PRINT "Monster: ";                                  :REM    ?
 monsterType = monster(row, column)                  :REM    ?
 IF monsterType = 0 THEN
  PRINT "nothing   "                                 :REM    ?
 ELSE                                                :REM    ?
  monsterName$ = MID$(monster$(monsterType), 1, 10)  :REM    ?
  PRINT monsterName$                                 :REM    ?
 END IF                                              :REM   ??

 LOCATE 8, 1
 INPUT "What now"; reply$
 LOCATE 10, 1
 PRINT SPACE$(79)

 SELECT CASE reply$
        CASE IS = "n"
         IF row = 1 THEN
          LOCATE 10, 1
          PRINT moveErr$
         ELSE
          row = row - 1
          LOCATE 10, 1
          PRINT "You go north."
         END IF
        CASE IS = "s"
         IF row = 10 THEN
          LOCATE 10, 1
          PRINT moveErr$
         ELSE
          row = row + 1
          LOCATE 10, 1
          PRINT "You go south."
         END IF
        CASE IS = "w"
         IF column = 1 THEN
          LOCATE 10, 1
          PRINT moveErr$
         ELSE
          column = column - 1
          LOCATE 10, 1
          PRINT "You go west."
         END IF
        CASE IS = "e"
         IF column = 10 THEN
          LOCATE 10, 1
          PRINT moveErr$
         ELSE
          column = column + 1
          LOCATE 10, 1
          PRINT "You go east."
         END IF
        CASE IS = "x"
         IF ((row = exitRow) AND (column = exitColumn)) THEN
          IF gold < 100 THEN
           LOCATE 10, 1
           PRINT "You dont have enough gold!"
          ELSE
           LOCATE 10, 1
           PRINT "You have escaped! Well done!"
           END
          END IF
         END IF
        CASE IS = "q"
         LOCATE 10, 1
         PRINT "Bye!"
         END
 END SELECT

LOOP

monsterData:                      :REM  <??? new
DATA "blind bat "                 :REM    ?
DATA "rat       "                 :REM    ?
DATA "snake     "                 :REM    ?
DATA "goblin    "                 :REM    ?
DATA "troll     "                 :REM    ?
DATA "bear      "                 :REM    ?
DATA "lion      "                 :REM    ?
DATA "sabretooth"                 :REM    ?
DATA "elephant  "                 :REM    ?
DATA "dragon    "                 :REM   ??

I decided to allocate a number to each room to identify the type of monster in
the room.
To do this I needed 10 x 10 numbers.
If we keep in mind that our player's location is stored as a row and a column
value, its easy to see why I decided to to use a similar method of storing
the monster values.
Just by using row and column ( monster(row, column) ) you get the monster value
at the player's location.

As you can see at the top of the program, I gave each location a monster value
ranging from 0 to 10 (remember that INT(RND * 11) never gives 11).
Why not 1 to 10?
The 0 will serve as an indicator that there is no monster at that location.

What's RESTORE and READ?
The READ command looks for DATA statements in your program and reads their
values (e.g. the names of the monsters).
It starts at the first DATA statement unless you use RESTORE to point it to
a specific part of the program.
RESTORE points to a LABEL (e.g. monsterData).
You can put LABELS anywhere in your program, just remember to follow it with a
colon.

Why READ the monster names when you can use: monster$(1) = "blind bat ",
monster$(2) = "rat       ", etc?
Its just easier to find the data if its grouped together.
You can then use a FOR..NEXT loop to set the values rather than typing
monster(x)="abcd" every time.

One last thing about READ: it remembers the position where it last read a value
, so you have to use RESTORE if you want to read from the top again.     

Notice how I use the monster number (monsterType) to display its name from a
monster$. 
So if monsterType = 1 then monster$(monsterType) = "blind bat " will be
displayed.

This should be enough reading for one day!

-------------------------------------------------------------------------------
?????????????????
? Week 2, Day 3 ?
?????????????????

What good are monsters if they dont put up a fight?
I'll rectify that if you type and RUN:

CLS
DIM monster(10, 10)
FOR count1 = 1 TO 10
 FOR count2 = 1 TO 10
  monster(count1, count2) = INT(RND * 11)
 NEXT count2
NEXT count1

row = 5
column = 5
moveErr$ = "You cannot move in that direction!"
pressKey$ = "Press any key to continue."             :REM  <??- new
exitRow = INT(RND * 10) + 1
exitColumn = INT(RND * 10) + 1
gold = 0
health = 20                                          :REM  <??? new
weapon = 1                                           :REM   ??

DIM monster$(10)
RESTORE monsterData
FOR count = 1 TO 10
 READ monster$(count)
NEXT count

LOCATE 14, 1
PRINT "Commands:   n - north"
PRINT "            s - south"
PRINT "            e - east"
PRINT "            w - west"
PRINT "            a - attack"             :REM  <??- new
PRINT "            x - use exit"
PRINT
PRINT "            q - quit"

DO
 LOCATE 1, 1
 PRINT "Your position:"; row; column
 LOCATE 1, 25                                           :REM  <??? new
 PRINT "Gold:"; gold; "  Health:"; health               :REM   ??
  IF ((row = exitRow) AND (column = exitColumn)) THEN 
  LOCATE 2, 1
  PRINT "You are at the exit!"
 ELSE
  LOCATE 2, 1
  PRINT SPACE$(79)
 END IF
 LOCATE 3, 1
 PRINT "Monster: ";
 monsterType = monster(row, column)
 IF monsterType = 0 THEN
  PRINT "nothing   "
 ELSE
  monsterName$ = MID$(monster$(monsterType), 1, 10)
  PRINT monsterName$
  monsterAttack = VAL(MID$(monster$(monsterType), 11, 1))     :REM  <??- new
  monsterHealth = VAL(MID$(monster$(monsterType), 12, 1))     :REM    ?
  monsterGold = monsterType * INT(RND * 6)                    :REM   ??
 END IF

 LOCATE 8, 1
 INPUT "What now"; reply$
 LOCATE 10, 1
 PRINT SPACE$(79)
 PRINT SPACE$(79)
 PRINT SPACE$(79)
  
 SELECT CASE reply$
        CASE IS = "n"
         IF row = 1 THEN
          LOCATE 10, 1
          PRINT moveErr$
         ELSE
          row = row - 1
          LOCATE 10, 1
          PRINT "You go north."
         END IF
        CASE IS = "s"
         IF row = 10 THEN
          LOCATE 10, 1
          PRINT moveErr$
         ELSE
          row = row + 1
          LOCATE 10, 1
          PRINT "You go south."
         END IF
        CASE IS = "w"
         IF column = 1 THEN
          LOCATE 10, 1
          PRINT moveErr$
         ELSE
          column = column - 1
          LOCATE 10, 1
          PRINT "You go west."
         END IF
        CASE IS = "e"
         IF column = 10 THEN
          LOCATE 10, 1
          PRINT moveErr$
         ELSE
          column = column + 1
          LOCATE 10, 1
          PRINT "You go east."
         END IF
        CASE IS = "x"
         IF ((row = exitRow) AND (column = exitColumn)) THEN
          IF gold < 100 THEN
           LOCATE 10, 1
           PRINT "You dont have enough gold!"
          ELSE
           LOCATE 10, 1
           PRINT "You have escaped! Well done!"
           END
          END IF
         END IF
        CASE IS = "a"                                             :REM  <?? new
         IF monsterType = 0 THEN
          LOCATE 10, 1                                            :REM    ?
          PRINT "There's nothing to attack!"                      :REM    ?
         ELSE                                                     :REM    ?
          DO WHILE ((monsterHealth > 0) AND (health > 0))         :REM    ?
           LOCATE 10, 1                                           :REM    ?
           PRINT SPACE$(79)                                       :REM    ?
           PRINT SPACE$(79)                                       :REM    ?
           PRINT SPACE$(79)                                       :REM    ?
           LOCATE 10, 1                                           :REM    ?
           attack = weapon + INT(RND * 9)                         :REM    ?
           SELECT CASE attack                                     :REM    ?
                  CASE IS = monsterAttack                         :REM    ?
                   PRINT "No one wins this round."                :REM    ?
                  CASE IS > monsterAttack                         :REM    ?
                   PRINT "You deal the "; monsterName$; " a blow!":REM    ?
                   monsterHealth = monsterHealth - 1              :REM    ?
                  CASE IS < monsterAttack                         :REM    ?
                   PRINT "You have been wounded!"                 :REM    ?
                   health = health - 1                            :REM    ?
           END SELECT                                             :REM    ?
           PRINT pressKey$                                        :REM    ?
           SLEEP                                                  :REM    ?
          LOOP                                                    :REM    ?
          LOCATE 10, 1                                            :REM    ?
          IF health > 0 THEN
           PRINT "You won the fight!"                             :REM    ?
           PRINT "You found "; monsterGold; " pieces of gold!"    :REM    ?
           gold = gold + monsterGold                              :REM    ?
           monsterType = 0                                        :REM    ?
           monster(row, column) = 0                               :REM    ?
           PRINT pressKey$                                        :REM    ?
           SLEEP                                                  :REM    ?
          ELSE                                                    :REM    ?
           PRINT "The "; monsterName$; " killed you!"             :REM    ?
           PRINT "Game over!"                                     :REM    ?
           END                                                    :REM    ?
          END IF                                                  :REM    ?
         END IF                                                   :REM   ??
        CASE IS = "q"     
         LOCATE 10, 1                                                
         PRINT "Bye!"                                                
         END                                                         
 END SELECT                                                          

LOOP

monsterData:                    
DATA "blind bat 21"                  :REM  <??? changed
DATA "rat       11"                  :REM    ?
DATA "snake     31"                  :REM    ?
DATA "goblin    23"                  :REM    ?
DATA "troll     44"                  :REM    ?
DATA "bear      55"                  :REM    ?
DATA "lion      54"                  :REM    ?
DATA "sabretooth65"                  :REM    ?
DATA "elephant  78"                  :REM    ?
DATA "dragon    98"                  :REM   ??

Starting from the top:
The variable "health" starts of at 20 but 1 gets subtracted from it each time a
monster hits you.
If it reaches 0 you've had it.
The variable "weapon" gets added to your attack score: weapon + INT(RND * 9).
So the attack score will range from 1 to 9. (INT(RND * 9) gives 0 to 8)

MonsterAttack: A monster's attack score is stored as the second last character
               in a monster$.
VAL takes a string and converts it to a decimal value, so VAL("10") gives 10.
Trying something like VAL("ABC") will cause a runtime error.

MonsterHealth: The last character READ into a monster$ is the monster's health.
               Each time you wound it, it loses a point of health and dies when
               it loses all its points.

MonsterGold: I chose to add a random factor to the amount of gold found, but by
             multiplying with monsterAttack you should still find more gold 
             after defeating tougher monsters.

Notice that fighting takes place and continues until one side runs out of 
health.
So when this loop terminates we know that if your health > 0 then the monster's
health must have run out.
If the monster loses then monsterType is set to 0 so that you cannot fight
it again.
Monsters(row, column) = 0 changes the location's monster to "nothing", so when
you enter this location again there will be no monsters.

Can you remember that the SLEEP command is used to pause the program for a
number of seconds?
SLEEP on its own waits indefinitely or until a key is pressed.
I've used it to wait for a keypress.
You can use   DO: LOOP UNTIL INKEY$ <> ""   instead of SLEEP.
 
Thats all for now!

-------------------------------------------------------------------------------
?????????????????
? Week 2, Day 4 ?
?????????????????

Lets scatter some useful items like food and weapons throughout the maze.
To balance things we'll add a few traps..

CLS
RANDOMIZE TIMER                                 :REM  <??? new
DIM monster(10, 10)
FOR count1 = 1 TO 10
 FOR count2 = 1 TO 10
  monster(count1, count2) = INT(RND * 11)
 NEXT count2
NEXT count1

DIM item(10, 10)                                :REM  <??? new
FOR count1 = 1 TO 10                            :REM    ?
 FOR count2 = 1 TO 10                           :REM    ?
  IF RND < .2 THEN                              :REM    ?
   item(count1, count2) = INT(RND * 9) + 1      :REM    ?
  ELSE                                          :REM    ?
   item(count1, count2) = 0                     :REM    ?
  END IF                                        :REM    ?
 NEXT count2                                    :REM    ?
NEXT count1                                     :REM   ??

row = 5
column = 5
moveErr$ = "You cannot move in that direction!"
pressKey$ = "Press any key to continue."
exitRow = INT(RND * 10) + 1
exitColumn = INT(RND * 10) + 1
gold = 0
health = 20
weapon = 1

DIM monster$(10)
RESTORE monsterData
FOR count = 1 TO 10
 READ monster$(count)
NEXT count

DIM item$(9)                                    :REM  <??? new
RESTORE itemData                                :REM    ?
FOR count = 1 TO 9                              :REM    ?
 READ item$(count)                              :REM    ?
NEXT count                                      :REM   ??

LOCATE 14, 1
PRINT "Commands:   n - north"
PRINT "            s - south"
PRINT "            e - east"
PRINT "            w - west"
PRINT "            a - attack"
PRINT "            t - take item"               :REM  <??? new
PRINT "            x - use exit"
PRINT
PRINT "            q - quit"

LOCATE 14, 40                                           :REM  <??? new
PRINT CHR$(201); STRING$(10, CHR$(205)); CHR$(187)      :REM    ?
LOCATE 15, 40                                           :REM    ?
PRINT CHR$(186); SPACE$(10); CHR$(186)                  :REM    ?
LOCATE 16, 40                                           :REM    ?
PRINT CHR$(200); STRING$(10, CHR$(205)); CHR$(188)      :REM    ?
LOCATE 17, 44                                           :REM    ?
PRINT "ITEM"                                            :REM   ??

DO
 LOCATE 1, 1
 PRINT "Your position:"; row; column
 LOCATE 1, 25
 PRINT "Gold:"; gold; "  Health:"; health; "  Weapon:"; weapon  :REM <??changed
  IF ((row = exitRow) AND (column = exitColumn)) THEN
  LOCATE 2, 1
  PRINT "You are at the exit!"
 ELSE
  LOCATE 2, 1
  PRINT SPACE$(79)
 END IF
 LOCATE 3, 1
 PRINT "Monster: ";
 monsterType = monster(row, column)
 IF monsterType = 0 THEN
  PRINT "nothing   "
 ELSE
  monsterName$ = MID$(monster$(monsterType), 1, 10)
  PRINT monsterName$
  monsterAttack = VAL(MID$(monster$(monsterType), 11, 1))
  MonsterHealth = VAL(MID$(monster$(monsterType), 12, 1))
  MonsterGold = monsterType * INT(RND * 6)
 END IF

 itemType (or edit) = item(row, column)                           :REM  <??? new
 IF itemType (or edit) = 0 THEN                                   :REM    ?
  LOCATE 15, 41                                         :REM    ?
  PRINT "nothing   "                                    :REM    ?
 ELSE                                                   :REM    ?
  itemName$ = LEFT$(item$(itemType (or edit)), 10)                :REM    ?
  itemClass$ = MID$(item$(itemType (or edit)), 11, 1)             :REM    ?
  itemValue = VAL(RIGHT$(item$(itemType (or edit)), 1))           :REM    ?
  LOCATE 15, 41                                         :REM    ?
  PRINT itemName$                                       :REM    ?
  IF itemClass$ = "T" THEN                              :REM    ?
   LOCATE 10, 1                                         :REM    ?
   PRINT "The "; RTRIM$(itemName$); " damages you for "; itemValue; " points!"
   health = health - itemValue                          :REM    ?
   item(row, column) = 0                                :REM    ?
   itemType (or edit) = 0                                         :REM    ?
   IF health <= 0 THEN                                  :REM    ?
    PRINT "You die!"                                    :REM    ?
    PRINT "Game over!"                                  :REM    ?
    END                                                 :REM    ?
   END IF                                               :REM    ?
  END IF                                                :REM    ?
 END IF                                                 :REM   ??

 LOCATE 8, 1
 INPUT "What now"; reply$
 LOCATE 10, 1
 PRINT SPACE$(79)
 PRINT SPACE$(79)
 PRINT SPACE$(79)
  
 SELECT CASE reply$
        CASE IS = "n"
         IF row = 1 THEN
          LOCATE 10, 1
          PRINT moveErr$
         ELSE
          row = row - 1
          LOCATE 10, 1
          PRINT "You go north."
         END IF
        CASE IS = "s"
         IF row = 10 THEN
          LOCATE 10, 1
          PRINT moveErr$
         ELSE
          row = row + 1
          LOCATE 10, 1
          PRINT "You go south."
         END IF
        CASE IS = "w"
         IF column = 1 THEN
          LOCATE 10, 1
          PRINT moveErr$
         ELSE
          column = column - 1
          LOCATE 10, 1
          PRINT "You go west."
         END IF
        CASE IS = "e"
         IF column = 10 THEN
          LOCATE 10, 1
          PRINT moveErr$
         ELSE
          column = column + 1
          LOCATE 10, 1
          PRINT "You go east."
         END IF
        CASE IS = "x"
         IF ((row = exitRow) AND (column = exitColumn)) THEN
          IF gold < 100 THEN
           LOCATE 10, 1
           PRINT "You dont have enough gold!"
          ELSE
           LOCATE 10, 1
           PRINT "You have escaped! Well done!"
           END
          END IF
         END IF
        CASE IS = "a"
         IF monsterType = 0 THEN
          LOCATE 10, 1
          PRINT "There's nothing to attack!"
         ELSE
          DO WHILE ((MonsterHealth > 0) AND (health > 0))
           LOCATE 10, 1
           PRINT SPACE$(79)
           PRINT SPACE$(79)
           PRINT SPACE$(79)
           LOCATE 10, 1
           attack = weapon + INT(RND * 9)
           SELECT CASE attack
                  CASE IS = monsterAttack
                   PRINT "No one wins this round."
                  CASE IS > monsterAttack
                                                              :REM  <?? changed
                   PRINT "You deal the "; RTRIM$(monsterName$); " a blow!"
                                                              :REM   ??????
                   MonsterHealth = MonsterHealth - 1
                  CASE IS < monsterAttack
                   PRINT "You have been wounded!"
                   health = health - 1
           END SELECT
           PRINT pressKey$
           SLEEP
          LOOP
          LOCATE 10, 1
          IF health > 0 THEN
           PRINT "You won the fight!"; SPACE$(20)
           PRINT "You found "; MonsterGold; " pieces of gold!"
           gold = gold + MonsterGold
           monsterType = 0
           monster(row, column) = 0
           PRINT pressKey$
           SLEEP
          ELSE
                                                              :REM  <?? changed
           PRINT "The "; RTRIM$(monsterName$); " killed you!"; SPACE$(20)
                                                              :REM   ??????
           PRINT "Game over!"; SPACE$(20)
           END
          END IF
         END IF
        CASE IS = "t"                                               :REM <??new
         IF itemType (or edit) = 0 THEN                                       :REM   ?
          LOCATE 10, 1                                              :REM   ?
          PRINT "Nothing to take!"                                  :REM   ?
          PRINT pressKey$                                           :REM   ?
          SLEEP                                                     :REM   ?
         ELSE                                                       :REM   ?
          SELECT CASE itemClass$                                    :REM   ?
                CASE IS = "F"                                       :REM   ?
                 LOCATE 10, 1                                       :REM   ?
                 PRINT "You eat the "; RTRIM$(itemName$); "."       :REM   ?
                 IF health = 20 THEN                                :REM   ?
                  PRINT "You had no wounds, so the food is wasted." :REM   ?
                 ELSE                                               :REM   ?
                  health = health + itemValue                       :REM   ?
                  PRINT "You gain "; itemValue; " health points."   :REM   ?
                 END IF                                             :REM   ?
                CASE IS = "W"                                       :REM   ?
                 LOCATE 10, 1                                       :REM   ?
                 IF weapon >= itemValue THEN                        :REM   ?
                  PRINT "You have a similar or better weapon."      :REM   ?
                 ELSE                                               :REM   ?
                  PRINT "You pick up a "; RTRIM$(itemName$); " !"   :REM   ?
                  weapon = itemValue                                :REM   ?
                  PRINT "Your weapon rating is now "; weapon; "."   :REM   ?
                 END IF                                             :REM   ?
          END SELECT                                                :REM   ?
          PRINT pressKey$                                           :REM   ?
          SLEEP                                                     :REM   ?
          item(row, column) = 0                                     :REM   ?
          itemType (or edit) = 0                                              :REM   ?
         END IF                                                     :REM  ??
        CASE IS = "q"
         LOCATE 10, 1
         PRINT "Bye!"
         END
 END SELECT

LOOP

monsterData:                 
DATA "blind bat 21"               
DATA "rat       11"               
DATA "snake     31"               
DATA "goblin    23"               
DATA "troll     44"               
DATA "bear      55"               
DATA "lion      54"               
DATA "sabretooth65"               
DATA "elephant  78"               
DATA "dragon    98"               

itemData:                               :REM  <??? new
DATA "apple     F1"                     :REM    ?
DATA "bread     F2"                     :REM    ?
DATA "chicken   F3"                     :REM    ?
DATA "dagger    W2"                     :REM    ?
DATA "sword     W3"                     :REM    ?
DATA "halberd   W4"                     :REM    ?
DATA "smoke     T1"                     :REM    ?
DATA "noose trapT2"                     :REM    ?
DATA "pit trap  T3"                     :REM   ??

Starting from the top:
You have probably noticed that, although RND gives random effects, you keep
getting the same set of random values!
This is because the computer uses a base value (called a "seed") to start
calculating RND.
RANDOMIZE sets the "seed" to a new value so the RNDs will be different.
The value of TIMER is the amount of seconds since midnight.
Because this value keeps changing we use it as a "seed" in the expression
RANDOMIZE TIMER.

Items are addressed by using the array item(10, 10), allowing for one item
per room in the maze.
There's only a 20% chance of a room having an item (RND < .2) and then the
item is identified by a number ranging from 1 to 9.
More data on the 9 different item types is READ into item$.

CHR$ is used to convert an ASCII value into a character.
So instead of doing PRINT "A", we can use PRINT CHR$(65), 65 being its ASCII
value.
By using CHR$ we can access some nice characters for graphical purposes.
To view these characters in QBasic: Press SHIFT-F1.  Choose the "Contents" box,
then choose the "ASCII character codes" box.
The character with ASCII value 2 would make a nice PACMAN.

Each "item" has a name, class and value.
The class shows whether its food ("F"), a weapon ("W"), or a trap("T").
The value is used differently for each class:
class:  food           Value:  number of health points gained by player
        weapon                 new "weapon" value for player
        trap                   number of health points player will lose

LEFT$(a$, 10) is the same as MID$(a$, 1, 10), in other words it just starts
at the first position in the string.
RIGHT$("ABCDE", 3) gives "CDE", in other words it takes the rightmost 3
characters.
You can use MID$ instead of LEFT$ and RIGHT$, but its possible to save time by
using them.

The "trap" item immediately damages the player upon entering the room.
The trap is then disabled by removing it from the array (item(row, column) = 0)

RTRIM$("ABC  ") gives "ABC", in other words it removes the spaces on the right.
LTRIM$ work in the same way, but removes spaces from the left.

I added some interesting checks for when a player takes an item.
If he takes food and he has no wounds (health = 20), the food goes to waste.
If he tries to take a weapon thats rated worse or the same as his present
weapon, he is stopped.

This concludes our RPG.
Tomorrow I'll illustrate a few commands for generating graphics.

-------------------------------------------------------------------------------
?????????????????
? Week 2, Day 5 ?
?????????????????

I'll demonstrate manipulation of a simple graphic by putting the screen in
graphics mode (its usually in text mode), drawing the graphic, grabbing it
from the screen and storing it in an array, displaying it again from the array
while shifting its position from the left to the right of the screen.
(I have a long breath!)
Here goes:

REM SCREEN mode number
REM        1 = CGA 320x200, 4 colors Graphics mode
SCREEN 1

REM COLOR palette number,                      background color
REM       0 -> black, green, red,     brown    0 to 15
REM       1 -> black, cyan,  magenta, white
REM      color = 0     1      2        3
COLOR 0, 1

xDim = 16: REM The width of the image in pixels
yDim = 16: REM The height of the imgae in pixels

REM Use this formula for calculating the size of the array needed to store
REM the image.  The size is measured in bytes.
size = 4 + INT(((xDim + 1) * 2 + 7) / 8) * (yDim + 1)

DIM pic(size / 2) AS INTEGER: REM An INTEGER is two bytes in size

REM Draw a block 14x14 pixels in size and fill it.
REM LINE (startX, startY)-(endX, endY), color, BF=block fill
REM The entire screen starts at (0, 0) and ends at (319, 199)
LINE (1, 1)-(14, 14), 1, BF

REM Get a 16x16 image from the screen and store it in the array pic.
GET (0, 0)-(15, 15), pic

CLS

FOR count = 0 TO 320 - 16
 REM Put the image on the screen. PSET makes it overwrite the previous image.
 PUT (count, 90), pic, PSET
 REM Slow down the computer.  Make the value bigger if its still too fast.
 FOR nothing = 1 TO 100
 NEXT nothing
NEXT count

END

The REMs explain nearly everything.
Experiment with colors by choosing one of the two sets (four colors in each
set) by modifying the COLOR statement.
Then choose between the four available colors by modifying the LINE statement.

Why did I draw a 14x14 image but stored it as a 16x16 image?
That way the stored image is surrounded by a "frame" of black dots.
When moving the image around, the black "frame" deletes the previous (old)
image.
So I'm displaying the image in its new position and deleting the old image at
the same time!

You could make more interesting images by using the PSET command which places
dots on the screen.
Type (or edit) and RUN:

SCREEN 1
COLOR 0, 1

xDim = 8
yDim = 8

size = 4 + INT(((xDim + 1) * 2 + 7) / 8) * (yDim + 1)

DIM pic(size / 2) AS INTEGER

RESTORE pacmanPic
FOR row = 1 TO yDim
 FOR column = 1 TO xDim
  READ picData
  PSET (column, row), picData
 NEXT column
NEXT row

GET (0, 0)-(xDim - 1, yDim - 1), pic

CLS

FOR count = 0 TO 320 - 16
 PUT (count, 90), pic, PSET
 FOR nothing = 1 TO 100
 NEXT nothing
NEXT count

END

pacmanPic:
DATA 0,0,0,0,0,0,0,0
DATA 0,0,1,1,1,1,0,0
DATA 0,1,1,1,2,1,1,0
DATA 0,1,1,0,0,0,0,0
DATA 0,1,1,0,0,0,0,0
DATA 0,1,1,1,1,1,1,0
DATA 0,0,1,1,1,1,0,0
DATA 0,0,0,0,0,0,0,0

Storing the pixels as DATA beats doing every one with the PSET command!
Try changing the picture DATA using the values 0 to 3.

Just by changing yDim and xDim and the DATA you can now design and display a
bigger or smaller picture.

-------------------------------------------------------------------------------
Thats all folks!
================
Hope you enjoyed the course - I can honestly say that I enjoyed writing it.

If you have any comments or questions you can E-mail me at my Internet address:
?????????????????????????
? avw@mickey.iaccess.za ?
?????????????????????????
or you can reach me by snail-mail:
?????????????????????
? A. van Wyk        ?
? 105 Sidvale Court ?
? Parow             ?
? 7500              ?
? Western Cape      ?
? South Africa      ?
?????????????????????

If you have found the course useful and would like to see further modules, just
let me know!
Time allowing and if there is sufficient interest, I will expand on the course.

Cheers for now,
Andre