526 lines
12 KiB
Plaintext
526 lines
12 KiB
Plaintext
|
|
{-----------------------------------------------------------------------+
|
|
| |
|
|
| Snake game |
|
|
| |
|
|
+-----------------------------------------------------------------------}
|
|
|
|
gcl0x
|
|
|
|
{
|
|
Maybe:
|
|
XXX Don't allow autoplayer to obtain a hi score
|
|
XXX Use DOKE to plot fat pixels
|
|
XXX More colors, less green
|
|
XXX Smarter border drawing (spiral draw)
|
|
XXX Use same drawing techique for clearing playfield
|
|
XXX Increasing speed
|
|
XXX Increase speed when pressing button
|
|
}
|
|
|
|
{-
|
|
First setup all subroutine definitions and variables, without making
|
|
calls. This way allows use of vLR to hop from page to page during setup,
|
|
with minimal overhead. At the end, run the main loop.
|
|
-}
|
|
|
|
0 HighScore=
|
|
|
|
{ Print a 5x8 character on screen with the built-in font
|
|
Char must be in the 32-127 range (this is not checked) }
|
|
[def {PrintChar}
|
|
{Map ASCII code to offset in font table}
|
|
Char 82- [if<0 50+ i= \font32up
|
|
else i= \font82up] fontData= {Select low or high page}
|
|
i 2<< i+ {Multiply by 5}
|
|
fontData+ fontData= {Add to page address to reach bitmap data for Char}
|
|
|
|
{Draw 5 vertical slices: 5 using font data}
|
|
BgColor \sysArgs0.
|
|
Color \sysArgs1.
|
|
Pos \sysArgs4:
|
|
6+ Pos=
|
|
\SYS_VDrawBits_134 \sysFn:
|
|
$fb i= [do
|
|
fontData 0? fontData<++ \sysArgs2. 134!!
|
|
\sysArgs4<++
|
|
i<++ i if<>0loop]
|
|
ret
|
|
] PrintChar=
|
|
|
|
[def {PrintText}
|
|
push
|
|
Text=
|
|
[do
|
|
Text, Char= {Next character to be printed}
|
|
if<>0 {Zero termination}
|
|
Text<++ {Advance text pointer}
|
|
Char 10^ [if=0 Pos<. $800 Pos+ Pos=
|
|
else PrintChar!]
|
|
loop]
|
|
pop ret
|
|
] PrintText=
|
|
|
|
[def
|
|
$47# $69# $67# $61# $74# $72# $6f# $6e# 0# {Gigatron}
|
|
] Title=
|
|
|
|
[def
|
|
{-
|
|
DrawLine -- Draw line
|
|
-}
|
|
Count i=
|
|
[do if>0
|
|
Color Pos.
|
|
Pos Step+ Pos=
|
|
i 1- i=
|
|
loop]
|
|
ret
|
|
] DrawLine=
|
|
|
|
[def
|
|
push
|
|
\frameCount, TimeOut- 128& [if=0
|
|
Timer [if>0 1- Timer=]
|
|
DrawTimer!
|
|
]
|
|
pop ret
|
|
] UpdateTimer=
|
|
|
|
[def
|
|
push
|
|
Head Pos= 63 {White} Color= DrawBlock!
|
|
pop ret
|
|
] DrawHead=
|
|
|
|
{-----------------------------------------------------------------------+
|
|
|}\vLR>++ ret{ RAM page 3 |
|
|
+-----------------------------------------------------------------------}
|
|
$0300:
|
|
|
|
[def
|
|
{-
|
|
Game over
|
|
-}
|
|
push
|
|
$4435 Pos=
|
|
4 BgColor=
|
|
[def
|
|
$47# $41# $4d# $45# $20# $4f# $56# $45# $52# 0# {GAME OVER}
|
|
] PrintText!
|
|
|
|
PlayGameOverSound!
|
|
|
|
Score HighScore- [if>0
|
|
Score HighScore=
|
|
30 Color= DrawHighScore!
|
|
]
|
|
pop ret
|
|
] GameOver=
|
|
|
|
[def {Wait -- Wait Delay number of frames (range 1..255)}
|
|
tmp= \frameCount, tmp+ 255& tmp=
|
|
[do \frameCount, tmp- if<>0loop]
|
|
ret
|
|
] Wait=
|
|
|
|
[def
|
|
{-
|
|
Intro
|
|
-}
|
|
push
|
|
|
|
{Display welcome tekst}
|
|
8 {Green} Color=
|
|
0 BgColor=
|
|
$800 ClearScreen!
|
|
$838 Pos= Title PrintText!
|
|
60 Wait!
|
|
|
|
pop ret
|
|
] Intro=
|
|
|
|
[def {ClearScreen -- Clear screen from current position to bottom right}
|
|
Pos= p=
|
|
Pos 255| 255^ {Clear low byte}
|
|
i= $8001 i+ i= {Offset to move to next stripe}
|
|
[do
|
|
{Clear one stripe}
|
|
p [do BgColor p. $100 p+ p= if>=0loop]
|
|
{Next stripe}
|
|
i+ p=
|
|
255& 160^ if<>0loop]
|
|
ret
|
|
] ClearScreen=
|
|
|
|
[def
|
|
0 stepV- tmp=
|
|
stepU stepV=
|
|
tmp stepU=
|
|
ret
|
|
] TurnL=
|
|
|
|
[def
|
|
0 stepU- tmp=
|
|
stepV stepU=
|
|
tmp stepV=
|
|
ret
|
|
] TurnR=
|
|
|
|
[def
|
|
Pos p=
|
|
Color Pos.
|
|
Pos<++ Pos.
|
|
Pos>++ Pos.
|
|
p>++ p.
|
|
ret
|
|
] DrawBlock=
|
|
|
|
{-----------------------------------------------------------------------+
|
|
|}\vLR>++ ret{ RAM page 4 |
|
|
+-----------------------------------------------------------------------}
|
|
$0400:
|
|
|
|
[def
|
|
{-
|
|
RunGame --
|
|
-}
|
|
push
|
|
|
|
[do
|
|
{Control is one of LaunchControl, PlayerControl or AutoControl}
|
|
Control!
|
|
|
|
{Leave a trace behind in the pixels two high bits}
|
|
{Bit 15 and bit 0 of stepU identify the direction}
|
|
stepU>, 128& tmp=
|
|
stepU 1& [if<>0 64] tmp+
|
|
|
|
30+ {Cyan} Color= Head Pos= DrawBlock! {Tail color and trace}
|
|
|
|
{Make step}
|
|
Head stepU+ stepU+ Head=
|
|
|
|
Head, $33& [if<>0 {Hit wall or poison} pop ret]
|
|
Head, 8^ {Food?} [if=0
|
|
{Eat food}
|
|
$40 Timer+ SetTone!
|
|
2 \soundTimer.
|
|
Score Timer+ Score=
|
|
DrawScore!
|
|
5 AddTimer!
|
|
Grow<++ Drops<++
|
|
]
|
|
DrawHead!
|
|
|
|
{Update tail}
|
|
Grow [if>0
|
|
1- Grow= {Do nothing while growing}
|
|
AddFood!
|
|
else
|
|
{Tail is following the head}
|
|
Tail, tmp=
|
|
Drops [if>0 1- Drops= 11 {Orange} else 4] Color=
|
|
Tail Pos= DrawBlock!
|
|
|
|
tmp 64& [if=0 $0100 else $0001] x=
|
|
tmp 128& [if=0 x else 0 x-]
|
|
1<< Tail+ Tail=
|
|
]
|
|
|
|
UpdateTimer!
|
|
|
|
2 Wait! {Fixed game speed}
|
|
loop]
|
|
] RunGame=
|
|
|
|
[def
|
|
push
|
|
8 {Green} Color=
|
|
[do
|
|
\SYS_Random_34 \sysFn: 34!! Pos=
|
|
Pos<, 128- [if<0 157+] 1+ {1..157} $fe& Pos<.
|
|
Pos>, 127& 64- [if<0 109+] $11+ {$11..$fd} $fe& Pos>.
|
|
Pos, 4^ if<>0loop]
|
|
DrawBlock!
|
|
pop ret
|
|
] AddFood=
|
|
|
|
{-----------------------------------------------------------------------+
|
|
|}\vLR>++ ret{ RAM page 5 |
|
|
+-----------------------------------------------------------------------}
|
|
$0500:
|
|
|
|
[def
|
|
push
|
|
{If a key is pressed, start restart the game}
|
|
\serialRaw, $cf& {~buttonStart&~buttonSelect} $cf^ [if<>0 SetupGame! pop ret]
|
|
|
|
{Auto snake control}
|
|
TurnL p=
|
|
TurnR q=
|
|
{Look ahead} Head stepU+ stepU+ peek 4^ tmp=
|
|
{Look left} Head stepV- stepV- peek 4^ [if<>0 {8^4}12^ [if<>0 0 p= else 0 q= 1 tmp=]]
|
|
{Look right} Head stepV+ stepV+ peek 4^ [if<>0 {8^4}12^ [if<>0 0 q= else 0 p= 1 tmp=]]
|
|
tmp [if=0 \entropy, $7f& 6- [if<0 1 else 0]]
|
|
[if<>0 {8^4}12^ if<>0
|
|
{Wall or random direction change: must go left or right.
|
|
Pick randomly, without bias, but don't crash into a wall when not needed}
|
|
p [if=0 q else
|
|
q [if=0 p else
|
|
\entropy, 1& [if=0 p else q]
|
|
]
|
|
]
|
|
[if<>0 call {TurnL or TurnR}]
|
|
]
|
|
pop ret
|
|
] AutoControl=
|
|
|
|
[def
|
|
stepU tmp= {Default keep running in same direction}
|
|
\serialRaw, $fe^ {~buttonRight} [if=0 $0001 tmp=]
|
|
\serialRaw, $fd^ {~buttonLeft} [if=0 $ffff tmp=]
|
|
\serialRaw, $fb^ {~buttonDown} [if=0 $0100 tmp=]
|
|
\serialRaw, $f7^ {~buttonUp} [if=0 $ff00 tmp=]
|
|
{Only turn if not reversing 180 degrees}
|
|
tmp stepU+ [if<>0 tmp stepU=]
|
|
{Or if there is no tail yet in the beginning of the game}
|
|
Tail Head- [if=0 tmp stepU=]
|
|
{Note: `stepV' is not used once under player control}
|
|
ret
|
|
] PlayerControl=
|
|
|
|
{-----------------------------------------------------------------------+
|
|
|}\vLR>++ ret{ RAM page 6 |
|
|
+-----------------------------------------------------------------------}
|
|
$0600:
|
|
|
|
[def {AddTimer}
|
|
push
|
|
Timer+ Timer=
|
|
15- [if>0 15 Timer=]
|
|
\frameCount, TimeOut=
|
|
DrawTimer!
|
|
pop ret
|
|
] AddTimer=
|
|
|
|
[def {SetupGame}
|
|
push
|
|
|
|
{Reset score}
|
|
0 Score= Timer= DrawScore!
|
|
15 Timer= DrawTimer!
|
|
DrawHighScore!
|
|
|
|
{ClearScreen}
|
|
4 BgColor=
|
|
$1000 ClearScreen!
|
|
|
|
{Draw bounding box}
|
|
26 Color=
|
|
+1 Step= 159 Count= DrawLine!
|
|
$100 Step= 111 Count= DrawLine!
|
|
-1 Step= 159 Count= DrawLine!
|
|
-$100 Step= 110 Count= DrawLine!
|
|
+1 Step= 158 Count= DrawLine!
|
|
$100 Step= 109 Count= DrawLine!
|
|
-1 Step= 157 Count= DrawLine!
|
|
-$100 Step= 109 Count= DrawLine!
|
|
|
|
{Get ready message}
|
|
$4432 Pos= 3 {Red} Color=
|
|
[def
|
|
$47# $45# $54# $20# $52# $45# $41# $44# $59# $21# 0# {GET READY!}
|
|
] PrintText!
|
|
60 Wait!
|
|
$4432 Pos=
|
|
[def
|
|
$20# $20# $20# $20# $20# $20# $20# $20# $20# $20# 0#
|
|
] PrintText!
|
|
|
|
{Place snake}
|
|
$4430 Head= Tail=
|
|
DrawHead!
|
|
|
|
0 Grow= Drops=
|
|
Timer= 15 AddTimer!
|
|
$0001 stepU= $0100 stepV= {Start right}
|
|
|
|
{Place 25 foods}
|
|
25 [do i= AddFood! i 1- if>0loop]
|
|
|
|
LaunchControl Control=
|
|
|
|
pop ret
|
|
] SetupGame=
|
|
|
|
{-----------------------------------------------------------------------+
|
|
|}$08a0 \vLR: ret{ RAM page 8 |
|
|
+-----------------------------------------------------------------------}
|
|
$08a0:
|
|
|
|
[def {LaunchControl}
|
|
{-
|
|
XXX better strategy: run both PlayerControl and AutoControl.
|
|
The first one to take control will take over the game...
|
|
-}
|
|
push
|
|
$449c Head- [if=0
|
|
{Switch to autopilot when reaching this position}
|
|
30 {XXX} Color=
|
|
$0802 Pos=
|
|
[def $41# $55# $54# $4f# 0#{AUTO}] PrintText!
|
|
AutoControl Control= call
|
|
else
|
|
{Disable launch control once a button is pressed}
|
|
\serialRaw, $cf& {~buttonStart|~buttonSelect} $cf^ [if<>0 PlayerControl Control= call]
|
|
]
|
|
pop ret
|
|
] LaunchControl=
|
|
|
|
[def { DrawNumber2 - Value Radix }
|
|
push
|
|
$20 Char=
|
|
10 Radix= DrawNextDigit!
|
|
$30 Char=
|
|
1 Radix= DrawNextDigit!
|
|
pop ret
|
|
] DrawNumber2=
|
|
|
|
{-----------------------------------------------------------------------+
|
|
|}\vLR>++ ret{ RAM page 9 |
|
|
+-----------------------------------------------------------------------}
|
|
$09a0:
|
|
|
|
[def { DrawNextDigit -- Value Radix }
|
|
push
|
|
Value Radix- [if>=0
|
|
Value=
|
|
$31 Char=
|
|
Value [do
|
|
Radix-
|
|
if>=0
|
|
Value=
|
|
Char<++
|
|
loop
|
|
]
|
|
PrintChar!
|
|
$30 Char=
|
|
else
|
|
PrintChar!
|
|
]
|
|
pop ret
|
|
] DrawNextDigit=
|
|
|
|
[def { DrawNumber4 - Value Radix }
|
|
push
|
|
$20 Char=
|
|
1000 Radix= DrawNextDigit!
|
|
100 Radix= DrawNextDigit!
|
|
10 Radix= DrawNextDigit!
|
|
$30 Char=
|
|
1 Radix= DrawNextDigit!
|
|
pop ret
|
|
] DrawNumber4=
|
|
|
|
{-----------------------------------------------------------------------+
|
|
|}\vLR>++ ret{ RAM page 10 |
|
|
+-----------------------------------------------------------------------}
|
|
$0aa0:
|
|
|
|
[def
|
|
push
|
|
$802 Pos=
|
|
Score HighScore- [if>0 30 else 8] Color=
|
|
0 BgColor=
|
|
Score Value= DrawNumber4!
|
|
pop ret
|
|
] DrawScore=
|
|
|
|
[def
|
|
push
|
|
$820 Pos=
|
|
8 Color=
|
|
0 BgColor=
|
|
Timer Value= DrawNumber2!
|
|
TimeOut 60+ 255& TimeOut=
|
|
pop ret
|
|
] DrawTimer=
|
|
|
|
{-----------------------------------------------------------------------+
|
|
|}\vLR>++ ret{ RAM page 11 |
|
|
+-----------------------------------------------------------------------}
|
|
$0ba0:
|
|
|
|
[def
|
|
push
|
|
$874 Pos= 0 BgColor=
|
|
[def $48# $49# $20# 0# {HI }] PrintText!
|
|
HighScore Value= DrawNumber4!
|
|
pop ret
|
|
] DrawHighScore=
|
|
|
|
[def {SetupChannel}
|
|
i= 255| 255^ $fa| p= {Pointer to channel struct}
|
|
i<, i= {Extract note}
|
|
0 p. p<++ {.wavA}
|
|
1 p. p<++ {.wavX: 0 "Noise", 1 Triangle, 2 Pulse, 3 Sawtooth}
|
|
\notesTable i+ 0? p. p<++ {.keyL}
|
|
\notesTable i+ 1? p. p<++ {.keyH}
|
|
ret
|
|
] SetupChannel=
|
|
|
|
{-----------------------------------------------------------------------+
|
|
|}\vLR>++ ret{ RAM page 12 |
|
|
+-----------------------------------------------------------------------}
|
|
$0ca0:
|
|
|
|
{ Setup a G-major chord with 4 channels but don't play it yet }
|
|
[def {SetTone}
|
|
push
|
|
1<< tmp=
|
|
$100 tmp| {Channel 1} SetupChannel!
|
|
$200 tmp| {Channel 2} SetupChannel!
|
|
$300 tmp| {Channel 3} SetupChannel!
|
|
$400 tmp| {Channel 4} SetupChannel!
|
|
pop ret
|
|
] SetTone=
|
|
|
|
[def
|
|
push
|
|
$49 j= [do
|
|
j SetTone!
|
|
5 \soundTimer.
|
|
[do \soundTimer, if<>0loop]
|
|
j 1- j= $30^ if<>0loop]
|
|
pop ret
|
|
] PlayGameOverSound=
|
|
|
|
{-----------------------------------------------------------------------+
|
|
|}\vLR>++ ret{ RAM page 13 |
|
|
+-----------------------------------------------------------------------}
|
|
$0da0:
|
|
|
|
{--- Run ---}
|
|
|
|
Intro!
|
|
|
|
$49 SetTone!
|
|
|
|
[do
|
|
SetupGame!
|
|
RunGame!
|
|
|
|
120 \soundTimer.
|
|
3 {Bright Red} Color= Head Pos= DrawBlock!
|
|
GameOver!
|
|
240 Wait!
|
|
|
|
loop
|
|
]
|
|
|
|
{-----------------------------------------------------------------------+
|
|
| End |
|
|
+-----------------------------------------------------------------------}
|
|
|