The feeling of progress is a huge part of a game’s enjoyability. I am not 100% sure that is a word, but you know what I mean!
This is the difference between a “pick up and play mini game” versus “wow, look at the time, I just spent my entire work day on this!”. Hypothetically.
As of now, our C64 BASIC dungeon has no levelling up, no character development, just one map. Don’t get me wrong, lots of fun games have one screen and no character development, but they do usually increase difficulty as your session continues.
So next we need to add progress, difficulty ramping, and character stats buffing.

You can play and examine the finished code listing by loading part11a.bas in the RGC online IDE. If you missed it, check out the previous part too (part ten).
Progress so far
While we only have one map, it is a playable one now. When you find the chalice the game ends with “YOU WIN” and a play again prompt.
Selecting to play again rolls a new character and generates a new map. All your progress is wiped, it is essentially the same as hitting ‘N’ for new game.

You can now follow the tutorials and edit the code right in your web browser with the Online Retro IDE
– No downloads, configuration, etc necessary, and it is free!
Defining what a level is now
In this version we move to have five levels. Each one generates a new map using the same generator as part ten, but with more rules around object placement and creation.
Rather than one chalice, now to leave a level you need to grab every chalice in the dungeon, only then can you walk onto the stairs. The number of chalices increases as the level goes up, and just to make it interesting it is not a simple +1:
| Level | 1 | 2 | 3 | 4 | 5 |
|---|---|---|---|---|---|
| Chalices | 1 | 1 | 2 | 2 | 3 |
LV is the level number, CL is chalices left. INT throws away the fraction, so levels 1 and 2 give 1, levels 3 and 4 give 2, level 5 gives 3.
CL=INT((LV+1)/2)
Your character now persists while they are still alive, keeping your hit points, stats, gold, keys and magic.
For now, the stairs on level 5 gets you out of the dungeon and wins you the game.
Win or lose, we now also show the level you reached as well as the gold acquired.

One routine builds a level
In part ten, I set the player up and drew the map in two places, starting a game, and the N key for a new game.
That code is now split in two. INITPLAYER is for everything about the character and only runs once per game. BUILDLEVEL is now everything about each level and runs once per level.
BUILDLEVEL:
PX=10 : PY=11 : OX=PX : OY=PY
WN=0 : LA=0
CL=INT((LV+1)/2)
POKE 53280,0 : POKE 53281,0
GOSUB MAPBLANK
GOSUB MAPROLL
GOSUB DISPLAY
GOSUB POPULATE
GOSUB DRAWPLAYER
RETURN
PX, PY put the player back at the start cell. WN is the “leave this level” flag. LA is the number of lines in the message log, zero because the screen has just been cleared.
A new game is GOSUB INITPLAYER then GOSUB BUILDLEVEL. Going down the stairs is GOSUB BUILDLEVEL on its own.
That is the difference between resetting the game and resetting the level, and is what lets the character survive the map generation intact.
Using the stairs
The stairs are placed in one of the four corner rooms, picked at random. Your player starts in the centre room, so the stairs can never be in the room you start in.
EX=4*INT(RND(1)*2) : EY=4*INT(RND(1)*2)
INT(RND(1)*2) is 0 or 1. Times 4 makes it 0 or 4, the first or last room across, and the same again for down.
Part ten’s map rule already makes every room reachable from every other, so any selected room should be a safe choice. I don’t check that the stairs can be reached, because by that logic they always can be.
I do force the stairs room to the open room type, and the stairs are placed in its centre cell.
IF RX=EX AND RY=EY THEN MT=1
The reason is stairs block movement until the chalice(s) are collected. We don’t want to block movement by placing the stairs in a bad spot.
Getting the position of that centre cell comes from the room numbers. A room is 4 cells wide including its left wall, and the map starts on screen row 2.
ROW=EY*4+4 : COL=EX*4+2
Gathering chalices and activating the stairs
Each chalice is still worth 10 gold and counts CL down. When it reaches zero the log tells you to “FIND THE STAIRS”.
POPULATE places as many chalices as the level needs, then sets CL to the number that were placed. PLACEONE gives up after 200 failed tries at finding empty floor, so on a crowded map a chalice could actually fail to appear. Counting only the ones that were added means the level can still be finished.
Q=CL : CL=0
IT$="{PURPLE}(" : FOR N=1 TO Q : GOSUB PLACEONE : CL=CL+PF : NEXT N
PF is PLACEONE‘s “it worked” flag, 1 or 0, so adding it up counts the successes.
Walking into the stairs with chalices still unpicked bounces the player back with “CHALICES LEFT” and the number.
With none left, the stairs set WN=1 and return. WN started life as ‘won’ in part 10, and now it means the level is won, not the entire game!
The main loop sees the flag and jumps to NEXTLEVEL. It’s the same flag-then-GOTO approach we used for winning in part ten. The stairs are found inside a GOSUB, and building a new level from in there would leave that GOSUB unfinished on BASIC’s stack every time.
Levelling up
For now, each new level rewards your character hit points equal to half your constitution, rounded down. We also add +1 to strength on even levels, and +1 dexterity on odd ones.
This is mainly to show how it can be done at this point, we can give more thought to what would be actually beneficial later in a polishing phase.
HL=INT(STATS(2)/2) : HP=HP+HL
S=LV AND 1 : STATS(S)=STATS(S)+1
AC=10+INT((STATS(1)-10)/2)
STATS(0) is strength, STATS(1) is dexterity, STATS(2) is constitution.
LV AND 1 is 1 for an odd number and 0 for an even one. AND compares the two numbers bit by bit, and the lowest bit of any odd number is 1. So the answer is also the array index of the stat to raise.
Armour class is worked out again afterwards, because it is derived from your dexterity.
Strength helps your to-hit roll and the damage you deal via its modifier. A modifier only changes on every second point, so one point of strength does not always immediately make much difference. Again, balancing character abilities versus good fortune is a balancing thing once you have code working.
The log reveals to you the new level, the stat that went up and the hit points gained.
Potions finally become magic
Collecting a * potion now adds 50 magic, up to a ceiling of 100.
IF CH=42 THEN MG=MG+50:MSG$="MAGIC UP 50":GOSUB TAKEITEM
IF MG>100 THEN MG=100
Nothing spends magic yet, but it is counted and shown, ready for the ranged attack in part twelve.
The numbers match the C version of this game, where the same pickup gives 50 and a spell costs 5 plus 1 for each cell it travels.

The status line
This means we need two more counters, your magic, and the current level. As we take up more room, the gaps between the counters went from two spaces to one. Our status line is now 31 characters out of the 40 available.
It is built with two PRINT statements. The first ends in a semicolon, which keeps the cursor on the same line for the second part.
Still on the to-do list
First, we added some progression but we really need to ramp up difficulty. Every level still has the same 3 to 6 goblins, for example.
Second, magic can be collected but not be used yet.
Lastly, we still have some RAM available, so can we fit into memory more pickups and gameplay variety?
Some questions for you:
- Should stairs work in both directions? Would revisiting a level respawn the enemies?
- Collected keys carry over, so should we encourage holding a spare key from one level so you can open a door on the next?
- Levelling up your character is automatic, should we offer the player a choice of which stat to raise?
- How many levels should there be before game over?


Worth a Watch issue 06