Fungeball
Designed by | Sara Berman (User:Lykaina) |
---|---|
Appeared in | 2023 |
Computational class | Unknown |
Reference implementation | https://lykaina.github.io/fungeball/ |
File extension(s) | .bft |
A two-dimensional "multi-threaded" language based on Befunge-93 implementing a subset of commands from Funge-98 to allow for a similar form of threading to what Funge-98 uses.
Thought up in March 2023, development was stagnant for almost two years and resumed with a fresh start in February 2025 after author discovered that Funge-98 is a lot harder to write an interpreter for in MicroPython-compliant Python than Befunge-93 is.
Instructions
Fungeball has all of the same commands as Befunge-93, plus these:
(Technically, '@' is closer to the Funge-98 version than the Befunge-93 version, so it is in this list.)
Note: Anything described as (Experimental) has not yet been debugged and should be avoided until no longer experimental.
Cmd | Description |
---|---|
@
|
End Thread: Ends any thread that touches it. If no threads are left, the program quits with a return code of 0. |
a
|
Hex-A: Push decimal value 10 to thread stack. |
b
|
Hex-B: Push decimal value 11 to thread stack. |
c
|
Hex-C: Push decimal value 12 to thread stack. |
d
|
Hex-D: Push decimal value 13 to thread stack. |
e
|
Hex-E: Push decimal value 14 to thread stack. |
f
|
Hex-F: Push decimal value 15 to thread stack. |
h
|
Hex: Pop b,a from thread stack and Push a*16+(b%16) to thread stack. |
i
|
Push to Common Stack: Pop b, a from thread stack and then Push a to common stack b%16. |
j
|
Jump: Pop y,x,d, move to location x,y on playfield, use d as delta in format deg/90. |
k
|
Keep At: Pop a, Do Nothing, not even move, until there are no 'threads' with label value a. |
l
|
Label: Pop a, (Re-)Label 'thread' with value a. |
m
|
Clear a Common Stack: Pop a, Clear Common Stack (a%16). |
n
|
Clear Stack: Clears thread stack. |
o
|
Pop from Common Stack: Pop b from thread stack, Pop a from common stack b%16, and then Push a to thread stack. |
q
|
Quit: Pop r then quit the program with a return code of abs(r)%256. |
r
|
Reverse: Reverses Delta (180-degree turn) |
s
|
Load Grid and Restart: (Experimental) Read xmax*ymax bytes from input and store to playfield, and reinitialize program. |
t
|
Split: Start a new thread travelling in the direction 180 degrees from current. |
u
|
Get Delta: Push delta to thread stack in format deg/90 |
w
|
Wait: Pop a, Do Nothing, not even move, until there are at most (a+1) threads. |
x
|
Hex with 8-bit output: Pop b,a from thread stack and Push (a%16)*16+(b%16) to thread stack. |
y
|
Set Delta: Pop a, set delta to a in format deg/90. |
z
|
No Op: Does Nothing except use up a cycle. |
Examples
Hello, World!
This one was used to verify that threading was working:
" ,olleH">:#,_#vt@ v "World!"*25n< >:#,_@
This one and equivalents are the fastest possible where the threads split after 'cycle' 2 and still provide the correct output: (Timing is hard when 'multi-threading'...)
#vt" ,olleH">:#,_@ >zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz25*"!dlroW">:#,_@
This one is almost the same as above, but uses a '0w' instead of a bunch of 'z's:
#vt" ,olleH">:#,_@ >0w25*"!dlroW">:#,_@
This one uses the first common stack as a temporary space before outputting, and uses 'a' instead of '25*':
#vt"Hello, World!"a>:#i #0_@ >0w>0# o# :#,_@
Same as above, but a single 'thread':
"Hello, World!"a>:#i #0_>0# o# :#,_@
Test of 'k' and 'l':
#vt1l"Hello, World!"a>:#i #0_@ >1k>0# o# :#,_@
Implementation Notes
Compatibility
Befunge-93
Fungeball should be able to execute any Befunge-93 program.
Funge-98
Despite sharing some commands with Funge-98, Fungeball programs should not be run in Funge-98 interpreters and vice-versa.
Threading
Each child 'thread' starts with a copy of its parent's stack and location, a delta 180 degrees from that of its parent, and has its String Mode and Wait Mode flags set to False.
During a 'cycle', each thread completes one 'tick', or command.
The amount of 'ticks' per 'cycle' is the current number of 'threads'.
'Threads' are executed in series, in an unspecified order, so take care to write so that at most one 'thread' is editing the shared playfield, reading shared input, or writing to shared output in a cycle.
Common Stacks
While each 'thread' has its own stack, there are also 16 common stacks, intended as a way for communications between 'threads' to occur.
A common stack can also be used for other things, such as an output buffer.
Spaces, Double Quotes, No Ops, and String Mode
Spaces, when not in String Mode, are passed over. (i.e. do not count as ticks)
Double Quotes, which shift between normal operation and String Mode, do take up a tick each in this implementation.
No Ops do take up a tick.
String Mode uses as many ticks as there are chars in the string, plus the two ticks for each double quote.
Versions
GitHub Versions
v1.0-beta7: Fixes bug in 'k', adds 'j', 'm', 'r', 's', 'u', and 'y'.
v1.0-beta6: Adds 'h','k','l', and 'x', and changes 'w' slightly.
v1.0-beta5a: Adds 'a' - 'f', fixes 'i' and 'o' to provide for 16 common stacks.
v1.0-beta5: Adds 'i', 'o', 'w', and a separate common stack.
v1.0-beta4: Fixed the bug that accidentally caused a shared stack.
v1.0-beta3: Fungeball release now bundled with a Befunge-93 interpreter as well, along with example programs I wrote.
Pre-GitHub Versions
1.0b3: Fungeball release is now two files: library and wrapper.
1.0b2: Stream I/O is implemented better now.
1.0b1: String Mode bug fixed.
1.0b0: Thought it would work, but not everything has been tested. There is a bug involving an accidental global String Mode.