Dialog Wishlist

Yeah me too.

1 Like

I think I have, for the moment—on Linux, Mac, or BSD, I just read 128 bits from /dev/urandom, on Windows I use CryptGenRandom to get those same 128 bits. In this case, having a good PRNG within the program isn’t important: what’s important is getting those 128 bits of entropy, since we never need to produce more than one IFID per compiler run. So xoshiro and such aren’t helpful; the output of calling it only once per run can never be more random than the seed that’s put in, and could be less.

That’s also why rand() isn’t suitable here, since by the spec it can only have as much entropy as the bit width of an int (minimum 16, usually 32, very rarely 128). Most PRNGs aren’t designed to get a whole bunch of randomness all at once and then never again.

The “u” stands for “really”!

Oh, I didn’t mean you should copy their xorshiro implementation, just that arc4random etc are useful to know about.

Ah, yes! Definitely agreed there. The reason I went with /dev/urandom over arc4random is that it seems to be more widely supported, and will generally be the highest-quality entropy source the system can provide. It’s only really Windows that has a command line and doesn’t have a /dev/urandom. But if I hadn’t found a recommended open-source implementation that used /dev/urandom (reassuring me it was reliable), I probably would have taken that route.

Seeing as you’re already using file system code there’s probably no reason not to read from /dev/urandom. If you weren’t including FS already then using the function APIs might be better.

On further reflection, yes, this makes sense. But I also don’t want to give people additional footguns—Dialog generally tries not to do that as a rule.

So I can think of two straightforward ways of implementing this:

  • A --reproducible switch that replaces the serial number with something like XDEBUG. Good for testing, but it’s clear that people shouldn’t be using this to ship their actual games.
  • A --serial option that lets you set the serial number to anything you want, but also prints a warning on every compile saying this shouldn’t be done without a good reason.

Mostly, I don’t want people seeing this option, going “oh I should set my serial number once and keep it from ever changing again”, and making archiving an enormous pain for everyone else.

3 Likes

The second option (--serial) would be preferable because this isn’t just for testing purposes, and printing the warning when using the option is absolutely fine.

FWIW, I agree that letting the user set the serial number would be a small kindness… determinism does matter to some folks / in some environments. We could always give it a more verbose flag name like --override-serial if we want to nudge folks away from it.

I have trouble getting worked up about the IFID thing in general, but I agree printing a more helpful error should not hurt! (Aside from any additional maintenance burden, which Daniel is most equipped to evaluate, and in the worst case we can just drop the code without breaking compatibility in the future.)

3 Likes

Good idea! The PR is up.

Now the option --override-serial YYYY-MM-DD will set the Å-machine release date to YYYY-MM-DD and the Z-machine serial number to YYMMDD. Nothing stops you from putting nonsense in these fields; the consequences of doing so are entirely on you.

There is an unsilenceable warning every time you use this option:

Warning: Release date has been set to “0123456789” and serial number has been set to “235689”. This is not recommended, and should only be used when necessary for reproducible builds.

It’s also deliberately not documented in the manual. Anyone who needs this kind of fine-grained control over their compilation process will have read dialogc --help and seen it there.

3 Likes

Some time has passed with no objections, so I’ve started merging PRs that aren’t waiting for specific people’s review. Now (current div width $) and (current div height $) work on the Å-machine (though you may need to download a more recent version of aambundle to use them), the Dialog compiler not just doesn’t but can’t produce deprecated Å-machine opcodes, and you can specify word separators if you really want to.

My personal hope is to have build 1b/01 out in time for TALJ, since I want to use it for my entries, but there’s plenty of time before then, and I don’t think I have any more big changes on my agenda. (Maybe (full name $) if I get a moment.) So for now, I’m happy to step back and let other people develop and review at their own pace.

Instead, my next priority in the IF space will be getting version 1.0.0 of the Å-machine tools officially released, so those can get into Homebrew and dgt and such. I’m working on a way to compile the Node.js Å-machine interpreter into a single portable command-line executable, so that can be incorporated into testing without messing around with Node at all.

4 Likes

Oh, that was way easier than I thought. All right, the next release of the Å-machine tools will include a new aamrun executable alongside aambundle and aamshow, which acts as a basic command-line interpreter. Think of it as equivalent to dumbfrotz: it doesn’t try to do anything fancy on the screen, but when you just want to pipe input in and output out, it’s ideal.

(As part of this, I added an option to set or uncap the effective screen width, and made progress bars show as ASCII art instead of just the raw numbers. It was annoying me.)

This also means that Dialog will no longer need Node installed to run the automated regression tests. It’ll just need this interpreter instead.

4 Likes

Fewer external dependencies is always a win! (And I’ll try to block out some time to get my PR in; it’s been a bit of a slog figuring out execution flow to get it actually passing my tests.)

1 Like

For the Skein: the dgdebug intro text:

Dialog Interactive Debugger (dgdebug) version 1a/01.
Type @help at the game prompt for a brief introduction.

it would be nice if there was an option to suppress this. Often the Skein output is used for the walkthrough, and (with the recent Skein changes) this text is now captured into the Skein.

That’s easy enough! The question is, should it also suppress the warnings printed after that header? Off the top of my head, there are four types:

  • Object was used in source, but never declared as topic; can be suppressed with --no-warn-not-topic
  • Predicate has only one of a rule, a query, or an interface; can be solved by adding an interface
  • Last file included on the command line doesn’t define a (library version) predicate; cannot be fixed or suppressed without altering program behavior
  • There are at least 100 lines of non-library source and meta information is not provided; cannot be fixed or suppressed without altering program behavior

Of course, ideally a program won’t have any warnings, but we don’t always live in an ideal world.

A future version of dgdebug will hopefully send game output to stdout and meta messages like this to stderr, which will fix the problem completely, but that’s not easy with the current architecture, so I wouldn’t expect it for 1b/01.

1 Like

I’d just like to suppress the one header; the warnings in the body have use while developing and should be gone by the time you release a project, but the initial header is stuck there if you use the dgdebug engine to generate your walkthrough. I could hack something into the walkthrough code to remove it, but I’d rather it was never emitted.

Easily doable, then! The next version of dgdebug will recognize --no-header.

1 Like

Done. I always like getting issue reports I can fix in thirty seconds.

1 Like

Oh, here’s one that just occurred to me. I’d like to add a predicate that checks whether a transcript is currently being recorded or not. On Z-machine, this is accessible as flags 2 bit 0; on Å-machine, it would be a new VM_INFO.

Why is this helpful? Well, two reasons.

One, it would be nice if transcript comments like * should the sundial be portable? checked if a transcript was active, and warned the player if not. The library can’t implement this check itself, because any flag the library set would get undone by a RESTORE or RESTART, but transcripting would still be active.

Two, attempting to start a transcript on the Å-machine web interpreter always fails, because the interpreter keeps its own transcript; the interpreter prints its own message to explain the situation. But that means the library shouldn’t display an error message when it happens—and there’s currently no way for the library to detect that. (The current library uses a hack, relying on the fact that the Å web interpreter is the only one where (interpreter supports quit) will fail. This should not be encouraged.)

Any objections?

  • This is a good idea!
  • This is a bad idea, don’t do it
  • I really don’t care either way
0 voters

If you support it, the next question is—what to name it? Transcripting is started with (transcript on) and stopped with (transcript off), so my first thought is to test it with (transcript active), but I don’t know if that would become confusing.

(transcribing) might be another option. Or (is transcript active) to highlight that this acts like a boolean.

I’d like to avoid the word “is” if possible, because the standard library convention is that the verbs “is” and “has” mark dynamic predicates, which this isn’t. Otherwise, something like (transcript is active) would definitely read better.

I had some extra time this afternoon, so I implemented it under the name (transcript active), but changing the name of the builtin is trivial if we decide on something else. The implementation is taken from (interpreter supports undo), which similarly checks a header bit on Z-machine, checks a VM_INFO on Å-machine, and is hardcoded in the debugger.

(This also turned up a small bug in the Å-machine Node interpreter, so the builds in this PR are currently failing. There’s a PR in the Å-machine repo to fix that, so that’ll have to get merged first.)