Kingdom is a multi-player resource-management game in which each player governs a village over five years (twenty seasons), balancing population, money, and corn while defending against floods, starvation, and thieves. Each turn players allocate workers to three jobs—dyke mending, planting, and defence—then deal with randomly triggered disasters. The program stores per-player state in parallel arrays (M, C, Q, D, N, Z, X, T) and uses string slicing on N$(A,11) to pack both a player’s name and gender code into a single dimensioned string. A notable optimisation at line 8000 pre-builds a 22-line screen image string in FAST mode before the game begins. The listing includes an embedded note at line 9005 acknowledging that the program crashes at line 470.
Program Analysis
Program Structure
The program is divided into a title/intro section, initialisation, a main game loop, and several subroutines:
- Lines 1–57: Title screen, rules display, player registration (
GOSUB 7000), and array initialisation. - Lines 100–630: Main seasonal loop.
Scycles 1–4 (seasons);Ycounts years 1–5. The outer loop at line 170 iterates over players (P). - Lines 640–730: End-of-game winner announcement.
- Lines 1000–1110: Flood/dyke subroutine.
- Lines 2000–2180: Thieves/defence subroutine.
- Lines 3000–3040: Starvation subroutine.
- Lines 4000–4220: Corn-buying subroutine.
- Lines 5000–5140: Corn-selling subroutine.
- Lines 7000–7190: Player registration loop.
- Lines 8000–8050: Pre-build screen background string in
FASTmode. - Lines 9000–9010:
SAVEandRUN.
Data Model
All per-player state is held in parallel numeric arrays dimensioned to A (number of players). The packed name/gender string array N$(A,11) uses the 11th character as a gender flag (‘M’ or ‘F’), with characters 1–10 holding the name proper. Slices like N$(P)(TO 10) and N$(P)(11) exploit ZX81-style string slicing to read back name and gender independently.
| Array | Meaning | Initial value |
|---|---|---|
M(A) | Money ($) | 1000 |
Q(A) | Population | 1000 |
C(A) | Corn (sacks) | 2500 |
D(A) | Corn planted this spring | — |
Z(A) | Flood casualties (display) | 0 |
X(A) | Starvation casualties (display) | 0 |
T(A) | Thief casualties (display) | 0 |
N(A) | New arrivals this season | — |
U(A) | Player age | — |
Seasonal / Year Loop
S is incremented each iteration of the outer player loop preamble (line 115) and wraps back to 0 at S=4 (line 150). Y is only incremented when S=1 (Spring, line 140), giving a clean year counter. The game ends when Y=5 at line 630.
Disaster Subroutines
Three randomly triggered disasters are evaluated each season per player. Each is called conditionally based on the player’s labour allocation:
- Floods (1000): Triggered if dyke workers (
A1) are fewer thanQ(P)/2.2. A randomK(5–14) killsK*10people, destroysK*15sacks of corn, and fines the player money ifK>8. A 1-in-3 chance of no event provides a random reprieve. - Thieves (2000): Triggered if defenders (
A3) are fewer thanQ(P)/2.2. Deducts people, corn, and money. Has a bug: usesT(the loop variable) instead ofRNDin the reprieve check at line 2010. - Starvation (3000): Triggered if corn planted is less than twice the population. Deaths equal the shortfall, capped at the total population.
Corn Economy
At the end of each season, corn is updated as C(P) = (C(P)/1.2) + D(P)*3 (line 535), meaning planted corn triples but existing stocks decay. If the total corn is below Q(P)*2, subroutine 4000 forces the player to buy corn at a random rate ($15–$19 per sack). If surplus exists, subroutine 5000 offers selling at $5–$9 per sack. Money grows automatically at 9% per season (line 580).
Screen Techniques
The program uses PRINT AT extensively for layout and scrolls the screen with a FOR/SCROLL/NEXT loop (22 iterations) rather than CLS, to avoid screen flicker between game phases. The subroutine at line 8000 pre-builds a 22-line background string M$ in FAST mode using inverse characters and ASCII art, then prints it in one statement at line 470 (PRINT AT 0,0;M$).
Centring of numeric output at lines 240–280 is achieved with a formula: TAB 15-(((LEN(STR$ value))+N)/2), where N accounts for the label length. This is an elegant approach to dynamic text centering without knowing the number’s width in advance.
Player Title Logic
Lines 190–200 determine the player’s title for display. The logic uses gender (character 11 of N$) and age (U(P)) to assign King/Queen/Prince/Princess. However, line 200 contains a bug: it tests N$(P)="F" against the full 11-character string rather than N$(P)(11)="F", so the Queen title will never be displayed correctly.
Input Validation
Labour allocations (lines 335, 375, 410) are validated with IF INT A1 <> A1 THEN GOTO to reject fractional inputs. The total labour check at line 412 ensures workers assigned don’t exceed population, looping back to re-display if over-allocated. The corn planting input (line 425) checks it doesn’t exceed available stocks.
Bugs and Anomalies
- Line 11 / lines 10–12:
LET Y=0is inside aFOR F=10 TO 21loop with noPRINTorSCROLL, so it serves only to resetY(the year counter) 12 times on the title screen — the loop body appears to be a remnant of a screen-clear attempt. - Line 200: Condition
N$(P)="F"tests the entire 11-character name string against a single character, so the Queen title is never triggered. - Line 280: The corn display is missing
C(P)— the format string prints" SACKS OF CORN."but the corn value itself is not included in thePRINTstatement. - Line 415: Inside the labour-overflow loop (lines 414–416),
IF INT A3<>A3 THEN GOTO 410is a stray validation check that has no effect since the loop is only entered after valid integer input. - Line 2010: Uses
T(the loop control variable from line 2030 if previously run, otherwise 0) instead ofRNDfor the 1-in-3 reprieve, making the thieves event deterministic rather than random. - Line 2088:
PRINT EXP 10,16;is clearly a typo forPRINT AT 10,16;, and would cause a syntax or runtime error. - Lines 5040–5070: The sell subroutine prints a prompt but never actually inputs a value —
A$is used at lines 5050 and 5070 but is never assigned by anINPUTstatement in this subroutine, so it retains whatever value it last held. - Line 7160:
INPUT H$appears twice (lines 7150 and 7160), requiring the player to confirm twice. - Line 9005: An inline
REMnote from the author states “THIS PROGRAM CRASHES REPORT CODE 5/470”, referencing a crash at line 470 (PRINT AT 0,0;M$), likely due toM$being too long for a singlePRINTstatement. - Line 705:
POKE 16418,0resets the system variable controlling the cursor position — an unusual direct memory write in an otherwise pure-BASIC program.
Content
Source Code
1 PRINT AT 3,7;"*****************"
2 PRINT AT 4,7;"* *"
3 PRINT AT 5,7;"* K I N G D O M *"
4 PRINT AT 6,7;"* *"
5 PRINT AT 7,7;"*****************"
6 PRINT AT 10,0;"YOU HAVE TO GOVERN A VILLAGE";AT 12,0;"FOR A PERIOD OF FIVE YEARS.YOU";AT 14,0;"MUST TRY TO KEEP ALIVE AS MANY"
7 PRINT AT 16,0;"PEOPLE AS POSSIBLE.THEY WILL DO";AT 18,0;"ONE OF THREE JOBS.";AT 20,0;"YOU MUST PROTECT THEM AGAINST.."
8 PRINT AT 21,5;"PRESS ANY KEY TO CONTINUE"
9 IF INKEY$="" THEN GOTO 9
10 FOR F=10 TO 21
11 LET Y=0
12 NEXT F
13 PRINT AT 10,0;"...(A)>=FLOODS";AT 11,0;"...(B)>=STARVATION";AT 12,0;"...(C)>=THIEVES";AT 14,0;"YOU HAVE TO BE AS RICH AS POSS.";AT 16,0;"AT THE END OF THE FIVE YEARS";AT 18,0;"AND THE RICHEST WINS."
14 PRINT AT 21,5;"PRESS ANY KEY TO CONTINUE"
15 IF INKEY$="" THEN GOTO 15
16 FOR F=10 TO 21
17 PRINT AT F,0;" "
18 NEXT F
19 PRINT AT 10,0;"HOW MANY PLAYERS? ";
20 INPUT A
21 PRINT A
22 DIM N$(A,11)
23 DIM U(A)
24 GOSUB 7000
34 PRINT AT 21,5;"PRESS ANY KEY TO START"
35 IF INKEY$="" THEN GOTO 35
36 FOR F=1 TO 22
37 SCROLL
38 NEXT F
39 GOSUB 8000
40 DIM M(A)
41 DIM C(A)
42 DIM Q(A)
43 FOR F=1 TO A
44 LET M(F)=1000
45 LET Q(F)=1000
46 LET C(F)=2500
47 NEXT F
48 DIM D(A)
49 DIM N(A)
50 DIM Z(A)
51 DIM X(A)
52 DIM T(A)
53 FOR F=1 TO A
54 LET Z(F)=0
55 LET X(F)=0
56 LET T(F)=0
57 NEXT F
100 REM START
105 LET S=0
115 LET S=S+1
120 IF S=1 THEN LET Y$="SPRING"
125 IF S=2 THEN LET Y$="SUMMER"
130 IF S=3 THEN LET Y$="AUTUMN"
135 IF S=4 THEN LET Y$="WINTER"
140 IF S=1 THEN LET Y=Y+1
150 IF S=4 THEN LET S=0
170 FOR P=1 TO A
175 LET N(P)=INT (RND*10)
176 LET Q(P)=Q(P)+N(P)
180 PRINT AT 0,9;Y$;" YEAR ";Y
190 IF N$(P)(11)="M" AND U(P)>18 THEN PRINT "KING ";N$(P)( TO 10)
193 IF N$(P)(11)="F" AND U(P)<=18 THEN PRINT "PRINCESS ";N$(P)( TO 10)
195 IF N$(P)(11)="M" AND U(P)<=18 THEN PRINT "PRINCE ";N$(P)( TO 10)
200 IF N$(P)="F" AND U(P)>18 THEN PRINT "QUEEN ";N$(P)( TO 10)
201 PRINT
202 PRINT N(P);" PEOPLE CAME TO THE VILLAGE."
203 PRINT
210 PRINT TAB 9;"CASUALTIES:"
211 PRINT " STARVED . FLOODS . THIEVES"
212 PRINT TAB 3;X(P);TAB 12;Z(P);TAB 22;T(P)
214 PRINT "********************************"
220 PRINT TAB 10;"YOU HAVE:"
240 PRINT TAB 15-(((LEN (STR$ M(P)))+2)/2);"$";M(P);","
260 PRINT TAB 15-(((LEN (STR$ Q(P)))+8)/2);Q(P);" PEOPLE,"
280 PRINT TAB 15-(((LEN (STR$ C(P)))+15)/2);" SACKS OF CORN."
290 PRINT "********************************"
300 PRINT "LABOR ARRANGEMENT:"
320 PRINT "(A) MENDING THE DYKE ";
330 INPUT A1
335 IF INT A1<>A1 THEN GOTO 330
340 PRINT A1
360 PRINT "(B) PLANTING CORN "
370 INPUT A2
375 IF INT A2<>A2 THEN GOTO 370
380 PRINT A2
400 PRINT "(C) DEFENDING THE VILLAGE "
409 INPUT A3
410 IF INT A3<>A3 THEN GOTO 409
411 PRINT A3
412 IF A1+A2+A3<=Q(P) THEN GOTO 420
413 PRINT AT 21,5;"TOO MANY PEOPLE"
414 FOR F=1 TO 22
415 IF INT A3<>A3 THEN GOTO 410
416 NEXT F
417 GOTO 180
420 IF Y$<>"SPRING" THEN GOTO 430
422 PRINT "HOW MANY SACKS OF CORN ARE TO";" BE PLANTED? ";
423 INPUT D(P)
424 PRINT D(P)
425 IF D(P)>C(P) THEN GOTO 422
426 LET C(P)=C(P)-D(P)
427 IF D(P)/10>A2 THEN LET D(P)=A2*10
430 PRINT AT 21,5;"PRESS ANY KEY TO CONTINUE"
440 IF INKEY$="" THEN GOTO 440
450 FOR F=1 TO 22
460 SCROLL
465 NEXT F
466 FAST
470 PRINT AT 0,0;M$
490 PRINT AT 8,14;"******";AT 9,14;"* *";AT 10,14;"* ++ *";AT 11,14;"* *";AT 12,14;"******"
500 PRINT AT 10,27;"T"
501 LET T(P)=0
502 LET Z(P)=0
503 LET X(P)=0
504 SLOW
510 IF A1<Q(P)/2.2 THEN GOSUB 1000
520 IF A3<Q(P)/2.2 THEN GOSUB 2000
530 IF D(P)<Q(P)*2 THEN GOSUB 3000
535 LET C(P)=(C(P)/1.2)+D(P)*3
540 IF C(P)+D(P)<Q(P)*2 THEN GOSUB 4000
550 IF C(P)+D(P)>Q(P)*2 THEN GOSUB 5000
560 LET Q(P)=Q(P)*1.2
565 LET Q(P)=INT (Q(P))
575 LET C(P)=INT (C(P))
580 LET M(P)=M(P)*1.09
583 LET M(P)=INT (M(P))
590 FOR F=1 TO 22
600 SCROLL
610 NEXT F
611 IF M(P)<0 THEN LET M(P)=0
612 IF C(P)<0 THEN LET C(P)=0
613 IF Q(P)<0 THEN LET Q(P)=0
620 NEXT P
630 IF Y<5 THEN GOTO 115
640 PRINT AT 0,0;"NOW FOR THE WINNER....."
644 LET W$=""
645 LET W=0
650 FOR F=1 TO A
660 PRINT N$(F)( TO 10);" WITH $";M(F);","
680 IF M(F)>W THEN LET W$=N$(F)( TO 10)
690 IF M(F)>W THEN LET W=M(F)
700 NEXT F
705 POKE 16418,0
710 PRINT AT 20,0,"CONGRATULATIONS",W$;" YOU ARE THE WINNER OF THE GAME WITH $";W
730 GOTO 10000
1000 REM DYKE
1010 IF INT (RND*3)+1=1 THEN RETURN
1020 LET K=INT (RND*10)+5
1030 FOR F=3 TO K+3
1040 FOR G=0 TO 21
1050 PRINT AT G,F;CHR$ 8
1060 NEXT G
1070 IF K*10>Q(P) THEN LET K=INT (Q(P)/10)
1080 LET Q(P)=Q(P)-K*10
1090 IF K>8 THEN LET M(P)=M(P)-((K-8)*100)
1095 LET Z(P)=K*10
1100 LET C(P)=C(P)-K*15
1110 RETURN
2000 REM DEF
2010 IF INT (T*3)+1=1 THEN RETURN
2020 LET K=INT (RND*10)+5
2025 IF K*6>Q(P) THEN LET K=INT (Q(P)/6)
2030 FOR F=27 TO 16 STEP -1
2040 PRINT AT 10,F;"T "
2050 NEXT F
2060 FOR F=1 TO K
2070 PRINT AT 10,16;". "
2080 PRINT EXP 10,16;"' "
2090 PRINT AT 10,16;" '"
2100 PRINT AT 10,16;" ."
2110 NEXT F
2120 FOR F=16 TO 27
2130 PRINT AT 10,F;" T"
2140 NEXT F
2150 LET Q(P)=Q(P)-K*6
2151 LET T(P)=K*6
2160 LET C(P)=C(P)-K*25
2170 LET M(P)=M(P)-K*15
2180 RETURN
3000 REM STAR
3010 LET K=ABS (D(P)-(Q(P)*2))
3015 IF K>Q(P) THEN LET K=Q(P)
3020 LET Q(P)=Q(P)-(INT (K))
3035 LET X(P)=K
3040 RETURN
4000 REM BUY
4010 LET K=INT (RND*5)+15
4020 FOR F=1 TO 22
4030 SCROLL
4040 NEXT F
4050 PRINT AT 0,0;"YOU HAVEN/T GOT ENOUGH CORN TO FEED ";"YOUR VILLAGE-YOU MUST BUY SOME..."
4060 PRINT
4070 PRINT "CURRENT BUYING RATE = ";K
4080 PRINT
4090 PRINT "YOU HAVE $";M(P)
4100 PRINT
4110 PRINT "THE MOST YOU CAN HAVE ARE ";INT (M(P)/K)
4120 PRINT "SACKS"
4140 PRINT "HOW MANY DO YOU WANT TO BUY?";
4150 INPUT I
4160 IF I>(M(P)/K) THEN GOTO 4140
4170 PRINT I
4180 PRINT
4190 PRINT "THAT WILLCOST $ ";I*K
4200 LET M(P)=M(P)-(K*I)
4210 LET C(P)=C(P)+1
4220 RETURN
5000 REM SELL
5010 FOR F=1 TO 22
5020 SCROLL
5030 NEXT F
5040 PRINT AT 0,0;"YOU HAVE A SURPLUS OF CORN.DO YOU";"WANT TO SELL ANY? IF SO, SPECIFY THE AMOUNT."
5050 IF A$(1)="N" THEN RETURN
5070 LET K=VAL A$
5071 IF K<=C(P) THEN GOTO 5080
5072 PRINT
5073 PRINT "YOU ONLY HAVE ";INT (C(P));" SACKS."
5074 IF INKEY$="" THEN GOTO 5074
5075 GOTO 5000
5080 LET J=INT (RND*5)+5
5090 PRINT K;" SACKS OF CORN AT"
5100 PRINT "$";J;" A SACK,WILL MAKE "
5110 PRINT "$";K*J
5120 LET M(P)=M(P)+K*J
5130 LET C(P)=C(P)-K
5140 RETURN
7000 FOR F=1 TO A
7010 CLS
7020 PRINT "PLAYER ";F
7030 PRINT
7040 PRINT "YOUR NAME PLEASE: "
7050 INPUT N$(F)
7051 PRINT N$(F)
7052 PRINT
7060 PRINT "YOUR AGE? ";
7070 INPUT U(F)
7080 PRINT U(F)
7090 PRINT
7100 PRINT "ARE MALE(M) OR FEMALE(F)? ";
7110 INPUT N$(F)(11)
7120 PRINT N$(F)(11)
7130 PRINT
7140 PRINT "O.K.? ";
7150 INPUT H$
7160 INPUT H$
7170 IF H$="NO" OR H$="NO" THEN GOTO 7010
7180 NEXT F
7190 RETURN
8000 FAST
8005 LET M$=""
8010 FOR F=1 TO 22
8020 LET M$=M$+"%A%A%A; % ; ;//////"
8030 NEXT F
8040 SLOW
8050 RETURN
9000 SAVE "1014%9"
9005 REM THIS PROGRAM CRASHES REPORT CODE 5/470
9010 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
