From 03e0ae32147c194b88f48ae364a2430b4500e82d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20Schw=C3=B6rer?= Date: Wed, 16 Jul 2014 19:10:02 +0200 Subject: [PATCH] More BefunGen desc --- .../BefunGen/02_TextFunge/02_Display.markdown | 37 ++ .../02_TextFunge/03_Limitations.markdown | 37 ++ .../02_TextFunge/04_Tips and Tricks.markdown | 29 + .../03_Examples/01_Hello World.markdown | 14 + .../02_Sieve of Eratosthenes.markdown | 77 +++ .../03_Euclidian Algorithm.markdown | 43 ++ .../03_Examples/04_Fibonacci Numbers.markdown | 38 ++ .../03_Examples/04_Fizz Buzz.markdown | 37 ++ .../BefunGen/03_Examples/06_PI Calc.markdown | 107 ++++ .../07_Befunge-93 interpreter.markdown | 285 ++++++++++ .../03_Examples/08_Sudoku Gen.markdown | 224 ++++++++ .../03_Examples/09_Game of Life.markdown | 101 ++++ .../BefunGen/03_Examples/10_Maze Gen.markdown | 252 +++++++++ .../03_Examples/11_Square It.markdown | 500 ++++++++++++++++++ 14 files changed, 1781 insertions(+) create mode 100644 www/data/programs/desc/BefunGen/03_Examples/01_Hello World.markdown create mode 100644 www/data/programs/desc/BefunGen/03_Examples/02_Sieve of Eratosthenes.markdown create mode 100644 www/data/programs/desc/BefunGen/03_Examples/03_Euclidian Algorithm.markdown create mode 100644 www/data/programs/desc/BefunGen/03_Examples/04_Fibonacci Numbers.markdown create mode 100644 www/data/programs/desc/BefunGen/03_Examples/04_Fizz Buzz.markdown create mode 100644 www/data/programs/desc/BefunGen/03_Examples/06_PI Calc.markdown create mode 100644 www/data/programs/desc/BefunGen/03_Examples/07_Befunge-93 interpreter.markdown create mode 100644 www/data/programs/desc/BefunGen/03_Examples/08_Sudoku Gen.markdown create mode 100644 www/data/programs/desc/BefunGen/03_Examples/09_Game of Life.markdown create mode 100644 www/data/programs/desc/BefunGen/03_Examples/10_Maze Gen.markdown create mode 100644 www/data/programs/desc/BefunGen/03_Examples/11_Square It.markdown diff --git a/www/data/programs/desc/BefunGen/02_TextFunge/02_Display.markdown b/www/data/programs/desc/BefunGen/02_TextFunge/02_Display.markdown index e69de29..82f938d 100644 --- a/www/data/programs/desc/BefunGen/02_TextFunge/02_Display.markdown +++ b/www/data/programs/desc/BefunGen/02_TextFunge/02_Display.markdown @@ -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. \ No newline at end of file diff --git a/www/data/programs/desc/BefunGen/02_TextFunge/03_Limitations.markdown b/www/data/programs/desc/BefunGen/02_TextFunge/03_Limitations.markdown index e69de29..9a36b18 100644 --- a/www/data/programs/desc/BefunGen/02_TextFunge/03_Limitations.markdown +++ b/www/data/programs/desc/BefunGen/02_TextFunge/03_Limitations.markdown @@ -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. diff --git a/www/data/programs/desc/BefunGen/02_TextFunge/04_Tips and Tricks.markdown b/www/data/programs/desc/BefunGen/02_TextFunge/04_Tips and Tricks.markdown index e69de29..5517860 100644 --- a/www/data/programs/desc/BefunGen/02_TextFunge/04_Tips and Tricks.markdown +++ b/www/data/programs/desc/BefunGen/02_TextFunge/04_Tips and Tricks.markdown @@ -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. diff --git a/www/data/programs/desc/BefunGen/03_Examples/01_Hello World.markdown b/www/data/programs/desc/BefunGen/03_Examples/01_Hello World.markdown new file mode 100644 index 0000000..272fa42 --- /dev/null +++ b/www/data/programs/desc/BefunGen/03_Examples/01_Hello World.markdown @@ -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* \ No newline at end of file diff --git a/www/data/programs/desc/BefunGen/03_Examples/02_Sieve of Eratosthenes.markdown b/www/data/programs/desc/BefunGen/03_Examples/02_Sieve of Eratosthenes.markdown new file mode 100644 index 0000000..358deb7 --- /dev/null +++ b/www/data/programs/desc/BefunGen/03_Examples/02_Sieve of Eratosthenes.markdown @@ -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* \ No newline at end of file diff --git a/www/data/programs/desc/BefunGen/03_Examples/03_Euclidian Algorithm.markdown b/www/data/programs/desc/BefunGen/03_Examples/03_Euclidian Algorithm.markdown new file mode 100644 index 0000000..8821517 --- /dev/null +++ b/www/data/programs/desc/BefunGen/03_Examples/03_Euclidian Algorithm.markdown @@ -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* \ No newline at end of file diff --git a/www/data/programs/desc/BefunGen/03_Examples/04_Fibonacci Numbers.markdown b/www/data/programs/desc/BefunGen/03_Examples/04_Fibonacci Numbers.markdown new file mode 100644 index 0000000..2510f31 --- /dev/null +++ b/www/data/programs/desc/BefunGen/03_Examples/04_Fibonacci Numbers.markdown @@ -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* \ No newline at end of file diff --git a/www/data/programs/desc/BefunGen/03_Examples/04_Fizz Buzz.markdown b/www/data/programs/desc/BefunGen/03_Examples/04_Fizz Buzz.markdown new file mode 100644 index 0000000..974a7f4 --- /dev/null +++ b/www/data/programs/desc/BefunGen/03_Examples/04_Fizz Buzz.markdown @@ -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* \ No newline at end of file diff --git a/www/data/programs/desc/BefunGen/03_Examples/06_PI Calc.markdown b/www/data/programs/desc/BefunGen/03_Examples/06_PI Calc.markdown new file mode 100644 index 0000000..da5479c --- /dev/null +++ b/www/data/programs/desc/BefunGen/03_Examples/06_PI Calc.markdown @@ -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* \ No newline at end of file diff --git a/www/data/programs/desc/BefunGen/03_Examples/07_Befunge-93 interpreter.markdown b/www/data/programs/desc/BefunGen/03_Examples/07_Befunge-93 interpreter.markdown new file mode 100644 index 0000000..d8a799f --- /dev/null +++ b/www/data/programs/desc/BefunGen/03_Examples/07_Befunge-93 interpreter.markdown @@ -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* \ No newline at end of file diff --git a/www/data/programs/desc/BefunGen/03_Examples/08_Sudoku Gen.markdown b/www/data/programs/desc/BefunGen/03_Examples/08_Sudoku Gen.markdown new file mode 100644 index 0000000..a059b8c --- /dev/null +++ b/www/data/programs/desc/BefunGen/03_Examples/08_Sudoku Gen.markdown @@ -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* \ No newline at end of file diff --git a/www/data/programs/desc/BefunGen/03_Examples/09_Game of Life.markdown b/www/data/programs/desc/BefunGen/03_Examples/09_Game of Life.markdown new file mode 100644 index 0000000..785466e --- /dev/null +++ b/www/data/programs/desc/BefunGen/03_Examples/09_Game of Life.markdown @@ -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* \ No newline at end of file diff --git a/www/data/programs/desc/BefunGen/03_Examples/10_Maze Gen.markdown b/www/data/programs/desc/BefunGen/03_Examples/10_Maze Gen.markdown new file mode 100644 index 0000000..c8926df --- /dev/null +++ b/www/data/programs/desc/BefunGen/03_Examples/10_Maze Gen.markdown @@ -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* \ No newline at end of file diff --git a/www/data/programs/desc/BefunGen/03_Examples/11_Square It.markdown b/www/data/programs/desc/BefunGen/03_Examples/11_Square It.markdown new file mode 100644 index 0000000..c0da7f1 --- /dev/null +++ b/www/data/programs/desc/BefunGen/03_Examples/11_Square It.markdown @@ -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* \ No newline at end of file