Repeat after Simona

Copyright © 2020 by Víctor Parada

Repeat After Simona

This is a little game for the 2020 NOMAM's BASIC 10-liners Contest. This program fits in the EXTREM-256 category, and it was written using FastBasic 4.3 for the 8-bits ATARI XL/XE. Development started on 2019-07-19, and it took 1+6 days. The final version's date is 2020-03-06.

UPDATE: It obtained the 1st place of 25 entries in the category.


Description

Your personal trainer Simona teachs you a series of exercises, and you must memorize and repeat them.


Instructions

SIMONAR start Simona is your personal trainer in pink, and she'll invite you to do some exersizes.
SIMONAR levels There are 3 different levels:
EASY: There are only 4 different basic movements to remember, one for each joystick direction (up, down, left and right).
REGULAR: There are 4 extra movements in addition to the 4 basic ones, but you only have to move the joystick in the same 4 directions, and the extra ones will be automatically selected for the series.
HARD: You have to press the trigger to select the extra movements along with the joystick, giving real 8 different movements to remember.
SIMONAR series Each time you finish a series, a new one will start.
SIMONAR length The first series is a short one, and the next ones will be longer.
SIMONAR fail The game is over when you fail a single series. No chances to try the same series again!
SIMONAR win If you complete all 10 series, you win the game.

Development of the game

Thinking about a game with a simple animation, it came to me an idea of an animated Simon-like game: instead of colors and sounds, the player might remember positions, and the most practical way to do that should be gymastics or aerobics. It took me many days to design the game in my mind, performing some calculations about the RAM requirements and which should be a good graphic resolution. I also thought about the name of the game: "Simona's Fitness Club", and obviously Simona would be the character for the game. But I had to start with something and that could by some drawings, so I used Paint program in zoom mode and started to put pixels to draw a girl in sport clothes from the 80's. After some minutes, I had a nice toon of her that it was detailed enough, but not so big for a tenliner. Then, I drawed some other positions and also the transitions from the resting one. The next day I completed full sequences for 8 movements and the corresponding transitions. I decided to have 2 different movements for each side in order to introduce difficulty to the game.

SIMONA design 1

Initial design of the character

SIMONA design 2

The whole series

I had to transfer this design to the Atari, but instead of convert the whole bitmap to be used in some graphics mode of the Atari, I decided to send it already sliced and ready to use from the BASIC program, and I selected FastBasic for this project. I picked every different image and put them in a row. Each image has a height of 18 pixels and a width of 11 pixels. As any 4 colour graphics mode uses a byte every 4 pixels, I'd need 3 bytes per line, and a total of 54 bytes per image. The grand total would be 918 bytes for the whole 17 images, and that is 40% of the available coding space in the EXTREM-256 category, or 75% in PUR-120. I was sure I'd need to compress the images, so I deliberately designed the images with portions of it in a static position, in order to reuse the bytes, and those were the legs. It won't make any difference in the amount of storage if a graphics mode or a text mode (in ANTIC 5) would be used. A redefined charset would require 9 chars per image: 3 bytes height (3x8=24 lines) and 3 chars width (3x4=12 pixels), and I didn't try to find how to split the images to get the common characters from different images. To simplfy, I just bet for a graphics mode and defined only 6 tiles per image, and the height of each of them was 9 pixels. I wrote a script that read the picture, splitted every image into tiles, found the duplicated ones, and wrote the bitmap of the selected tiles and an index to the required tiles for every image. The result was only 62 tiles instead of 159, with a total of 558 bytes, less than 22% of the coding space in EXTREM-256 category. The index used 17x6=102 aditional bytes, and the unpack routine used about 120 bytes more, but it did it directly into the precached buffers. A simple loop modifying the memory pointer of a GRAPHICS 5 screen pointing to the buffers showed me the animation for whole exercises sequence, and I liked it.

SIMONA design 3

All 17 images of Simona

SIMONA prototype

Animation in the Atari

In the bottom of the screen was displayed the next cache buffer, and that gave me the idea of two ladies in the playfield at the same time: one for Simona and one for the player, but they shouldn't be the same image, at least the color of the clothes should be different, and I already was using all 3 colors and the background. I could had a 4th color if I had used ANTIC text mode 4, and used inverse video in the chars of one of the ladies, but the images would be much smaller. By those days, I was talking with DMSC about adding display list interrupts (DLI) to his FastBasic language. With a single DLI it would be possible to have 2 completely different color sets, one for each character. But the development of DLI in FastBasic took too much time trying to find the best way to add such powerful feature to the language that it could manage many interruptions in the same screen and be simple to use at the same time, and the developement of this game got frozen for many months... During this stand-by period, I thought about a variation of the game: instead of a Simon-like game, make a reflex game, trying to react as fast as possible. When the call for the 2020 contest arrived, I had to decide which of the variations to try first, and the reflex version won over the memory one, and what happened next was documented in "Follow Simona" documentation.

After I finished the reflex version of the game, I resumed the original idea of a Simon-like memory game. At this time, I've already had a game engine, selected the colors for Simona, included a messages routine, and defined 3 difficulty levels. So I started changing the colors for the player and removing most of the game loop even when I tried to reuse most of the variables for the equivalent function. Without too much effort, I could code the backbone of the repeating game.

SIMONAR prototype 1

Simona performing Simon-like series.

The next day I included the routine to repeat what Simona played in a series. Having two ladies in the screen, allowed me to play the repetition with both of them, and Simona showing the fail after a miss. Besides the rythm sound, I included the same 4 tones from "Uncle Simon", but it was too much sound, so I removed the rythm. Changing Simona's messages for the game, I included different gameover messages based on the reached level.

In this version of the game, all 10 lines and a bit more were used, and I had to change some things to reacomodate the code in only 10 lines. After I finished the optimizations, I merged them into the reflex version of the game, having two equivalent final versions.... still without docs!!!

SIMONAR prototype 2

Final version of "Repeat after Simona".

SIMONAF prototype 5

Final version of "Follow Simona".


Download and try

Get the SIMONAR.ATR file and set it as drive 1 in a real Atari (or emulator). Turn the computer on and the game should start after the loading completes. A joystick in port 1 is required.


The code

The abbreviated BASIC code is the following:

The full and expanded BASIC listing is:

graphics 0
poke 710,0
poke 752,1
poke 82,0
Set up screen

GR 5: SCR=$BBA0
GR 0: SCR=$BC40
?
? "Repeat after Simona"
?
? "Setting up..."
j=adr("{binary data}")+1
Joystick movements

Prepare Simona's movements
mset $8000,$3800,0
Clean frames buffer
a=adr("{binary data}")+1
Tiles needed for each frame (17 frames of 3x2 tiles)
move adr("{binary data}")+1,$8000,225
Bitmap data for every tile (4x9)
move adr("{binary data}")+1,$80E1,225
move adr("{binary data}")+1,$81C2,108
for k=0 to 16
  s=$840A+k*512
  for b=0 to 5
    x=$8000+9*peek(a+b+k*6)
    for c=0 to 8
      poke s+(b/2)+180*(b&1)+c*20,peek(x+c)
    next c
  next b
next k
Unpack frames
? "{binary data}"
Clean the text screen
move adr("{binary data}")+1,708,4
Set up colors (hair,skin,clothing,text)
dli set u = $CA into $D019, $96 into $D016, $16 into $D017, $4A into $D018
dli u
move adr("{binary data}")+1,$BB6A,54
dpoke 560,$BB6A
Set up the display list
pause 50
Wait for a second
q=$BB6E
Frame vector for Player
p=$BB86
Frame vector for Simona
a=adr("{binary data}")+1
Frames for sequences, 4 frames each
d=adr("{binary data}")
List of messages
n=1
exec m
Display welcome message
do
Main loop
  n=35
  exec m
Display difficulty selection message
  repeat
    n=56
    exec m
  until x<7
Display get ready message
  ? "{binary data}"
  position 20,0
  ? "{binary data}"
Reset on-screen scoreboard
  z=4+4*(x<>5)
Number of movements, 8 for normal and hard, 4 for easy
  y=x=3
Trigger is needed in hard
  n=95
  exec m
Display count down...
  data o() byte = 121,85,60,173,121,85,60,173
Tones for steps
  dim h(15) byte, w(15) byte
Sequence of a series
  r=1
Round number
  g=600
Delay for speed control
  s=0
Current player movement
  repeat
Game loop
    position 27,0
    ? r
Display series number
    e=0
    repeat
Loop for the series
      position 37,0
      ? e+1;" "
Display current steps number in the series
      b=rand(z)
      h(e)=b*4+4
      w(e)=o(b)
Select next movement
      f=0
      repeat
Show the excercise series
        for i=0 to 3
Iterate through frames of the step
          sound 0,w(f),10,9-i*2
Play the sound for that step
          k=$8400+peek(a+h(f)+i)*512+4
          pause 0
          dpoke p,k
Simona's next step
          for c=0 to g
          next c
Delay (each time a shorter one)
        next i
        sound
        pause 2
Stop the tones
        inc f
Next step
      until f>e
Last step of the series?
      f=0
      repeat
Repeating the excercise series
        repeat
          s=peek(j+stick(0))*4
        until s
        if y
Wait for a joystick movement
          s=s+16*(strig(0)=0)
        else
2nd type of movement is get when the trigger was pressed
          s=s+16*(h(f)>16)
        endif
Automatic selection of 2nd type of movement
        t=s<>h(f)
Is the same movement than the series?
        for i=0 to 3
Iterate through frames of the step
          if t and i=2
Plays a sound at the second frame
            sound 3,200,12,8
            pause 80
            sound 3
          else
Plays a buzzer
            sound 0,o((s-4)/4),10,9-i*2
          endif
Play the sound for that step
          k=$8400+peek(a+h(f)+i)*512+4
Simona's next step
          l=$8400+peek(a+s+i)*512
Player's next step
          pause 0
          dpoke q,l
          dpoke p,k
Refresh movements
          c=0
          repeat
            inc c
Delay between steps
          until c>g or (c>30 and stick(0)=15)
Quits delay if the joystick was released
        next i
Back to the next step
        sound
        pause 2
Stop the tones
        inc f
      until f>e or t
Last step?
      pause 30
      poke 77,0
Wait for a moment and disable attract mode if it was active
      inc e
    until e>r+3 or t
End of steps for the round?
    if t=0
      for c = 600 to 0 step -1
        sound 0,c/3,10,8
      next c
      sound
    endif
Plays a sound when the series was finished successfully
    pause 50
    g=g-25
    inc r
Decrease delay time for the next series
  until r>10 or t
End of series? Failed?
  sound
Stop sounds
  n=125+55*(r<11)+24*(r<6)
  exec m
Display game over message
137=Excelent
192=Good
215=Bad
loop
Back to game loop
proc m
Procedure to display a group of messages
  c=d+n
  x=7
Find text of the message
  while peek(c) and x=7
Repeat for every word(s) of the list, or until a key is pressed
    v=peek(c)
    position 7-v/2,0
    pause 0
    ? $(c)
Print next word(s) centered in text area
    b=0
    repeat
      x=peek(53279)
      inc b
      pause 1
    until b>25 or x<7
Wait for a moment or a key press
    mset $BC40,20,0
    pause 8
Clean message area
    c=c+v+1
  wend
endproc
Move to next line

Return to my 10-liners page.

© 2020 by Víctor Parada - 2020-03-15 (updated: 2020-08-15)