Hello Internet!
In this tutorial I will talk about BF and how to make programs with it. Let’s start with what is BF and why you should love it.
Brainfuck (unfortunate name, can’t really put it on your CV) is a minimalist esoteric language. Even simplest programs are a challenge in BF and that is the beauty of it. If you love the challenge and want some headaches, BF is the one for you.
In BF you have an infinitely long *debatable, in some implementations it is constant, in others it reallocates new space as you need it 8bit byte array *again, it is usually byte but can be bigger and a pointer that points to one of the elements in this array. In a BF program, you move this pointer, alter the cell that it points to or do I/O operations for current cell. It is basically a turing machine, only even more simpler.
BF has a full set of 8 operations. These are “+-<>[].,
“. Any character other those 8 characters are disregarded by the interpreter and can be used as comments (and you will need them).
Let’s talk about these 8 operations.
Movement operations are <>
. They move pointer (or cursor, if you prefer) ‘left’ or ‘right’. Initially cursor points to beginning of the array and you use these operations to move the cursor. In some implementations it is forbidden to move left side of the initial position, in others it reallocates array or simply wraps to the other side of the array. So be careful about that. I always assume you can’t move left side of the initial position.
These operations only move it 1 cell. For example initially you are at position 0 and if you call >
it moves to position 1. If you call >>>
after that it moves to position 4.
As you probably guessed +-
are increment and decrement operations *+ is increment, - is decrement if you didn't. They increase or decrease the content of the current. That is it. You have no other way (other than I/O) altering the contents of the current cell.
At the beginning of the program, each cell is set to 0. These operations can cause integer overflows so if you call -
when cell is 0, it will be -1 (or 255, if you don’t want to bother with signs) and +
will cause it to overflow 0 again.
You can’t set a cell to a constant. If you want a cell to be set to 10, you need to call ++++++++++
*assuming it was 0 before, if you want to set it to 50 you will need 50 + operations*There are easier ways of course, I will talk about them in 'advanced' section 🙂
So here is a very simple program that uses all operations we learned.
++++>+++--
First we increase the cell0 by 4 then move cursor to the left. It increases cell1 by 3 and decreases it by 2 to set it 1. In the end our cell is “31000000…..” and cursor points to 1 (cell1)
We have an input and an output operator in BF. Basically they input a byte (or character) from stdin or outputs a byte (or character) to stdout. .
outputs content of current to cell to stdout and ,
inputs a byte from stdin. Again they only alters/uses current cell.
You will need basics of ascii to input/output meaningful data. For example if you set a cell to 48 and call .
it will print ‘0’ to the console because ascii value for ‘0’ is 48. If you call ,
and press 2 it will set current cell to 50 (ascii value of 2).
So here is a much more complicated BF program! You can press run to see output of the program.
!bf!+++++ +++++ +++++ +++++
+++++ +++++ +++++ +++++
+++++ +++++ ++ set current cell to 52 (4)
. print 4
-- decrease current cell by 2 set it to 50 (2)
. print 2
> +++++ +++++ . go to cell1 and set it to 10 and print (\n)
, input a charcter (i assume that user will press something between 0 and 9)
+ increase the inputted value
. print new character
First part is obvious, it first sets cell to ‘4’, prints it then set it to ‘2’ and prints it again. You get the answer to the life. It prints a \n after that to go next line.
In second part it inputs a character from user and increases its value by and outputs it. If user inputs ‘0’ it is 48 in ascii, after +
it is set to 49 and when printed it prints ‘1’. If user inputs 5, it prints 6. If he inputs 9, no it does not print 10. It prints ‘:’ because ascii value after ‘9’ is equal to ascii value of ‘:’. Printing two digit numbers are very tricky.
That is all for I/O. Now comes the tricky part.
Our final two operations are []
. These are used for creating loops or conditional statements. Every [
operation is matched by a ]
. Any command between these two operations are evaulated if only a certain condition is satisfied.
When a BF interpreter reaches a [
statement, it checks if value of current cell is zero or non zero. If it is zero, than code between []
is not evaulated and it jumps to the operator that comes after ]
. If it is non zero than it simply jumps next operator after [
and continue to execute normally. When it finally reaches ]
it rewinds back to [
and again if current cell is zero or non zero. It loops until current cell is non zero.
It is basically a while loop that uses value of current cell as a boolean. zero = false, non-zero = true.
Be careful that when it rewinds to the back, it does not move cursor to the old position. If you are using <>
operations between []
, you will probably want number of <
is equal to >
. And it does not alter the content of the current cell so you will want to decrease (or increase) current cell to break loop at some point.
Now let's write a program that prints 10 exclamation marks using a loop.
!bf!+++++ +++++ +++++ +++++
+++++ +++++ +++ set current cell to 33 (!)
> move cell1
+++++ +++++ set cell 1 to 10
[ start loop at cell 1
< move cell 0 (contains !)
. print !
> move cell 1 again
- decrease cell 1 by 1
] end loop
First we set cell0 to ascii value of ! then it moves to cell1 and sets it to 10. Cell 1 is our test cell, as long as it is non zero this loop will be executed.
At each iteration of loop it moves back to cell0 and prints it. Then it again moves back to cell 1 and decrease it. When it rewinds back to [ it will test if cell1 (current cell) is nonzero and if it is non-zero it will execute again. During the execution cell1 will be 10 9 8 .. 1 and finally 0 and execution of loop will stop.
Previously I said that you can use a simpler/shorter way to set a cell to 50. Here it is
+++++++[->+++++++<]>+
It first sets cell0 to 7 and loops until it is zero. In each loop it moves to cell 1 and increases it by 7 again. It is basically a multiplaction operation at the end of the loop cell1 is 7x7=49. We increase it once again and set it to 50. Easier than +++++...+ times 50!
That is it! Now you can write a doom clone in BF!
I am planning more complex tutorials on BF. There are some tricks I learned that makes writing more complex program easier. I will make and explain some code examples that shows some essential stuff (printing two digit numbers for example :)). Stay tuned!