gigatron/rom/Apps/Snake/Snake_v1.gcl
2025-01-28 19:17:01 +03:00

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 |
+-----------------------------------------------------------------------}