Twin Peaks
Twin Peaks is a small North American town of about 500 people, and two sides are fighting over it. You play one of them. Recruit as many townspeople as you can, find the key, break into the enemy encampment with it, win the battle, and get out alive.
The game was written in 1994 for the Soviet Elektronika MK-52 and MK-61 by Evgeny Vek, as one of a series called Good and Evil (see also The Sinister Hall). The MK-52/61 listing below is his program; the HP-15C version is a re-implementation from his description of the game, not a translation. The original leans on hidden-code tricks and on words spelled out in the calculator’s display, neither of which the HP-15C can do, and the HP-15C’s odds and battle formulas are new.
Ported game. Twin Peaks is not an HP game. It was written in 1994 by Evgeny Vek (Lord_BSS) for the Soviet Elektronika MK-52 and MK-61, and this page is based on his work. The MK listing below is his program as he published it, and the original page, in Russian, is at lordbss.narod.ru/pmk13.html. The HP-15C version is a re-implementation built from his description of the game, so its odds and battle formulas are not his, and it is not endorsed by him.
How a game goes
- Recruiting. Each turn you choose a persuasion method, 1 to 10. How many people it wins you depends on the ground you are standing on, and on luck. Forest is worth the least, then swamp, then the village, and a house is worth the most. The enemy recruits from the same pool.
- Exploring. Then you move one square. The map is a grid of 100 squares, and the house you are being drawn towards is shown as a square number.
- The key. One square holds the key to the encampment. Step on it and the calculator shows a code of 4 to 7 digits. Copy it down.
- The encampment. Another square is the enemy encampment, and the display tells you when you reach it. Key in the code to storm it, or press R/S to carry on recruiting.
- The battle. Each round you pick a strategy, 1 to 10, and both armies shrink. Run out of people and you lose.
- The escape. If you win, you are still inside the encampment. Images of the exits flash past on the display, and you must stop on the right one.
| # | Persuasion | Battle strategy |
|---|---|---|
| 1 | rally | offensive |
| 2 | supporters’ march | assault |
| 3 | demonstration | attack |
| 4 | presentation | sortie |
| 5 | printed leaflets | regrouping |
| 6 | radio ad | dispersal |
| 7 | TV appearance | ambush |
| 8 | hypnosis | repel attack |
| 9 | threats | withdrawal |
| 10 | bribery | retreat |
The original’s own word for the first column is “propaganda” (Russian пропаганда, which means winning people over to your cause); “persuasion” is closer to how English speakers use it. Those names come from the original’s instructions. The HP-15C port takes the same 1 to 10 choices, but it does not name them: a number only matters through how it plays against the luck factor.
Playing on the HP-15C
On a real HP-15C, make room first. The program is 368 lines long, and a real 15C holds only 308 as
it comes, because the rest of its memory is set aside for data registers that this game does not use.
In run mode, type 10, then press f, the SIN key (its gold label is DIM) and the COS key
(its gold label is (i)): f DIM (i). Nothing is shown to confirm it. That keeps registers R0 to R10
(the game uses R0 to R9 and R.0) and turns the other nine into 63 more program lines. That is just enough: with all 368 lines keyed in,
nothing is left over, so there is no room to add steps.
To check it, press g, then the RCL key (its g label is MEM): the first number shown is the
highest data register and must read 10, not 19. On the emulator, with the whole program in, the
display reads 10 0 55-0. Without this step a real 15C stops keying the
program in at line 308 with Error 4.
The HP-15C Simulator (version 5.1, Linux) took the whole program without this step, so skip it there. If the game gives Error 4 in the simulator anyway, a label or line is missing: do the step and load the program again.
Then key in the program, or paste it. In the HP-15C Simulator, use the copy for HP-15C simulator button, switch to PRGM mode and press Ctrl+V (the plain copy is not accepted), or open a saved program file. Then:
- Seed the random generator once: type any number, then STO RAN#.
- Press f A. Each turn it stops on one number at a time, so you can write it down; press R/S
for the next. In order: the terrain code with a direction hint (see below), then
your square . house square(37.52 means you are on 37 and the house is on 52), then the enemy’s people, then the neutral people left. The fifth stop is your people. - Type a persuasion number from 1 to 10 and press R/S. It stops on the recruits, then R/S again for your people.
- Type a move and press R/S: 1 north, 2 east, 3 south, 4 west. Squares are numbered 00 to 99. North and south move by 10 and east and west by 1, wrapping around the range, so east of 09 is 10.
- A number of 4 to 7 digits means you are on the key square: write it down and press R/S. 507.00 is the enemy encampment: type the key code and press R/S to storm it, or just R/S to move on.
- In the battle it stops on the enemy’s people, then R/S shows yours. Type a strategy, 1 to 10, and press R/S, until one side is gone. Error 0 means your side lost.
- If you win, the digits 1, 2, 3 and 507 flash past. Press R/S while 507.00 is showing, then press f D to check. If you stopped on it, the display shows 7777.00; if not, the flashing carries on.
The direction hint
The first stop shows the terrain and a compass hint together, as terrain.hint: the whole
number is the terrain (1 forest, 2 swamp, 3 village, 4 house), and the two digits after the point
are the move keys that lead towards your target. Before you have the key, the target is the key
square. Once you have stepped on it, the target is the enemy encampment.
| Hint | Go | Hint | Go |
|---|---|---|---|
| .10 | north (1) | .30 | south (3) |
| .12 | north or east (1 or 2) | .32 | south or east (3 or 2) |
| .02 | east (2) | .34 | south or west (3 or 4) |
| .04 | west (4) | .14 | north or west (1 or 4) |
| .00 | you are on the target |
So 2.12 is swamp, with the target to the north-east: type 1 or 2 as your move. Squares are laid out ten to a row, so north and south wrap round the map, and the hint takes whichever way is shorter. East and west do not wrap within a row: moving east off the end of a row lands in the next one, so the hint never sends you that way. Following the hint, every target is within 14 moves.
Working out the hint is about 90 program steps, and the 15C runs roughly ten steps a second, so this first stop takes 8 to 9 seconds to appear each turn, and about 12 seconds after f A. The calculator is not stuck. Wait for the number.
The hint is a feature of the port. The MK-52/61 original has no such clue.
Playing on the MK-52 / MK-61
Key in the program in program mode (F PRG), switch to run mode (F AVT), key in the register setup, and start with GOTO 39 R/S. The first number to appear is your people. Following the original’s own instructions:
- Type a persuasion number from 1 to 10, then R/S. Houses are worth dozens of people, open ground only a few, and swamp more than forest but less than the village. After the move the display shows your people again. If the whole town has been recruited, it shows your square with a negative warning number.
- Type a movement code, then R/S.
- A 4 to 7 digit number means you are on the key square. Copy it, then R/S.
- An encampment message (
BICЧ 507, in the original’s spelled-out letters) is the enemy base. Key in the key code and press R/S to storm it, or R/S to keep exploring. - In the battle, X is your people and Y is the enemy’s. Type a strategy, 1 to 10, then R/S.
- ЕГГОГ (the MK’s “error” message) means you lost.
- If you won, scenes from the encampment flash past. Press R/S to stop on the encampment exit (
BICЧ 507) and R/S again to return to Earth: ВЕЗЛО- В (“lucky”) means you made it. If any other number sticks on the display, press B/O then R/S to carry on.
Reading the MK listing
The listing is the author’s table, one line per program step, with the step number on the left. Cells that are Cyrillic are the Russian key labels; the comment gives the English name.
| Russian | English | Russian | English |
|---|---|---|---|
| Пх n | RCL n | БП | GOTO |
| хП n | STO n | ПП | GSB |
| С/П | R/S | В/О | RTN |
| ВП | EEX | /–/ | CHS |
| ↔ | x<>y | Сх | CLX |
| F Вх | LASTX | F lg | LOG |
| К {x} | FRAC | К [x] | INT |
| К |x| | ABS | К ЗН | SIGN |
| К БП, К ПП, К Пх, К хП | indirect GOTO, GSB, RCL, STO | К x=0 | indirect test |
Registers A to E are the calculator’s 11th to 15th, keyed with the ., /-/, ВП, Cx and В↑
keys after Пх or хП. The conditional jumps (F x=0, F x≠0, F x≥0, F L0) take the next
step as their address, and the MK jumps when the condition is false.
One thing in the listing is not a typo. The address of the GOTO at step 50 is the byte at step 51,
and that byte is also a perfectly good instruction (RCL 3) that the test at step 37 jumps straight
into. The author reuses it, so step 51 is written once as 63: enter it as a normal GOTO 63.
HP-15C port
Numbered as the HP-15C numbers its program lines: every digit, decimal point and EEX is a line of its own, 368 in all. A real 15C holds only 308 lines as it comes, so on one, first give up the spare registers: type 10, then press f DIM (i). The HP-15C Simulator does not need this. Run it with f A.
001LBL A ; init: 500 neutral, random start/house/key/encampment squares, random key code, first target = key
002FIX 2
0035
0040
0050
006STO 2
0070
008STO 0
009STO 1
010GSB 0
011STO 3
012GSB 0
013STO 4
014GSB 0
015STO 5
016GSB 0
017STO 6
018RCL 5
019STO .0
020RAN#
0219
022EEX
0236
024×
025INT
0261
027EEX
0283
029+
030STO 7
031LBL 1 ; turn start: arrival events
032RCL 3
033RCL 6
034x=y?
035GTO 5
036LBL 7
037RCL 3
038RCL 5
039x=y?
040GTO 6
041LBL 4 ; status, one stop per number (R/S for the next), then ask persuasion number
042GSB 2
043GSB .1 ; terrain.hint: terrain code, then the move keys that lead to the target
044R/S
045INT
046x²
0473
048×
049STO 8
050RCL 4
0511
0520
0530
054÷
055RCL 3
056+
057R/S
058RCL 1
059R/S
060RCL 2
061R/S
062RCL 0
063R/S
064RAN#
0651
0660
067×
068INT
0691
070+
071−
072ABS
0731
0740
075÷
076CHS
0771
078+
079.
0801
081x<y?
082x<>y
083RCL 8
084×
085RAN#
086.
0875
088+
089×
090INT
091RCL 2
092x≥y?
093x<>y
094STO+ 0
095STO− 2
096R/S
097RAN#
0982
0990
100×
101INT
102RCL 2
103x≥y?
104x<>y
105STO+ 1
106STO− 2
107RCL 0
108R/S
109STO 8
1102
111÷
112FRAC
113x=0?
114GTO B
115RCL 8
1162
117−
1181
1190
120×
121GTO C
122LBL B ; move: even codes
1233
124RCL 8
125−
126LBL C ; apply move, wrap on 0-99
127STO+ 3
128RCL 3
1291
1300
1310
132+
1331
1340
1350
136÷
137FRAC
1381
1390
1400
141×
142RND ; round off the FRAC (exact on a 15C, needed on floating-point simulators)
143STO 3
144GTO 1
145LBL 5 ; encampment found
1465
1470
1487
149R/S
150RCL 7
151x=y?
152GTO 8
153GTO 7
154LBL 6 ; key square: from now on the hint points at the encampment
155RCL 7
156R/S
157RCL 6
158STO .0
159GTO 4
160LBL 0 ; subroutine: random square 0-99
161RAN#
1621
1630
1640
165×
166INT
167RTN
168LBL 2 ; subroutine: terrain code 1-3, or 4 at house
169RCL 3
170RCL 4
171x=y?
172GTO 3
173R↓
1743
175÷
176INT
1773
178×
179RCL 3
180x<>y
181−
1821
183+
184RTN
185LBL 3 ; house
1864
187RTN
188LBL 8 ; BATTLE
189RCL 1
190R/S
191RCL 0
192R/S
193RAN#
1941
1950
196×
197INT
1981
199+
200−
201ABS
2021
2030
204÷
205CHS
2061
207+
208.
2091
210x<y?
211x<>y
212STO 8
213RCL 0
214×
215.
2164
217×
218RAN#
219.
2205
221+
222×
223INT
2241
225+
226STO 9
2271
228.
2291
230RCL 8
231−
232RCL 1
233×
234.
2354
236×
237RAN#
238.
2395
240+
241×
242INT
2431
244+
245STO− 0
246RCL 9
247STO− 1
248RCL 0
249x≤0?
250GTO E
251RCL 1
252x≤0?
253GTO 9
254GTO 8
255LBL E ; defeat: Error 0
2561
257ENTER
2580
259÷
260LBL 9 ; escape: flashing codes
261RAN#
2624
263×
264INT
2651
266+
2674
268x=y?
269GTO .0
270x<>y
271PSE
272GTO 9
273LBL .0
2745
2750
2767
277PSE
278GTO 9
279LBL D ; press f D to freeze-check the displayed code
2805
2810
2827
283x=y?
284GTO .2
285GTO 9
286LBL .2 ; victory
2877
2887
2897
2907
291R/S
292LBL .1 ; subroutine: X = terrain code in, terrain + hint/100 out. R.0 is the target square
293STO 8
294RCL .0 ; rows: target row minus my row, wrapped to -5..4 (a move north or south wraps)
2951
2960
297÷
298INT
299RCL 3
3001
3010
302÷
303INT
304−
3051
3065
307+
3081
3090
310÷
311FRAC
3121
3130
314×
3155
316−
317GSB .3 ; vertical sign
318ENTER ; 1 north, 3 south: sign + 2 |sign|, times 10, kept on the stack
319ABS
3202
321×
322+
3231
3240
325×
326RCL .0 ; columns: target minus mine, no wrap (an east move off column 9 changes row)
3271
3280
329÷
330FRAC
3311
3320
333×
334RCL 3
3351
3360
337÷
338FRAC
3391
3400
341×
342−
343GSB .3 ; horizontal sign
344ENTER ; 2 east, 4 west: 3 |sign| - sign
345ABS
3463
347×
348x<>y
349−
350+
3511
3520
3530
354÷
355RCL 8
356+
357RTN
358LBL .3 ; subroutine: sign of X (-1, 0 or 1)
359ENTER
360ABS
361.
3625
363+
364÷
3652
366×
367INT
368RTN
Elektronika MK-52 / MK-61 original program
The author's own program, step for step as published. Start it with GOTO 39 R/S.
00Пх7 ; RCL 7
01Пх8 ; RCL 8
02Пх9 ; RCL 9
03ПхД ; RCL D
04КБПВ ; GTO indirect via RB
05Кинв ; K INV
06С/П ; R/S
07ВП ; EEX
08/–/ ; CHS
091
10K{x} ; FRAC
11ПхС ; RCL C
12F10x ; 10^x
13K{x} ; FRAC
14хПС ; STO C
15– ; −
16K|x| ; ABS
17ПхЕ ; RCL E
18х ; ×
19K[х] ; INT
20В/О ; RTN
21Пх6 ; RCL 6
22Fx≥o ; x≥0 ?
2370 ; address
24↔ ; x<>y
25– ; −
26хП6 ; STO 6
27FBx ; LASTX
28В/О ; RTN
29КППД ; GSB indirect via RD
30КПП7 ; GSB indirect via R7
31ПхВ ; RCL B
32+ ; +
33хПВ ; STO B
34Пх3 ; RCL 3
35Пх1 ; RCL 1
36– ; −
37Fx=o ; x=0 ?
3851 ; address
39Пх0 ; RCL 0
402
41F10x ; 10^x
42+ ; +
43хПЕ ; STO E
44Сх ; CLX
45КППД ; GSB indirect via RD
46КхПЕ ; STO indirect via RE
47FL0 ; L0 loop
4839 ; address
49хПЕ ; STO E
50БП ; GTO
5163 ; address byte (the 37/38 test also lands here, where 63 runs as RCL 3)
52хП3 ; STO 3
53ВП ; EEX
54Fx≠o ; x≠0 ?
5559 ; address
564
57– ; −
58Кзн ; SIGN
598
60+ ; +
61хПЕ ; STO E
62КПхЕ ; RCL indirect via RE
63ПхА ; RCL A
64КПП8 ; GSB indirect via R8
65КПП7 ; GSB indirect via R7
66ПхА ; RCL A
67+ ; +
68хПА ; STO A
69Пх1 ; RCL 1
70Пх3 ; RCL 3
71С/П ; R/S
72Пх3 ; RCL 3
73+ ; +
74хП3 ; STO 3
75Пх2 ; RCL 2
76– ; −
77Fx=o ; x=0 ?
7884 ; address
79ПхС ; RCL C
80ВП ; EEX
817
82хП5 ; STO 5
83С/П ; R/S
84Пх3 ; RCL 3
85Пх4 ; RCL 4
86– ; −
87Kx=o9 ; x=0 ? (indirect, address in R9)
88ПхД ; RCL D
89С/П ; R/S
90Пх5 ; RCL 5
91– ; −
92Kx=o9 ; x=0 ? (indirect, address in R9)
93ПхВ ; RCL B
94ПхА ; RCL A
95хПЕ ; STO E
96КПП8 ; GSB indirect via R8
97хПА ; STO A
98Flg ; LOG
99ПхВ ; RCL B
A0хПЕ ; STO E
A1КППД ; GSB indirect via RD
A2хПВ ; STO B
A3Fx=o ; x=0 ?
A493 ; address
Run this after keying in the program and before the first game. Several of the constants are hidden-code numbers that the program uses as on-screen text and as jump addresses.
4 ; R0 = 4
хП0
Fex ; F e^x (e^4)
хП5 ; R5
500 ; the town's residents
хП6 ; R6
Сх ; your people
хПА ; RA
Сх ; enemy people
хПВ ; RB
0,12345 ; any number from 0 to 1: the random factor
хПС ; RC
66080706 ; the next four stores build the "text" constants in R8, R7, RD and R9
В↑
3003
К∨ ; written "KV" on the original page
К{x}
ВП
7
хП8
888888
В↑
3364221
К∨
К{x}
ВП
7
хП7
80808
В↑
11447507
К∨
ВП
7
хПД
888808
В↑
44630229
К∨
К{x}
ВП
7
хП9
Original game by Evgeny Vek (Lord_BSS), 1994. Source page.