---
title: "Parchisi"
id: 55203
type: "computer_media"
slug: "parchisi"
url: "http://localhost/computer_media/parchisi/"
markdown_url: "http://localhost/computer_media/parchisi.md"
published_at: "2024-06-20T11:49:58+00:00"
modified_at: "2026-03-30T21:44:37+00:00"
author: "David Anderson"
featured_image:
url: "http://localhost/wp-content/uploads/2024/06/Parchisi.png"
excerpt: "A fully playable four-player Parcheesi board game with computer opponents, custom pawn graphics, and hex-encoded board paths packed into BASIC strings."
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/"
indiv:
- name: "Cedric Bastiaans"
slug: "bastiaans-cedric"
taxonomy: "indiv"
url: "http://localhost/indiv/bastiaans-cedric/"
genre:
- name: "Game"
slug: "game"
taxonomy: "genre"
url: "http://localhost/type/game/"
media_contents:
- id: 55220
title: "Long Island Sinclair Timex (LIST) User Group Library Tape #7"
type: "computer_media"
url: "http://localhost/computer_media/long-island-sinclair-timex-list-user-group-library-tape-7/"
media_type: "Program"
programmers:
- name: "Cedric Bastiaans"
slug: "bastiaans-cedric"
taxonomy: "indiv"
url: "http://localhost/indiv/bastiaans-cedric/"
download_url: "https://archive.org/download/timex-sinclair-software-archive/Parchisi%20%28198x%29%28Bastiaans%2C%20Cedric%3B%20Groothedde%2C%20Ferry%29%28TS2068%29%28US%29%28Program%29.zip"
mediadate: "198x"
images:
- url: "http://localhost/wp-content/uploads/2024/06/Parchisi.png"
- url: "http://localhost/wp-content/uploads/2024/06/Parchisi-2.png"
media_type_tags: "Game"
---
# Parchisi
This program implements a four-player Parcheesi-style board game called “Don’t Be Aggravated,” originally written in Dutch by Ferry Groothedde and translated/adapted by Cedric R. Bastiaans. The game supports zero, one, or two human players competing against computer-controlled opponents, with full rules including entering pawns on a six, capturing, and home-area movement. Board positions are encoded as two-digit hex coordinate pairs packed into strings (b$), allowing compact path representation for each of the four players’ routes around the 11×11 logical grid. Four custom UDG characters (\p, \i, \o, \n) are defined via POKE USR to render the pawn tokens graphically on the board. The computer AI uses a set of subroutines at lines 3000–3560 to evaluate blocking and capturing opportunities depending on the current die value.
***
## Program Analysis
### Program Structure
The program is organized into several functional blocks:
1. **Lines 1–5:** REMs, UDG initialization, and variable setup.
2. **Lines 10–50:** Board path encoding, player/pawn initialization, and welcome screen.
3. **Lines 70–180:** Board rendering using PRINT OVER.
4. **Lines 190–290:** Opening dice roll sequence to determine who starts.
5. **Lines 300–590:** Computer move subroutine (auto-play for non-human players).
6. **Lines 880–920:** No-move animation/fallthrough.
7. **Lines 1000–1380:** Human player move subroutine, including input handling and pawn movement logic.
8. **Lines 2000:** Error message for invalid move input.
9. **Lines 3000–3560:** AI helper subroutines checking blocking and capture positions by die value.
10. **Lines 4000–4080:** Entry of a new pawn onto the board on a roll of six.
11. **Lines 5000–5030:** Data initialization for die face display strings and coordinate look-up table.
12. **Lines 6000–6320:** Instructions display and number-of-players selection.
13. **Lines 7000–7040:** Main game loop dispatching turns to each of the four players.
14. **Lines 8000–8540:** Win detection, end-of-game messages, and restart/quit logic.
15. **Lines 9200–9330:** SAVE routine and UDG DATA definitions.
### Board Path Encoding
Each player’s route around the board is encoded in `b$(1)` through `b$(4)` as a string of two-digit decimal coordinate pairs packed without delimiters. For example, `b$(2)` begins `" 172737475758595a5b..."` — each pair of characters encodes one board row and one board column as hexadecimal-ish values readable by `VAL`. This allows the program to iterate over path positions with a simple `FOR p=2 TO 80 STEP 2` loop and evaluate `VAL b$(j,p)` and `VAL b$(j,p+1)` for row and column coordinates respectively.
Player paths 1, 3, and 4 are derived from player 2’s path by rotating the string slice — `b$(1)` is built from a substring of `b$(2)` offset by 20 positions, then the remaining segment, plus the home stretch. This rotation-by-substring technique avoids duplicating path data and keeps all four routes consistent.
### Board State Array
The 11×11 array `a()` tracks the board state. Each cell stores an integer encoding the occupant:
| Value | Meaning |
| --- | --- |
| 0 | Empty |
| 1–4 | Human player 4’s pawn number (s array index) |
| 5–8 | Computer/player piece (player index + 4) |
| 9 | Center/home marker (initialized at a(6,6)=9) |
| 11+ | Human player 2’s pawn (t array index + 10) |
Pawn positions for the computer players (1 and 3) are stored only in `a()` directly; human players additionally maintain explicit position indices in arrays `s()` (player 4) and `t()` (player 2) that record how far along the path each pawn has traveled.
### Custom UDG Characters
Lines 9300–9330 define four UDGs named `\p`, `\i`, `\o`, and `\n` using DATA statements. Line 4 loads them with `FOR f=1 TO 4: READ a$: FOR g=0 TO 7: READ A: POKE USR a$+g,A: NEXT g: NEXT f`. These four characters together form a 2×2 tile representing a pawn token on the board and are printed with color attributes (`PAPER k(j)` and `INK`) to distinguish the four players visually.
### Variable Aliasing for Code Compression
The program makes heavy use of small integer variables as aliases to reduce token repetition:
- `e=1` — used ubiquitously wherever the literal 1 would appear, saving one byte per use.
- `a=10`, `b=11` — used as row/column constants and in arithmetic thresholds.
- `j=4` — initially set as the number of players but reused as a loop variable in the main game loop.
This is a well-known Sinclair BASIC optimization: assigning frequently used constants to single-letter variables reduces the size of each tokenized line.
### Die Face Display
Die faces are rendered as 3-character ASCII art using `d$()` initialized at line 5010 with dot patterns. The `e$()` array at line 5020 stores three-digit strings such as `"525"`, `"153"`, etc., where each digit indexes into `d$()` to select the correct row of the die face for values 1–6. This allows a three-line die face to be printed with a single `FOR p=1 TO 3` loop using `d$(VAL e$(z,p))`.
### Player Turn Dispatch
The main loop at line 7000 iterates `j` from 1 to 4. The variable `sp` (set at line 6310 as `CODE s$ - CODE "1"`) encodes how many humans are playing: `sp=-1` means zero humans (computer vs. itself), `sp=0` means one human, `sp=1` means two humans. Turn routing is:
- Player 1 (`j=1`) and Player 3 (`j=3`): always GO SUB 3000 (computer AI).
- Player 2 (`j=2`): GO SUB 300 (computer) or GO SUB 1000 (human) based on `sp`.
- Player 4 (`j=4`): always GO SUB 1000 (human or overridden by sp=-1).
### AI Subroutines (Lines 3000–3560)
The computer AI uses a table of subroutines spaced 50 lines apart, dispatched by `GO SUB 2900+100*s` or `GO SUB 2950+100*s` where `s` is the die value. Each subroutine checks a specific board cell to determine whether a capture or block is possible, updating the local variable `v` with the recommended pawn to move. The duplication across lines 3000–3560 — with pairs of subroutines for each die value — reflects the two different home-stretch entry positions for players 2 and 4.
### Key BASIC Idioms
- `PAUSE 0` followed by `INKEY$` — standard keypress wait idiom appearing at lines 10, 6055, 6310.
- `INPUT ""` — used to flush the keyboard buffer or force a pause at several points.
- `AND` used as a conditional multiplier: e.g. `"both " AND sp` at line 8010 prints the word “both” only when `sp` is nonzero.
- `GO TO VAL"number"` is not present, but `VAL b$(j,p)` is used to dereference packed coordinate data inline.
- `NOT LEN INKEY$` / `LEN INKEY$` pairs for key-down detection loops (lines 210–235, 1060).
### Anomalies and Notable Points
- Line 70 uses `PRINT OVER e` (i.e., OVER 1) to draw board path markers as `/\ \/` two-character pairs — the OVER mode allows overlaying without erasing previously drawn content.
- Line 550 references `"\p\i"` and `"\o\n"` as UDG character pairs for the 2×2 pawn tile, printed with per-player color attributes set inline.
- Lines 8000, 8100, 8200 each begin with `INPUT ""` suggesting they are reached as fall-through targets rather than clean subroutine calls; GO TO jumps from the move subroutines land here directly.
- The `d$(5)` row is defined but never referenced, as die values only run 1–6 and `e$()` only uses rows 1–4 of `d$()`.
- Lines 6022 and 6024 contain color attribute placeholders mid-string that appear as blank spaces in the listing — these would display colored ink swatches on the actual hardware to illustrate player colors.
## Source Code
```
1 REM PARCHISI-LIKE GAME
2 REM Written by Ferry Groothedde; authorized translation by CedricBastiaans (only for use by members of the L.I.S.T. group)
3 REM RESET "SINCLAIR GEBRUIKER", a Dutch computer magazine; \* F.Groothedde; \* C.R.Bastiaans
4 FOR f=1 TO 4: READ a$: FOR g=0 TO 7: READ A: POKE USR a$+g,a: NEXT g: NEXT f
5 LET e=1: GO SUB 5000: LET a=10: LET b=11: BRIGHT e: PAPER e: CLS : INK 9: BORDER e: LET u$=" ": FOR p=e TO 6: LET u$(p)=CHR$ 8: NEXT p
10 LET j=4: DIM a(b,b): DIM b$(j,96): LET a(6,6)=9: PRINT "Welcome to""DON'T BE AGGRAVATED!""";'"A Dutch Parcheesi-like Boardgame": PRINT : PRINT " Written by \*Ferry Groothedde";'" Authorized Translation and";'" Adaptation"'" by \*Cedric R. Bastiaans";AT 21,0;"Need Instructions? (Y/N)": PAUSE 0: GO SUB 6000+(310 AND (INKEY$="n" OR INKEY$="N"))
20 LET b$(2)=" 172737475758595a5b6b7b7a7978778797a7b7b6b5a59585757473727161515253545545352515162636465666666666"
30 LET b$(e)=" "+b$(2,62 TO 81)+b$(2,2 TO 61)+"626364656666666666666666"
40 LET b$(3)=" "+b$(e,42 TO 81)+b$(e,2 TO 41)+"6a696867666666666666"
50 LET b$(4)=" "+b$(2,42 TO 81)+b$(2,2 TO 41)+"a69686766666666666666"
70 FOR p=2 TO 80 STEP 2: PRINT OVER e;AT 2*VAL b$(j,p)-2,2*VAL b$(j,p+e);"/\\ \\/": NEXT p
100 FOR p=2 TO 19: PRINT OVER e;AT p,12;"##": NEXT p: PRINT AT a,4;"######## ########";AT b,4;"######## ########"
130 DIM k(4): DIM s(4): DIM t(4): DIM x(4): DIM y(4)
150 FOR p=e TO 4: LET y(p)=4: NEXT p
160 PRINT OVER e;AT e,3;"4";TAB 22;"4";AT 20,3;"4";TAB 22;"4"
170 LET k(2)=4: LET k(3)=6: LET k(4)=2: LET k(e)=7
180 PRINT OVER e;AT 0,2;" ";TAB 21;" ";AT 2,2;" ";TAB 21;" ";AT 19,2;" ";TAB 21;" ";AT 21,2;" ";TAB 21;" "
190 PRINT #e;AT 0,0;"Highest throw starts game ( / ) throws";
210 IF NOT LEN INKEY$ THEN GO TO 210
215 IF LEN INKEY$ THEN GO TO 215
220 BEEP .1,b: LET s=INT (RND*6+e): PRINT #e;s," throws ";
230 IF sp AND NOT LEN INKEY$ THEN GO TO 230
235 IF LEN INKEY$ AND sp THEN GO TO 235
240 BEEP .1,b: LET z=INT (RND*6+e): PRINT #e;z
250 FOR p=-b TO 50: BEEP .02,p: NEXT p: INPUT "": IF s=z THEN GO TO 190
260 FOR j=2 TO 4: IF j=2 AND s>z THEN LET j=4
270 IF j=4 OR (j=2 AND sp) THEN GO SUB 1000
280 IF j=3 OR (j=2 AND NOT sp) THEN GO SUB 300
290 NEXT j: GO TO 7000
300 LET z=INT (RND*6+e)
310 FOR p=e TO 3: PRINT PAPER k(j); INK 9;AT p+9,27;d$(VAL e$(z,p)): NEXT p
320 IF z=6 THEN FOR p=e TO 100: NEXT p
330 LET v=0: LET w=v
350 IF y(j) AND z=6 THEN GO TO 4000
360 IF x(j)+y(j)=4 THEN GO TO 880
370 FOR p=80 TO 2 STEP -2: LET st=a(VAL b$(j,p),VAL b$(j,p+e))
380 IF st<>j+4 THEN GO TO 430
390 LET dl=a(VAL b$(j,p+2*z),VAL b$(j,e+p+2*z))
400 IF dl=a-e THEN GO TO 430
410 IF dl<>j+4 THEN LET v=p
420 IF (p+2*z>80 AND NOT dl) OR (p=2 AND NOT dl) OR (dl AND dl<>j+4) THEN LET w=p
430 NEXT p: IF NOT v THEN GO TO 880
440 IF w THEN LET v=w
450 IF v+2*z>80 THEN LET x(j)=x(j)+e
470 LET aa=VAL b$(j,v): LET aaa=VAL b$(j,v+e): LET ab=VAL b$(j,v+2*z): LET abb=VAL b$(j,v+e+2*z)
500 LET a(aa,aaa)=0: LET aq=a(ab,abb)
510 IF aq<9 AND aq>4 THEN LET y(aq-4)=y(aq-4)+e
520 IF aq>a THEN LET t(aq-a)=0: LET y(2)=y(2)+e
530 IF aq AND aq<5 THEN LET s(aq)=0: LET y(4)=y(4)+e
540 LET a(ab,abb)=j+4
550 PRINT AT 2*aa-2,2*aaa;"/\\";AT 2*aa-e,2*aaa;"\\/": BEEP .1,RND*b: PRINT AT e,3;y(e);AT e,22;y(2);AT 20,3;y(4);AT 20,22;y(3);AT 2*ab-2,2*abb; INK j=e; PAPER k(j);"\p\i";AT 2*ab-e,2*abb;"\o\n": BEEP .1,RND*b
560 IF x(j)=4 THEN GO TO 8000
580 IF z=6 THEN RANDOMIZE : GO TO 300
590 RETURN
880 FOR p=e TO 100: NEXT p
900 FOR p=e TO 3: PRINT PAPER 0; OVER e; INVERSE e;AT p+a-e,27;" ": NEXT p
910 BEEP e,-RND*b: IF z=6 THEN RANDOMIZE : GO TO 300
920 RETURN
1000 IF sp=-e THEN GO TO 300
1010 LET s=INT (RND*6+e)
1020 FOR p=e TO 3: PRINT PAPER k(j); INK 9;AT p+9,27;d$(VAL e$(s,p)): NEXT p
1050 PRINT #e;AT e,e; INVERSE e;"Your move? (0=No Move Possible)"
1060 IF LEN INKEY$ THEN GO TO 1060
1070 LET u$=INKEY$: IF u$<"0" OR u$>"4" THEN GO TO 1070
1080 INPUT "": BEEP .05,a: LET v=VAL u$: IF v THEN GO TO 1200
1100 IF s=6 THEN GO TO 1000+(50 AND y(j))
1120 RETURN
1200 IF s<6 AND NOT (s(v) AND j=4)+(t(v) AND j=2) THEN GO TO 1050
1202 IF j=4 AND a(b,5) AND a(b,5)<5 THEN GO SUB 2900+100*s
1203 IF j=2 AND a(e,7)>=a THEN GO SUB 2950+100*s
1205 IF (s(v) AND j=4)+(t(v) AND j=2)+s>44 OR (s(v) AND j=4)+(t(v) AND j=2)>40 THEN GO TO 1050
1207 IF j=4 THEN IF s<6 OR NOT y(j) OR (a(b,5) AND a(b,5)<5) THEN GO TO 1260
1208 IF j=2 THEN IF s<6 OR NOT y(j) OR a(e,7)>a THEN GO TO 1280
1210 IF (t(v) AND j=2) OR (s(v) AND j=4) THEN GO TO 2000
1215 BEEP e,b: IF j=2 THEN GO TO 1230
1220 LET s(v)=e: LET y3=b: LET y4=5: GO TO 1240
1230 LET t(v)=e: LET y3=e: LET y4=7
1240 LET y(j)=y(j)-e: PRINT AT 20,3;y(4);AT e,22;y(2): LET l=a(y3,y4): GO TO 1335
1260 LET y1=VAL b$(j,2*s(v)): LET y2=VAL b$(j,e+2*s(v)): LET y3=VAL b$(j,2*(s+s(v))): LET y4=VAL b$(j,e+2*(s+s(v)))
1270 GO TO 1300
1280 LET y1=VAL b$(j,2*t(v)): LET y2=VAL b$(j,e+2*t(v)): LET y3=VAL b$(j,2*(s+t(v))): LET y4=VAL b$(j,e+2*(s+t(v)))
1300 LET l=a(y3,y4)
1305 IF (l AND l<5 AND j=4) OR (l>a AND j=2) THEN GO TO 1050
1310 PRINT AT 2*y1-2,2*y2;"/\\";AT 2*y1-e,2*y2;"\\/"
1320 LET a(y1,y2)=0: IF j=2 THEN LET t(v)=t(v)+s: LET x(j)=x(j)+(t(v)>40): GO TO 1335
1330 LET s(v)=s(v)+s: LET x(j)=x(j)+(s(v)>40)
1335 IF l>a THEN LET t(l-a)=0: LET y(2)=y(2)+e
1337 IF l>4 AND l4 THEN LET v=a(b,5)
3010 RETURN
3050 IF a(2,7)4 THEN LET v=a(b,5)
3110 RETURN
3150 IF a(3,7)4 THEN LET v=a(b,5)
3210 RETURN
3250 IF a(4,7)4 THEN LET v=a(b,5)
3310 RETURN
3350 IF a(5,7)4 THEN LET v=a(b,5)
3410 RETURN
3450 IF a(5,8)4 THEN LET v=a(b,5)
3510 RETURN
3550 IF a(5,9)a THEN LET t(aa-a)=0: LET y(2)=y(2)+e
4040 IF aa>4 AND aae THEN GO TO 6310
6320 CLS : RETURN
7000 RANDOMIZE : FOR j=e TO 4
7010 IF j=e OR j=3 THEN GO SUB 3000
7020 IF j=2 THEN GO SUB 300+(700 AND sp)
7030 IF j=4 THEN GO SUB 1000
7040 NEXT j: GO TO 7000
8000 IF sp=-e THEN GO TO 8500
8010 INPUT "": PRINT #e;AT 0,0;"You have ";"both " AND sp;"lost the game": GO TO 8500
8100 INPUT "": PRINT #e;AT 0,0;" has won the game!": GO TO 8500
8200 INPUT "": IF sp THEN PRINT #e;AT 0,0;" has won the game!": GO TO 8500
8210 PRINT #e;AT 0,0;"You have won the game!"
8500 PRINT #e;AT e,0;"Another game? (y/n)",
8510 IF LEN INKEY$ THEN GO TO 8510
8520 IF NOT LEN INKEY$ THEN GO TO 8520
8530 IF INKEY$="n" OR INKEY$="N" THEN NEW
8540 RUN
9200 CLEAR : SAVE "parchisi" LINE 1: VERIFY ""
9300 DATA "\p",255,255,254,252,252,254,254,252
9310 DATA "\i",255,255,63,31,31,63,63,31
9320 DATA "\o",252,248,248,240,240,224,255,255
9330 DATA "\n",31,15,15,7,7,3,255,255
```