--- title: "Kingdom" id: 57261 type: "computer_media" slug: "kingdom" url: "http://localhost/computer_media/kingdom/" markdown_url: "http://localhost/computer_media/kingdom.md" published_at: "2024-10-04T07:45:12+00:00" modified_at: "2026-04-03T07:58:39+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/10/149_King.png" excerpt: "Govern a medieval village through five years of floods, thieves, and famine in this multi-player resource-management game with seasonal turns and shared leaderboard." 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 1000" slug: "ts1000" taxonomy: "post_tag" url: "http://localhost/tag/ts1000/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" genre: - name: "Game" slug: "game" taxonomy: "genre" url: "http://localhost/type/game/" - name: "Resource Management" slug: "resource-management" taxonomy: "genre" url: "http://localhost/type/resource-management/" media_contents: - id: 56734 title: "Timex Sinclair Public Domain Library Tape 1003" type: "computer_media" url: "http://localhost/computer_media/timex-sinclair-public-domain-library-tape-1003/" media_type: "Program" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/10/149_King.png" media_type_tags: "Game, Resource Management" --- 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: 1. Lines 1–57: Title screen, rules display, player registration (`GOSUB 7000`), and array initialisation. 2. Lines 100–630: Main seasonal loop. `S` cycles 1–4 (seasons); `Y` counts years 1–5. The outer loop at line 170 iterates over players (`P`). 3. Lines 640–730: End-of-game winner announcement. 4. Lines 1000–1110: Flood/dyke subroutine. 5. Lines 2000–2180: Thieves/defence subroutine. 6. Lines 3000–3040: Starvation subroutine. 7. Lines 4000–4220: Corn-buying subroutine. 8. Lines 5000–5140: Corn-selling subroutine. 9. Lines 7000–7190: Player registration loop. 10. Lines 8000–8050: Pre-build screen background string in `FAST` mode. 11. Lines 9000–9010: `SAVE` and `RUN`. ### 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 than `Q(P)/2.2`. A random `K` (5–14) kills `K*10` people, destroys `K*15` sacks of corn, and fines the player money if `K>8`. A 1-in-3 chance of no event provides a random reprieve. - **Thieves (2000):** Triggered if defenders (`A3`) are fewer than `Q(P)/2.2`. Deducts people, corn, and money. Has a bug: uses `T` (the loop variable) instead of `RND` in 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=0` is inside a `FOR F=10 TO 21` loop with no `PRINT` or `SCROLL`, so it serves only to reset `Y` (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 the `PRINT` statement. - **Line 415:** Inside the labour-overflow loop (lines 414–416), `IF INT A3<>A3 THEN GOTO 410` is 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 of `RND` for the 1-in-3 reprieve, making the thieves event deterministic rather than random. - **Line 2088:**`PRINT EXP 10,16;` is clearly a typo for `PRINT 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 an `INPUT` statement 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 `REM` note from the author states “THIS PROGRAM CRASHES REPORT CODE 5/470”, referencing a crash at line 470 (`PRINT AT 0,0;M$`), likely due to `M$` being too long for a single `PRINT` statement. - **Line 705:**`POKE 16418,0` resets the system variable controlling the cursor position — an unusual direct memory write in an otherwise pure-BASIC program. ## 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 A1Q(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 ```