ChemiCompiler
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.
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 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.
Guide to Making Chemcompiler Programs/Reactions
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. 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 :<
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.
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.
'ΤΗΕ Ρ⌊ΔΝ ¦ς Α§ ΙΜΡΩℜΘΑΝΘ Ας ⊥Η∃ ϖℜœℑ®αΜΜìñϑ∴', 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.
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.
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 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.
Let's say we want that final mixdown beaker to be 3/4s 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 12.5 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.
Sulfuric
Our new 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:
13 sulfur 13 oxygen 13 hydrogen Into buffer works out to 26, so 25 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 we move on to the final mix. We already have the sulfuric acid ready, so we need
25 fluorine 25 hydrogen 25 potassium 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)
Now we need to document the heating needed to change the precursors into our final form.
Heat Mixdown to 374 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, and the real fun begins.
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
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
- [ Start of a While loop. This bracket is simply a label used by ].
- ] Checks if the value at the pointer is 0. If false: looks backwards through the instructions until [ 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.
- ~ "Compile" the code, so it cannot be retrieved again via the load button. This does not prevent over-writing!
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 and test, you better stick with me you brat.
Sulfuric
We'll start with the setup
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. 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.
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.
+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++>+++++++++++++++++++++++++
That last two is 13 and 25. They're there so that we can handle the sulfuric step without too much extra movement. You want to conserve movement as much as possible, because you have a -lot- of memory available.
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.
13 sulfur(R1) 13 oxygen(R2) 13 hydrogen(R3) Into buffer(R9) works out to 26, so 25 into mixdown(R10)
Right now (after the values we loaded) we're at reference 12. We can visualize it as something like this
+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++>+++++++++++++++++++++++++ Memory and Pointer: v 00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025
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 13 - that's how much sulfur we want. We do that by finding either a reference or a value (we'll be using values to avoid confusing you, but they're both numbers, see?)
<<< Memory and Pointer: v 00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025
And set tx
) (Registers: tx = 9)
Then we move back over to reference 10, which has the value 13 we need for ax.
>>' (Registers: ax = 13) Memory and Pointer: 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.
Oh yeah. If you're confused about register 9 being '08', it's because I didn't explain you didn't notice that everything for references starts at 00. So one is 00, two is 01, and so on. Pay more attention!
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, but the bold step is what we've just done.
+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++>+++++++++++++++++++++++++ 13 sulfur <<<)>>'<<<<<<<<<<} (Registers: sx 1, tx 9, ax 13) 13 oxygen 13 hydrogen Into buffer works out to 26, so 25 into mixdown Memory and Pointer: v 00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025
So now we add the @ at the end to move the sulfur
@
and we can finally do something! We move 13 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
+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++>+++++++++++++++++++++++++<<<}>>'<<<<<<<<<<}@
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!
By now, it should be pretty obvious what to do next, but I'll walk through it just in case.
+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++>+++++++++++++++++++++++++ 13 sulfur <<<)>>'<<<<<<<<<<}@ (Registers: sx = 1, tx = 9, ax = 13, and move) 13 oxygen >}@ (Registers: sx = 2, and move) 13 hydrogen >}@ (Registers: sx = 3, and move) Into buffer Memory and Pointer: v 00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025 works out to 26, so 25 into mixdown >>>>>>} (Registers: 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
And just like that:
+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++>+++++++++++++++++++++++++<<<)>>'<<<<<<<<<<}@>}@>}@>>>>>>}>)>>'@
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.
Into fluorosulphuric precursor
Taking the rest of the plan, we do not need to shift tx or ax except at the very end. It's now a breeze to transfer the rest of the components for fluorosulphuric acid and cook the mix.
+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++>+++++++++++++++++++++++++<<<)>>'<<<<<<<<<<}@>}@>}@>>>>>>}>)>>'@ Registers: sx = 9, tx = 10, ax = 25 25 potassium <<<<<<<}@ (Register(s): sx 5) Memory and Pointer: v 00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025 25 fluorine <}@ (sx 4) Memory and Pointer: v 00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025 25 hydrogen <}@ (sx 3) 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
Into fluorosulphuric (Heating explained)
So after much register shuffling, now comes heating.
Unlike the rest of the values in the wiki, it's based on Celsius. You can use the Googles to figure out how much you need to heat the mixture.
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.
It also subtracts tx from 273, so that you can reach negative values if necessary. We'll just set tx to zero.
Finally it adds ax.
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 190! 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 = 190) Memory and Pointer: v 00x001 01x002 02x003 03x004 04x005 05x006 06x007 07x008 08x009 09x010 10x013 11x025 12x000 13x101 $ (Heat!) sx = 10, tx = 0, ax = 190
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.
+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++>+++++++++++++++++++++++++<<<)>>'<<<<<<<<<<}@>}@>}@>>>>>>}>)>>'@<<<<<<<}@<}@<}@>>>>>>>}>>>)>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++'$
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.
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 10x013 11x025 12x000 13x101
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 got lazy decided that making the two acids was enough to teach everything you could need was 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 |