Difference between revisions of "ChemiCompiler"
(First draft) |
(No difference)
|
Revision as of 14:36, 26 February 2015
"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. "
Piff paff. Complicated? I think not.
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 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.
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:
9 sulfur 9 oxygen 9 hydrogen Into buffer works out to 27, so 25 into mixdown
We want to keep track of these changes, because running out of something is potentially dangerous
Sulfur 41/50 Oxygen 41/50 Hydrogen 41/50 (2x) Fluorine 50/50 Potassium 50/50 Buffer 2/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 41/50 Oxygen 41/50 Hydrogen 16/50 (2x) Fluorine 25/50 Potassium 25/50 Buffer 2/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 41/50 Oxygen 41/50 Hydrogen 16/50 (2x) Fluorine 25/50 Potassium 25/50 Buffer 2/50 (sulfuric acid) Mixdown 100/100 (100 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
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!
Other operations:
- $ 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 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 25 and 50. They're there so that we can handle the buffer step smoothly.
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.
9 sulfur(R1 9 oxygen(R2 9 hydrogen(R3 Into buffer works out to 27, so 25 into mixdown
Right now (after the values we loaded) we're at reference 12. We can visualize it as something like this
+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++++++++++++++>++++++++++++++++++++++++++++++++++++++++++++++++++ 11x050
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
<<< 08x09
And set both ax and tx
(^
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.
+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++++++++++++++>++++++++++++++++++++++++++++++++++++++++++++++++++
9 sulfur <<<(^<<<<<<<<{ (Registers: sx 1, tx 9, ax 9) 9 oxygen 9 hydrogen Into buffer works out to 27, so 25 into mixdown
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
+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++++++++++++++>++++++++++++++++++++++++++++++++++++++++++++++++++<<<(^<<<<<<<<{@
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.
+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++++++++++++++>++++++++++++++++++++++++++++++++++++++++++++++++++ 9 sulfur <<<(^<<<<<<<<{@ (Registers: sx 1, tx 9, ax 9) 9 oxygen >{@ (Registers: sx 2) 9 hydrogen >{@ (Registers: sx 3) Into buffer works out to 27, so 25 into mixdown >>>>>>{>(>^@ (Registers: sx 9, tx 10, ax 25)
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:
+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++++++++++++++++>++++++++++++++++++++++++++++++++++++++++++++++++++<<<(^<<<<<<<<{@>{@>{@ Registers: sx = 9, tx = 10, ax = 25
25 potassium <<<<<<{@ (Register(s): sx 5) 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
Into fluorosulphuric (Heating explained)
So after much register shuffling, now comes heating.
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.
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, because we might need that or something
Then it adds ax. That's much more useful
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) >+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++^ (Register: ax = 101) $ sx = 10, tx = 0, ax = 101
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
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.
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!
Nothing here has been tested yet. Use at your own risk.