Let the player change food without editing the BASIC listing. F opens a small number editor. The plan stays separate from the settlement until Space commits it. Planting remains fixed at 100 acres for this checkpoint.
Add lines 300, 310, 320, 340, 360, 500, 510, 520, 530, 2230, 2240, 4140, 6000, 6030, 6040, 6050, 6060, 6070, 6080, 6090, 6100, 6110, 6130, 6140, 6170, 6200, 6220, 6240, 8000, 8010, 8020, 8030.
Delete lines 280, 480.
To delete a BASIC line, enter its number on its own.
300 GO SUB 8000
310 IF k$="q" OR k$="Q" THEN STOP
320 IF k$="r" OR k$="R" THEN GO TO 200
340 IF k$="f" OR k$="F" THEN LET edit=2: GO SUB 6000: GO TO 270
360 IF k$<>" " OR ok=0 THEN GO TO 300
500 GO SUB 8000
510 IF k$="q" OR k$="Q" THEN STOP
520 IF k$="r" OR k$="R" THEN GO TO 200
530 GO TO 500
2230 PRINT AT 19,1; INK 5;"F edits the food allocation."
2240 PRINT AT 20,1;"SPACE harvest. R reset. Q quit."
4140 PRINT AT 19,1;"R restarts. Q quits."
6000 LET d$="": LET a$="Feed grain"
6030 PRINT AT 19,0;" ";AT 20,0;" ";AT 21,0;" "
6040 PRINT AT 19,1; INK 6;a$;": ";d$;"_ "
6050 PRINT AT 20,1;"Digits, ENTER. DELETE erases."
6060 PRINT AT 21,1;"X cancels. Blank keeps plan."
6070 GO SUB 8000
6080 IF k$="x" OR k$="X" THEN RETURN
6090 IF CODE k$=13 AND d$="" THEN RETURN
6100 IF CODE k$=13 THEN GO TO 6200
6110 IF CODE k$=12 AND LEN d$>0 THEN LET d$=d$( TO LEN d$-1): GO TO 6040
6130 IF CODE k$<48 OR CODE k$>57 THEN GO TO 6070
6140 IF LEN d$>=4 THEN GO TO 6070
6170 LET d$=d$+k$: GO TO 6040
6200 LET value=VAL d$
6220 IF edit=2 THEN LET feed=value
6240 RETURN
8000 IF INKEY$<>"" THEN GO TO 8000
8010 LET k$=INKEY$
8020 IF k$="" THEN GO TO 8010
8030 RETURNComplete source at this checkpoint
10 BORDER 0: PAPER 0: INK 7: CLS
140 RANDOMIZE
200 LET pop=60: LET grain=360: LET land=100: LET yr=1: LET lost=0
220 LET feed=180
240 LET plant=100
270 GO SUB 2000
300 GO SUB 8000
310 IF k$="q" OR k$="Q" THEN STOP
320 IF k$="r" OR k$="R" THEN GO TO 200
340 IF k$="f" OR k$="F" THEN LET edit=2: GO SUB 6000: GO TO 270
360 IF k$<>" " OR ok=0 THEN GO TO 300
400 LET oldpop=pop: LET oldgrain=grain: LET oldland=land
410 LET grain=left
420 LET deaths=pop-fed: LET lost=lost+deaths: LET pop=fed
430 LET crop=2+INT (RND*4): LET harvest=plant*crop: LET grain=grain+harvest
440 LET newcomers=0
470 GO SUB 4000
500 GO SUB 8000
510 IF k$="q" OR k$="Q" THEN STOP
520 IF k$="r" OR k$="R" THEN GO TO 200
530 GO TO 500
2000 LET fed=INT (feed/3)
2010 IF fed>pop THEN LET fed=pop
2020 LET left=grain-feed-plant
2030 LET ok=1: LET m$="All fed. Ready for harvest."
2040 IF fed<pop THEN LET m$=STR$ (pop-fed)+" people will starve."
2045 IF feed>3*pop THEN LET m$="Extra food gives no bonus."
2050 IF left<0 THEN LET ok=0: LET m$="Grain short by "+STR$ (-left)
2060 IF plant>2*fed THEN LET ok=0: LET m$="Too few fed workers."
2070 IF plant>land THEN LET ok=0: LET m$="Planting exceeds your land."
2090 CLS
2100 PRINT AT 0,1; INK 6; BRIGHT 1;"YEARFALL";AT 0,20;"YEAR ";yr
2110 PRINT AT 2,1; INK 5;"PEOPLE ";pop;AT 2,17;"LAND ";land
2120 PRINT AT 3,1; INK 5;"GRAIN ";grain
2130 PRINT AT 5,1; INK 4;"PLAN";AT 5,17;"AMOUNT";AT 5,25;"COST"
2150 PRINT AT 8,1;"F Feed grain";AT 8,17;feed;AT 8,25;feed
2160 PRINT AT 9,1;"P Plant acres";AT 9,17;plant;AT 9,25;plant
2170 PRINT AT 11,1; INK 6;"Grain left: ";left
2180 PRINT AT 12,1;"Food needed: ";3*pop
2200 PRINT AT 14,1;"Fed workers can plant: ";2*fed
2210 PRINT AT 16,1; INK 6;m$
2230 PRINT AT 19,1; INK 5;"F edits the food allocation."
2240 PRINT AT 20,1;"SPACE harvest. R reset. Q quit."
2250 RETURN
4000 CLS
4010 PRINT AT 0,1; INK 6; BRIGHT 1;"YEARFALL";AT 0,18;"HARVEST ";yr
4020 PRINT AT 2,1;"Yield: ";crop;" grain per acre"
4030 PRINT AT 4,1; INK 5;"GRAIN ACCOUNT"
4040 PRINT AT 6,1;"At start";AT 6,23;oldgrain
4060 PRINT AT 8,1;"Food spent";AT 8,23;feed
4070 PRINT AT 9,1;"Seed spent";AT 9,23;plant
4080 PRINT AT 10,1;"Harvest added";AT 10,23;harvest
4090 PRINT AT 12,1; INK 6;"Grain in store";AT 12,23;grain
4100 PRINT AT 14,1;"People lost: ";deaths
4120 PRINT AT 16,1; INK 5;"People ";oldpop;" -> ";pop
4130 PRINT AT 17,1; INK 5;"Land ";oldland;" -> ";land
4140 PRINT AT 19,1;"R restarts. Q quits."
4160 RETURN
6000 LET d$="": LET a$="Feed grain"
6030 PRINT AT 19,0;" ";AT 20,0;" ";AT 21,0;" "
6040 PRINT AT 19,1; INK 6;a$;": ";d$;"_ "
6050 PRINT AT 20,1;"Digits, ENTER. DELETE erases."
6060 PRINT AT 21,1;"X cancels. Blank keeps plan."
6070 GO SUB 8000
6080 IF k$="x" OR k$="X" THEN RETURN
6090 IF CODE k$=13 AND d$="" THEN RETURN
6100 IF CODE k$=13 THEN GO TO 6200
6110 IF CODE k$=12 AND LEN d$>0 THEN LET d$=d$( TO LEN d$-1): GO TO 6040
6130 IF CODE k$<48 OR CODE k$>57 THEN GO TO 6070
6140 IF LEN d$>=4 THEN GO TO 6070
6170 LET d$=d$+k$: GO TO 6040
6200 LET value=VAL d$
6220 IF edit=2 THEN LET feed=value
6240 RETURN
8000 IF INKEY$<>"" THEN GO TO 8000
8010 LET k$=INKEY$
8020 IF k$="" THEN GO TO 8010
8030 RETURNRUN, press F, type 179 and press Enter. The plan should warn that one person would starve. Press F again and X to cancel: the allocation must remain 179. Enter 180 to restore full food. Space commits one harvest; the report waits for R to restart or Q to quit. There is no next year yet.
Read one press
The routine at 8000 first waits for the previous key to be released. INKEY$ returns an empty string when no character is pressed. It then waits for a new character and returns it in k$. Every caller uses the same contract. Holding a digit must append it once; holding Space must not rush through a report.
The planning loop handles Q, R and F. An unmatched key returns to waiting. Space reaches the harvest only when ok is one. A false IF skips the rest of that line, so rejected input does not accidentally fall into the resource changes.
Keep text until it is safe to convert
The editor builds a string, d$. It begins empty so typing a new amount replaces the existing allocation. CODE gives a character’s numeric code: Enter is 13, Delete is 12, and digits run from 48 to 57. Other characters are ignored. LEN supplies the string length; the four-digit limit prevents unbounded entry.
Deleting uses a slice ending one character before the old end. With one character, the result is empty. X returns without assigning feed. Enter on an empty string also leaves the old allocation intact. Only a nonempty string made entirely of digits reaches VAL, which turns it into a number. We never ask VAL to evaluate arbitrary player text.
Why does typing 9 and then X leave the old food allocation intact?
Show the explanation
The 9 lives only in d$. Cancelling returns before line 6220 assigns the converted value to feed. A draft entry is not yet a draft plan, and neither is committed settlement state.
Try a held digit, Delete, an empty Enter and a letter. Then enter 9999: the editor accepts a whole number, but the budget rejects spending it. Input syntax and game rules are different checks. INKEY$ is entered with N in extended mode; LEN uses K, VAL uses J, and CODE uses I in extended mode.
Sources
Steven Vickers, edited by Robin Bradbeer, ZX Spectrum BASIC Programming, second edition (Sinclair Research, 1983), chapter 8, chapter 9, chapter 14, chapter 18.
Run it here
This unit's program, built for you.
- Program
- yearfall.tap
- Machine
- ZX Spectrum 48K (PAL)