Conquest

Products: Conquest
Developer(s): Lloyd Dreger
Date: 1993
Type: Program
Platform(s): TS 2068
Tags: Strategy

Conquest is a turn-based strategy game loader and front-end menu system that manages game setup, saving, loading, map editing, and commander statistics tracking. The program uses a series of machine code routines loaded from an external CODE file (“conque.C1”), with RANDOMIZE USR calls at addresses such as 59950, 60000 (6E4), 53500, and two stored in variables ky and kz to invoke gameplay logic. Player names are encoded into memory starting at address 31514 using a delimiter scheme where the last character of each name has 128 (kh) added to its ASCII code to mark boundaries. A commander hall-of-fame system tracks up to 20 players across games, recording games played, wins, and win percentage in DIM arrays that persist between sessions via the game save/load CODE mechanism.

Program Structure

The program is organized as a dispatcher menu at lines 1–10, with numbered subroutine blocks handling each menu option:

LinesFunctionMenu Option
100–199New Game setup1
200–210Load Game2
300–399Save Game3
400–499Map Editor4
500–505Save Map5
600–620View Commanders6
800–891Game-end / winner determination(internal)
999Stats display subroutine(internal)

Dispatch is handled at line 9 with GO SUB a*kc, where kc is a constant representing 100, so each menu selection (1–6) maps to a subroutine at a multiple of 100. Option 7 simply executes STOP.

Symbolic Constants via Short Variable Names

The program makes heavy use of single-letter or two-letter variables as numeric constants, a common technique to shorten tokenized BASIC lines and reduce memory usage. Based on context, the inferred mappings are:

  • k0 = 0
  • k1 = 1
  • k2 = 2
  • k3 = 3
  • k5 = 5
  • k9 = 9
  • kc = 100
  • kh = 128 (used as a name-delimiter marker)
  • kl = 21 (screen rows)
  • km = address of the music-on/off flag in machine code
  • kw = map start address (checked against 16 for city verification)
  • kx = line number for the game launch jump target
  • ky, kz = USR addresses for machine code entry points

These constants are presumably set by the loaded machine code block or a prior initialization section not shown here.

Machine Code Integration

Line 1 POKEs addresses 23730–23731 to relocate or configure the system channel, then immediately loads the machine code file conque.C1. Multiple RANDOMIZE USR calls throughout invoke machine code routines:

  • RANDOMIZE USR ky — called in both the Map Editor (line 400) and game-end handler (line 800)
  • RANDOMIZE USR VAL "6E4" — shorthand for address 60000, in the Map Editor block (line 405)
  • RANDOMIZE USR VAL "59950" — gives computer players map knowledge during New Game (line 151)
  • RANDOMIZE USR 53500 — called at game-end (line 805)
  • RANDOMIZE USR kz — called in both Map Editor and game-end blocks

The use of VAL "6E4" (scientific notation) to express 60000 is a memory-saving trick: the tokenized number literal 60000 takes more bytes than the short string "6E4".

Player Name Encoding

Lines 112–118 implement a compact encoding scheme for storing player names into a contiguous memory block starting at address 31514. The last character of each name has 128 added to its ASCII code (using constant kh), acting as an end-of-name delimiter. This allows the machine code to parse variable-length names without storing explicit length bytes. Lines 825–855 reverse this process, reconstructing a$, b$, and c$ by scanning the block and detecting the high-bit marker.

Commander Hall of Fame

The game maintains a persistent leaderboard in arrays s$, g, w, and p (referenced in line 872’s REM as dimensioned to 20 entries). Line 600 computes win percentages, and lines 868–891 update the table after a game ends. The logic searches for a matching name in s$(x); if not found and the slot is blank (" "), it inserts the new commander. If the table is full, line 871 prints “NO ROOM IN TABLE” and pauses. Lines 875–891 also update games-played counts for non-winning players using the h$ string as a two-character flag encoding which players (a, b, c) lost.

Winner Determination Logic

Lines 815–865 contain non-trivial winner detection. The code PEEKs address 31541 for the number of players and 51361 and 52360 for game-state flags. The conditional logic at lines 855–860 handles both two-player and three-player endings, computing the winner index a (1, 2, or 3) through a series of boolean additions — a technique that exploits the fact that BASIC boolean expressions evaluate to 1 (true) or 0 (false).

Input Handling Idioms

Lines 6–7 use a standard debounce pattern: line 6 loops on empty INKEY$ and line 7 captures a valid keypress only when a digit 1–7 is detected. The interactive stats-entry loop at lines 123–127 uses FLASH 1 to highlight the current field and accepts single-character commands (u, d, o) for up, down, and okay, a clean approach to cursor-driven numeric input without a full INPUT statement.

Notable Anomalies

  • Line 130 computes c(b,1) = 20 - c(b,1), inverting the starting resource value, which suggests the UI displays remaining capacity but the machine code stores consumed units (or vice versa).
  • Line 812 checks NOT PEEK 52360 and returns early, acting as a guard against running the winner-announcement code when no winner flag is set.
  • The REM at line 872 documents array dimensions that must be set elsewhere (likely in the machine code initialization or a prior BASIC section), serving as inline developer documentation rather than executable code.

Related Products

You command an expeditionary force landing on an unknown, inhabited planet. Build armies, aircraft and fleets in the cities you...

Related Content

Image Gallery

Source Code

    1 POKE VAL "23730", VAL "24":POKE VAL "23731", VAL "123":LOAD "conque.C1"CODE 
    4 LET h$="":BORDER k0:PAPER k0:INK VAL "7"
    5 LET a=k0:CLS :PRINT ' TAB 12;"CONQUEST";''' TAB k5;"1. New Game";'' TAB k5;"2. Load Game";'' TAB k5;"3. Save Game";'' TAB k5;"4. Map Editor";'' TAB k5;"5. Save Map";'' TAB k5;"6. View Commanders";'' TAB k5;"7. Quit"
    6 IF INKEY$="" THEN GO TO k3+k3
    7 IF INKEY$ >="1" AND INKEY$ <="7" THEN LET a= VAL INKEY$
    8 IF a=7 THEN STOP 
    9 GO SUB a*kc
   10 GO TO k5-k1
  100 CLS :PRINT '"How many Players? (2 or 3)"
  101 INPUT a:IF a <>k2 AND a <>k3 THEN GO TO kc+k1
  102 LET x= VAL "31541":POKE x,a:PRINT '"How many Human Players? (0-3)"
  103 INPUT a:IF a>(PEEK x) THEN GO TO kc+k3
  106 POKE (x-k1),a: LET a$="Yellow":LET b$="Red":LET c$="White"
  107 IF a=k0 THEN GO TO VAL "112"
  108 IF a >=k1 THEN PRINT ''"First Player's Name?":INPUT a$
  109 IF a >=k2 THEN PRINT ''"Second Player's Name?":INPUT b$
  110 IF a=k3 THEN PRINT ''"Third Player's Name?":INPUT c$
  112 LET b= CODE a$(LEN a$)+kh:LET d$=a$:LET d$(LEN d$)= CHR$ b
  114 LET b= CODE b$(LEN b$)+kh:LET d$=d$+b$:LET d$(LEN d$)= CHR$ b
  116 LET b= CODE c$(LEN c$)+kh:LET d$=d$+c$:LET d$(LEN d$)= CHR$ b
  117 LET x= VAL "31514":POKE x,kh:LET x=x+k1:FOR b=k1 TO LEN d$
  118 POKE x, CODE d$(b):LET x=x+k1:NEXT b
  120 CLS :PRINT '"First Player    ";a$;'' TAB k5;e$;'' TAB k5;f$;''"Second Player   ";b$;'' TAB k5;e$;'' TAB k5;f$;''"Third Player    ";c$;'' TAB k5;e$;'' TAB k5;f$
  121 PRINT AT kl-k1,k0;"u=UP; d=Down; o=Okay"
  122 DIM c(k3,k2):LET a= PEEK VAL "31541":FOR b=k1 TO a:FOR d=k1 TO k2:LET c(b,d)= VAL "10":NEXT d:NEXT b:GO SUB VAL "999"
  123 LET m=k3:FOR l=k1 TO a:FOR n=k1 TO k2:PRINT AT m,k3; FLASH k1;"\::"
  125 INPUT h$:IF h$="u" THEN LET c(l,n)=c(l,n)+ SGN PI:GO SUB VAL "999":GO TO VAL "124"
  126 IF h$="d" THEN LET c(l,n)=c(l,n)- SGN PI:GO SUB VAL "999":GO TO VAL "124"
  127 IF h$="o" THEN PRINT AT m,k3;" ":LET m=m+k2:NEXT n:LET m=m+k2:NEXT l
  128 PRINT AT VAL "21",k0;"Okay? (y  OR n)":INPUT h$:IF h$="n" THEN GO TO VAL "122"
  130 FOR b=k1 TO k3:LET c(b,k1)=20-c(b,k1):NEXT b
  131 LET m= VAL "31544":FOR b=k1 TO a:FOR d=k2 TO k1 STEP -k1:POKE m,c(b,d):LET m=m+ SGN PI:NEXT d:NEXT b
  133  PRINT AT kl,k0;"Music on? (y  OR n)":INPUT h$:IF h$="n" THEN POKE km,k0
  135  PRINT AT kl,k0;"Random map? (y  OR n)":INPUT h$:IF h$="y" THEN GO TO kx
  150 CLS :PRINT "Which map number?":INPUT b$:LET a$="map"+b$+".C1":LOAD a$ CODE 
  151 PRINT ''"Give computer players map? (y OR n)":INPUT h$:IF h$="y" THEN RANDOMIZE USR VAL "59950"
  155 GO TO kx
  199 RETURN 
  200 CLS :PRINT "Which game number?":INPUT b$:LET a$="game"+b$+".C1":LOAD a$ CODE 
  210  PRINT AT kl,k0;"Music on? (y  OR n)":INPUT h$:IF h$="n" THEN POKE km,k0:GO TO kx
  300 CLS :PRINT "Game number please.":INPUT h$:LET a$="game"+h$+".C1":SAVE a$ CODE VAL "31514", VAL "20882"
  320 PRINT ''"Continue game? (y OR n)":INPUT h$:IF h$="y" THEN GO TO kx
  399 RETURN 
  400 RANDOMIZE USR ky
  405 RANDOMIZE USR VAL "6E4"
  410 RANDOMIZE USR kz
  499 RETURN 
  500 CLS : LET a= PEEK kw:IF a<16 THEN PRINT ''"Cities not verified":RETURN 
  505 PRINT "what number please.":INPUT h$:LET a$="map"+h$+".C1":SAVE a$ CODE kw, VAL "4097":RETURN 
  600 FOR x=k1 TO kl-k1:IF g(x)=k0 THEN GO TO 603
  601 LET p(x)=w(x)/g(x)*kc
  603 NEXT x
  605 CLS :PRINT TAB k5+k9;"COMMANDERS","  NAME       GAMES WINS PERCENT"  
  610 FOR x=k1 TO kl-k1:PRINT AT x+k1,k0;s$(x); TAB 15;g(x); TAB kl;w(x); TAB kl+k5;p(x):NEXT x
  620 PAUSE 4E4:RETURN 
  800 RANDOMIZE USR ky
  805 RANDOMIZE USR 53500
  810 RANDOMIZE USR kz
  812 IF NOT PEEK 52360 THEN RETURN 
  815 LET a= PEEK 31541:LET d= PEEK 51361:IF a=k3 AND d <>k0 AND d <>255  THEN RETURN 
  820 LET d$="":LET a$="        ":LET b$=a$:LET c$=a$
  825 FOR x=31515 TO 31538:LET d$=d$+ CHR$ (PEEK x):NEXT x
  830 FOR x=k1 TO LEN d$:IF CODE d$(x)<kh THEN LET a$(x)=d$(x):NEXT x
  835 LET a$(x)= CHR$ (CODE d$(x)-kh):LET b=x
  840 FOR x=x+1 TO LEN d$:IF CODE d$(x)<kh THEN LET b$(x-b)=d$(x):NEXT x
  845 LET b$(x-b)= CHR$ (CODE d$(x)-kh):IF a=k2 THEN GO TO 860
  850 LET b=x:FOR x=x+1 TO LEN d$:IF CODE d$(x)<kh THEN LET c$(x-b)=d$(x):NEXT x
  855 LET c$(x-b)= CHR$ (CODE d$(x)-kh):LET b= PEEK 52360:IF a=k2 THEN LET a=k1+(b=k1):GO TO 865
  860 LET a=k1+(b=k1)+(d=k1):IF a=k2 THEN LET a=a+(b=k2)+(d=k2)
  865 CLS :PRINT AT k5,k5;"CONGRATULATIONS"; AT k5+k2,k5;"COMMANDER ";(a$ AND a=k1);(b$ AND a=k2);(c$ AND a=k3)
  866 LET w$="":LET w$=w$+(a$ AND a=k1)+(b$ AND a=k2)+(c$ AND a=k3)
  868 FOR x=k1 TO kl-k1:IF w$=s$(x) THEN LET g(x)=g(x)+k1:LET w(x)=w(x)+k1:GO TO 875
  869 IF s$(x)="        " THEN LET s$(x)=w$:GO TO 868
  870 NEXT x
  871 PRINT AT kl,k0;"NO ROOM IN TABLE":PAUSE 4E4:RETURN 
  872 REM DIM s$(20,10),g,w AND p to 20
  875 IF w$=a$ THEN LET h$="bc"
  876  IF w$=b$ THEN LET h$="ac"
  877  IF w$=c$ THEN LET h$="ab"
  878 LET l$="":LET l$=l$+(a$ AND h$(k1)="a")+(b$ AND h$(k1)="b")
  880 FOR x=k1 TO kl-k1:IF s$(x)=l$ THEN LET g(x)=g(x)+k1:GO TO 886
  881 IF s$(x)="        " THEN LET s$(x)=l$:LET g(x)=g(x)+k1:GO TO 886
  882 NEXT x
  883 GO TO 871
  886 LET l$="":LET l$=l$+(b$ AND h$(k2)="b")+(c$ AND h$(k2)="c")
  888 FOR x=k1 TO kl-k1:IF s$(x)=l$ THEN LET g(x)=g(x)+k1:RETURN 
  889 IF s$(x)="        " THEN LET s$(x)=l$:LET g(x)=g(x)+k1:RETURN 
  890 NEXT x
  891 GO TO VAL "871"
  950 STOP 
  999 LET e=k3:FOR b=k1 TO a:FOR d=k1 TO k2:PRINT AT e,17;"  ":LET e=e+k2:NEXT d:LET e=e+k2:NEXT b:LET e=k3:PRINT AT e,17;:FOR b=k1 TO a:FOR d=k1 TO k2:PRINT c(b,d);:LET e=e+k2:PRINT AT e,17;:NEXT d:LET e=e+k2:PRINT AT e,17;:NEXT b:RETURN 
 1000 SAVE "conquest" LINE 1

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.