--- title: "Kingdom" id: 64771 type: "computer_media" slug: "kingdom-2" url: "http://localhost/computer_media/kingdom-2/" markdown_url: "http://localhost/computer_media/kingdom-2.md" published_at: "2026-03-08T00:24:24+00:00" modified_at: "2026-03-30T21:43:25+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2026/03/Kingdom-3.png" excerpt: "A five-year kingdom management game where players juggle floods, famine, and thieves — with animated raiders and a market economy — to become the wealthiest ruler." 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: "Paul Holmgren" slug: "paul-holmgren" taxonomy: "indiv" url: "http://localhost/indiv/paul-holmgren/" 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" programmers: - name: "Paul Holmgren" slug: "paul-holmgren" taxonomy: "indiv" url: "http://localhost/indiv/paul-holmgren/" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2026/03/Kingdom-3.png" - url: "http://localhost/wp-content/uploads/2026/03/Kingdom-2.png" - url: "http://localhost/wp-content/uploads/2026/03/Kingdom.png" media_type_tags: "Game" --- # Kingdom Successfully manage your kingdom for 10 years to win. Kingdom is a multi-player resource-management strategy game in which 1–4 players govern medieval kingdoms over five in-game years, each divided into four seasons. Each turn, players allocate their population among three tasks — mending dykes (flood prevention), planting grain, and defending against thieves — then face randomised consequences including floods, starvation, and raids. The program uses string arrays to store player names and a gender/age field to assign titles (King/Queen/Prince/Princess), and builds a scrolling landscape string in line 1360 by repeatedly tripling a base string. Two UDGs are defined from DATA for animated thief sprites, and a third UDG (“s”) is loaded for a separate graphic used during the introduction. A variation of [Hamurabi](https://en.wikipedia.org/wiki/Hamurabi_(video_game)). *** ## Program Structure The program is organised into a main loop and a collection of subroutines reached via `GO SUB` or `GO TO`. Execution begins at line 10 with a `GO TO 1130` that skips to the setup block. The main game loop runs from line 50 to line 530, iterating over all players with a `FOR p=1 TO a` loop each season. 1. **Lines 10–40:** REM header, startup jump, shared utility subroutines (keypress wait, screen clear). 2. **Lines 50–530:** Main seasonal loop — season/year tracking, per-player turn, labour allocation, consequence resolution. 3. **Lines 540–820:** Event subroutines — dyke failure (floods), defence failure (thieves), starvation. 4. **Lines 830–1120:** Economy subroutines — starvation deaths, grain buying, grain selling. 5. **Lines 1130–1480:** Setup, title screen, UDG loading, player data entry, initial resource assignment. 6. **Lines 1490–1590:** Winner determination and display; line 1590 is a `SAVE` statement that auto-runs the program. 7. **Lines 1600–1680:** Small utility subroutines: title assignment by gender/age, labour-overflow warning, spring planting input. ## Data Structures and Arrays | Array | Dimensions | Purpose | | --- | --- | --- | | `n$(a,11)` | a × 11 chars | Player name (cols 1–10) and gender flag (col 11) | | `u(a)` | a | Player ages (used for title selection) | | `m(a)` | a | Money (dollars) | | `c(a)` | a | Grain sacks | | `p(a)` | a | Population | | `d(a)` | a | Sacks of grain planted in spring | | `n(a)` / `N(a)` | a | Random newcomers arriving each season | | `z(a)` | a | Flood casualties display counter | | `x(a)` | a | Starvation casualties display counter | | `t(a)` | a | Thief casualties display counter | Players start each game with `c(p)=2500` sacks of grain, `m(p)=1000` dollars, and `p(p)=1000` people (line 1380–1400). ## UDG Definition and Animation Three UDGs are defined by reading bytes from `DATA` statements. Lines 1220–1230 load UDGs `"a"` and `"b"` simultaneously from interleaved data (16 bytes, alternating). Line 1260 loads UDG `"s"` from a third set of 8 bytes. The thief animation in lines 680–780 alternates between `\a` and `\b` characters with short `PAUSE` delays to create a two-frame walking sprite moving across the screen horizontally. ## Landscape String Construction Line 1350 initialises `m$` with a 32-character base string of block graphics and caret characters. Line 1360 expands it by tripling it three times in a loop, then truncates to 838 characters with `m$=m$( TO 838)`. This landscape is printed at line 370 as a scrolling backdrop. The expansion method — `m$=m$+m$+m$` repeated — is an efficient way to build a long repeating string without a character-by-character loop. ## Variable Case Ambiguity Bug The Spectrum’s BASIC is case-sensitive for string variables but not for numeric ones. The program uses `n(p)` and `N(p)` interchangeably (lines 110 and 120), which refer to the same numeric array. However, `a1`, `a2`, `a3` (lowercase) at lines 240–330 are used in computations, while the `READ g$` at line 290 compares against `G$` (uppercase) — on the Spectrum these are the same string variable, so this works correctly. The `A$` used in the sell routine (lines 1020–1040) is distinct from `a$` used in line 1040 itself; this inconsistency could cause a mismatch on strict interpreters. ## Season and Year Tracking The variable `s` cycles 1–4 representing Spring through Winter. Line 70 resets `s` to 0 (via `NOT s`, which evaluates to 0 when `s` is non-zero) after Winter, and line 50 increments it at the start of each pass. Line 80 increments the year counter `y` only in Spring. After five years the game ends at line 90 with a jump to the winner screen at 1490. ## Season Name Assignment Line 60 uses a Spectrum BASIC idiom for conditional string selection: `LET y$=("Spring" AND s=1)+("Summer" AND s=2)+("Autumn" AND s=3)+("Winter" AND s=4)` Each parenthesised expression evaluates to the string if the condition is true, or the empty string `""` if false; the `+` operator concatenates them, yielding exactly one season name. ## Title Assignment by Gender and Age Subroutines at lines 1600–1610 use the same string-AND idiom to assign a title to each player’s ruler. Gender is stored in character position 11 of `n$(p)` and age in `u(p)`. Players over 18 receive “King”/”QUEEN”; 18 or under receive “Prince”/”Princess”. Note the inconsistent capitalisation: “QUEEN” is all-caps while “King” is title-case. ## Labour Allocation and Validation Players input workers for each of three tasks (lines 240–330). Line 340 checks whether the total exceeds population: `IF a1+a2+a3>p(p) THEN GO SUB 1620`. The subroutine at 1620 prints a warning and returns to line 130 via `GO TO 130` rather than `RETURN`, effectively restarting the turn for that player without re-initialising their state — a crude error recovery. ## Planting Prompt Bug Line 1630 contains a visible typo in the prompt string: `"Pl LLIST nt how many sacks of grain?"` — “Plant” has been corrupted to “Pl LLIST nt”, likely because the author typed the BASIC keyword `LLIST` accidentally mid-word while entering the string. ## Flood Animation Lines 570–590 animate a flood by printing solid-block characters (`█`) column by column across the screen using a nested loop. The width of the flood (`k`) is determined randomly (line 550) and capped at a fraction of the population (line 600). Casualties scale linearly with flood width: 10 people per flood-column, plus financial and grain losses for severe floods. ## Market Economy The grain market uses a randomly generated price each transaction (lines 890 and 1070). The buy price ranges from $13–$17 per sack, while the sell price ranges from $5–$9 — ensuring players always sell at a loss relative to buying, which discourages over-planting. Line 980 adds only 1 sack regardless of how many were purchased (`LET c(p)=c(p)+1`), which appears to be a bug; it should read `LET c(p)=c(p)+i`. ## Winner Determination Lines 1510–1560 iterate over all players and find the maximum `M(p)` value using a running maximum pattern. `w` is initialised to `NOT a`, which evaluates to 0 when `a>0` — a slightly obscure way to write zero. The winner’s name is stored in `W$` and displayed with `FLASH 1` formatting at line 1570. ## READ/RESTORE for Crop Names Line 290 reads sequentially from `DATA` at line 1290 containing crop names ending with the sentinel `"E"`. When the sentinel is encountered, `RESTORE 1290` resets the data pointer and the read is repeated, creating a cycling list. This means each player’s turn uses the next crop name in sequence — “corn”, “wheat”, “rice”, “rye”, “barly” (note spelling) — cycling indefinitely. ## Source Code ``` 10 REM KINGDOM 20 CLS : GO TO 1130 30 PRINT AT 21,4; FLASH 1;"TAP ANY KEY TO CONTINUE ": PAUSE 0: RETURN 40 FOR f=21 TO 9 STEP -1: PRINT AT f,0;" ": NEXT f: RETURN 50 LET s=s+1: REM START 60 LET y$=("Spring" AND s=1)+("Summer" AND s=2)+("Autumn" AND s=3)+("Winter" AND s=4) 70 IF s=4 THEN LET s=NOT s 80 IF s=1 THEN LET y=y+1 90 IF y>5 THEN GO TO 1490 100 FOR p=1 TO a 110 LET N(p)=INT (RND*10) 120 LET p(p)=p(p)+n(p): CLS 130 PRINT TAB 8;y$;" of Year ";y 140 IF n$(p,11)="m" OR n$(p,11)="M" THEN GO SUB 1600 150 IF n$(p,11)="f" OR n$(p,11)="F" THEN GO SUB 1610 160 PRINT r$;n$(p, TO 10)'n(p);" People came to the village." 170 PRINT TAB 10;"Casualities:","Starved . Floods . Thieves" 180 PRINT " ";x(p);TAB 12;z(p);TAB 22;t(p): LET x=RND*6 190 PRINT INK X;"********************************" 200 PRINT TAB 10;"You have:";TAB 16-(LEN STR$ m(p))+2/2;"$";m(p);"," 210 PRINT TAB 16-(LEN STR$ p(p)+8)/2;p(p);" People." 220 PRINT TAB 16-(LEN STR$ c(p)+15)/2;c(p);" Sacks of grain." 230 PRINT INK X;"********************************"; INK 0;"Labor arrangement:" 240 INPUT "Mending the dyke? ";a1 250 IF INT a1<>a1 THEN GO TO 240 260 PRINT "(A).Mending the dyke";TAB 31-(LEN STR$ a1);a1 270 INPUT "Planting grain? ";a2 280 IF INT a2<>a2 THEN GO TO 270 290 READ g$: IF G$="E" THEN RESTORE 1290: GO TO 290 300 PRINT "(B).Planting the ";G$;TAB 31-(LEN STR$ a2);a2 310 INPUT "Defending the Kingdom? ";a3 320 IF INT a3<>a3 THEN GO TO 310 330 PRINT "(C).Defending Kingdom";TAB 31-(LEN STR$ a3);a3 340 IF a1+a2+a3>p(p) THEN GO SUB 1620 350 IF y$="Spring" THEN GO SUB 1630 360 GO SUB ph: CLS 370 PRINT 'm$; INK 0 ;AT 8,14;"▛▀▀▀▀▜";AT 9,14;"▌ ▐";AT 10,14;"▌ "; INK 6;"^^"; INK 0;" ▐";AT 11,14;"▌ ▐";AT 12,14;"▙▄▄▄▄▟" 380 PRINT AT 10,28;"\a" 390 LET t(p)=0: LET z(p)=0: LET x(p)=0 400 IF a1p(p)*2 THEN GO SUB 1000 450 IF c(p)+d(p)p(p) THEN LET k=INT (p(p)/10) 610 LET p(p)=p(p)-k*10 620 IF k>8 THEN LET m(p)=m(p)-(k-8)*100 630 LET z(p)=k*10 640 LET c(p)=INT (c(p)-k*15): RETURN 650 IF INT (RND*3)+1=1 THEN RETURN : REM DEFEND 660 LET k=INT (RND*10)+5 670 IF k*6>p(p) THEN LET k=INT p(p)/6 680 FOR n=28 TO 16 STEP -1 690 PRINT AT 10,n;"\a ": PAUSE 5 700 PRINT AT 10,n;"\b ": PAUSE 5 710 NEXT n 720 FOR n=1 TO k 730 PRINT AT 10,16;"@": PAUSE 9: PRINT AT 10,16;"©": PAUSE 5 740 NEXT n 750 FOR n=16 TO 27 760 PRINT AT 10,n;" \s\a": PAUSE 3 770 PRINT AT 10,n;" \s\b": PAUSE 3 780 NEXT n 790 LET p(p)=p(p)-k*6 800 LET c(p)=c(p)-k*25 810 LET m(p)=m(p)-k*15 820 LET t(p)=k*6: RETURN 830 REM STARVE 840 LET k=ABS (d(p)-p(p)*2) 850 IF k>p(p) THEN LET k=p(p) 860 LET p(p)=p(p)-INT k 870 LET x(p)=k: RETURN 880 REM BUY 890 LET k=INT (RND*5)+13: CLS 900 PRINT n$(p, TO 10)''"You haven""t got enough grain to feed your village-You must buy some on the Common Market..." 910 PRINT '"Current Market rate = $";k 920 PRINT '"You have $";m(p) 930 PRINT '"You can buy ";INT (m(p)/k);" sacks." 940 INPUT "How many do you wish to buy? ";i 950 IF i>m(p)/k THEN GO TO 940 960 PRINT i;" sacks will cost $";i*k 970 LET m(p)=m(p)-k*i 980 LET c(p)=c(p)+1 990 GO SUB ph: RETURN 1000 REM sell 1010 CLS : PRINT n$(p, TO 10)''"You have surplus grain. Do you wish to sell any, if so input the amount. "; FLASH 1;"N= none" 1020 INPUT "I am selling "; LINE A$ 1030 IF A$(1)="N" OR A$(1)="n" THEN RETURN 1040 IF a$="a" THEN LET a$=STR$ INT c(p) 1050 LET k=VAL a$: IF k<=INT c(p) THEN GO TO 1070 1060 PRINT ''"You can not sell that much at this time.": GO SUB ph: GO TO 1000 1070 LET j=INT (RND*5)+5 1080 PRINT k;" sacks of grain, at $";j 1090 PRINT "a sack, making","$";k*j 1100 LET m(p)=m(p)+k*j 1110 LET c(p)=c(p)-k 1120 GO SUB ph: RETURN 1130 REM SETUP 1140 LET s=0: LET y=s 1150 LET ph=30 1160 PRINT '" "; FLASH 1;"A ""PEH SOFTWARE"" SPECIAL" 1170 PRINT ''; INK 1;" *****************"," * *" 1180 PRINT " * K i n g d o m *"," * *" 1190 PRINT INK 1;" *****************"'' INK 0;" You have 5 years to govern your"''"kingdom. You must try to keep"''"alive as many of your serfs as" 1200 PRINT '"possible, they have 3 jobs."''"You must protect them against" 1210 GO SUB ph: GO SUB 40 1220 DATA 24,24,24,24,231,36,36,100,36,189,24,24,36,36,66,36,0,0,0,0,255,255,102,102 1230 FOR d=0 TO 7: READ r: POKE USR "a"+d,r: READ r: POKE USR "b"+d,r: NEXT d 1240 PRINT "...(A) FLOODS"'"...(B) STARVATION"'"...(C) THIEVES" 1250 PRINT '"You have to be the richest"''"player after 5 years to "; FLASH 1;"WIN"; FLASH 0;"." 1260 FOR d=0 TO 7: READ r: POKE USR "s"+d,r: NEXT d 1270 GO SUB ph: GO SUB 40 1280 INPUT "How many are playing ";a 1290 DATA "corn","wheat","rice","rye","barly","E" 1300 DIM n$(a,11): DIM u(a) 1310 DIM M(a): DIM C(a) 1320 DIM P(a): DIM D(a) 1330 DIM N(a): DIM Z(a) 1340 DIM x(a): DIM t(a) 1350 LET m$="██████████████████████████^^^^^^" 1360 FOR f=1 TO 3: LET m$=m$+m$+m$: NEXT f: LET m$=m$( TO 838) 1370 FOR p=1 TO a 1380 LET c(p)=2500 1390 LET m(p)=1e3 1400 LET p(p)=m(p) 1410 INPUT "Who are you? "; LINE n$(p) 1420 INPUT "How old are you? ";u(p) 1430 INPUT "Are you ""M"" OR ""F"" "; LINE n$(p,11) 1440 PRINT "Palyer No. ";p'n$(p, TO 10);" age = ";u(p);" sex = ";n$(p,11) 1450 INPUT "Is this O.K.? (Y/N) "; LINE h$ 1460 IF h$(1)="n" THEN GO TO 1410 1470 NEXT p 1480 GO TO 50 1490 REM WINNER 1500 PRINT '"AND NOW FOR THE "; FLASH 1;"WINNER" 1510 LET W$="": LET w=NOT a 1520 FOR P=1 TO A 1530 PRINT N$(P, TO 10);" WITH $";M(P);"," 1540 IF M(p)>w THEN LET W$=N$(p, TO 10) 1550 IF M(p)>w THEN LET W=M(p) 1560 NEXT p 1570 PRINT AT 10,0; FLASH 1;"Congratulations ";W$'' FLASH 0;"You are the "; FLASH 1;"WINNER"; FLASH 0;" of the game"''"with $";W 1580 STOP 1590 SAVE "Kingdom" LINE 10 1600 LET r$=("King " AND u(p)>18)+("Prince " AND u(p)<=18): RETURN 1610 LET r$=("QUEEN " AND u(p)>18)+("Princess " AND u(p)<=18): RETURN 1620 PRINT AT 20,3; INK 2;"Too many people": GO SUB ph: GO TO 130 1630 INPUT "Pl LLIST nt how many sacks of grain? ";d(p) 1640 IF d(p)>c(p) THEN GO TO 1630 1650 PRINT d(p);" sacks of ";G$;" planted." 1660 LET c(p)=c(p)-d(p) 1670 IF d(p)/10>a2 THEN LET d(p)=a2*10 1680 RETURN ```