UFO Attack!

Copyright © 2019 by Víctor Parada

UFO Attack!

This is a little game for the 2019 NOMAM's BASIC 10-liners Contest. This program fits in the "stock" PUR-80 category, and it was written using Atari BASIC for the 8-bits ATARI XL/XE. Development started on 2019-03-01, and it took 2+5 days. The final version's date is 2019-03-16.

UPDATE: It obtained the 14th place of 35 entries in the category.


Description

Use the shields to protect the earth from the attack of an aggressive flying saucer.


Instructions

UFOATAK step1 An Unidentified Flying Object is approaching and releasing bombs.
UFOATAK step2 Use a paddle controller to move the shields in order to block the bombs.
UFOATAK step3 If a bomb is missed during a wave, one of the shields is destroyed.
UFOATAK step4 A new shield is generated when a wave is cleared, but you can have a maximum of 3 shields at the same time.
UFOATAK step5 The game is over when the last shield is destroyed. You will see the number of completed waves and the number of destroyed boms. Press the trigger to defend the earth from another attack.

Development of the game

I was thinking about a simple paddle game that could fit in the PUR-80 category, because I like paddles and I want to put a game in the podium of this category, and Activision's Kaboom! came into my mind. The challenge was to write the program in plain Atari BASIC (stock 800XL). I thought that 800 chars were enough for a simplified version of the game, but I was worried about the speed. Could it be fast enough?

I started writing a prototype just to test the concept. At the beginning, I thought about the use of P/M graphics for the bomber and the buckets because they can be moved to any horizontal position after setup with a single POKE for each of them (one for the bomber and one for all the buckets), and let the bombs be just scrolled down by OS's PRINT routine by inserting lines, but then I had to discard this method because there is no scrolling available in graphics mode 1 or 2 (big colour chars) like in graphics mode 0. As Atari BASIC has no MOVE statement, I decided to use the same string management I did in my game Deep Canyon. While I was setting this up, I realized that the bomber could also be managed with strings almost as fast as a POKE to HPOSx register.

When the falling bombs routine was working, with the bomber moving from side to side randomly and dropping the bombs, I added the buckets also as substrings, and that looked nice, but still without bitmaps (redefined charset). I could then manage the remove of the captured bombs without having to manage P/M collisions detection. The code at that time had 6 lines, but there wasn't sound, score or nice bitmaps. I had to decide between good looking graphics, sound FX and a way of scoring to be put in the remaining 2 lines. A simple calculation said that to add a bitmap for the 4 chars in use would require a bit more than a complete line. But there was another pending setup that would use the remaining space, and no scoring or waves yet!!! So I decided to discard the bitmaps and to replace the assigned chars with some standard ASCII chars to give tho look&feel of Kaboom!, and finally to add rounds of increasing difficulty and simple round based scoring. The result? A very hard game to play with a paddle (mouse) in the Altirra emulator, even when it was noticeable slow compared to the original Kaboom! game, without the posibility to increase speed in every new level. I changed the code to support a joystick instead of a paddle expecting for a better control of the game, but the result was very similar. I decided to drop this prototype for the PUR-80 category, and to start looking for another game or idea for the category.

UFOATAK prototype 1

Initial proof of concept

UFOATAK prototype 2

Using standard chars instead of bitmaps

A week later, Kevin Savetz submitted another port of Kaboom! to the contest called "Bomber". His game was written in TurboBasic XL and it was impressively fast, much more than mine. He also used a paddle controller, and then I realized that he used a single bucket (pad) that was very wide, and I guess that it was to make the game playable. This made me try a wider bucket in my version and I resumed the development of it.

UFOATAK bomber

Kevin Savetz's Bomber

With a couple of modifications, I could play my version with a wider bucket and reach level 4 or 5. Wow! But I was still unconfortable with the ASCII graphic, so I tried many combination of letters and symbols to represent both the head and the body of the bomber, until I decided to add additional symbols to represent the arms surrounding the body. The result: it looked like a spaceship or flying saucer from the 50's or the 60's!!! That gave me the idea to turn this game into a new one: the bomber turned into a UFO, the buckets into shields and bombs into... into... into another kind of bombs. Also, I reversed the order in wich the buckets were removed: instead of remove buckets from bottom to top, the shields would be removed from top to bottom. At last, I included a way to detect collisions and play a sound at that moment.

UFOATAK prototype 3

Wider buckets and bomber with arms

I did lots of code simplification and earned a line and a half of free space, so I decided to try the code to change the charset, but it could only provide 4 chars and some of them should be used many times, having to define some patterns. But, what if instead of a spaceship I draw the bomber as it was originally designed? After merging both branches of the development, the result was a playable game, but still difficult to play with a mouse in the emulator. I unpacked my real 800XL and connected it to the PC via SIO2PC-USB and booted it with the same ATR I was using in the emulator. Yee-haw! It was really enjoyable to play it using a real paddle controller.

UFOATAK prototype 4

Using bitmaps for Mini Kaboom

It was easy to add the shield recovery at the end of a wave and to count the number of bombs destroyed to be displayed when the game ends, because both required only few extra bytes, but forced me to minimize the message with the score at the end of the game.

But since I was happy with my derivative idea of an UFO attack, I included the new changes of the Kaboom branch into the UFO branch, and tried some different designs in the modified charset to get nice patterns. As the final one looked nice in the LCD TV screen of my 800XL, I decided to fork the joystick branch again and try it with all the code changes. It turned out to be too easy with a real joystick, so I decided to decrease the width of the force shields again, like in the dropped prototype.

UFOATAK prototype 5

Trying some different bitmaps

UFOATAK prototype 6

Joystick version with narrower shields

Few hours AFTER I sent this game to the contest, another simple optimization came into my mind, so I emailed Gunnar to wait for a moment and to not publish it yet in the entries list. The optimization gave me about one complete line, so I could add more bitmaps instead of the pattern used for the UFO. Some hours later, I had a new version with new graphics and better sound effects. Also, I could accomodate the lines in a way that all 3 versions of the game look the same in the ATASCII listing.

UFOATAK prototype 7

New bitmaps with 6 chars

I also found a bug in the joystick version. I had changed the STICK(0) read and manipulation for STRIG(0) and STRIG(1) in order to be able to split the positioning formula and acommodate it in two lines, because those functions read the same pins from the horizontal movement of the joystick. To save coding space and speed up a bit, I used their complement values, so the formula always added one position to either side when the joystick is released, and the net result was to stay, but when the joystick is moved to one side, what was really happening is that it was signaling that the other side was released. The problem was that Atari BASIC was too slow that sometimes the delay between the read of both triggers was enough to make the program believe that the player wanted to move the shields to the other side.

An interesting fact in this development is that IF-THEN, IF-GOTO, ON-GOTO, ON-GOSUB, GOTO or GOSUB statements where not used. All conditions were included in expressions, and loops were implemented using FOR-NEXT statements, most of them using the 0 to 1 range, but resetting the index variable to 0 just before performing the NEXT statement for an infinite loop, or allowing it to be 1 to exit as in a REPEAT-UNTIL loop.


Download and try

Get the UFOATAK.ATR file and set it as drive 1 in a real Atari with paddle controllers in port 1. Turn on the computer with BASIC enabled (without pressing OPTION key) and the game should start after loading.

Emulator Advice: a mouse does not replace the experience of a real paddle controller, and the game turns very hard. Play it at your own risk!!!

Bonus: the same disk contains a joystick version of UFO Attack! ("UFOATAKJ.BAS") and my Mini Kaboom game ("KABOOM.BAS").

TurboBasic XL hack! To play this game using TurboBasic XL, you must change memory adresses in a pair of POKE at line 3:
- 48485 instead of 40293
- 48484 instead of 40292
The game will be run faster, but would you be able to finish a couple of waves at this speed?


The code

The abbreviated BASIC code of UFO Attack! is the following:

The full and expanded BASIC listing is:

l=440
dim a$(20),b$(60),f$(32276-adr(b$)),z$(l),
  c$(248),s$(40),p$(l),q$(l),t$(l)
Reserves space for strings:
- A$: small buffer used to compare substrings to check for collisions.
- B$: buffer with the UFO image, to be copied into S$ with a given offset.
- F$: just a filler to force C$ to start at the beginning of memory page 128 ($80) plus 8 bytes, and S$ to start at page 129 ($81).
- Z$: string full of zeroes, used to quickly initialize other strings. Last 8 bytes are also used as custom charset for internal cone 0 (space).
- C$: Custom charset, contains internal codes 1 to 6. Remaining bytes are filler to complete a memory page.
- S$: ANTIC memory the first 2 rows of the screen, where the UFO moves from side to side.
- P$: ANTIC memory for the 22 remaining lines of the playfield.
- Q$: temporary buffer to perform the scrolling down of the bombs.
- T$: temporary buffer with a copy of Q$ to add the shields before copying it to the screen, all at once.
L is just a constant that allows the DIM statement fit in only 80 chars by saving 2 bytes each time it is used here.
graphics 17
Sets graphics mode 1 without text box, giving a playfield of 24 rows of 20 chars in ANTIC 6 mode of text in 4 colors,but only 19 columns are used for the playfield.
d=1
Sets the initial moving direction.
z$="{binary char}"
z$(l)=z$
z$(2)=z$
Initializes the initializer string. All strings stores bytes in internal code as they'll be read directly by ANTIC to be displayed.
a$=z$
Initializes the collisions checker string.
b$=z$
b$(20,20)="{binary char}"
b$(39,41)="{binary string}"
Initializes de UFO buffer to be displayed, in internal code.
for g=0 to 1
MAIN LOOP
  f=1
  r=0
  m=0
  x=9
  y=8
  u=3
Initializes the counters and variables:
- F: flag to signal if a bomb might be released.
- R: wave number.
- M: number of catched bombs.
- X: horizontal position of the UFO, range 1 to 18.
- Y: horizontal position of the shields (initialization required for joystick version), range 16 to 0 for paddle version, 17 to 0 for joystick version.
- U: current number of shields, range 0 to 3.
  for h=0 to 1
GAME LOOP
    s$=z$
    p$=z$
    q$=z$
Initializes the buffers for the wave.
    poke 77,0
Reset the ATRACT counter to disable attract mode.
    poke 756,128
Changes the charset pointer to the custom bitmaps in C$.
    poke 40293,129
    poke 40292,0
Changes the memory address in the display list to make ANTIC read data from S$ and P$ string variables.
    for i=r*4+34 to 0 step -1
WAVE LOOP
The number of itariations of this loop depends on the current wave number and it is counted backwards. Each new wave is 2 bombs longer than the previous.
      s$=b$(21-x)
Displays the UFO in its current position.
      h=(x=2)+(x=18)+(rnd(0)<0.1)
Calculates if the direction of the UFO must change to the other side. It happens when it arrived to any of the borders or just randomly.
      d=d*(h=0)-d*(h>0)
Changes the moving direction if it was signaled.
      x=x+d
Changes the UFO next horizontal position, moving it to the current direction.
      t$=a$
      t$(21)=q$
Performs a scroll down of the playfield buffer in a temporary variable, by concatenating an empty line with the current playfield, which its bottom is automatically discarded.
      t$(x,x)=chr$((i>21)*f)
Puts a bomb in the top of the buffer if it was flagged to do.
      q$=t$
Saves the new playfield in its buffer.
      y=int(paddle(0)/13.5)
Obtains the current horizontal position of the shields, in a range from 0 to 16. As the paddle gives values from 0 to 228, it is required to apply a normalization function.
      for v=1 to u
Loop to put the shields on the buffer.
        w=477-60*v-y
Calculates the coordinate of a shield
        c=q$(w,w+2)<>"{binary string}"
Checks if there was a bomb in that place.
        sound 0,20+3*x,8,c*8
Plays a sound if there was a bomb.
        m=m+c
Increase the bombs counter if there was a bomb.
        q$(w,w+2)=a$
        t$(w,w+2)="{binary string}"
Cleans the position in the bombs-buffer of the playfield and puts a shield in the screen-buffer of the playfield.
      next v
      p$=t$
Displays the playfield with bombs and shields.
      k=q$(421)=a$
Checks if the botom of the playfield is empty or if it has a bomb.
      f=1-f
Toggles the flag for adding a bomb in the next scroll down.
      i=i*k
    next i
Before going to the next iteration of the wave, checks if a bomb was missed, finishing the loop.
    for i=0 to 15
      sound 0,180-i*k*9,8+2*k,15-i
    next i
Makes an "end of wave" sound or an explosion if a bomb was missed.
    u=u-(k=0)+k*(u<3)
Decreases the number of shields if a bomb was missed, or increases it if a round was completed, with a maximum of 3 shields.
    r=r+k
Increases the number of the wave if it was completed.
    h=u=0
  next h
Go to the same/next wave only if there are shields available.
  graphics 17
  position 4,9
  ?#6;"{binary}";r;"  {binary}";m
Restores the graphics mode 1 (without textbox) to display the final score: number of waves completed and number of destroyed bombs.
  for i=0 to 1
    i=1-ptrig(0)
  next i
Waits for the trigger.
  g=0
next g
Play again!

Details of the bonus games

The abbreviated BASIC code for the game variations are the following:

UFO Attack! (Joystick Version)

Joystick version of UFO Attack!

Mini Kaboom

Mini Kaboom

The code is almost the same than the one listed above, changing only data lengths or formulas in string manipulation and/or values. For the joystick version, a variable should be initialized to start in the middle of the screen and store the current position, and it was also needed to check to stay within screen limits. For Mini Kaboom, the extra bitmaps were used to improve the buckets.


Return to my 10-liners page.

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