--- title: "Bridge" id: 64750 type: "computer_media" slug: "bridge-2" url: "http://localhost/computer_media/bridge-2/" markdown_url: "http://localhost/computer_media/bridge-2.md" published_at: "2026-03-07T23:33:23+00:00" modified_at: "2026-03-30T21:29:17+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2026/03/bridge-1.png" excerpt: "A fully playable bridge hand trainer that deals, displays with suit symbols, and tracks all 13 tricks — complete with contract entry and audio feedback at key trick counts." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" genre: - name: "Game" slug: "game" taxonomy: "genre" url: "http://localhost/type/game/" media_contents: - id: 64715 title: "Miscellaneous Programs" type: "computer_media" url: "http://localhost/computer_media/miscellaneous-programs/" media_type: "Program" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2026/03/bridge-1.png" - url: "http://localhost/wp-content/uploads/2026/03/bridge-2.png" media_type_tags: "Game" --- # Bridge This program implements a practice bridge hand dealer and card-play trainer. It deals a shuffled 52-card deck into four hands (North, East, South, West), displays them on screen using suit UDGs for spades, hearts, diamonds, and clubs, then allows the user to enter a contract and play out all 13 tricks. The shuffle uses a Fisher-Yates-style algorithm encoded in a string of two-digit card numbers stored in `A$`. Trick-taking logic evaluates played cards numerically, tracking trump and lead suit, and sounds BEEP tones at contract-making or defeating trick counts. *** ## Program Structure The program is organized into loosely coupled routines, navigated via `GO TO` and `GO SUB`. The main flow is: 1. Lines 1–15: UDG setup and jump to intro/deal entry point. 2. Lines 670–699: Title screen, instructions, deal invocation, sort, then display. 3. Lines 600–645: Card shuffle and deck initialization. 4. Lines 100–150: Selection sort of each hand. 5. Lines 60–80: Hand display loop. 6. Lines 250–570: Contract input, card play, trick resolution loop. 7. Lines 900–920: End-of-hand options (redeal or replay). Subroutines are used sparingly: `GO SUB 20` builds a display string for each suit holding, and `GO SUB 100` sorts each hand. Most other logic uses `GO TO` chains. ## UDG Initialization Lines 5–10 define four UDGs for the suit symbols using `POKE USR X$+J,X`, reading glyph bitmaps from `DATA`. The characters loaded are `"H"` (hearts), `"C"` (clubs), `"D"` (diamonds), and `"S"` (spades), occupying UDG slots corresponding to those letters. These are then referenced in the display string `I$="\s\h\d\c"` at line 671 and in suit indicator prints throughout the play loop. ## Shuffle Algorithm The deck is encoded in `A$` at line 600 as a 104-character string of zero-padded two-digit numbers from `"01"` to `"52"`. The shuffle loop (lines 610–645) picks a random two-character substring, extracts it into `B$(X)` and `A(X)`, then removes those two characters from `A$` using string slicing. This is a correct partial Fisher-Yates draw-without-replacement. The special case at lines 620–625 handles the final card when `LEN A$=2` and issues a `RETURN` mid-loop — a notable structural quirk that exits the `GO SUB 600` call early from inside the `FOR` loop body. ## Hand Sorting Lines 100–150 implement a **selection sort** over 13 elements. Variable `C` is initialized to 12 (step count), and each pass finds the maximum value in the unsorted tail, swapping it to the end. The sort is descending by card number (where Ace=14 is highest). The loop decrements `C` and returns when `C=0`. The comment `REM FLOAT SORT, SYNC 4:2,20` is a note to the author’s own documentation system. ## Hand Display and Suit String Building The `GO SUB 20` routine (lines 20–45) constructs a Procrustean (fixed-capacity) string `E$(ED)` of up to 10 characters representing a suit holding. It scans the hand array for cards belonging to the current suit offset `B`, builds a rank string using `D$="AKQJ1098765432"`, and handles the special two-character case `"10"`. The variable `V$` is a space character used as a sentinel/padding value throughout the display and erasure logic. Line 60 uses `DATA 0,12,8,20,16,12,8,0` at line 75 to supply screen row/column coordinates for the four hands’ display positions, printing with `INK 2` for red suits (hearts and diamonds). ## Contract and Play Input Lines 275–305 validate three separate `INPUT` fields: declarer direction (`H$`), denomination (`K$`: 1–7), and suit/NT (`T$`: S/H/D/C/N). Each is checked against the lookup string `O$="NESWNSHDC1234567"` using a `FOR` loop; invalid input loops back to line 275. This is an efficient single-string multi-field lookup idiom. The card play input at line 435 accepts rank strings (e.g., `"A"`, `"10"`, `"J"`) validated against the current suit holding `R$` using a sliding substring search at lines 450–455. Entering `"X"` at any input point triggers a return to trick 1 (line 495 via `GO TO 80`). ## Trick Evaluation The array `C(4)` stores the effective trick value for each player’s played card. Lines 470–475 assign values: if following the lead suit, the card’s numeric value is used; if playing trump, 13 is added to the value, making any trump beat any non-trump. The winner is determined at lines 500–510 by finding the maximum in `C(1..4)`. ## Score Tracking and Audio Running trick counts are displayed for both N-S and E-W. `BEEP` calls provide audio feedback at contract-making or defeating thresholds: - A short beep (`BEEP .25,30` or `BEEP .25,-20`) sounds on each trick won. - A long beep (`BEEP 1,0` or `BEEP 1,-60`) sounds when the contract is made or defeated, computed as `VAL K$+6` tricks for declarer or `8-VAL K$` tricks for defenders. ## Notable Idioms and Techniques - `VAL H$` converts direction letters to numeric offsets (N=0 implied by ASCII difference or lookup position) — actually `VAL H$` on `"N"`, `"E"`, `"S"`, `"W"` will return 0; the program relies on `O$(R)` position for numeric direction via `R`, but uses `VAL H$*4` — this only works correctly if `H$` has been set to a digit string, which happens at line 340: `H$=O$(R+1)` where positions 5–8 of `O$` are `"N"`,`"S"`,`"H"`,`"D"` — actually `O$` positions 1–4 are `N,E,S,W` and 5–8 are re-used as suit chars; this is a latent confusion but the program resets `H$` from position-derived values. - String boolean expressions like `(D$(Y) AND Y<5)` select substrings conditionally without `IF`. - `RESTORE 315` / `READ` loops re-read the suit symbol data multiple times during play (lines 476–483). - The `REM HERE` comments on lines 45, 150, and 340 are positional markers indicating jump targets for `GO TO` statements, a common idiom when the target is mid-routine. ## Source Code ``` 1 REM SAVE "DEAL A" AT B35 5 FOR I=1 TO 4: READ X$: FOR J=0 TO 7: READ X: POKE USR X$+J,X: NEXT J: NEXT I 10 DATA "H",34,119,127,127,62,62,28,8,"C",28,28,8,107,127,107,8,8,"D",8,28,62,127,62,28,8,0,"S",8,28,62,127,127,127,107,8 15 GO TO 670 20 LET ED=ED+1: LET F$="": IF ED=17 THEN LET ED=1: REM PRINT HAND/SUIT ROUTINE TO... 25: FOR R=A TO A+12: LET X=A(R): LET Y=X-B: IF Y>0 AND Y<14 THEN GO TO 40 30 NEXT R 35 PRINT E$(ED): LET G$(ED)=E$(ED): LET V=V+1: RETURN 40 LET F$=F$+(D$(Y) AND Y<5)+("10" AND Y=5)+(D$(Y+1) AND Y>5): LET E$(ED)=F$ 45 GO TO 30: REM HERE 60 RESTORE 75: FOR A=1 TO 40 STEP 13: READ V: READ H: FOR B=0 TO 39 STEP 13: PRINT INK (2 AND (B=13 OR B=26));AT V,H;I$(B/13+1);;V$;: GO SUB 20 65 NEXT B: NEXT A: GO TO 250 75 DATA 0,12,8,20,16,12,8,0 80 FOR X=20 TO 21: FOR Y=0 TO 31: PRINT AT X,Y;V$: NEXT Y: NEXT X: GO TO 60 100 LET C=12: REM FLOAT SORT, SYNC 4:2,20; TO... 110 LET K=A: LET Q=A(A) 115 FOR S=A+1 TO A+C: IF A(S)1 THEN GO TO 395 352 LET VV=0: REM ONE-SUIT HAND ROUTINE... 355 FOR T=1 TO 4: IF E$(VAL H$*4+T,1)=V$ THEN GO TO 365 360 LET TT=T: GO TO 367 365 LET VV=VV+1 367 NEXT T 369 IF VV=3 THEN LET S$=O$(TT+5) 370 IF VV=3 THEN GO TO 385: REM TO HERE 375 INPUT "SUIT?";S$: IF S$="X" THEN GO TO 495 380 IF S$<>"S" AND S$<>"H" AND S$<>"D" AND S$<>"C" THEN GO TO 375 385 IF I=1 THEN LET W$=S$: REM W$ IS LEAD;L$ IS WORKING SUIT 390 LET L$=S$ 395 IF L$="S" THEN LET Z=VAL H$*4+1: REM "S" ALREADY VALUED FOR SOUTH 400 IF L$="S" THEN GO TO 410 405 LET Z=VAL H$*4+VAL L$ 410 FOR R=1 TO 10: IF E$(Z,R)=V$ THEN GO TO 420: REM R-1 IS # OF VISIBLE CHARACTERS IN PROCRUSTEAN E$ 415 NEXT R 420 LET R$=E$(Z,1 TO R-1) 425 IF LEN R$=0 THEN GO TO 352: REM VOIDS 430 IF R$="10" OR LEN R$=1 THEN LET C$=R$: GO TO 440: REM SINGLETONS 435 INPUT "CARD?";C$: IF C$="X" THEN GO TO 495 440 IF LEN C$>1 AND C$<>"10" THEN GO TO 435 445 IF C$="" THEN GO TO 435 450 FOR R=1 TO LEN R$: IF R$(R TO R+LEN C$-1)=C$ THEN GO TO 460 455 NEXT R: GO TO 435 460 LET E$(Z)=R$( TO R-1)+R$(R+LEN C$ TO ) 465 PRINT AT Z-1+(4 AND H$="E")+(8 AND H$="S")-(4 AND H$="W"),14+(8 AND H$="E")-(12 AND H$="W");E$(Z)+((V$+V$) AND E$(Z)=""): REM REMOVES CARD FROM HAND AND CLOSES UP SUIT 470 LET C(VAL H$+1)=(VAL C$ AND L$=W$) 475 IF L$=T$ THEN LET C(VAL H$+1)=VAL C$+13 476 FOR M=1 TO 4: READ M$: READ N$: IF M$=L$ THEN GO TO 480: REM READS 315 477 NEXT M 480 LET V=10+(2 AND H$="S")-(2 AND H$="N"): LET HZ=14+(2 AND H$="E")-(2 AND H$="W") 481 PRINT AT V,HZ; INK (2 AND (L$="H" OR L$="D"));N$; INK 0;C$;V$: REM PLAYS CARD TO CENTER 483 RESTORE 315 485 LET I=I+1: IF I<5 THEN GO TO 575 495 LET I=1: FOR X=8 TO 12 STEP 2: FOR Y=12 TO 18: PRINT AT X,Y;V$: NEXT Y: NEXT X: IF C$="X" OR S$="X" THEN GO TO 80: REM PICKS UP TRICK WITH ACCEPTABLE DELAY 500 LET R=1: FOR X=2 TO 4: IF C(R)>C(X) THEN GO TO 510 505 LET R=X 510 NEXT X 515 LET H$=O$(R): PRINT AT 21,20;"E-W": PRINT AT 21,12;"N-S": IF R=1 OR R=3 THEN GO TO 545: REM PASSES LEAD TO WINNER;E-W TRICK ROUTINE 520 LET II=II+1: PRINT AT 21,24;II: IF J$="S" OR J$="N" THEN GO TO 535 525 BEEP .25,30: IF II=VAL K$+6 THEN BEEP 1,0 530 GO TO 565 535 BEEP .25,-20: IF II=8-VAL K$ THEN BEEP 1,-60 540 GO TO 565 545 PRINT AT 21,16;TR-II: IF J$="E" OR J$="W" THEN GO TO 560: REM N-S TRICK ROUTINE 550 BEEP .25,30: IF TR-II=VAL K$+6 THEN BEEP 1,0 555 GO TO 565 560 BEEP .25,-20: IF TR-II=8-VAL K$ THEN BEEP 1,-60 565 LET TR=TR+1: IF TR=14 THEN GO TO 900 570 GO TO 345 575 LET L$=W$: GO TO 330: REM TO FOLLOW LEAD RATHER THAN LAST SUIT PLAYED 600 LET A$="01020304050607080910111213141516171819202122232425262728293031323334353637383940414243444546474849505152" 602 LET ED=0: DIM E$(16,10): DIM G$(16,10): REM WORKING AND RECORDING SUIT STRINGS 603 LET D$="AKQJ1098765432": LET V$=" " 605 DIM B$(52,2): DIM A(52) 610 FOR X=1 TO 52 615 LET R=(INT (RND*(53-X))+1)*2-1 620 IF LEN A$=2 THEN LET A(X)=VAL A$ 625 IF LEN A$=2 THEN RETURN 630 LET B$(X)=A$(R TO R+1) 635 LET A$=A$( TO R-1)+A$(R+2 TO ) 640 LET A(X)=VAL B$(X): REM CONVERT TO NUMBERS 645 NEXT X: REM SYNC 4:2,10 670 PRINT TAB 5;"PRACTICE BRIDGE HANDS"' 671 LET I$="\s\h\d\c": FOR I=1 TO 4: PRINT INK (2 AND (I=2 OR I=3));AT 1,I*4+5;I$(I): NEXT I 672 PRINT : PRINT "Decide how hand should be bid."'' 674 PRINT "Enter contract. Enter suit and" 676 PRINT "card to play hand. Forced plays" 678 PRINT "are automatic."'' 680 PRINT "Input denomination of spot cards" 682 PRINT "and initial letter of suits and" 684 PRINT "face cards; then press ENTER."'' 686 PRINT "Illegal inputs will not ENTER."'' 687 PRINT "To change unENTERED input, use" 688 PRINT "R/L arrows and retype."'' 689 PRINT "To return to trick 1, press ""X""."''' 690 GO SUB 600 694 FOR A=1 TO 40 STEP 13: GO SUB 100 695 NEXT A 696 PRINT "Press ""ENTER"" to deal hand." 697 INPUT U$ 699 CLS : GO TO 60 900 CLS : PRINT "Press R for a new deal." 905 PRINT "Press ""X"" for last hand." 910 IF INKEY$="X" THEN GO TO 920 912 IF INKEY$="R" THEN RUN 915 GO TO 910 920 CLS : GO TO 60 ```