Difference between revisions of "ChemiCompiler"

From Space Station 13 Wiki
Jump to navigation Jump to search
(First draft)
 
(→‎Commands: Added the previously-undocumented "*" NOP operation.)
 
(34 intermediate revisions by 14 users not shown)
Line 1: Line 1:
''"A complicated chemistry device, which uses a programming language derived from Brainfuck. It features 5 registers, 1024 bytes of RAM and 10 reagent reservoirs - to add beakers, click on the r[number] slots. It also has a pill generator, a vial generator and an ejection port. "''
<center>
{| border="2" cellpadding=5


{{Wip}}
</center>


Piff paff. Complicated? I think not.
''"A complicated chemistry device, which uses a programming language derived from Brainfuck. It features 5 registers, 1024 bytes of RAM and 10 reagent reservoirs - to add beakers, click on the r[number] slots with a beaker in-hand.  The machine can also generate pills or generate vials or trash the contents from beakers. "''
== Guide to Making Chemcompiler Programs/Reactions ==
 
Piff paff. Complicated? I think not. [[Scientist|Scientists]] worth their salt can figure this out. Eventually.
 
If you have an aneurysm while trying to understand this thing, you can use [https://112358sam.github.io/ChemiAssembler/ this tool] to make the code for you while using more human readable instructions.
 
Note that everything in this guide applies also applies to its [[Syndicate Items#ChemiCompiler|portable version]]. However, keep in mind it only has 6 reagent reservoirs.
 
== The Interface ==
The interface is broken up into a bunch of rows. The list numbering relates to the image.
[[File:ChemiCompiler_Interface_Labeled.png|right|The ChemiCompiler window.]]
# The code area. This is where you can paste in codes to save into the machine, or copy them out of the machine. It can accept very very long text strings.
# The load and save buttons. You need to save your code into the machine before you can run it. Once some code is in area-1, press the save button, then press a button in area-3 to save it to that slot. Pressing load, and then a button from area-3 will instead overwrite area-1 with the stored code.
# Code slots. The machine can store 6 codes, one per slot. These buttons turn green when they hold code. Pressing a button will begin the execution of the code stored in that slot, locking all further interactions with the machine until it completes.
# Reservoirs 1 thru 5. Beaker slots. These buttons turn blue when they hold a beaker. To insert a beaker, hold a beaker in-hand and press a button. Likewise, with an empty-hand, press a button to retrieve a beaker.
# Reservoirs 6 thru 10. More beaker slots.
# Register read-outs. Useful for debugging. Shows the value of the sx, tx, and ax registers at the time of completion. Only updates at the time of completion, does not update mid-execution.
Do not let the nice buttons and chui fool you, the interface beguiles the complexity within.
 
== Signals ==
During normal operation, the chemicompiler emits a number of text-log cues to provide you feedback. These are as follows:
* ChemiCompiler CCS1000 beeps quietly 2 times.
Beginning of a program.
* ChemiCompiler CCS1000 beeps loudly once.
An operation has failed, probably due to a missing beaker in either sx or tx.
* ChemiCompiler CCS1000 emits a slight humming sound.
Transfer step in a program
* ChemiCompiler CCS1000 clicks.
Heating step in a program, once each for the beginning and end.
* ChemiCompiler CCS1000 beeps quietly once.
The program has finished running and the machine is idle.
 
 
The sprite will animate while the machine is running, and it will also provide the normal chemical reaction messages if they occur.
== Introduction to ChemFuck ==
Much like how modern programs run by executing one line of a program at a time, the ChemiCompiler works by executing one character from a string at a time. These strings of characters are referred to as "codes". An example code with 6 characters (6 commands) is "+}+)'@". The commands and the internal operations of the machine are based on the [https://en.wikipedia.org/wiki/Brainfuck Brainfuck programming language]. Thus the portmanteau ChemFuck. Our ChemFuck has more commands than it's predecessor, so it's marginally more "useful".
 
Everything in Brainfuck is about manipulating the Pointer. Think about the Pointer like a cursor selecting a cell on a super-wide single-row spreadsheet. The cursor can be moved left or right, one cell at a time. It's always selecting a cell and it begins at the very first one available at the far left. The memory is 0-indexed, so our first cell is named 00x. The subsequent cell is named 01x, and so on, following a [https://en.wikipedia.org/wiki/Hexadecimal#Written_representation hexadecimal] naming scheme until the 256th cell, FFx.
  v
00x000 01x000 02x000 03x000 ... FFx000
In the representation above, the first two numbers are the Reference (the name). The last three, after the x, are the Value. We can do two primary things with the pointer - we can shift the pointer left (<) or right (>). We can add 1 to the value (+) or subtract 1 (-).
 
Say we wanted the numbers 1 through 10 stored in memory. This would be the program to write it
+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++
Stepping through, it first adds 1 to the first reference (the pointer always starts 00x)
+
  v
00x001 01x000 02x000 03x000 04x000 05x000 06x000 07x000 08x000 09x000
Then it moves the pointer over 1 (>)
+>
  ------>v
00x001 01x000 02x000 03x000 04x000 05x000 06x000 07x000 08x000 09x000
Then it adds 1 to that reference twice
+>++
          v
00x001 01x002 02x000 03x000 04x000 05x000 06x000 07x000 08x000 09x000
And so forth, ending on reference 09x incrementing its value to 10
+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++
                                                                  v
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010
Because there is no multiplication or direct entry of numbers in Brainfuck, it's helpful to copy/paste +/- signs in known quantities if you need to reach larger numbers. And yes, chemfuck programs really are just long strings of symbols.
 
== Commands ==
 
Registers:
* ptr = data pointer (16-bit) (Data is 0-indexed.)
* iptr = instruction pointer (16-bit) (1-indexed.)
* sx = source register (8-bit) (Valid sources are 1-10 for the 1 through 10 reagent reservoirs.)
* tx = target register (16-bit) (Valid targets are reservoirs as above, or 11 for pill generator, 12 for vial generator, or 13 for ejection port.)
* ax = amount register (16-bit)
 
Basic pointer manipulation and arithmetic
* > Increment the pointer's reference
* < Decrement the pointer's reference
* + Increment the value of the reference under the pointer
* - Decrement the value of the reference under the pointer
 
While loops
 
Loops respect nesting.
* [ Start of a While loop. If the value at the pointer is 0, it will skip to the close (]) of the loop.
* ] Checks if the value at the pointer is 0. If false: looks backwards through the instructions until the matching [ is found, and resumes at that bracket. If true, continues execution past the ].
Of note: The ChemiCompiler will automatically halt after thousands of instructions if caught in an infinite loop, which can take a few minutes. However, it will hang indefinitely if there is a ] without a preceding [.
 
Register operations:
* } Copies the value from the pointer to the Source register (sx).
* { Copies the value from the Source register to the pointer. It's just backwards!
* ) Same as }, but for the Target register. The Target register (tx) is used for setting both where a chemical will go if it's moved during the current step of the program, and for cooling.
* ( Same as {, but for the Target register.
* ' Same as ) or }, but for the Amount register. Amount (ax) is used for both the amount of chemicals to be moved, and for heating.
* ^ Same as ( or {, but for Amount.
You get the idea, hopefully. There's two for each of these. If the chemcompiler throws out a string of loud beeps the first time you load a program into it, you've probably gotten these backwards.
 
Input operation:
* , Measure the amount of reagent in reservoir sx and stores the value in the register (ax).
 
Other operations:
* $ Heat or cool reagent in sx to ((273 - tx) + ax) Kelvin. Heating takes as long as the chemistry lab heater would take.
* @ Transfer ax units of reagent from reservoir sx to resevoir tx.
* # Isolates ax units of reagent number *ptr from reservoir sx to reservoir tx. Indexing begins at 1.
* . Output an ASCII character to the buffer based on *ptr.
* ~ "Compile" the code, so it cannot be retrieved again via the load button. This does not prevent over-writing!
* * "NOP" No Operation, this will cause the machine to do nothing for a moment. Useful for reactions that have a time component.
 
== Guide to Understanding the Internal Operations of the ChemiCompiler ==
Commands got you confused? This pointer / memory stuff not getting across? What's this added detail about copying to the sx, tx, and ax registers?
 
A graphical guide that focuses on 4 examples is available for viewing and download [https://onedrive.live.com/embed?cid=DE65DE37FA783FE9&resid=DE65DE37FA783FE9%21232797&authkey=ADsaYHCUmNb5sck&em=2&wdAr=1.7777777777777776 here].
 
Each example steps through the code one command at a time, highlighting the relation between the commands, pointer, memory, registers, and beakers.
The examples are roughly ordered to scale in complexity:
# Moving fluid from one beaker to another.
# Cooling a beaker.
# Using loops to heat multiple beakers
# Non-destructively isolating reagents from a beaker, and outputting a pill.
 
The focus of the guide is to help you understand how the ChemiCompiler works. It does not aim to teach how best to make a ChemFuck program. Read on for a method for making a program.
== Guide to Making Chemcompiler Programs ==


The Chemcompiler seems arcane, and almost useless at first glance. But imagine a cocktail like this:
The Chemcompiler seems arcane, and almost useless at first glance. But imagine a cocktail like this:
Line 12: Line 131:
  12 Fluorosurfactant
  12 Fluorosurfactant
  3 Plasma
  3 Plasma
It's a bomb, it's a face-eater, it's a fireball. It's everything, and it will kill you dead in seconds with a drop - I know, I've tested it on myself after testing it on monkeys. I dunno, or maybe it sucks, but I like it :<
It's a bomb, it's a face-eater, it's a fireball, and the ChemiCompiler can make it.


Using the chemcompiler, I will show you how to systematically create the beginnings of this mixture (or blow you to hell, if you didn't load the beakers right), and hopefully give you some idea what the hell it's about. If you use this guide, a fair payment would be giving me all your programs/plans so that I can murder myself more effectively.
This guide will show you how to systematically create the beginnings of this mixture. The goal is to make 75u of fluorosulfuric acid.


== Initial steps and planning ==
=== Initial steps and planning ===


In order to make a coherent ChemCompiler program, you first need to have a plan for every step of your reaction. A lot can go wrong. But if you follow things through systematically, you might be ok.
In order to make a coherent ChemiCompiler program, you first need to have a plan for every step of your reaction. A lot can go wrong. But if you follow things through systematically, you might be ok.
The plan is as important as the program. Do not neglect your plan. After forming  a plan, we will code alongside it - it will be our comments and our test data every step of the way.


''''''&Tau;&Eta;&Epsilon; &Rho;&lfloor;&Delta;&Nu; &brvbar;&sigmaf; &Alpha;&sect; &Iota;&Mu;&Rho;&Omega;&real;&Theta;&Alpha;&Nu;&Theta; &Alpha;&sigmaf; &perp;&Eta;&exist; &piv;&real;&oelig;&image;&reg;&alpha;&Mu;&Mu;&igrave;&ntilde;&thetasym;&there4;'''''', though neither is as important as wasting time on the internet. Do not neglect your plan. We will actually code alongside it - it will be our comments and our test data every step of the way.
To make fluorosulphuric acid we need sulfuric acid, fluorine, hydrogen, and potassium in equal quantities in a beaker. Then the beaker needs to be heated up to 374 degrees. Sulfuric acid needs sulfur, oxygen, and hydrogen. Obviously we need to make the sulfuric acid first.  


Let's do something simple first: Sulfuric acid into Fluorosulphuric Acid. It's sulfuric acid, fluorine, hydrogen, and potassium in equal quantities. It also needs to be heated up to 374 degrees. Sulfuric needs sulfur, oxygen, and hydrogen. Obviously we need to make that first. Also, when working with the chemcompiler, you need to respect the amount available to you in each beaker as well as (and this is my approach, not necessarily the best one) the amount of room left in the final output beaker. So we document all of that to ensure a clean reaction and help with testing later.
When working with the ChemiCompiler, you need to take care of the capacity and current volume of each beaker. It's helpful to note both as you plan and program. So we document all of that to ensure a clean reaction and help with testing later.


I start it out looking like like this:
I start it out looking like like this:
Line 31: Line 151:
  Potassium 50/50
  Potassium 50/50
  Mixdown 0/100
  Mixdown 0/100
Note that I marked what is used twice in the reaction - you should do this so that you know, later, which ones are best to double up a beaker with, because you only have 10 slots, and for complicated reaction chains you run dry fast.
Note that Hydrogen is marked twice since it is used twice in the reaction - you should do this so that you know, later, which ones are best to double up a beaker with, because you only have 10 slots. Complicated reaction chains can run dry fast.


Let's say we want that final mixdown beaker to be full of fluorosulphuric acid in the end. We know that we need four components to make it, so we'll need 1/4 of it full of sulfuric. But sulfuric has 3 components! We'd end up needed 8.33 repeating of sulfur, oxygen, and hydrogen. No good. What we can do instead is make more than what we need, and put it into a buffer mix. That's not a great solution for more complex reactions, but it's worth remembering as a fix, because residual chemicals suck. The buffer can be emptied at any time in the ChemCompiler using a few simple operations.
The goal is for the final mixdown beaker to be 3/4s full of fluorosulphuric acid (75u). We know that we need four components to make it, so we'll need 25u of sulfuric acid. But sulfuric acid has 3 components! We'd end up needed 12.5 of sulfur, oxygen, and hydrogen. No good, we need whole integers (or a much more complex program). What we can do instead is make more than what we need, and put it into a buffer mix. That's not a great solution for more complex reactions, but it's worth remembering as a fix, because residual chemicals suck. The buffer can be emptied at any time in the ChemCompiler using a few simple operations but that won't be covered in this example.


=== Sulfuric ===
==== Sulfuric ====


Our new setup looks like this
Adding the buffer beaker, the setup looks like this
  Sulfur 50/50
  Sulfur 50/50
  Oxygen 50/50
  Oxygen 50/50
Line 46: Line 166:
  Mixdown 0/100
  Mixdown 0/100
So now we know we need:
So now we know we need:
  9 sulfur
  Move
  9 oxygen
13 sulfur, and
  9 hydrogen
  13 oxygen, and
  Into buffer
  13 hydrogen
  works out to 27, so 25 into mixdown
  into buffer.
  Will produce 26u of sulfuric acid, so  
Move 25u from the buffer into mixdown
We want to keep track of these changes, because running out of something is potentially ''dangerous''
We want to keep track of these changes, because running out of something is potentially ''dangerous''
  Sulfur 41/50
  Sulfur 37/50
  Oxygen 41/50
  Oxygen 37/50
  Hydrogen 41/50 (2x)
  Hydrogen 37/50 (2x)
  Fluorine 50/50
  Fluorine 50/50
  Potassium 50/50
  Potassium 50/50
  Buffer 2/50 (sulfuric acid)
  Buffer 1/50 (sulfuric acid)
  Mixdown 25/100 (sulfuric acid)
  Mixdown 25/100 (sulfuric acid)
=== Into fluorosulfuric ===
 
Now we move on to the final mix. We already have the sulfuric acid ready, so we need
==== Into fluorosulfuric ====
  25 fluorine
Now to produce the final mix. We already have the sulfuric acid ready, so we need to
  25 hydrogen
Move
  25 fluorine, and
  25 hydrogen, and
  25 potassium
  25 potassium
 
into mixdown
  Sulfur 41/50
 
  Oxygen 41/50
  Sulfur 37/50
  Hydrogen 16/50 (2x)
  Oxygen 37/50
  Hydrogen 12/50 (2x)
  Fluorine 25/50
  Fluorine 25/50
  Potassium 25/50
  Potassium 25/50
  Buffer 2/50 (sulfuric acid)
  Buffer 1/50 (sulfuric acid)
  Mixdown 100/100 (25 sulfuric acid, 25 fluorine, 25 hydrogen, 25 potassium)</code>
  Mixdown 100/100 (25 sulfuric acid, 25 fluorine, 25 hydrogen, 25 potassium)
Now we need to document the heating needed to change the precursors into our final form.
Lastly, document the heating needed to change the precursors into the final form.
  Heat Mixdown to 374
  Heat Mixdown to 374K
   
   
  Sulfur 41/50
  Sulfur 37/50
  Oxygen 41/50
  Oxygen 37/50
  Hydrogen 16/50 (2x)
  Hydrogen 12/50 (2x)
  Fluorine 25/50
  Fluorine 25/50
  Potassium 25/50
  Potassium 25/50
  Buffer 2/50 (sulfuric acid)
  Buffer 1/50 (sulfuric acid)
  Mixdown 100/100 (100 Fluorosulphuric acid!)
  Mixdown 100/100 (75 Fluorosulphuric acid!)
Success! It may seem overly redundant to lay it out like this, but we can use it to make our ChemFuck program quickly and easily now, and the real fun begins.
Success! It may seem overly redundant to lay it out like this, but we can use it to make our ChemFuck program quickly and easily now.
== Introduction to ChemFuck ==
Everything in Brainfuck/the ChemCompiler is about manipulating the Pointer. Think about the Pointer like a mouse that can go left or right. It's always hovering over a number (it begins at the very first one available), and those numbers have their own locations in memory (references) So initially it looks like this
  v
00x000 01x000 02x000 03x000 ... FFx000
The first two numbers are the Reference. The last three, after the x, are the Value. We can do two things with the pointer - we can shift the Reference left (<) or right (>). We can add 1 to the value (+) or subtract (-).
 
Already we know how to do something useful. Say we wanted the numbers 1 through 10 stored in memory. This would be the program to write it
+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++
So stepping through, it first adds 1 to the first (always 00) reference
+
  v
00x001 01x000 02x000 03x000 04x000 05x000 06x000 07x000 08x000 09x000
Then it moves the pointer over 1 (>)
+>
  ------>v
00x001 01x000 02x000 03x000 04x000 05x000 06x000 07x000 08x000 09x000
Then it adds 1 to that reference twice
+>++
          v
00x001 01x002 02x000 03x000 04x000 05x000 06x000 07x000 08x000 09x000
And so forth, ending on reference 09 incrementing its value to 10
+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++
                                                                  v
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010
Because there is no multiplication or direct entry of numbers in Brainfuck, it's helpful to copy/paste +/- signs in known quantities if you need to reach larger numbers. And yes, chemfuck programs really are just long strings of symbols.
 
Here's all of them at once to confuse you!
 
== Commands ==
 
 
Basic pointer manipulation and arithmetic
* > Increment the reference position
* < Decrement the reference position
* + Increment the value of the reference under the pointer
* - Decrement the value of the reference under the pointer
 
While loops
* [ Start a While loop (returns to this spot when it hits ], and goes off to ] if the reference value under the pointer at that time is 0
* ] Same as above, but exactly ''backwards''. Yes, backwards. As in the program checks if the current value is 0, reverses itself until it hits a [ if not, and then it returns and does its check again. What. (if you think about it carefully, this doesn't infinite-loop either type of while loop, so why not?)


Register operations:
* { Set the Source register (number) to the value of the current reference under the pointer. The Source register (sx on the chemcompiler screen) is typically whatever beaker you're taking chemicals from next.
* } Set the Source register (number) to the current reference position
* ( Same as {, but for the Target register. The Target register (tx) you might have guessed is where a chemical will go if it's moved during the current step of the program, for instance.
* ) Same as }, but for the Target register
* ^ Same as ( or {, but for the Amount register. Amount (ax) is used for both the amount of chemicals to be moved, and Temperature values.
* ' Same as } or ), but for Amount.


You get the idea, hopefully. There's two for each of these. I might get them backwards sometimes. You might get them backwards sometimes. Experiment!
=== Actual Brogramming ===
 
Now to add the commands to match the plan.
Other operations:
==== Sulfuric ====
* $ Heat or cool reagent in sx to ((273 - tx) + ax) Kelvin. According to the original wiki entry at least. TODO more testing needed.
* @ Transfer ax units of reagent from reservoir sx to target tx.
* ~ "Compile" the code, so it cannot be retrieved again via the load button.
== Actual Brogramming ==
So now that I've thoroughly confused you, we can move on to making our first reaction in the chemcompiler. Isn't that exciting? Are you bored yet? Fuck you. This took a long time to write, you better stick with me you brat.
=== Sulfuric ===
We'll start with the setup
  1 Sulfur 50/50
  1 Sulfur 50/50
  2 Oxygen 50/50
  2 Oxygen 50/50
Line 149: Line 220:
  9 Buffer 0/50
  9 Buffer 0/50
  10 Mixdown 0/100
  10 Mixdown 0/100
Notice the numbers before each. These are the registers we're using. We could have made them anything from 1-10, but at the very least I like to make the final mix be register 10 for consistency. They're the numbered buttons in the chemcompiler menu. You load the beakers into the compiler by putting one into your hand and clicking the corresponding button - the beaker should disappear and the button should light up. Click the button again to retrieve into an empty hand.
Notice the numbers before each beaker. These are the reservoirs we're using. We could have anywhere from 1-10, but I like to make the final mix be reservoir 10 for consistency. They're the numbered buttons in the chemcompiler menu. You load the beakers into the compiler by putting one into your hand and clicking the corresponding button - the beaker should disappear and the button should light up. Click the button again to retrieve into an empty hand.


You should start by loading this mix into the compiler. Every single one, yes. Don't leave any out.
You should start by loading this mix into the compiler. Every single one, yes. Don't leave any out.


To begin with, it's really useful to load a bunch of values into the program that represent our registers, and just common numbers that we'll use constantly, so let's do that.
To begin with, it's useful to load a bunch of values into the program that represent our registers, and just common numbers that we'll use constantly, so let's do that.
  +>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++++++++++++++>++++++++++++++++++++++++++++++++++++++++++++++++++
  +>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++>+++++++++++++++++++++++++
That last two is 25 and 50. They're there so that we can handle the buffer step smoothly.
That last two numbers are 13 and 25. They're there so that we can handle the sulfuric step without too much extra movement.


We'll take the section of our plan and add to it directly. In your plan you can just edit it rather than make a giant wiki page to show your work like I did.
We'll put the starting code and a memory representation at the top of our plan.  
9 sulfur(R1
  +>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++>+++++++++++++++++++++++++
9 oxygen(R2
   
9 hydrogen(R3
Memory and Pointer:
Into buffer
                                                                                v
works out to 27, so 25 into mixdown
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025
Right now (after the values we loaded) we're at reference 12. We can visualize it as something like this
Now, modify the Sulfur part of the plan to include the reservoir names
+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++++++++++++++>++++++++++++++++++++++++++++++++++++++++++++++++++
Move
  11x050
13 sulfur(r1), and
There's three things we want to do now. We want to set tx to 9, or Buffer. We want to set sx to 1, or Sulfur. And we want to set ax to 9. Since we're there already, we can do ax and tx simultaneously. So we move the pointer
13 oxygen(r2), and
13 hydrogen(r3)
into buffer (r9).
Will produce 26u of sulfuric acid, so
Move 25u from the buffer(r9) into mixdown(r10)
Moving sulfur into the buffer requires three steps. Set ax to 13 - how much to move, set sx to 1 - where to take from, and set tx to 9 - where to deposit to. We do that by moving to and selecting the appropriate values. We'll set tx first.
  <<<
  <<<
  08x09
  Memory and Pointer:
And set both ax and tx
                                                          v
  (^
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025
I like to annotate the plan directly with these short sections of code as they fall out naturally.
And set tx
  ) (Register tx = 9)


Oh yeah. If you're confused about register 9 being '08', it's because <strike>I didn't explain</strike> you didn't notice that everything for ''references'' starts at 00. So one is 00, two is 01, and so on. Pay more attention!
Then we move back over to reference 10x, which has the value 13 we need for ax.
---
>>' (Register ax = 13)
So now we add in the modification to the Source register. It needs to be 1. I'm going to go ahead and throw it down like I was actually doing this for a living and annotate our plan.
Memory and Pointer:
+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++++++++++++++>++++++++++++++++++++++++++++++++++++++++++++++++++
                                                                        v
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025
Lastly the source register sx needs to be 1.
<<<<<<<<<<} (Register sx = 1)
Memory and Pointer:
  v
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025
With the registers set, all that's left is to trigger a transfer with the @ command.


  9 sulfur <<<(^<<<<<<<<{     (Registers: sx 1, tx 9, ax 9)
So far, the top of our plan file should look like this:
  9 oxygen
+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++>+++++++++++++++++++++++++
  9 hydrogen
   
  Into buffer
Move
  works out to 27, so 25 into mixdown
13 sulfur(r1), and    <<<)>>'<<<<<<<<<<}@     (Registers: sx 1, tx 9, ax 13)
 
  13 oxygen(r2), and
So now we can finally do something! We move 9 units of sulfur to register 9, or the buffer beaker you put into place. You did put it into place, right? Compositing all of the code so far together, you get
  13 hydrogen(r3)
  +>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++++++++++++++>++++++++++++++++++++++++++++++++++++++++++++++++++<<<(^<<<<<<<<{@
  into buffer (r9).
You can drop this into the compiler and test it out if you like. Hit Save, click 1 (in 1-6), and click 1 again. The compiler should beep a few times, and the sulfur should be moved. It pays off long-run to test these steps as you go, since things may not mix exactly as you expect, you may make typos, you can count wrong, etc. Science! Face melting!
  Will produce 26u of sulfuric acid, so  
 
Move 25u from the buffer(r9) into mixdown(r10)
By now, it should be pretty obvious what to do next, but I'll walk through it just in case.
  +>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++++++++++++++>++++++++++++++++++++++++++++++++++++++++++++++++++
Memory and Pointer:
  v
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025
Alright! So far our code moves 13 units of sulfur to reservoir 9. The whole code looks like:
  +>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++>+++++++++++++++++++++++++<<<}>>'<<<<<<<<<<}@
You can drop this into the compiler and test it out if you like. Hit Save, click 1 (in 1-6), and click 1 again. The compiler should beep a few times, and the sulfur should be moved. It's smart to test these steps as you go, since things may not mix exactly as you expect, you may make typos, you can count wrong, etc. Science! Face melting! Accidental explosions!
----
Hopefully it's obvious what to do next, but lets continue the example.
  +>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++>+++++++++++++++++++++++++
Move
13 sulfur(r1), and    <<<)>>'<<<<<<<<<<}@      (Registers: sx 1, tx 9, ax 13)
13 oxygen(r2), and    '''>}@'''                  '''(Registers: sx = 2, and move)'''
13 hydrogen(r3)      '''>}@'''                  '''(Registers: sx = 3, and move)'''
into buffer (r9).
Will produce 26u of sulfuric acid, so
Move 25u from the buffer(r9) into mixdown(r10)
Memory and Pointer:
                v
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025
With all three reagents moved, there should now be 26u of sulfuric acid in reservoir 9. Next step is to move 25u to r10.
>>>>>>} (Register sx = 9)
Memory and Pointer:
                                                          v
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025
>) (Registers: tx = 10)
Memory and Pointer:
                                                                  v
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025
>>'@ (Registers: ax = 25)
Memory and Pointer:
                                                                                v
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025
Putting it all together:
+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++>+++++++++++++++++++++++++
Move
13 sulfur(r1), and    <<<)>>'<<<<<<<<<<}@      (Registers: sx 1, tx 9, ax 13, and move)
13 oxygen(r2), and    '''>}@'''                      '''(Registers: sx = 2, and move)'''
13 hydrogen(r3)      '''>}@'''                      '''(Registers: sx = 3, and move)'''
into buffer (r9).
Will produce 26u of sulfuric acid, so
Move 25u from the buffer(r9) into mixdown(r10)  '''>>>>>>}>)>>'@'''  '''(Registers: sx 9, tx 10, ax 25, and move)'''
   
   
  9 sulfur <<<(^<<<<<<<<{@      (Registers: sx 1, tx 9, ax 9)
  Memory and Pointer:
9 oxygen >{@                  (Registers: sx 2)
                                                                                v
  9 hydrogen >{@                (Registers: sx 3)
  00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025
Into buffer
And putting it all together:
works out to 27, so 25 into mixdown >>>>>>{>(>^@
  +>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++>+++++++++++++++++++++++++<<<)>>'<<<<<<<<<<}@>}@>}@>>>>>>}>)>>'@
(Registers: sx 9, tx 10, ax 25)
You now have a program to mix sulfuric acid. Now's a good time to test again. (It works.)
And just like that:
==== Into fluorosulphuric ====
  +>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++++++++++++++>++++++++++++++++++++++++++++++++++++++++++++++++++<<<(^<<<<<<<<{@>{@>{@
Per the second half of our plan, we need to don't need to change tx or ax until the heating step.
You now have a program to mix sulfuric acid. Only with this setup, granted (sulfur in Register 1, oxygen in Register 2, hydrogen in Register 3, and an empty, empty beaker in 9 and 10 each) but it'll work. Hopefully. I didn't test it, by the way.
Move
=== Into fluorosulphuric precursor ===
25 potassium (r5), and
Taking the rest of the plan:
25 fluorine (r4), and
  +>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++++++++++++++>++++++++++++++++++++++++++++++++++++++++++++++++++<<<(^<<<<<<<<{@>{@>{@
25 hydrogen (r3)
into mixdown (r10)
Heat Mixdown (r10) to 374K
So lets move the reagents into mixdown
Picking up from the first half:
  +>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++>+++++++++++++++++++++++++<<<)>>'<<<<<<<<<<}@>}@>}@>>>>>>}>)>>'@
  Registers: sx = 9, tx = 10, ax = 25
  Registers: sx = 9, tx = 10, ax = 25
25 potassium <<<<<<<}@ (Register sx = 5, and move)
Memory and Pointer:
                              v
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025
25 fluorine  <}@      (sx = 4, and move)
Memory and Pointer:
                        v
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025
25 hydrogen  <}@      (sx = 3, and move)
Memory and Pointer:
                v
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025


25 potassium <<<<<<{@ (Register(s): sx 5)
Combined together:
25 fluorine  <{@      (sx 4)
  +>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++>+++++++++++++++++++++++++<<<)>>'<<<<<<<<<<}@>}@>}@>>>>>>}>)>>'@<<<<<<<}@<}@<}@
25 hydrogen  <{@      (sx 3)
(I rearranged these from our original plan so that there would be fewer back and forth movements of the pointer.)
 
  +>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++++++++++++++>++++++++++++++++++++++++++++++++++++++++++++++++++<<<(^<<<<<<<<{@>{@>{@<<<<<<{@<{@<{@
  Register: sx = 3, tx = 10, ax = 25
  Register: sx = 3, tx = 10, ax = 25


Now comes heating. The heating command heats (or cools) the Source register sx. So that should point at the beaker we want to heat. 10 is the beaker that we want to heat. Definitely not 3.
The heating formula is  273 - tx + ax 


=== Into fluorosulphuric (Heating explained) ===
Given that our goal is to heat -not cool- we can simply the equation by setting tx to 0. Now we just need to set ax to 110 to get 383K


So after much register shuffling, now comes heating.
So first, we're setting sx to 10 (the mixdown), setting tx to 0 (we already have this, we just need to go to the next uninitialized reference) and setting ax to 110! Then we use the heat operation, $
 
  >>>>>>>} (Register: sx = 10)
 
Memory and Pointer:
It's a little strange, because it's based off of 274k to keep you from having to use too many hundreds of +'s or -'s to get the right value.
                                                                  v
 
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025
 
It also, counterintuitively, heats the Source register sx. So that should point at the beaker we want to heat. 10 is the beaker that we want to heat. Definitely not 3.
  >>>) (Register: tx = 0)
 
Memory and Pointer:
 
                                                                                      v
It also subtracts tx from 273, because we might need that or something
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025 12x000
 
 
>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++'
Then it adds ax. That's much more useful
(Register: ax = 110)
 
 
So first, we're setting sx to 10 (the mixdown), setting tx to 0 (we already have this, we just need to go to the next uninitialized reference) and setting ax to 101! Then we use the heat operation, $
  >>>>>>>{ (Register: sx = 10)
  >>>( (Register: tx = 0)
   
   
  >+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++^
  Memory and Pointer:
  (Register: ax = 101)
                                                                                              v
  00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025 12x000 13x110
   
   
  $
  $ (Heat!)
  sx = 10, tx = 0, ax = 101
  sx = 10, tx = 0, ax = 110
Copy/pasting all of that together, we get our glorious finished program, giving 100 fluorosulphuric acid from raw reagents, with only a modest amount of clicking.
Copy/pasting all of that together, we get our glorious finished program, giving 75u fluorosulphuric acid from raw reagents, with only a modest amount of clicking.
  +>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++++++++++++++>++++++++++++++++++++++++++++++++++++++++++++++++++<<<(^<<<<<<<<{@>{@>{@<<<<<<{@<{@<{@>>>>>>>{>>>(>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++^$
  +>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++>+++++++++++++++++++++++++<<<)>>'<<<<<<<<<<}@>}@>}@>>>>>>}>)>>'@<<<<<<<}@<}@<}@>>>>>>>}>>>)>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++'$
== Homework/Addendum ==
For fun reference purposes, the final memory footprint of our program looks like this probably:
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x025 11x050 12x000 13x374
We didn't end up using 50 anywhere in our program, but it doesn't hurt to include a bit of redundancy. Well, it can, but you'll figure that out.
 
 
Setting tx to 11, 12, and 13 makes pills, vials, and disposes of reagents accordingly, when using the transfer (@) operation. If you're still not comfortable with the idea of making a plan like this of your own, try making an addition to the program to get rid of the remnant sulfuric acid in register 9, or make the compiler spit out acid pills, etc.


=== Homework/Addendum ===
You can compile a program using the ~ instruction. Put it at the end, and load it in. This prevents anyone from tinkering with it behind your back.


The while operators can create looping patterns in your program to do repetitive things without so much typing. But it's brainfuck. Most programs are like two lines long anyway. It's something to keep in the back of your mind while making your own programs/plans.
Setting tx to 11, 12, and 13 makes pills, vials, and disposes of reagents accordingly, when using the transfer (@) operation. If you're still not comfortable with the idea of making a plan like this of your own, try making an addition to the program to get rid of the lone remnant sulfuric acid in register 9, or make the compiler spit out acid pills, etc.


The "while" operators can create looping patterns in your program to do repetitive things without so much typing. But it's brainfuck. Most programs are like two lines long anyway. It's something to keep in the back of your mind while making your own programs/plans.


After you're done making fluorosulphuric, you have 3 (or 4, if you can keep from using the buffer) beakers to use for Science. Adding additional reactions, considering what you already have available, should be an obvious improvement to the program. The register layout for the first mixture I mentioned, before I <strike>got lazy</strike> decided that making the two acids was enough to teach everything you could need was this:
After you're done making fluorosulphuric, you have 3 (or 4, if you can keep from using the buffer) beakers to use for Science. Adding additional reactions, considering what you already have available, should be an obvious improvement to the program. The reservoir layout for the hellmix mentioned above is this:
  1 - Stabilizer 2x
  1 - Stabilizer 2x
  2 - Plasma 2x
  2 - Plasma 2x
Line 265: Line 400:
  9 - Phosphorus 2x
  9 - Phosphorus 2x
  10 - mix
  10 - mix
But you can make your own recipes. Remember that the plan is key!
But you can make your own recipes. Remember that the plan is key! Fancy [[Chemicals|chemical reactions]] are not all bad.


Additional tip: Don't forget that you can pre-mix you reservoirs! When you're comfortable, instead of filling beakers with 50u of a base chem, use the Chem-dispenser's bookmark feature to use exact-ratio pre-mixes.
Pentetic Acid -the apex Rad & Tox treatment- Is made of 8 base-chems + welding fuel. Those 8 chems can be pre-mixed into 2 different beakers with bookmarks, saving many steps in the Chemi-compiler plan.


Nothing here has been tested yet. Use at your own risk.
----
{{Department Guides}}

Latest revision as of 04:42, 26 June 2024

MechanicNew64.png This page is under construction.
The following information may be incomplete.
You can help by adding missing information or formatting.

"A complicated chemistry device, which uses a programming language derived from Brainfuck. It features 5 registers, 1024 bytes of RAM and 10 reagent reservoirs - to add beakers, click on the r[number] slots with a beaker in-hand. The machine can also generate pills or generate vials or trash the contents from beakers. "

Piff paff. Complicated? I think not. Scientists worth their salt can figure this out. Eventually.

If you have an aneurysm while trying to understand this thing, you can use this tool to make the code for you while using more human readable instructions.

Note that everything in this guide applies also applies to its portable version. However, keep in mind it only has 6 reagent reservoirs.

The Interface

The interface is broken up into a bunch of rows. The list numbering relates to the image.

The ChemiCompiler window.
  1. The code area. This is where you can paste in codes to save into the machine, or copy them out of the machine. It can accept very very long text strings.
  2. The load and save buttons. You need to save your code into the machine before you can run it. Once some code is in area-1, press the save button, then press a button in area-3 to save it to that slot. Pressing load, and then a button from area-3 will instead overwrite area-1 with the stored code.
  3. Code slots. The machine can store 6 codes, one per slot. These buttons turn green when they hold code. Pressing a button will begin the execution of the code stored in that slot, locking all further interactions with the machine until it completes.
  4. Reservoirs 1 thru 5. Beaker slots. These buttons turn blue when they hold a beaker. To insert a beaker, hold a beaker in-hand and press a button. Likewise, with an empty-hand, press a button to retrieve a beaker.
  5. Reservoirs 6 thru 10. More beaker slots.
  6. Register read-outs. Useful for debugging. Shows the value of the sx, tx, and ax registers at the time of completion. Only updates at the time of completion, does not update mid-execution.

Do not let the nice buttons and chui fool you, the interface beguiles the complexity within.

Signals

During normal operation, the chemicompiler emits a number of text-log cues to provide you feedback. These are as follows:

  • ChemiCompiler CCS1000 beeps quietly 2 times.

Beginning of a program.

  • ChemiCompiler CCS1000 beeps loudly once.

An operation has failed, probably due to a missing beaker in either sx or tx.

  • ChemiCompiler CCS1000 emits a slight humming sound.

Transfer step in a program

  • ChemiCompiler CCS1000 clicks.

Heating step in a program, once each for the beginning and end.

  • ChemiCompiler CCS1000 beeps quietly once.

The program has finished running and the machine is idle.


The sprite will animate while the machine is running, and it will also provide the normal chemical reaction messages if they occur.

Introduction to ChemFuck

Much like how modern programs run by executing one line of a program at a time, the ChemiCompiler works by executing one character from a string at a time. These strings of characters are referred to as "codes". An example code with 6 characters (6 commands) is "+}+)'@". The commands and the internal operations of the machine are based on the Brainfuck programming language. Thus the portmanteau ChemFuck. Our ChemFuck has more commands than it's predecessor, so it's marginally more "useful".

Everything in Brainfuck is about manipulating the Pointer. Think about the Pointer like a cursor selecting a cell on a super-wide single-row spreadsheet. The cursor can be moved left or right, one cell at a time. It's always selecting a cell and it begins at the very first one available at the far left. The memory is 0-indexed, so our first cell is named 00x. The subsequent cell is named 01x, and so on, following a hexadecimal naming scheme until the 256th cell, FFx.

  v
00x000 01x000 02x000 03x000 ... FFx000

In the representation above, the first two numbers are the Reference (the name). The last three, after the x, are the Value. We can do two primary things with the pointer - we can shift the pointer left (<) or right (>). We can add 1 to the value (+) or subtract 1 (-).

Say we wanted the numbers 1 through 10 stored in memory. This would be the program to write it

+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++

Stepping through, it first adds 1 to the first reference (the pointer always starts 00x)

+
  v
00x001 01x000 02x000 03x000 04x000 05x000 06x000 07x000 08x000 09x000

Then it moves the pointer over 1 (>)

+>
  ------>v
00x001 01x000 02x000 03x000 04x000 05x000 06x000 07x000 08x000 09x000

Then it adds 1 to that reference twice

+>++
         v
00x001 01x002 02x000 03x000 04x000 05x000 06x000 07x000 08x000 09x000

And so forth, ending on reference 09x incrementing its value to 10

+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++
                                                                 v
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010

Because there is no multiplication or direct entry of numbers in Brainfuck, it's helpful to copy/paste +/- signs in known quantities if you need to reach larger numbers. And yes, chemfuck programs really are just long strings of symbols.

Commands

Registers:

  • ptr = data pointer (16-bit) (Data is 0-indexed.)
  • iptr = instruction pointer (16-bit) (1-indexed.)
  • sx = source register (8-bit) (Valid sources are 1-10 for the 1 through 10 reagent reservoirs.)
  • tx = target register (16-bit) (Valid targets are reservoirs as above, or 11 for pill generator, 12 for vial generator, or 13 for ejection port.)
  • ax = amount register (16-bit)

Basic pointer manipulation and arithmetic

  • > Increment the pointer's reference
  • < Decrement the pointer's reference
  • + Increment the value of the reference under the pointer
  • - Decrement the value of the reference under the pointer

While loops

Loops respect nesting.

  • [ Start of a While loop. If the value at the pointer is 0, it will skip to the close (]) of the loop.
  • ] Checks if the value at the pointer is 0. If false: looks backwards through the instructions until the matching [ is found, and resumes at that bracket. If true, continues execution past the ].

Of note: The ChemiCompiler will automatically halt after thousands of instructions if caught in an infinite loop, which can take a few minutes. However, it will hang indefinitely if there is a ] without a preceding [.

Register operations:

  • } Copies the value from the pointer to the Source register (sx).
  • { Copies the value from the Source register to the pointer. It's just backwards!
  • ) Same as }, but for the Target register. The Target register (tx) is used for setting both where a chemical will go if it's moved during the current step of the program, and for cooling.
  • ( Same as {, but for the Target register.
  • ' Same as ) or }, but for the Amount register. Amount (ax) is used for both the amount of chemicals to be moved, and for heating.
  • ^ Same as ( or {, but for Amount.

You get the idea, hopefully. There's two for each of these. If the chemcompiler throws out a string of loud beeps the first time you load a program into it, you've probably gotten these backwards.

Input operation:

  • , Measure the amount of reagent in reservoir sx and stores the value in the register (ax).

Other operations:

  • $ Heat or cool reagent in sx to ((273 - tx) + ax) Kelvin. Heating takes as long as the chemistry lab heater would take.
  • @ Transfer ax units of reagent from reservoir sx to resevoir tx.
  • # Isolates ax units of reagent number *ptr from reservoir sx to reservoir tx. Indexing begins at 1.
  • . Output an ASCII character to the buffer based on *ptr.
  • ~ "Compile" the code, so it cannot be retrieved again via the load button. This does not prevent over-writing!
  • * "NOP" No Operation, this will cause the machine to do nothing for a moment. Useful for reactions that have a time component.

Guide to Understanding the Internal Operations of the ChemiCompiler

Commands got you confused? This pointer / memory stuff not getting across? What's this added detail about copying to the sx, tx, and ax registers?

A graphical guide that focuses on 4 examples is available for viewing and download here.

Each example steps through the code one command at a time, highlighting the relation between the commands, pointer, memory, registers, and beakers. The examples are roughly ordered to scale in complexity:

  1. Moving fluid from one beaker to another.
  2. Cooling a beaker.
  3. Using loops to heat multiple beakers
  4. Non-destructively isolating reagents from a beaker, and outputting a pill.

The focus of the guide is to help you understand how the ChemiCompiler works. It does not aim to teach how best to make a ChemFuck program. Read on for a method for making a program.

Guide to Making Chemcompiler Programs

The Chemcompiler seems arcane, and almost useless at first glance. But imagine a cocktail like this:

25 Fluorosulfuric acid
24 Phlogiston
24 Dark Matter
12 Smoke Powder
12 Fluorosurfactant
3 Plasma

It's a bomb, it's a face-eater, it's a fireball, and the ChemiCompiler can make it.

This guide will show you how to systematically create the beginnings of this mixture. The goal is to make 75u of fluorosulfuric acid.

Initial steps and planning

In order to make a coherent ChemiCompiler program, you first need to have a plan for every step of your reaction. A lot can go wrong. But if you follow things through systematically, you might be ok. The plan is as important as the program. Do not neglect your plan. After forming a plan, we will code alongside it - it will be our comments and our test data every step of the way.

To make fluorosulphuric acid we need sulfuric acid, fluorine, hydrogen, and potassium in equal quantities in a beaker. Then the beaker needs to be heated up to 374 degrees. Sulfuric acid needs sulfur, oxygen, and hydrogen. Obviously we need to make the sulfuric acid first.

When working with the ChemiCompiler, you need to take care of the capacity and current volume of each beaker. It's helpful to note both as you plan and program. So we document all of that to ensure a clean reaction and help with testing later.

I start it out looking like like this:

Sulfur 50/50
Oxygen 50/50
Hydrogen 50/50 (2x)
Fluorine 50/50
Potassium 50/50
Mixdown 0/100

Note that Hydrogen is marked twice since it is used twice in the reaction - you should do this so that you know, later, which ones are best to double up a beaker with, because you only have 10 slots. Complicated reaction chains can run dry fast.

The goal is for the final mixdown beaker to be 3/4s full of fluorosulphuric acid (75u). We know that we need four components to make it, so we'll need 25u of sulfuric acid. But sulfuric acid has 3 components! We'd end up needed 12.5 of sulfur, oxygen, and hydrogen. No good, we need whole integers (or a much more complex program). What we can do instead is make more than what we need, and put it into a buffer mix. That's not a great solution for more complex reactions, but it's worth remembering as a fix, because residual chemicals suck. The buffer can be emptied at any time in the ChemCompiler using a few simple operations but that won't be covered in this example.

Sulfuric

Adding the buffer beaker, the setup looks like this

Sulfur 50/50
Oxygen 50/50
Hydrogen 50/50 (2x)
Fluorine 50/50
Potassium 50/50
Buffer 0/50
Mixdown 0/100

So now we know we need:

Move
13 sulfur, and
13 oxygen, and
13 hydrogen
into buffer.
Will produce 26u of sulfuric acid, so 
Move 25u from the buffer into mixdown

We want to keep track of these changes, because running out of something is potentially dangerous

Sulfur 37/50
Oxygen 37/50
Hydrogen 37/50 (2x)
Fluorine 50/50
Potassium 50/50
Buffer 1/50 (sulfuric acid)
Mixdown 25/100 (sulfuric acid)

Into fluorosulfuric

Now to produce the final mix. We already have the sulfuric acid ready, so we need to

Move
25 fluorine, and
25 hydrogen, and
25 potassium
into mixdown
Sulfur 37/50
Oxygen 37/50
Hydrogen 12/50 (2x)
Fluorine 25/50
Potassium 25/50
Buffer 1/50 (sulfuric acid)
Mixdown 100/100 (25 sulfuric acid, 25 fluorine, 25 hydrogen, 25 potassium)

Lastly, document the heating needed to change the precursors into the final form.

Heat Mixdown to 374K

Sulfur 37/50
Oxygen 37/50
Hydrogen 12/50 (2x)
Fluorine 25/50
Potassium 25/50
Buffer 1/50 (sulfuric acid)
Mixdown 100/100 (75 Fluorosulphuric acid!)

Success! It may seem overly redundant to lay it out like this, but we can use it to make our ChemFuck program quickly and easily now.


Actual Brogramming

Now to add the commands to match the plan.

Sulfuric

1 Sulfur 50/50
2 Oxygen 50/50
3 Hydrogen 50/50 (2x)
4 Fluorine 50/50
5 Potassium 50/50
9 Buffer 0/50
10 Mixdown 0/100

Notice the numbers before each beaker. These are the reservoirs we're using. We could have anywhere from 1-10, but I like to make the final mix be reservoir 10 for consistency. They're the numbered buttons in the chemcompiler menu. You load the beakers into the compiler by putting one into your hand and clicking the corresponding button - the beaker should disappear and the button should light up. Click the button again to retrieve into an empty hand.

You should start by loading this mix into the compiler. Every single one, yes. Don't leave any out.

To begin with, it's useful to load a bunch of values into the program that represent our registers, and just common numbers that we'll use constantly, so let's do that.

+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++>+++++++++++++++++++++++++

That last two numbers are 13 and 25. They're there so that we can handle the sulfuric step without too much extra movement.

We'll put the starting code and a memory representation at the top of our plan.

 +>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++>+++++++++++++++++++++++++

Memory and Pointer:
                                                                               v
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025

Now, modify the Sulfur part of the plan to include the reservoir names

Move
13 sulfur(r1), and
13 oxygen(r2), and
13 hydrogen(r3)
into buffer (r9).
Will produce 26u of sulfuric acid, so 
Move 25u from the buffer(r9) into mixdown(r10) 

Moving sulfur into the buffer requires three steps. Set ax to 13 - how much to move, set sx to 1 - where to take from, and set tx to 9 - where to deposit to. We do that by moving to and selecting the appropriate values. We'll set tx first.

<<<
Memory and Pointer:
                                                          v
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025

And set tx

) (Register tx = 9)

Then we move back over to reference 10x, which has the value 13 we need for ax.

>>' (Register ax = 13)
Memory and Pointer:
                                                                        v
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025

Lastly the source register sx needs to be 1.

<<<<<<<<<<} (Register sx = 1)
Memory and Pointer:
  v
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025

With the registers set, all that's left is to trigger a transfer with the @ command.

So far, the top of our plan file should look like this:

+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++>+++++++++++++++++++++++++

Move
13 sulfur(r1), and    <<<)>>'<<<<<<<<<<}@      (Registers: sx 1, tx 9, ax 13)
13 oxygen(r2), and
13 hydrogen(r3)
into buffer (r9).
Will produce 26u of sulfuric acid, so 
Move 25u from the buffer(r9) into mixdown(r10) 

Memory and Pointer:
  v
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025

Alright! So far our code moves 13 units of sulfur to reservoir 9. The whole code looks like:

+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++>+++++++++++++++++++++++++<<<}>>'<<<<<<<<<<}@

You can drop this into the compiler and test it out if you like. Hit Save, click 1 (in 1-6), and click 1 again. The compiler should beep a few times, and the sulfur should be moved. It's smart to test these steps as you go, since things may not mix exactly as you expect, you may make typos, you can count wrong, etc. Science! Face melting! Accidental explosions!


Hopefully it's obvious what to do next, but lets continue the example.

+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++>+++++++++++++++++++++++++

Move
13 sulfur(r1), and    <<<)>>'<<<<<<<<<<}@      (Registers: sx 1, tx 9, ax 13)
13 oxygen(r2), and    >}@                   (Registers: sx = 2, and move)
13 hydrogen(r3)       >}@                   (Registers: sx = 3, and move)
into buffer (r9). 
Will produce 26u of sulfuric acid, so 
Move 25u from the buffer(r9) into mixdown(r10) 

Memory and Pointer:
                v
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025

With all three reagents moved, there should now be 26u of sulfuric acid in reservoir 9. Next step is to move 25u to r10.

>>>>>>} (Register sx = 9)
Memory and Pointer:
                                                          v
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025
>) (Registers: tx = 10)
Memory and Pointer:
                                                                 v
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025
>>'@ (Registers: ax = 25)
Memory and Pointer:
                                                                               v
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025

Putting it all together:

+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++>+++++++++++++++++++++++++

Move
13 sulfur(r1), and    <<<)>>'<<<<<<<<<<}@      (Registers: sx 1, tx 9, ax 13, and move)
13 oxygen(r2), and    >}@                       (Registers: sx = 2, and move)
13 hydrogen(r3)       >}@                       (Registers: sx = 3, and move)
into buffer (r9).
Will produce 26u of sulfuric acid, so 
Move 25u from the buffer(r9) into mixdown(r10)  >>>>>>}>)>>'@   (Registers: sx 9, tx 10, ax 25, and move)

Memory and Pointer:
                                                                               v
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025

And putting it all together:

+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++>+++++++++++++++++++++++++<<<)>>'<<<<<<<<<<}@>}@>}@>>>>>>}>)>>'@

You now have a program to mix sulfuric acid. Now's a good time to test again. (It works.)

Into fluorosulphuric

Per the second half of our plan, we need to don't need to change tx or ax until the heating step.

Move
25 potassium (r5), and
25 fluorine (r4), and
25 hydrogen (r3)
into mixdown (r10)
Heat Mixdown (r10) to 374K

So lets move the reagents into mixdown

Picking up from the first half:
+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++>+++++++++++++++++++++++++<<<)>>'<<<<<<<<<<}@>}@>}@>>>>>>}>)>>'@
Registers: sx = 9, tx = 10, ax = 25

25 potassium <<<<<<<}@ (Register sx = 5, and move)
Memory and Pointer:
                              v
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025
25 fluorine  <}@      (sx = 4, and move)
Memory and Pointer:
                       v
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025
25 hydrogen  <}@      (sx = 3, and move)
Memory and Pointer:
                v
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025

Combined together:

+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++>+++++++++++++++++++++++++<<<)>>'<<<<<<<<<<}@>}@>}@>>>>>>}>)>>'@<<<<<<<}@<}@<}@
Register: sx = 3, tx = 10, ax = 25

Now comes heating. The heating command heats (or cools) the Source register sx. So that should point at the beaker we want to heat. 10 is the beaker that we want to heat. Definitely not 3. The heating formula is 273 - tx + ax

Given that our goal is to heat -not cool- we can simply the equation by setting tx to 0. Now we just need to set ax to 110 to get 383K

So first, we're setting sx to 10 (the mixdown), setting tx to 0 (we already have this, we just need to go to the next uninitialized reference) and setting ax to 110! Then we use the heat operation, $

>>>>>>>} (Register: sx = 10)
Memory and Pointer:
                                                                 v
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025

>>>) (Register: tx = 0)
Memory and Pointer:
                                                                                      v
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025 12x000

>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++'
(Register: ax = 110)

Memory and Pointer:
                                                                                              v
00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025 12x000 13x110

$ (Heat!)
sx = 10, tx = 0, ax = 110

Copy/pasting all of that together, we get our glorious finished program, giving 75u fluorosulphuric acid from raw reagents, with only a modest amount of clicking.

+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++>+++++++++++++++++++++++++<<<)>>'<<<<<<<<<<}@>}@>}@>>>>>>}>)>>'@<<<<<<<}@<}@<}@>>>>>>>}>>>)>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++'$

Homework/Addendum

You can compile a program using the ~ instruction. Put it at the end, and load it in. This prevents anyone from tinkering with it behind your back.

Setting tx to 11, 12, and 13 makes pills, vials, and disposes of reagents accordingly, when using the transfer (@) operation. If you're still not comfortable with the idea of making a plan like this of your own, try making an addition to the program to get rid of the lone remnant sulfuric acid in register 9, or make the compiler spit out acid pills, etc.

The "while" operators can create looping patterns in your program to do repetitive things without so much typing. But it's brainfuck. Most programs are like two lines long anyway. It's something to keep in the back of your mind while making your own programs/plans.

After you're done making fluorosulphuric, you have 3 (or 4, if you can keep from using the buffer) beakers to use for Science. Adding additional reactions, considering what you already have available, should be an obvious improvement to the program. The reservoir layout for the hellmix mentioned above is this:

1 - Stabilizer 2x
2 - Plasma 2x
3 - Radium/Carbon 50/50
4 - Potassium/Sugar 50/50
5 - Sulfur 2x
6 - Hydrogen 3x
7 - Oxygen 2x
8 - Fluorine
9 - Phosphorus 2x
10 - mix

But you can make your own recipes. Remember that the plan is key! Fancy chemical reactions are not all bad.

Additional tip: Don't forget that you can pre-mix you reservoirs! When you're comfortable, instead of filling beakers with 50u of a base chem, use the Chem-dispenser's bookmark feature to use exact-ratio pre-mixes. Pentetic Acid -the apex Rad & Tox treatment- Is made of 8 base-chems + welding fuel. Those 8 chems can be pre-mixed into 2 different beakers with bookmarks, saving many steps in the Chemi-compiler plan.


Department Guides
Engineering Making and Breaking · Construction · Gas · Power Grid · Thermoelectric Generator · Singularity Generator · Geothermal Generator · Catalytic Generator · Nuclear Generator · Mining · Materials and Crafting · Wiring · Hacking · MechComp · Mechanic components and you · Control Unit · Ruckingenur Kit · Reactor Statistics Computer · Cargo Crates
Medsci Doctoring · Genetics · Robotics · Telescience · Plasma Research · Artifact Research · Chemistry · Chemicals · ChemiCompiler · Decomposition
Security Security Officer · Contraband · Forensics · Space Law
Service Foods and Drinks · Botany · Writing · Piano Song Dump · Instruments
The AI Artificial Intelligence · AI Laws · Chain of Command · Guide to AI · Humans and Nonhumans · Killing the AI
Computers Computers · TermOS · ThinkDOS · Packets