Software for the classic HP 12C calculator
------------------------------------------
This page contains my own key-in programs created for the HP 12C programmable
financial calculator to extend its capabilities.
All programs have been tested on the classic ("gold") 12C from 2001 with a
884 KHz Agilent CPU of the HP Nut architecture.
== Table of contents ==
This document contains the TRICKS, UTILS, SUITES and GAMES sections.
TRICKS:
* Min/max snippets
* GTO-less conditionals
* Reliable absolute value snippet
* Reliable modulo
* Pseudorandom number generation
* Generating several random integers in a single pass
* Hidden polynomial evaluator
* Hidden polynomial solver
* Indirect register access
* Harnessing extra memory from the Nj registers
* (Ab)using RCL CFj to organize small non-nested loops
UTILS:
* Trigonometry:
- Sine or cosine (Taylor-based)
- Sine and cosine (fast) - recommended
- FinSin: sine and arcsine based on the financial functions
- Arctangent (fixed-time)
- Scaling down the arctangent arguments
- Calculating arcsine and arccosine using arctangent programs
- Useful constants
* Coordinate unit conversions
* Measurement unit conversions
* Modular exponentiation
* Prime number generator (fun-sized)
* One-time pad encryption/decryption helper
* FinPoly: generalized Minimax polynomial calculator
* KHCEmu12: WDR's Der Know-How Computer emulator
SUITES:
* Luxferre's Trigonometry Suite
* Luxferre's Complex Number Suite
* Luxferre's Nautical Converter
* Neo12C: a handy 2x2 matrix operations suite
GAMES:
* Dice roll simulator
* YahBox12 (Yahtzee dice box simulator)
* Nicomachus
* UltimateMoo12 (Bulls and Cows HP 12C port)
* Hurwump12: Hunt the Hurkle + Mugwump 2-in-1 game pack for HP 12C
* Hurwurk12: Hunt the Hurkle + Mugwump + Snark 3-in-1 game pack
* OptiWump12: an optimized Mugwump port for the 12C
* OptiSnark12: an optimized Snark port for the 12C
* Hurkle3D aka Depth Charge
* Nim12: a classic variant of the Nim game
* EvenWins12: a port of the "Even Wins" game to HP 12C
This section contains short (usually unnumbered) snippets of code to be used
in HP 12C programs to perform common tasks not supported natively by its
instruction set.
== Min/max snippets ==
Whenever you need to detect the greatest or the lowest value among the two or
even three in your program (that are already present in the stack), that's
very simple:
Takes five steps but requires keeping track of instruction numbers. Here are
the replacements.
* Push the value A on top of the stack if the value in the X register is 0,
push the value B otherwise:
[A ENTER] [B] ROLL ROLL x<>y ROLL x=0 ROLL ROLL
* Push 1 (or any other constant) on top of the stack if the value in the X
register is 0, push 0 otherwise (shortcut):
ENTER x=0 1 - CHS
* Push the value A on top of the stack if the value in the X register is less
than or equal to the value in the Y register, push the value B otherwise (if
Y > X):
[A ENTER] [B] ROLL ROLL x<=y ROLL ROLL ROLL
== Reliable absolute value snippet ==
Unlike e.g. MK-52, HP 12C also lacks an absolute value function. A naive and
short implementation within a program would be like:
ENTER x SQRT
However, this uses an extra stack register and a slow SQRT function, which
also might lead to precision loss. A faster approach which guarantees no
precision loss is only one step longer:
0 x<>y x<=y CHS
Using the min snippet above, the fastest way to calculate abs(a - b) is:
x<=y x<>y x<>y -
This works because the minimum of the two will always get into the X
register.
== Reliable modulo ==
Since the 12C doesn't have a modulo operation but has a FRAC function, one
might be tempted to use it if it's necessary to calculate a full remainder
(not just check whether it's 0). For a generic a mod b operation, the naive
routine would be:
[a ENTER b] / LSTx x<>y FRAC x
However, while this routine works fine for divisors like 2, 5 or 10, it is
not recommended for the fractions that end up having infinite digits since
the loss of precision can accumulate rather quickly. The RND function will
do if you operate on limited precision that you are sure to not exceed
anytime, but a more reliable approach would be:
[a ENTER b] / LSTx x<>y FRAC x . 5 + INTG
In a program, it takes 9 steps (or 8 if the constant 0.5 is already stored
elsewhere). If you are ready to trade more steps for speed, the following
snippet is available that's only using the INTG function once and performs
only stack operations (assuming the dividend is in the reg Y and the divisor
in the reg X, so the stack state for a mod b is (b a - -)):
[a ENTER b] x<>y ENTER ROLL x<>y / LSTx x<>y INTG x x<>y ROLL -
If you only need to check if the modulo is 0, a 3-step routine (/ FRAC x=0)
is fine though.
For a register Rn from R0 to R4, the operation Rn mod b would look like:
b STO / [n] RCL [n] FRAC x . 5 + INTG STO [n]
This routine also takes 9 steps but also stores the value into the same
register.
== Pseudorandom number generation ==
Another notable thing missing in HP 12C is any kind of random number
generator. Here's my personal approach to generating pseudorandom numbers
from 0 to 1 using the calculator's transcendental functions in the shortest
way possible while still avoiding any statistical bias. The formula is: S[n]
= frac(12 * exp(S[n-1] + 3)). The line numbering can be arbitrary as this is
supposed to be a snippet of another program, but please make sure to end it
with GTO 00 if you plan on using it in a standalone manner:
01 RCL n ; recall Rn
02 FRAC ; and take its fractional part
03 3 ; push 3
04 + ; add 3
05 e^x ; take its natural exponent
06 12x ; multiply by 12 and rewrite Rn
07 FRAC ; return its fractional part for further usage
Set the initial seed between 0 and 1 to the financial register n before
running the snippet.
Alternatively, you can use the S[n] = frac(-12 / ln(S[n-1])) formula that
takes the same amount of steps, may be a little slower but pushes only one
extra value into the stack (preserving the contents of Y and Z registers in
Z and T respectively):
01 RCL n ; recall Rn
02 FRAC ; and take its fractional part
03 LN ; get its ln value
04 CHS ; change the sign
05 1/x ; get the reciprocal
06 12x ; multiply by 12 and rewrite Rn
07 FRAC ; return its fractional part for further usage
In case you need to use Rn for some other purposes (including those described
in this chapter), here's an alternative PRNG using Ri and the formula S[n] =
frac(exp(S[n-1] + 7) / 12):
01 RCL i ; recall Ri
02 FRAC ; and take its fractional part
03 7 ; push 7
04 + ; add 7
05 e^x ; take its natural exponent
06 12/ ; divide by 12 and rewrite Ri
07 FRAC ; return its fractional part for further usage
== Generating several random integers in a single pass ==
As long as N^M fits into nine digits at most, you can generate M pseudorandom
numbers from 0 to N-1 at once to save both the program size and execution
time. Here's how it's done. Suppose we use the PRNG described in the
previous section and continue from that point:
08 RCL i ; suppose we have our upper limit N in Ri
09 x ; multiply by the pseudorandom output
10 INTG ; get the pseudorandom integer Ni
11 LSTx ; restore the raw output
12 FRAC ; get the intermediate fractional part
13 x<>y ; move Ni to the front of the stack
.. ; do something with Ni (not losing the fraction in the reg. Y)
xx x<>y ; move the fraction to the front of the stack
xx GTO 08 ; do the same again to get the next number
== Hidden polynomial evaluator ==
The NPV (net present value) function of the HP 12C in fact evaluates
polynomials with the coefficients stored in R0..Rn and the argument stored
in Ri, but the argument first needs to be converted according to the formula
Ri = (1/x - 1) * 100. Luckily, we have a shortcut to do this:
1/x 1 x<>y D% i
where D% is the delta-% key, left to the normal % key.
Then, we can store the polynomial coefficients in the Horner order (from the
lowest power to the highest) using the CFo function to store the first one
and CFj to store the rest of them. You can also save repeated coefficients
after pressing CFj by specifying [count] Nj to populate move than one
coefficient with the same value. When all coefficients are in place and the
argument is in Ri (converted according to the algorithm above), running NPV
will compute the polynomial value.
There also exists an alternate way of storing the coefficients: store the
polynomial degree d into Rn and then directly assign values to the registers
R0..Rd. This only works in case you don't have multiple consecutively
repeated coefficients, if you do then you will have to use the CFo/CFj/Nj
approach.
== Hidden polynomial solver ==
Once we have stored the coefficients in the registers as described in the
previous section, we can use the IRR (internal rate of return) function to
find the roots of this polynomial.
After entering the coefficients, press 1 IRR and then % + 1/x to display the
actual root.
In case you're getting Error 3 or want to find another root, you can press
CLx and supply a different initial guess by typing it in and then pressing
RCL g R/S IRR. You'll then need to issue 1 x<>y % + 1/x to get the actual
root value.
In case you're getting Error 7, this means the HP-12C cannot solve the
polynomial equation with these coefficients. That might be because they
cannot all be positive or negative.
== Indirect register access ==
Officially, HP 12C doesn't support indirect register addressing, but that's
not entirely true. Combined with the register Rn, the CFj command allows
accessing main memory registers by their index, namely:
* writing: [index-1] n [value] CFj
* reading: [index] n RCL CFj
When writing, it does the pre-increment of the Rn contents, so you must
specify 1 less into the index, e.g. -1 to write to R0 and 4 to write to R5.
When reading, the CFj command automatically post-decrements the contents of
the Rn register.
When writing one position beyond the last available index, an error won't be
thrown but the value will be stored into the FV register instead. E.g. if
your program takes up all available steps and only R0 to R6 are accessible,
writing a value with 6 n [value] CFj will populate the FV register instead
of the inaccessible R7 register.
Note: inside a program, it's better to use STO n instead of just n to prevent
inadvertent triggering of TVM calculations that could alter the other
financial registers. Same goes for STO i and others.
== Harnessing extra memory from the Nj registers ==
In case you don't need the polynomial functionality or the NPV/IRR
functionality per se, you can use the 21 additional registers the 12C
provides to store integers from 0 to 99 inclusively (you'll get an Error 6
if you try writing a non-integer number or an integer out of these bounds).
You'll also need the register n to control the interaction with Nj
registers: unlike the previous section, this is the only way of interacting
with them.
* Write the register Nj[index]: [index] n [value] Nj
* Read the register Nj[index]: [index] n RCL Nj
The index must be from 0 to 20, the value must be from 0 to 99. Both must be
integers. Unlike CFj and RCL CFj, the Nj and RCL Nj commands do not alter
the Rn register contents.
Despite the limitations on what they can store, the Nj registers survive the
CL.FIN (f x<>y) command. On the CL.REG (f CLx) command, they all get reset
to 1.
Although it's not documented anywhere, the amount of available Nj registers
is one more than the amount of available general purpose registers displayed
in g MEM. That is, if all program steps are taken, you have 7 general
purpose registers and 8 Nj registers available.
== (Ab)using RCL CFj to organize small non-nested loops ==
Since the 12C doesn't have any special loop functionality, a normal loop
would look like this (using R0..R4 for storage arithmetic, R0 provided as an
example here):
(n) 5 ; push iteration count
(n+1) STO 0 ; store iteration count into R0
(n+2) ... ; loop start
.. ; main loop body
(k) 1 ; push 1
(k+1) STO - 0 ; decrement R0
(k+2) RCL 0 ; recall its contents
(k+3) x=0 ; if it's 0
(k+4) GTO (k+6) ; then skip the next instruction
(k+5) GTO (n+2) ; else go to the loop start
However, if the iteration count is small enough (within the amount of
accessible main registers + 1) and the body doesn't alter the contents of
Rn, we can save one program step by doing this instead:
(n) 5 ; push iteration count
(n+1) STO n ; set Rn
(n+2) ... ; loop start
.. ; main loop body
(k) RCL CFj ; decrement the n register
(k+1) RCL n ; recall its contents
(k+2) x=0 ; if it's 0
(k+3) GTO (k+5) ; then skip the next instruction
(k+4) GTO (n+2) ; else go to the loop start
As a bonus, you can issue RCL CFj earlier in the loop body instead and do
something with the register contents read by it. This allows to dynamically
iterate over register contents in a list-like fashion.
These are the programs that mostly solve a single task well.
== Trigonometry ==
Among other things, the 12C is famous for the absence of trigonometry
functions. These programs aim to fill in this gap. For a full set of
functions in a single program, see the SUITES section.
## Sine or cosine (Taylor-based) ##
Only calculates either sine or cosine, but does it with maximum accuracy.
Reuses the same Taylor series algorithm. The argument must be in radians.
To calculate sine, type 1 STO 3 [arg] STO 1 STO 2 R/S.
To calculate cosine, type 0 STO 3 1 STO 1 STO 2 [arg] R/S.
Listing:
01 ENTER ; commit x to stack
02 x ; calculate x^2
03 CHS ; calculate -x^2
04 STO 5 ; save -x^2 to R5
05 RCL 2 ; loop start; save the current result at R2
06 STO 6 ; ...to the previous result cache at R6
07 RCL 5 ; recall -x^2
08 RCL 3 ; recall c
09 1 ; calculate c + 1
10 +
11 / ; calculate (-x^2) / (c + 1)
12 RCL 3 ; recall c
13 2 ; calculate c + 2
14 +
15 / ; calculate (-x^2) / (c + 1) / (c + 2)
16 STO x 1 ; multiply this result by t and store into t
17 2 ; add 2
18 STO + 3 ; ...to the c value
19 RCL 1 ; recall t
20 STO + 2 ; and add it to R2
21 RCL 2 ; recall the result
22 RCL 6 ; recall the previous result cache
23 - ; subtract the cache value
24 x=0 ; if they are equal...
25 GTO 27 ; then skip to the end
26 GTO 05 ; else go to the loop start
27 RCL 2 ; display the result
28 GTO 00 ; program end
## Sine and cosine (fast) - recommended ##
Based on the approximation to convert a hyperbolic cosine value into the
trigonometric cosine value. Calculates both sine and cosine with
near-machine precision, leaving cosine in the X register and sine in the Y
register. Takes about 4 seconds to run.
Enter the argument (from 0 to Pi/2 radians) and press R/S. The cosine value
will be on the display. Press x<>y to view the sine value or the division
key to get the tangent. From the tangent view, press 1/x to get the
cotangent.
Listing:
01 STO 0 ; store our argument x into R0
02 4 ; push 4
03 y^x ; calculate x^4
04 12/ ; calculate x^4 / 12 as the variable K (storing it into Ri)
05 STO 1 ; store it into R1 too
06 ENTER ; push into the stack
07 x ; calculate K^2
08 1
09 4
10 0
11 / ; calculate K^2 / 140
12 STO + 1 ; append into R1
13 RCL i ; recall K
14 x ; calculate K^3 / 140
15 9
16 9
17 0
18 / ; calculate K^3 / 138600
19 STO + 1 ; append this into R1 too
20 RCL 0 ; recall x
21 e^x ; natural exponent
22 ENTER ; push into the stack
23 1/x ; reciprocal: calculate e^(-x)
24 + ; calculate e^x + e^(-x)
25 2 ; calculate (e^x + e^(-x))/2
26 / ; the result is cosh x which can be used to approx cos x
27 STO - 1 ; subtract this from R1
28 2 ; and add the final 2
29 STO + 1 ; the cosine value is now in R1
30 RCL 1 ; recall it
31 ENTER ; push into the stack
32 x ; calculate (cos x)^2
33 1 ; push 1
34 - ; calculate (cos x)^2 - 1
35 CHS ; calculate 1 - (cos x)^2 = (sin x)^2
36 SQRT ; calculate sin x
37 RCL 1 ; recall cos x
38 GTO 00 ; PROFIT!
## FinSin: sine and arcsine based on the financial functions ##
Using the NPV and IRR functions of the 12C, we can evaluate polynomials to
approximate trigonometric functions. Particularly, we can get a nice
approximation from the setup close to what the Apollo mission had been using
when landing on the Moon. The arcsine function is just solving the root of
the same polynomial by replacing the free coefficient 0 with the opposite to
the argument, so it takes little space too. Not counting the setup steps,
the entire code is just 22 steps long. The sine part is accurate to the
fourth decimal digit after rounding, the arcsine part is accurate to about
6.2 angular seconds.
5 n CL.STAT 1.57065 STO 1 .64323 CHS STO 3 .0727 STO 5
All input/output is in degrees. Run with R/S to get sine, run with GTO 13 R/S
to get arcsine.
Listing:
; sine part
01 9
02 0
03 x<>y
04 / ; divide by 90, then perform 1/x
05 1 ; prepare as NPV input
06 x<>y
07 D%
08 i ; save as NPV input
09 CLx ; ensure the R0 is set to 0
10 STO 0 ; to make the calculations correct
11 NPV ; run it
12 GTO 00 ; this is your sine
; arcsine part
13 CHS ; change the argument sign
14 STO 0 ; replace the free coefficient with it
15 1 ; prepare to run IRR
16 RCL g R/S ; run it
17 % ; get the true root
18 +
19 1/x
20 9
21 0
22 x ; multiply to get the degrees
23 GTO 00 ; this is your arcsine
## Arctangent (fixed-time) ##
Based on the arithmetic-geometric mean algorithm. For the default 15
iterations, the runtime is just under 17 seconds regardless of the argument.
You can change the amount of iterations in the code to get faster results at
the expense of accuracy. At the default iteration count, it starts losing
the last (9th) digit of precision at the values of x about 2.1, but never
loses accuracy up to the 8th decimal digit. The tests showed no practical
sense increasing the iteration count above 15.
No setup or argument conversion necessary, just enter the argument and press
R/S.
Listing:
01 STO 4 ; store the x argument into R4
02 ENTER ; push into the stack
03 x ; calculate x^2
04 1 ; push 1
05 STO 2 ; store 1 into b while at it
06 + ; calculate 1 + x^2
07 SQRT ; calculate sqrt(1 + x^2)
09 1/x ; calculate a0
09 STO 1 ; store a
10 STO 3 ; store a0
11 1 ; push the iteration count (15 by default)
12 5
13 STO 0 ; store iteration count into R0
14 RCL 1 ; loop start, recall a
15 RCL 2 ; recall b
16 + ; a + b
17 2 ; push 2
18 / ; get the arithmetic mean
19 STO 1 ; store the new a value
20 RCL 2 ; recall b again
21 x ; calculate a*b
22 SQRT ; calculate sqrt(a*b)
23 STO 2 ; store the new b value
24 1 ; push 1
25 STO - 0 ; decrement the iteration count
26 RCL 0 ; recall the iteration count
27 x=0 ; if out of iterations, then
28 GTO 30 ; go to the end
29 GTO 14 ; else go to the loop start
30 RCL 4 ; recall x
31 RCL 3 ; recall a0
32 x ; multiply them
33 RCL 1 ; recall a
34 / ; the result is x * a0 / a
35 GTO 00 ; program end
## Scaling down the arctangent arguments ##
In order to bring any argument to the range 0<=x<=1, you can use the
following algorithm:
1. Save the pi/2 constant into some register the program doesn't touch, e.g.
to R7: 1.570796327 STO 7
2. Before running the arctangent program, type in your large argument and
then press 1/x.
3. Press R/S to start the program. When it finishes, type RCL 7 x<>y - to get
your result.
## Calculating arcsine and arccosine using arctangent programs ##
Using any program to calculate arctangents, you can calculate arcsine by
keying in:
[arg] ENTER ENTER x 1 x<>y - SQRT / R/S
and arccosine by keying in:
[arg] ENTER ENTER x 1 x<>y - SQRT x<>y / R/S
or
[arg] ENTER ENTER x 1 x<>y - SQRT / 1/x R/S
## Useful constants ##
These constants are recommended to save somewhere in the registers to aid
with trigonometric operations.
* 1.570796327: pi/2, can be used to derive the arctangents of large arguments
and complementary angles.
* 57.29577951: 180/pi, defines how many degrees are in a radian. Divide by it
to convert into radians, multiply by it to convert into degrees.
== Coordinate unit conversions ==
Another practical feature common for almost all scientific calculators but
missing in the 12C is the ability to convert degree-minute-second notation
used for geographical coordinates to just degrees (with a fractional part)
and vice versa. Let's fix this.
This program combines the two algorithms into a single conversion utility.
Enter a positive value to convert ddd.mmss... to decimal degrees, and a
negative value to convert decimal degrees to the ddd.mmss... format. The
sign will be changed according to the format: ddd.mmss is always positive,
decimal degrees is always negative.
## Listing ##
01 INTG ; get the degrees part
02 STO 0 ; store the degrees into R0
03 LSTx ; get the original value
04 FRAC ; get the fractional part
05 0 ; push 0
06 x<>y ; exchange the stack
07 x<=y ; if the value is negative
08 GTO 23 ; then go to the decimal to DMS part
09 EEX ; start of the DMS to decimal part; push 100
10 2 ;
11 x ; multiply by 100
12 ENTER ; push this into stack
13 INTG ; get the minutes part
14 6 ; push 60
15 0
16 / ; get the decimal part of minutes
17 STO + 0 ; add to the result
18 x<>y ; get the cached minutes.seconds
19 FRAC ; get the fractional part
20 3 ; push 36
21 6
22 GTO 39 ; go to the common finalizer
23 6 ; start of the decimal to DMS part; push 60
24 0
25 STO 1 ; cache 60 into R1
26 x ; convert into minutes.parts_of_minute format
27 ENTER ; stash it
28 INTG ; get the amount of minutes
29 EEX ; push 100
30 2
31 / ; divide
32 STO + 0 ; add to the result cache
33 x<>y ; retrieve the minutes.parts_of_minute value
34 FRAC ; get the fractional part
35 RCL 1 ; recall 60
36 x ; convert into the number of seconds
37 EEX ; push 10000
38 4
39 / ; common finalizer
40 STO + 0 ; add to the result
41 RCL 0 ; show the result
42 CHS ; change the result sign
43 GTO 00 ; program end
== Measurement unit conversions ==
This section contains short snippets to convert between some US measurement
units and world standard measurement units. Assumes that the argument
already has been pushed to the stack (e.g. typed in and then ENTER is
pressed).
Temperature conversions:
* Celsius to Fahrenheit: 1.8 x 32 +
* Fahrenheit to Celsius: 32 - 1.8 /
Some US length unit conversions can be simplified if we enter a constant
0.3048 (meters in a foot) into the n register my the means of multiplying
0.0254 meters in an inch by 12:
0254 12x
With this in place, we have:
* Meters to feet: RCL n /
* Feet to meters: RCL n x
* Meters to yards: RCL n / 3 /
* Yards to meters: RCL n x 3 x
The rest of the conversions is just constant-based:
* Centimeters to inches: 2.54 /
* Inches to centimeters: 2.54 x
* Kilometers/kph to US miles/mph: 1.609344 /
* US miles/mph to kilometers/kph: 1.609344 x
* Kilometers/kph to international nautical miles/knots: 1.852 /
* International nautical miles/knots to kilometers/kph: 1.852 x
* Kilometers per hour to meters per second: 3.6 /
* Meters per second to kilometers per hour: 3.6 x
* Kilograms to pounds: .45359237 /
* Pounds to kilograms: .45359237 x
* Liters to US gallons: 3.785411784 /
* US gallons to liters: 3.785411784 x
* Milliliters to US fluid ounces: 29.57352956 /
* US fluid ounces to milliliters: 29.57352956 x
* Hectopascals (mbar) to mmHg: 1.333223874 /
* mmHg to hectopascals (mbar): 1.333223874 x
== Modular exponentiation ==
This program combines the concepts from the modulo tricks section with a fast
modular exponentiation algorithm to compute large exponents modulo some
other value within reasonable time on HP 12C.
Enter the arguments for a ^ b (mod c) in the following order: a ENTER b ENTER
c.
## Listing ##
01 1 13 x 25 FRAC 37 FRAC 49 x
02 STO 3 14 . 26 LSTx 38 x 50 RCL 5
03 ROLL 15 5 27 INTG 39 RCL 5 51 +
04 STO 0 16 STO 5 28 STO 2 40 + 52 INTG
05 ROLL 17 + 29 x<>y 41 INTG 53 STO 1
06 STO 2 18 INTG 30 x=0 42 STO 3 54 GTO 20
07 ROLL 19 STO 1 31 GTO 43 43 RCL 1 55 RCL 3
08 STO 1 20 RCL 2 32 RCL 1 44 STO x 1 56 GTO 00
09 RCL 0 21 x=0 33 STO x 3 45 RCL 0
10 STO / 1 22 GTO 55 34 RCL 0 46 STO / 1
11 RCL 1 23 2 35 STO / 3 47 RCL 1
12 FRAC 24 / 36 RCL 3 48 FRAC
== Prime number generator (fun-sized) ==
This program successively generates first ten prime numbers (from 2 to 29).
Start with GTO 00 R/S. Press any key to stop, R/S to resume.
Because the program runs out of precision after the 10th iteration, this is
more for amusement purposes, although the algorithm itself uses no
(external) registers and can be used within some other programs to get first
ten primes in linear time.
This program merely _subtracts_ two 5-digit numbers from one another
digit-wise, modulo 10. The usage guide will show how to use it in
subtraction-only (XOR-like) encryption/decryption.
Note: this program is optimized for speed rather than size. The
three-register version with loops was about half as long but took over 10
seconds instead of <6.5 on the original HP 12C.
## Listing ##
01 EEX 17 INTG 33 RCL 5 49 LSTx 65 INTG 81 RCL 2
02 9 18 STO + 1 34 x 50 FRAC 66 STO - 4 82 FRAC
03 / 19 LSTx 35 INTG 51 RCL 5 67 RCL 5 83 +
04 INTG 20 FRAC 36 STO + 4 52 x 68 STO / 0 84 RCL 5
05 STO 0 21 RCL 5 37 LSTx 53 INTG 69 STO / 1 85 x
06 LSTx 22 x 38 FRAC 54 STO - 2 70 STO / 2 86 RCL 3
07 FRAC 23 INTG 39 RCL 5 55 LSTx 71 STO / 3 87 FRAC
08 1 24 STO + 2 40 x 56 FRAC 72 STO / 4 88 +
09 0 25 LSTx 41 INTG 57 RCL 5 73 RCL 0 89 RCL 5
10 STO + 0 26 FRAC 42 STO - 0 58 x 74 FRAC 90 x
11 STO 1 27 RCL 5 43 LSTx 59 INTG 75 x 91 RCL 4
12 STO 2 28 x 44 FRAC 60 STO - 3 76 RCL 1 92 FRAC
13 STO 3 29 INTG 45 RCL 5 61 LSTx 77 FRAC 93 +
14 STO 4 30 STO + 3 46 x 62 FRAC 78 + 94 RCL 5
15 STO 5 31 LSTx 47 INTG 63 RCL 5 79 RCL 5 95 x
16 x 32 FRAC 48 STO - 1 64 x 80 x 96 GTO 00
## Usage guide ##
This simple program can be used to aid with one-time pad encryption, where
you have a non-repeatable keystream and a message of the same length, both
converted into digital form and split into blocks of five decimal digits.
You have to process the keystream and message pairs one block at a time.
For more convenience, you can disable the decimals display by pressing f 0.
1. Input a 5-digit block of the keystream first, then a 5-digit block of the
message/ciphertext as the second part of the same number.
2. Press R/S. The encryption/decryption result will be displayed.
The operation is the same for encryption and decryption.
The result of each operation must contain exactly five digits. If the result
on the display contains less digits, pad them manually with zeroes on the
left side, e.g. if you get 394, write down 00394 as the result.
Example. Suppose we have a message block 31415 and a key block 92653.
Enter the number to encrypt with the key block first and the message second:
9265331415 R/S
We get the result 61248. To decrypt it with the same key block, enter:
9265361248 R/S
We get the initial message block 31415.
Using the approach introduced in FinSin, we can generalize it to calculate
any functions (and their inverses) that can be represented with a Minimax
polynomial approximation. In an even more general sense, this program 1)
automates the steps required to use the HP 12C's hidden polynomial
evaluator, 2) enables solving the equation P(x) = a, not just P(x) = 0, by
supplying a as the argument to the inverse function routine.
## Listing ##
; direct function computation part
01 1/x ; prepare the NPV input
02 1
03 x<>y
04 D%
05 i ; save as NPV input
06 NPV ; run it
07 GTO 00 ; get the direct result
; inverse computation part
08 RCL 0 ; recall the free coefficient a0
09 x<>y ; get the argument to the front
10 STO - 0 ; subtract it from a0 in R0
11 x<>y ; get the original a0 to the front
12 1 ; prepare to run IRR: (1 origA0 arg -)
13 RCL g R/S ; run it
14 % ; get the true root
15 +
16 1/x
17 x<>y ; get the original a0 to the front
18 STO 0 ; store the original a0 back to R0
19 x<>y ; show the result again
20 GTO 00 ; end of the program
## Setup ##
Here are some recommended polynomial setups for functions which are simple to
fill in.
* Sine/arcsine (input/output in radians, high precision, R0..R7):
0 CFo 1 CFj 0 CFj 6 1/x CHS CFj 0 CFj 120 1/x CFj 0 CFj 5125 1/x CHS CFj
or
7 n CL.STAT STO 0 1 STO 1 6 1/X CHS STO 3 120 1/x STO 5 5125 1/x CHS STO 7
* Cosine/arccosine (input/output in radians, mid-high precision, R0..R8):
1 CFo 0 CFj .5 CHS CFj 0 CFj 24 1/x CFj 0 CFj 721 1/x CHS CFj 0 CFj
42875 1/x CFj
or
8 n CL.STAT STO 7 1 STO 0 .5 CHS STO 2 24 1/x STO 4 721 1/x CHS STO 6
42875 1/x STO 8
* ...to be continued
## Usage ##
* Compute the direct function: [arg] R/S
* Compute the inverse function: [arg] GTO 08 R/S
== KHCEmu12: WDR's Der Know-How Computer emulator ==
This is an experiment of creating a fully functional emulator/VM on the HP
12C. This program emulates an educational paper computer model by WDR
Computer Club called "Der Know-How Computer" created in 1983 (which is
interesting since the 12C itself was first introduced in 1981), whose very
limited instruction set was proven to be Turing-complete. While the original
KHC worksheet had 8 registers and 21 program steps, this emulator supports
up to 5 registers and 25 steps.
Note that it is quite slow on the original 12C and even a simple addition
program can take well over a minute to execute, but this was meant to be a
proof of concept rather than a usable tool.
## Listing ##
01 1 17 - 33 LSTx 49 GTO 63 65 5
02 STO i 18 EEX 34 FRAC 50 x 66 +
03 RCL i 19 2 35 2 51 3 67 STO n
04 x=0 20 x<>y 36 5 52 x<>y 68 RCL CFj
05 GTO 00 21 y^x 37 x 53 - 69 x=0
06 1 22 RCL CFj 38 x<>y 54 x<>y 70 GTO 72
07 - 23 x<>y 39 x=0 55 5 71 GTO 76
08 ENTER 24 / 40 GTO 42 56 + 72 RCL i
09 ENTER 25 INTG 41 GTO 45 57 STO n 73 1
10 5 26 EEX 42 x<>y 58 x<>y 74 +
11 / 27 2 43 STO i 59 RCL CFj 75 STO i
12 INTG 28 / 44 GTO 03 60 + 76 RCL i
13 STO n 29 FRAC 45 2 61 CFj 77 1
14 ENTER 30 4 46 x<>y 62 GTO 76 78 +
15 5 31 x 47 x<=y 63 ROLL 79 STO i
16 x 32 INTG 48 GTO 50 64 x<>y 80 GTO 03
## Instruction set and format ##
Like in the original paper computer, the KHCEmu12's instructions are numbered
from 1. That allowed to merge the Stop instruction with the Jump
instruction: Stop means Jump 0, just like in the 12C itself.
Hence, the actual KHCEmu12 instruction set has the following opcodes:
0) JMP k: jump to the instruction number k (JMP 0 is equivalent to halt/stop);
1) INC k: increment the register k;
2) DEC k: decrement the register k;
3) ISZ k: skip the next instruction if the register k is set to zero.
Before storing the program in the 12C's registers, every instruction needs to
be converted into exactly two digits according to the formula: instr = 25 *
opcode + k. Then, in case k is a register number (i.e. the opcode is not 0),
1 needs to be subtracted. E.g. the halt instruction will be 00 and the JMP
12 instruction will be 12, but the INC 3 will be 1 * 25 + 3 - 1 = 27, the
ISZ 1 instruction will be 3 * 25 + 1 - 1 = 75 and so on.
Afterwards, the program needs to be packed from the least significant digit
pairs to the most into the first five registers (R0 to R4).
Let's see an example. Here's a "standard" adding program for the Know-How
Computer that takes two registers and leaves the sum in the first of them
(the instruction numbers aren't usually written but here they are written
for clarity):
Now, let's pack these instructions into the first five registers of the 12C.
Starting from the first encoded instruction, group them into five and write
these groups in the reversed order:
0276512504 STO 0
0 STO 1
0 STO 2
0 STO 3
0 STO 4
In this format, the program is ready to run.
## Usage ##
* Enter the program in the format stated above into the registers R0 to R4.
* Enter the input register state into the registers R5 to R8 and RFV.
* Press R/S to execute the program.
* Look at the outputs by probing the registers R5 to R8 and RFV.
The KHC registers are mapped to the 12C registers as follows:
* KHC register 1 is stored in R5,
* KHC register 2 is stored in R6,
* KHC register 3 is stored in R7,
* KHC register 4 is stored in R8,
* KHC register 5 is stored in RFV.
These programs combine several utilities based on a common topic into one,
and can be executed from different points to perform different functions.
Due to their length, the listings are hereby provided in a columnar format
without comments.
== Luxferre's Trigonometry Suite ==
This HP 12C program combines the above algorithms for fast direct
trigonometry and fixed-time inverse trigonometric functions with a handy
storage for the radian conversion constant 57.29577951 and optional
automatic conversion of the inverse trig results back to degrees.
## Listing ##
01 STO 0 21 e^x 41 x 61 RCL 1 81 /
02 4 22 ENTER 42 1 62 RCL 2 82 R/S
03 y^x 23 1/x 43 x<>y 63 + 83 5
04 12/ 24 + 44 - 64 2 84 7
05 STO 1 25 2 45 SQRT 65 / 85 .
06 ENTER 26 / 46 / 66 STO 1 86 2
07 x 27 STO - 1 47 R/S 67 RCL 2 87 9
08 1 28 2 48 STO 4 68 x 88 5
09 4 29 STO + 1 49 ENTER 69 SQRT 89 7
10 0 30 RCL 1 50 x 70 STO 2 90 7
11 / 31 ENTER 51 1 71 1 91 9
12 STO + 1 32 x 52 STO 2 72 STO - 0 92 5
13 RCL i 33 1 53 + 73 RCL 0 93 1
14 x 34 - 54 SQRT 74 x=0 94 x
15 9 35 CHS 55 1/x 75 GTO 77 95 GTO 00
16 9 36 SQRT 56 STO 1 76 GTO 61
17 0 37 RCL 1 57 STO 3 77 RCL 4
18 / 38 GTO 00 58 1 78 RCL 3
19 STO + 1 39 ENTER 59 5 79 x
20 RCL 0 40 ENTER 60 STO 0 80 RCL 1
## Main usage ##
* Sine/cosine/tangent/cotangent: just enter the argument (from 0 to Pi/2
radians) and press R/S. The cosine value will be on the display. Press x<>y
to view the sine value or the division key to get the tangent. From the
tangent view, press 1/x to get the cotangent.
* Arcsine: enter the argument and press GTO 39 R/S. Press R/S again in a
second.
* Arccosine: enter the argument and press GTO 39 R/S. Press 1/x R/S in a
second.
* Arctangent: enter the argument and press GTO 48 R/S.
* Arccotangent: enter the argument and press 1/x GTO 48 R/S.
* After running any inverse trigonometric function, you should either press
GTO 00 to finish the operation or press R/S once again to convert the result
from radians into degrees.
* To convert any radian value in the X register into degrees, press GTO 83
R/S.
* To convert any degree value in the X register into radians, press GTO 83
1/x R/S 1/x.
## Special cases ##
* For obvious reasons, arcsin 1 and arccos 0 cannot be directly calculated by
this program (a divide-by-zero condition occurs). Since arcsin 1 = arccos 0
= Pi/2 radians or 90 degrees, see below how to get the Pi/2 value.
* To get the Pi/2 constant value, press 90 1/x GTO 83 R/S 1/x.
* To get the Pi constant value, press 90 1/x GTO 83 R/S 1/x 2 x. This method
is better than just entering 180 in the above sequence as it retains one
more digit of precision.
* To just get the radian conversion constant, press 1 GTO 83 R/S.
## Advanced usage ##
* Convert polar coordinates r and phi to Cartesian coordinates x and y:
[input phi] (GTO 83 1/x R/S 1/x) R/S [input r] x x<>y LSTx x
(enter the part in (parentheses) if phi is in degrees)
You'll get the y coordinate in the register X. Press x<>y to see the x
coordinate.
* Convert Cartesian coordinates x and y to polar coordinates r and phi:
To get r: [input x] ENTER ENTER x [input y] ENTER x + SQRT
To get phi AFTER you get r: / GTO 39 R/S 1/x R/S
(press R/S again to convert phi into degrees)
To get phi independently: [input y] ENTER [input x] / GTO 48 R/S
Note that you may need to adjust the angle manually according to the quadrant.
* Complex number multiplication (using polar coordinate conversions)
Multiple complex numbers xn + i * yn can be processed at once.
1. For every complex number xn + i * yn, convert the (xn, yn) pair to (rn,
tn) polar coordinates.
2. Multiply all rn values together into the value Pr.
3. Sum all tn values together into the value St.
4. Convert the (Pr, St) pair from the polar coordinates back to the Cartesian
coordinates (Xr, Yr).
5. The resulting complex number is Xr + i * Yr.
* Complex number division (using polar coordinate conversions)
For two complex numbers x1 + i * y1 and x2 + i * y2:
1. For both complex numbers, convert the (xn, yn) pair to (rn, tn) polar
coordinates.
2. Convert the (r1/r2, t1-t2) pair back to the Cartesian coordinates (Xr, Yr).
3. The resulting complex number is Xr + i * Yr.
* Raising complex numbers to real powers (using polar coordinate conversions)
For the complex number x + i * y and the real exponent n, perform these steps:
1. Convert the (x, y) pair to (r, t) polar coordinates.
2. Convert the (r^n, t * n) pair back to the Cartesian coordinates (Xr, Yr).
3. The resulting complex number is Xr + i * Yr.
## Inverse trigonometry precision adjustment ##
The program steps 58 and 59 contain the constant 15, specifying the number of
iterations for the AGM-based arctangent algorithm. Feel free to reduce this
constant to calculate the inverse trig functions faster at the expense of
the result accuracy. The number of iterations is mapped to the guaranteed
accuracy and run time (on the original 12C) as follows:
To adjust the constant, enter P/R GTO . 57 and then the two digits from the
mapping above. Press P/R to return to the run mode.
== Luxferre's Complex Number Suite ==
Most scientific calculators have basic arithmetic operations on complex
numbers. Let's equip the 12C with them.
## Listing ##
01 x<>y 14 STO 0 27 ROLL 40 x 53 x<>y 66 ENTER
02 ROLL 15 ROLL 28 ROLL 41 LSTx 54 STO 0 67 x
03 + 16 ENTER 29 ROLL 42 ROLL 55 ROLL 68 x<>y
04 ROLL 17 ENTER 30 x<>y 43 ROLL 56 RCL 1 69 ENTER
05 + 18 x 31 / 44 STO 0 57 x 70 x
06 x<>y 19 ROLL 32 CHS 45 x<>y 58 ROLL 71 +
07 ROLL 20 ROLL 33 RCL 0 46 x 59 x 72 SQRT
08 GTO 00 21 x 34 RCL 1 47 LSTx 60 x<>y 73 GTO 00
09 x<>y 22 LSTx 35 ROLL 48 ROLL 61 ROLL
10 ROLL 23 ROLL 36 ROLL 49 x<>y 62 -
11 ROLL 24 + 37 ROLL 50 ROLL 63 RCL 0
12 STO 1 25 / 38 STO 1 51 + 64 x<>y
13 ROLL 26 LSTx 39 x<>y 52 RCL 0 65 GTO 00
## Usage guide ##
This guide assumes the numbers a + b * i and c + d * i.
The real part of the result will be in the X register, the imaginary part
will be in the Y register (press x<>y to see it).
* Addition: [a] ENTER [b] ENTER [c] ENTER [d] R/S
* Subtraction: [a] ENTER [b] ENTER [c] CHS ENTER [d] CHS R/S
* Multiplication: [a] ENTER [b] ENTER [c] ENTER [d] GTO 37 R/S
* Division: [a] ENTER [b] ENTER [c] ENTER [d] GTO 09 R/S
* Absolute value (single argument): [a] ENTER [b] GTO 66 R/S
Addition/subtraction and absolute value use no memory registers.
Multiplication and division use R0 and R1 registers.
== Luxferre's Nautical Converter ==
This program combines the coordinate conversion routines with some
measurement unit conversions related to nautical navigation. Usage guide
follows.
The program can run in two modes, not interfering with each other.
## Listing ##
01 INTG 21 6 41 RCL 0 61 2 81 3
02 STO 0 22 GTO 39 42 CHS 62 / 82 2
03 LSTx 23 6 43 GTO 00 63 12x 83 2
04 FRAC 24 0 44 1 64 ENTER 84 4
05 0 25 STO 1 45 . 65 5 85 STO PV
06 x<>y 26 x 46 8 66 . 86 R/S
07 x<=y 27 ENTER 47 STO 4 67 2 87 RCL 5
08 GTO 23 28 INTG 48 2 68 8 88 -
09 EEX 29 EEX 49 x 69 x 89 RCL 4
10 2 30 2 50 STO 2 70 STO 6 90 /
11 x 31 / 51 3 71 1 91 GTO 00
12 ENTER 32 STO + 0 52 2 72 . 92 RCL 4
13 INTG 33 x<>y 53 STO 5 73 8 93 x
14 6 34 FRAC 54 2 74 5 94 RCL 5
15 0 35 RCL 1 55 . 75 2 95 +
16 / 36 x 56 5 76 STO 3 96 GTO 00
17 STO + 0 37 EEX 57 4 77 1
18 x<>y 38 4 58 STO i 78 .
19 FRAC 39 / 59 ENTER 79 3
20 3 40 STO + 0 60 EEX 80 3
## Coordinate conversion mode ##
The first mode is the coordinate conversion mode.
Enter a positive value to convert ddd.mmss... to decimal degrees, and a
negative value to convert decimal degrees to the ddd.mmss... format. Press
R/S and get the converted result. The sign will be changed according to the
format: ddd.mmss is always positive, decimal degrees is always negative.
You can just enter the program up to the step 43 if you only need this mode.
## Unit conversion mode ##
The second mode is the measurement unit conversion mode. Set it up with GTO
44 R/S. After you press this sequence at least once, the following
conversions become available:
* Fahrenheit to Celsius: GTO 87 R/S
* Celsius to Fahrenheit: GTO 92 R/S
* m/s to km/h: RCL 2 x
* km/h to m/s: RCL 2 /
* Nautical miles to kilometers: RCL 3 x
* Kilometers to nautical miles: RCL 3 /
* Statute miles to kilometers: RCL 6 x
* Kilometers to statute miles: RCL 6 /
* Inches to centimeters: RCL i x
* Centimeters to inches: RCL i /
* Feet to meters: RCL n x
* Meters to feet: RCL n /
* Yards to meters: RCL n x 3 x
* Meters to yards: RCL n / 3 /
* mmHg to hectopascals (mbar): RCL PV x
* Hectopascals (mbar) to mmHg: RCL PV /
These conversions are available at any time, using coordinate conversion
doesn't affect them. However, if you have changed any of the registers
R2-R6, Rn, Ri or RPV, you need to enter the GTO 44 R/S sequence again in
order to be able to use the unit conversion routines correctly.
== Neo12C: a handy 2x2 matrix operations suite ==
While HP 15C contains full-featured matrix support and some other advanced
scientific calculators have 2x2 matrix operation capabilities, the 12C has
been missing all that. Not anymore. The 12C's register memory is enough for
full 2x2 matrix operation support.
The program leaves exactly 8 free main registers to enter the element data
for the two 2x2 matrices.
## Listing ##
01 STO x 0 19 RCL 6 37 RCL 1 55 RCL 3 73 RCL 0
02 STO x 1 20 STO x 2 38 RCL 7 56 RCL 7 74 STO 3
03 STO x 2 21 RCL 7 39 x 57 x 75 x<>y
04 STO x 3 22 STO x 3 40 + 58 + 76 STO 0
05 GTO 60 23 GTO 60 41 STO 1 59 STO 3 77 1
06 RCL 4 24 RCL 0 42 RCL 2 60 RCL 0 78 CHS
07 STO + 0 25 ENTER 43 ENTER 61 RCL 3 79 STO x 1
08 RCL 5 26 ENTER 44 ENTER 62 x 80 STO x 2
09 STO + 1 27 RCL 4 45 RCL 4 63 RCL 1 81 GTO 60
10 RCL 6 28 x 46 x 64 RCL 2 82 RCL 1
11 STO + 2 29 RCL 1 47 RCL 3 65 x 83 RCL 2
12 RCL 7 30 RCL 6 48 RCL 6 66 - 84 STO 1
13 STO + 3 31 x 49 x 67 R/S 85 x<>y
14 GTO 60 32 + 50 + 68 STO / 0 86 STO 2
15 RCL 4 33 STO 0 51 STO 2 69 STO / 1 87 GTO 60
16 STO x 0 34 x<>y 52 x<>y 70 STO / 2
17 RCL 5 35 RCL 5 53 RCL 5 71 STO / 3
18 STO x 1 36 x 54 x 72 RCL 3
## Usage guide ##
Suppose we have two matrices A and B with their elements entered into
corresponding registers:
A: B:
R0 R1 R4 R5
R2 R3 R6 R7
Then, the following operations are available for the matrix A and modify it
in place:
And the following operations are available for the two matrices A and B:
* Addition (A + B): GTO 06 R/S
* Subtraction (B - A aka -A + B): 1 CHS GTO 00 R/S GTO 06 R/S
* Full matrix multiplication (A x B): GTO 24 R/S
* Hadamard product (element-wise multiplication, A (o) B): GTO 15 R/S
The result is always put into R0..R3 (modifying the matrix A in place).
Notice that in case of subtraction, the matrix order is reversed.
At the end of these operations, the determinant of the resulting matrix is
displayed.
(Required!) Press GTO 00 if you don't need to compute the inverse matrix.
At the end of these operations, the determinant of the resulting matrix is
displayed.
To directly calculate the determinant of matrix A without modifying it, press
GTO 60 R/S.
Press GTO 00 if you don't need to compute the inverse matrix after the
determinant is displayed.
## Tips ##
* Trace value of the matrix A: RCL 0 RCL 3 +
* Trace value of the matrix B: RCL 4 RCL 7 +
* Quickly enter the identity matrix into A: 1 STO 0 STO 3 CLx STO 1 STO 2
* Quickly enter the identity matrix into B: 1 STO 4 STO 7 CLx STO 5 STO 6
################################### GAMES ####################################
This section contains some simple calculator games that can fit into the
12C's limited 99-step program memory.
Most game programs in this section require a PRNG seed value from 0 to 1 to
be entered into the financial register n.
E.g. to enter 0.384 as a seed, type .384 n.
== Dice roll simulator ==
The simplest game in the list (or rather a helper program for tabletop games).
Enter the number of sides into Ri, e.g. by pressing 6 i for a 6-sided die.
Then, just press R/S every time you want to get a new random value from 1 to
N.
## Listing ##
01 RCL n ; recall Rn
02 FRAC ; and take its fractional part
03 3 ; push 3
04 + ; add 3
05 e^x ; take its natural exponent
06 12x ; multiply by 12 and rewrite Rn
07 FRAC ; return its fractional part for further usage
08 RCL i ; recall the number of sides
09 x ; multiply by the number of sides
10 1 ; push 1
11 + ; add 1
12 INTG ; get the integer part
13 GTO 00 ; program end
== YahBox12 (Yahtzee dice box simulator) ==
A Yahtzee tabletop game helper program to shuffle five 6-sided dice, reroll
them by selection and display their sum.
## Listing ##
01 STO 2 12 0 23 GTO 37 34 + 45 STO + 4
02 EEX 13 STO 5 24 RCL n 35 INTG 46 1
03 5 14 STO x 1 25 FRAC 36 GTO 44 47 STO - 0
04 STO / 1 15 STO x 2 26 3 37 RCL 1 48 RCL 0
05 STO / 2 16 STO x 3 27 + 38 INTG 49 x=0
06 5 17 RCL 2 28 e^x 39 RCL 5 50 GTO 52
07 STO 0 18 INTG 29 12x 40 / 51 GTO 11
08 CLx 19 RCL 5 30 FRAC 41 FRAC 52 RCL 4
09 STO 3 20 / 31 6 42 RCL 5 53 RCL 3
10 STO 4 21 FRAC 32 x 43 x 54 STO 1
11 1 22 x=0 33 1 44 STO + 3 55 GTO 00
## Setup ##
Before the first-time launch, select a random seed from 0 to 1, then press
[seed] n.
No other setup is necessary.
## Gameplay ##
* Type in 11111 R/S to get the initial/full roll.
* To reroll certain positions, type in ones in the positions you want to
reroll and zeroes in the positions you want to keep, then press R/S.
E.g. you have rolled 35253 and only want to keep the fives, so you enter
10101 R/S next.
Suppose you have rolled 25555 afterwards and aim for a yahtzee, so you
enter 10000 R/S as you only want to reroll the first position.
* After getting the roll, you can press x<>y to view the dice sum.
== Nicomachus ==
This is more of a simple arithmetic trick rather than a full game, but it was
featured in a famous BASIC games collection book. You think of a number
between 1 and 100 and enter its remainders when divided by 3, 5 and 7, and
the machine guesses the initial number. No setup necessary.
Think of a number N between 1 and 100. Find its remainders from division by
3, 5 and 7. Then input:
[N mod 3] ENTER [N mod 5] ENTER [N mod 7] R/S
The calculator will show your initial number.
== UltimateMoo12 (Bulls and Cows HP 12C port) ==
Probably the most complicated game in the list. Requires proper setup.
The goal of the game is to guess a four-digit number (where all digits are
different) in the fewest tries possible.
## Listing ##
01 CL.STAT 18 CLx 35 STO / 2 52 RCL n 69 1
02 RCL i 19 Nj 36 RCL 7 53 - 70 STO - 1
03 FRAC 20 RCL 7 37 STO x 4 54 RCL 7 71 RCL 1
04 7 21 STO / 4 38 RCL 4 55 / 72 x=0
05 + 22 1 39 INTG 56 FRAC 73 GTO 75
06 e^x 23 STO + 1 40 RCL 7 57 x=0 74 GTO 48
07 12/ 24 3 41 / 58 GTO 60 75 1
08 FRAC 25 RCL 1 42 FRAC 59 GTO 69 76 STO - 0
09 RCL 7 26 x<=y 43 RCL 7 60 RCL 7 77 RCL 0
10 x 27 GTO 02 44 x 61 1 78 x=0
11 INTG 28 R/S 45 STO n 62 RCL 0 79 GTO 81
12 STO n 29 STO 2 46 1 63 RCL 1 80 GTO 32
13 RCL Nj 30 4 47 Nj 64 - 81 RCL 8
14 x=0 31 STO 0 48 RCL 7 65 x=0 82 STO / 4
15 GTO 02 32 4 49 STO x 2 66 ROLL 83 RCL 3
16 RCL n 33 STO 1 50 RCL 2 67 ROLL 84 STO - 3
17 STO + 4 34 RCL 8 51 INTG 68 STO + 3 85 GTO 28
## Setup ##
Before the first-time launch, select a random seed from 0 to 1, then press
this sequence:
(f 0) f REG 10 STO 7 EEX 4 STO 8 [seed] i
(the f 0 is optional just to get rid of the decimal zeroes, not affecting the
gameplay)
## Gameplay ##
1. Press f PRGM R/S to start the game for the first time.
2. When 4 appears, enter your four-digit guess and press R/S. The number you
enter must contain exactly four different digits (leading zero allowed).
3. The game will display your guess score: tens are bulls, ones are cows.
Bulls are the number of digits guessed in the correct places.
Cows are the number of digits present in the number but guessed in the
wrong positions.
E.g.:
- 40 means the number has been fully guessed,
- 12 means one digit has been guessed in the correct place and two in the
wrong places,
- 4 means all digits have been guessed but in the wrong positions,
- 0 means none of the entered digits are present in the target number.
4. Enter your new guess and press R/S. You can view your previous guess by
pressing RCL 2.
5. The game doesn't keep track of attempt count but the goal is to get the
score 40 within seven attempts.
6. If you fully give up, you can view the target number by pressing f 4 RCL 4.
7. To start over with a new number to guess, press f PRGM R/S.
== Hurwump12: Hunt the Hurkle + Mugwump 2-in-1 game pack for HP 12C ==
This is a program that contains two games with a lot of common logic, Hunt
the Hurkle and Mugwump. You wander around a grid of caves and scan for a
monster you need to hunt down (Hurkle/Mugwump respectively), and you need to
find it as quickly as possible for the village safety. These two games
became the precursors to more advanced adventure games like Hunt the Wumpus.
## Listing ##
01 STO 0 15 / 29 RCL 1 43 RCL 0 57 RCL 4
02 RCL n 16 ENTER 30 - 44 x=0 58 /
03 FRAC 17 INTG 31 STO 3 45 GTO 50 59 STO - 3
04 3 18 STO 2 32 ENTER 46 ROLL 60 ROLL
05 + 19 - 33 x 47 ROLL 61 x=0
06 e^x 20 1 34 SQRT 48 + 62 GTO 67
07 12x 21 0 35 STO 4 49 GTO 25 63 /
08 FRAC 22 x 36 x<>y 50 ROLL 64 3
09 EEX 23 STO 1 37 ENTER 51 RCL 3 65 x
10 2 24 CLx 38 x 52 5 66 STO + 3
11 x 25 R/S 39 LSTx 53 STO 3 67 RCL 3
12 INTG 26 RCL 2 40 x<>y 54 ROLL 68 GTO 25
13 1 27 - 41 SQRT 55 x=0
14 0 28 x<>y 42 x<>y 56 GTO 60
## Setup ##
Before the first-time launch, select a random seed from 0 to 1, then press
[seed] n.
No other setup is necessary.
## Gameplay ##
* Press 0 R/S to start the Hunt the Hurkle game, 1 R/S to start the Mugwump
game (in fact, any non-zero value in the register X will start the Mugwump
game).
* Enter the (x,y) coordinates (from (0,0) to (9,9)) to guess the
Hurkle/Mugwump location: x ENTER y R/S
* Hurkle mode: you get a direction 1 to 9 (according to the keyboard) to go
further, 5 is a victory.
* Mugwump mode: you get the grid distance (in the amount of squares to
travel) to the Mugwump, 0 is a victory.
* Press GTO 00 [0|1] R/S to start over the game.
The (0,0) point is the northwestern corner of the grid.
In the Hurkle mode, the directions can easily be visualized if you look at
the calculator keyboard:
* 1 is go southwest,
* 2 is go south,
* 3 is go southeast,
* 4 is go west,
* 5 is no movement (you've found the target),
* 6 is go east,
* 7 is go northwest,
* 8 is go north,
* 9 is go northeast.
== Hurwurk12: Hunt the Hurkle + Mugwump + Snark 3-in-1 game pack ==
In case you also need a Snark game for more grid hide-and-seek adventure
variety, this is a larger version of the previous pack that also includes it.
## Listing ##
01 STO 0 21 0 41 STO i 61 GTO 25 81 ROLL
02 RCL n 22 x 42 ROLL 62 ROLL 82 RCL 5
03 FRAC 23 STO 1 43 ENTER 63 RCL 3 83 RCL 6
04 3 24 CLx 44 x 64 5 84 +
05 + 25 R/S 45 STO 6 65 STO 3 85 RCL i
06 e^x 26 RCL 2 46 LSTx 66 ROLL 86 x<=y
07 12x 27 - 47 x<>y 67 x=0 87 GTO 90
08 FRAC 28 x<>y 48 SQRT 68 GTO 72 88 2
09 EEX 29 RCL 1 49 x<>y 69 RCL 4 89 GTO 25
10 2 30 - 50 RCL 0 70 / 90 -
11 x 31 STO 3 51 x=0 71 STO - 3 91 x=0
12 INTG 32 ENTER 52 GTO 62 72 ROLL 92 GTO 95
13 1 33 x 53 x<>y 73 x=0 93 CLx
14 0 34 STO 5 54 ROLL 74 GTO 79 94 GTO 25
15 / 35 SQRT 55 2 75 / 95 1
16 ENTER 36 STO 4 56 x<=y 76 3 96 GTO 25
17 INTG 37 x<>y 57 GTO 81 77 x
18 STO 2 38 ROLL 58 ROLL 78 STO + 3
19 - 39 ROLL 59 ROLL 79 RCL 3
20 1 40 x 60 + 80 GTO 25
## Setup ##
Before the first-time launch, select a random seed from 0 to 1, then press
[seed] n.
No other setup is necessary.
## Gameplay ##
* Press 0 R/S to start the Hunt the Hurkle game, 1 R/S to start the Mugwump
game, 2 R/S to start the Snark game (in fact, any value > 1 in the register
X will start the Snark game).
* In the Hurkle/Mugwump mode, enter the (x,y) coordinates (from (0,0) to
(9,9)) to guess the Hurkle/Mugwump location: x ENTER y R/S
* In the Snark mode, first enter the circle radius r and then the
coordinates: r ENTER x ENTER y R/S
* Hurkle mode: you get a direction 1 to 9 (according to the keyboard) to go
further, 5 is a victory.
* Mugwump mode: you get the grid distance (in the amount of squares to
travel) to Mugwump, 0 is a victory.
* Snark mode: you get 0 if Snark is outside the circle, 1 if Snark is on the
circle, 2 if inside the circle. 1 with the circle of radius 0 is a victory.
* Press GTO 00 [0|1|2] R/S to start over the game.
The (0,0) point is the northwestern corner of the grid.
In the Hurkle mode, the directions can easily be visualized if you look at
the calculator keyboard:
* 1 is go southwest,
* 2 is go south,
* 3 is go southeast,
* 4 is go west,
* 5 is no movement (you've found the target),
* 6 is go east,
* 7 is go northwest,
* 8 is go north,
* 9 is go northeast.
## OptiWump12: an optimized Mugwump port for the 12C ##
In case you're only interested in the Mugwump game among the trilogy, here's
a highly optimized version.
## Setup ##
Before the first-time launch, select a random seed from 0 to 1, then press
[seed] n.
No other setup is necessary.
* Press R/S to start the game.
* When prompted, enter the (x,y) coordinates (from (0,0) to (9,9)) to guess
the Mugwump location in the form: x ENTER y
* The grid distance (in the amount of squares to travel) to Mugwump is
displayed, 0 is a victory.
* Press GTO 00 R/S to start over.
The (0,0) point is the northwestern corner of the grid.
## OptiSnark12: an optimized Snark port for the 12C ##
In case you're only interested in the Snark game among the trilogy, here's a
highly optimized version.
## Setup ##
Before the first-time launch, select a random seed from 0 to 1, then press
[seed] n.
No other setup is necessary.
## Listing ##
01 RCL n 11 INTG 21 STO 0 31 SUM+ 41 -
02 FRAC 12 STO 7 22 f SUM 32 x<>y 42 ENTER
03 3 13 LSTx 23 RCL 0 33 ENTER 43 x=0
04 + 14 FRAC 24 R/S 34 x 44 1
05 e^x 15 1 25 RCL 8 35 RCL 3 45 -
06 12x 16 0 26 - 36 x<>y 46 CHS
07 FRAC 17 x 27 SUM+ 37 x<=y 47 GTO 21
08 1 18 INTG 28 ROLL 38 GTO 41
09 0 19 STO 8 29 RCL 7 39 2
10 x 20 CLx 30 - 40 GTO 21
## Gameplay ##
* Press R/S to start the game.
* When prompted, enter the circle radius r and then the (x,y) coordinates
(from (0,0) to (9,9)) to guess the Mugwump location in the form: r ENTER x
ENTER y
* The game displays 0 if Snark is outside the circle, 1 if Snark is on the
circle, 2 if inside the circle. 1 with the circle of radius 0 is a victory.
* Press GTO 00 R/S to start over.
The (0,0) point is the northwestern corner of the grid.
## Hurkle3D aka Depth Charge ##
This is an adaptation of Hunt the Hurkle for a 3D space 10x10x10 units each,
also known as the (submarine-themed) Depth Charge game from the old BASIC
books. You enter the three coordinates (surface coordinates and then the
depth) and get the directions where to move next.
## Listing ##
01 RCL n 16 RCL 5 31 STO 4 46 x 61 RCL 0
02 FRAC 17 x 32 ROLL 47 SQRT 62 x=0
03 3 18 INTG 33 RCL 3 48 / 63 GTO 73
04 + 19 STO 2 34 - 49 STO - 4 64 ENTER
05 e^x 20 LSTx 35 STO 0 50 x<>y 65 ENTER
06 12x 21 FRAC 36 ROLL 51 x=0 66 x
07 FRAC 22 RCL 5 37 RCL 2 52 GTO 61 67 SQRT
08 1 23 x 38 - 53 ENTER 68 /
09 0 24 INTG 39 x<>y 54 ENTER 69 .
10 STO 5 25 STO 1 40 RCL 1 55 x 70 3
11 x 26 CLx 41 - 56 SQRT 71 x
12 INTG 27 R/S 42 x=0 57 / 72 STO - 4
13 STO 3 28 5 43 GTO 50 58 3 73 RCL 4
14 LSTx 29 . 44 ENTER 59 x 74 GTO 27
15 FRAC 30 5 45 ENTER 60 STO + 4
## Setup ##
Before the first-time launch, select a random seed from 0 to 1, then press
[seed] n.
No other setup is necessary.
## Gameplay ##
Press R/S to start the game. When prompted with 0, enter the (x,y,z)
coordinates (from (0,0,0) to (9,9,9)) to guess the Hurkle/submarine location:
x ENTER y ENTER z R/S
The (0,0,0) point is northwestern point on the grid, with depth 0 (surface).
The game will respond with the directions in the following format:
[surf].[depth], where the [surf] value is the same as for the regular
Hurkle, according to the calculator keypad layout:
* 1 is go southwest,
* 2 is go south,
* 3 is go southeast,
* 4 is go west,
* 5 is no movement (you're on the same surface coordinates as the target),
* 6 is go east,
* 7 is go northwest,
* 8 is go north,
* 9 is go northeast,
and the [depth] value is the direction for the third coordinate, according to
the calculator keypad layout:
* 2 is go up,
* 5 is no movement (you're on the required depth),
* 8 is go down.
So, you have won whenever the game responds with 5.5 (no movement required in
either direction).
To restart the game from the beginning, press GTO 00 R/S.
## Nim12: a classic variant of the Nim game ##
This is a 12-coin version of Nim on the 12C. Ironic, huh? Modeled after the
oldschool Dr. Nim toy and a lot of homebrew implementations, it only offers
an option for the player to go first, a single pile of coins and 3 coins
maximum to be taken in a single turn. However, you can actually customize
the number of coins, the allowed maximum number to take and the victory
condition at the beginning of the source code, for instance, turning it into
the "23 matches" game or even a "100 game". The machine is always aiming for
the optimal strategy and also asks you to repeat your move if you try taking
away an invalid number of coins.
1. Press (GTO 00) R/S to start the game from the beginning.
2. The remaining number of coins is displayed. Enter the number of coins to
take from the pile. The game will prompt you again if you enter an invalid
amount.
3. The game will briefly show you how many coins the computer opponent has
taken, and then goes back to step 2.
4. When the coins cannot be taken anymore, the game shows 0 or 1 and ends.
Press R/S to restart.
Victory condition: depending on the game mode, 0 is the victory condition if
the winner is supposed to take the last coin, 1 if the loser is supposed to
take the last coin.
== EvenWins12: a port of the "Even Wins" game to HP 12C ==
"Even Wins" is a Nim-like game where the goal is to get an even number of
coins/matches/other tokens at the end of the game. Two players can take from
1 to 4 tokens at a time. The starting token amount is 27 by default but is
customizable (must be odd). You always go first and the machine is following
the optimal strategy.
No setup is necessary. Removing the decimals with f 0 is recommended though.
* Press R/S to start the game.
* When prompted with the current token count in the pile, enter the amount of
tokens to remove (from 1 to 4) and press R/S. You'll be re-prompted if an
invalid amount is entered.
* The game will briefly display how many tokens the machine has taken and
then prompt you again.
* In case the pile becomes empty after your or the machine's move, the game
ends, displaying both your and machine's piles of tokens in the format PPMM
where PP is the two digits of how many tokens the player has taken and MM is
the two digits of how many tokens the machine has taken, e.g. 1116 means you
have taken 11 tokens and the machine has taken 16 tokens.
* Whoever has an even amount of tokens at the end is the winner.
## Customization ##
The first two steps of the program contain the total number of tokens. 27 is
the classic default value. You can replace it with any two-digit odd number.