Kingdom of the Lyre: Combat
Thursday, 14th November 2019
In this series, Damian blogs about how the game works.
Since it's a simple game, combat in Kingdom of the Lyre is as simple as I could make it. You have one stat, health, stored in the variable H. Monsters from random encounters have their strength or number stored in the variable M. Each combat round, one or other stat gets reduced by one, and combat finishes when one side is dead or the player flees. The main routine is here:
REM --- Deal with a random encounter
210 LET Z=F
LET C=0
211 GOSUB 990
LET C=C+1
IF C<=P THEN GOTO 211
IF Z-Z/8*8>1 THEN RETURN
REM --- Monster encountered
GOSUB 400
IF J=3 THEN GOTO 213
LET Z=G
REM --- Combat loop
212 PRINT "Health: ",H,", enemy strength: ",M
PRINT " 0:quit, 1:fight or 2:flee?"
INPUT C
IF C<0 THEN GOTO 212
IF C>2 THEN GOTO 212
IF C=0 THEN LET Q=1
IF C=2 THEN GOTO 214
REM --- Do battle!
GOSUB 990
LET G=Z
IF Z/100-Z/200*2=1 THEN GOSUB 410
IF Z/100-Z/200*2=0 THEN GOSUB 420
IF M=0 THEN GOSUB 430
IF H=0 THEN GOSUB 440
IF Q=0 THEN IF H>0 THEN IF M>0 THEN IF C<>2 THEN GOTO 212
RETURN
REM --- The player is invisible - sneak past the monsters
213 PRINT "You are invisible, so you sneak past the enemy."
RETURN
REM --- The cowardly player flees the monsters
214 PRINT "You flee back whence you came!"
LET D=10-D
IF D=2 THEN LET P=P-80
IF D=4 THEN LET P=P-1
IF D=6 THEN LET P=P+1
IF D=8 THEN LET P=P+80
GOSUB 300
GOSUB 310
RETURN
We've already dealt with the initial encounter in the previous blog post. After generating and displaying the monsters, combat will be skipped entirely if J (the variable for potion Just drunk) is 3 (invisibility). Otherwise, initialise the random number generator from a variable seed, G.
If the F seed were used for combat, then each fight with a particular random enemy would go the same way. If a fight goes badly and you flee, you don't want it to go exactly the same way when you return. So the G seed is used instead, and this is changed every time the player attempts to hit an enemy.
The combat round itself chooses randomly between the routines at 410 and 420, which I reproduce here. 410 is what happens if a monster hits the player, 420 if the player hits the monster.
REM --- Subroutine process a monster hit on the player
REM --- Inputs: T - the terrain
REM --- Changes: H - player's reduced health
410 LET H=H-1
GOTO 411+T
411 PRINT "A thief hits you, reducing your health to ",H
RETURN
412 PRINT "A boar impales you, reducing your health to ",H
RETURN
413 PRINT "A goblin slashes at you, reducing your health to ",H
RETURN
414 PRINT "The crocodile snaps at you, reducing your health to ",H
RETURN
REM --- Subroutine process a player hit on a monster
REM --- Inputs: T - the terrain
REM --- Changes: M - the reduced number of monsters
420 LET M=M-1
GOTO 421+T
421 PRINT "You kill a thief, reducing their numbers to ",M
RETURN
422 PRINT "You kill a boar, reducing their numbers to ",M
RETURN
423 PRINT "You kill a goblin, reducing their numbers to ",M
RETURN
424 PRINT "You hit the crocodile, reducing its strength to ",M
RETURN
Their complexity comes from the need for flavour text and the lack of strings or arrays: in Tiny BASIC you can't have a line like
PRINT "The ",M$," hits you."
Because of this limitation, it's actually easier to make the monsters behave differently from each other. Had I had more time I'd definitely have done this. Subroutine 430 deals with a player victory over the enemy:
REM --- Subroutine to deal the the aftermath of combat victory
REM --- Inputs: H - health affects how grateful peasants are
REM --- L - location of the lyre
REM --- O - location of the home village
REM --- Changes: A - distance to the lyre is calculated
REM --- B - bearing to the lyre is calculated
REM --- F - encounter seed is changed
REM --- I - possible potion reward
REM --- X - parameter for finding lyre
REM --- Z - random number seed
430 PRINT "You have slain the enemy!"
LET Z=F
GOSUB 990
LET F=Z
REM --- Do grateful peasants give directions?
IF L=O THEN GOTO 431
LET X=L
GOSUB 600
IF A<=8 THEN GOTO 431
IF Z-Z/20*20<H THEN GOTO 431
GOSUB 700
GOSUB 720
RETURN
REM Is there a treasure?
431 IF I<>0 THEN RETURN
GOSUB 990
IF Z-Z/8*8>=4 THEN RETURN
LET I=Z-Z/8*8+1
PRINT "With the enemy dead, you notice"
LET X=I
GOSUB 710
RETURN
Notice the change to the F seed discussed earlier. The second part of the routine decides whether local peasantry, grateful for your policing efforts, give you a clue to the whereabouts of the lyre. The more damage you've taken, the more grateful they are.
The final part of the routine decides whether to give you a potion reward, assuming you're not already carrying one (I, for potion in Inventory). The subroutine at 710 just displays the name of the potion. This is another area where I could have varied the gameplay for different biomes. If potions of far-seeing were more common in the mountains, it would give the player a reason to seek out the mountains, for instance.
The subroutine for player death is trivial:
REM --- The player is dead!
REM --- Outputs: Q - quit flag
440 PRINT "The enemy has slain you!"
LET Q=2
RETURN
The other types of encounter are quite simple, so if you want to see them just look at subroutines 220-250 the full source code. In tomorrow's post I'll discuss how the players' actions are dealt with.
Comments