Butterbrain

From Esolang
Jump to navigation Jump to search

Butterbrain is an esolang heavily inspired by brainfuck. Butterbrain and brainfuck both share the idea of a strip of memory cells that can be looked at through a "head" which is pointing to one cell. While brainfuck uses relative positioning, such as > to move the head to the right, Butterbrain uses absolute positioning.

Evaluation

Butterbrain code is evaluated from left to right, top to bottom, as is with regular code. It is composed of special characters and expressions. Characters not matching the instruction set are ignored. Comments are not supported, though it might be possible to improvise one.

Special Characters

Special characters perform I/O, loops, and movement. Most special characters depend on the value the head is pointing at, so that value will from now on be referred as #. The special characters are the following:

Symbol Use
s sets # to input
g sets the head's position to input
p prints #
i sets # to input from stdin
n prints a newline to stdout
a prints #'s ASCII value
~ prints the values from the 0th cell up to #'s cell - used for improvised debugging
[ jumps to the next balanced ] if # is 0
] jumps back to the previous balanced [ if # is not 0
{ jumps to the next balanced } if # is not 0
} jumps back to the previous balanced { if # is 0

The bread and butter of this language is s and g. These two special characters take input by evaluating the expression to the right of them.

Expressions

Using expressions can be thought of as nesting functions. Each expression is a single character that takes the value on the right as input, performs a simple operation, then returns another value. By placing them together, these chains of expressions modify the input on the right to modifies the input in potentially complex ways. Each chain starts with an expression that does not take input and ends in s or g. They are as follows:

Expression Use
v returns the head's position
0 - 9 returns their value as positive integers in base 10
Expression Use
@ returns the value of cell input
) returns the head's position + input
( returns the head's position - input
+ returns # + input
- returns # - input
* returns # * input
/ returns # / input, rounded down
& returns # bitwise and with input
returns # bitwise or with input
^ returns # bitwise xor with input
= returns 1 if # = input, 0 otherwise
> returns 1 if # > input, 0 otherwise
< returns 1 if # < input, 0 otherwise
! returns 1 if input is 0, 0 otherwise
% returns # bitwise modulo input

This expression is given as an example. It takes the number 66, adds # to it, multiplies it by #, then checks if it is equal to #.

=*+66

If # was 2, the expression would be evaluated as follows:

2 == (2 * (2 + (66)))

Examples

Hello, world!

This program works by setting the 0th cell in memory to the ASCII values of Hello, world!\n, printing the character with 'a' at each step. then printing a newline:

s72  a
s101 a
s108 a
s108 a
s111 a
s44  a
s32  a
s119 a
s111 a
s114 a 
s108 a
s100 a
s33  a
n

Truth-machine

A truth machine prints 0 if the input is 0, and an infinite amount of 1s otherwise.

i     
[s1p]
p

The first line sets the 0th cell to the user input.

i

The second line will be skipped if the user input was 0. Otherwise, it sets the 0th cell to 1 and keeps printing what's in the 0th cell indefinitely.

[s1p]

The third line will only be run if the input is 0 and will print the input.

p

Nim AI

Nim is a 2-player game played with piles of objects. Players take turns taking any number of objects from any single pile until there are no objects left. The object of the game can either be to be the last player to have taken an object or to force the other player to take the last object depending on the game. This instance of Nim is played with the objective to take the last object with 3 piles of 3, 5, and 7 objects.

The first line of code sets up cells 0 through 8 to for the game. The 0th, 1st, and 2nd cells represent the 3 piles the game is played with. The 3rd cell is used for printing the board. The 4th cell represents whose turn it is and is set to user input, so the player can decide if the AI can go first. Cells 5 and 6 will be used for user input, where 5 is which pile to take from and 6 is how much to take. They are set to 0 and 1 for now. Cell 7 is 1 as long as the game is not over.

Note that butterbrain does not support comments, so the blocks of explanatory text should be erased before the interpreter runs.

s3 g1s5 g2s7 g4i g5s0 g6s1 g7s1
[
  g3s3            Prints out the board.
  [
    g(@v
    p
    g3s-1
  ]
  n
  g4              Gets user input if it is their turn.
  {
    g5i
    g6i
  }
  g4s!@v          Gets the ideal move the AI should make via XOR or a nimsum.
  {
    g8s0
    g9s1
    [
      g9
      s@@8
      g10s@8s+1s%3s@@v
      g11s@8s+2s%3s@@v
      g10s^@)1
      g9s-@10
      g12s@9s<1
      g13s@@8
      s<@9
      s|@12
      g12
      s!@13
      {
        g15s1
        g5s@8
        g6s@9
      }
      g8s+1
      g14
      s@8s<3
    ]
    g15 
    s!@v          If no ideal move exists, take 1 from the first non-zero pile
      {
      g5s0
      g6s1
        [
        s@@5
        s!@v{
          g5s+1
        }
        g6
      ]
      g6s1
    }
  }               Update board and check if the game is over
  g6
  g@(1
  s-@6
  g7
  s@0s+@1s+@2
 ]
                  Print winner
 g4
 s!@v
 p

Because whitespace doesn't matter in Butterbrain, this code can be minimized to:

s3g1s5g2s7g4ig5s0g6s1g7s1[g3s3[g(@vpg3s-1]ng4{g5ig6i}g4s!@v{g8s0g9s1[g9s@@8g10s@8s+1s%3
s@@vg11s@8s+2s%3s@@vg10s^@)1g9s-@10g12s@9s<1g13s@@8s<@9s|@12g12s!@13{g15s1g5s@8g6s@9}g8
s+1g14s@8s<3]g15s!@v{g5s0g6s1[s@@5s!@v{g5s+1}g6]g6s1}}g6g@(1s-@6g7s@0s+@1s+@2]g4s!@vp

Example terminal output:

input
1

Player starts first

357
input
0
input
1

Take 1 from the 0th pile

257

The result of your actions

157

AI's turn

input
2
input
3

Take 3 from the 2nd pile

154

The result of your actions

151

The ai went

input
0
input
1

Take 1 from the 0th pile

051

The result of your actions

011

The ai went

input
1
input
1
001

Take 1 from the 1st pile

0

The computer (player 0) wins

Binary Search Tree

This code sets up the memory for a binary search tree, occupies that memory with an example tree, then searches through the tree for a given value. The memory is set up in a way where the first cell in a node is the data stored in that node. The next cell is a pointer to the parent node, and the last two cells are pointers to the left and right branch nodes.

g)1
s1
[g)1s(1s+4s/8s-1s*4s+1g)1svs*2s-1g)1svs*2s+1g)1svs<32]  Sets up memory
g1
s10
g@)2
s5
g@)2
s2
g@)1g@)3
s7
g@)1g@)1g@)3
s15
g@)2
s12
g@)1g@)3
s20
g1000i
g)1s1
[
  g0
  s@@1001
  pn
  s=@1000
  {s@1000pns1}
  s!@v
  {
    s@@1001
    s<@1000
    {g1001s+1}
    g1001
    s+2
    s@@v
    g0
    s@1001
    s<32
  }
]

Interpreters

C

See Github