Black Box

Developer(s): D. J. Currie
Date: 198x
Type: Program
Platform(s): TS 2068

Black Box is a three-dimensional adaptation of the classic deduction puzzle, extending the traditional 2D grid into an 8×8×8 cube space with five hidden atoms. The player fires laser beams into the cube by specifying three coordinates; the beam-tracing routine at lines 150–250 uses delta-direction vectors (dx, dy, dz) and iterates through all 27 neighboring cells to compute reflections caused by adjacent atoms, normalizing the result with SGN after each deflection step. Atoms are placed randomly in the inner 6×6×6 region (coordinates 2–9 internally, displayed as 1–8) using a DIM b(10,10,10) array, with the outer layer reserved as entry/exit boundary. The introduction subroutine at line 530 draws an isometric cube diagram using PLOT and DRAW to illustrate the coordinate system before gameplay begins.


Program Structure

The program is organized as a collection of subroutines dispatched from a main loop, with a one-time introduction sequence that runs before the game begins. Control flow is as follows:

  1. Line 30: GO SUB 530 — runs the full introduction and diagram sequence, then returns.
  2. Line 50: GO TO 420 — jumps to the main program block.
  3. Lines 420–520: Main loop — places atoms, then cycles between shooting (GO SUB 60 → GO SUB 140) and guessing (GO SUB 260) based on player input.

The subroutines and their roles are:

  • Lines 60–130: Input a shot (surface entry point).
  • Lines 140–250: Beam-tracing — computes the exit coordinates of a fired beam.
  • Lines 260–310: Input and evaluate an atom-location guess.
  • Lines 320–410: Shared coordinate input routine used by both shooting and guessing.
  • Lines 530–830: Introduction screens with text and isometric cube diagram.

Data Representation

The playing field is a 10×10×10 array b(10,10,10) declared at line 40. Atoms occupy the internal region with indices 2–9 (corresponding to displayed values 1–8), leaving index 1 and 10 unused. The outer playable surface (indices 2 and 9 in any axis) serves as the beam entry/exit boundary. A cell containing an atom is set to 1; all others remain 0 (the default for a numeric array).

Atom placement at line 440 uses RND*6+2, which generates a real number in [2, 8), truncated by array indexing to integers 2–7. This means atoms are never placed in row/column 8 (displayed as 7 or 8 depending on truncation), which is a subtle off-by-one issue — atoms should occupy positions 2–9 but the formula only reaches index 7 (displayed as 6–7 range), slightly biasing placement toward the interior.

Beam-Tracing Algorithm

The beam tracer (lines 150–250) is the technical core of the program. It operates on the current beam position (px, py, pz) and direction vector (dx, dy, dz), each component being −1, 0, or 1.

  1. A triple nested loop over x, y, z from −1 to 1 checks all 27 neighboring cells (including the current cell itself) for atoms.
  2. For each atom found, the direction vector is modified by subtracting the offset (x, y, z) from (dx, dy, dz).
  3. After the loop, each direction component is normalized to {−1, 0, 1} using SGN (line 210), modeling the reflection rule.
  4. The beam advances one step (line 220) and the loop repeats until the beam reaches a surface (line 230 checks if any coordinate equals 2 or 9).

Line 230 uses addition of boolean expressions as a sum — if any coordinate is on a surface, at least one term is 1, making the total non-zero, and the beam exits. This is a compact idiom for an OR condition across multiple equality tests.

Coordinate Input and Validation

The shared input subroutine at lines 320–410 adds 1 to each entered coordinate (px=px+1 etc.) to translate the user’s 1–8 range into the internal 2–9 indexing. Validation loops (lines 350, 370, 390) re-prompt if any coordinate falls outside the valid range. The shot-input subroutine (lines 60–130) additionally checks that at least one of dx, dy, dz is non-zero, enforcing that the entry point is on a surface rather than in the interior.

The direction components are derived at lines 90–110 using boolean arithmetic: (px=2)-(px=9) evaluates to 1 if px=2 (beam moving in the positive direction), −1 if px=9 (moving in the negative direction), and 0 otherwise. This is an elegant Sinclair BASIC idiom for computing a signed direction without IF statements.

Introduction and Diagram

Lines 530–830 form a multi-screen introduction. Lines 600–670 draw an isometric cube using PLOT and DRAW: horizontal grid lines are drawn in two passes (lines 600–610 and 620–630), and diagonal lines completing the isometric perspective are drawn in a loop at lines 640–670. The axis labels and numbered coordinate scales are then PRINTed using AT positioning (lines 680–740).

Three screens of rules text explain the three reflection cases: direct back-reflection when a beam hits an atom head-on, right-angle reflection for beams passing through an orthogonally adjacent cell, and double right-angle (diagonal) reflection for cells diagonally adjacent to an atom. Each screen waits for a keypress using the IF INKEY$="" THEN GO TO idiom.

Notable Techniques and Anomalies

  • The 27-neighbor loop (including the (0,0,0) offset) means the beam’s own cell is checked for atoms. Since a beam enters from the surface and atoms cannot be on the surface, this does not cause errors in practice, but it is technically unnecessary for the (0,0,0) case.
  • The main loop at lines 460–520 does not track the number of shots fired or provide a scoring mechanism — the game ends when the player guesses correctly, with no penalty count.
  • Line 440 does not check for duplicate atom placements; two RND calls could produce the same cell, resulting in fewer than five distinct atoms.
  • The SAVE "Black Box" LINE 20 at line 840 saves the program with an auto-run start line.
  • Output of results (line 240) and inputs (line 400) subtract 1 from internal coordinates to display the user-facing 1–8 range.

Image Gallery

Source Code

  10 REM \{6}From\{6} Tantalizing Games for the\{6} TS 2000 Series\{6}\{6}    - typed by D.J.Currie -\{6}\{6}
  20 BORDER 6:PAPER 6:INK 0:CLS 
  30 GO SUB 530
  40 DIM b(10,10,10)
  50 GO TO 420
  60 REM input shot
  70 PRINT "Please input shot"
  80 GO SUB 320:REM input
  90 LET dx=(px=2)-(px=9)
 100 LET dy=(py=2)-(py=9)
 110 LET dz=(pz=2)-(pz=9)
 120 IF (dx=0) AND (dy=0) AND (dz=0) THEN GO TO 80
 130 RETURN 
 140 REM compute result
 150 FOR x=-1 TO 1
 160 FOR y=-1 TO 1
 170 FOR z=-1 TO 1
 180 IF b(px+x,py+y,pz+z) <>1 THEN GO TO 200
 190 LET dx=dx-x:LET dy=dy-y:LET dz=dz-z
 200 NEXT z:NEXT y:NEXT x
 210 LET dx= SGN dx:LET dy= SGN dy:LET dz= SGN dz
 220 LET px=px+dx:LET py=py+dy:LET pz=pz+dz
 230 IF (px=2)+(px=9)+(py=2)+(py=9)+(pz=2)+(pz=9)=0 THEN GO TO 150
 240 PRINT "Result: ";px-1;" ";py-1;" ";pz-1
 250 RETURN 
 260 REM input guess
 270 PRINT "Please input guess"
 280 GO SUB 320
 290 IF b(px,py,pz)=1 THEN PRINT "Right!":RETURN 
 300 PRINT "Wrong!"
 310 RETURN 
 320 REM input coordinates
 330 PRINT "Enter coordinates"
 340 INPUT "P1=";px:LET px=px+1
 350 IF px<2 OR px>9 THEN GO TO 340
 360 INPUT "P2=";py:LET py=py+1
 370 IF py<2 OR py>9 THEN GO TO 360
 380 INPUT "P3=";pz:LET pz=pz+1
 390 IF pz<2 OR pz>9 THEN GO TO 380
 400 PRINT "Input:  ";px-1;" ";py-1;" ";pz-1
 410 RETURN 
 420 REM main program
 430 FOR a=1 TO 5
 440 LET b(RND*6+2, RND*6+2, RND*6+2)=1
 450 NEXT a
 460 GO SUB 60:REM input shot
 470 GO SUB 140:REM compute result
 480 INPUT "Shoot or guess (s or g)? ";t$
 490 IF t$ <>"s" AND t$ <>"g" THEN GO TO 480
 500 IF t$="s" THEN GO TO 460
 510 GO SUB 260:REM input guess
 520 GO TO 480
 530 CLS :PRINT AT 2,7;"BLACK BOX"
 540 PRINT '''"  There are 5 atoms randomly    placed in 5 cubes of a black boxconsisting of 8x8x8 cubes. Atomsare never found in the outer    layer of cubes."
 550 PRINT '"  You have a laser beam to find the cubes which contain the     atoms."
 560 PRINT ''' TAB 7;"GOOD LUCK!"
 570 PRINT #0;"Press any key to continue"
 580 IF INKEY$="" THEN GO TO 580
 590 CLS 
 600 FOR n=32 TO 96 STEP 8
 610 PLOT 60,n:DRAW 64,0:DRAW 64,32:NEXT n
 620 FOR n=60 TO 124 STEP 8
 630 PLOT n,32:DRAW 0,64:DRAW 64,32:NEXT n
 640 LET x=60:LET y=96
 650 PLOT x,y:DRAW 64,0:DRAW 0,-64
 660 IF x >=124 OR y >=128 THEN GO TO 680
 670 LET x=x+8:LET y=y+4:GO TO 650
 680 PRINT AT 13,0;"x= P1"; AT 20,9;"y= P2"; AT 16,23;"z= P3"
 690 PRINT AT 0,0;"Enter 3 coordinates in order.   A shot enters at a surface so   1 of the 3 coordinates must     be either 1 or 8."
 700 FOR n=1 TO 8
 710 PRINT AT 18-n,6;n:NEXT n
 720 FOR n=1 TO 8
 730 PRINT AT 18,6+n;n:NEXT n
 740 PRINT AT 17,16;"12"; AT 16,18;"34"; AT 15,20;"56"; AT 14,22;"78"
 750 PRINT AT 21,0;"Press any key to continue"
 760 IF INKEY$="" THEN GO TO 760
 770 CLS 
 780 PRINT "A beam which strikes an atom is reflected straight back in the  opposite direction              i.e. an atom at 335 and a shot  at 331 would exit at 331." 
 790 PRINT '"A beam set to pass through a    cube directly adjacent to an    atom will be reflected at right angLes                          i.e. an atom at 335 and a shot  at 321 would exit at 314."
 800 PRINT '"A beam set to pass through a    cube diagonally adjacent to an  atom will be reflected in a     direction obtained by adding 2  right angled reflections        i.e. an atom at 335 and a shot  at 221 would exit at 114."
 810 PRINT #0;"  Press any key to continue"
 820 IF INKEY$="" THEN GO TO 820
 830 CLS :RETURN 
 840 CLEAR :SAVE "Black Box" LINE 20

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