1
0

Updated BefunGen to >> BefunUtils

This commit is contained in:
2014-12-29 13:41:57 +01:00
parent 9ee572fa9f
commit 7500ee5b5a
25 changed files with 15 additions and 11 deletions

View File

@@ -0,0 +1,60 @@
BefunExec is a fast Befunge-93 interpreter.
![BEFUNEXEC_MAINWINDOW](/data/programs/desc/BefunGen/01_Manuals/BefunExec_Main.png)
BefunExec can either be controlled over the menu or by keyboard shortcuts.
You can read about the shortcuts and the command line parameters in the console window of BefunExec.
##Program
In the center you can see the program, depending on your options highlighted or not.
You can zoom in either with your mouse wheel or by dragging a selection box. With `Esc` can you go one zoom level back.
By pressing `R` can you reset the whole program and by pressing `Space` can you pause/un-pause it.
While he program s paused you can do a single step by pressing `Left`
You can also change the simulation speed with the shortcuts `1` to `5` and add breakpoints by clicking on a single command (breakpoints are displayed blue).
> **Tip:**
> Access debug information like FPS and your current interpretation speed by holding `tab`
##Stack
On the left side is the current program stack, if you have enabled it you can see behind the numbers the ASCII representation of the number.
##In/Output
Every output is written into the output field and the console, you can also access all the output over the menu entry "show output".
For the input there is an input buffer in place. You can enter a series of chars in the input-box and press the input button.
Your text is then in the input buffer and the next time the program wants to read a character it will take it from this buffer.
If the buffer is empty the program will pause until there is a character in it which it can read.
When the programs reads a number on the other side will always pause the program and ask the user to enter a number.
##Settings
Over the menu you can change a few settings:
- **Syntax Highlighting**: Choose your Syntax highlighting method
- **Follow cursor**: Zoom in and follow the PC automatically around
- **Show trail**: Show trail behind PC
- **ASCII stack**: Show ASCII characters in stack display
- **Skip NOP's**: Skip continuous White spaced
- **Debug mode**: While in debug mode you will be warned of operations that would never occur in a BefunGen created program (wrap-around-edge, pop empty stack ...)
###Extended Syntax Highlighting
![BEFUNEXEC_ESH](/data/programs/desc/BefunGen/01_Manuals/BefunExec_ESH_example.png)
BefunExec can use BefunHighlight to highlight the program (= extended Syntax highlighting).
It will automatically choose so if the program isn't too big and you haven't explicitly specified another highlighting method.
Be aware that when you run on top speed and BefunExec is getting slowed down a lot by BefunHighlight it will automatically change the highlighting method.
##Additional
###Capture GIF
![BEFUNEXEC_CAPTUREGIFDIALOG](/data/programs/desc/BefunGen/01_Manuals/BefunExec_CaptureGifDialog.png)
With the menu point "Capture GIF" you can create an animated .gif animation of your running program.
You can set the amount of steps to capture and the animation delay between the steps. You can also set the final delay before the animation restarts.
There is also the "Automatic frame count" option, only use this if your program terminates in a reasonable amount of frames.

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

View File

@@ -0,0 +1,52 @@
BefunRep is an command line tool to calculate Befunge93 number representations
![BEFUNREP_MAINWINDOW](/data/programs/desc/BefunGen/01_Manuals/BefunRep_Main.png)
To execute BefunRep you need to open the windows command line (cmd.exe).
The representations are saved in a "safe", you can give the safe-path with the parameter **safe**.
There are three safe-formats available: binary (.bin), CSV (.csv) and JSON (.json). But for most cases the binary safe is the best, especially for bigger safes.
When you first generate a safe you have to give him a number range with the parameters **lower** and **upper**
> **\> BefunRep -safe="binsafe.bin" -lower=0 -upper=1000 -reset**
The **reset** command resets the safe if the file already exists.
You can update an existing safe and search for improvements
> **\> BefunRep -safe="binsafe.bin"**
Here the existing limits in the safe are re-used. But you can also extend a safe and give him a new range.
> **\> BefunRep -safe="binsafe.bin" -lower=-100 -upper=3500**
As you can see with every iteration on the same range there is a chance to find a few improvements.
You can also specify a fixed amount of iterations with the parameter **iterations**. A negative iteration number will result in calculations until no more improvements can be found.
> **\> BefunRep -safe="binsafe.bin" -reset -lower=-100 -upper=3500 -iterations=-1**
When you calculate a new safe you will get a lot of console output, this will probably slow your program down. The parameter **quiet** (or just **q**) prevents the "Found improvement" output.
Also you can specify a statistics level from 0 to 3 with **stats**, this regulates the safe statistics you can see at the end of the program.
> **\> BefunRep -safe="binsafe.bin" -reset -lower=-100 -upper=3500 -iterations=-1 -q -stats=3**
If you already have an safe and don't want to calculate anything so you only see its statistics you can use iterations=0
> **\> BefunRep -safe="binsafe.bin" -iterations=0 -stats=3**
The binary safe format is not really human readable, to get the results in a better format use the **out** parameter. Supported formats are CSV (.csv), JSON (.json) and XML (.xml). XML and JSON are useful to redirect it to other programs and CSV to manually read them, because CSV doesn't need to escape any characters.
> **\> BefunRep -safe="binsafe.bin" -reset -lower=-100 -upper=3500 -iterations=-1 -q -out="csvoutput.csv"**
Similiar to the statistics you can also use the iterations=0 trick to generate an output of an existing safe
> **\> BefunRep -safe="binsafe.bin" -iterations=0 -out="csvoutput.csv"**
Internally BefunRep has multiple algorithms that are executed one after the other. Normally all are executed but you can also specify a single one to use with the parameter **algorithm**
> **\> BefunRep -safe="binsafe.bin" -reset -lower=-100 -upper=3500 -algorithm=3**
If you need a list of the possible arguments execute BefunRep without any arguments or with **help**
> **\> BefunRep -help**

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View File

@@ -0,0 +1,81 @@
BefunWrite is an IDE to write and compile TextFunge, once started you will see the main window:
![BEFUNWRITE_MAINWINDOW](/data/programs/desc/BefunGen/01_Manuals/BefunWrite_Main.png)
You can write your code in the center and see a summary of current constants/variables/methods on the right side.
On the bottom site you can also expand the tabs `Output` and `ErrorList`.
In the code section you can see an example program (a simple hello world), feel free to edit this example or delete it completely.
You can safe your code in the menu or by pressing `STRG+S`. 3 different files will be created:
- `projectname.tfp` : The project file, it contains settings and the path to the other files
- `projectname.tf` : The actual source-code
- `projectname.tfdv` : The initial display value (or empty if not defined)
If you want to set an initial display value (see the topic `TextFunge` for more information) you can modify the tab `Display` beside the tab `code`.
To build the project simply choose a build configuration (Debug and Release are the defaults) and click `Build`.
The builded Befunge files will end up in the sub-folder `projectname\configname`.
To test the program you can also choose run, this will build the project and then open it in BefunExec.
##Build configurations
With the build configurations dialog you can modify the build process
![BEFUNWRITE_SETTINGS](/data/programs/desc/BefunGen/01_Manuals/BefunWrite_Settings.png)
> **Note:**
>
> - **PC** is the *Program Counter*, the current position in the program
> - **NOP-cells** are the unused parts of the program, they are neither variable space, nor commands.
> The PC will enter them and they should never be evaluated.
###General
> General BefunWrite Settings
- **Name**
###Execution
> BefunExec Settings
- **Debugging Enabled**: Enable debugging options (warnings on unexpected behaviours)
- **Start Paused**: Starts the program non-running
- **Syntax highlighting**: Sets the preferred syntax highlighting method
- **Show chars in stack**: Show the ASCII chars in the stack
- **Follow PC**: Start with follow mode enabled
- **Skip Whitespace**: Skip continuous white-spaces
- **Initial speed**: Sets (the index) of the initial interpretation speed
- **Speed[x]**: The delay between cycles on speed level *x*
- **Show Tail**: Show a fading tail behind the actual PC
- **Lifetime Tail**: The time (in ms) until the tail has faded away
- **Start zoomed in on display**: Set the initial zoom fitting for the display
###Code Generation
> BefunGen Settings
- **Number literal representation**: The used algorithm for presenting number literals
- **Optimize double string-mode**: Try to combine two adjacent `"` together
- **Set NOP to special char**: Set NOP cells to a special character
- **Custom NOP char**: The special character for NOP cells (if used)
- **Horizontal compression**: Try to horizontally compress the program
- **Vertical compression**: Try to vertically compress the program
- **Minimum VarDecl. width**: The minimum width of a declaration block, increase this if your initialization-blocks grow in height.
- **Default VarDecl char**: The initial char (before initialization) of variable fields
- **Default TempDecl/TempResult char**: The initial char (before use) of temporary fields
- **Safe boolean cast**: When hard-casting a variable to boolean it will result in either a **1** or a **0**
- **Default local int/char/bool var value**: The initial value of a local variable *(should stay default)*
- **Initial disp char**: The initial character of the display fields
- **Display border value**: The character of the border around the display
- **Display border thickness**: The thickness of the border around the display
- **Prevent Display overflow**: When accessing coordinates outside of the display wrap around the edges.
- **Optimize static Expr**: Try to compile-time interpret simple expressions (4 * 4 + 4 ==> 20)
- **Remove unused methods**: Don't include methods that get never called
> **Warning !**
> If **Prevent Display overflow** is not set you can write into your own program and cause *really* strange behaviour.
> If you choose this path you have to prevent an out-of-bounds display access for yourself.
Be aware that it is wise to leave most code generation settings on their default values.
For the most cases only the settings **Set NOP to special char**, **Safe boolean cast** and **Prevent Display overflow** should be interesting.

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -0,0 +1,478 @@
TextFunge is the c-like language used for BefunGen.
Most constructs are very similar to C and Pascal, so you won't have trouble writing anything in it.
> *Note:*
> TexFunge programs are case-insensitive. *(but please be consistent with your naming)*
###Program structure
A TextFunge program starts with the keyword `program` and the program name and ends with `end`
```textfunge
program example_01 : display[0, 0]
begin
// code
end
void method()
begin
// code
end
end
```
between program` and `end` you can put your methods. The first method has no header and is called the main method.
This method is called upon the beginning and when this method has finished the program terminates.
You can specify a display by writing `: display[width, height]`, if the display is not specified its has a width and height of zero.
###Types
TextFunge knows 9 different variable types:
- Integer: A single integer value
- Digit: A single Base-10 digit (integer in the range from `0` to `9` )
- Character: A single character
- Boolean: A boolean value (`TRUE` or `FALSE`)
- Void: Nothing, used for methods that return nothing
- Integer Array: An fixed-length array of multiple integer
- String: An fixed-length array of multiple character
- Digit Array: An fixed-length array of multiple digits
- Boolean Array: An fixed-length array of multiple booleans
```textfunge
int a1;
integer a2;
int[4] a3;
char b1;
character b2;
character[4] b3;
bool c1;
boolean c2;
bool[4] c3;
digit d1;
digit[4] d2;
```
You can freely cast all value types into each other and all array-types with the same length (see *Casts* for more information)
###Variables
Between each method header and the `begin` keyword you can specify local variables under the `var` keyword:
```textfunge
void method()
var
int var_1, var_2;
int var_3 := 77;
int[4] var_4 := {0, 1, 1, 0};
char[4] var_5 := "FFFF";
begin
```
These variables have a local scope and can't be accessed from anywhere else.
You can also at the beginning of the program specify variables with a global scope
```textfunge
program example_02
global
int gvar_1, gvar_2;
int gvar3;
```
> *Note:*
> Global variables (unlike local variables) can **not** have an initializer, they will initially have the value which you specified while compiling.
To access a variable as whole just write its name, to access an specific array index write the index in square brackets:
```textfunge
var_1[0] = var_2[4 + 1];
```
###Constants
At the same position as global variables can (global) constants be defined:
```textfunge
program example_02
const
int VERSION := 14;
int COL_BLUE := 0x0000FF;
char UNDERSCORE := '_';
```
Be aware that constants are always in the compiled program inlined.
So constants are only *syntactical sugar* and result in the same as writing the literal everywhere, where you use the constant.
> *Note:*
> You can only define constants for value types, array constants are not *yet* supported.
###Literals
You can specify (Base-10) integer literals by simply writing the number:
```textfunge
0
9283
-9283
```
And also Base-16 (Hexadecimal) integer literals with `0x`
```textfunge
0x00
0xF0F
0x123
```
Digit literals have a `#` prefix:
```textfunge
#0
#6
#9
```
Char literals are surrounded by single ticks:
```textfunge
' '
'A'
'a'
```
Boolean literals consist of the two boolean keywords:
```textfunge
true
false
TRUE
```
String literals are surrounded by quotation marks: (Be aware that a string literal is only a shortcut notation of an char array)
```textfunge
""
"hello"
"hello \r\n second line"
```
And Array literals are the values inside of a set of curly braces:
```textfunge
{0, 1}
{'h', 'e', 'l', 'l', 'o'}
{true, false, true}
```
###Methods
Methods consist of 2 parts, the header and the body:
```textfunge
int[9] method(int a, int b, int[9] c)
var
int var_1 := 0;
int var_2;
begin
// Code
// Code
// Code
return c;
end
```
In the header you define the return type (value type, array type or `void`),
the method name (the normal C naming restriction are valid) and the parameter list (multiple value or array types).
Then you can (optionally) define local variables.
And finally between `begin` and `end` you can write your code.
> *Note:*
> Every path of an method must result in an `return` statement.
> If the return type is void the compiler can automatically add an return to the end.
###Control Structures
#### If / Elsif
```textfunge
if (a) then
// Code [a == true]
elsif (b) then
// Code [b == true]
elsif (c) then
// Code [c == true]
else
// Code [else]
end
```
You can write a branch statement with the keyword `if`.
Unlike C you have to write additional `else if`-branches with the keyword `elsif` and you have to end the whole block with `end`
#### While do
The `while` loop repeats a statement block until a condition is false
```textfunge
while (running) do
// Code
end
```
Every loop the condition is evaluated and checked.
#### Repeat until
The `repeat until` loop repeats a statement block until a condition is true
```textfunge
while (running) do
// Code
end
```
The difference to a `while` loop is that the condition is executed at least once.
#### For
The `for` loop is a more comfortable loop, because it has an initializer field, a condition field, and a statement field
```textfunge
// (init ; cond ; stmt)
for (i = 0; i < 10; i++ ) do
// Code
end
```
Each field can also be empty, allowing for this simple, infinite loop:
```textfunge
for (;;) do
// Code
end
// <-- unreachable (without goto)
```
#### Switch case
If you want to distinct multiple values you can use a switch statement:
```textfunge
switch(c)
begin
case ' ':
// Code
end
case '0':
// Code
end
default:
// Else-Code
end
end
```
> *Note:*
> This is **not** C, there is no fall-through with empty case blocks.
> *Note:*
> Having a lot of cases in a single switch can increase the horizontal size of your program drastically.
> Think about using other possibilities in this case
#### Goto
```textfunge
goto MLBL;
out "Nobody sees me";
MLBL:
out "end";
```
You can define labels by writing the identifier and a colon (instead of a semicolon).
And you can write goto statements with the keyword `goto`
> *Note:*
> This is **not** C, you have to end an goto statement with an semicolon, like every other statement too.
> *Note:*
> Use goto's sparely, they are pretty slow and I'm not sure if they are bug-free.
###Expressions
####Mathematical operators
You can use the normal mathematical operators `+`, `-`, `*`, `/`, `%` (modulo), `(` and `)`.
Normal precedence rules apply
```textfunge
a = ((5 + 5)*4 - 10)/-1 % 4;
```
####Boolean operators
You can use the boolean operators `&&` (AND), `||` (OR), `^` (XOR), `!` (NOT).
```textfunge
a = (10 == x) ^ true;
b = !(10 == x);
```
####Comparison
You can use the normal c-like comparison operators `==`, `!=`, `<`, `>`, `<=` and `>=`
```textfunge
while (a < 100 && a > -100) do
a *= 2;
end
```
###Special Statements
####Random
You can either generate a random boolean value by using `rand`, or a random integer value by using `rand[?]`.
`rand[n]` generates a random number from [0, 4^n), where 0 is included and 4^n is excluded. So you are only able to set the upper border to results of the formula 4^n.
```textfunge
if (rand) do
a = rand[6] % 10;
end
```
> *Note:*
> Be aware that in the example above not all values are equally distributed (4^6 % 10 != 0), but approximately it is good, and it becomes better with bigger values for n.
####Quit
The statement `quit`, `stop` or `close` instantly terminates the program. The main method will always implicitly have an `quit` at the end.
```textfunge
if (error != 0) then
out "FATAL ERROR";
quit;
end
```
####Code block
You can start everywhere a new code block, it probably wont change the resulting program but has its use in structuring the source code.
```textfunge
// Code
begin
// Code
// Code
end
// Code
```
####De-/Increment
With `++` and `--` you can increment/decrement a variable in a shorter way than a assignment.
```textfunge
a++;
a = a + 1; // equally
```
####Assignments
With a single `=` you can assign a value to a variable.
```textfunge
a = 3;
b[3] = 0;
```
###Method calls
Method calls are pretty much like in every other language.
```textfunge
method_1(0, 6, "hello");
method_2(getA(), getB(0));
```
###Comments
You can write either full line comments with `//` or block comments with `/*` and `*/`
```textfunge
/* Comment
* Comment
*/
// Comment
method_99( /* comment */ );
```
###Casts
TextFunge supports explicit and implicit casting.
The cases in which implicit casts happen are:
- `digit` -> `int`
- `digit[]` -> `int[]` (with same length)
You can cast all other value types into each other and array types if they have the same length.
```textfunge
var
bool b;
int i;
char c;
begin
c = (char)i;
b = (bool)c;
```
> *Note:*
> When casting no information is lost, so hard casting to an digit can yield to an illegal value.
> Also casting something from an boolean does not always result in `0` or `1` (it results in `0` / `not 0`). If you want this you can enable "explicit boolean casting" in the compiler options.
###Input/Output
####Out
With the statement `out` you can output either a value or a string:
```textfunge
out 99;
out 'a';
out "Hello World";
out var_1;
```
####OutF
`Outf` is a shortcut to writing multiple `out` statement. You can give it a comma-separated list of expressions to output
```textfunge
out 99, 'a', "Hello World", var_1;
```
####In
With the `In` Statement you can ask the user for a value, the input routine differs when you give it a integer variable or a character variable.
```
var
int var_1;
char var_2;
begin
in var_1; // Asks for number
in var_2; // Asks for character
```

View File

@@ -0,0 +1,37 @@
In TextFunge you can optionally define a read- and writable display area.
```textfunge
program example_01 : display[16, 16]
```
The display has a width and a height and every field has initially the value you set in the options (the standard is space).
You can access the display with the `display[x, y]` command.
```textfunge
display[0, 0] = 'X'; // Write 'X' to position (0,0)
c = display[0, 1]; // Set c to the value of (0,1)
```
There are also a few automatically defined constants for teh work with displays:
```textfunge
DISPLAY_WIDTH // The width of the display
DISPLAY_HEIGHT // The height of the display
DISPLAY_SIZE // The size (width*height) of the display
```
You can use the display to
- display information to the user without using input commands
- gather a big amount of data from the user before execution (he has to fill the display manually)
- use it as a big 2-dimensional array for calculations
> **Note:**
> Beware that there is normally no mechanism to control access overflow.
> So you can enter to high/low x/y values and access/modify program pieces that are not part of the display.
> This is a way of bricking your program by writing in the area of program code
>
>**Tip:**
> You can prevent this by enabling the compiler option *Prevent display overflow*.
> But beware that tis will result in longer display access times.

View File

@@ -0,0 +1,37 @@
There are a few things you should consider when creating programs with Befunge:
###Number ranges
The size of the internal numbers is dependent on the interpreter, while you can safely assume that the number is at least 16bit, everything higher is not sure.
So for bigger programs you have to either work with smaller numbers or use interpreters which use bigger sizes.
> **Tip:**
> [BefunExec](/programs/view/BefunGen) uses 64bit integer (= long values).
###Negative numbers
A real problem are negative numbers. In created programs variables are saved in the grid.
If the interpreter does not support negative grid values you will not be able to use negative numbers.
But don't worry too much - most interpreters I know support negative numbers in the grid.
###Performance
BefunGen is definitely not a tool to create fast Befunge programs, it's a tool to create big ones.
And while it optimize your program quite a bit, a manual written program will always be faster and smaller.
So for bigger programs you will also need an fast interpreter - otherwise the execution could take a long time
> **Tip:**
> [BefunExec](/programs/view/BefunGen) is a pretty fast multi-threaded interpreter.
###Program size
While the generated programs are strictly bound to the Befunge-93, they can become pretty big (bigger than 80x25).
So you have to either use a Befunge-93 interpreter which ignores the size limit (many interpreters do that)
or use a Befunge-98 interpreter.
> **Tip:**
> [BefunExec](/programs/view/BefunGen), as you probably can assume, has no "real" size limit to it.

View File

@@ -0,0 +1,29 @@
Here a few tricks for programming with BefunGen:
###Horizontal size
Normally a program only grows in height, the more instructions your program has the greater is the height of the generated code.
So it is kinda bad when you have one really long line, because the width of the program is determined by the longest line.
So its good to try to avoid long lines for the sake of smaller - more compressed programs.
Here are a few common cases which compile to long single lines:
- Deep Nesting (e.g. multiple nested `for` loops)
- A lot of consecutive `elsif` statements
- `Switch` statements with a lot of cases
- Function calls with a lot of parameters
- Very long arrays
- Complex "one-line" statements (e.g. multiple nested method calls)
Neither of these things has any real consequence - except your program having a lot of empty space.
###Display as array
If you are in need of a really big array, or of a 2 dimensional array you can use the display for that.
The display is an easy way of having an **global** 2dimensional array, that is easily visible to the user.
###Constants
You can without hesitation use constants in your program, they are inlined on compilation and have no performance cost at all.

View File

@@ -0,0 +1,14 @@
###Hello World
A simple "Hello World"
```textfunge
program example
begin
out "Hello World\r\n";
quit;
end
end
```
> **Note:** *This and other examples are included in the BefunGen download*

View File

@@ -0,0 +1,77 @@
###Sieve of Erasthothenes
Calculates the primes between 0 and 19200 with the sieve of Erasthothenes
```textfunge
program SieveOfEratosthenes : display[240, 80]
begin
// Init all Fields with '?'
init();
// Set an 'X' to every Primenumberfield
calculate();
// Output the primes
output();
end
void init()
var
int i;
begin
for(i = 0; i < DISPLAY_SIZE; i++) do
display[i % DISPLAY_WIDTH, i / DISPLAY_WIDTH] = '?';
end
display[0, 0] = ' ';
display[1, 0] = ' ';
end
void calculate()
var
int i;
begin
for(i = 2; i < DISPLAY_SIZE; i++) do
doNumber(i);
end
end
void doNumber(int i)
var
char c;
begin
c = display[i % DISPLAY_WIDTH, i / DISPLAY_WIDTH];
if (c == 'X' || c == ' ') then
return;
elsif (c == '?') then
display[i % DISPLAY_WIDTH, i / DISPLAY_WIDTH] = 'X';
clear(i);
end
end
void clear(int n)
var
int p;
begin
for(p = 2*n; p < DISPLAY_SIZE; p += n) do
display[p % DISPLAY_WIDTH, p / DISPLAY_WIDTH] = ' ';
end
end
void output()
var
int i;
begin
out "Prime Numbers:\r\n";
for(i = 2; i < DISPLAY_SIZE; i++) do
if (display[i % DISPLAY_WIDTH, i / DISPLAY_WIDTH] == 'X') then
outf i, "\r\n";
end
end
end
end
```
> **Note:** *This and other examples are included in the BefunGen download*

View File

@@ -0,0 +1,43 @@
###The Euclidean algorithm
A simple, *recursive* implementation of the [euclidian algorithm](http://en.wikipedia.org/wiki/Euclidean_algorithm)
```textfunge
program EuclidianAlgo
var
int a, b, eucl;
begin
out "Please insert numer [a]\r\n";
in a;
out "Please insert numer [b]\r\n";
in b;
eucl = euclid(a, b);
outf "euclid(", a, ",", b, ") = ", eucl, "\r\n";
outf a, "/", b, " = ", (a/eucl), "/", (b/eucl), "\r\n";
quit;
end
int euclid(int a, int b)
begin
if (a == 0) then
return b;
else
if (b == 0) then
return a;
else
if (a > b) then
return euclid(a - b, b);
else
return euclid(a, b - a);
end
end
end
end
end
```
> **Note:** *This and other examples are included in the BefunGen download*

View File

@@ -0,0 +1,38 @@
###Fibonacci numbers
Calculates the [Fibonacci sequence](http://en.wikipedia.org/wiki/Fibonacci_number)
```textfunge
program Fibbonacci
var
int i;
begin
out "Input the maximum\r\n";
in i;
doFiber(i);
quit;
end
void doFiber(int max)
var
int last := 0;
int curr := 1;
int tmp;
begin
repeat
if (last > 0) then
out ",";
end
out curr;
tmp = curr + last;
last = curr;
curr = tmp;
until (last > max)
end
end
```
> **Note:** *This and other examples are included in the BefunGen download*

View File

@@ -0,0 +1,37 @@
###Fizz Buzz
A simple implementation of the [Fizz Buzz](http://en.wikipedia.org/wiki/Fizz_buzz) game.
```textfunge
program FizzBuzz
begin
fizzbuzz();
quit;
end
void fizzbuzz()
var
int i := 0;
begin
i = 1;
while (i < 100) do
if (i % 3 == 0 && i % 5 == 0) then
out "FizzBuzz";
elsif (i % 3 == 0) then
out "Fizz";
elsif (i % 5 == 0) then
out "Buzz";
else
out i;
end
out "\r\n";
i++;
end
end
end
```
> **Note:** *This and other examples are included in the BefunGen download*

View File

@@ -0,0 +1,107 @@
###PI Calculation
Calculates PI to a certain degree with the Monte Carlo algorithm
```textfunge
program PICalc : display[256, 256]
const
// WIDTH = HEIGHT = 4^SIZE
int SIZE := 4;
// Total Count
int COUNT := 65536;
// After n Steps print out intermediate result
int STEPS := 4096;
global
int hit;
int miss;
var
int i;
begin
hit = 0;
miss = 0;
for(i = 0; i < COUNT; i++) do
drop();
if (i % STEPS == 0) then
output();
end
end
output();
end
void output()
begin
// PI := (4 * hit)/(total)
outf "PI = ", (4*hit), "/", (hit+miss), " = ", floatDiv(4 * hit, miss + hit), "\r\n";
end
void drop()
var
int x, y;
char c;
begin
x = RAND[SIZE];
y = RAND[SIZE];
c = display[x, y];
display[x, y] = 'X';
if (c == '#') then
hit++;
elsif (c == ' ') then
miss++;
else
out "FATAL ERROR 0x01";
end
display[x, y] = c;
end
// Gives a string containing a/b as float back
char[10] floatDiv(int a, int b)
var
char[10] result;
int mantissa;
int pos := 0;
begin
mantissa = a / b;
repeat
if (pos == 10) then
return result;
end
result[pos++] = (char)((int)'0' + (mantissa % 10));
mantissa /= 10;
until (mantissa == 0)
if (pos == 10) then
return result;
end
result[pos++] = ',';
for(;;) do
if (pos == 10) then
return result;
end
a %= b;
a *= 10;
result[pos++] = (char)((int)'0' + (a / b));
end
return result;
end
end
```
> **Note:** This program needs a special initial display value to work - see the download to execute it.
> **Note:** *This and other examples are included in the BefunGen download*

View File

@@ -0,0 +1,285 @@
###Befunge-93 interpreter
An Befunge-93 interpreter
```textfunge
program BefInterpreter : display[60, 30]
const
int STACKSIZE := 16;
global
int[4] DELTA_IDX_X;
int[4] DELTA_IDX_Y;
bool running;
int PC_X;
int PC_Y;
int D_X;
int D_Y;
bool stringmode;
int[16] stack;
int stackHead;
begin
Init();
while (running) do
execute();
move();
end
quit;
end
void Init()
begin
DELTA_IDX_X[0] = 1;
DELTA_IDX_X[1] = 0;
DELTA_IDX_X[2] = -1;
DELTA_IDX_X[3] = 0;
DELTA_IDX_Y[0] = 0;
DELTA_IDX_Y[1] = -1;
DELTA_IDX_Y[2] = 0;
DELTA_IDX_Y[3] = 1;
stackHead = 0;
PC_X = 0;
PC_Y = 0;
D_X = 1;
D_Y = 0;
stringmode = false;
running = true;
end
void execute()
var
char c;
int tmp, tmp2, tmp3;
begin
c = display[PC_X, PC_Y];
if (stringmode && c != '"') then
push((int)c);
return;
end
switch(c)
begin
case ' ':
// NOP
end
case '0':
push(0);
end
case '1':
push(1);
end
case '2':
push(2);
end
case '3':
push(3);
end
case '4':
push(4);
end
case '5':
push(5);
end
case '6':
push(6);
end
case '7':
push(7);
end
case '8':
push(8);
end
case '9':
push(9);
end
end
switch(c)
begin
case '+':
push(pop() + pop());
end
case '-':
tmp = pop();
push(pop() - tmp);
end
case '*':
push(pop() * pop());
end
case '/':
tmp = pop();
push(pop() / tmp);
end
case '%':
tmp = pop();
push(pop() % tmp);
end
case '!':
push((int)(!popBool()));
end
case '`':
tmp = pop();
push((int)(pop() > tmp));
end
case '>':
D_X = 1;
D_Y = 0;
end
case '<':
D_X = -1;
D_Y = 0;
end
case '^':
D_X = 0;
D_Y = -1;
end
case 'v':
D_X = 0;
D_Y = 1;
end
case '?':
tmp = RAND[1];
D_X = DELTA_IDX_X[tmp];
D_Y = DELTA_IDX_Y[tmp];
end
end
switch(c)
begin
case '_':
if (popBool()) then
D_X = DELTA_IDX_X[2];
D_Y = DELTA_IDX_Y[2];
else
D_X = DELTA_IDX_X[0];
D_Y = DELTA_IDX_Y[0];
end
end
case '|':
if (popBool()) then
D_X = DELTA_IDX_X[1];
D_Y = DELTA_IDX_Y[1];
else
D_X = DELTA_IDX_X[3];
D_Y = DELTA_IDX_Y[3];
end
end
case '"':
stringmode = !stringmode;
end
case ':':
push(peek());
end
case '\\':
tmp = pop();
tmp2 = pop();
push(tmp);
push(tmp2);
end
case '$':
pop();
end
case '.':
out pop();
end
case ',':
out popChar();
end
case '#':
move();
end
case 'g':
tmp = pop();
tmp2 = pop();
if (tmp >= 0 && tmp2 >= 0 && tmp2 < DISPLAY_WIDTH && tmp < DISPLAY_HEIGHT) then
push((int)display[tmp2, tmp]);
else
push(0);
end
end
case 'p':
tmp = pop();
tmp2 = pop();
if (tmp >= 0 && tmp2 >= 0 && tmp2 < DISPLAY_WIDTH && tmp < DISPLAY_HEIGHT) then
display[tmp2, tmp] = popChar();
else
pop();
end
end
case '&':
in tmp;
push(tmp);
end
case '~':
in tmp3;
push((int)tmp3);
end
case '@':
out "\r\n\r\n >> FINISHED";
running = false;
end
default:
// NOP
end
end
end
void move()
begin
PC_X += D_X + DISPLAY_WIDTH;
PC_Y += D_Y + DISPLAY_HEIGHT;
PC_X %= DISPLAY_WIDTH;
PC_Y %= DISPLAY_HEIGHT;
end
void push(int v)
begin
stack[stackhead++] = v;
end
int pop()
begin
if (stackhead == 0) then
return 0;
end
return stack[--stackhead];
end
char popChar()
begin
return (char)pop();
end
bool popBool()
begin
return (bool)pop();
end
int peek()
begin
if (stackhead == 0) then
return 0;
end
return stack[stackhead - 1];
end
end
```
> **Note:** *This and other examples are included in the BefunGen download*

View File

@@ -0,0 +1,224 @@
###Sudoku Generator
Generates a random (but valid) Sudoku puzzle
```textfunge
program SudoGen : display[17, 17]
const
char CHR_EMPTY := ' ';
char CHR_UNKNOWN := ' ';
char CHR_BORDER := '#';
char CHR_INTERSECT := '+';
char CHR_HORZ := '-';
char CHR_VERT := '|';
begin
Init();
Create();
Obfuscate();
end
void Init()
var
int x, y;
begin
for (y = 0; y < DISPLAY_HEIGHT; y++) do
for (x = 0; x < DISPLAY_WIDTH; x++) do
if (x % 2 == 0 && y % 2 == 0) then
display[x, y] = CHR_EMPTY;
elsif ((x + 1) % 6 == 0 || (y + 1) % 6 == 0) then
display[x, y] = CHR_BORDER;
elsif ((x - 1) % 2 == 0 && (y - 1) % 2 == 0) then
display[x, y] = CHR_INTERSECT;
elsif ((x - 1) % 2 == 0 && y % 2 == 0) then
display[x, y] = CHR_VERT;
elsif (x % 2 == 0 && (y - 1) % 2 == 0) then
display[x, y] = CHR_HORZ;
end
end
end
end
bool Create()
var
int x, y;
int on;
int n;
begin
if (!IsValid()) then
return false;
end
on = rand[3] % 9;
for (y = 0; y < 9; y++) do
for (x = 0; x < 9; x++) do
if (display[x * 2, y * 2] == CHR_EMPTY) then
for (n = 0; n < 9; n++) do
display[x * 2, y * 2] = (char)((int)'1' + ((n + on) % 9));
if (Create()) then
return true;
end
display[x * 2, y * 2] = CHR_EMPTY;
end
return false;
end
end
end
return true;
end
bool IsValid()
var
int x, y;
int p;
int c;
int[9] vals;
begin
// Rows
for (y = 0; y < 9; y++) do
for (p = 0; p < 9; ) do
vals[p++] = 0;
end
for (x = 0; x < 9; x++) do
if (display[x * 2, y * 2] != CHR_EMPTY) then
vals[((int)display[x * 2, y * 2]) - ((int)'1')]++;
end
end
for (p = 0; p < 9; p++) do
if (vals[p] > 1) then
return false;
end
end
end
// Cols
for (x = 0; x < 9; x++) do
for (p = 0; p < 9; ) do
vals[p++] = 0;
end
for (y = 0; y < 9; y++) do
if (display[x * 2, y * 2] != CHR_EMPTY) then
vals[((int)display[x * 2, y * 2]) - ((int)'1')]++;
end
end
for (p = 0; p < 9; p++) do
if (vals[p] > 1) then
return false;
end
end
end
// Rects
for (c = 0; c < 9; c++) do
for (p = 0; p < 9; ) do
vals[p++] = 0;
end
for (x = (c / 3) * 3; x < (c / 3 + 1) * 3; x++) do
for (y = (c % 3) * 3; y < (c % 3 + 1) * 3; y++) do
if (display[x * 2, y * 2] != CHR_EMPTY) then
vals[((int)display[x * 2, y * 2]) - ((int)'1')]++;
end
end
end
for (p = 0; p < 9; p++) do
if (vals[p] > 1) then
return false;
end
end
end
return true;
end
bool isRemovable(int x, int y)
var
int v;
int p;
int rx, ry;
bool[9] vals;
begin
v = ((int)display[x * 2, y * 2]) - ((int)'1');
for (p = 0; p < 9; ) do
vals[p++] = false;
end
// Row
for (p = 0; p < 9; p++) do
if (display[p * 2, y * 2] != CHR_UNKNOWN) then
vals[((int)display[p * 2, y * 2]) - ((int)'1')] = true;
end
end
// Col
for (p = 0; p < 9; p++) do
if (display[x * 2, p * 2] != CHR_UNKNOWN) then
vals[((int)display[x * 2, p * 2]) - ((int)'1')] = true;
end
end
//Rect
for (rx = (x / 3) * 3; rx < (x / 3 + 1) * 3; rx++) do
for (ry = (y / 3) * 3; ry < (y / 3 + 1) * 3; ry++) do
if (display[rx * 2, rx * 2] != CHR_UNKNOWN) then
vals[((int)display[rx * 2, ry * 2]) - ((int)'1')] = true;
end
end
end
//Test
for (p = 0; p < 9; p++) do
if (!vals[p] && p != v) then
return false;
end
end
return true;
end
void Obfuscate()
var
int ox, oy;
int x, y;
begin
ox = rand[3];
oy = rand[3];
for (x = ox; x < ox + 9; x++) do
for (y = oy; y < oy + 9; y++) do
if (display[(x % 9) * 2, (y % 9) * 2] != CHR_UNKNOWN) then
if (isRemovable(x % 9, y % 9)) then
display[(x % 9) * 2, (y % 9) * 2] = CHR_UNKNOWN;
Obfuscate();
return;
end
end
end
end
return;
end
end
```
> **Note:** *This and other examples are included in the BefunGen download*

View File

@@ -0,0 +1,101 @@
###Conway's Game of Life
A simulation of [Conway's Game of Life](http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life)
```textfunge
program GameOfLife : display[40, 40]
const
char FIELD_UNSET := ' ';
char FIELD_SET := 'O';
char FIELD_PREBORN := 'o';
char FIELD_PREDEAD := 'Q';
begin
Init();
Run();
end
void Init()
var
int x, y;
begin
for (x = 0; x < DISPLAY_WIDTH; x++)
do
for (y = 0; y < DISPLAY_HEIGHT; y++)
do
if (display[x, y] != FIELD_UNSET) then
display[x, y] = FIELD_SET;
else
display[x, y] = FIELD_UNSET;
end
end
end
end
void Run()
var
int i := 0;
begin
for(;;i++) do
Tick();
OUTF "Tick Nr " , i , "\r\n";
end
end
void Tick()
var
int x, y;
int nc;
begin
for (x = 0; x < DISPLAY_WIDTH; x++) do
for (y = 0; y < DISPLAY_HEIGHT; y++) do
nc = GetNeighborCount(x, y);
if (display[x, y] == FIELD_SET) then
if (nc < 2) then // Underpopulation
display[x, y] = FIELD_PREDEAD;
elsif (nc > 3) then // Overcrowding
display[x, y] = FIELD_PREDEAD;
end
else
if (nc == 3) then // It lives !
display[x, y] = FIELD_PREBORN;
end
end
end
end
for (x = 0; x < DISPLAY_WIDTH; x++) do
for (y = 0; y < DISPLAY_HEIGHT; y++) do
if (display[x, y] == FIELD_PREBORN) then
display[x, y] = FIELD_SET;
elsif (display[x, y] == FIELD_PREDEAD) then
display[x, y] = FIELD_UNSET;
end
end
end
end
int GetNeighborCount(int x, int y)
var
int r;
begin
r = 0;
r += (int)(display[x - 1, y - 1] == FIELD_SET || display[x - 1, y - 1] == FIELD_PREDEAD);
r += (int)(display[x + 0, y - 1] == FIELD_SET || display[x + 0, y - 1] == FIELD_PREDEAD);
r += (int)(display[x + 1, y - 1] == FIELD_SET || display[x + 1, y - 1] == FIELD_PREDEAD);
r += (int)(display[x - 1, y + 0] == FIELD_SET || display[x - 1, y + 0] == FIELD_PREDEAD);
r += (int)(display[x + 1, y + 0] == FIELD_SET || display[x + 1, y + 0] == FIELD_PREDEAD);
r += (int)(display[x - 1, y + 1] == FIELD_SET || display[x - 1, y + 1] == FIELD_PREDEAD);
r += (int)(display[x + 0, y + 1] == FIELD_SET || display[x + 0, y + 1] == FIELD_PREDEAD);
r += (int)(display[x + 1, y + 1] == FIELD_SET || display[x + 1, y + 1] == FIELD_PREDEAD);
return r;
end
end
```
> **Note:** This programs needs the options `Safe Boolean Convert` and `Prevent Display Overflow` enabled
> **Note:** *This and other examples are included in the BefunGen download*

View File

@@ -0,0 +1,252 @@
###Maze Generator
Generates a Maze on the display with the [Hunt&Kill algorithm](http://weblog.jamisbuck.org/2011/1/24/maze-generation-hunt-and-kill-algorithm) - thens solves is by recursively trying every path
```textfunge
program MazeGen : display[131, 51]
const
char CHR_UNSET := '@';
char CHR_WALL := '#';
char CHR_FLOOR := ' ';
char CHR_PATH := '+';
var
bool succ;
begin
Init();
Create();
succ = Solve(1, 1, DISPLAY_WIDTH - 2, DISPLAY_HEIGHT - 2);
if (succ) then
out "Maze solved";
else
out "Fatal Error: Maze could not be solved";
end
end
void Init()
var
int x, y;
begin
for(x = 0; x < DISPLAY_WIDTH; x++) do
for(y = 0; y < DISPLAY_HEIGHT; y++) do
if (x == 0 || y == 0 || x == DISPLAY_WIDTH - 1 || y == DISPLAY_HEIGHT - 1 || (x % 2 == 0 && y % 2 == 0)) then
display[x,y] = CHR_WALL;
ELSE
display[x,y] = CHR_UNSET;
end
end
end
end
void Create()
begin
Kill(1, 1);
end
void Kill(int x, int y)
var
bool top;
bool left;
bool bot;
bool right;
int possibleDirections;
int direction;
begin
for(;;) do
top = (display[x + 0, y - 1] == CHR_UNSET);
left = (display[x - 1, y + 0] == CHR_UNSET);
bot = (display[x + 0, y + 1] == CHR_UNSET);
right = (display[x + 1, y + 0] == CHR_UNSET);
possibleDirections = 0;
possibleDirections += (int)top;
possibleDirections += (int)left;
possibleDirections += (int)bot;
possibleDirections += (int)right;
if (possibleDirections == 0) then
display[x, y] = CHR_FLOOR;
Hunt();
return;
end
direction = rand[3] % possibleDirections;
if (top) then
if (direction == 0) then
if (display[x, y + 1] == CHR_UNSET) then
display[x, y + 1] = CHR_WALL;
end
if (display[x + 1, y] == CHR_UNSET) then
display[x + 1, y] = CHR_WALL;
end
if (display[x - 1, y] == CHR_UNSET) then
display[x - 1, y] = CHR_WALL;
end
display[x, y] = CHR_FLOOR;
y--;
end
direction--;
end
if (left) then
if (direction == 0) then
if (display[x + 1, y] == CHR_UNSET) then
display[x + 1, y] = CHR_WALL;
end
if (display[x, y + 1] == CHR_UNSET) then
display[x, y + 1] = CHR_WALL;
end
if (display[x, y - 1] == CHR_UNSET) then
display[x, y - 1] = CHR_WALL;
end
display[x, y] = CHR_FLOOR;
x--;
end
direction--;
end
if (bot) then
if (direction == 0) then
if (display[x, y - 1] == CHR_UNSET) then
display[x, y - 1] = CHR_WALL;
end
if (display[x + 1, y] == CHR_UNSET) then
display[x + 1, y] = CHR_WALL;
end
if (display[x - 1, y] == CHR_UNSET) then
display[x - 1, y] = CHR_WALL;
end
display[x, y] = CHR_FLOOR;
y++;
end
direction--;
end
if (right) then
if (direction == 0) then
if (display[x - 1, y] == CHR_UNSET) then
display[x - 1, y] = CHR_WALL;
end
if (display[x, y + 1] == CHR_UNSET) then
display[x, y + 1] = CHR_WALL;
end
if (display[x, y - 1] == CHR_UNSET) then
display[x, y - 1] = CHR_WALL;
end
display[x, y] = CHR_FLOOR;
x++;
end
direction--;
end
end
end
void Hunt()
var
int ox, oy;
int fx, fy;
int x, y;
begin
ox = rand[6];
oy = rand[6];
ox %= DISPLAY_WIDTH;
oy %= DISPLAY_HEIGHT;
for (fy = 0; fy < DISPLAY_HEIGHT; fy++) do
for (fx = 0; fx < DISPLAY_WIDTH; fx++) do
x = (fx + ox) % DISPLAY_WIDTH;
y = (fy + oy) % DISPLAY_HEIGHT;
if (display[x, y] == CHR_UNSET) then
if (y > 1 && ((x) % 2 != 0 || (y - 1) % 2 != 0)) then
if (display[x, y - 1] == CHR_WALL && display[x, y - 2] == CHR_FLOOR) then
display[x, y - 1] = CHR_FLOOR;
Kill(x, y - 1);
return;
end
end
if (x > 1 && ((x - 1) % 2 != 0 || (y) % 2 != 0)) then
if (display[x - 1, y] == CHR_WALL && display[x - 2, y] == CHR_FLOOR) then
display[x - 1, y] = CHR_FLOOR;
Kill(x - 1, y);
return;
end
end
if (y < DISPLAY_HEIGHT - 2 && ((x) % 2 != 0 || (y + 1) % 2 != 0)) then
if (display[x, y + 1] == CHR_WALL && display[x, y + 2] == CHR_FLOOR) then
display[x, y + 1] = CHR_FLOOR;
Kill(x, y + 1);
return;
end
end
if (x < DISPLAY_WIDTH - 2 && ((x + 1) % 2 != 0 || (y) % 2 != 0)) then
if (display[x + 1, y] == CHR_WALL && display[x + 2, y] == CHR_FLOOR) then
display[x + 1, y] = CHR_FLOOR;
Kill(x + 1, y);
return;
end
end
end
end
end
end
bool Solve(int x, int y, int tx, int ty)
var
bool top, left, bot, right;
begin
top = display[x + 0, y - 1] == CHR_FLOOR;
left = display[x - 1, y + 0] == CHR_FLOOR;
bot = display[x + 0, y + 1] == CHR_FLOOR;
right = display[x + 1, y + 0] == CHR_FLOOR;
display[x, y] = CHR_PATH;
if (x == tx && y == ty) then
return true;
end
if (top) then
if (Solve(x, y - 1, tx, ty)) then
return true;
end
end
if (left) then
if (Solve(x - 1, y, tx, ty)) then
return true;
end
end
if (bot) then
if (Solve(x, y + 1, tx, ty)) then
return true;
end
end
if (right) then
if (Solve(x + 1, y, tx, ty)) then
return true;
end
end
display[x, y] = CHR_FLOOR;
return false;
end
end
```
> **Note:** *This and other examples are included in the BefunGen download*

View File

@@ -0,0 +1,500 @@
###Square It
An implementation of the game [Square It](http://en.wikipedia.org/wiki/Dots_and_Boxes). Complete with a computer opponent.
```textfunge
program Square_It : display[34, 36] // 1 + 1+2*16 || 1 + 1+2*16 + 2
const
int FIELD_WIDTH := 16;
int FIELD_HEIGHT := 16;
char CHAR_VERTICAL := '|';
char CHAR_HORIZONTAL := '-';
char CHAR_EMPTY := ' ';
char CHAR_JUNCTION := '+';
char CHAR_EMPTYFIELD := ' ';
char CHAR_PLAYER_P1 := 'X';
char CHAR_PLAYER_P2 := 'O';
char CHAR_PLAYER_NEUTRAL := '#';
global
char currPlayer;
int p1_c, p2_c;
begin
restart();
end
void restart()
var
int choice;
begin
for(;;) do
Init();
outf "WHAT DO YOU WANT TO PLAY?",
"\r\n",
"0: Player vs Player",
"\r\n",
"1: Player vs Computer",
"\r\n",
"2: Computer vs Computer",
"\r\n",
"\r\n",
"\r\n";
in choice;
if (choice == 0) then
Game_P_v_P();
elsif (choice == 1) then
Game_P_v_NP();
elsif (choice == 2) then
Game_NP_v_NP();
end
end
end
void Game_P_v_P()
var
char winner;
begin
currPlayer = CHAR_PLAYER_P1;
repeat
outf "PLAYER ", currPlayer, ":\r\n";
DoPlayerTurn();
until (GameFinished())
winner = GetWinningPlayer();
if (winner == CHAR_PLAYER_P1) then
out ">> PLAYER 1 (X) WINS !\r\n\r\n";
elsif (winner == CHAR_PLAYER_P2) then
out ">> PLAYER 2 (O) WINS !\r\n\r\n";
else
out ">> DRAW !\r\n\r\n";
end
return;
end
void Game_P_v_NP()
var
char winner;
begin
currPlayer = CHAR_PLAYER_P1;
repeat
if (currPlayer == CHAR_PLAYER_P1) then
outf "PLAYER ", currPlayer, ":\r\n";
DoPlayerTurn();
else
outf "COMPUTER ", currPlayer, ":\r\n";
DoComputerTurn();
end
until (GameFinished())
winner = GetWinningPlayer();
if (winner == CHAR_PLAYER_P1) then
out ">> YOU WIN !\r\n\r\n";
elsif (winner == CHAR_PLAYER_P2) then
out ">> YOU LOOSE !\r\n\r\n";
else
out ">> DRAW !\r\n\r\n";
end
return;
end
void Game_NP_v_NP()
var
char winner;
begin
currPlayer = CHAR_PLAYER_P1;
repeat
outf "COMPUTER ", currPlayer, ":\r\n";
DoComputerTurn();
until (GameFinished())
winner = GetWinningPlayer();
if (winner == CHAR_PLAYER_P1) then
out ">> PC1 (X) WINS !\r\n\r\n";
elsif (winner == CHAR_PLAYER_P2) then
out ">> PC2 (O) WINS !\r\n\r\n";
else
out ">> DRAW !\r\n\r\n";
end
return;
end
void Init()
var
int x, y;
int px, py;
begin
for(x = 0; x < FIELD_WIDTH; x++) do
if (x > 9) then
display[2 + x*2, 0] = (char)(x + (int)'7');
else
display[2 + x*2, 0] = (char)(x + (int)'0');
end
end
for(y = 0; y < FIELD_HEIGHT; y++) do
if (y > 9) then
display[0, 2 + y*2] = (char)(y + (int)'7');
else
display[0, 2 + y*2] = (char)(y + (int)'0');
end
end
for(x = 0; x < FIELD_WIDTH; x++) do
for(y = 0; y < FIELD_HEIGHT; y++) do
px = 2 + x*2;
py = 2 + y*2;
// CENTER
display[px + 0, py + 0] = CHAR_EMPTYFIELD;
// TOP RIGHT
display[px + 1, py + 1] = CHAR_JUNCTION;
// BOTTOM RIGHT
display[px - 1, py + 1] = CHAR_JUNCTION;
// BOTTOM LEFT
display[px - 1, py - 1] = CHAR_JUNCTION;
// TOP LEFT
display[px + 1, py - 1] = CHAR_JUNCTION;
// TOP
if (y == 0) then
display[px + 0, py - 1] = CHAR_HORIZONTAL;
else
display[px + 0, py - 1] = CHAR_EMPTY;
end
// RIGHT
if (x == FIELD_WIDTH - 1) then
display[px + 1, py + 0] = CHAR_VERTICAL;
else
display[px + 1, py + 0] = CHAR_EMPTY;
end
// BOTTOM
if (y == FIELD_HEIGHT - 1) then
display[px + 0, py + 1] = CHAR_HORIZONTAL;
else
display[px + 0, py + 1] = CHAR_EMPTY;
end
// LEFT
if (x == 0) then
display[px - 1, py + 0] = CHAR_VERTICAL;
else
display[px - 1, py + 0] = CHAR_EMPTY;
end
end
end
end
void DoPlayerTurn()
var
char x,y,d;
int ix, iy, idx, idy;
int posx, posy;
begin
out " ";
out "X: ";
in x;
out x;
out " Y: ";
in y;
out y;
out " Direction (U/D/L/R): ";
in d;
outf d, "\r\n";
if (x >= '0' && x <= '9') then
ix = (int)x - (int)'0';
elsif (x >= 'A' && x <= 'Z') then
ix = (int)x - (int)'A';
elsif (x >= 'a' && x <= 'z') then
ix = (int)x - (int)'a';
else
out " ";
out "ERROR - CANT PARSE INPUT (X)\r\n";
DoPlayerTurn();
return;
end
if (y >= '0' && y <= '9') then
iy = (int)y - (int)'0';
elsif (y >= 'A' && y <= 'Z') then
iy = (int)y - (int)'A';
elsif (y >= 'a' && y <= 'z') then
iy = (int)y - (int)'a';
else
out "ERROR - CANT PARSE INPUT (Y)\r\n";
DoPlayerTurn();
return;
end
if (d == 'U' || d == 'u') then
idx = 0;
idy = -1;
elsif (d == 'R' || d == 'r') then
idx = 1;
idy = 0;
elsif (d == 'D' || d == 'd') then
idx = 0;
idy = 1;
elsif (d == 'L' || d == 'l') then
idx = -1;
idy = 0;
else
out " ";
out "ERROR - CANT PARSE INPUT (DIRECTION)\r\n";
DoPlayerTurn();
return;
end
posx = 2 + ix*2 + idx;
posy = 2 + iy*2 + idy;
if (display[posx, posy] == CHAR_EMPTY) then
DoTurn(ix, iy, idx, idy);
return;
else
out " ";
out "ERROR - FIELD ALREADY SET\r\n";
DoPlayerTurn();
return;
end
end
void DoTurn(int x, int y, int dx, int dy)
var
int posx, posy;
bool t_a, t_b;
begin
posx = 2 + 2*x;
posy = 2 + 2*y;
if (dx == 0) then
display[posx + dx, posy + dy] = CHAR_HORIZONTAL;
else
display[posx + dx, posy + dy] = CHAR_VERTICAL;
end
t_a = testField(x, y);
t_b = testField(x + dx, y + dy);
if (! (t_a || t_b)) then
SwitchPlayer();
end
end
void DoComputerTurn()
begin
if (FindComputerTurn(3)) then
return;
end
if (FindComputerTurn(1)) then
return;
end
if (FindComputerTurn(0)) then
return;
end
if (FindComputerTurn(2)) then
return;
end
while (true) do out "ERROR"; end
end
bool FindComputerTurn(int target_surr)
var
int c_x, c_y;
int x, y;
int r_x, r_y, r_d;
int c_i, i;
int dx, dy;
begin
r_x = RAND[4];
r_y = RAND[4];
r_d = RAND[1];
for(c_x = 0; c_x < FIELD_WIDTH; c_x++) do
for(c_y = 0; c_y < FIELD_HEIGHT; c_y++) do
x = (c_x + r_x) % FIELD_WIDTH;
y = (c_y + r_y) % FIELD_HEIGHT;
if (getSurrounding(x, y) == target_surr) then
for(c_i = 0; c_i < 4; c_i++) do
i = (c_i + r_d) % 4;
switch(i)
begin
case 0:
dx = 0;
dy = -1;
end
case 1:
dx = 0;
dy = 1;
end
case 2:
dx = -1;
dy = 0;
end
case 3:
dx = 1;
dy = 0;
end
end
if (display[2+2*x + dx, 2+2*y + dy] == CHAR_EMPTY) then
switch(i)
begin
case 0:
outf " X: ", x, " Y: ", y, " D: [UP]", "\r\n";
end
case 1:
outf " X: ", x, " Y: ", y, " D: [DOWN]", "\r\n";
end
case 2:
outf " X: ", x, " Y: ", y, " D: [LEFT]", "\r\n";
end
case 3:
outf " X: ", x, " Y: ", y, " D: [RIGHT]", "\r\n";
end
end
DoTurn(x, y, dx, dy);
return true;
end
end
end
end
end
return false;
end
bool TestField(int x, int y)
var
bool result;
begin
x = 2 + x*2;
y = 2 + y*2;
result = true;
result &= (display[x, y] == CHAR_EMPTYFIELD);
result &= (display[x + 1, y] != CHAR_EMPTY);
result &= (display[x - 1, y] != CHAR_EMPTY);
result &= (display[x, y + 1] != CHAR_EMPTY);
result &= (display[x, y - 1] != CHAR_EMPTY);
if (result) then
display[x, y] = currplayer;
return true;
else
return false;
end
end
void SwitchPlayer()
begin
if (currplayer == CHAR_PLAYER_P1) then
currplayer = CHAR_PLAYER_P2;
else
currplayer = CHAR_PLAYER_P1;
end
display[DISPLAY_WIDTH - 9, DISPLAY_HEIGHT - 1] = 'P';
display[DISPLAY_WIDTH - 8, DISPLAY_HEIGHT - 1] = 'L';
display[DISPLAY_WIDTH - 7, DISPLAY_HEIGHT - 1] = 'A';
display[DISPLAY_WIDTH - 6, DISPLAY_HEIGHT - 1] = 'Y';
display[DISPLAY_WIDTH - 5, DISPLAY_HEIGHT - 1] = 'E';
display[DISPLAY_WIDTH - 4, DISPLAY_HEIGHT - 1] = 'R';
display[DISPLAY_WIDTH - 3, DISPLAY_HEIGHT - 1] = ' ';
display[DISPLAY_WIDTH - 2, DISPLAY_HEIGHT - 1] = currplayer;
display[1, DISPLAY_HEIGHT - 1] = (char)((p1_c/100)%10 + 48);
display[2, DISPLAY_HEIGHT - 1] = (char)((p1_c/10)%10 + 48);
display[3, DISPLAY_HEIGHT - 1] = (char)((p1_c/1)%10 + 48);
display[4, DISPLAY_HEIGHT - 1] = ' ';
display[5, DISPLAY_HEIGHT - 1] = '-';
display[6, DISPLAY_HEIGHT - 1] = ' ';
display[7, DISPLAY_HEIGHT - 1] = (char)((p2_c/100)%10 + 48);
display[8, DISPLAY_HEIGHT - 1] = (char)((p2_c/10)%10 + 48);
display[9, DISPLAY_HEIGHT - 1] = (char)((p2_c/1)%10 + 48);
end
int GetSurrounding(int x, int y)
var
int result;
begin
result = 0;
x = 2 + x*2;
y = 2 + y*2;
result += (int)(display[x + 1, y] != CHAR_EMPTY);
result += (int)(display[x - 1, y] != CHAR_EMPTY);
result += (int)(display[x, y + 1] != CHAR_EMPTY);
result += (int)(display[x, y - 1] != CHAR_EMPTY);
return result;
end
bool GameFinished()
var
int x, y;
begin
p1_c = 0;
p2_c = 0;
for(x = 0; x < FIELD_WIDTH; x++) do
for(y = 0; y < FIELD_HEIGHT; y++) do
if (display[2+2*x, 2+2*y] == CHAR_PLAYER_P1) then
p1_c++;
elsif (display[2+2*x, 2+2*y] == CHAR_PLAYER_P2) then
p2_c++;
end
end
end
return p1_c + p2_c == FIELD_WIDTH * FIELD_HEIGHT;
end
char GetWinningPlayer()
begin
if (p1_c > p2_c) then
return CHAR_PLAYER_P1;
elsif (p1_c < p2_c) then
return CHAR_PLAYER_P2;
else
return CHAR_PLAYER_NEUTRAL;
end
end
```
> **Note:** *This and other examples are included in the BefunGen download*

View File

@@ -0,0 +1,133 @@
This is my collection of tools and libraries for the esoteric programming language [Befunge](http://esolangs.org/wiki/Befunge).
IT consists of the following components:
###[BefunGen](https://github.com/Mikescher/BefunGen):
A library to automatically generate Befunge-93 programs out of a imperative-programming-language
###[BefunGenTest](https://github.com/Mikescher/BefunGenTest):
A test set for BefunGen
###[BefunWrite](https://github.com/Mikescher/BefunWrite):
A samll editor for Textfunge, the language used by BefunGen - use this if you want to try BefunGen for yourself
###[BefunHighlight](https://github.com/Mikescher/BefunHighlight):
A dynamic Befunge-93 syntax highlighting library. Highlights your sourcecode intelligent and context-sensitive
###[BefunExec](https://github.com/Mikescher/BefunExec):
A (fast) Befunge-93 interpreter and debugger
###[BefunRep](https://github.com/Mikescher/BefunRep):
A tool to calculate (the best) number-representation in Befunge-93 space
&nbsp;
> **NOTE:**
>
> If you don't know the esoteric language Befunge I can refer you to the [esolang page](http://esolangs.org/wiki/Befunge) and my own [tutorial](/blog/2/Lets_do_Befunge93)
## BefunWrite
BefunWrite is the main program that uses all the other parts.
It's an IDE in which you can write a program in *TextFunge*, and compile it to valid Befunge-98 code.
> **NOTE:**
>
> While the generated Code practically is Befunge-98, you can use it in nearly every Befunge-93 interpreter.
> Because it doesn't use a single command, which was not defined in Befunge-93, the only non-Befunge-93 feature is the extended file size.
> Because this tool can generate fairly big Befunge-93 code, it often exceeds the size of 80x25, and is so no longer totally valid Befunge-93 code.
> But for the sake of confusion I will refer in the rest of these documents to it as Befunge-93 code.
In BefunWrite you write your source code in the, specially for this developed, language **TextFunge**.
BefunWrite supports you in this process with a lot of the basic IDE features you already know from other IDE's.
After written you can compile your TextFunge code into BEfunge-93 code and execute it in **BefunExec**.
The main advantage for you is how you can easily generate even complex programs in Befunge.
Because TextFunge supports all the basic features of a procedural language you can use constructs like:
- if-clauses and switch-cases
- for-loops, while-loops, repeat-until-loops
- methods
- recursion
- global and local variables with different data-types
- GOTO's
- arithmetical and logical expressions
BefunWrite also provides an easy interface for the multiple compiler-settings, for more information please visit the individual manuals.
## BefunGen
BefunGen is the core of this compilations. It's a compiler for for TextFunge and a code generator for Befunge.
Essentially it performs the conversion between TextFunge and Befunge. Most of the generated Befunge programs could be a lot smaller if an actual person would take the time writing them.
That is the case because the generated Befunge code has a lot of organisation code included. It needs to manage the global variables and also the local ones. The local variables need initialization and in case of a different method call their current state needs to be saved. Also there has to be a call-stack to return to previous methods and re-initialization code when you jump back into methods.
This is important to understand, while I always try to optimize the generated code as much as I can it will always be a good amount bigger (and slower) than actual human-made code. This is also the case because there are neat little "tricks" and design concepts in Befunge that you just can't express in a procedural language.
But thats not really the problem, because the target of BefunGen is **not** generate code that could also be made by hand. The target code size is code so big that it would be totally impractical to write by hand (without spending days and weeks on it).
BefunGen itself is not a standalone program, but a simple library. You are free to use the DLL in your own program (but beware of the license, please give me credits...). If you need help how to use it you can either simply look at the source code (of BefunGen or BefunWrite) or write me a friendly mail.
## BefunExec
BefunExec is a fast Befunge-93 interpreter (without any program-size limitations) and a simple tool to execute and debug the generated Befunge-93 files.
While developing BefunGen I encountered the problem that not many interpreters where able to execute my programs.
Because of the properties of my generated code I needed an interpreter that was
- really fast, it needed to execute really many executions per second
- able to open and display large to *extremely* large programs
- able too zoom in programs (because they can be large)
- able to debug the program (show stack, output, input, breakpoints, single-step ...)
As you can imagine, I didn't find an interpreter that fitted my needs and so I wrote my own.
The big point that makes BefunExec unique is it's very high speed. On my machine (and its not really a good one) I reach a maximum speed of **6.5 MHz**. This are over **6 million** executions per second, enough for most of my programs :D.
Some other features are (as stated above) the ability to set breakpoints, step slowly through the program and zoom into specific parts.
Also you are able to capture the program execution as a gif animation.
One other big feature is the integration of BefunHighlight, which will be explained in the BefunHighlight section below.
## BefunHighlight
BefunHighlight is just a helper library mainly for BefunExec.
BefunExec has normal Befunge syntax-highlighting implemented, that means that every character is colored based on its function.
The problem here is that there may be code that never gets executed (not part of the real program), or there may be code that only gets used inside of string-mode (so the function doesn't matter, only the ASCII value).
BefunHighlight tries to solve this by evaluating every possible path an program can execute and so calculating the ways a single command is used.
Based on these informations it's now possible for another program to better highlight the source code.
Be aware that **p**ut and **g**et operations will invalidate the calculated values and it is needed to update them.
## BefunRep
A common problem with Befunge is the *(efficient)* representation of big numbers. *(= putting a number on the stack with the least amount of instructions)*
BefunRep is a commandline tool to generate a list of representations for all numbers in a specified range. I'm pretty sure the calculation of the optimal representation is a NP complete. But BefunRep tries to to find good representations for all numbers via various algorithms. And it does a pretty good job. It finds for all the numbers between -1 million and +1 million representations with a maximum of eleven characters.
Here an example call to BefunRep:
> **\> BefunRep.exe -lower=0 -upper=1000 -iterations=3 -stats=3 -q -safe="safe.bin" -out="out.csv" -reset**
This calculates the numbers from **0** to **1000**.
With a maximum of **3** iterations *(use -1 to calculate until no more improvmenets can be found)*
Safe the results in binary format in the file **safe.bin**
If the safe already exists it will be reseted (-**reset**)
And exports the results readable to **out.csv**
You can also update an existing safe
> **\> BefunRep.exe -safe="safe.bin" -iterations=-1**
Or don't calculate anything and only output an existing safe into another format
> **\> BefunRep.exe -safe="safe.bin" -iterations=0 -stats=3 -out="out.json"**
Here an example of a few calculated values:
Number | Representation
-------|----------------
113564 | `"tY!"**3/`
113565 | `"qC-"**3/`
113566 | `"[' "**2-`
113567 | `"[' "**1-`
113568 | `"[' "**`
113569 | `"~~U"++:*`
113570 | `"[' "**2+`
113571 | `"wj"*5+9*`
113572 | `"[' "**4+`
113573 | `"[' "**5+`
113574 | `"E~(&"*+*`