1
0

More BefunGen desc

This commit is contained in:
Mike Schwörer 2014-07-16 19:10:02 +02:00
parent 14f3d5df3b
commit 03e0ae3214
14 changed files with 1781 additions and 0 deletions

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*