# EXAPUNKS

## byCarbon dioxide

### Part 9: Point of Sale System

Part 9 - Point of Sale System

=== Trash World Inbox ===

First of all, there was some discussion in the thread about overflow and clamping, and how clamping is rare in real computers. That's certainly true, and it's a direct result of how binary counting works. Without going into a complete electronics lesson: in the end a binary number in a CPU register is just represented as a bunch of electrical parts that have a voltage on them (1) or not (0). If you add two numbers together, it uses logic gates in such a way that 0 + 0 = 0; and 0 + 1 = 1.
1 + 1 = 0 too, but in that case you tell the next bit over to add a carry bit. Imagine if all the bits are 1 (e.g. 1111 1111), and you add 1 to it. The rightmost bit will become zero and tell the second bit to carry. 1 + carry = 0, and it tells the next one over to carry. At some point you have 0000 0000 with the most significant bit telling the next one over to carry - but there's no next one so that carry bit just disappears into the void and your answer becomes 0.
Overflow is a natural result of circuit design, and to make clamping possible would require circuits to be much more complex.

ColTim posted about some advanced instructions where clamping happens, but that's complex vector and matrix calculations so there you're way beyond basic addition circuits anyway.

#### GuavaMoment posted:

Unroll the loops! Instead of FJUMPing to the start of the loop you're going to have to TJUMP to an end condition (which is SEEK -1, VOID F). This will get you 27 cycles.

You can save one more cycle by not having the line COPY M X and testing over M every time. One exa grabs file 300 and constantly sends PEANUTS over M. But how does that exa know when to stop? It doesn't. You have a third exa wait exactly 21 cycles and KILL your transmitting exa. Five cycles later you complete the level, worst case scenario. 26/45/3
The first suggestion was trickier than I thought. Just unrolling the loop doesn't work, because an untriggered TJMP takes a cycle, just like a triggered one does. The only way to save a cycle is to also make sure you don't even execute the jump instruction in the worst case scenario. I did it by changing XB to this:
##### code:
``````LINK 800
GRAB 237
COPY M X

@REP 10
TEST F = X
TJMP END
@END

VOID F
HALT

MARK END
SEEK -1
VOID F
``````
Repeat the test exactly 10 times. If it falls through all of that you know you're in the worst-case test and you can just immediately delete the value at the file pointer and halt the EXA. 27 cycles.

For the second half:

##### code:
``````; XA:
GRAB 300
COPY F X

@REP 10
COPY X M
@END

; XB
GRAB 237

@REP 10
TEST F = M
TJMP END
@END

VOID F
HALT

MARK END
SEEK -1
VOID F

;XC
MARK LOOP
TEST X = 7
FJMP LOOP

KILL
``````
As you say, 26 cycles. The tricky thing here is making sensible choices to stay under the size limit. It is important to unroll the loop in XA. That way the slowest EXA in the communication will be XB, which has to run an extra TJMP for each cycle. Having a loop in XA would slow both of them down. This means you do not have enough lines left to do any loop unrolling in XC - but that's perfectly fine because XC's only purpose is waiting a set number of cycles. In my solution, each loop in XC takes 3 cycles, so counting up to 7 is perfect. If I had needed some number of cycles not divisible by 7 I would just have slapped some extra NOOPs at the end.

Note that both of these solutions require timing the worst case test precisely. Or, trial and error. Just putting different numbers in the @REP and the XC loop and find the lowest numbers that still work.

=== Zebros Copies - Point Of Sale System ===

Processing.
No peanuts in Peanut Blast. Was that funny?

Three votes for "I don't get it" and one for "Kind of".

I don't get it, no.

You have to imagine someone wanting peanuts really bad, and not getting them.
Or is that just torture?
More data for the corpus.
Let's continue.

I'm not sure if I like all that data collection.

You're gonna help Ghast with his copy shop bill?
That's kind of you.

One vote for "He's an old friend", and three for "I help people when I can."

I help people when I can...

Is that altruism? I've heard of that.
This is the first time I've seen it in the wild.
I'm going to have to add a new table to my database.

How old are you anyway? Or is that a rude question to ask an AI?

Our assignment this time is to clear Ghast's tab.

OST: Network Exploration

The assignment:
- Erase Ghast's debt to the copy shop by zeroing out his balance in the customer database (file 200) and appending a payment to the payment log (file 201) with today's date and the exact amount of his prior balance.
- Ghast's customer ID is available in file 300.
- For more information see "Network Exploration: Digicash Point-of-Sale Systems" in the first issue of the zine.

Oh, the zine has a page on this? Let's see.

Alright, so if I understand correctly, you're in trouble if your operating system is a Point of Sale.

Before I dive into the assignment, let's mess around a bit first.

Move a bunch of EXAs into the COPY hosts and have them write 999 to the #COPY hardware register constantly, hehehe.

The value is capped at 99, and if you pause your EXAs you see it slowly decrement while the copiers in the view of the camera are constantly printing. The EXAs constantly push it back up to 99. If you let this run for a while you get the TONER_LOW Steam achievement.

Looking at the assignment, it definitely feels like the training wheels are coming off now. Before we start it's a good idea to think of a general approach.

I need to do several things here. First, the line in file 200 that matches Ghast's customer ID in 300 should get a pair of 0's.
Secondly, I need to add a line to file 201 containing the current date, Ghast's ID, and then the amount that used to be in file 200. So I need to keep track of that too.
I can get the current date from the #DATE hardware register. Perhaps it also works to copy from the last line in file 201, but I'm not sure if that works for all tests. Worth a try in the optimizations, but let's start simple.

I'll try to take you along with my train of thought when working on a programming assignment such as this.

This deals with file 200. XA grabs the file containing Ghast's ID and sends it over M. Meanwhile XB immediately links to 800, wasting no time with grabbing files in my home host.
The FINDLOOP has a SEEK 2 since it only needs to test every third value in the file. In the most naive approach, you would test, then do a conditional jump, and then only move forward in the file if you're not there yet. But since you can't just put the SEEK 2 at the start (because then it would skip the first value in the file), I can't think of a way to do that without 2 conditional jumps per loop. That would be at least one cycle PER LOOP extra. Instead I just put a single SEEK -2 beyond the loop which is always one cycle extra, regardless of how often the loop runs. Keeping loops short is key for a low cycle count.

After that, I first store the current amount in X and T, and then SEEK back once more to write 0s to the file. That's file 200 done, although I still have to do something with the current amount.

There's different ways I could handle appending the log. I could have XB do that after it's done with 200. I could spawn a fresh EXA, have it link to 800, grab 201, and do stuff with it. Or I could use REPL commands in XB.

Having XB handle everything feels slow, since it can only grab the new file after it's done with the old. That, or REPL, would be a good way to get a low activity score though, since you have less EXAs to LINK from the home host. However, a REPL costs a cycle for XB, during which it could be doing something useful.
For low cycle count, using an additional EXA sounds best.

I decided to start with the additional EXA, and try the REPL solution later for a better activity score.

XB has been changed, and I added XC. Let's look at the latter first.
XC starts by waiting a cycle. Since it'll have to wait for data from XB, we need to make sure XB can get to work as fast as possible. Once it's in the network, it first makes a DATEGETTER which does nothing but jump to the CLOCK host and send the current date to M.

The base XC GRABs file 201, goes to its end, and writes the first value from M in there.
It's important to get the DATEGETTER going right away. This way, it posts its message to M, even before XB is through its very first loop. This ensures that no matter what else comes on M, the date will always be first.

As for XB, it no longer stores the old amount to X and T, but sends them to M instead. Before it does so, though, it also sends its value in X (Ghast's ID) to M, so that XC can use that for the payment log.

And with that, I'm already very close to a working solution.

Since I took care of sending the different values to M in the right order, all that was left was adding some additional COPY instructions to XC.

The 'fixed' files.

The first result is not bad at all. The cycles are right there among the lowest peak on the histogram.

As for lowering them, I tried unrolling the loop but I didn't find an immediate benefit. You still have to do those conditional jump checks every time.

I did manage to lower it to 58 with this solution:
##### code:
``````;XA
GRAB 300
COPY F M
SEEK -1
COPY F M

;XB

COPY M X
GRAB 200

MARK FINDLOOP
TEST X = F
SEEK 2
FJMP FINDLOOP

SEEK -2
COPY F M
COPY F M

SEEK -2
COPY 0 F
COPY 0 F

;XC
NOOP
REPL DATEGETTER
COPY M X
GRAB 201
SEEK 9999
COPY M F
COPY X F
COPY M F
COPY M F

HALT

MARK DATEGETTER
COPY #DATE M
``````
Now XA sends Ghast's ID twice. Once XC gets its copy, it temporarily stores it in X, then waits for the date, copies that and the ID to the log file, and then only has to wait for the amount from XB, meaning it can handle more steps before XB is done. 58 cycles.

We already know we can improve Activity with some REPLs:

##### code:
``````;XA
GRAB 300
COPY F M
SEEK -1
COPY F M

;XB
REPL LOGAPPENDER

COPY M X
GRAB 200

MARK FINDLOOP
TEST X = F
SEEK 2
FJMP FINDLOOP

SEEK -2
COPY F M
COPY F M

SEEK -2
COPY 0 F
COPY 0 F

HALT

MARK LOGAPPENDER
REPL DATEGETTER
COPY M X
GRAB 201
SEEK 9999
COPY M F
COPY X F
COPY M F
COPY M F

HALT

MARK DATEGETTER
COPY #DATE M
``````
Exactly the same as before, except the LOGAPPENDER is now created by XB, removing the need for it to LINK. Result: 58/32/2

A 1-activity solution would be possible only if we could grab the last date from the log file and reuse that. However, the devs thought of that and have a test where the oldest log line isn't from today, so that won't work.

Finally, it looks a decent improvement possible in the size is possible. I'd love to see what the thread comes up with.

Is that copy shop name unusually weird to you?
It's an outlier in my model.
What is "Zebros" supposed to be?

Here is the first vote for this update.

[x10x10x]: eh
[x10x10x]: not worth it

Just in case you hadn't realized, we're not hacking simulations anymore. My hacks have real world consequences, even if it feels everything happens in this little box in my room.

*Knock knock*

OST: Apartment

What's this now?

This voice...
I remember the name but not much else...
Isn't this someone I've known for a long time?

Isadora is voiced by Krizia Bajos.

Hey. I brought you some snacks.
It's, um, well it's Peanut Blast, but without the peanuts.
I guess there was some screw-up at the factory, so now we have a bunch of these that we can't sell.
Seemed like a waste to throw away.

Isadora hands me a few of the non-peanut-containing Peanut Blast candy bars.

I hope you're doing okay.
We should hang out again sometime.
I don't have a lot of free time anymore, though.
Working at Last Stop's really taken over my life.
Speaking of which- I should get back.
Take care, okay?

Um. Thanks, I think.

And with that, let's see the intro for the next assignment.

Would you change your behavior in response to stimuli?
Of course you would. Let me refine.
Would slogans printed on signs and posters in your environment affect your outlook on the world?

And that's the second vote.