Eamon Porting – Some really ugly BASIC

In my ongoing adventures in porting Eamon Adventures I stumbled on some truely ugly BASIC code:

110 HD = FN A(8):AG = FN A(8):CH = FN A(8)
120 PRINT " HARDINESS--";HD: PRINT " AGILITY --";AG: PRINT " CHARISMA --";CH;"'": PRINT 
125 IF HD + AG + CH < 39 THEN GOSUB 600
130 PRINT "(HIT 'R' TO READ INSTRUCTIONS, 'T' TO GIVE THEM BACK)";

...Read instructions and continue character creation code here...

600 REM /// SUICIDE ROUTINE 
610 PRINT : PRINT "YOUR CHARACTER IS SUCH A POOR EXCUSE": PRINT : PRINT "FOR AN ADVENTURER THAT WE WILL ALLOW": PRINT : PRINT "YOU TO   COMMIT SUICIDE. ENTER 'Y' TO": PRINT : PRINT "COMMIT SUICIDE, ELSE 'N'";
620 GET A$: IF A$ < > "Y" AND A$ < > "N" THEN 620
630 PRINT : PRINT : IF A$ = "N" THEN RETURN 
640 PRINT "WE RESSURRECT YOU AGAIN AND YOUR PRIME": PRINT : PRINT "ATTRIBUTES ARE --": PRINT : POP : GOTO 110

This looks like a relatively simple subroutine until you realize that 640 is the last line in the program. Also what is this strange “POP” command.

Well POP removes the stored stack frame from the previous GOSUB. It is like RETURN except you don’t jump back to where you called from. It is madness! A subroutine with two different exit paths, not two points in the subroutine where you return to your caller but instead two completely different places you return to. No wonder people had no idea what complex BASIC programs were doing.

When I converted this code to C# the construct was much cleaner:

bool suicide = false;
do
{
    newChar.hardiness = RollDice(3, 8);
    newChar.agility = RollDice(3, 8);
    newChar.charisma = RollDice(3, 8);

    Console.WriteLine($"\r\n HARDINESS--{newChar.hardiness} AGILITY--{newChar.agility} CHARISMA--{newChar.charisma}");

    if (newChar.hardiness + newChar.agility + newChar.charisma < 39)
    {
        Console.WriteLine("\r\nYOUR CHARACTER IS SUCH A POOR EXCUSE");
        Console.WriteLine("\r\nFOR AN ADVENTURER THAT WE WILL ALLOW");
        Console.WriteLine("\r\nYOU TO COMMIT SUICIDE. ENTER \'Y\' TO");
        Console.WriteLine("COMMIT SUICIDE, ELSE \'N\'");

        string answer;
        do
        {
            answer = Input();
        } while (answer.ToLowerInvariant() != "y" && answer.ToLowerInvariant() != "n");

        if (answer.ToLowerInvariant() == "y")
        {
            Console.WriteLine("WE RESSURRECT YOU AGAIN AND YOUR PRIME");
            Console.WriteLine("ATTRIBUTES ARE --");
            suicide = true;
        }
    }
} while (suicide);

Ignore the fact that this new code takes many more lines, cramming lots of commands on the same line in BASIC was required due to memory contraints. What you should notice is that it is very clear that you are going to generate stats at least once and continue to do it until the character chooses not to commit suicide. The BASIC code implements the same looping structure but has the very strange construct of calling a subroutine and then exiting that subroutine to two different points in the code to simulate the do..while looping.