Sabotage (Amstrad CPC) by Copper France
About
SABOTAGE
Sabotage is the Amstrad CPC version of the game of the same name released on ZX81 (written by Don Priestley and published by Macronics 1982). In this version you play the saboteur only.
Keyboard arrows are used to move the saboteur and space to put a charge. You need to put 10 charges and destroy a maximum of ammunitions represented with blue cylinders. (Video inverse X in the original version)
You need to avoid the guard because if he is in front of you he shot you instantly and the game will be over.
TECHNICAL PART
The game works on all Amstrad CPC (using only BASIC 1.0) but for CPC 464 there is another version because POKE&B7C3,
There is a difference using this POKE because CPC 464 is using PEN 1 instead of PEN 3 on other machines... That's why I swapped INK 1 & 3 and changed SYMBOLs in the 464 version.
1) Control Characters
The game use a lot of control characters to replace MODE, PAPER, BORDER, INK, SYMBOL in only one PRINT in the first line :
MODE is CHR$(4)+"2" FOR MODE 2
PAPER is CHR$(14)+"0" FOR PAPER 0
BORDER is CHR$(29)+CHR$(64+0)+CHR$(64+0) for BORDER 0,0
INK is CHR$(18)+CHR$(64+v)+CHR$(64+v) for INK v,v
SYMBOL is CHR$(25)+CHR$(i)+CHR$(a)+CHR$(b)+CHR$(c)+CHR$(d)+CHR$(e)+CHR$(f)+CHR$(g)+CHR$(h) for SYMBOL i,a,b,c,d,e,f,g,h
CHR$(8) is also used in the tiles's strings to avoid -1 for all LOCATE 2*
2) CALL &BD1C
The BASIC use MODE 2 but a CALL &BD1C,1 (one parameter (value not important) is needed to have 1 in Z80's A register) is doing a MODE 1 without clearing the screen.
With this trick you can have 4 colors tiles with a simple PRINT of two characters in MODE 2.
Each characters print 4 pixels in 4 colors and are encoding using the MODE 1 video memory scheme :
I used famous tool ConvImgCpc for encoding SYMBOLs converting it's asm file to DATAs.
3) POKE &B7C3,
When you use CALL &BD1C,1 you can't print normal text except if you use POKE &B7C3,1 so PRINT is working in MODE 1 again. I use it to PRINT the final score and the explosion square to speed it up a little.
When I want to have 4 colors tiles again I restore previous state with POKE &B7C3,2 (PRINT is working in MODE 2)
4) Explosion / guard AI
The original game was disassembled for studying explosion and AI algorithm of the guard and finding other useful information.
For example, the guard is starting at the center of the map (if center if not free using first free spot to the right)
The saboteur is starting near a wall (left, right, top or bottom)
Explosion is propagated to all 9-neighbours arround. New ammunitions position are stored in a buffer of 50 positions max to be propagated until buffer is full or empty.
The guard try to reduce difference in x or y randomly except if the saboteur is near. If he is near or can't reduce difference he try a random position arround not used before.
If all position arround were already used he try one used only one time. If all positions arround were used twice all positions already used are cleared (reset)
5) Listing description
Line 1: Graphics initialization in one PRINT / Variables initializations
Line 2: Variables initializations / Magic switch in MODE 1 / RNG initialization
Line 3: Wall arround map initialization and display / Calling ammuntion random add sub routine in 10 / Guard starting position / Saboteur starting position
Line 4: Player (saboteur) moves and putting charge action
Line 5: Guard move (AI)
Line 6: Charge display / Guard shot tests
Line 7: Saboteur and guard display / Animated shot display (vertical or horizontal)
Line 8: Animated charge (or shot) explosion
Line 9: Bomb guard and saboteur hit checks (and end of charge animation) / Scoring / Game Over Final Score Display / Next Round
Line 10 : Ammunitions Random Add / Guard move (Update and display) / DATA for tiles's strings
6) Variables
z$ : CHR$(0)
u(),v() : Guard moves offsets
m : Timer before guard starts to move
n : Number of random ammunitions to add
o : Number of charges remaining
b(,) : Map
q(),r() : Buffer for explosion
m$ : Wall tile
x$ : Ammunition tile
g$ : Guard tile
s$ : Saboteur current tile
s$(,) : Saboteur tiles for each direction
b$ : Charge tile
h$,i$ : Horizontal shot tile (2 frames)
v$,w$ : Vertical shot tile (2 frames)
e$ : Empty tile
h$(),v$(): Horizontal and vertical shot tiles animations (10 frames)
t$ : Top and bottom horizontal wall
g,h : Guard position
s,t : Saboteur position
u,v : Saboteur move offset / Offset between guard and saboteur
w : Random Number used to randomize AI moves horizontaly or verticaly / Shot direction
q,r : Charge position
k : Temp variable also set when saboteur is shoted
p : Used to check used position / used twice position
i,j : Used for loops
w,z : Guard move offset
x : Map content
f : Flag to simulate markers reset
b : Timer before charge explode
c : Saboteur hit by explostion
d : Guard hit by explostion
e : Explosion buffer index
a$ : Explostion tile
a : Score
x,y : Random Position (Line 10)