2048-9L

An 2048 game written in BASIC, using only 9 lines.
Coded by Csabo/LOD in 2020, submitted for BASIC 10 Liners 2020.

Bonus 0.5 points for documentation, here we come! :-)

*About the game*

The game is controlled with cursor keys, which slide the pieces on the board
in the chosen direction. Merge pieces with the same number,
eventually creating pieces with "2048" (or higher numbers) on it.

*Why?*

I looked through the past submitted games in the BASIC 10 Liners
contests, and could not find a 2048 game on any platform (I could be wrong,
I didn't do any very exhaustive search). On a whim, I wanted to see
if it would be possible to code it, and this was the end result.

*Representing the Board*

The board is stored in a 4x4 array called B (for board). Each cell in the
array represents a piece. Zero means the cell is empty. Otherwise,
the number represents the "type" of piece, where the value of that piece
is 2 to the power of the number:
1 = 2^1 = 2
2 = 2^2 = 4
etc.
This way, when two cells are merged, the numbers in the array can be
simply incremented by one. To give an example: let's say the player
is about to merge two "64" pieces, which would be two 6s in the array.
Once the code sees that two 6 values are next to one another, one of them
is removed (replaced by a zero), and the other one is incremented to 7.
2^7 = 128, so a 128 piece is created. Keeping track of score is done
using these numbers, stored in variable S (for score).

*Main loop*

The game is basically a keyboard loop (line 6), which keeps waiting for
keypresses. The INSTR() function - only available in BASIC V3.5 or higher
is fantastic here, since we can get the index of the pressed key by comparing
it to a string constant. Using that index, we can use the ON # GOTO
statement to handle keypresses. We add one to the index - when a "wrong"
key is pressed, the INSTR() function returns zero; so it becomes 1.
In effect pressing a "wrong" key simply returns to the keyboard loop.
The left/right and up/down  movements are actually handled by the same lines.
These lines still need to distinguish between the directions, so
we store the index in the K variable (for keypress). The L variable is
the same value, but for the vertical movement.

*Making moves*

Line 7 handles horizontal moves, line 8 handles vertical ones. These keep
track of whether something moved on the board by using the M variable
(for move). When a move is occurs, M is set to 1. When M is zero, we're done.
To actually make a move, we call the merge/move check subroutine in line 1/2.
This subroutine needs two pairs of coordinates: X,Y and C,U (since C and U
are next to X,Y on the keyboard). This way, regardless of the direction,
all moving/merging is handled the same way. The left/right or up/down
direction is handled with simple arithmetic, the only thing that needs to
change here is the direction of the inner loop.

There's one more thing to keep in mind: it is possible for the player
to make "invalid" moves. For example, assume that the pieces 2-4-2-4
are the only pieces on the board, in the bottom line. Pressing left, right
or even down are "invalid" moves, since nothing can slide. In order to keep
track of this, the game uses the variable V (for valid). At the start of
the keyboard loop, it's set to 0. When a move or merge occurs, it's set to 1.
After each move, V is checked, and the code either returns to line 3 (see below)
or line 6, the keyboard loop, if the move was "invalid".

*Placing pieces*

Line 3 generates a random pair of coordinates, using variables X,Y.
If that cell in the board is non-zero, it keeps going. Otherwise a 2 piece
(represented by 1 in the array) is placed there, and we get into the display.

*Let's draw something!*

The most "verbose" part of the code is the display routine, which is in
lines 3-5. It's a nested loop, which loops through all cells in the array.
Using BASIC V3.5's CHAR function is very useful here for positioning.
We check if the cell is empty or not, non-empty cells are drawn with
PRINT USING, and the "=" directive. This automatically centers the given
string! We have to convert the numbers to a string with the STR$() function,
and then remove the first space with the MID$() function (the space is there
because it's a positive number).

(Note that PRINT USING also automatically removes any extra characters.
While it's not possible to merges two 65536 cells, since there's not
enough room on the board, the game would work with "13107" displayed.
The game could theoretically handle pieces as absurdly high as 2^126,
before running into an overflow error at 2^127.)

Zero pieces are printed using the "orange" color (Plus/4 color code
$48). The background/border color was chosen to match this, is color
code $58, just one shade lighter of the same color.

Finally, score is printed (in black).

*Possible improvements*

There's still a whole extra line free, plus some more characters,
so here are couple things we could add:

- The game does not have "game over" detection, but I think it's not
a must have. Considering it's a BASIC game, it's not a big stretch to 
assume players would see that the board is full and no more legal 
moves remain, and would be expected to press Run/Stop.

- In most versions of 2048, occasionally a 4 piece is created.
This version does not handle this.

- More varied colors for different pieces would be a possibility.