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