This game was written for ASCII Basic Game 10Liner competition 2021.

It's inspired by classic quiz games I remember from some newspapers and also just from several matchboxes.


Aim of the game

Try to solve as many equations as possible, and as quickly as possible!

Find the right equation by moving one match from one place to another only.

Signs of the equation cannot be changed, you can modify numbers only.

You have to enter the first digit, followed by the second one and the result of the addition.

When the correct answer is provided, you earn a point and progress to the next equation.

Otherwise game ends. Then, you will see the number of points scored and how long have you played in seconds. The highest score is the best one only if scored in the shortest time, this is what all champions aim for!


Notes

When the program runs via emulation with autorun, randomisation doesn't work properly. On each run, all numbers are returned in the same sequence without the user's interaction (explanation here).

In order to avoid this behaviour, break the execution of the program on run with ESC key, and type RUN followed by ENTER to start the game again. From now on, the sequence will be randomised.


Coding challenges

What makes this challenge harder, was not only that a program has to fit in ten lines but also in the 72 characters per line limit. Because of that, I played with different ideas and in the end, I created four versions including a different approach of locating matches on the screen, numbers randomisation, and answer validation. This involved a lot of commands swapping to squeeze them in a single line and finding some patterns after writing a portion of code to make things clever. Or, just shorter, as I still think there is a way to make this code more clever! There must be, right? It was some sort of a question about the infinity of possible solutions against the finite amount of lines available.

The simplest trick I used was to spread variable initialization by using READ and DATA. Iteratively I needed to move things to different lines and see if it fits. Lots of swapping, and saving of the character space like the one with the most common numbers occurring in the game. "10" takes two places, but when assigned to a "Z" variable, it takes one!

To save some character space I also defined a function for randomisation which saved just a few characters, but a few I needed.

Another idea to save some characters space was to define the graphical representation of all matches not within DATA but with printing values as PETSCII characters on the screen.

I used the same colour as the background to print them, so they are not visible but you can find them on the very top of the screen. So, instead of using an array that needed to be assigned from DATA values, PEEK was used to read data from the screen.

As the space available is really small, code is not able to replace one match ahead before drawing all matches on the screen. It might happen then, that during the rendering of the equation, a match taken from one place cannot be moved to another. In such situations, I added a fallback to re-shuffle an equation which will cause also a redraw of the screen. Not a big deal, but I really had no free space to write some sort of a dry-run or provide some fixed possibilities.

One of the earlier versions had a naive approach of accepting an answer as a correct one only when the first and the second digit were exactly the same as the numbers randomised by the program. What could happen though is that when the program randomises that 2 + 3 = 5 and the player provides 3 + 2 = 5, it would be treated as an incorrect answer?! Everyone knows that addition is commutative, meaning that order does not matter. So the program needed to behave the same way. But there was no free space left. 10 lines of code taken already!

Moving a match with some pointer rather than providing values from the keyboard would be a perfect solution. The program would only need to check then if the shapes of all matches are referring to numbers, but again, there was no space left! Using INPUTs instead is just the shortest.

It seemed that the project cannot be finished, but I knew there must be a way. And I found one by having a eureka moment during some random walk. What I realized was that to solve this problem I have to think about the BALANCE. When one match goes somewhere else, the balance is still there so the program has to validate the player's input to see if the amount of matches is the same and that the equation makes sense. Of course, under some circumstances, there is room for some other answers, but it's rare. This way I saved a lot of space by re-using the same code which already renders matches on the screen to add another dimension to it: to not render but count a number of matches provided from the player's equation. This solution saved the project!

In the end, I learned that when autostarting the game you'll get the exact same seed every time the game runs. As the result, all equations were not random at all but followed the same sequence each time the game ran! It's caused by no user interaction. I managed to fix it by calling RND(-TI) but in the case the game is executed with autorun via emulation, this behaviour can be fixed by breaking the execution and running the program again.


Why Commodore 64?

Commodore 64 was my first computer. My adventure with this machine started in the early 90s. A tape deck, a 15" TV screen, and the unlimited world of imagination! Those were times! Even though I moved to Amiga, after several years I wanted to write something for Commodore 64 instead! I did some programming in BASIC around 2002 but then I realized I want to do more, so I learned assembly. The journey continues with some advanced assembly projects, but still, writing something in BASIC, especially on the real thing is just an exciting experience!


Line by line explanation

  • Line #0:

    0rEs,z,s$,m$,v:dEfnr(x)=int(rN(1)*x):pOv,5:pOv+1,6:x=rN(-ti):gO5:dA60,10

    Length: 72

    This line is executed only once. It starts from assigning values used for several calculations and screen displaying, defining a function for randomisation used for retrieving two digits for equation and also used for removing and adding a match stick. Before jumping to line 5, a trick to shuffle a randomisation seed is performed.
  • Line #1:

    1fori=0to6:t=fnr(8):u=pE(1024+c)aN2^i:y=-(u>0):w=-(l=0aNy=1aNt>4):m=m+y

    Length: 71

    A procedure to display a number from matches. Used also to count matches of a number (kept in variable M). Variable T contains the result from the randomisation and it's one of a component used for determining if a match should be added or removed from a number. Variable W contains the flag if a match should be removed from a number.
  • Line #2:

    2v=-(l=1aNy=0aNt>4):l=l-(w+v>0):on-(l<3aN(v=1or(y=1aNw=0)))goS3:next:reT

    Length: 72

    Variable V contains the flag if a match should be added to a number. Variable L keeps the information if a match was already taken or added, it progresses up. In case a match should be displayed, GOSUB to line 3 is performed.
  • Line #3:

    3pO214,int(i/3)*4+o-int(o/z)*z:dA"{clr}{blu}{CBM-Y}$]{CBM-Z}.{CBM-Q}{CBM-F}%{CBM-B}{CBM-P}","{down}{left}B{down}{left}B{down}{left}BCCC",53280

    Length: 68

    Render a match on the screen starts here.
  • Line #4:

    4pO211,4+o/z-(i=2ori=5)*4:sY58640:?"{red}Q{orng}"mI(m$,1-(i=0ori=3ori=6)*9,9):reT

    Length: 72

    Continuation of a match rendering.
  • Line #5:

    5?s$:l=0:m=0:o=4:a=fnr(9):b=fnr(9):c=a:goS1:o=68:i=0:goS3:i=1:o=86:goS3

    Length: 71

    Clear a screen and randomisation of both digits of the equation. Display the first digit followed by a plus sign.
  • Line #6:

    6o=114:c=b:goS1:o=177:i=0:goS3:o=179:goS3:d=a+b:c=d/z:o=224:on-(d>9)goS1

    Length: 72

    Display the second digit followed by equal sign, then display tens of the second digit (if any).
  • Line #7:

    7o=o-s*(d>9):c=d+(d>9)*z:goS1:on-(l<2)gO5:l=3:x=ti:n=m:m=0:input"{down}{down}{wht}a";j

    Length: 72

    Display the rest of the result. Time is started to be measured from here on. Input for the first digit.
  • Line #8:

    8input"b";k:input"=";r:f=f+(ti-x)/s:c=j:goS1:c=k:goS1:c=r/z:e=r>9:g=g+1

    Length: 71

    Input for the second digit and the result. All GOSUB 1 jumps are used to count the number of matches from the answer provided by a player. Time taken to answer is added to the overall time kept in variable F. Points progress in variable G.
  • Line #9:

    9on-(e)goS1:c=r+(e)*z:goS1:on-(j+k=raNn=m)gO5:?a"+"b"="d;g-1"pts in"f"s"

    Length: 72

    In case a match was not replaced, a fallback is used to re-shuffle the equation. In case the answer is correct, another equation will be shuffled (GOTO 5). Otherwise, it's a game over. Display points scored and time taken. The program ends execution here as there are no following lines below.



From author

Have good fun with other games submitted to the ASCII Basic Game 10Liner competition!

Thanks to https://lvllvl.com/c64/ for great JS emulator embedding!

Check out www.commocore.com for more games and open source projects!

Bartosz Żołyński

Download

Download NowName your own price

Click download now to get access to the following files:

mathsticks10.prg 666 bytes
mathsticks-10-petcat-with-abbreviations.txt 830 bytes
mathsticks-10-petcat.txt 950 bytes

Leave a comment

Log in with itch.io to leave a comment.