Using Bocfel on Discord

3 views
Skip to first unread message

Andrew Plotkin

unread,
Jun 7, 2025, 2:46:03 PMJun 7
to gargl...@googlegroups.com
I have been experimenting with getting Glulxe and Bocfel running in a
Discord bot. You can see the bot running on the IFTF Discord in the
#zarfbot-9000 channel.

I've had to make some changes to Bocfel for this environment. It's tricky
because I'm using remglk's -singleturn option. That is, the interpreter is
not launched until a command comes in, and then it does:

- launch
- autorestore
- accept input
- generate output
- autosave
- shut down

So the interpreter is never suspended waiting for input. This is great
for avoiding RAM load on the server, but there are a lot of fussy details
to work through.

My dev repository is at https://github.com/erkyrath/bocfel ("autosave"
branch). I will eventually turn this into a PR (or several) on the Garglk
repo, but it's not ready for prime time yet. Many bugs remain.

I'm working off of 2.2.4 (because I started this last week!) I haven't
touched the graphics code though -- my bot doesn't support graphics at
all -- so I don't anticipate any merge problems.

--Z

--
"And Aholibamah bare Jeush, and Jaalam, and Korah: these were the borogoves..."
*

Chris Spiegel

unread,
Jun 7, 2025, 8:31:04 PMJun 7
to gargl...@googlegroups.com
This is very cool, and I'll happily merge in changes once you have them ready.

In what has widely been regarded as a bad move, all Bocfel development is done locally in a private Git repo; so while I'd have no problem with PRs against Gargoyle, what I'd do with those is reapply them locally for the next Bocfel release, and pull _that_ into Gargoyle.

If it's just as easy for you, I can add your repo as remote locally here and merge changes directly from whatever branch(es) you have when you're ready. For my part, I'd prefer having your changes in my repo be actual commits from you instead of me just reproducing them, as it'd feel a bit more organic.

Andrew Plotkin

unread,
Jun 7, 2025, 11:00:35 PMJun 7
to Chris Spiegel, gargl...@googlegroups.com
On Sat, 7 Jun 2025, Chris Spiegel wrote:

> If it's just as easy for you, I can add your repo as remote locally here
> and merge changes directly from whatever branch(es) you have when you're
> ready.

Sure, that's fine.

Andrew Plotkin

unread,
Jun 15, 2025, 6:29:19 PMJun 15
to Chris Spiegel, gargl...@googlegroups.com
On Sat, 7 Jun 2025, Chris Spiegel wrote:

> This is very cool, and I'll happily merge in changes once you have them
> ready.

This is settled enough for me to offer up the changes. What's the easiest
way for me to do it?

Currently, in https://github.com/erkyrath/bocfel , the master branch is
2.2.4 and the autosave branch is what I'm using. I could divide up the
changes a bit...

- config env vars: I added a Options::read_envvars() function which checks
the environment for every config var in the m_from_config list
(capitalized). So you could set BOCFEL_AUTOSAVE=1 instead of putting
"autosave 1" in a config file. Same for every other config name.

- Then added some new config vars: BOOL skip_autorestore, STRING
autosave_directory, BOOL autosave_librarystate.

- If autosave_directory is set, we autosave there instead of
SETTINGS/bocfel/autosave/FILE.

- When autosave_librarystate is true, we use a new SaveType::AutosaveLib.
This is like Autosave except that we tell the library (RemGlk) to save all
of *its* state in an auxiliary autosave file. Then on autorestore, we come
back with all the windows already open, the transcript stream (if any)
live, etc. This affects various details of the save/restore process.

- We autosave in zsave() and zrestore(). What? Huh? Well, if the
interpreter is about to call glk_fileref_create_by_prompt() for the save
file name, I gotta autosave so that I can relaunch to that point later
when the filename comes in. (This means that the SaveOpcode enum has more
cases.)

- rock support: load_file() in glkstart.cpp and the IO() constructor have
optional StreamRock arguments. (StreamRock is an enum type.) Same for
IO::open_as_glk()

- We also have a WindowRock enum for windows.

- transcript stream: The transio object is handled somewhat differently
when autosave_librarystate is true). We use a Glk stream (rather than a
stdio stream) because we want to record and recover it in the libautosave.
We also discard and close it on SCRIPT OFF, rather than leaving it sitting
around open forever.

- We call glk_set_interrupt_handler() with a function that closes transio
at shutdown time. This is a pain in the ass which avoids a double-free
segfault.

I don't mean to divide this up into a dozen PRs, but there's a few logical
division points.

Not yet implemented:

- Include the UNDO state in SaveType::AutosaveLib. (Maybe in
SaveType::Autosave as well.)

- Autosave on the zsave5() / zrestore5() cases that have table arguments,
i.e. they don't just call through to zsave() / zrestore().

Chris Spiegel

unread,
Jun 16, 2025, 10:38:11 AMJun 16
to Andrew Plotkin, gargl...@googlegroups.com
> This is settled enough for me to offer up the changes. What's the easiest
way for me to do it?

I'll be merging directly from your branch/branches into master here;
so it's just a matter of you pointing me to whatever branches need to
be merged. That could be the autosave branch as-is, or if you'd
prefer, you can rewrite history into a few commits that represent
specific changes, or create separate branches for those logical
divisions.

Effectively, a PR here is just you saying "merge branch A [then B,
then C, ...]".

Chris Spiegel

unread,
Jun 18, 2025, 3:14:04 PMJun 18
to Andrew Plotkin, Andrew Plotkin, gargl...@googlegroups.com
Looks good, and it's now merged into master here. It'll be included
with the next (non-point) release.

Thanks!
Reply all
Reply to author
Forward
0 new messages