ÖÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ· º 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