Reverse engineering the phi and pi calculators

For discussion of specific patterns or specific families of patterns, both newly-discovered and well-known.
User avatar
simsim314
Posts: 1731
Joined: February 10th, 2014, 1:27 pm

Re: Reverse engineering the phi and pi calculators

Post by simsim314 » November 7th, 2019, 4:35 pm

dvgrn wrote:
November 7th, 2019, 3:13 pm
As currently configured, the script emulates the phi calculator, figures out where to expect blocks and boats in all the registers (simple and binary), and stops when reality fails to match the model.
The next step would be to check out that particular case. There could be two options that I see:

1. The lookup table model return Z and actually there should be NZ (a typo of some sort or bug in the table generation).
2. Something missed from the state. Some block or boat was ignored, so you think it's always Z in that case but it depends on some SL you missed.

If you know exactly where it happens - and you know to correlate between everything, and you know it's the first place - the bug should be in that single operation that returns the wrong value.

It takes much longer with my script to run 13K iterations. Anyway I've somewhat more troublesome issue (I guess you'll solve the bugs eventually - if you're starting to give up I can try to get into this "physical level" but it less of my interest):

I see a lot of logic going on inside the calculator. But I have no clue how to use them to actually program stuff. There is some level of knowledge between the hardware and software which I completely lack. A good start would be a set of simple algorithms explained and coded into the calculator:

1. Given hardcoded A and B - print A, print B and print A > B, A + B, A - B, A * B, A / B, A % B,
2. Nth Fibonacci, N!, Sum(1+2+...+N) etc.
3. Simple primer (divide N by all numbers 2...N-1)
4. The same as 1 above with fixed point floats.
5. Math functions like sqrt, sin, exp etc.
6. More complex data structures (effective primer).

After we have some basic understanding of lower level coding with APGsembly:

7. Hopefully some programming language above assembly and below C. More toward the assembly of 8 bit computer.
8. I can see how libraries can come to be in this language.

User avatar
dvgrn
Moderator
Posts: 6049
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Reverse engineering the phi and pi calculators

Post by dvgrn » November 7th, 2019, 6:51 pm

simsim314 wrote:
November 7th, 2019, 4:35 pm
I see a lot of logic going on inside the calculator. But I have no clue how to use them to actually program stuff. There is some level of knowledge between the hardware and software which I completely lack. A good start would be a set of simple algorithms explained and coded into the calculator:

1. Given hardcoded A and B - print A, print B and print A > B, A + B, A - B, A * B, A / B, A % B,
2. Nth Fibonacci, N!, Sum(1+2+...+N) etc.
3. Simple primer (divide N by all numbers 2...N-1)
4. The same as 1 above with fixed point floats.
5. Math functions like sqrt, sin, exp etc.
6. More complex data structures (effective primer).
I probably won't have the patience to use the pi/phi calculator technology to write any algorithms beyond your #3, but most of #1 and #2 are fairly straightforward to implement with just the simple sliding-block registers.

The emulator started out with nothing but those simple unary sliding-block registers (SBRs), plus the 2D memory used by the Osqrtlogt pattern. I wrote sample A+B and A*B code for those registers, which you can find archived toward the top of the emulator code (not running, because they're replaced by the phi calculator's code lower down).

Adding the contents of two SBRs together might look like the following, as long as you don't mind zeroing the original registers. To keep those values intact, they'd have to be copied out to a third register, then copied back as part of the ADD operation.

Code: Select all

# ADD R0 R1 pseudocode
# DEC_R0:
#    TEST-DECREMENT R0
#    CASE r0_test_result == 0
#        Jump to DEC_R1
#    CASE r0_test_result != 0
#        INC OUT
#        Jump to DEC_R0
# DEC_R1:
#    TEST-DECREMENT R1
#    CASE r1_test_result == 0
#        HALT
#    CASE r1_test_result != 0
#        INC OUT
#        Jump to DEC_R1
   
# ADD R0 R1 program
APGsembly = """INITIAL; Z; A1; TDEC R0
A1; Z; A2; TDEC R1
A1; NZ; A1; TDEC R0, INC OUT
A2; Z; A3; NOP
A2; NZ; A2; TDEC R1, INC OUT
A3; Z; A3; HALT"""
progname = "ADD R0+R1"
registers = {"R0":13,"R1":21,"R2":0,"OUT":0}
Multiplying with just SBRs might look like this:

Code: Select all

# multiply pseudocode
# DEC_R0:
#     TEST-DECREMENT R0
#     CASE R0-TEST-RESULT == 0
#         HALT
#     CASE R0-TEST-RESULT != 0
#         COPY R1 -> R2
#         TRANSFER R2 -> OUT
#     Jump to DEC_R0

# For multiplication we need an extra register for temporary storage.
# R0 will be decremented steadily till it's 0,
#   after which the program will halt.
# R1 will be copied to R2, decreasing temporarily to 0
# R2 will temporarily contain a copy of R1,
#   but then it will be decremented back to 0 while
#   simultaneously incrementing both R1 and OUT.

# MULT R1 R2
APGsembly = """INITIAL; Z; A1; TDEC R0
A1; Z; NOSTATE; HALT
A1; NZ; A2; TDEC R1
A2; Z; A3; TDEC R2
A2; NZ; A2; TDEC R1, INC R2
A3; Z; A1; TDEC R0
A3; NZ; A3; TDEC R2, INC R1, INC OUT"""
progname = "Multiply R0*R1"
registers = {"R0":13,"R1":21,"R2":0,"OUT":0}
It's O(A*B) to multiply A times B, if you have nothing but SBRs to work with... but at least it's easy to see what's going on, and the circuitry isn't too complicated. It would be easy to assemble a complete computer implementing the above A+B or A*B algorithms, even just by hand. (Better to write a compiler, of course -- but I'd like to try replacing all those Silver reflectors with Snarks and syringes!)

Also, the phi calculator's APGsembly code is nicely commented -- unlike the pi calculator's code which is a deep dark mystery because it's decompiled straight from the pattern and has lost all its labels. Phi-calculator comments include

# Initialise T0 with the number '22'.
# Initialise T1 with the number '400'.
# Print the value "1.6", and leave the algorithm to do the rest.
# Multiply T0 by 10 and store in T2
# Set the value of R3 equal to 9 (the largest decimal digit)
# Clear T4
# Copy R3 to R4 via R1
# Copy T3 to T2
# Add R4 to T3
# Copy R3 to R4 via R1
# Multiply T3 by R4 and store in T4
# Compare T4 with T1
# Subtract T4 from T1
# Centuple T1
# 10-tuple T0
# Add R4 to T0

Any of these that involve the binary "T" registers are going to be doing their operations on strings of binary digits, so that might let you check off a few more of the items on your list. I haven't really tried to get an overall picture of what the phi calculator is doing yet, but it might be worthwhile to write some pseudocode based on the above comments, and see if the whole algorithm ends up making any sense.

User avatar
dvgrn
Moderator
Posts: 6049
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Reverse engineering the phi and pi calculators

Post by dvgrn » November 7th, 2019, 9:23 pm

Ha -- finally found and swatted the last silly bug in the emulator. I had managed to put labels on the B0 and B1 inputs in the ADD and SUB modules backwards. I've fixed the labels in the pattern in the first post now.

Here's a version of the emulator that doesn't bother running the real phi calculator in parallel. It could be made to go quite a bit faster, but this seems good enough for now:

Code: Select all

x = 606, y = 14, rule = LifeHistory
2A11.2A.A5.2A5.2A.A6.2A.A4.2A.A4.2A.A6.2A.A6.2A.A6.2A.A4.A.2A4.2A3.2A
4.2A.A6.2A.A6.2A.A4.2A3.2A4.2A.A4.2A3.2A4.2A.A6.2A.A6.2A.A4.2A3.2A4.
2A.A6.2A.A6.2A.A6.2A.A4.2A.A4.2A3.2A2.2A.A6.2A.A6.2A.A6.2A.A4.2A.A6.
2A.A5.2A4.2A3.A.2A4.A.2A6.2A.A6.2A.A4.2A.A6.2A.A6.2A.A5.2A3.A.2A6.2A.
A6.2A.A6.2A.A6.2A.A4.A.2A6.2A.A6.2A.A6.2A.A6.2A.A6.2A.A5.2A3.2A.A6.2A
.A4.2A3.2A2.2A3.2A4.2A.A6.2A.A6.2A.A6.2A.A4.A.2A6.2A.A$.A11.A.2A6.A5.
A.2A6.A.2A4.A.2A4.A.2A6.A.2A6.A.2A6.A.2A4.2A.A4.2A3.2A4.A.2A6.A.2A6.A
.2A4.2A3.2A4.A.2A4.2A3.2A4.A.2A6.A.2A6.A.2A4.2A3.2A4.A.2A6.A.2A6.A.2A
6.A.2A4.A.2A4.2A3.2A2.A.2A6.A.2A6.A.2A6.A.2A4.A.2A6.A.2A6.A5.A3.2A.A
4.2A.A6.A.2A6.A.2A4.A.2A6.A.2A6.A.2A6.A3.2A.A6.A.2A6.A.2A6.A.2A6.A.2A
4.2A.A6.A.2A6.A.2A6.A.2A6.A.2A6.A.2A6.A3.A.2A6.A.2A4.2A3.2A2.2A3.2A4.
A.2A6.A.2A6.A.2A6.A.2A4.2A.A6.A.2A$A10.2A9.A4.2A4.2A2.2A4.2A6.2A6.2A
2.2A4.2A2.2A4.2A2.2A4.2A6.2A11.2A4.2A2.2A4.2A2.2A4.2A11.2A4.2A11.2A4.
2A8.2A2.2A4.2A11.2A8.2A4.2A2.2A8.2A4.2A6.2A15.2A2.2A8.2A8.2A12.2A2.2A
4.2A3.A5.A8.2A6.2A8.2A2.2A4.2A6.2A2.2A4.2A2.2A4.2A3.A8.2A2.2A4.2A2.2A
4.2A2.2A4.2A2.2A12.2A2.2A14.2A2.2A4.2A2.2A14.2A3.A8.2A2.2A26.2A4.2A2.
2A14.2A8.2A6.2A2.2A4.2A$2A9.A10.2A3.A5.A3.A5.A7.A7.A3.A5.A3.A5.A3.A5.
A8.A2.2A3.2A2.A5.A3.A5.A3.A5.A3.2A3.2A2.A5.A3.2A3.2A2.A5.A9.A3.A5.A3.
2A3.2A2.A9.A5.A3.A9.A5.A7.A3.2A3.2A6.A3.A9.A9.A13.A3.A5.A4.2A4.2A8.A
7.A8.A3.A5.A7.A3.A5.A3.A5.A4.2A8.A2.A5.A3.A5.A3.A5.A3.A14.A2.A15.A3.A
5.A3.A15.A4.2A7.A3.A9.2A3.2A2.2A3.2A2.A5.A3.A15.A9.A8.A2.A5.A$12.A15.
A5.A3.A5.A7.A7.A3.A5.A3.A5.A3.A5.A6.A3.A.A.A.A3.A5.A3.A5.A3.A5.A2.A.A
.A.A3.A5.A2.A.A.A.A3.A5.A9.A3.A5.A2.A.A.A.A3.A9.A5.A3.A9.A5.A7.A2.A.A
.A.A7.A3.A9.A9.A13.A3.A5.A18.A7.A10.A3.A5.A7.A3.A5.A3.A5.A12.A4.A5.A
3.A5.A3.A5.A3.A12.A4.A15.A3.A5.A3.A15.A13.A3.A8.A.A.A.A2.A.A.A.A3.A5.
A3.A15.A9.A6.A4.A5.A$2A9.2A9.2A3.2A4.2A2.2A4.2A6.2A6.2A2.2A4.2A2.2A4.
2A2.2A4.2A6.2A4.A.A4.2A4.2A2.2A4.2A2.2A4.2A4.A.A4.2A4.2A4.A.A4.2A4.2A
8.2A2.2A4.2A4.A.A4.2A8.2A4.2A2.2A8.2A4.2A6.2A4.A.A8.2A2.2A8.2A8.2A12.
2A2.2A4.2A3.2A4.2A7.2A6.2A8.2A2.2A4.2A6.2A2.2A4.2A2.2A4.2A3.2A7.2A2.
2A4.2A2.2A4.2A2.2A4.2A2.2A12.2A2.2A14.2A2.2A4.2A2.2A14.2A3.2A7.2A2.2A
10.A.A6.A.A4.2A4.2A2.2A14.2A8.2A6.2A2.2A4.2A$.A3.2A.A4.2A.A6.A5.2A.A
4.A5.A3.2A.A4.2A.A6.2A.A6.2A.A6.2A.A6.2A5.2A.A6.2A.A6.2A.A6.2A.A5.2A.
A6.2A.A5.2A.A6.2A.A6.2A.A4.A5.A4.2A.A6.2A.A6.2A.A6.2A.A6.2A.A4.2A.A5.
2A.A4.2A.A6.2A.A6.2A.A6.2A.A4.2A.A6.2A.A6.A5.A5.2A6.2A6.2A.A4.A5.A3.
2A.A4.A5.A5.2A.A6.A5.2A6.2A.A6.2A.A4.A5.A5.2A.A6.2A6.2A.A6.2A.A6.2A.A
6.2A.A6.2A.A6.A3.2A.A6.2A.A5.2A.A5.2A.A6.2A.A6.2A.A6.2A.A6.2A.A6.2A4.
A5.A$A4.A.2A4.A.2A5.A6.A.2A5.A5.A2.A.2A4.A.2A6.A.2A6.A.2A6.A.2A7.A9.
2A4.A.2A6.A.2A6.A.2A9.2A4.A.2A9.2A4.A.2A6.A.2A5.A5.A7.2A4.A.2A6.A.2A
6.A.2A6.A.2A4.A.2A9.2A2.A.2A6.A.2A6.A.2A6.A.2A4.A.2A6.A.2A5.A5.A7.A7.
A6.A.2A5.A5.A2.A.2A5.A5.A4.A.2A5.A7.A6.A.2A6.A.2A5.A5.A4.A.2A7.A6.A.
2A6.A.2A6.A.2A6.A.2A6.A.2A5.A4.A.2A6.A.2A9.2A7.2A4.A.2A6.A.2A6.A.2A6.
A.2A7.A5.A5.A$2A9.2A4.2A3.2A3.2A4.2A2.2A4.2A6.2A6.2A8.2A2.2A4.2A2.2A
4.2A4.A11.A8.2A2.2A4.2A8.2A8.A2.2A4.2A8.A2.2A4.2A2.2A8.2A4.2A8.A8.2A
2.2A4.2A2.2A4.2A2.2A4.2A6.2A8.A6.2A2.2A4.2A8.2A2.2A4.2A6.2A2.2A4.2A3.
2A4.2A5.A7.A5.2A8.2A4.2A6.2A2.2A4.2A8.2A3.2A5.A11.2A2.2A4.2A2.2A4.2A
8.2A4.A5.2A4.2A2.2A8.2A4.2A2.2A4.2A2.2A9.2A7.2A8.2A8.A8.A2.2A4.2A2.2A
4.2A2.2A8.2A10.A5.2A4.2A$11.A5.A9.A5.A3.A5.A7.A7.A9.A3.A5.A3.A5.A5.2A
9.A9.A3.A5.A9.A8.A3.A5.A8.A3.A5.A3.A9.A5.A8.A9.A3.A5.A3.A5.A3.A5.A7.A
8.A7.A3.A5.A9.A3.A5.A7.A3.A5.A17.2A6.2A4.A9.A5.A7.A3.A5.A9.A11.2A10.A
3.A5.A3.A5.A9.A5.2A4.A5.A3.A9.A5.A3.A5.A3.A19.A9.A8.A8.A3.A5.A3.A5.A
3.A9.A11.2A4.A5.A$2A10.A5.A3.2A4.A5.A3.A5.A7.A7.A9.A3.A5.A3.A5.A2.2A
11.2A9.A3.A5.A9.A7.2A3.A5.A7.2A3.A5.A3.A9.A5.A7.2A9.A3.A5.A3.A5.A3.A
5.A7.A7.2A7.A3.A5.A9.A3.A5.A7.A3.A5.A3.2A4.2A3.2A6.2A7.A9.A5.A7.A3.A
5.A9.A3.2A3.2A13.A3.A5.A3.A5.A9.A2.2A7.A5.A3.A9.A5.A3.A5.A3.A9.2A8.A
9.A7.2A7.2A3.A5.A3.A5.A3.A9.A8.2A7.A5.A$.A9.2A4.2A4.A3.2A4.2A2.2A4.2A
6.2A6.2A8.2A2.2A4.2A2.2A4.2A3.A12.A8.2A2.2A4.2A8.2A8.A2.2A4.2A8.A2.2A
4.2A2.2A8.2A4.2A8.A8.2A2.2A4.2A2.2A4.2A2.2A4.2A6.2A8.A6.2A2.2A4.2A8.
2A2.2A4.2A6.2A2.2A4.2A4.A5.A4.A7.A6.2A8.2A4.2A6.2A2.2A4.2A8.2A4.A4.A
12.2A2.2A4.2A2.2A4.2A8.2A3.A6.2A4.2A2.2A8.2A4.2A2.2A4.2A2.2A10.A7.2A
8.2A8.A8.A2.2A4.2A2.2A4.2A2.2A8.2A9.A6.2A4.2A$A12.2A.A5.A6.2A.A6.2A.A
4.2A.A4.2A.A6.2A.A6.2A.A6.2A.A4.A12.A5.2A.A6.2A.A6.2A.A9.A5.2A.A9.A5.
2A.A6.2A.A6.2A.A9.A5.2A.A6.2A.A6.2A.A6.2A.A4.2A.A9.A3.2A.A6.2A.A6.2A.
A6.2A.A4.2A.A6.2A.A5.A5.A4.A7.A9.2A.A6.2A.A4.2A.A6.2A.A6.2A.A5.A4.A9.
2A.A6.2A.A6.2A.A6.2A.A4.A9.2A.A6.2A.A6.2A.A6.2A.A6.2A.A5.A4.2A.A6.2A.
A9.A8.A5.2A.A6.2A.A6.2A.A6.2A.A4.A9.2A.A$2A11.A.2A5.2A5.A.2A6.A.2A4.A
.2A4.A.2A6.A.2A6.A.2A6.A.2A4.2A11.2A4.A.2A6.A.2A6.A.2A9.2A4.A.2A9.2A
4.A.2A6.A.2A6.A.2A9.2A4.A.2A6.A.2A6.A.2A6.A.2A4.A.2A9.2A2.A.2A6.A.2A
6.A.2A6.A.2A4.A.2A6.A.2A5.2A4.2A3.2A6.2A8.A.2A6.A.2A4.A.2A6.A.2A6.A.
2A5.2A3.2A8.A.2A6.A.2A6.A.2A6.A.2A4.2A8.A.2A6.A.2A6.A.2A6.A.2A6.A.2A
5.2A3.A.2A6.A.2A9.2A7.2A4.A.2A6.A.2A6.A.2A6.A.2A4.2A8.A.2A!
#C [[ WIDTH 800 HEIGHT 240 ZOOM 1.3 ]]
After you run the script, hit 'g' to step, or 'r' to toggle the continuous run mode.

Code: Select all

# APGsembly code emulator, version 0.2 (beta)

import golly as g
from glife.text import make_text
import types

mullookup = {"MUL0 00000":["Z", "00000"],"MUL1 00000":["Z", "00101"],"MUL0 00001":["NZ", "00000"],"MUL1 00001":["NZ", "00101"],
	     "MUL0 00010":["Z", "00001"],"MUL1 00010":["Z", "00110"],"MUL0 00011":["NZ", "00001"],"MUL1 00011":["NZ", "00110"],
	     "MUL0 00100":["Z", "00010"],"MUL1 00100":["Z", "00111"],"MUL0 00101":["NZ", "00010"],"MUL1 00101":["NZ", "00111"],
	     "MUL0 00110":["Z", "00011"],"MUL1 00110":["Z", "01000"],"MUL0 00111":["NZ", "00011"],"MUL1 00111":["NZ", "01000"],
	     "MUL0 01000":["Z", "00100"],"MUL1 01000":["Z", "01001"],"MUL0 01001":["NZ", "00100"],"MUL1 01001":["NZ", "01001"],
	     "MUL0 01010":["Z", "00101"],"MUL1 01010":["Z", "01010"],"MUL0 01011":["NZ", "00101"],"MUL1 01011":["NZ", "01010"],
	     "MUL0 01100":["Z", "00110"],"MUL1 01100":["Z", "01011"],"MUL0 01101":["NZ", "00110"],"MUL1 01101":["NZ", "01011"],
	     "MUL0 01110":["Z", "00111"],"MUL1 01110":["Z", "01100"],"MUL0 01111":["NZ", "00111"],"MUL1 01111":["NZ", "01100"],
	     "MUL0 10000":["Z", "01000"],"MUL1 10000":["Z", "01101"],"MUL0 10001":["NZ", "01000"],"MUL1 10001":["NZ", "01101"],
	     "MUL0 10010":["Z", "01001"],"MUL1 10010":["Z", "01110"],"MUL0 10011":["NZ", "01001"],"MUL1 10011":["NZ", "01110"],
	     "MUL0 10100":["Z", "01010"],"MUL1 10100":["Z", "01111"],"MUL0 10101":["NZ", "01010"],"MUL1 10101":["NZ", "01111"],
	     "MUL0 10110":["Z", "01011"],"MUL1 10110":["Z", "00000"],"MUL0 10111":["NZ", "01011"],"MUL1 10111":["NZ", "00000"],
	     "MUL0 11000":["Z", "01100"],"MUL1 11000":["Z", "00001"],"MUL0 11001":["NZ", "01100"],"MUL1 11001":["NZ", "00001"],
	     "MUL0 11010":["Z", "01101"],"MUL1 11010":["Z", "00010"],"MUL0 11011":["NZ", "01101"],"MUL1 11011":["NZ", "00010"],
	     "MUL0 11100":["Z", "01110"],"MUL1 11100":["Z", "00011"],"MUL0 11101":["NZ", "01110"],"MUL1 11101":["NZ", "00011"],
	     "MUL0 11110":["Z", "01111"],"MUL1 11110":["Z", "00100"],"MUL0 11111":["NZ", "01111"],"MUL1 11111":["NZ", "00100"]}

addlookup = {"000 bit0 A1":["NONE","010 bit1"],"000 bit0 B1":["NZ","000 bit0"],"000 bit0 B0":["Z","000 bit0"],
	     "000 bit1 A1":["NONE","010 bit0"],"000 bit1 B1":["Z","000 bit0"],"000 bit1 B0":["NZ","000 bit0"],
	     "001 bit0 A1":["NONE","011 bit1"],"001 bit0 B1":["NZ","000 bit0"],"001 bit0 B0":["Z","000 bit0"],
	     "001 bit1 A1":["NONE","011 bit0"],"001 bit1 B1":["Z","000 bit0"],"001 bit1 B0":["NZ","000 bit0"],
	     "010 bit0 A1":["NONE","000 bit1"],"010 bit0 B1":["NZ","100 bit1"],"010 bit0 B0":["Z","000 bit0"],
	     "010 bit1 A1":["NONE","000 bit0"],"010 bit1 B1":["Z","100 bit1"],"010 bit1 B0":["NZ","000 bit0"],
	     "011 bit0 A1":["NONE","001 bit1"],"011 bit0 B1":["NZ","000 bit0"],"011 bit0 B0":["Z","100 bit1"],
	     "011 bit1 A1":["NONE","001 bit0"],"011 bit1 B1":["Z","000 bit0"],"011 bit1 B0":["NZ","100 bit1"],
	     "100 bit0 A1":["NONE","110 bit1"],"100 bit0 B1":["NZ","100 bit1"],"100 bit0 B0":["Z","000 bit0"],
	     "100 bit1 A1":["NONE","110 bit0"],"100 bit1 B1":["Z","100 bit1"],"100 bit1 B0":["NZ","000 bit0"],
	     "101 bit0 A1":["NONE","111 bit1"],"101 bit0 B1":["NZ","000 bit0"],"101 bit0 B0":["Z","100 bit1"],
	     "101 bit1 A1":["NONE","111 bit0"],"101 bit1 B1":["Z","000 bit0"],"101 bit1 B0":["NZ","100 bit1"],
	     "110 bit0 A1":["NONE","100 bit1"],"110 bit0 B1":["NZ","100 bit1"],"110 bit0 B0":["Z","100 bit1"],
	     "110 bit1 A1":["NONE","100 bit0"],"110 bit1 B1":["Z","100 bit1"],"110 bit1 B0":["NZ","100 bit1"],
	     "111 bit0 A1":["NONE","101 bit1"],"111 bit0 B1":["NZ","100 bit1"],"111 bit0 B0":["Z","100 bit1"],
	     "111 bit1 A1":["NONE","101 bit0"],"111 bit1 B1":["Z","100 bit1"],"111 bit1 B0":["NZ","100 bit1"]}

sublookup = {"000 stopper0 bit0 A1":["NONE","000 stopper1 bit1"],"000 stopper0 bit0 B0":["Z","000 stopper0 bit0"],
	     "000 stopper0 bit0 B1":["NZ","100 stopper0 bit1"],"000 stopper0 bit1 A1":["NONE","000 stopper1 bit0"],
	     "000 stopper0 bit1 B0":["NZ","000 stopper0 bit0"],"000 stopper0 bit1 B1":["Z","100 stopper0 bit1"],
	     "000 stopper1 bit0 A1":["NONE","FAILURE"],"000 stopper1 bit0 B0":["Z","000 stopper0 bit0"],
	     "000 stopper1 bit0 B1":["NZ","000 stopper0 bit0"],"000 stopper1 bit1 A1":["NONE","FAILURE"],
	     "000 stopper1 bit1 B0":["NZ","000 stopper0 bit0"],"000 stopper1 bit1 B1":["Z","000 stopper0 bit0"],
	     "001 stopper0 bit0 A1":["NONE","001 stopper1 bit1"],"001 stopper0 bit0 B0":["Z","100 stopper0 bit1"],
	     "001 stopper0 bit0 B1":["NZ","000 stopper0 bit0"],"001 stopper0 bit1 A1":["NONE","001 stopper1 bit0"],
	     "001 stopper0 bit1 B0":["NZ","100 stopper0 bit1"],"001 stopper0 bit1 B1":["Z","000 stopper0 bit0"],
	     "001 stopper1 bit0 A1":["NONE","FAILURE"],"001 stopper1 bit0 B0":["Z","000 stopper0 bit0"],
	     "001 stopper1 bit0 B1":["NZ","000 stopper0 bit0"],"001 stopper1 bit1 A1":["NONE","FAILURE"],
	     "001 stopper1 bit1 B0":["NZ","000 stopper0 bit0"],"001 stopper1 bit1 B1":["Z","000 stopper0 bit0"],
	     "010 stopper0 bit0 A1":["NONE","010 stopper1 bit1"],"010 stopper0 bit0 B0":["Z","000 stopper0 bit0"],
	     "010 stopper0 bit0 B1":["NZ","000 stopper0 bit0"],"010 stopper0 bit1 A1":["NONE","010 stopper1 bit0"],
	     "010 stopper0 bit1 B0":["NZ","000 stopper0 bit0"],"010 stopper0 bit1 B1":["Z","000 stopper0 bit0"],
	     "010 stopper1 bit0 A1":["NONE","FAILURE"],"010 stopper1 bit0 B0":["Z","000 stopper0 bit0"],
	     "010 stopper1 bit0 B1":["NZ","100 stopper0 bit1"],"010 stopper1 bit1 A1":["NONE","FAILURE"],
	     "010 stopper1 bit1 B0":["NZ","000 stopper0 bit0"],"010 stopper1 bit1 B1":["Z","100 stopper0 bit1"],
	     "011 stopper0 bit0 A1":["NONE","011 stopper1 bit1"],"011 stopper0 bit0 B0":["Z","000 stopper0 bit0"],
	     "011 stopper0 bit0 B1":["NZ","000 stopper0 bit0"],"011 stopper0 bit1 A1":["NONE","011 stopper1 bit0"],
	     "011 stopper0 bit1 B0":["NZ","000 stopper0 bit0"],"011 stopper0 bit1 B1":["Z","000 stopper0 bit0"],
	     "011 stopper1 bit0 A1":["NONE","FAILURE"],"011 stopper1 bit0 B0":["Z","100 stopper0 bit1"],
	     "011 stopper1 bit0 B1":["NZ","000 stopper0 bit0"],"011 stopper1 bit1 A1":["NONE","FAILURE"],
	     "011 stopper1 bit1 B0":["NZ","100 stopper0 bit1"],"011 stopper1 bit1 B1":["Z","000 stopper0 bit0"],
	     "100 stopper0 bit0 A1":["NONE","100 stopper1 bit1"],"100 stopper0 bit0 B0":["Z","100 stopper0 bit1"],
	     "100 stopper0 bit0 B1":["NZ","100 stopper0 bit1"],"100 stopper0 bit1 A1":["NONE","100 stopper1 bit0"],
	     "100 stopper0 bit1 B0":["NZ","100 stopper0 bit1"],"100 stopper0 bit1 B1":["Z","100 stopper0 bit1"],
	     "100 stopper1 bit0 A1":["NONE","FAILURE"],"100 stopper1 bit0 B0":["Z","000 stopper0 bit0"],
	     "100 stopper1 bit0 B1":["NZ","100 stopper0 bit1"],"100 stopper1 bit1 A1":["NONE","FAILURE"],
	     "100 stopper1 bit1 B0":["NZ","000 stopper0 bit0"],"100 stopper1 bit1 B1":["Z","100 stopper0 bit1"],
	     "101 stopper0 bit0 A1":["NONE","101 stopper1 bit1"],"101 stopper0 bit0 B0":["Z","100 stopper0 bit1"],
             "101 stopper0 bit0 B1":["NZ","100 stopper0 bit1"],"101 stopper0 bit1 A1":["NONE","101 stopper1 bit0"],
	     "101 stopper0 bit1 B0":["NZ","100 stopper0 bit1"],"101 stopper0 bit1 B1":["Z","100 stopper0 bit1"],
	     "101 stopper1 bit0 A1":["NONE","FAILURE"],"101 stopper1 bit0 B0":["Z","100 stopper0 bit1"],
	     "101 stopper1 bit0 B1":["NZ","000 stopper0 bit0"],"101 stopper1 bit1 A1":["NONE","FAILURE"],
	     "101 stopper1 bit1 B0":["NZ","100 stopper0 bit1"],"101 stopper1 bit1 B1":["Z","000 stopper0 bit0"],
	     "110 stopper0 bit0 A1":["NONE","110 stopper1 bit1"],"110 stopper0 bit0 B0":["Z","000 stopper0 bit0"],
	     "110 stopper0 bit0 B1":["NZ","100 stopper0 bit1"],"110 stopper0 bit1 A1":["NONE","110 stopper1 bit0"],
	     "110 stopper0 bit1 B0":["NZ","000 stopper0 bit0"],"110 stopper0 bit1 B1":["Z","100 stopper0 bit1"],
	     "110 stopper1 bit0 A1":["NONE","FAILURE"],"110 stopper1 bit0 B0":["Z","100 stopper0 bit1"],
	     "110 stopper1 bit0 B1":["NZ","100 stopper0 bit1"],"110 stopper1 bit1 A1":["NONE","FAILURE"],
	     "110 stopper1 bit1 B0":["NZ","100 stopper0 bit1"],"110 stopper1 bit1 B1":["Z","100 stopper0 bit1"],
	     "111 stopper0 bit0 A1":["NONE","111 stopper1 bit1"],"111 stopper0 bit0 B0":["Z","100 stopper0 bit1"],
	     "111 stopper0 bit0 B1":["NZ","000 stopper0 bit0"],"111 stopper0 bit1 A1":["NONE","111 stopper1 bit0"],
	     "111 stopper0 bit1 B0":["NZ","100 stopper0 bit1"],"111 stopper0 bit1 B1":["Z","000 stopper0 bit0"],
	     "111 stopper1 bit0 A1":["NONE","FAILURE"],"111 stopper1 bit0 B0":["Z","100 stopper0 bit1"],
	     "111 stopper1 bit0 B1":["NZ","100 stopper0 bit1"],"111 stopper1 bit1 A1":["NONE","FAILURE"],
             "111 stopper1 bit1 B0":["NZ","100 stopper0 bit1"],"111 stopper1 bit1 B1":["Z","100 stopper0 bit1"]}
# Osqrtlogt pseudocode
"""bitval = READ (SQX, SQY)

ADD_1:
    CASE bitval == 0
        Set (SQX, SQY)                   # if current memory bit was OFF, turn it ON,
        Jump to BACK_TO_ORIGIN           #   and then we're done with the carry operation
    CASE bitval != 0
        Jump to CARRY                    # there was a 1 in the current location, which is now a 0,
                                         #   so now we have to toggle the next higher memory bit 
BACK_TO_ORIGIN:
    Set R0=0, R1=0, R2=0, SQX=0, SQY=0
    Jump to ADD_1

CARRY:                                      
    CASE R0 == 0                         # R0 contains _how much further we should look_ on current row
        Set SQX = 0                      # reset to home column
        INC SQY                          # go to next higher row
        INC R1                           # record that we've moved to the next higher row
        Copy R1 to R0 (using R2 to help) # row N of the triangle contains N bits,
                                         #   so set R0 to the new number of bits to read        
    CASE R0 != 0
        INC SQX                          # look at the next memory bit in the row
        TDEC R0                          # reduce the distance we have left to go in the row
        bitval = READ (SQX, SQY)
        Jump to ADD_1

    bitval = READ (SQX, SQY)             # SQX and SQY registers are now pointing to the next memory bit
    Jump to ADD_1                        #   so we're ready to test it and continue the carry if necessary"""
   
# Osqrtlogt program
APGsembly = """INITIAL; Z; A1; READ SQ
INITIAL; NZ; A1; READ SQ
A1; Z; B1; SET SQ, NOP
A1; NZ; C1; NOP
B1; Z; B2; DEC SQX
B1; NZ; B2; DEC SQX
B2; Z; B3; DEC SQY
B2; NZ; B2; DEC SQX
B3; Z; B4; TDEC R0
B3; NZ; B3; DEC SQY
B4; Z; B5; TDEC R1
B4; NZ; B4; TDEC R0
B5; Z; B6; TDEC R2
B5; NZ; B5; TDEC R1
B6; Z; A1; READ SQ
B6; NZ; B6; TDEC R2
C1; Z; C2; TDEC R0
C1; NZ; C2; TDEC R0
C2; Z; C4; DEC SQX
C2; NZ; C3; INC SQX, NOP
C3; Z; A1; READ SQ
C3; NZ; A1; READ SQ
C4; Z; C5; INC SQY, INC R1, NOP
C4; NZ; C4; DEC SQX
C5; Z; C6; TDEC R1
C5; NZ; C6; TDEC R1
C6; Z; C7; TDEC R2
C6; NZ; C6; INC R2, TDEC R1
C7; Z; A1; READ SQ
C7; NZ; C7; INC R0, INC R1, TDEC R2"""
progname = "Osqrtlogt emulator"
registers = {"R0":0,"R1":0,"R2":0,"SQX":0,"SQY":0} # not really needed -- registers default to 0 when initialized

# ADD R0 R1 pseudocode
# DEC_R0:
#    TEST-DECREMENT R0
#    CASE r0_test_result == 0
#        Jump to DEC_R1
#    CASE r0_test_result != 0
#        INC OUT
#        Jump to DEC_R0
# DEC_R1:
#    TEST-DECREMENT R1
#    CASE r1_test_result == 0
#        HALT
#    CASE r1_test_result != 0
#        INC OUT
#        Jump to DEC_R1
   
# ADD R0 R1 program
APGsembly = """INITIAL; Z; A1; TDEC R0
A1; Z; A2; TDEC R1
A1; NZ; A1; TDEC R0, INC OUT
A2; Z; A3; NOP
A2; NZ; A2; TDEC R1, INC OUT
A3; Z; A3; HALT"""
progname = "ADD R0+R1"
registers = {"R0":13,"R1":21,"R2":0,"OUT":0}

# multiply pseudocode:
# DEC_R0:
#     TEST-DECREMENT R0
#     CASE R0-TEST-RESULT == 0
#         HALT
#     CASE R0-TEST-RESULT != 0
#         COPY R1 -> R2
#         TRANSFER R2 -> OUT
#     Jump to DEC_R0

# For multiplication we need an extra register for temporary storage.
# R0 will be decremented steadily till it's 0,
#   after which the program will halt.
# R1 will be copied to R2, decreasing temporarily to 0
# R2 will temporarily contain a copy of R1,
#   but then it will be decremented back to 0 while
#   simultaneously incrementing both R1 and OUT.

# MULT R1 R2
APGsembly = """INITIAL; Z; A1; TDEC R0
A1; Z; NOSTATE; HALT
A1; NZ; A2; TDEC R1
A2; Z; A3; TDEC R2
A2; NZ; A2; TDEC R1, INC R2
A3; Z; A1; TDEC R0
A3; NZ; A3; TDEC R2, INC R1, INC OUT"""
progname = "Multiply R0*R1"
registers = {"R0":13,"R1":21,"R2":0,"OUT":0}

# OUTPUT test program
APGsembly = """INITIAL; Z; P1; OUTPUT 0, NOP
INITIAL; NZ; P1; OUTPUT 0, NOP
P1; Z; P2; OUTPUT 1, NOP
P1; NZ; P2; OUTPUT 1, NOP
P2; Z; P3; OUTPUT 2, NOP
P2; NZ; P3; OUTPUT 2, NOP
P3; Z; P4; OUTPUT 3, NOP
P3; NZ; P4; OUTPUT 3, NOP
P4; Z; P5; OUTPUT 4, NOP
P4; NZ; P5; OUTPUT 4, NOP
P5; Z; P6; OUTPUT 5, NOP
P5; NZ; P6; OUTPUT 5, NOP
P6; Z; P7; OUTPUT 6, NOP
P6; NZ; P7; OUTPUT 6, NOP
P7; Z; P8; OUTPUT 7, NOP
P7; NZ; P8; OUTPUT 7, NOP
P8; Z; P9; OUTPUT 8, NOP
P8; NZ; P9; OUTPUT 8, NOP
P9; Z; P10; OUTPUT 9, NOP
P9; NZ; P10; OUTPUT 9, NOP
P10; Z; P11; OUTPUT ., NOP
P10; NZ; P11; OUTPUT ., NOP
P11; Z; P11; HALT
P11; NZ; P11; HALT"""
memory = {}
progname = "output-test"

# pi program
APGsembly = """INITIAL; Z; S1; READ T0
INITIAL; NZ; S1; READ T0
S1; Z; S2; SET T0, READ T2
S1; NZ; S2; SET T0, READ T2
S2; Z; S3; NOP, SET T2
S2; NZ; S3; NOP, SET T2
S3; Z; S4; NOP, INC R4
S3; NZ; S4; NOP, INC R4
S4; Z; S5; NOP, INC R0
S4; NZ; S5; NOP, INC R0
S5; Z; S6; NOP, INC R0
S5; NZ; S6; NOP, INC R0
S6; Z; S7; NOP, INC R0
S6; NZ; S7; NOP, INC R0
S7; Z; S8; NOP, INC R0
S7; NZ; S8; NOP, INC R0
S8; Z; S9; NOP, INC R0
S8; NZ; S9; NOP, INC R0
S9; Z; S10; NOP, INC R0
S9; NZ; S10; NOP, INC R0
S10; Z; S11; NOP, INC R0
S10; NZ; S11; NOP, INC R0
S11; Z; S12; NOP, INC R0
S11; NZ; S12; NOP, INC R0
S12; Z; S13; NOP, INC R9
S12; NZ; S13; NOP, INC R9
S13; Z; S14; NOP, INC R9
S13; NZ; S14; NOP, INC R9
S14; Z; S15; NOP, INC R9
S14; NZ; S15; NOP, INC R9
S15; Z; P1; NOP, INC R9
S15; NZ; P1; NOP, INC R9
P1; Z; P2; TDEC R9
P1; NZ; P2; TDEC R9
P2; Z; Q1; NOP
P2; NZ; P3; NOP
P3; Z; P4; NOP, INC R3
P3; NZ; P4; NOP, INC R3
P4; Z; P5; NOP, INC R4
P4; NZ; P5; NOP, INC R4
P5; Z; P6; TDEC R0, INC R4
P5; NZ; P6; TDEC R0, INC R4
P6; Z; P7; TDEC R1
P6; NZ; P6; TDEC R0, INC R1
P7; Z; P8; TDEC R2
P7; NZ; P7; INC R0, TDEC R1, INC R2
P8; Z; P13; DEC T3
P8; NZ; P9; READ T3
P9; Z; P10; READ T0
P9; NZ; P10; READ T0
P10; Z; P11; RESET T0, RESET T3, INC T3
P10; NZ; P11; SET T0, SET T3, INC T3
P11; Z; P12; INC T0
P11; NZ; P12; INC T0
P12; Z; P8; TDEC R2
P12; NZ; P8; TDEC R2
P13; Z; P14; DEC T0
P13; NZ; P13; DEC T3
P14; Z; P15; TDEC R0
P14; NZ; P14; DEC T0
P15; Z; P16; TDEC R1
P15; NZ; P15; TDEC R0, INC R1
P16; Z; P17; TDEC R2
P16; NZ; P16; INC R0, TDEC R1, INC R2
P17; Z; P23; DEC T0
P17; NZ; P18; READ T0
P18; Z; P19; RESET T0, READ T3
P18; NZ; P19; SET T0, READ T3, ADD A1
P19; Z; P20; ADD B0
P19; NZ; P20; ADD B1
P20; Z; P21; RESET T3, INC T3
P20; NZ; P21; SET T3, INC T3
P21; Z; P22; INC T0
P21; NZ; P22; INC T0
P22; Z; P17; TDEC R2
P22; NZ; P17; TDEC R2
P23; Z; P24; DEC T3
P23; NZ; P23; DEC T0
P24; Z; P25; TDEC R0
P24; NZ; P24; DEC T3
P25; Z; P26; TDEC R1
P25; NZ; P25; TDEC R0, INC R1
P26; Z; P27; TDEC R2
P26; NZ; P26; INC R0, TDEC R1, INC R2
P27; Z; P33; DEC T1
P27; NZ; P28; READ T1
P28; Z; P29; RESET T1, READ T3
P28; NZ; P29; RESET T1, READ T3, ADD A1
P29; Z; P30; ADD B0
P29; NZ; P30; ADD B1
P30; Z; P31; RESET T3, INC T3
P30; NZ; P31; SET T3, INC T3
P31; Z; P32; INC T1
P31; NZ; P32; INC T1
P32; Z; P27; TDEC R2
P32; NZ; P27; TDEC R2
P33; Z; P34; DEC T3
P33; NZ; P33; DEC T1
P34; Z; P35; NOP
P34; NZ; P34; DEC T3
P35; Z; P36; TDEC R4
P35; NZ; P36; TDEC R4
P36; Z; P37; TDEC R1
P36; NZ; P36; INC R1, TDEC R4
P37; Z; P38; TDEC R5
P37; NZ; P37; TDEC R1, INC R4, INC R5
P38; Z; P49; NOP
P38; NZ; P39; TDEC R0
P39; Z; P40; TDEC R1
P39; NZ; P39; TDEC R0, INC R1
P40; Z; P41; TDEC R2
P40; NZ; P40; INC R0, TDEC R1, INC R2
P41; Z; P47; DEC T3
P41; NZ; P42; READ T3
P42; Z; P43; READ T1, RESET T3
P42; NZ; P43; READ T1, SET T3, ADD A1
P43; Z; P44; ADD B0
P43; NZ; P44; ADD B1
P44; Z; P45; RESET T1, INC T1
P44; NZ; P45; SET T1, INC T1
P45; Z; P46; INC T3
P45; NZ; P46; INC T3
P46; Z; P41; TDEC R2
P46; NZ; P41; TDEC R2
P47; Z; P48; DEC T1
P47; NZ; P47; DEC T3
P48; Z; P38; TDEC R5
P48; NZ; P48; DEC T1
P49; Z; P50; TDEC R0
P49; NZ; P50; TDEC R0
P50; Z; P51; TDEC R1
P50; NZ; P50; TDEC R0, INC R1
P51; Z; P52; TDEC R2
P51; NZ; P51; INC R0, TDEC R1, INC R2
P52; Z; P57; DEC T3
P52; NZ; P53; READ T3
P53; Z; P54; READ T0
P53; NZ; P54; READ T0
P54; Z; P55; RESET T0, RESET T3, INC T3
P54; NZ; P55; RESET T0, SET T3, INC T3
P55; Z; P56; INC T0
P55; NZ; P56; INC T0
P56; Z; P52; TDEC R2
P56; NZ; P52; TDEC R2
P57; Z; P58; DEC T0
P57; NZ; P57; DEC T3
P58; Z; P59; NOP
P58; NZ; P58; DEC T0
P59; Z; P60; TDEC R3
P59; NZ; P60; TDEC R3
P60; Z; P61; TDEC R1
P60; NZ; P60; INC R1, TDEC R3
P61; Z; P62; TDEC R5
P61; NZ; P61; TDEC R1, INC R3, INC R5
P62; Z; P73; NOP
P62; NZ; P63; TDEC R0
P63; Z; P64; TDEC R1
P63; NZ; P63; TDEC R0, INC R1
P64; Z; P65; TDEC R2
P64; NZ; P64; INC R0, TDEC R1, INC R2
P65; Z; P71; DEC T3
P65; NZ; P66; READ T3
P66; Z; P67; READ T0, RESET T3
P66; NZ; P67; READ T0, SET T3, ADD A1
P67; Z; P68; ADD B0
P67; NZ; P68; ADD B1
P68; Z; P69; RESET T0, INC T0
P68; NZ; P69; SET T0, INC T0
P69; Z; P70; INC T3
P69; NZ; P70; INC T3
P70; Z; P65; TDEC R2
P70; NZ; P65; TDEC R2
P71; Z; P72; DEC T0
P71; NZ; P71; DEC T3
P72; Z; P62; TDEC R5
P72; NZ; P72; DEC T0
P73; Z; P74; TDEC R0
P73; NZ; P74; TDEC R0
P74; Z; P75; TDEC R1
P74; NZ; P74; TDEC R0, INC R1
P75; Z; P76; TDEC R2
P75; NZ; P75; INC R0, TDEC R1, INC R2
P76; Z; P81; DEC T3
P76; NZ; P77; READ T3
P77; Z; P78; READ T2
P77; NZ; P78; READ T2
P78; Z; P79; RESET T2, RESET T3, INC T3
P78; NZ; P79; RESET T2, SET T3, INC T3
P79; Z; P80; INC T2
P79; NZ; P80; INC T2
P80; Z; P76; TDEC R2
P80; NZ; P76; TDEC R2
P81; Z; P82; DEC T2
P81; NZ; P81; DEC T3
P82; Z; P83; NOP
P82; NZ; P82; DEC T2
P83; Z; P84; TDEC R4
P83; NZ; P84; TDEC R4
P84; Z; P85; TDEC R1
P84; NZ; P84; INC R1, TDEC R4
P85; Z; P86; TDEC R5
P85; NZ; P85; TDEC R1, INC R4, INC R5
P86; Z; P97; NOP
P86; NZ; P87; TDEC R0
P87; Z; P88; TDEC R1
P87; NZ; P87; TDEC R0, INC R1
P88; Z; P89; TDEC R2
P88; NZ; P88; INC R0, TDEC R1, INC R2
P89; Z; P95; DEC T3
P89; NZ; P90; READ T3
P90; Z; P91; READ T2, RESET T3
P90; NZ; P91; READ T2, SET T3, ADD A1
P91; Z; P92; ADD B0
P91; NZ; P92; ADD B1
P92; Z; P93; RESET T2, INC T2
P92; NZ; P93; SET T2, INC T2
P93; Z; P94; INC T3
P93; NZ; P94; INC T3
P94; Z; P89; TDEC R2
P94; NZ; P89; TDEC R2
P95; Z; P96; DEC T2
P95; NZ; P95; DEC T3
P96; Z; P86; TDEC R5
P96; NZ; P96; DEC T2
P97; Z; P98; TDEC R3
P97; NZ; P98; TDEC R3
P98; Z; P99; TDEC R1
P98; NZ; P98; INC R1, TDEC R3
P99; Z; P1; NOP
P99; NZ; P99; INC R0, TDEC R1, INC R3
Q1; Z; Q2; TDEC R7
Q1; NZ; Q2; TDEC R7
Q2; Z; Q3; TDEC R1
Q2; NZ; Q2; INC R1, TDEC R7
Q3; Z; Q4; NOP
Q3; NZ; Q3; TDEC R1, INC R7, INC R8
Q4; Z; Q5; TDEC R0
Q4; NZ; Q5; TDEC R0
Q5; Z; Q6; TDEC R1
Q5; NZ; Q5; TDEC R0, INC R1
Q6; Z; Q7; TDEC R2
Q6; NZ; Q6; INC R0, TDEC R1, INC R2
Q7; Z; Q12; DEC T3
Q7; NZ; Q8; READ T3
Q8; Z; Q9; READ T0
Q8; NZ; Q9; READ T0
Q9; Z; Q10; RESET T0, RESET T3, INC T3
Q9; NZ; Q10; SET T0, SET T3, INC T3
Q10; Z; Q11; INC T0
Q10; NZ; Q11; INC T0
Q11; Z; Q7; TDEC R2
Q11; NZ; Q7; TDEC R2
Q12; Z; Q13; DEC T0
Q12; NZ; Q12; DEC T3
Q13; Z; Q14; NOP
Q13; NZ; Q13; DEC T0
Q14; Z; Q15; TDEC R0
Q14; NZ; Q15; TDEC R0
Q15; Z; Q16; TDEC R1
Q15; NZ; Q15; TDEC R0, INC R1
Q16; Z; Q17; TDEC R2
Q16; NZ; Q16; INC R0, TDEC R1, INC R2
Q17; Z; Q23; DEC T1
Q17; NZ; Q18; READ T1
Q18; Z; Q19; RESET T1, READ T3
Q18; NZ; Q19; SET T1, READ T3, ADD A1
Q19; Z; Q20; ADD B0
Q19; NZ; Q20; ADD B1
Q20; Z; Q21; RESET T3, INC T3
Q20; NZ; Q21; SET T3, INC T3
Q21; Z; Q22; INC T1
Q21; NZ; Q22; INC T1
Q22; Z; Q17; TDEC R2
Q22; NZ; Q17; TDEC R2
Q23; Z; Q24; DEC T3
Q23; NZ; Q23; DEC T1
Q24; Z; Q25; TDEC R6
Q24; NZ; Q24; DEC T3
Q25; Z; Q26; NOP
Q25; NZ; Q25; TDEC R6
Q26; Z; Q27; TDEC R0
Q26; NZ; Q27; TDEC R0
Q27; Z; Q28; TDEC R1
Q27; NZ; Q27; TDEC R0, INC R1
Q28; Z; Q29; TDEC R2
Q28; NZ; Q28; INC R0, TDEC R1, INC R2
Q29; Z; Q32; READ T3
Q29; NZ; Q30; INC T3
Q30; Z; Q31; INC T2
Q30; NZ; Q31; INC T2
Q31; Z; Q29; TDEC R2
Q31; NZ; Q29; TDEC R2
Q32; Z; Q33; READ T2, RESET T3
Q32; NZ; Q36; READ T2, SET T3
Q33; Z; Q34; RESET T2, DEC T2
Q33; NZ; Q37; SET T2, DEC T3
Q34; Z; Q35; DEC T3
Q34; NZ; Q35; DEC T3
Q35; Z; Q40; DEC T2
Q35; NZ; Q32; READ T3
Q36; Z; Q39; RESET T2, DEC T3
Q36; NZ; Q34; SET T2, DEC T2
Q37; Z; Q38; DEC T2
Q37; NZ; Q37; DEC T3
Q38; Z; Q52; TDEC R8
Q38; NZ; Q38; DEC T2
Q39; Z; Q40; DEC T2
Q39; NZ; Q39; DEC T3
Q40; Z; Q41; NOP
Q40; NZ; Q40; DEC T2
Q41; Z; Q42; TDEC R0
Q41; NZ; Q42; TDEC R0
Q42; Z; Q43; TDEC R1
Q42; NZ; Q42; TDEC R0, INC R1
Q43; Z; Q44; TDEC R2
Q43; NZ; Q43; INC R0, TDEC R1, INC R2
Q44; Z; Q50; DEC T3
Q44; NZ; Q45; READ T3
Q45; Z; Q46; READ T2
Q45; NZ; Q46; READ T2, SUB A1
Q46; Z; Q47; RESET T2, SUB B0
Q46; NZ; Q47; SET T2, SUB B1
Q47; Z; Q48; RESET T3, INC T3
Q47; NZ; Q48; SET T3, INC T3
Q48; Z; Q49; INC T2
Q48; NZ; Q49; INC T2
Q49; Z; Q44; TDEC R2
Q49; NZ; Q44; TDEC R2
Q50; Z; Q51; DEC T2
Q50; NZ; Q50; DEC T3
Q51; Z; Q26; NOP, INC R6
Q51; NZ; Q51; DEC T2
Q52; Z; Q61; NOP
Q52; NZ; Q53; NOP
Q53; Z; Q54; TDEC R0
Q53; NZ; Q54; TDEC R0
Q54; Z; Q55; TDEC R1
Q54; NZ; Q54; TDEC R0, INC R1
Q55; Z; Q56; TDEC R2
Q55; NZ; Q55; INC R0, TDEC R1, INC R2
Q56; Z; Q60; DEC T3
Q56; NZ; Q57; READ T3
Q57; Z; Q58; MUL 0
Q57; NZ; Q58; MUL 1
Q58; Z; Q59; RESET T3, INC T3
Q58; NZ; Q59; SET T3, INC T3
Q59; Z; Q56; TDEC R2
Q59; NZ; Q56; TDEC R2
Q60; Z; Q25; TDEC R6
Q60; NZ; Q60; DEC T3
Q61; Z; Q62; TDEC R6
Q61; NZ; Q62; TDEC R6
Q62; Z; Q71; NOP, OUTPUT 0
Q62; NZ; Q63; TDEC R6
Q63; Z; Q71; NOP, OUTPUT 1
Q63; NZ; Q64; TDEC R6
Q64; Z; Q71; NOP, OUTPUT 2
Q64; NZ; Q65; TDEC R6
Q65; Z; Q71; NOP, OUTPUT 3
Q65; NZ; Q66; TDEC R6
Q66; Z; Q71; NOP, OUTPUT 4
Q66; NZ; Q67; TDEC R6
Q67; Z; Q71; NOP, OUTPUT 5
Q67; NZ; Q68; TDEC R6
Q68; Z; Q71; NOP, OUTPUT 6
Q68; NZ; Q69; TDEC R6
Q69; Z; Q71; NOP, OUTPUT 7
Q69; NZ; Q70; TDEC R6
Q70; Z; Q71; NOP, OUTPUT 8
Q70; NZ; Q71; NOP, OUTPUT 9
Q71; Z; Q72; TDEC R7
Q71; NZ; Q72; TDEC R7
Q72; Z; Q73; NOP, OUTPUT .
Q72; NZ; Q73; NOP, INC R7
Q73; Z; S12; NOP, INC R7
Q73; NZ; S12; NOP, INC R7"""
registers = {}
numtreg, numsimplereg = 4, 10
basetregx, basetregy = -1, -1 # fill these in
baserregx, baserregy = -1, -1 # fill these in
registers = {'T0': [0, '0'], 'T1': [0, '0'], 'T2': [0, '0'], 'T3': [0, '0'],
             'R0': 0, 'R1': 0, 'R2': 0, 'R3': 0, 'R4': 0, 'R5': 0, 'R6': 0, 'R7': 0, 'R8': 0, 'R9': 0}
progname = "pi-calc"

APGsembly = """INITIAL; Z; I1; INC R0, NOP
INITIAL; NZ; I1; INC R0, NOP
I1; Z; I2; INC R0, NOP
I1; NZ; I2; INC R0, NOP
I2; Z; I3; INC R0, NOP
I2; NZ; I3; INC R0, NOP
I3; Z; I4; INC R0, NOP
I3; NZ; I4; INC R0, NOP
I4; Z; I5; INC R0, NOP
I4; NZ; I5; INC R0, NOP
I5; Z; I6; INC R0, NOP
I5; NZ; I6; INC R0, NOP
I6; Z; I7; INC R0, NOP
I6; NZ; I7; INC R0, NOP
I7; Z; I8; INC R0, NOP
I7; NZ; I8; INC R0, NOP
I8; Z; I9; INC R0, NOP
I8; NZ; I9; INC R0, NOP
I9; Z; I10; INC R0, NOP
I9; NZ; I10; INC R0, NOP
I10; Z; I11; INC R0, NOP
I10; NZ; I11; INC R0, NOP
I11; Z; I12; INC R0, NOP
I11; NZ; I12; INC R0, NOP
I12; Z; I13; INC R0, NOP
I12; NZ; I13; INC R0, NOP
I13; Z; I14; INC R0, NOP
I13; NZ; I14; INC R0, NOP
I14; Z; I15; INC R0, NOP
I14; NZ; I15; INC R0, NOP
I15; Z; I16; INC R0, NOP
I15; NZ; I16; INC R0, NOP
I16; Z; I17; INC R0, NOP
I16; NZ; I17; INC R0, NOP
I17; Z; I18; INC R0, NOP
I17; NZ; I18; INC R0, NOP
I18; Z; I19; INC T0
I18; NZ; I19; INC T0
I19; Z; I20; READ T0
I19; NZ; I20; READ T0
I20; Z; I21; SET T0, INC T0
I20; NZ; I21; SET T0, INC T0
I21; Z; I22; READ T0
I21; NZ; I22; READ T0
I22; Z; I23; SET T0, INC T0
I22; NZ; I23; SET T0, INC T0
I23; Z; I24; INC T0
I23; NZ; I24; INC T0
I24; Z; I25; READ T0
I24; NZ; I25; READ T0
I25; Z; I26; SET T0, DEC T0
I25; NZ; I26; SET T0, DEC T0
I26; Z; I27; NOP
I26; NZ; I26; DEC T0
I27; Z; I28; INC T1
I27; NZ; I28; INC T1
I28; Z; I29; INC T1
I28; NZ; I29; INC T1
I29; Z; I30; INC T1
I29; NZ; I30; INC T1
I30; Z; I31; INC T1
I30; NZ; I31; INC T1
I31; Z; I32; READ T1
I31; NZ; I32; READ T1
I32; Z; I33; SET T1, INC T1
I32; NZ; I33; SET T1, INC T1
I33; Z; I34; INC T1
I33; NZ; I34; INC T1
I34; Z; I35; INC T1
I34; NZ; I35; INC T1
I35; Z; I36; READ T1
I35; NZ; I36; READ T1
I36; Z; I37; SET T1, INC T1
I36; NZ; I37; SET T1, INC T1
I37; Z; I38; READ T1
I37; NZ; I38; READ T1
I38; Z; I39; SET T1, DEC T1
I38; NZ; I39; SET T1, DEC T1
I39; Z; I40; NOP
I39; NZ; I39; DEC T1
I40; Z; I41; OUTPUT 1, NOP
I40; NZ; I41; OUTPUT 1, NOP
I41; Z; I42; OUTPUT ., NOP
I41; NZ; I42; OUTPUT ., NOP
I42; Z; NXD; OUTPUT 6, NOP
I42; NZ; NXD; OUTPUT 6, NOP
NXD; Z; A1; TDEC R0
NXD; NZ; A1; TDEC R0
A1; Z; A2; TDEC R1
A1; NZ; A1; INC R1, TDEC R0
A2; Z; A3; TDEC R2
A2; NZ; A2; INC R0, INC R2, TDEC R1
A3; Z; A9; DEC T0
A3; NZ; A4; READ T2
A4; Z; A5; READ T0
A4; NZ; A5; READ T0
A5; Z; A6; RESET T0, MUL 0
A5; NZ; A6; SET T0, MUL 1
A6; Z; A7; RESET T2, INC T0
A6; NZ; A7; SET T2, INC T0
A7; Z; A8; INC T2
A7; NZ; A8; INC T2
A8; Z; A3; TDEC R2
A8; NZ; A3; TDEC R2
A9; Z; A10; DEC T2
A9; NZ; A9; DEC T0
A10; Z; A11; INC R3, NOP
A10; NZ; A10; DEC T2
A11; Z; A12; INC R3, NOP
A11; NZ; A12; INC R3, NOP
A12; Z; A13; INC R3, NOP
A12; NZ; A13; INC R3, NOP
A13; Z; A14; INC R3, NOP
A13; NZ; A14; INC R3, NOP
A14; Z; A15; INC R3, NOP
A14; NZ; A15; INC R3, NOP
A15; Z; A16; INC R3, NOP
A15; NZ; A16; INC R3, NOP
A16; Z; A17; INC R3, NOP
A16; NZ; A17; INC R3, NOP
A17; Z; A18; INC R3, NOP
A17; NZ; A18; INC R3, NOP
A18; Z; EVL; INC R3, NOP
A18; NZ; EVL; INC R3, NOP
EVL; Z; B1; TDEC R0
EVL; NZ; B1; TDEC R0
B1; Z; B2; TDEC R1
B1; NZ; B1; INC R1, TDEC R0
B2; Z; B3; TDEC R2
B2; NZ; B2; INC R0, INC R2, TDEC R1
B3; Z; B4B; DEC T4
B3; NZ; B4; READ T4
B4; Z; B4A; RESET T4, INC T4
B4; NZ; B4A; RESET T4, INC T4
B4A; Z; B3; TDEC R2
B4A; NZ; B3; TDEC R2
B4B; Z; B5; NOP
B4B; NZ; B4B; DEC T4
B5; Z; B6; TDEC R3
B5; NZ; B6; TDEC R3
B6; Z; B7; TDEC R1
B6; NZ; B6; INC R1, TDEC R3
B7; Z; B8; NOP
B7; NZ; B7; INC R3, INC R4, TDEC R1
B8; Z; B9; TDEC R0
B8; NZ; B9; TDEC R0
B9; Z; B10; TDEC R1
B9; NZ; B9; INC R1, TDEC R0
B10; Z; B11; TDEC R2
B10; NZ; B10; INC R0, INC R2, TDEC R1
B11; Z; B16; DEC T2
B11; NZ; B12; READ T3
B12; Z; B13; READ T2
B12; NZ; B13; READ T2
B13; Z; B14; RESET T2, RESET T3, INC T2
B13; NZ; B14; SET T2, SET T3, INC T2
B14; Z; B15; INC T3
B14; NZ; B15; INC T3
B15; Z; B11; TDEC R2
B15; NZ; B11; TDEC R2
B16; Z; B17; DEC T3
B16; NZ; B16; DEC T2
B17; Z; ADD; NOP
B17; NZ; B17; DEC T3
ADD; Z; C1; TDEC R4
ADD; NZ; C1; TDEC R4
C1; Z; C5; NOP
C1; NZ; C2; READ T3
C2; Z; C4; SET T3, DEC T3
C2; NZ; C3; RESET T3, INC T3
C3; Z; C2; READ T3
C3; NZ; C2; READ T3
C4; Z; C1; TDEC R4
C4; NZ; C4; DEC T3
C5; Z; C6; TDEC R3
C5; NZ; C6; TDEC R3
C6; Z; C7; TDEC R1
C6; NZ; C6; INC R1, TDEC R3
C7; Z; MUL; NOP
C7; NZ; C7; INC R3, INC R4, TDEC R1
MUL; Z; D1; TDEC R4
MUL; NZ; D1; TDEC R4
D1; Z; D11; TDEC R0
D1; NZ; D2; TDEC R0
D2; Z; D3; TDEC R1
D2; NZ; D2; INC R1, TDEC R0
D3; Z; D4; TDEC R2
D3; NZ; D3; INC R0, INC R2, TDEC R1
D4; Z; D9; DEC T3
D4; NZ; D5; READ T3
D5; Z; D6; RESET T3, READ T4
D5; NZ; D6; SET T3, ADD A1, READ T4
D6; Z; D7; ADD B0
D6; NZ; D7; ADD B1
D7; Z; D8; RESET T4, INC T4
D7; NZ; D8; SET T4, INC T4
D8; Z; D8A; INC T3
D8; NZ; D8A; INC T3
D8A; Z; D4; TDEC R2
D8A; NZ; D4; TDEC R2
D9; Z; D10; DEC T4
D9; NZ; D9; DEC T3
D10; Z; D1; TDEC R4
D10; NZ; D10; DEC T4
D11; Z; D12; TDEC R1
D11; NZ; D11; INC R1, TDEC R0
D12; Z; COMP; NOP
D12; NZ; D12; INC R0, INC R2, TDEC R1
COMP; Z; E1; TDEC R2
COMP; NZ; E1; TDEC R2
E1; Z; E4; READ T1
E1; NZ; E2; INC T1
E2; Z; E3; INC T4
E2; NZ; E3; INC T4
E3; Z; E1; TDEC R2
E3; NZ; E1; TDEC R2
E4; Z; E5; RESET T1, READ T4
E4; NZ; E8; SET T1, READ T4
E5; Z; E6; RESET T4, DEC T4
E5; NZ; E9; SET T4, DEC T1
E6; Z; E7; DEC T1
E6; NZ; E7; DEC T1
E7; Z; E13; DEC T4
E7; NZ; E4; READ T1
E8; Z; E12; RESET T4, DEC T1
E8; NZ; E6; SET T4, DEC T4
E9; Z; E10; DEC T4
E9; NZ; E9; DEC T1
E10; Z; E11; TDEC R3
E10; NZ; E10; DEC T4
E11; Z; EVL; NOP
E11; NZ; EVL; NOP
E12; Z; E13; DEC T4
E12; NZ; E12; DEC T1
E13; Z; SUB; NOP
E13; NZ; E13; DEC T4
SUB; Z; F1; TDEC R0
SUB; NZ; F1; TDEC R0
F1; Z; F2; TDEC R1
F1; NZ; F1; INC R1, TDEC R0
F2; Z; F3; TDEC R2
F2; NZ; F2; INC R0, INC R2, TDEC R1
F3; Z; F9; DEC T1
F3; NZ; F4; READ T1
F4; Z; F5; READ T4
F4; NZ; F5; SUB A1, READ T4
F5; Z; F6; RESET T4, SUB B0
F5; NZ; F6; SET T4, SUB B1
F6; Z; F7; RESET T1, INC T1
F6; NZ; F7; SET T1, INC T1
F7; Z; F8; INC T4
F7; NZ; F8; INC T4
F8; Z; F3; TDEC R2
F8; NZ; F3; TDEC R2
F9; Z; F10; DEC T4
F9; NZ; F9; DEC T1
F10; Z; CENT; NOP
F10; NZ; F10; DEC T4
CENT; Z; G1; TDEC R0
CENT; NZ; G1; TDEC R0
G1; Z; G2; TDEC R1
G1; NZ; G1; INC R1, TDEC R0
G2; Z; G3; TDEC R2
G2; NZ; G2; INC R0, INC R2, TDEC R1
G3; Z; G6; DEC T1
G3; NZ; G3A; READ T1
G3A; Z; G4; MUL 0
G3A; NZ; G4; MUL 1
G4; Z; G5; RESET T1, INC T1
G4; NZ; G5; SET T1, INC T1
G5; Z; G3; TDEC R2
G5; NZ; G3; TDEC R2
G6; Z; G7; TDEC R0
G6; NZ; G6; DEC T1
G7; Z; G8; TDEC R1
G7; NZ; G7; INC R1, TDEC R0
G8; Z; G9; TDEC R2
G8; NZ; G8; INC R0, INC R2, TDEC R1
G9; Z; G12; DEC T1
G9; NZ; G9A; READ T1
G9A; Z; G10; MUL 0
G9A; NZ; G10; MUL 1
G10; Z; G11; RESET T1, INC T1
G10; NZ; G11; SET T1, INC T1
G11; Z; G9; TDEC R2
G11; NZ; G9; TDEC R2
G12; Z; DEC; NOP
G12; NZ; G12; DEC T1
DEC; Z; H1; TDEC R0
DEC; NZ; H1; TDEC R0
H1; Z; H2; TDEC R1
H1; NZ; H1; INC R1, TDEC R0
H2; Z; H3; TDEC R2
H2; NZ; H2; INC R0, INC R2, TDEC R1
H3; Z; H6; DEC T0
H3; NZ; H3A; READ T0
H3A; Z; H4; MUL 0
H3A; NZ; H4; MUL 1
H4; Z; H5; RESET T0, INC T0
H4; NZ; H5; SET T0, INC T0
H5; Z; H3; TDEC R2
H5; NZ; H3; TDEC R2
H6; Z; H7; TDEC R3
H6; NZ; H6; DEC T0
H7; Z; H8; TDEC R1
H7; NZ; H7; INC R1, TDEC R3
H8; Z; H9; TDEC R4
H8; NZ; H8; INC R3, INC R4, TDEC R1
H9; Z; H13; TDEC R3
H9; NZ; H10; READ T0
H10; Z; H12; SET T0, DEC T0
H10; NZ; H9; RESET T0, INC T0
H11; Z; H10; READ T0
H11; NZ; H10; READ T0
H12; Z; H9; TDEC R4
H12; NZ; H12; DEC T0
H13; Z; H14; TDEC R1
H13; NZ; H13; INC R1, TDEC R3
H14; Z; H15; TDEC R4
H14; NZ; H14; INC R3, INC R4, TDEC R1
H15; Z; H19; TDEC R3
H15; NZ; H16; READ T0
H16; Z; H18; SET T0, DEC T0
H16; NZ; H15; RESET T0, INC T0
H17; Z; H16; READ T0
H17; NZ; H16; READ T0
H18; Z; H15; TDEC R4
H18; NZ; H18; DEC T0
H19; Z; H28; OUTPUT 0, NOP
H19; NZ; H20; TDEC R3
H20; Z; H28; OUTPUT 1, NOP
H20; NZ; H21; TDEC R3
H21; Z; H28; OUTPUT 2, NOP
H21; NZ; H22; TDEC R3
H22; Z; H28; OUTPUT 3, NOP
H22; NZ; H23; TDEC R3
H23; Z; H28; OUTPUT 4, NOP
H23; NZ; H24; TDEC R3
H24; Z; H28; OUTPUT 5, NOP
H24; NZ; H25; TDEC R3
H25; Z; H28; OUTPUT 6, NOP
H25; NZ; H26; TDEC R3
H26; Z; H28; OUTPUT 7, NOP
H26; NZ; H27; TDEC R3
H27; Z; H28; OUTPUT 8, NOP
H27; NZ; H28; OUTPUT 9, NOP
H28; Z; H29; INC R0, NOP
H28; NZ; H29; INC R0, NOP
H29; Z; H30; INC R0, NOP
H29; NZ; H30; INC R0, NOP
H30; Z; H31; INC R0, NOP
H30; NZ; H31; INC R0, NOP
H31; Z; NXD; INC R0, NOP
H31; NZ; NXD; INC R0, NOP"""
progname = "phi-calc"
registers = {'T0': [0, '0'], 'T1': [0, '0'], 'T2': [0, '0'], 'T3': [0, '0'], 'T4': [0, '0'],
             'R0': 0, 'R1': 0, 'R2': 0, 'R3': 0, 'R4': 0}
numtreg, numsimplereg = 5, 5
basetregx, basetregy = -33508, 55803
baserregx, baserregy = -43923, 70925
proglines = APGsembly.split("\n")
program = {}

s=""
g.new(progname)
g.setcell(0,0,1)
g.fit()
g.setcell(0,0,0)
g.update()
runflag = 0

def check_keyboard():
  global runflag
  while 1:
    evt = g.getevent()
    if evt == "key q none":
      g.setclipstr(s)
      g.exit()
    if evt == "key r none":
      runflag = 1-runflag
    elif evt=="key g none":
      break
    else:
      g.doevent(evt)
    if runflag == 1:
      break

# every state has a Z and NZ jump instruction to following states,
#   so the order of the program lines doesn't really matter.
#   Turn the program into a dictionary.
for item in proglines:
   label, bitval, nextstate, instr = item.replace(", ",",").split("; ")
   program[label+";"+bitval]=[nextstate,instr]

state, nextstate, nextoutput, outputtext = "START","INITIAL","Z",""

g.show(state + " -- " + nextstate + " :: " + instr + "; regs=" + str(registers)  + "; mem=" + str(memory) + " -- 'r' to toggle run mode, any key to step")
# s+="\nregs=" + str(registers)  + "; mem=" + str(memory)

check_keyboard()

instrcount = -1

while 1:

   if nextoutput == "":
      g.show(state + " -- " + nextstate + " :: " + instr + "; regs=" + str(registers)  + "; mem=" + str(memory))
      g.note("Program reached halt state (because no bit value was returned by any instruction).")
      g.setclipstr(s)
      g.exit()
   
   # s+="\n" + str(instrcount+100000)[1:] + ": Output = " + nextoutput ########################
   # instrcount+=1
   # if instrcount>=32768:
   #   g.setclipstr(s)
   #   g.exit() #####################################################################
   state = nextstate + ";" + nextoutput
   # get info from program dictionary, move to next state
   nextstate, instr = program[state]

   # process instructions for current state
   # -- there may be just one instruction,
   #    or several comma-separated instructions
   nextoutput = ""  # if some instruction doesn't set this variable, the program will halt
   for i in instr.split(","):
     # allow stepping or full-speed run from keyboard (toggle "r")
     g.show(str(instrcount) + ": " + state + " -- " + nextstate + " :: " + instr + "; regs=" + str(registers)  + "; mem=" + str(memory) + " -- 'r' to toggle run mode, any key to step")
     # s+="  Instr=" + nextstate + " " + i + "; regs=" + str(registers)  + "; mem=" + str(memory)
     check_keyboard()

     if i == "NOP":
       nextoutput = "Z"

     elif i == "READ SQ":
       if "SQX" not in registers: registers["SQX"], registers["SQY"]=0,0  # initialize if necessary
       coord = str(registers["SQX"]) +","+str(registers["SQY"])
       if coord not in memory:
         memory[coord]=0
       if memory[coord]==0:
         nextoutput = "Z"
       else:
         nextoutput = "NZ"
         memory[coord] = 0  # this is a destructive read operation
#         g.setcell(registers["SQX"]-registers["SQY"],-registers["SQX"]-registers["SQY"],memory[coord])
#         g.update()

     elif i == "SET SQ":
       if coord not in memory:
         memory[coord]=0
       if memory[coord]==0:
         memory[coord] = 1
#         g.setcell(registers["SQX"]-registers["SQY"],-registers["SQX"]-registers["SQY"],memory[coord])
#         g.update()
       else:
         g.note("PROGRAM ERROR:\nTried to set memory coordinate " + coord + "to 1,\nwhen it was already 1.")
         g.exit()

     elif i[:4]=="INC ":
       reg = i.split(" ")[1]
       if reg not in registers:
         if reg[:1]=="T": # binary register
           registers[reg]=[0,"0"]
         else:
           registers[reg]=0 # simple register
       if isinstance(registers[reg], types.ListType): # binary register
         ptr,bits = registers[reg]
         if ptr == len(bits)-1:
           bits+="0"         # the mechanism automatically adds a zero when INCing past current end of tape
           nextoutput = "Z"  # ... and it returns a zero output in that case
         else:
           nextoutput = "NZ" # if it's not creating a new bit, it returns an NZ output.  TODO: what does the program use this for?
         registers[reg] = [ptr+1,bits]
       else:
         registers[reg] += 1  # simple register

     elif i[:5]=="TDEC ": # simple register
       reg = i.split(" ")[1]
       if reg not in registers:
         registers[reg]=0
       if registers[reg] == 0:
         nextoutput = "Z" # don't update register, it's already zero
       else:
         registers[reg] -= 1
         nextoutput = "NZ"

     elif i[:4]=="DEC ": # binary register
       reg = i.split(" ")[1]
       ptr,bits = registers[reg]
       if ptr == 0:
         nextoutput = "Z" # don't update register, it's already zero
       else:
         registers[reg] = [ptr-1,bits]
         nextoutput = "NZ"    

     elif i=="HALT":
       g.note("Program reached halt state.")
       g.setclipstr(s)
       g.exit()

     elif i[:4]=="MUL ":
       bit = str(i[4:])
       if "MUL" not in registers:
         registers["MUL"]="00000"
       nextoutput, registers["MUL"] = mullookup["MUL" + bit + " " + registers["MUL"]]

     elif i[:7] == "OUTPUT ":
       outputtext += i[7:]
       outpat = make_text(outputtext)
       g.putcells(outpat, 0, 10)
       g.update()

     elif i[:4]=="SUB ":
       if "SUB" not in registers:
         registers["SUB"]="000 stopper0 bit0"
       whichinput = i[4:]
       out, registers["SUB"] = sublookup[registers["SUB"] + " " + whichinput]
       if registers["SUB"] == "FAILURE":
         g.note("Program crashed at line '" + i + "'.  SUB A1 must have been run twice (?).")
         g.exit()
       if out != "NONE":
         nextoutput = out

     elif i[:4]=="ADD ":
       if "ADD" not in registers:
         registers["ADD"]="000 bit0"
       whichinput = i[4:]
       temp = registers["ADD"] + " " + whichinput
       out, registers["ADD"] = addlookup[temp]
       # g.note("ADD called with " + temp + " -- result: " + out + ", " + registers["ADD"]) #######################3
       if out != "NONE":
         nextoutput = out

     elif i[:5]=="READ ":
       binregname = i[5:] # TODO: maybe be consistent and use .split()?
       if binregname not in registers:
         registers[binregname]=[0,"0"]
       ptr, bits = registers[binregname]
       if bits[ptr]=="x":
         g.note("Program crashed on instruction '" + i + "':\n attempt to read an empty position in a binary register.")
         g.exit()
       elif bits[ptr]=="0":
         nextoutput = "Z"
       elif bits[ptr]=="1":
         nextoutput = "NZ"
       else:
         g.note("Emulator error. Found value '" + bits[ptr] + "' on READ, in " + binregname + " bitstring -- " + str(registers[binregname]) + ".")
         g.exit()
       registers[binregname] = [ptr, bits[:ptr]+"x"+bits[ptr+1:]]

     elif i[:4]=="SET ":
       binregname = i[4:]
       if binregname not in registers:
         registers[binregname]=[0,"0"]
       ptr, bits = registers[binregname]
       if bits[ptr]!="x":
         g.note("Crash. Found value '" + bits[ptr] + "' on SET, in " + binregname + " bitstring -- " + str(registers[binregname]) + ".")
         g.exit()
       registers[binregname] = [ptr, bits[:ptr]+"1"+bits[ptr+1:]]

     elif i[:6]=="RESET ":
       binregname = i[6:]
       if binregname not in registers:
         registers[binregname]=[0,"0"]
       else:
         ptr, bits = registers[binregname]
       if bits[ptr]!="x":
         g.note("Crash. Found value '" + bits[ptr] + "' on READ, in " + binregname + " bitstring -- " + str(registers[binregname]) + ".")
         g.exit()
       registers[binregname] = [ptr, bits[:ptr]+"0"+bits[ptr+1:]]

     else:
       g.note("Unknown instruction: " + instr + " -- ~" + i + "~")
       g.exit()

"""
   if instrcount>=1:  # the phi pattern is already advanced one cycle
     g.run(2**20)


   # compare current contents of register to actual boats in the Life universe ##############
   for ireg in range(5): # this is for the phi pattern -- for pi it's just range(4)
     sdat = registers["T"+str(ireg)][1]
     pos = registers["T"+str(ireg)][0]
     if g.getcell(-34763-2560*ireg-pos,57046+2560*ireg-pos)==0:
       errmsg = "T" + sreg + " register pointer not found at the correct place in cycle #" + str(instrcount)
       g.note(errmsg)
       s += "\n" + errmsg
     count = 0
     ptrx, ptry = basetregx-2560*ireg, basetregy+2560*ireg
     for char in sdat:
       read0 = g.getcell(ptrx,ptry) % 2
       read1 = g.getcell(ptrx-3, ptry-3) % 2
       if char=="0":
         if read0 == 0 or read1 == 1:
           errmsg = "Discrepancy found in T" + str(ireg) + " bit #" + str(count) + " at (" + str(ptrx) + ", " + str(ptry) + ") at instruction " +str(instrcount) + ": emulator says it's a 0."
           g.note(errmsg)
           s += "\n" + errmsg
       if char=="1":
         if read0 == 1 or read1 == 0:
           errmsg = "Discrepancy found in T" + str(ireg) + " bit #" + str(count) + " at (" + str(ptrx) + ", " + str(ptry) + ") at instruction " +str(instrcount) + ": emulator says it's a 1."
           g.note(errmsg)
           s += "\n" + errmsg
       if char=="x":
         if read0 == 1 or read1 == 1:
           errmsg = "Discrepancy found in T" + str(ireg) + " bit #" + str(count) + " at (" + str(ptrx) + ", " + str(ptry) + ") at instruction " +str(instrcount) + ": emulator says it's an x."
           g.note(errmsg)
           s += "\n" + errmsg
       ptrx-=16
       ptry-=16
       count+=1
     # check beyond the end of the binary tape, see if anything other than 'x' (vacuum) is present
     read0 = g.getcell(ptrx,ptry) % 2
     read1 = g.getcell(ptrx-3, ptry-3) % 2
     if read0 == 1 or read1 == 1:
       errmsg = "Discrepancy found in T" + str(ireg) + " bit #" + str(count) + " at (" + str(ptrx) + ", " + str(ptry) + ") at instruction " +str(instrcount) + ": emulator says it's an x."
       g.note(errmsg)
       s += "\n" + errmsg
   # check the positions of all the simple registers also
   for ireg in range(numsimplereg):
     rval = registers["R" + str(ireg)]
     ptrx, ptry = baserregx-ireg*1024, baserregy+ireg*1024
     if g.getcell(ptrx-rval, ptry-rval)%2 != 1:
       errmsg="Discrepancy found in register R" + str(ireg) + " at (" + str(ptrx) + ", " + str(ptry) + ") at instruction " +str(instrcount) + ": emulator says it should be at " + str(rval) + ".\n" 
       g.note(errmsg)
       s += "\n" + errmsg
   
   # check nextoutput against the Z / NZ output in the pattern
   if nextoutput == "Z":
     if g.getcell(-23315,51768)!=1:
       errmsg = "Discrepancy found at instruction " + str(instrcount) + ": output is NZ in the real pattern."
       g.note(errmsg)
       s += "\n" + errmsg
   elif nextoutput == "NZ":
     if g.getcell(-23545,51654)!=1:
       errmsg = "Discrepancy found at instruction " + str(instrcount) + ": output is Z in the real pattern."
       g.note(errmsg)
       s += "\n" + errmsg   
   # g.note("No discrepancy found for cycle " + str(instrcount))
   # end of added register-checking session ######################
"""
I'm taking a break now. Will try the same emulator on the pi-calculator code later this evening. Fingers crossed!

EDIT: The pi-calculator assembly code works, too. I think the emulator is officially in business.

Code: Select all

x = 157, y = 14, rule = LifeHistory
2A.A11.2A3.2A3.2A3.2A5.2A.A6.2A.A6.2A.A6.2A.A6.2A.A4.2A.A6.2A.A6.2A.A
6.2A.A4.A.2A6.2A.A4.2A.A6.2A.A$A.2A12.A3.2A3.2A4.A5.A.2A6.A.2A6.A.2A
6.A.2A6.A.2A4.A.2A6.A.2A6.A.2A6.A.2A4.2A.A6.A.2A4.A.2A6.A.2A$4.2A9.A
14.A4.2A8.2A4.2A8.2A2.2A8.2A12.2A2.2A8.2A4.2A2.2A4.2A6.2A2.2A4.2A6.2A
8.2A$4.A10.2A3.2A3.2A3.2A3.A9.A5.A9.A3.A9.A13.A3.A9.A5.A3.A5.A8.A2.A
5.A7.A9.A$5.A14.A.A.A.A9.A9.A5.A9.A3.A9.A13.A3.A9.A5.A3.A5.A6.A4.A5.A
7.A9.A$4.2A9.2A5.A.A5.2A3.2A8.2A4.2A8.2A2.2A8.2A12.2A2.2A8.2A4.2A2.2A
4.2A6.2A2.2A4.2A6.2A8.2A$2A.A4.2A.A4.A4.2A.A6.A5.2A.A6.2A.A6.2A.A6.2A
.A6.2A.A4.2A.A6.2A.A6.2A.A6.2A.A6.2A6.2A.A4.2A.A6.2A.A$A.2A4.A.2A3.A
9.2A3.A6.A.2A6.A.2A6.A.2A6.A.2A6.A.2A4.A.2A6.A.2A6.A.2A6.A.2A7.A6.A.
2A4.A.2A6.A.2A$4.2A9.2A9.A3.2A9.2A8.2A2.2A8.2A4.2A8.2A6.2A8.2A2.2A4.
2A8.2A4.A11.2A6.2A2.2A$4.A20.A15.A9.A3.A9.A5.A9.A7.A9.A3.A5.A9.A5.2A
10.A7.A3.A$5.A9.2A8.2A3.2A10.A9.A3.A9.A5.A9.A7.A9.A3.A5.A9.A2.2A13.A
7.A3.A$4.2A10.A9.A4.A9.2A8.2A2.2A8.2A4.2A8.2A6.2A8.2A2.2A4.2A8.2A3.A
12.2A6.2A2.2A$2A.A11.A9.A4.A6.2A.A6.2A.A6.2A.A6.2A.A6.2A.A4.2A.A6.2A.
A6.2A.A6.2A.A4.A9.2A.A4.2A.A6.2A.A$A.2A11.2A8.2A3.2A5.A.2A6.A.2A6.A.
2A6.A.2A6.A.2A4.A.2A6.A.2A6.A.2A6.A.2A4.2A8.A.2A4.A.2A6.A.2A!
#C [[ WIDTH 800 HEIGHT 240 ZOOM 5 ]]
Here's the code cut down a bit, leaving just what's needed to calculate pi:

Code: Select all

# APGsembly code emulator, version 0.314159+ (beta)
# remove phi calculator and other test programs, activate pi calculator

import golly as g
from glife.text import make_text
import types

mullookup = {"MUL0 00000":["Z", "00000"],"MUL1 00000":["Z", "00101"],"MUL0 00001":["NZ", "00000"],"MUL1 00001":["NZ", "00101"],
	     "MUL0 00010":["Z", "00001"],"MUL1 00010":["Z", "00110"],"MUL0 00011":["NZ", "00001"],"MUL1 00011":["NZ", "00110"],
	     "MUL0 00100":["Z", "00010"],"MUL1 00100":["Z", "00111"],"MUL0 00101":["NZ", "00010"],"MUL1 00101":["NZ", "00111"],
	     "MUL0 00110":["Z", "00011"],"MUL1 00110":["Z", "01000"],"MUL0 00111":["NZ", "00011"],"MUL1 00111":["NZ", "01000"],
	     "MUL0 01000":["Z", "00100"],"MUL1 01000":["Z", "01001"],"MUL0 01001":["NZ", "00100"],"MUL1 01001":["NZ", "01001"],
	     "MUL0 01010":["Z", "00101"],"MUL1 01010":["Z", "01010"],"MUL0 01011":["NZ", "00101"],"MUL1 01011":["NZ", "01010"],
	     "MUL0 01100":["Z", "00110"],"MUL1 01100":["Z", "01011"],"MUL0 01101":["NZ", "00110"],"MUL1 01101":["NZ", "01011"],
	     "MUL0 01110":["Z", "00111"],"MUL1 01110":["Z", "01100"],"MUL0 01111":["NZ", "00111"],"MUL1 01111":["NZ", "01100"],
	     "MUL0 10000":["Z", "01000"],"MUL1 10000":["Z", "01101"],"MUL0 10001":["NZ", "01000"],"MUL1 10001":["NZ", "01101"],
	     "MUL0 10010":["Z", "01001"],"MUL1 10010":["Z", "01110"],"MUL0 10011":["NZ", "01001"],"MUL1 10011":["NZ", "01110"],
	     "MUL0 10100":["Z", "01010"],"MUL1 10100":["Z", "01111"],"MUL0 10101":["NZ", "01010"],"MUL1 10101":["NZ", "01111"],
	     "MUL0 10110":["Z", "01011"],"MUL1 10110":["Z", "00000"],"MUL0 10111":["NZ", "01011"],"MUL1 10111":["NZ", "00000"],
	     "MUL0 11000":["Z", "01100"],"MUL1 11000":["Z", "00001"],"MUL0 11001":["NZ", "01100"],"MUL1 11001":["NZ", "00001"],
	     "MUL0 11010":["Z", "01101"],"MUL1 11010":["Z", "00010"],"MUL0 11011":["NZ", "01101"],"MUL1 11011":["NZ", "00010"],
	     "MUL0 11100":["Z", "01110"],"MUL1 11100":["Z", "00011"],"MUL0 11101":["NZ", "01110"],"MUL1 11101":["NZ", "00011"],
	     "MUL0 11110":["Z", "01111"],"MUL1 11110":["Z", "00100"],"MUL0 11111":["NZ", "01111"],"MUL1 11111":["NZ", "00100"]}

addlookup = {"000 bit0 A1":["NONE","010 bit1"],"000 bit0 B1":["NZ","000 bit0"],"000 bit0 B0":["Z","000 bit0"],
	     "000 bit1 A1":["NONE","010 bit0"],"000 bit1 B1":["Z","000 bit0"],"000 bit1 B0":["NZ","000 bit0"],
	     "001 bit0 A1":["NONE","011 bit1"],"001 bit0 B1":["NZ","000 bit0"],"001 bit0 B0":["Z","000 bit0"],
	     "001 bit1 A1":["NONE","011 bit0"],"001 bit1 B1":["Z","000 bit0"],"001 bit1 B0":["NZ","000 bit0"],
	     "010 bit0 A1":["NONE","000 bit1"],"010 bit0 B1":["NZ","100 bit1"],"010 bit0 B0":["Z","000 bit0"],
	     "010 bit1 A1":["NONE","000 bit0"],"010 bit1 B1":["Z","100 bit1"],"010 bit1 B0":["NZ","000 bit0"],
	     "011 bit0 A1":["NONE","001 bit1"],"011 bit0 B1":["NZ","000 bit0"],"011 bit0 B0":["Z","100 bit1"],
	     "011 bit1 A1":["NONE","001 bit0"],"011 bit1 B1":["Z","000 bit0"],"011 bit1 B0":["NZ","100 bit1"],
	     "100 bit0 A1":["NONE","110 bit1"],"100 bit0 B1":["NZ","100 bit1"],"100 bit0 B0":["Z","000 bit0"],
	     "100 bit1 A1":["NONE","110 bit0"],"100 bit1 B1":["Z","100 bit1"],"100 bit1 B0":["NZ","000 bit0"],
	     "101 bit0 A1":["NONE","111 bit1"],"101 bit0 B1":["NZ","000 bit0"],"101 bit0 B0":["Z","100 bit1"],
	     "101 bit1 A1":["NONE","111 bit0"],"101 bit1 B1":["Z","000 bit0"],"101 bit1 B0":["NZ","100 bit1"],
	     "110 bit0 A1":["NONE","100 bit1"],"110 bit0 B1":["NZ","100 bit1"],"110 bit0 B0":["Z","100 bit1"],
	     "110 bit1 A1":["NONE","100 bit0"],"110 bit1 B1":["Z","100 bit1"],"110 bit1 B0":["NZ","100 bit1"],
	     "111 bit0 A1":["NONE","101 bit1"],"111 bit0 B1":["NZ","100 bit1"],"111 bit0 B0":["Z","100 bit1"],
	     "111 bit1 A1":["NONE","101 bit0"],"111 bit1 B1":["Z","100 bit1"],"111 bit1 B0":["NZ","100 bit1"]}

sublookup = {"000 stopper0 bit0 A1":["NONE","000 stopper1 bit1"],"000 stopper0 bit0 B0":["Z","000 stopper0 bit0"],
	     "000 stopper0 bit0 B1":["NZ","100 stopper0 bit1"],"000 stopper0 bit1 A1":["NONE","000 stopper1 bit0"],
	     "000 stopper0 bit1 B0":["NZ","000 stopper0 bit0"],"000 stopper0 bit1 B1":["Z","100 stopper0 bit1"],
	     "000 stopper1 bit0 A1":["NONE","FAILURE"],"000 stopper1 bit0 B0":["Z","000 stopper0 bit0"],
	     "000 stopper1 bit0 B1":["NZ","000 stopper0 bit0"],"000 stopper1 bit1 A1":["NONE","FAILURE"],
	     "000 stopper1 bit1 B0":["NZ","000 stopper0 bit0"],"000 stopper1 bit1 B1":["Z","000 stopper0 bit0"],
	     "001 stopper0 bit0 A1":["NONE","001 stopper1 bit1"],"001 stopper0 bit0 B0":["Z","100 stopper0 bit1"],
	     "001 stopper0 bit0 B1":["NZ","000 stopper0 bit0"],"001 stopper0 bit1 A1":["NONE","001 stopper1 bit0"],
	     "001 stopper0 bit1 B0":["NZ","100 stopper0 bit1"],"001 stopper0 bit1 B1":["Z","000 stopper0 bit0"],
	     "001 stopper1 bit0 A1":["NONE","FAILURE"],"001 stopper1 bit0 B0":["Z","000 stopper0 bit0"],
	     "001 stopper1 bit0 B1":["NZ","000 stopper0 bit0"],"001 stopper1 bit1 A1":["NONE","FAILURE"],
	     "001 stopper1 bit1 B0":["NZ","000 stopper0 bit0"],"001 stopper1 bit1 B1":["Z","000 stopper0 bit0"],
	     "010 stopper0 bit0 A1":["NONE","010 stopper1 bit1"],"010 stopper0 bit0 B0":["Z","000 stopper0 bit0"],
	     "010 stopper0 bit0 B1":["NZ","000 stopper0 bit0"],"010 stopper0 bit1 A1":["NONE","010 stopper1 bit0"],
	     "010 stopper0 bit1 B0":["NZ","000 stopper0 bit0"],"010 stopper0 bit1 B1":["Z","000 stopper0 bit0"],
	     "010 stopper1 bit0 A1":["NONE","FAILURE"],"010 stopper1 bit0 B0":["Z","000 stopper0 bit0"],
	     "010 stopper1 bit0 B1":["NZ","100 stopper0 bit1"],"010 stopper1 bit1 A1":["NONE","FAILURE"],
	     "010 stopper1 bit1 B0":["NZ","000 stopper0 bit0"],"010 stopper1 bit1 B1":["Z","100 stopper0 bit1"],
	     "011 stopper0 bit0 A1":["NONE","011 stopper1 bit1"],"011 stopper0 bit0 B0":["Z","000 stopper0 bit0"],
	     "011 stopper0 bit0 B1":["NZ","000 stopper0 bit0"],"011 stopper0 bit1 A1":["NONE","011 stopper1 bit0"],
	     "011 stopper0 bit1 B0":["NZ","000 stopper0 bit0"],"011 stopper0 bit1 B1":["Z","000 stopper0 bit0"],
	     "011 stopper1 bit0 A1":["NONE","FAILURE"],"011 stopper1 bit0 B0":["Z","100 stopper0 bit1"],
	     "011 stopper1 bit0 B1":["NZ","000 stopper0 bit0"],"011 stopper1 bit1 A1":["NONE","FAILURE"],
	     "011 stopper1 bit1 B0":["NZ","100 stopper0 bit1"],"011 stopper1 bit1 B1":["Z","000 stopper0 bit0"],
	     "100 stopper0 bit0 A1":["NONE","100 stopper1 bit1"],"100 stopper0 bit0 B0":["Z","100 stopper0 bit1"],
	     "100 stopper0 bit0 B1":["NZ","100 stopper0 bit1"],"100 stopper0 bit1 A1":["NONE","100 stopper1 bit0"],
	     "100 stopper0 bit1 B0":["NZ","100 stopper0 bit1"],"100 stopper0 bit1 B1":["Z","100 stopper0 bit1"],
	     "100 stopper1 bit0 A1":["NONE","FAILURE"],"100 stopper1 bit0 B0":["Z","000 stopper0 bit0"],
	     "100 stopper1 bit0 B1":["NZ","100 stopper0 bit1"],"100 stopper1 bit1 A1":["NONE","FAILURE"],
	     "100 stopper1 bit1 B0":["NZ","000 stopper0 bit0"],"100 stopper1 bit1 B1":["Z","100 stopper0 bit1"],
	     "101 stopper0 bit0 A1":["NONE","101 stopper1 bit1"],"101 stopper0 bit0 B0":["Z","100 stopper0 bit1"],
             "101 stopper0 bit0 B1":["NZ","100 stopper0 bit1"],"101 stopper0 bit1 A1":["NONE","101 stopper1 bit0"],
	     "101 stopper0 bit1 B0":["NZ","100 stopper0 bit1"],"101 stopper0 bit1 B1":["Z","100 stopper0 bit1"],
	     "101 stopper1 bit0 A1":["NONE","FAILURE"],"101 stopper1 bit0 B0":["Z","100 stopper0 bit1"],
	     "101 stopper1 bit0 B1":["NZ","000 stopper0 bit0"],"101 stopper1 bit1 A1":["NONE","FAILURE"],
	     "101 stopper1 bit1 B0":["NZ","100 stopper0 bit1"],"101 stopper1 bit1 B1":["Z","000 stopper0 bit0"],
	     "110 stopper0 bit0 A1":["NONE","110 stopper1 bit1"],"110 stopper0 bit0 B0":["Z","000 stopper0 bit0"],
	     "110 stopper0 bit0 B1":["NZ","100 stopper0 bit1"],"110 stopper0 bit1 A1":["NONE","110 stopper1 bit0"],
	     "110 stopper0 bit1 B0":["NZ","000 stopper0 bit0"],"110 stopper0 bit1 B1":["Z","100 stopper0 bit1"],
	     "110 stopper1 bit0 A1":["NONE","FAILURE"],"110 stopper1 bit0 B0":["Z","100 stopper0 bit1"],
	     "110 stopper1 bit0 B1":["NZ","100 stopper0 bit1"],"110 stopper1 bit1 A1":["NONE","FAILURE"],
	     "110 stopper1 bit1 B0":["NZ","100 stopper0 bit1"],"110 stopper1 bit1 B1":["Z","100 stopper0 bit1"],
	     "111 stopper0 bit0 A1":["NONE","111 stopper1 bit1"],"111 stopper0 bit0 B0":["Z","100 stopper0 bit1"],
	     "111 stopper0 bit0 B1":["NZ","000 stopper0 bit0"],"111 stopper0 bit1 A1":["NONE","111 stopper1 bit0"],
	     "111 stopper0 bit1 B0":["NZ","100 stopper0 bit1"],"111 stopper0 bit1 B1":["Z","000 stopper0 bit0"],
	     "111 stopper1 bit0 A1":["NONE","FAILURE"],"111 stopper1 bit0 B0":["Z","100 stopper0 bit1"],
	     "111 stopper1 bit0 B1":["NZ","100 stopper0 bit1"],"111 stopper1 bit1 A1":["NONE","FAILURE"],
             "111 stopper1 bit1 B0":["NZ","100 stopper0 bit1"],"111 stopper1 bit1 B1":["Z","100 stopper0 bit1"]}

memory = {}

# pi program
APGsembly = """INITIAL; Z; S1; READ T0
INITIAL; NZ; S1; READ T0
S1; Z; S2; SET T0, READ T2
S1; NZ; S2; SET T0, READ T2
S2; Z; S3; NOP, SET T2
S2; NZ; S3; NOP, SET T2
S3; Z; S4; NOP, INC R4
S3; NZ; S4; NOP, INC R4
S4; Z; S5; NOP, INC R0
S4; NZ; S5; NOP, INC R0
S5; Z; S6; NOP, INC R0
S5; NZ; S6; NOP, INC R0
S6; Z; S7; NOP, INC R0
S6; NZ; S7; NOP, INC R0
S7; Z; S8; NOP, INC R0
S7; NZ; S8; NOP, INC R0
S8; Z; S9; NOP, INC R0
S8; NZ; S9; NOP, INC R0
S9; Z; S10; NOP, INC R0
S9; NZ; S10; NOP, INC R0
S10; Z; S11; NOP, INC R0
S10; NZ; S11; NOP, INC R0
S11; Z; S12; NOP, INC R0
S11; NZ; S12; NOP, INC R0
S12; Z; S13; NOP, INC R9
S12; NZ; S13; NOP, INC R9
S13; Z; S14; NOP, INC R9
S13; NZ; S14; NOP, INC R9
S14; Z; S15; NOP, INC R9
S14; NZ; S15; NOP, INC R9
S15; Z; P1; NOP, INC R9
S15; NZ; P1; NOP, INC R9
P1; Z; P2; TDEC R9
P1; NZ; P2; TDEC R9
P2; Z; Q1; NOP
P2; NZ; P3; NOP
P3; Z; P4; NOP, INC R3
P3; NZ; P4; NOP, INC R3
P4; Z; P5; NOP, INC R4
P4; NZ; P5; NOP, INC R4
P5; Z; P6; TDEC R0, INC R4
P5; NZ; P6; TDEC R0, INC R4
P6; Z; P7; TDEC R1
P6; NZ; P6; TDEC R0, INC R1
P7; Z; P8; TDEC R2
P7; NZ; P7; INC R0, TDEC R1, INC R2
P8; Z; P13; DEC T3
P8; NZ; P9; READ T3
P9; Z; P10; READ T0
P9; NZ; P10; READ T0
P10; Z; P11; RESET T0, RESET T3, INC T3
P10; NZ; P11; SET T0, SET T3, INC T3
P11; Z; P12; INC T0
P11; NZ; P12; INC T0
P12; Z; P8; TDEC R2
P12; NZ; P8; TDEC R2
P13; Z; P14; DEC T0
P13; NZ; P13; DEC T3
P14; Z; P15; TDEC R0
P14; NZ; P14; DEC T0
P15; Z; P16; TDEC R1
P15; NZ; P15; TDEC R0, INC R1
P16; Z; P17; TDEC R2
P16; NZ; P16; INC R0, TDEC R1, INC R2
P17; Z; P23; DEC T0
P17; NZ; P18; READ T0
P18; Z; P19; RESET T0, READ T3
P18; NZ; P19; SET T0, READ T3, ADD A1
P19; Z; P20; ADD B0
P19; NZ; P20; ADD B1
P20; Z; P21; RESET T3, INC T3
P20; NZ; P21; SET T3, INC T3
P21; Z; P22; INC T0
P21; NZ; P22; INC T0
P22; Z; P17; TDEC R2
P22; NZ; P17; TDEC R2
P23; Z; P24; DEC T3
P23; NZ; P23; DEC T0
P24; Z; P25; TDEC R0
P24; NZ; P24; DEC T3
P25; Z; P26; TDEC R1
P25; NZ; P25; TDEC R0, INC R1
P26; Z; P27; TDEC R2
P26; NZ; P26; INC R0, TDEC R1, INC R2
P27; Z; P33; DEC T1
P27; NZ; P28; READ T1
P28; Z; P29; RESET T1, READ T3
P28; NZ; P29; RESET T1, READ T3, ADD A1
P29; Z; P30; ADD B0
P29; NZ; P30; ADD B1
P30; Z; P31; RESET T3, INC T3
P30; NZ; P31; SET T3, INC T3
P31; Z; P32; INC T1
P31; NZ; P32; INC T1
P32; Z; P27; TDEC R2
P32; NZ; P27; TDEC R2
P33; Z; P34; DEC T3
P33; NZ; P33; DEC T1
P34; Z; P35; NOP
P34; NZ; P34; DEC T3
P35; Z; P36; TDEC R4
P35; NZ; P36; TDEC R4
P36; Z; P37; TDEC R1
P36; NZ; P36; INC R1, TDEC R4
P37; Z; P38; TDEC R5
P37; NZ; P37; TDEC R1, INC R4, INC R5
P38; Z; P49; NOP
P38; NZ; P39; TDEC R0
P39; Z; P40; TDEC R1
P39; NZ; P39; TDEC R0, INC R1
P40; Z; P41; TDEC R2
P40; NZ; P40; INC R0, TDEC R1, INC R2
P41; Z; P47; DEC T3
P41; NZ; P42; READ T3
P42; Z; P43; READ T1, RESET T3
P42; NZ; P43; READ T1, SET T3, ADD A1
P43; Z; P44; ADD B0
P43; NZ; P44; ADD B1
P44; Z; P45; RESET T1, INC T1
P44; NZ; P45; SET T1, INC T1
P45; Z; P46; INC T3
P45; NZ; P46; INC T3
P46; Z; P41; TDEC R2
P46; NZ; P41; TDEC R2
P47; Z; P48; DEC T1
P47; NZ; P47; DEC T3
P48; Z; P38; TDEC R5
P48; NZ; P48; DEC T1
P49; Z; P50; TDEC R0
P49; NZ; P50; TDEC R0
P50; Z; P51; TDEC R1
P50; NZ; P50; TDEC R0, INC R1
P51; Z; P52; TDEC R2
P51; NZ; P51; INC R0, TDEC R1, INC R2
P52; Z; P57; DEC T3
P52; NZ; P53; READ T3
P53; Z; P54; READ T0
P53; NZ; P54; READ T0
P54; Z; P55; RESET T0, RESET T3, INC T3
P54; NZ; P55; RESET T0, SET T3, INC T3
P55; Z; P56; INC T0
P55; NZ; P56; INC T0
P56; Z; P52; TDEC R2
P56; NZ; P52; TDEC R2
P57; Z; P58; DEC T0
P57; NZ; P57; DEC T3
P58; Z; P59; NOP
P58; NZ; P58; DEC T0
P59; Z; P60; TDEC R3
P59; NZ; P60; TDEC R3
P60; Z; P61; TDEC R1
P60; NZ; P60; INC R1, TDEC R3
P61; Z; P62; TDEC R5
P61; NZ; P61; TDEC R1, INC R3, INC R5
P62; Z; P73; NOP
P62; NZ; P63; TDEC R0
P63; Z; P64; TDEC R1
P63; NZ; P63; TDEC R0, INC R1
P64; Z; P65; TDEC R2
P64; NZ; P64; INC R0, TDEC R1, INC R2
P65; Z; P71; DEC T3
P65; NZ; P66; READ T3
P66; Z; P67; READ T0, RESET T3
P66; NZ; P67; READ T0, SET T3, ADD A1
P67; Z; P68; ADD B0
P67; NZ; P68; ADD B1
P68; Z; P69; RESET T0, INC T0
P68; NZ; P69; SET T0, INC T0
P69; Z; P70; INC T3
P69; NZ; P70; INC T3
P70; Z; P65; TDEC R2
P70; NZ; P65; TDEC R2
P71; Z; P72; DEC T0
P71; NZ; P71; DEC T3
P72; Z; P62; TDEC R5
P72; NZ; P72; DEC T0
P73; Z; P74; TDEC R0
P73; NZ; P74; TDEC R0
P74; Z; P75; TDEC R1
P74; NZ; P74; TDEC R0, INC R1
P75; Z; P76; TDEC R2
P75; NZ; P75; INC R0, TDEC R1, INC R2
P76; Z; P81; DEC T3
P76; NZ; P77; READ T3
P77; Z; P78; READ T2
P77; NZ; P78; READ T2
P78; Z; P79; RESET T2, RESET T3, INC T3
P78; NZ; P79; RESET T2, SET T3, INC T3
P79; Z; P80; INC T2
P79; NZ; P80; INC T2
P80; Z; P76; TDEC R2
P80; NZ; P76; TDEC R2
P81; Z; P82; DEC T2
P81; NZ; P81; DEC T3
P82; Z; P83; NOP
P82; NZ; P82; DEC T2
P83; Z; P84; TDEC R4
P83; NZ; P84; TDEC R4
P84; Z; P85; TDEC R1
P84; NZ; P84; INC R1, TDEC R4
P85; Z; P86; TDEC R5
P85; NZ; P85; TDEC R1, INC R4, INC R5
P86; Z; P97; NOP
P86; NZ; P87; TDEC R0
P87; Z; P88; TDEC R1
P87; NZ; P87; TDEC R0, INC R1
P88; Z; P89; TDEC R2
P88; NZ; P88; INC R0, TDEC R1, INC R2
P89; Z; P95; DEC T3
P89; NZ; P90; READ T3
P90; Z; P91; READ T2, RESET T3
P90; NZ; P91; READ T2, SET T3, ADD A1
P91; Z; P92; ADD B0
P91; NZ; P92; ADD B1
P92; Z; P93; RESET T2, INC T2
P92; NZ; P93; SET T2, INC T2
P93; Z; P94; INC T3
P93; NZ; P94; INC T3
P94; Z; P89; TDEC R2
P94; NZ; P89; TDEC R2
P95; Z; P96; DEC T2
P95; NZ; P95; DEC T3
P96; Z; P86; TDEC R5
P96; NZ; P96; DEC T2
P97; Z; P98; TDEC R3
P97; NZ; P98; TDEC R3
P98; Z; P99; TDEC R1
P98; NZ; P98; INC R1, TDEC R3
P99; Z; P1; NOP
P99; NZ; P99; INC R0, TDEC R1, INC R3
Q1; Z; Q2; TDEC R7
Q1; NZ; Q2; TDEC R7
Q2; Z; Q3; TDEC R1
Q2; NZ; Q2; INC R1, TDEC R7
Q3; Z; Q4; NOP
Q3; NZ; Q3; TDEC R1, INC R7, INC R8
Q4; Z; Q5; TDEC R0
Q4; NZ; Q5; TDEC R0
Q5; Z; Q6; TDEC R1
Q5; NZ; Q5; TDEC R0, INC R1
Q6; Z; Q7; TDEC R2
Q6; NZ; Q6; INC R0, TDEC R1, INC R2
Q7; Z; Q12; DEC T3
Q7; NZ; Q8; READ T3
Q8; Z; Q9; READ T0
Q8; NZ; Q9; READ T0
Q9; Z; Q10; RESET T0, RESET T3, INC T3
Q9; NZ; Q10; SET T0, SET T3, INC T3
Q10; Z; Q11; INC T0
Q10; NZ; Q11; INC T0
Q11; Z; Q7; TDEC R2
Q11; NZ; Q7; TDEC R2
Q12; Z; Q13; DEC T0
Q12; NZ; Q12; DEC T3
Q13; Z; Q14; NOP
Q13; NZ; Q13; DEC T0
Q14; Z; Q15; TDEC R0
Q14; NZ; Q15; TDEC R0
Q15; Z; Q16; TDEC R1
Q15; NZ; Q15; TDEC R0, INC R1
Q16; Z; Q17; TDEC R2
Q16; NZ; Q16; INC R0, TDEC R1, INC R2
Q17; Z; Q23; DEC T1
Q17; NZ; Q18; READ T1
Q18; Z; Q19; RESET T1, READ T3
Q18; NZ; Q19; SET T1, READ T3, ADD A1
Q19; Z; Q20; ADD B0
Q19; NZ; Q20; ADD B1
Q20; Z; Q21; RESET T3, INC T3
Q20; NZ; Q21; SET T3, INC T3
Q21; Z; Q22; INC T1
Q21; NZ; Q22; INC T1
Q22; Z; Q17; TDEC R2
Q22; NZ; Q17; TDEC R2
Q23; Z; Q24; DEC T3
Q23; NZ; Q23; DEC T1
Q24; Z; Q25; TDEC R6
Q24; NZ; Q24; DEC T3
Q25; Z; Q26; NOP
Q25; NZ; Q25; TDEC R6
Q26; Z; Q27; TDEC R0
Q26; NZ; Q27; TDEC R0
Q27; Z; Q28; TDEC R1
Q27; NZ; Q27; TDEC R0, INC R1
Q28; Z; Q29; TDEC R2
Q28; NZ; Q28; INC R0, TDEC R1, INC R2
Q29; Z; Q32; READ T3
Q29; NZ; Q30; INC T3
Q30; Z; Q31; INC T2
Q30; NZ; Q31; INC T2
Q31; Z; Q29; TDEC R2
Q31; NZ; Q29; TDEC R2
Q32; Z; Q33; READ T2, RESET T3
Q32; NZ; Q36; READ T2, SET T3
Q33; Z; Q34; RESET T2, DEC T2
Q33; NZ; Q37; SET T2, DEC T3
Q34; Z; Q35; DEC T3
Q34; NZ; Q35; DEC T3
Q35; Z; Q40; DEC T2
Q35; NZ; Q32; READ T3
Q36; Z; Q39; RESET T2, DEC T3
Q36; NZ; Q34; SET T2, DEC T2
Q37; Z; Q38; DEC T2
Q37; NZ; Q37; DEC T3
Q38; Z; Q52; TDEC R8
Q38; NZ; Q38; DEC T2
Q39; Z; Q40; DEC T2
Q39; NZ; Q39; DEC T3
Q40; Z; Q41; NOP
Q40; NZ; Q40; DEC T2
Q41; Z; Q42; TDEC R0
Q41; NZ; Q42; TDEC R0
Q42; Z; Q43; TDEC R1
Q42; NZ; Q42; TDEC R0, INC R1
Q43; Z; Q44; TDEC R2
Q43; NZ; Q43; INC R0, TDEC R1, INC R2
Q44; Z; Q50; DEC T3
Q44; NZ; Q45; READ T3
Q45; Z; Q46; READ T2
Q45; NZ; Q46; READ T2, SUB A1
Q46; Z; Q47; RESET T2, SUB B0
Q46; NZ; Q47; SET T2, SUB B1
Q47; Z; Q48; RESET T3, INC T3
Q47; NZ; Q48; SET T3, INC T3
Q48; Z; Q49; INC T2
Q48; NZ; Q49; INC T2
Q49; Z; Q44; TDEC R2
Q49; NZ; Q44; TDEC R2
Q50; Z; Q51; DEC T2
Q50; NZ; Q50; DEC T3
Q51; Z; Q26; NOP, INC R6
Q51; NZ; Q51; DEC T2
Q52; Z; Q61; NOP
Q52; NZ; Q53; NOP
Q53; Z; Q54; TDEC R0
Q53; NZ; Q54; TDEC R0
Q54; Z; Q55; TDEC R1
Q54; NZ; Q54; TDEC R0, INC R1
Q55; Z; Q56; TDEC R2
Q55; NZ; Q55; INC R0, TDEC R1, INC R2
Q56; Z; Q60; DEC T3
Q56; NZ; Q57; READ T3
Q57; Z; Q58; MUL 0
Q57; NZ; Q58; MUL 1
Q58; Z; Q59; RESET T3, INC T3
Q58; NZ; Q59; SET T3, INC T3
Q59; Z; Q56; TDEC R2
Q59; NZ; Q56; TDEC R2
Q60; Z; Q25; TDEC R6
Q60; NZ; Q60; DEC T3
Q61; Z; Q62; TDEC R6
Q61; NZ; Q62; TDEC R6
Q62; Z; Q71; NOP, OUTPUT 0
Q62; NZ; Q63; TDEC R6
Q63; Z; Q71; NOP, OUTPUT 1
Q63; NZ; Q64; TDEC R6
Q64; Z; Q71; NOP, OUTPUT 2
Q64; NZ; Q65; TDEC R6
Q65; Z; Q71; NOP, OUTPUT 3
Q65; NZ; Q66; TDEC R6
Q66; Z; Q71; NOP, OUTPUT 4
Q66; NZ; Q67; TDEC R6
Q67; Z; Q71; NOP, OUTPUT 5
Q67; NZ; Q68; TDEC R6
Q68; Z; Q71; NOP, OUTPUT 6
Q68; NZ; Q69; TDEC R6
Q69; Z; Q71; NOP, OUTPUT 7
Q69; NZ; Q70; TDEC R6
Q70; Z; Q71; NOP, OUTPUT 8
Q70; NZ; Q71; NOP, OUTPUT 9
Q71; Z; Q72; TDEC R7
Q71; NZ; Q72; TDEC R7
Q72; Z; Q73; NOP, OUTPUT .
Q72; NZ; Q73; NOP, INC R7
Q73; Z; S12; NOP, INC R7
Q73; NZ; S12; NOP, INC R7"""

registers = {}
progname = "pi-calc"
proglines = APGsembly.split("\n")
program = {}

g.new(progname)
g.setcell(0,0,1)
g.fit()
g.setcell(0,0,0)
g.update()
runflag = 0

def check_keyboard():
  global runflag
  while 1:
    evt = g.getevent()
    if evt !="":
      g.show(state + " -- " + nextstate + " :: " + instr + "; regs=" + str(registers)  + " -- 'r' to toggle run mode, any key to step")
    if evt == "key q none":
      g.setclipstr(s)
      g.exit()
    if evt == "key r none":
      runflag = 1-runflag
    elif evt=="key g none":
      break
    else:
      g.doevent(evt)
    if runflag == 1:
      break

# every state has a Z and NZ jump instruction to following states,
#   so the order of the program lines doesn't really matter.
#   Turn the program into a dictionary.
for item in proglines:
   label, bitval, nextstate, instr = item.replace(", ",",").split("; ")
   program[label+";"+bitval]=[nextstate,instr]

state, nextstate, nextoutput, outputtext = "START","INITIAL","Z",""

g.show(state + " -- " + nextstate + " :: " + instr + "; regs=" + str(registers)  + " -- 'r' to toggle run mode, any key to step")

check_keyboard()

while 1:

   if nextoutput == "":
      g.show(state + " -- " + nextstate + " :: " + instr + "; regs=" + str(registers)  + "; mem=" + str(memory))
      g.note("Program reached halt state (because no bit value was returned by any instruction).")
      g.setclipstr(s)
      g.exit()
   
   state = nextstate + ";" + nextoutput
   # get info from program dictionary, move to next state
   nextstate, instr = program[state]

   # process instructions for current state
   # -- there may be just one instruction,
   #    or several comma-separated instructions
   nextoutput = ""  # if some instruction doesn't set this variable, the program will halt
   for i in instr.split(","):
     # allow stepping or full-speed run from keyboard (toggle "r")
     check_keyboard()

     if i == "NOP":
       nextoutput = "Z"

     elif i == "READ SQ":
       if "SQX" not in registers: registers["SQX"], registers["SQY"]=0,0  # initialize if necessary
       coord = str(registers["SQX"]) +","+str(registers["SQY"])
       if coord not in memory:
         memory[coord]=0
       if memory[coord]==0:
         nextoutput = "Z"
       else:
         nextoutput = "NZ"
         memory[coord] = 0  # this is a destructive read operation
         g.setcell(registers["SQX"]-registers["SQY"],-registers["SQX"]-registers["SQY"],memory[coord])
         g.update()

     elif i == "SET SQ":
       if coord not in memory:
         memory[coord]=0
       if memory[coord]==0:
         memory[coord] = 1
         g.setcell(registers["SQX"]-registers["SQY"],-registers["SQX"]-registers["SQY"],memory[coord])
         g.update()
       else:
         g.note("PROGRAM ERROR:\nTried to set memory coordinate " + coord + "to 1,\nwhen it was already 1.")
         g.exit()

     elif i[:4]=="INC ":
       reg = i.split(" ")[1]
       if reg not in registers:
         if reg[:1]=="T": # binary register
           registers[reg]=[0,"0"]
         else:
           registers[reg]=0 # simple register
       if isinstance(registers[reg], types.ListType): # binary register
         ptr,bits = registers[reg]
         if ptr == len(bits)-1:
           bits+="0"         # the mechanism automatically adds a zero when INCing past current end of tape
           nextoutput = "Z"  # ... and it returns a zero output in that case
         else:
           nextoutput = "NZ" # if it's not creating a new bit, it returns an NZ output.  TODO: what does the program use this for?
         registers[reg] = [ptr+1,bits]
       else:
         registers[reg] += 1  # simple register

     elif i[:5]=="TDEC ": # simple register
       reg = i.split(" ")[1]
       if reg not in registers:
         registers[reg]=0
       if registers[reg] == 0:
         nextoutput = "Z" # don't update register, it's already zero
       else:
         registers[reg] -= 1
         nextoutput = "NZ"

     elif i[:4]=="DEC ": # binary register
       reg = i.split(" ")[1]
       ptr,bits = registers[reg]
       if ptr == 0:
         nextoutput = "Z" # don't update register, it's already zero
       else:
         registers[reg] = [ptr-1,bits]
         nextoutput = "NZ"    

     elif i=="HALT":
       g.note("Program reached halt state.")
       g.setclipstr(s)
       g.exit()

     elif i[:4]=="MUL ":
       bit = str(i[4:])
       if "MUL" not in registers:
         registers["MUL"]="00000"
       nextoutput, registers["MUL"] = mullookup["MUL" + bit + " " + registers["MUL"]]

     elif i[:7] == "OUTPUT ":
       outputtext += i[7:]
       outpat = make_text(outputtext)
       g.putcells(outpat, 0, 10)
       g.update()

     elif i[:4]=="SUB ":
       if "SUB" not in registers:
         registers["SUB"]="000 stopper0 bit0"
       whichinput = i[4:]
       out, registers["SUB"] = sublookup[registers["SUB"] + " " + whichinput]
       if registers["SUB"] == "FAILURE":
         g.note("Program crashed at line '" + i + "'.  SUB A1 must have been run twice (?).")
         g.exit()
       if out != "NONE":
         nextoutput = out

     elif i[:4]=="ADD ":
       if "ADD" not in registers:
         registers["ADD"]="000 bit0"
       whichinput = i[4:]
       temp = registers["ADD"] + " " + whichinput
       out, registers["ADD"] = addlookup[temp]
       if out != "NONE":
         nextoutput = out

     elif i[:5]=="READ ":
       binregname = i[5:] # TODO: maybe be consistent and use .split()?
       if binregname not in registers:
         registers[binregname]=[0,"0"]
       ptr, bits = registers[binregname]
       if bits[ptr]=="x":
         g.note("Program crashed on instruction '" + i + "':\n attempt to read an empty position in a binary register.")
         g.exit()
       elif bits[ptr]=="0":
         nextoutput = "Z"
       elif bits[ptr]=="1":
         nextoutput = "NZ"
       else:
         g.note("Emulator error. Found value '" + bits[ptr] + "' on READ, in " + binregname + " bitstring -- " + str(registers[binregname]) + ".")
         g.exit()
       registers[binregname] = [ptr, bits[:ptr]+"x"+bits[ptr+1:]]

     elif i[:4]=="SET ":
       binregname = i[4:]
       if binregname not in registers:
         registers[binregname]=[0,"0"]
       ptr, bits = registers[binregname]
       if bits[ptr]!="x":
         g.note("Crash. Found value '" + bits[ptr] + "' on SET, in " + binregname + " bitstring -- " + str(registers[binregname]) + ".")
         g.exit()
       registers[binregname] = [ptr, bits[:ptr]+"1"+bits[ptr+1:]]

     elif i[:6]=="RESET ":
       binregname = i[6:]
       if binregname not in registers:
         registers[binregname]=[0,"0"]
       else:
         ptr, bits = registers[binregname]
       if bits[ptr]!="x":
         g.note("Crash. Found value '" + bits[ptr] + "' on READ, in " + binregname + " bitstring -- " + str(registers[binregname]) + ".")
         g.exit()
       registers[binregname] = [ptr, bits[:ptr]+"0"+bits[ptr+1:]]

     else:
       g.note("Unknown instruction: " + instr + " -- ~" + i + "~")
       g.exit()
The next TODO item is to clean the emulator script up a bit more, and maybe allow programs to be entered from the clipboard instead of hard-coding everything. Maybe use a Lua overlay display for all the register values, the output digits and so forth.

User avatar
dvgrn
Moderator
Posts: 6049
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Reverse engineering the phi and pi calculators

Post by dvgrn » November 8th, 2019, 10:08 am

If anyone would be interested in helping out with this pi-calculator emulator project, one thing that I haven't tackled yet is a detailed comparison between pi calculator APGsembly code and the commented-and-labeled phi calculator code.

There are clearly some subroutines in the pi code that do things very similar to what the phi code is doing -- copy one register to another, etc. For the first run at decompiling I just made "P" and "Q" labels for everything, where "Q" marked the start of an obvious important jump location.

Ideally there should be more different letter labels delineating smaller chunks of the code, ideally with # comment lines wherever it's really clear what's going on. Pretty much every state reached by a (relatively) long-distance jump could probably start a new section.

Here's the current working APGsembly code for the phi calculator:

Code: Select all

# Pi calculation program

# This is designed to calculate the decimal digits of Pi, or 3.14159...
# The original APGsembly code was written by Adam P. Goucher, February 2010.
# This version was decompiled from the the pi-calculator Life pattern
# in October/November 2019, since the original code listing is rumored
# to be irretrievably lost.
#
# State labels and comments still could use a lot of improvement.

# State    Input   Next state    Actions
# ---------------------------------------
INITIAL;   Z;      S1;           READ T0
INITIAL;   NZ;     S1;           READ T0
S1;        Z;      S2;           SET T0, READ T2
S1;        NZ;     S2;           SET T0, READ T2
S2;        Z;      S3;           NOP, SET T2
S2;        NZ;     S3;           NOP, SET T2
S3;        Z;      S4;           NOP, INC R4
S3;        NZ;     S4;           NOP, INC R4
S4;        Z;      S5;           NOP, INC R0
S4;        NZ;     S5;           NOP, INC R0
S5;        Z;      S6;           NOP, INC R0
S5;        NZ;     S6;           NOP, INC R0
S6;        Z;      S7;           NOP, INC R0
S6;        NZ;     S7;           NOP, INC R0
S7;        Z;      S8;           NOP, INC R0
S7;        NZ;     S8;           NOP, INC R0
S8;        Z;      S9;           NOP, INC R0
S8;        NZ;     S9;           NOP, INC R0
S9;        Z;      S10;          NOP, INC R0
S9;        NZ;     S10;          NOP, INC R0
S10;       Z;      S11;          NOP, INC R0
S10;       NZ;     S11;          NOP, INC R0
S11;       Z;      S12;          NOP, INC R0
S11;       NZ;     S12;          NOP, INC R0
S12;       Z;      S13;          NOP, INC R9
S12;       NZ;     S13;          NOP, INC R9
S13;       Z;      S14;          NOP, INC R9
S13;       NZ;     S14;          NOP, INC R9
S14;       Z;      S15;          NOP, INC R9
S14;       NZ;     S15;          NOP, INC R9
S15;       Z;      P1;           NOP, INC R9
S15;       NZ;     P1;           NOP, INC R9
P1;        Z;      P2;           TDEC R9
P1;        NZ;     P2;           TDEC R9
P2;        Z;      Q1;           NOP
P2;        NZ;     P3;           NOP
P3;        Z;      P4;           NOP, INC R3
P3;        NZ;     P4;           NOP, INC R3
P4;        Z;      P5;           NOP, INC R4
P4;        NZ;     P5;           NOP, INC R4
P5;        Z;      P6;           TDEC R0, INC R4
P5;        NZ;     P6;           TDEC R0, INC R4
P6;        Z;      P7;           TDEC R1
P6;        NZ;     P6;           TDEC R0, INC R1
P7;        Z;      P8;           TDEC R2
P7;        NZ;     P7;           INC R0, TDEC R1, INC R2
P8;        Z;      P13;          DEC T3
P8;        NZ;     P9;           READ T3
P9;        Z;      P10;          READ T0
P9;        NZ;     P10;          READ T0
P10;       Z;      P11;          RESET T0, RESET T3, INC T3
P10;       NZ;     P11;          SET T0, SET T3, INC T3
P11;       Z;      P12;          INC T0
P11;       NZ;     P12;          INC T0
P12;       Z;      P8;           TDEC R2
P12;       NZ;     P8;           TDEC R2
P13;       Z;      P14;          DEC T0
P13;       NZ;     P13;          DEC T3
P14;       Z;      P15;          TDEC R0
P14;       NZ;     P14;          DEC T0
P15;       Z;      P16;          TDEC R1
P15;       NZ;     P15;          TDEC R0, INC R1
P16;       Z;      P17;          TDEC R2
P16;       NZ;     P16;          INC R0, TDEC R1, INC R2
P17;       Z;      P23;          DEC T0
P17;       NZ;     P18;          READ T0
P18;       Z;      P19;          RESET T0, READ T3
P18;       NZ;     P19;          SET T0, READ T3, ADD A1
P19;       Z;      P20;          ADD B0
P19;       NZ;     P20;          ADD B1
P20;       Z;      P21;          RESET T3, INC T3
P20;       NZ;     P21;          SET T3, INC T3
P21;       Z;      P22;          INC T0
P21;       NZ;     P22;          INC T0
P22;       Z;      P17;          TDEC R2
P22;       NZ;     P17;          TDEC R2
P23;       Z;      P24;          DEC T3
P23;       NZ;     P23;          DEC T0
P24;       Z;      P25;          TDEC R0
P24;       NZ;     P24;          DEC T3
P25;       Z;      P26;          TDEC R1
P25;       NZ;     P25;          TDEC R0, INC R1
P26;       Z;      P27;          TDEC R2
P26;       NZ;     P26;          INC R0, TDEC R1, INC R2
P27;       Z;      P33;          DEC T1
P27;       NZ;     P28;          READ T1
P28;       Z;      P29;          RESET T1, READ T3
P28;       NZ;     P29;          RESET T1, READ T3, ADD A1
P29;       Z;      P30;          ADD B0
P29;       NZ;     P30;          ADD B1
P30;       Z;      P31;          RESET T3, INC T3
P30;       NZ;     P31;          SET T3, INC T3
P31;       Z;      P32;          INC T1
P31;       NZ;     P32;          INC T1
P32;       Z;      P27;          TDEC R2
P32;       NZ;     P27;          TDEC R2
P33;       Z;      P34;          DEC T3
P33;       NZ;     P33;          DEC T1
P34;       Z;      P35;          NOP
P34;       NZ;     P34;          DEC T3
P35;       Z;      P36;          TDEC R4
P35;       NZ;     P36;          TDEC R4
P36;       Z;      P37;          TDEC R1
P36;       NZ;     P36;          INC R1, TDEC R4
P37;       Z;      P38;          TDEC R5
P37;       NZ;     P37;          TDEC R1, INC R4, INC R5
P38;       Z;      P49;          NOP
P38;       NZ;     P39;          TDEC R0
P39;       Z;      P40;          TDEC R1
P39;       NZ;     P39;          TDEC R0, INC R1
P40;       Z;      P41;          TDEC R2
P40;       NZ;     P40;          INC R0, TDEC R1, INC R2
P41;       Z;      P47;          DEC T3
P41;       NZ;     P42;          READ T3
P42;       Z;      P43;          READ T1, RESET T3
P42;       NZ;     P43;          READ T1, SET T3, ADD A1
P43;       Z;      P44;          ADD B0
P43;       NZ;     P44;          ADD B1
P44;       Z;      P45;          RESET T1, INC T1
P44;       NZ;     P45;          SET T1, INC T1
P45;       Z;      P46;          INC T3
P45;       NZ;     P46;          INC T3
P46;       Z;      P41;          TDEC R2
P46;       NZ;     P41;          TDEC R2
P47;       Z;      P48;          DEC T1
P47;       NZ;     P47;          DEC T3
P48;       Z;      P38;          TDEC R5
P48;       NZ;     P48;          DEC T1
P49;       Z;      P50;          TDEC R0
P49;       NZ;     P50;          TDEC R0
P50;       Z;      P51;          TDEC R1
P50;       NZ;     P50;          TDEC R0, INC R1
P51;       Z;      P52;          TDEC R2
P51;       NZ;     P51;          INC R0, TDEC R1, INC R2
P52;       Z;      P57;          DEC T3
P52;       NZ;     P53;          READ T3
P53;       Z;      P54;          READ T0
P53;       NZ;     P54;          READ T0
P54;       Z;      P55;          RESET T0, RESET T3, INC T3
P54;       NZ;     P55;          RESET T0, SET T3, INC T3
P55;       Z;      P56;          INC T0
P55;       NZ;     P56;          INC T0
P56;       Z;      P52;          TDEC R2
P56;       NZ;     P52;          TDEC R2
P57;       Z;      P58;          DEC T0
P57;       NZ;     P57;          DEC T3
P58;       Z;      P59;          NOP
P58;       NZ;     P58;          DEC T0
P59;       Z;      P60;          TDEC R3
P59;       NZ;     P60;          TDEC R3
P60;       Z;      P61;          TDEC R1
P60;       NZ;     P60;          INC R1, TDEC R3
P61;       Z;      P62;          TDEC R5
P61;       NZ;     P61;          TDEC R1, INC R3, INC R5
P62;       Z;      P73;          NOP
P62;       NZ;     P63;          TDEC R0
P63;       Z;      P64;          TDEC R1
P63;       NZ;     P63;          TDEC R0, INC R1
P64;       Z;      P65;          TDEC R2
P64;       NZ;     P64;          INC R0, TDEC R1, INC R2
P65;       Z;      P71;          DEC T3
P65;       NZ;     P66;          READ T3
P66;       Z;      P67;          READ T0, RESET T3
P66;       NZ;     P67;          READ T0, SET T3, ADD A1
P67;       Z;      P68;          ADD B0
P67;       NZ;     P68;          ADD B1
P68;       Z;      P69;          RESET T0, INC T0
P68;       NZ;     P69;          SET T0, INC T0
P69;       Z;      P70;          INC T3
P69;       NZ;     P70;          INC T3
P70;       Z;      P65;          TDEC R2
P70;       NZ;     P65;          TDEC R2
P71;       Z;      P72;          DEC T0
P71;       NZ;     P71;          DEC T3
P72;       Z;      P62;          TDEC R5
P72;       NZ;     P72;          DEC T0
P73;       Z;      P74;          TDEC R0
P73;       NZ;     P74;          TDEC R0
P74;       Z;      P75;          TDEC R1
P74;       NZ;     P74;          TDEC R0, INC R1
P75;       Z;      P76;          TDEC R2
P75;       NZ;     P75;          INC R0, TDEC R1, INC R2
P76;       Z;      P81;          DEC T3
P76;       NZ;     P77;          READ T3
P77;       Z;      P78;          READ T2
P77;       NZ;     P78;          READ T2
P78;       Z;      P79;          RESET T2, RESET T3, INC T3
P78;       NZ;     P79;          RESET T2, SET T3, INC T3
P79;       Z;      P80;          INC T2
P79;       NZ;     P80;          INC T2
P80;       Z;      P76;          TDEC R2
P80;       NZ;     P76;          TDEC R2
P81;       Z;      P82;          DEC T2
P81;       NZ;     P81;          DEC T3
P82;       Z;      P83;          NOP
P82;       NZ;     P82;          DEC T2
P83;       Z;      P84;          TDEC R4
P83;       NZ;     P84;          TDEC R4
P84;       Z;      P85;          TDEC R1
P84;       NZ;     P84;          INC R1, TDEC R4
P85;       Z;      P86;          TDEC R5
P85;       NZ;     P85;          TDEC R1, INC R4, INC R5
P86;       Z;      P97;          NOP
P86;       NZ;     P87;          TDEC R0
P87;       Z;      P88;          TDEC R1
P87;       NZ;     P87;          TDEC R0, INC R1
P88;       Z;      P89;          TDEC R2
P88;       NZ;     P88;          INC R0, TDEC R1, INC R2
P89;       Z;      P95;          DEC T3
P89;       NZ;     P90;          READ T3
P90;       Z;      P91;          READ T2, RESET T3
P90;       NZ;     P91;          READ T2, SET T3, ADD A1
P91;       Z;      P92;          ADD B0
P91;       NZ;     P92;          ADD B1
P92;       Z;      P93;          RESET T2, INC T2
P92;       NZ;     P93;          SET T2, INC T2
P93;       Z;      P94;          INC T3
P93;       NZ;     P94;          INC T3
P94;       Z;      P89;          TDEC R2
P94;       NZ;     P89;          TDEC R2
P95;       Z;      P96;          DEC T2
P95;       NZ;     P95;          DEC T3
P96;       Z;      P86;          TDEC R5
P96;       NZ;     P96;          DEC T2
P97;       Z;      P98;          TDEC R3
P97;       NZ;     P98;          TDEC R3
P98;       Z;      P99;          TDEC R1
P98;       NZ;     P98;          INC R1, TDEC R3
P99;       Z;      P1;           NOP
P99;       NZ;     P99;          INC R0, TDEC R1, INC R3
Q1;        Z;      Q2;           TDEC R7
Q1;        NZ;     Q2;           TDEC R7
Q2;        Z;      Q3;           TDEC R1
Q2;        NZ;     Q2;           INC R1, TDEC R7
Q3;        Z;      Q4;           NOP
Q3;        NZ;     Q3;           TDEC R1, INC R7, INC R8
Q4;        Z;      Q5;           TDEC R0
Q4;        NZ;     Q5;           TDEC R0
Q5;        Z;      Q6;           TDEC R1
Q5;        NZ;     Q5;           TDEC R0, INC R1
Q6;        Z;      Q7;           TDEC R2
Q6;        NZ;     Q6;           INC R0, TDEC R1, INC R2
Q7;        Z;      Q12;          DEC T3
Q7;        NZ;     Q8;           READ T3
Q8;        Z;      Q9;           READ T0
Q8;        NZ;     Q9;           READ T0
Q9;        Z;      Q10;          RESET T0, RESET T3, INC T3
Q9;        NZ;     Q10;          SET T0, SET T3, INC T3
Q10;       Z;      Q11;          INC T0
Q10;       NZ;     Q11;          INC T0
Q11;       Z;      Q7;           TDEC R2
Q11;       NZ;     Q7;           TDEC R2
Q12;       Z;      Q13;          DEC T0
Q12;       NZ;     Q12;          DEC T3
Q13;       Z;      Q14;          NOP
Q13;       NZ;     Q13;          DEC T0
Q14;       Z;      Q15;          TDEC R0
Q14;       NZ;     Q15;          TDEC R0
Q15;       Z;      Q16;          TDEC R1
Q15;       NZ;     Q15;          TDEC R0, INC R1
Q16;       Z;      Q17;          TDEC R2
Q16;       NZ;     Q16;          INC R0, TDEC R1, INC R2
Q17;       Z;      Q23;          DEC T1
Q17;       NZ;     Q18;          READ T1
Q18;       Z;      Q19;          RESET T1, READ T3
Q18;       NZ;     Q19;          SET T1, READ T3, ADD A1
Q19;       Z;      Q20;          ADD B0
Q19;       NZ;     Q20;          ADD B1
Q20;       Z;      Q21;          RESET T3, INC T3
Q20;       NZ;     Q21;          SET T3, INC T3
Q21;       Z;      Q22;          INC T1
Q21;       NZ;     Q22;          INC T1
Q22;       Z;      Q17;          TDEC R2
Q22;       NZ;     Q17;          TDEC R2
Q23;       Z;      Q24;          DEC T3
Q23;       NZ;     Q23;          DEC T1
Q24;       Z;      Q25;          TDEC R6
Q24;       NZ;     Q24;          DEC T3
Q25;       Z;      Q26;          NOP
Q25;       NZ;     Q25;          TDEC R6
Q26;       Z;      Q27;          TDEC R0
Q26;       NZ;     Q27;          TDEC R0
Q27;       Z;      Q28;          TDEC R1
Q27;       NZ;     Q27;          TDEC R0, INC R1
Q28;       Z;      Q29;          TDEC R2
Q28;       NZ;     Q28;          INC R0, TDEC R1, INC R2
Q29;       Z;      Q32;          READ T3
Q29;       NZ;     Q30;          INC T3
Q30;       Z;      Q31;          INC T2
Q30;       NZ;     Q31;          INC T2
Q31;       Z;      Q29;          TDEC R2
Q31;       NZ;     Q29;          TDEC R2
Q32;       Z;      Q33;          READ T2, RESET T3
Q32;       NZ;     Q36;          READ T2, SET T3
Q33;       Z;      Q34;          RESET T2, DEC T2
Q33;       NZ;     Q37;          SET T2, DEC T3
Q34;       Z;      Q35;          DEC T3
Q34;       NZ;     Q35;          DEC T3
Q35;       Z;      Q40;          DEC T2
Q35;       NZ;     Q32;          READ T3
Q36;       Z;      Q39;          RESET T2, DEC T3
Q36;       NZ;     Q34;          SET T2, DEC T2
Q37;       Z;      Q38;          DEC T2
Q37;       NZ;     Q37;          DEC T3
Q38;       Z;      Q52;          TDEC R8
Q38;       NZ;     Q38;          DEC T2
Q39;       Z;      Q40;          DEC T2
Q39;       NZ;     Q39;          DEC T3
Q40;       Z;      Q41;          NOP
Q40;       NZ;     Q40;          DEC T2
Q41;       Z;      Q42;          TDEC R0
Q41;       NZ;     Q42;          TDEC R0
Q42;       Z;      Q43;          TDEC R1
Q42;       NZ;     Q42;          TDEC R0, INC R1
Q43;       Z;      Q44;          TDEC R2
Q43;       NZ;     Q43;          INC R0, TDEC R1, INC R2
Q44;       Z;      Q50;          DEC T3
Q44;       NZ;     Q45;          READ T3
Q45;       Z;      Q46;          READ T2
Q45;       NZ;     Q46;          READ T2, SUB A1
Q46;       Z;      Q47;          RESET T2, SUB B0
Q46;       NZ;     Q47;          SET T2, SUB B1
Q47;       Z;      Q48;          RESET T3, INC T3
Q47;       NZ;     Q48;          SET T3, INC T3
Q48;       Z;      Q49;          INC T2
Q48;       NZ;     Q49;          INC T2
Q49;       Z;      Q44;          TDEC R2
Q49;       NZ;     Q44;          TDEC R2
Q50;       Z;      Q51;          DEC T2
Q50;       NZ;     Q50;          DEC T3
Q51;       Z;      Q26;          NOP, INC R6
Q51;       NZ;     Q51;          DEC T2
Q52;       Z;      Q61;          NOP
Q52;       NZ;     Q53;          NOP
Q53;       Z;      Q54;          TDEC R0
Q53;       NZ;     Q54;          TDEC R0
Q54;       Z;      Q55;          TDEC R1
Q54;       NZ;     Q54;          TDEC R0, INC R1
Q55;       Z;      Q56;          TDEC R2
Q55;       NZ;     Q55;          INC R0, TDEC R1, INC R2
Q56;       Z;      Q60;          DEC T3
Q56;       NZ;     Q57;          READ T3
Q57;       Z;      Q58;          MUL 0
Q57;       NZ;     Q58;          MUL 1
Q58;       Z;      Q59;          RESET T3, INC T3
Q58;       NZ;     Q59;          SET T3, INC T3
Q59;       Z;      Q56;          TDEC R2
Q59;       NZ;     Q56;          TDEC R2
Q60;       Z;      Q25;          TDEC R6
Q60;       NZ;     Q60;          DEC T3
Q61;       Z;      Q62;          TDEC R6
Q61;       NZ;     Q62;          TDEC R6
Q62;       Z;      Q71;          NOP, OUTPUT 0
Q62;       NZ;     Q63;          TDEC R6
Q63;       Z;      Q71;          NOP, OUTPUT 1
Q63;       NZ;     Q64;          TDEC R6
Q64;       Z;      Q71;          NOP, OUTPUT 2
Q64;       NZ;     Q65;          TDEC R6
Q65;       Z;      Q71;          NOP, OUTPUT 3
Q65;       NZ;     Q66;          TDEC R6
Q66;       Z;      Q71;          NOP, OUTPUT 4
Q66;       NZ;     Q67;          TDEC R6
Q67;       Z;      Q71;          NOP, OUTPUT 5
Q67;       NZ;     Q68;          TDEC R6
Q68;       Z;      Q71;          NOP, OUTPUT 6
Q68;       NZ;     Q69;          TDEC R6
Q69;       Z;      Q71;          NOP, OUTPUT 7
Q69;       NZ;     Q70;          TDEC R6
Q70;       Z;      Q71;          NOP, OUTPUT 8
Q70;       NZ;     Q71;          NOP, OUTPUT 9
Q71;       Z;      Q72;          TDEC R7
Q71;       NZ;     Q72;          TDEC R7
Q72;       Z;      Q73;          NOP, OUTPUT .
Q72;       NZ;     Q73;          NOP, INC R7
Q73;       Z;      S12;          NOP, INC R7
Q73;       NZ;     S12;          NOP, INC R7

User avatar
simsim314
Posts: 1731
Joined: February 10th, 2014, 1:27 pm

Re: Reverse engineering the phi and pi calculators

Post by simsim314 » November 8th, 2019, 6:07 pm

I've analyzed all the operations again after all the bugs were fixed.

MUL:
It works up to 01010 (including) and not further.

MUL0 + (xyz):
z -> Z/NZ
xyz -> xy

MUL1 + (xyz):
z -> Z/NZ
xyz -> xy + 5

ADD:

A1 + (xyz) + b:
Z/NZ -> NONE
xyz = x(~y)z
b -> ~b

B1 + (xyz) + b:
b -> NZ/Z

(xyz) -> {0, 1} = (000 b0 | 100 b1)

0,1,3,5 -> 0
2,4,6,7 -> 1

B0 + (xyz) + b:
b -> Z/NZ

(xyz) -> {0, 1} = (000 b0 | 100 b1)

0,1,2,4 -> 0
3,5,6,7 -> 1

SUB

The second and third bits are irrelevant.

A1 + x + s + b (x - first bit, s = stopper, b = bit):

A1:
b -> ~b

xs->xs:
00->01
10->11

B1:
b->NZ/Z

xs->xsb:
00 -> 101
01 -> 000
10 -> 101
11 -> 101

B0:
b->Z/NZ
00 -> 000
01 -> 000
10 -> 101
11 -> 000
Last edited by simsim314 on November 8th, 2019, 10:17 pm, edited 2 times in total.

User avatar
simsim314
Posts: 1731
Joined: February 10th, 2014, 1:27 pm

Re: Reverse engineering the phi and pi calculators

Post by simsim314 » November 8th, 2019, 7:48 pm

I want to cover the computational model for broader audience.

These calculators are basically finite-state machines, where each line in a program corresponds to a state, and you have JUMP instructions for every state. Each line can trigger one or more actions -- INC R0, TDEC R2, NOP, etc. -- and you have to make sure that you execute exactly one reaction that returns a zero/nonzero value.

Thus the calculator has:

0. Clock.
1. Programming code.
2. Computational unit array.
3. Printer.

Clock: the computational cycle

- Each 2^20 generations, a glider gun is initiating an action based on output from previous cycle (it waits until output has returned).
- The new action could be either Z or NZ.
- Each cycle is expected to return either Z or NZ.

Programming code.

- Each line of code consists of 4 parts:
Name; Z/NZ; NextLine; OP1, OP2, OP3 etc.

Name Each line has a tag name.
Z/NZ Each line has a policy of operations depending on returning Z or NZ from the previous cycle.
NextLine Each line + Z/NZ defines the next execution line.
Opi Each line + Z/NZ defines a list of operations to be executed. The operations are inputs to the computational units. Some operations will not return anything and only change the state of the unit and some will return either Z or NZ depending on the internal state and the logic of some particular unit. It's programmer task to make sure there is exactly one return value.

Example

Code: Select all

INITIAL; Z; A2; NOP
A1; Z; A2; INC T0
A1; NZ; A2; INC T0
A2; Z; A1; READ T0, SET T0
A2; NZ; A1; READ T0, SET T0"
Computational units

We have 5 types of units, each type has several instruction commands.

1. Sliding block register.
2. Binary string register.
3. ADD
4. SUB
5. MUL

The calculator can have arbitrary number of 1 and 2 units and a single 3,4,5 units.

Sliding block

- Sliding block in the code is always starting from R. For example R0, R1, R2 etc.
- Sliding block has very simple logic. They represent a single number, and all you can do with them is INC (increase by 1) and TDEC (decrease by 1).

Operations:

- INC Rx will just increase the register by 1. Will not return anything.
- TDEC Rx will decrease the register by 1. Will return NZ if the register > 0 and Z otherwise.

Binary string or T registers

- The binary string registers are starting with T. For example T0, T1, ..T14 in APGsembly.
- They have a "reading head". It can be moved with INC and DEC just like sliding block.
- They can store arbitrarily-large binary strings. A program can only retrieve one bit at a time using READ command, followed by SET, RESET that can be called "WRITE 1" and "WRITE 0".

Operations:

- INC Tx increase the position of reading head. Returns Z unless the space is empty then it returns NZ.
- DEC Tx decrease the position of reading head. Returns NZ unless at 0.
- READ return the state of the binary string value located at reading head. Returns Z if the value is 0 and NZ if 1.
- SET sets the state of the binary string to 1. Must be after READ operation which deletes the state.
- RESET setse state of the binary string to 0. Must be after READ operation which deletes the state.

ADD

One should think about the adder as having two bits A and B. Each of them has 0 or 1 option, and each of the options is an input to the adder. A input is just changing the state of the Adder unit, and B input returns the result.

- A0 is ignored case because there is nothing to change.
- A1 is a valid input
- B0, B1 should come after A was initialized.
- The adder returns (Ax + By + Memory) % 2
- The adder stores Memory = (Ax + By + Prev Memory >= 2)
- The memory bit is always stored in the unit when existent.
- If you not sure about the state of the adder just send B0 and you can be sure the Memory is cleaned.

ADD, SUB, MUL

Each of them has special inputs. You can see the analysis of the operations in the previous message.

Printer

The printer can print "." and digits 0-9.

The command is
OUTPUT x, NOP

The NOP operation is sending Z output directly.

Summary

You can see the discussions and examples in this thread to verify you can get the APGsembly code. dvgrn recently made an emulator and posted several examples and calcyman made a code that computes the digits of pi and phi using it.

User avatar
simsim314
Posts: 1731
Joined: February 10th, 2014, 1:27 pm

Re: Reverse engineering the phi and pi calculators

Post by simsim314 » November 8th, 2019, 11:36 pm

More APGsembly examples:

Binary adder in binary format print:

Code: Select all

APGsembly = """INITIAL; Z; AD; READ T0
AD; Z; D; SET T0, DEC T0
AD; NZ; AD1; RESET T0, INC T0
AD1; Z; AD2; READ T0, INC R0, NOP
AD2; Z; D; SET T0, DEC T0
AD1; NZ; AD; READ T0
D; NZ; D; DEC T0
D; Z; PRStart; TDEC R0
PRStart; Z; PR; READ T0
PRStart; NZ; PRStart1; TDEC R0
PRStart1; Z; PR; READ T0
PRStart1; NZ; PRStart; INC T0
PR; Z; PR1; OUTPUT 0, RESET T0, INC R0, DEC T0
PR; NZ; PR1; OUTPUT 1, SET T0, INC R0, DEC T0
PR1; NZ; PR; READ T0
PR1; Z; AD; OUTPUT ., READ T0"""

progname = "Inf"
registers = {"R0":1, "T0":[0, '0']}
Add two registers T0 and T1 and print the result:

Code: Select all

"""INITIAL; Z; T0R2; READ T0
T0R1; Z; T0R2; READ T0
T0R1; NZ; T0R2; READ T0
T0R2; Z; T1R1; RESET T0, INC T0
T0R2; NZ; T1R1; ADD A1, SET T0, INC T0
T1R1; NZ; T1R2; READ T1
T1R1; Z; T1R3; READ T1
T1R2; Z; T1R4; RESET T1, ADD B0
T1R2; NZ; T1R4; SET T1, ADD B1
T1R4; Z; T0R1; OUTPUT 0, INC T1 
T1R4; NZ; T0R1; OUTPUT 1, INC T1 
T1R3; Z; T1R5; RESET T1, ADD B0
T1R3; NZ; T1R5; SET T1, ADD B1
T1R5; Z; T1R6; OUTPUT 0, INC T1 
T1R5; NZ; T1R6; OUTPUT 1, INC T1 
T1R6; Z; T1R7; ADD B0
T1R7; Z; T1R8; OUTPUT 0, HALT
T1R7; NZ; T1R8; OUTPUT 1, HALT
T1R6; NZ; T0R2; READ T0"""

progname = "Inf"
registers = {"T0":[0, '1111111'], "T1":[0, '111']}
EDIT A simple design pattern to implement libraries. Assuming I've a function for example sin(x) which is called from several places. I want the computation go to part of the code that computes sin(x) and then return to the part from which sin(x) was called. We would have a "root" line and address scheme. Each function is returning to the root - for example we set T0 to be equal x and call sin(x), it places sin(x) into T0 and returns to the root line. The root is then using an address list, for example using T1 we can decide to which line of code we want to return. Before any function is calling sin(x) it registers the return line after the execution inside T1 logic. A binary tree defining line of code is then edited s.t. we know to compute the relevant line from T1 state.

For example I want to call sinX line and return to A, B, C, D lines after execution of the sinX logic. It will look like so in APGsembly:

Code: Select all

... inside A function assuming T1 is at 0 and T0 is initialized
---- Set T1 address to 00 ------ 

SETA; Z/NZ; SETA1; READ T1, RESET T1
SETA1; Z/NZ; SETA2; INC T1
SETA2; NZ; sinxStart; READ T1, RESET T1 //Calling the sinx function 

A; Z; .... //returning here through the ROOT

sinxE; Z/NZ; ROOT; READ T1
ROOT; Z; x; RESET T1, INC T1
ROOT; NZ; y; SET T1, INC T1
x; NZ; x1; READ T1
y; NZ; y1; READ T1
x1; Z; A; RESET T1 //A = 00
x1; NZ; B; SET T1  //B = 01 
y1; Z; C; RESET T1  //C = 10
y1; NZ; D; SET T1  //D = 11
In the example above the root is hardcoded. We can make somewhat automated address management. The user can only call:
- Register A to ROOT.
- SET T1 to return to A

And the compiler will know to add the lines of code that make the whole loop through the root back to where we started. I think all compilers are doing it anyway, but the don't use address tree only a direct pointer to function execution line. In APGsembly the tree looks like more native approach, at least until we will have some sort of LUTs as integrated part of the units. Then we will just register our line into the LUT.

User avatar
simsim314
Posts: 1731
Joined: February 10th, 2014, 1:27 pm

Re: Reverse engineering the phi and pi calculators

Post by simsim314 » November 9th, 2019, 2:00 am

Self replication design based on the calculator:

We need only three units:

1. T0
2. BUILD. It has 3 commands:
INIT - place the block in correct (x, y) + Build initial reading head.
BUILD0 - builds Boat0 as in T0 tape and moves the construction block
BUILD1 - builds Boat1 as in T0 tape and moves the construction block
3. ARM. Construction arm - or a block connected to logic. It has two channels: A, B which allow to code 4 operations:
AA - push
AB - pull
BA - shoot white
BB - shoot black
Every pair of commands to the ARM is coding an operation on the construction block.

Then we will use the following code (assuming the reading head is at the end of T0):

Code: Select all

INITIAL; Z; A1; BUILD INIT, NOP
A1; Z; A2; READ T0
A1; NZ; A2; READ T0
A2; Z; A3; RESET T0, BUILD0, DEC T0
A2; NZ; A3; SET T0, BUILD1, DEC T0
A3; Z; Construct; READ T0
A3; NZ; A1; NOP
Construct; Z; Construct1; ARM A, RESET T0
Construct; NZ; Construct1; ARM B, SET T0
Construct1; Z; Construct2; INC T0
Construct1; NZ; Construct2; INC T0
Construct2; Z; Construct; READ T0
Construct2; NZ; EMPTY; HALT
Inside the T0 tape we code all slow salvo construction of the calculator except the tape. Then the code is built of two parts:
Ax - copy the tape using BUILD unit.
Constructx - use the ARM command coded in the tape to make a copy of the unit itself.

I'm guessing the iteration with modern tek should be measured in trillions (think original Gemini (30M) + single construction arm which takes x 100 (3B) + each command is million iteration instead of 1000 (3*T)). I guess just like the pi calculator itself it's possible to execute in golly.

Post Reply