The Art of BASIC 10-Liner Challenges: Cosmic Aq (Mattel Aquarius)

Writing a complete 10-line game using Mattel Aquarius BASIC, in which each line is limited to 72-characters. The total size of the game is 720 bytes.

Last year I attempted something I never had before — what is known as a PUR-80 BASIC 10-Liner programming challenge. The objective is to squeeze as much as you possibly can within 10 lines of code, with no line to exceed 80 characters. A challenge open for any platform but one that is especially inviting for the old 8-bit systems that had limited resources to begin with.

It came at a time when I had become increasingly intrigued by the oft-forgotten Mattel Aquarius computer of 1983. The factory system included a version of Microsoft BASIC but with quite a few severe limitations. It lacks even a simple CLS to clear the screen, instead relying on special character allocations to handle it in the ROM (e.g., ?CHR$(11) = CLS). Even worse, it restricted each line to a maximum of 72 characters, so even the PUR-80 category, which is the most minimalistic and restrictive of the 10-Liner challenges, was beyond its capability.

This means that entering the 10-liner challenge with an Aquarius results in a maximum of 720 BYTES for the entire game, versus other platforms that would grant you 800 BYTES at 80 characters per line. This handicap basically robs Aquarius of a full 80 byte line that others can embellish. Perhaps a more balanced version of this challenge would be to specify the cut-off in bytes (characters) rather than lines. It may not sound like a big difference, but when you are compacting an incredible amount of functionality into single letter variables that can mean a lot in the world of features.

More Severe Weaknesses of Aquarius

Even then, Aquarius suffers weaknesses rarely seen on other 8-bit systems. It has no GPU, no sprites, no customizable graphics at all. Instead the entire system revolves around a fixed 256 character ROM, 8x8 pixels each (and even a few of those slots are duplicates of one another). This includes the standard alphanumeric English ASCII characters, a series of glyph shapes, and bloxels (2x2 and 2x3 patterns) to allow pseudo-graphics by combining various characters together. More precisely, the character set includes:

  • 96 English Character Alphanumeric Set (A-Z, a-z, 0-9, Symbols)
  • 16 Directional Glyphs and Arrows
  • 16 Left-and-Right Facing Humanoid Figures (8 Upper and 8 Lower Halves)
  • 8 Airplane, Space and General Shapes
  • 16 Progressively Filled Horizontal/Vertical Gylphs
  • 16 Sphere and Special Effect Glyphs
  • 80 Bloxel, Shading and Piping Glyphs
  • 8 Miscellaneous Glyphs including Empty and Full

The display is fixed to a 40x24 character grid space. Technically there is a 25th row at the top of the screen that can be manually drawn to via POKE, but the top-left character also alters the overall screen border. And although the resolution is technically 320x200, the lack of per-pixel plotting or customizable characters essentially limits "custom drawing" to 80x72 when using the 2x3 bloxels. This leads to another conundrum in that the lack of any GPU-acceleration, sprites or per-pixel modifications means the movement of any game will feel clunky. The game Astrosmash uses large graphics constructed out of bloxels to give an effective feel of smooth movement and speed, but compared to the other versions of Astrosmash including Astroblast on the Atari 2600 it becomes clear of the Aquarius' limitations (and why the system was internally mocked by developers in the 1980s as "the system for the 1970s!")

The available memory was also painfully low by 1983 standards for home computing. It came with 4KB of internal RAM, of which almost all of that was consumed by the screen memory (color and character bytes) and internal allocations for BASIC. This results in a maximum of 1,724 BYTES of free space. Although that doesn't affect a 10-liner challenge that only allows 720 BYTES, it still is astronomically small if you intend to do any serious development. One of the few type-in game books released for it even stressed the limitations and had to cut a lot of corners in its own games to attempt to squeeze everything within the vanilla RAM. There were common 4K and 16K expansion packs, with most third party cassette games requiring the 16K expansion. A rarer 32K pack also existed, but a modern 32K alternative is also available on eBay.

Planning for the Challenge

With all of the limitations understood, I recognized I'd have to set my goals small and then butcher those into even smaller realities to eventually make something that worked within those confines. I've always been a fan of Cosmic Ark as one of the first games I have any memory of playing on the Atari 2600, so thought I could mimic the basic meteor battle scenario for this small type-in exercise. The premise would require:

  • Central space ship graphic
  • Input to shoot a bullet UP, DOWN, LEFT, RIGHT
  • Meteors to approach from any four directions
  • Detection for when the player successfully shoots a meteor (add to score)
  • Detection for when a meteor strikes the ship (delete from lives)
  • Progression in which the projectiles increase in speed
  • Game over functionality when all lives have elapsed
  • Restart functionality to begin a new game

Initially I explored the programming aspects without much concern for the character or line limit. In fact I developed an in-house BASIC editor that assisted in some aspects, including automatic line numbering, labels and other nifty utilities that could then be output to Aquarius-compatible BASIC lines. This is a utility that at some point in time I'd like to finalize and release as another free Aquarius utility alongside the Aquarius Draw utility I made last year.

Eventually I had some simple functionality including pretty cool meteor animations and a compact ship. But I realized early on that most of this polish would have to be shaved away to fit within the limits. This led to a lot more creative exploration of how to get the most out of each byte, including a lot of different tricks. As one example, I was able to creatively cycle between two different characters of the ROM to simulate animation of the meteors, the tattered ship construction and the starfield, while simultaneously cycling the ship colors all within a few bytes of code. It took a lot of trial and error to eventually come to what I felt was an adequate representation, even if it is severely reduced from my original prototype.

The final 10-line gameplay screenshot. The ship, meteors and overall layout is quite a far-cry from my original vision, but still functional.

BASIC CODE DISASSEMBLY: The Code

To fit everything into the 10-line, 72-characters-per-line limit, everything had to be refined as much as possible. This means swapping descriptive variable names for single letters, making use of DATA reads and whatever other shortcuts I could muster within the confines of Aquarius. For example, PRINT is synonymous with ?. Spaces were stripped and as many lines as possible were made to fit per line. The final ten lines are as follows:

BASIC CODE DISASSEMBLY: Overview

Since the end result is a wall of cryptic BASIC, it is worth doing a proper disassembly for the betterment of mankind. Below is a basic summary of what each of the 10 lines achieves. A more precise breakdown will follow.

  • LINE 0: Declares the main variables and array and sets defaults.
  • LINE 1: Initializes display, generates stars & begins draw loop.
  • LINE 2: Reads data into array and draws the on-screen spaceship.
  • LINE 3: Starts main game loop, handles sound, game over & reset.
  • LINE 4: Calculates direction of meteor and sets base properties.
  • LINE 5: Updates lives and sets properties for horizontal meteor.
  • LINE 6: Handles meteor movement display and checks player input.
  • LINE 7: Controls meteor speed and sets flag if player won round.
  • LINE 8: Cleans up visuals for next round and handles round loss.
  • LINE 9: Jumps to start of loop and stores values for game array.

LINE 0: Variable Declarations

  • B: Array that stores 23 integers from DATA (Ship, Controls, Misc.).
  • D: Topmost screen location of the ship visuals (Row 10, Col 19).
  • E: Default screen location of incoming meteor (Row 0, Col 19).
  • T: Delay duration of approaching meteor; gets faster every turn.
  • L: Total number of lives as a character value (53=5 . . . 48=0).
  • M: Storage location of last pressed key for checking keyboard input.
  • N: Screen offset used when calculating meteor direction and display.
  • Q: Matches "B" array length, used for iteration and sound effects.
  • R: Calculated location for the firing edge of ship, defaults to N.
  • S: Base character value for drawing the ship, also used for sounds.
  • A: Character value for an empty tile, 32 and 160 are equivalent.

LINE 1:  Display Initialization

  • Clears the screen, initializes data loop and draws basic HUD and bg.
  • The value Z is assigned an alternating value of 3 or 0 for effects.
  • The random starfield draws "." or "+" (46/43) to screen, based on Z.
  • The far top-left tile 12288 (E-59) creates border from character 46.
  • B: Stores 1024, the offset needed to add COLOR to POKED characters.
  • I: Begins the loop from 0 to 22, used to load DATA, draw ship, etc.

LINE 2: Data Storage and Ship Generation

  • Stores DATA values into array B for ship design, controls and more.
  • The array order is inversed to save a few characters on input check.
  • For the first 13 elements, draws to screen to construct the ship.
  • POKE command uses data values to draw ship from offset D (12747).
  • Z value is used to alternate ship char 243/246 and colors 179/182.
  • The result of the alternating character/color is a "run-down" look.
  • Plays a small tune while the game is initializing, repeats loop.

LINE 3: Start of Game Loop

  • Called at end of each "round" when meteor reaches ship or is shot.
  • It plays a unique sound effect based on whether user survived round.
  • If the lives are 0 (character value 48), an end sequence occurs.
  • At game over, a final death sound is made and the score displayed.
  • The program then waits for user input, on [ENTER] will start over.
  • Pressing [CTRL]+[C] will break out of the program and exit game.

LINE 4: Calculate Direction of Meteor

  • The direction of the next meteor is determined by this unusual line.
  • It generates a value of -2 (RIGHT) -1 (BOTTOM) 1 (TOP) or 2 (LEFT).
  • In this way, the value can be passed to an array for input handling
  • as well as visual updates to the appropriate ship side and so forth.
  • The variables defined and updated on this line are given defaults
  • applicable for BOTTOM (-1) and TOP (1) meteor directions.
  • G: Direction of the next meteor, as described above (-2, -1, 1, 2).
  • U: Calculated vertical movement vector and location of the meteor.
  • H: Calculated horizontal movement vector and location of the meteor.
  • K: Total number of moves the meteor has before reaching the ship. 
  • F: Resets flag that indicates if player loses (2) or wins (1) round.
  • V: Offsets meteor character value to provide animated effect [O o].

LINE 5: HUD Update and Meteor Initialization

  • Updates the total number of lives and space ship icon for HUD.
  • 75% chance of decreasing the meteor delay T by 1 so it progresses in speed.
  • If the user is extraordinary and gets 73+, it will double the step (hyper speed).
  • Checks to see if the meteor direction is LEFT or RIGHT (2, -2).
  • If so, updates the variables to support horizontal movement instead.
  • The position is recalculated so it can accommodates both directions.

LINE 6: Meteor Movement and User Input

  • Creates a loop based on defined meteor direction properties.
  • Draws the meteor to screen based on the current loop index and data.
  • 16|-16 is added to the character base of 95 to animate meteor look.
  • Data cell containing last pressed key is read and compared.
  • If the pressed key matches the meteor direction, player wins round.
  • I: Iterator that traverses the meteor from edge of screen to ship.
  • C: Step value for loop/speed. If alive after 100 turns, is set to 2 (hyperspeed!).
  • W: Stores the last pressed user key to compare input.
  • F: Flag is set to 1 to indicate the user has won the round.
  • O: If user has won, sets value to end of for loop for an early exit.

LINE 7: Time Delay and Round Win 

  • In Aquarius, delays are created using simple loops like CPU cycles.
  • An empty loop is iterated based on duration value to slow meteors.
  • Each successful attack against a meteor reduces the delay 1 cycle.
  • If the user fires in same direction as meteor, it displays gunshot.
  • A point is awarded for a successful hit against the meteor.
  • The win flag gets set to 0 specifically for sound reasons in line 3.

LINE 8: Cleanup and Round Loss 

  • Overwrites last meteor and gunshot locations to clear the graphics.
  • Resets input value so it doesn't match any of the four directions.
  • Sets the color of the ship edge area to red (for visual collisions).
  • If the round has been lost, decrease player lives by one.

LINE 9: Loop End and Data Structure 

Sends the program back to line 3 to begin the next round. Contains 23 different data elements used throughout the program. The data is stored in the array in REVERSE-ORDER for some reductions.

[0-4] : 46,122,0,97,44

  • Stores the character codes that correspond to input.
  • 46 = FIRE RIGHT (-2), 122 = FIRE DOWN (-1)
  • 97 = FIRE UP (1), 44 = FIRE LEFT (2)
  • The middle value 0 is the base point referenced in game.
  • To its index gets added the direction value (-2,-1,1,2).
  • This allows condensed checking if user has shot meteor.
  • The middle value is arbitrary and is not actively used.

[5-9] : 17,133,0,-67,9

  • Stores the values of the ship edges as offsets from N.
  • Used to alter colors/designs on fire or collision.
  • The middle value 0 is the base point referenced in game.
  • To its index gets added the direction value (-2,-1,1,2).
  • The middle value is arbitrary and is not actively used.

[10] : -498

  •  Traverses back to top of screen during ship generation.
  • This is to override the default black cursor at the top.
  • In the game, this tile gets replaced with the lives icon.

 [11-22] : 39,1,1,36,1,1,1,1,1,1,37,0

  • Stores offsets from D-12747 for the ship's construction.
  • The ship is built as data is read & stored as part of it.
  • Could be useful in-game to make parts of ship destruct.
  • Not actively called in-game due to no coding space left!

In the end, this proved to be a much more thoughtful and time-consuming adventure than I had originally anticipated. It required a lot of unorthodox thinking and still had to cut back on many planned ideas. As one example, the data for the ship construction exists in a way that I had anticipated having the ship visibly destruct with each hit, but simply ran out of bytes. At some point I'm not opposed to creating a full-featured version of this game that will more closely reflect my original vision. For fun, I created a flyer and physical cassette media that can be loaded onto the actual device. For more details, downloads and more, it is available on itch.io