RomeoT

Date: 198x
Type: Program
Platform(s): TS 2068
Tags: Game

This program implements a carnival-style weight-guessing game where the player enters their weight and a “guesser” character attempts to predict it. Custom UDGs (User Defined Graphics) are defined via DATA statements and POKEd into memory at USR “\a” through USR “\e”, creating the character sprites and display elements. The game draws a scale using block graphics and PLOT/DRAW commands, animates a weight indicator moving up or down, and compares the player’s input against a randomly generated target range. Lines 9900–9952 contain an elaborate self-listing routine that reads the program’s own tokenized BASIC from memory, decodes keyword tokens, and renders each statement graphically using DRAW commands to approximate letter shapes, with arc-based curves for rounded characters like O, C, and S.


Program Analysis

Program Structure

The program divides cleanly into two independent sections. Lines 10–370 implement the weight-guessing game itself. Lines 9900–9952 form a standalone self-listing and pseudo-pretty-printer routine that is never called by the game — it must be invoked separately (e.g., by RUNning from line 9900 or via the SAVE line’s LINE 0 autostart).

UDG Initialization

Lines 20–70 define five custom UDGs (\a through \e, characters 144–148) using 40 bytes of DATA. Each UDG is 8 bytes tall. The DATA at line 30 uses the variable a as a placeholder (value 0 after being consumed by READ) — this is a subtle trick where a appears in the DATA list itself, producing whatever value a currently holds at read time, which is 0 after the first READ iteration resets it. The POKE loop at line 70 writes sequentially to USR "\a" through USR "\a"+39, filling five UDGs.

Game Logic

The game flow is as follows:

  1. Draw a decorative border using block graphics (lines 80–110).
  2. Initialize player position (x=21, y=8) and draw a scale with PLOT/DRAW (line 120).
  3. Place the player sprite (\a) at the starting position (line 130).
  4. Pick a random target row h in the range 8–18 and display a marker (\b) (lines 140–150).
  5. Prompt for and validate weight input w, 1–14 (lines 160–170).
  6. Animate a weight dropping (line 180) and redraw the scale line (line 190).
  7. Move the sprite upward by w rows (lines 200–230) then shift left two columns (line 240).
  8. Compare final position against target h: exact match triggers a win (lines 280–310); landing above the target causes a fall animation (lines 320–350); landing below shows a failure sprite (\e) with a low BEEP (line 270).

Graphics Techniques

The playing field border is drawn entirely with block graphic characters printed via PRINT AT, using INK 6 (yellow) for the frame and INK 4 (green) for interior details. The weighing scale is rendered with PLOT 64,0: DRAW 37,16 and later erased and redrawn with DRAW OVER 1 to show the scale tipping. Sprite animation uses character-cell movement: the old position is blanked with a space and the new position is printed with the UDG character.

Self-Listing Routine (Lines 9900–9952)

This is the most technically ambitious section of the program. It walks the tokenized BASIC program area in memory, decoding each line and rendering keyword tokens as pixel-drawn letterforms using DRAW commands.

  • PEEK 23635 + 256*PEEK 23636 (line 9901) reads system variable PROG to find the start of the BASIC area.
  • Line 9903 reads the two-byte line number and advances the pointer past the line-length word (4 bytes total header).
  • Lines 9906–9911 dispatch on the token byte b to select a drawing subroutine for that keyword’s shape. Token values in the 226–254 range correspond to BASIC keywords.
  • Line 9911 draws a generic rectangular letter outline using a sequence of DRAW commands (baseline rectangle with a gap), representing the keyword.
  • Line 9923 draws rounded-end forms (for tokens like ON ERR, PRINT, etc.) using arc DRAW calls with -PI angle parameter for semicircles.
  • Line 9924 draws plain rectangular outlines for another token class.
  • Lines 9925–9932 handle tokens for SOUND (b=250) and STICK (b=243) with a distinctive stepped shape.
  • Lines 9933–9938 handle CIRCLE and related tokens, drawing an actual circle with CIRCLE x,y-4,4.
  • Lines 9916–9920 scan forward through the token stream byte by byte; byte 34 (") triggers a subroutine to skip string literals (lines 9951–9952), byte 14 skips the 5-byte floating-point number format (LET a=a+4), byte 13 is a newline (end of statement), and byte 58 (:) marks a statement separator handled at line 9939.
  • Line 9942 displays a prompt using INVERSE 1, and lines 9943–9945 poll INKEY$ for “v” (view) or “p” (print via COPY).

Notable Idioms and Techniques

  • VAL "number" is not used here; GO TO targets are plain literals.
  • The DRAW OVER 1 at line 190 erases the previous scale line by XOR-drawing over it, a standard technique for flicker-free animation.
  • The self-lister limits output to 20 items (c=20 checks at lines 9921 and 9939) to avoid scrolling off-screen.
  • The SAVE line at 9953 uses LINE 0, targeting non-existent line 0, which is a recognized technique to influence program startup behavior.
  • The DATA values in line 30 use the variable a literally inside a DATA statement — this is unusual and works because the variable a holds 0 after the first READ, making those entries effectively 0.

Potential Bugs and Anomalies

  • Line 30’s use of a in DATA is unconventional. In standard Spectrum BASIC, DATA elements are stored as literals at program entry time, not evaluated dynamically, so a here is the numeric variable’s current value when READ is executed — this works only because a is reliably 0 at that point, but it is fragile.
  • The self-lister at line 9946 resets c=0, x=130, y=175 for a fresh render pass, but a continues from wherever the previous pass left off, meaning the “view” mode may not restart from the beginning of the program.
  • Line 9950 issues COPY for printer output but does not reset the display mode, so the printed output depends on what is currently on screen.

Token Dispatch Table

Token byte(s)DescriptionDrawing routine
226, 234, 242, 254Rounded-end keyword groupLine 9923 (arc DRAW)
228–230, 232, 235, 241, 247, 249, 253Rectangular keyword groupLine 9924 (box DRAW)
243, 250STICK / SOUNDLine 9925 (stepped shape)
236, 237CIRCLE-relatedLine 9933 (CIRCLE + line)
all othersGeneric keywordsLine 9911 (default outline)

Content

Appears On

Library tape of the Indiana Sinclair Timex User’s Group.

Related Products

Related Articles

Related Content

Image Gallery

RomeoT

Source Code

   10 PAPER 0: INK 7: BORDER 0: CLS 
   20 DATA 56,56,146,254,16,124,68,198
   30 DATA 0,255,171,a,a,a,255,a
   40 DATA 0,a,28,20,62,a,127,a
   50 DATA 0,a,a,a,24,126,255,a
   60 DATA 192,224,a,240,a,224,a,192
   70 FOR f=0 TO 39: READ a: POKE USR "\a"+f,a: NEXT f
   80 PRINT AT 4,0; INK 6;"\:: \:: \:: \::"'"\::\::\::\::\::\::\::"'"\::\::\::\::\::\::\::"
   90 FOR n=7 TO 21: PRINT AT n,1; INK 6;"\::\::\::\::\::": NEXT n
  100 PRINT AT 11,13; INK 4;"\':\::\::";AT 12,15;"\':";AT 13,15;"\ :";AT 14,15;"\ '";AT 18,15;"\ :";AT 19,15;"\ :";AT 20,15;"\ :";AT 21,15;"\.:"
  110 FOR n=11 TO 21: PRINT AT n,16; INK 4;"\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::": NEXT n
  120 LET x=21: LET y=8: PRINT AT 21,10;"O": PLOT 64,0: DRAW 37,16
  130 PRINT AT x,y; INK 5;"\a"
  140 LET h=INT (RND*11)+8
  150 PRINT AT h+1,6;"\b"
  160 PRINT AT 4,11;"ENTER WEIGHT";AT 5,13;"(max.14)"
  170 INPUT w: IF w<=0 OR w>=15 THEN GO TO 170
  180 FOR n=10 TO 20: PRINT AT n-1,12;" ";AT n,12;"\c": BEEP .1,n: NEXT n
  190 PLOT 64,0: DRAW OVER 1;37,16: PLOT 64,16: DRAW 37,-16
  200 FOR n=1 TO w
  210 LET x=x-1
  220 PRINT AT x,y;"\a";AT x+1,y;" "
  230 NEXT n
  240 FOR n=1 TO 2: LET y=y-1: PRINT AT x,y;"\a ": NEXT n
  250 IF x=h THEN GO TO 280
  260 IF x>h THEN GO TO 320
  270 IF x<=h THEN PRINT AT x,y; INK 5;"\e": BEEP 1,-10: PAUSE 30: CLS : GO TO 80
  280 PRINT AT x,y+1;"WELL DONE!"
  290 FOR n=0 TO 40 STEP 10: BEEP .1,n: NEXT n
  300 CLS 
  310 PAUSE 30: RUN 
  320 FOR n=x TO 21
  330 PRINT AT n,y; INK 5;"\e";AT n-1,y;" "
  340 BEEP .05,n: NEXT n
  350 PRINT AT 21,y; INK 5;"\d"
  360 BEEP 1,-10
  370 PAUSE 30: CLS : GO TO 80
 9900 OVER 0: INVERSE 0: BRIGHT 0: FLASH 0: BORDER 7: PAPER 7: INK 0: CLS 
 9901 LET a=PEEK 23635+256*PEEK 23636
 9902 LET c=0: LET y=175: LET x=130
 9903 LET l=PEEK (a+1)+256*PEEK a: LET a=a+4
 9904 IF l>9900 THEN GO TO 9942
 9905 PRINT l;TAB 5;CHR$ PEEK a: LET c=c+2: PRINT 
 9906 PLOT x,y: LET b=PEEK a
 9907 IF b=226 OR b=234 OR b=242 OR b=254 THEN GO TO 9923
 9908 IF b>227 AND b<231 OR b=232 OR b=235 OR b=241 OR b=247 OR b=249 OR b=253 THEN GO TO 9924
 9909 IF b=243 OR b=250 THEN GO TO 9925
 9910 IF b=236 OR b=237 THEN GO TO 9933
 9911 DRAW 16,0: DRAW -4,-8: DRAW -28,0: DRAW 4,8: DRAW 12,0
 9912 LET y=y-8
 9913 IF b=226 OR b=236 OR b=237 OR b=254 THEN GO TO 9915
 9914 PLOT x,y: DRAW 0,-7: DRAW 4,4: DRAW -4,-4: DRAW -4,4
 9915 LET y=y-8
 9916 LET b=PEEK a: IF b=34 THEN GO SUB 9951
 9917 IF b=14 THEN LET a=a+4
 9918 IF b=13 THEN GO TO 9921
 9919 IF b=58 THEN GO TO 9939
 9920 LET a=a+1: GO TO 9916
 9921 IF c=20 THEN GO TO 9942
 9922 LET a=a+1: GO TO 9903
 9923 DRAW 12,0: DRAW 4,-8,-PI: DRAW -24,0: DRAW -4,8,-PI: DRAW 12,0: GO TO 9912
 9924 DRAW 16,0: DRAW 0,-8: DRAW -32,0: DRAW 0,8: DRAW 16,0: GO TO 9912
 9925 DRAW 8,-4: DRAW 8,0: DRAW -4,4: DRAW 4,-4: DRAW -4,-4: DRAW 4,4: DRAW -8,0: DRAW -8,-4: DRAW -8,4: DRAW 8,4
 9926 IF b=243 THEN GO TO 9932
 9927 LET a=a+1: LET f=PEEK a
 9928 IF f=14 THEN LET a=a+4
 9929 IF NOT f=203 THEN GO TO 9927
 9930 LET a=a+1: LET f=PEEK a: PRINT AT c-2,19;CHR$ f: PRINT 
 9931 IF f=236 OR f=237 THEN GO TO 9934
 9932 GO TO 9912
 9933 CIRCLE x,y-4,4: PLOT x+4,y-4: DRAW 64,0: DRAW -4,4: DRAW 4,-4: DRAW -4,-4: PLOT x,y
 9934 LET a=a+1: LET f=PEEK a
 9935 IF NOT f=14 THEN GO TO 9934
 9936 LET a=a+3: LET g=PEEK a+256*PEEK (a+1)
 9937 PRINT AT c-2,26;g: PRINT 
 9938 GO TO 9912
 9939 IF c=20 THEN GO TO 9942
 9940 LET a=a+1: PRINT "   :";TAB 5;CHR$ PEEK a: PRINT : LET c=c+2
 9941 GO TO 9906
 9942 INVERSE 1: PRINT AT 21,0;" PRESS ""V"" TO VIEW:""P"" TO PRINT ": INVERSE 0
 9943 IF INKEY$="v" THEN GO TO 9946
 9944 IF INKEY$="p" THEN GO TO 9950
 9945 GO TO 9943
 9946 CLS : LET d=0: LET e=22: LET c=0: LET x=130: LET y=175
 9947 IF PEEK a=58 THEN GO TO 9940
 9948 IF l>9900 THEN PRINT AT 20,6;"End of Basic Program": STOP 
 9949 LET a=a+1: GO TO 9903
 9950 PRINT AT 21,0,,: COPY : GO TO 9946
 9951 LET a=a+1: LET b=PEEK a: IF b=34 THEN RETURN 
 9952 GO TO 9951
 9953 SAVE "ROMEO  T" LINE 0

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

People

No people associated with this content.

Scroll to Top