mirror of
https://github.com/opsxcq/mirror-textfiles.com.git
synced 2025-08-09 14:36:34 +02:00
1061 lines
38 KiB
Plaintext
1061 lines
38 KiB
Plaintext
ÖÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ·
|
|
º 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
|