“Coin Drop” is a coin-pusher arcade simulation in which the player inserts virtual 10p coins, guides them across the top of the screen, and tries to stack five coins in a single column to trigger a payout. The program uses UDGs (User Defined Graphics) to represent the coin sprite across four characters (\a\b on top, \c\d on bottom), defined via a DATA-driven POKE loop at line 3000 that writes directly to the UDG area using PEEK 23675/23676 to find its base address. A real-time clock is implemented by reading the three-byte frame counter at addresses 23672–23674, converting it to seconds by dividing by 50, and storing it as a function FN t() defined at line 72; this is used to enforce a four-minute arcade session limit. The title screen draws each letter of “COIN DROP” using individual PLOT/DRAW commands with arcs, then animates falling coin stacks across all five columns before prompting for instructions. Financial accounting tracks cumulative winnings across multiple games using the variable ow, and the display logic uses integer arithmetic to detect whether a monetary value needs a trailing zero appended.
Program Analysis
Program Structure
The program is organized into clearly separated functional regions:
- Lines 1–3: Initialization — screen attributes and the cumulative winnings variable
ow. - Lines 4: UDG sprite aliases stored in
a$(top half of coin:\a\b) andb$(bottom half:\c\d). - Lines 10–120: Title/intro call, screen draw, peg layout, and game-loop entry.
- Lines 130–190: Coin movement loop — horizontal drift and player nudge handling.
- Lines 500–640: Column landing logic — detects which column a coin falls into, checks for a stack of five, and awards points.
- Lines 1000–1070: Board initialization — randomly seeds existing coin stacks in each column.
- Lines 1100–1320: Coin insertion and fall sequence — slides coin across the top, drops it into the chosen column.
- Lines 1990–2140: End-of-game summary — shows spend, winnings, net gain/loss, and cumulative totals.
- Lines 2500–2670: Title screen animation and instructions subroutine.
- Lines 3000–3050: UDG definition subroutine using a DATA table.
- Line 9999: SAVE with autostart.
UDG Definition via PEEK/POKE
The subroutine at line 3000 locates the UDG table dynamically by reading the system variable at addresses 23675–23676 (PEEK 23675+256*PEEK 23676), which holds the UDG base address. It then READs bytes from a DATA list at lines 3040–3050 and POKEs them sequentially, terminating on the sentinel value 0.5. This defines four UDGs (A–D, 32 bytes total) that together form a 2×2 character coin sprite. Using the system variable rather than a hardcoded address makes the routine relocatable regardless of memory configuration.
Real-Time Clock via Frame Counter
Line 72 defines a user function FN t() that constructs a seconds counter from the three-byte frame counter held at system variables 23672–23674:
DEF FN t()=INT((65536*PEEK 23674+256*PEEK 23673+PEEK 23672)/50)
Dividing the 24-bit frame count by 50 (the frame rate) gives elapsed seconds. The value is captured at game start as t1 and compared against t later to enforce the four-minute (240-second) arcade closing limit at lines 576 and 1115. Line 2082 also uses the timer to reset cumulative winnings if a new session starts after the timer has expired.
Coin Movement and Bounce Logic
After a coin is launched horizontally (lines 1100–1160), it enters the main movement loop at lines 130–190. Each iteration, k is set to either +2 or -2 via 2*COS(PI*INT(RND*2)), introducing a random lateral drift. Boundary checks at lines 154–158 reverse the drift direction at the column edges (y=27 and y=3). The player can use p (right) and q (left) to nudge the coin, but only during specific movement phases (m=2 or m=3). The loop variable m counts movement steps, and the coin lands after 6 steps (m=6 at line 180).
Column Stack and Payout
Five playfield columns are tracked at column positions y=5, 9, 13, 21, and 25 (column 17 is a drain/miss). Stack height per column is stored in variables a, b, c, e, and f respectively. When a coin lands, the relevant counter increments. Once a counter reaches 4 (a stack of 5, since 0-indexed), line 530 branches to 600 which awards 10 points per coin in the stack and clears it. The credit variable cr=nw+60 tracks whether the player still has credit to continue; going to zero or below ends the game.
Title Screen Drawing
The subroutine at line 2500 draws the text “COIN DROP” letter by letter using PLOT and DRAW commands with arc parameters. For example, the “C” uses a curved arc: PLOT 26,144: DRAW 0,-32,11*PI/10. After the lettering, lines 2558–2565 animate coin stacks falling into each of the five columns in sequence by iterating q from 5 to 25 in steps of 4, printing coin sprites at decreasing stack heights.
Financial Display and Decimal Formatting
Lines 2003–2007 implement a custom decimal formatting workaround. The program stores money internally as integer pence and displays it divided by 100 to show pounds. It uses the idiom INT((ow-10)/100)=INT(ow/100) to detect whether the value is a whole number of pounds (i.e., the last two digits are zero), and if so appends a literal “0” to pad the display. There are separate cases for positive (ow>=0) and negative (ow<0) values.
Notable Techniques and Idioms
DIM i$(26)followed immediately byPRINT ... i$is used to efficiently clear a row of the screen by printing a fresh zero-filled string of spaces (lines 35, 2010, 2110).- The coin sprite is rendered as two adjacent 2-character strings (
a$,b$) using AT-positioned PRINT statements, giving a 2×2 character cell appearance. - The delay loop
FOR n=1 TO 100: NEXT nat line 166 provides a hardware-independent pause for coin fall speed without usingPAUSE, which would interrupt BEEP. - Line 1000–1050 use an unconventional single-line
FOR...IF...NEXTpattern where the body of the loop contains anIFguard; this avoids a zero-iteration edge case crash since the loop runsFOR n=1 TO 0when the random value is 0, and theIFsuppresses the PRINT on those iterations. - The peg layout (lines 40–65) is drawn using
CIRCLEwith a radius of 2, giving minimal dots arranged in a triangular/staggered grid to simulate a Pachinko-style peg board.
Potential Anomalies
- Line 565 checks
y=17(the drain column) and prints blank spaces to erase the coin, then plays a BEEP — but column 17 is handled as a no-score case at line 515 (g=0), and the coin is not actually added to any stack, which is correct behavior. - The
INKEY$tests at lines 575–580 form a tight polling loop without aPAUSE, so they consume all CPU time while waiting for the “L” key — this is standard BASIC practice but means the frame counter continues to tick rapidly during this wait. - Line 1250 uses the expression
INT((y+1)/4)=INT((y+3)/4)to test whetheryis on a column boundary (i.e., an even multiple of 4), determining when to stop the horizontal slide and enter the drop phase.
Content
Source Code
1 REM "COIN DROP"
2 GO SUB 3000: BORDER 5: PAPER 6: INK 1
3 LET ow=0
4 LET a$="\a\b": LET b$="\c\d"
10 GO SUB 2500
15 CLS
35 FOR n=0 TO 21: DIM i$(26): PRINT PAPER 6;AT n,3;i$: DIM j$(2): PRINT PAPER 5;AT n,0;j$;AT n,30;j$: NEXT n
40 FOR n=0 TO 192 STEP 32
45 CIRCLE 32+n,77,2: BEEP .05,10: CIRCLE 32+n,109,2: BEEP .05,20: CIRCLE 32+n,141,2: BEEP .05,30
50 NEXT n
55 FOR n=0 TO 160 STEP 32
60 CIRCLE 48+n,93,2: BEEP .05,40: CIRCLE 48+n,125,2: BEEP .05,20
65 NEXT n
70 PAUSE 100
72 DEF FN t()=INT ((65536*PEEK 23674+256*PEEK 23673+PEEK 23672)/50)
74 LET t1=FN t()
75 FOR n=0 TO 21
80 PRINT INK 4;AT n,2;"\f";AT n,29;"\e"
85 IF n>12 THEN PRINT INK 2;AT n,3;"\e\f \e\f \e\f \e\f \e\f \e\f \e\f": REM GRAPHICS EF
90 NEXT n
95 PLOT INK 3;24,159: DRAW INK 3;207,0
100 LET w=0: LET l=0
110 PAUSE 100
120 GO TO 1000
130 PRINT AT x,y;" ";AT x+1,y;" "
135 IF INKEY$="a" AND l>40 THEN LET nw=w-l: GO TO 2000
140 LET k=2*COS (PI*(INT (RND*2)))
150 LET x=x+2
151 IF m=2 AND y<23 AND INKEY$="p" THEN LET y=y+2: GO TO 160
152 IF m=3 AND y>7 AND INKEY$="q" THEN LET y=y-2: GO TO 160
154 IF k>0 AND y=27 THEN LET y=y-k: GO TO 160
155 IF k>0 AND y<26 THEN LET y=y+k
157 IF k<0 AND y=3 THEN LET y=y-k: GO TO 160
158 IF k<0 AND y>4 THEN LET y=y+k
160 PRINT INK 1;AT x,y;a$;AT x+1,y;b$
165 BEEP .05,20
166 FOR n=1 TO 100: NEXT n
170 LET m=m+1
180 IF m=6 THEN GO TO 500
190 GO TO 130
500 IF y=5 THEN LET g=a: LET a=a+1: GO TO 530
505 IF y=9 THEN LET g=b: LET b=b+1: GO TO 530
510 IF y=13 THEN LET g=c: LET c=c+1: GO TO 530
515 IF y=17 THEN LET g=0: GO TO 530
520 IF y=21 THEN LET g=e: LET e=e+1: GO TO 530
525 IF y=25 THEN LET g=f: LET f=f+1
530 IF g=4 THEN GO TO 600
540 FOR n=0 TO 3-g: PRINT INK 1;AT 12+2*n,y;" ";AT 13+2*n,y;" ";AT 14+2*n,y;a$;AT 15+2*n,y;b$
550 PAUSE 20
560 NEXT n
565 IF y=17 THEN PRINT AT 20,17;" ";AT 21,17;" ": BEEP 1,0
568 IF cr<=0 THEN GO TO 2000
570 PRINT INK 2; FLASH 1;AT 1,20;" Press L "
575 IF INKEY$="l" THEN PRINT INK 2; FLASH 1;AT 1,27;"M": GO TO 1100
576 LET t=FN t(): IF t>t1+240 THEN GO TO 1990
578 IF INKEY$="a" AND l>40 THEN LET nw=w-l: GO TO 2000
580 GO TO 575
600 BEEP 1,40
604 FOR n=0 TO 4
606 LET w=w+10: LET nw=w-l: LET cr=nw+60
608 PRINT AT 12+2*n,y;" ";AT 13+2*n,y;" ": BEEP .1,30: PAUSE 20
610 PRINT AT 0,15;" "
612 PRINT BRIGHT 1; FLASH 1;AT 0,15;cr
615 NEXT n
618 IF cr<=0 THEN GO TO 2000
620 IF y=5 THEN LET a=0
621 IF y=9 THEN LET b=0
622 IF y=13 THEN LET c=0
624 IF y=21 THEN LET e=0
625 IF y=25 THEN LET f=0
630 PRINT INK 2; FLASH 1;AT 1,20;" Press L "
635 IF INKEY$="l" THEN PRINT INK 2; FLASH 1;AT 1,27;"M": GO TO 1100
638 IF INKEY$="a" AND l>40 THEN GO TO 2000
640 GO TO 635
1000 LET a=INT (RND*3): FOR n=1 TO a: IF a<>0 THEN PRINT INK 1;AT 23-2*n,5;b$;AT 22-2*n,5;a$: BEEP .05,0: NEXT n
1010 LET b=INT (RND*3): FOR n=1 TO b: IF b<>0 THEN PRINT INK 1;AT 23-2*n,9;b$;AT 22-2*n,9;a$: BEEP .05,10: NEXT n
1020 LET c=INT (RND*5): FOR n=1 TO c: IF c<>0 THEN PRINT INK 1;AT 23-2*n,13;b$;AT 22-2*n,13;a$: BEEP .05,20: NEXT n
1040 LET e=INT (RND*5): FOR n=1 TO e: IF e<>0 THEN PRINT INK 1;AT 23-2*n,21;b$;AT 22-2*n,21;a$: BEEP .05,30: NEXT n
1050 LET f=INT (RND*3): FOR n=1 TO f: IF f<>0 THEN PRINT INK 1;AT 23-2*n,25;b$;AT 22-2*n,25;a$: BEEP .05,40: NEXT n
1060 PRINT INK 2; FLASH 1;AT 1,20;" Press L "
1065 IF INKEY$="l" THEN PRINT INK 2; FLASH 1;AT 1,27;"M": GO TO 1100
1068 IF INKEY$="a" AND l>40 THEN GO TO 2000
1070 GO TO 1065
1100 LET l=l+10: LET nw=w-l: LET cr=nw+60
1101 PRINT AT 0,15;" "
1102 PRINT BRIGHT 1; FLASH 1;AT 0,15;cr
1104 PRINT INK 1;AT 0,3;a$;AT 1,3;b$: PAUSE 6
1105 FOR n=3 TO 27
1110 PRINT AT 0,n;" ";AT 1,n;" "
1115 IF n=27 AND cr<=0 THEN GO TO 2000
1120 IF n=27 THEN GO TO 1060
1130 PRINT INK 1;AT 0,n+1;a$;AT 1,n+1;b$
1140 PAUSE 6
1150 IF INKEY$="m" AND INT (n/2)<>INT ((n-1)/2) THEN LET y=n+1: PRINT AT 1,20;" ": GO TO 1200
1160 NEXT n
1200 LET x=0: LET m=0
1210 PRINT AT x,y;" ";AT x+1,y;" "
1212 PRINT AT 0,15;" "
1215 PRINT BRIGHT 1; FLASH 1;AT 0,15;cr
1220 LET x=x+2: LET m=m+1
1230 PRINT INK 1;AT x,y;a$;AT x+1,y;b$
1240 BEEP .05,20: FOR n=1 TO 50: NEXT n
1250 IF INT ((y+1)/4)=INT ((y+3)/4) THEN GO TO 1300
1260 IF m=2 THEN GO TO 1300
1270 GO TO 1210
1300 PRINT AT x,y;" ";AT x+1,y;" "
1310 PLOT INK 3;24,159: DRAW INK 3;207,0
1320 GO TO 135
1990 PRINT AT 0,15;" ";AT 1,20;" "
1992 PRINT INK 1; FLASH 1;AT 1,8;" ARCADE CLOSING "
1994 FOR n=0 TO 400: NEXT n
2000 PRINT AT 0,15;" ";AT 1,20;" "
2002 LET ow=ow+nw
2003 IF ow>=0 AND INT ((ow-10)/100)=INT (ow/100) THEN PRINT INK 7; PAPER 1; FLASH 1;AT 1,4;" WINNINGS SO FAR #";AT 1,22;ow/100;"0 "
2004 IF ow>=0 AND INT ((ow-10)/100)<>INT (ow/100) THEN PRINT INK 7; PAPER 1; FLASH 1;;AT 1,4;" WINNINGS SO FAR #";AT 1,22;ow/100;".0 "
2006 IF ow<0 AND INT ((ow-10)/100)=INT (ow/100) THEN PRINT INK 7; PAPER 1; FLASH 1;AT 1,7;" LOSS SO FAR #";AT 1,21;-ow/100;"0 "
2007 IF ow<0 AND INT ((ow-10)/100)<>INT (ow/100) THEN PRINT INK 7; PAPER 1; FLASH 1;AT 1,7;" LOSS SO FAR #";AT 1,21;-ow/100;" .0 "
2009 FOR n=0 TO 8
2010 DIM i$(26)
2020 PRINT PAPER 2; BRIGHT 1;AT 13+n,3;i$
2030 NEXT n
2040 PRINT INK 7; PAPER 2;AT 14,4;"You have just spent "; FLASH 1; BRIGHT 1;AT 14,24;l;"p"
2050 PRINT INK 7; PAPER 2;AT 16,7;"and have won "; FLASH 1; BRIGHT 1;AT 16,20;w;"p"
2060 IF nw>=0 THEN PRINT INK 7; PAPER 2;AT 18,5;"Your net gain is "; INK 7; PAPER 0; FLASH 1; BRIGHT 1;AT 18,22;nw;"p"
2070 IF nw<0 THEN PRINT INK 7; PAPER 2;AT 18,5;"Your net loss is "; INK 7; PAPER 0; FLASH 1; BRIGHT 1;AT 18,22;-nw;"p"
2080 PRINT INK 7; PAPER 1; FLASH 1; BRIGHT 1;AT 20,4;" Press P to play again "
2082 IF t>t1+240 AND INKEY$="p" THEN LET t1=FN t(): LET ow=0: GO TO 2100
2085 IF INKEY$="p" THEN GO TO 2100
2090 GO TO 2040
2100 PRINT AT 1,3;" "
2105 FOR n=0 TO 8
2110 DIM i$(26)
2120 PRINT PAPER 6;AT 13+n,3;i$
2130 NEXT n
2140 GO TO 75
2500 DIM i$(704): PRINT AT 0,0;i$
2520 PLOT 26,144: DRAW 0,-32,11*PI/10: BEEP .05,10
2523 PAUSE 30
2524 PLOT 32,112: DRAW 12,32: BEEP .05,10: DRAW 12,-32: BEEP .05,10: PLOT 35,120: DRAW 18,0: BEEP .05,10
2526 PLOT 80,136: DRAW -8,-8,3*PI/2: BEEP .05,10: PLOT 64,120: DRAW 8,8,3*PI/2: BEEP .05,10
2527 PAUSE 30
2528 PLOT 88,112: DRAW 0,32: BEEP .05,10: PLOT 104,112: DRAW 0,32: BEEP .05,10: PLOT 88,128: DRAW 16,0: BEEP .05,10
2529 PAUSE 30
2530 PLOT 116,128: DRAW 8,0: BEEP .05,10
2531 PAUSE 30
2532 PLOT 136,112: DRAW 0,32: BEEP .05,10: DRAW 16,0: BEEP .05,10: PLOT 136,128: DRAW 10,0: BEEP .05,10
2533 PAUSE 30
2534 PLOT 176,112: DRAW -16,0: BEEP .05,10: DRAW 0,32: BEEP .05,10
2535 PAUSE 30
2536 PLOT 194,144: DRAW 0,-32,5*PI/6: BEEP .05,10: DRAW 0,32,5*PI/6: BEEP .05,10
2537 PAUSE 30
2538 PLOT 214,144: DRAW 8,-32: BEEP .05,10: DRAW 8,16: BEEP .05,10: DRAW 8,-16: BEEP .05,10: DRAW 8,23: BEEP .05,10
2540 FOR n=13 TO 21
2545 PRINT INK 2;AT n,3;"\e\f \e\f \e\f \e\f \e\f \e\f \e\f"
2550 PRINT INK 4;AT n,2;"\f";AT n,29;"\e"
2555 NEXT n
2558 LET q=5
2560 FOR n=0 TO 3: PRINT INK 1;AT 12+2*n,q;" ";AT 13+2*n,q;" ";AT 14+2*n,q;a$;AT 15+2*n,q;b$: BEEP .05,q: NEXT n
2561 FOR n=0 TO 2: PRINT INK 1;AT 12+2*n,q;" ";AT 13+2*n,q;" ";AT 14+2*n,q;a$;AT 15+2*n,q;b$: BEEP .05,q: NEXT n
2562 FOR n=0 TO 1: PRINT INK 1;AT 12+2*n,q;" ";AT 13+2*n,q;" ";AT 14+2*n,q;a$;AT 15+2*n,q;b$: BEEP .05,q: NEXT n
2563 PRINT INK 1;AT 14,q;a$;AT 15,q;b$: BEEP .05,q
2565 LET q=q+4: IF q<29 THEN GO TO 2560
2570 IF q=29 THEN PRINT FLASH 1; BRIGHT 1; INK 1;AT 10,2;" PRESS<I> FOR INSTRUCTIONS "
2575 IF INKEY$="i" THEN GO TO 2600
2580 GO TO 2570
2600 CLS
2610 PRINT INVERSE 1;AT 1,10;" CASH-FLOW "
2615 PRINT AT 3,2;"Get five coins in one column to start the flow."
2620 PRINT AT 6,3;"You have six 10p pieces to play with, plus any winnings"
2622 FOR n=0 TO 400: NEXT n
2625 PRINT INK 6; PAPER 2;AT 10,1;" CONTROLS "
2630 PRINT AT 10,13;"L inserts coin";AT 11,13;"M lets it fall"
2635 PRINT AT 13,3;"P and Q nudge the coin to right or left (once only)"
2640 PRINT AT 17,2;"<A> enables you to abandon a game with your winnings after spending 50p"
2642 FOR n=0 TO 400: NEXT n
2644 DIM i$(160): PRINT PAPER 6;AT 3,0;i$
2646 PRINT INK 1; FLASH 1;AT 5,2;" ARCADE CLOSES IN 4 MINUTES "
2648 FOR n=0 TO 400: NEXT n
2650 PRINT AT 5,2;" "; INK 3; FLASH 1;AT 5,7;" PRESS Z TO PLAY "
2660 IF INKEY$="z" THEN RETURN
2670 GO TO 2660
3000 RESTORE : LET n=0
3010 LET u=PEEK 23675+256*PEEK 23676
3020 READ j: IF j=.5 THEN RETURN
3030 POKE u+n,j: LET n=n+1: GO TO 3020
3040 DATA 7,31,63,112,119,228,239,231,224,248,252,14,230,247,247,247,231,224,231,97,112,63,31,7,247,247,231,198,14,252,248,224
3050 DATA 127,127,127,127,127,127,127,127,254,254,254,254,254,254,254,254,.5
9999 SAVE "COIN DROP" LINE 1
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.


