Well, how should that parameter be encoded? The Z-machine uses magic numbers (1 for reverse, 2 for bold, 4 for italic, and 8 for fixed pitch). I don’t think that level of detail should propagate all the way up into the library or story code. Those particular numbers would be meaningless for any other backend, so it would tie stories to the Z-machine for no good reason. Better, then, to use human-readable predicate names.
I’m not quite happy with the status bar mechanism, so it might indeed change. But I envision a change in the other direction: Let the author specify an abstract layout, such as a table of rows and columns (possibly centered or right-justified), or something in the spirit of html divs. The current approach is too tied to Z-machine specific notions of a fixed-width status bar and a fixed-pitch font.
But I hear what you and Zarf are saying here: That sometimes there’s need for low-level control, on an intermediate level between the library and the compiler. That low-level control would be specific to each particular backend, and using a known assembly syntax would allow some people to tweak those routines without having to dive into the inner workings of the compiler. But, well, I hesitate. I feel that low-level control would invariably lead to hacked-together solutions, stories that require certain interpreters, and so on.
The compiler upgrade fixes a couple of optimization-related bugs.
Noun-based disambiguation
The new version of the library features an improved disambiguation mechanism. As before, the parser returns every possible interpretation of the action that was typed. But this set of results is now checked to see if they only differ in one of the objects. If so, a more natural question is posed, offering a list of nouns (e.g. did you want to push the red button or the green button?). The player can respond with the desired object, or type a completely different action if so desired. Should the actions differ in a more complex way, they are presented as before, in a numbered list (e.g. did you want to 1. go north and west, or 2. tell ms. North to go west?). But in this case, too, the new version allows the player to ignore the question and type a new action instead of a number.
Can Dialog also take into account the current game state with disambiguation?
Consider this: on the floor is a red cube and the player is holding a blue cube. Now, would Dialog know that the ‘drop cube’ command means the blue cube or would it ask which cube to drop?
Dropping a non-held object is considered unlikely, so because there is at least one held cube, the parser will interpret “drop cube” as referring to that one. Also “drop all” and “drop all cubes” will do the expected thing. On the other hand, if there’s a cube in the room but none in the inventory, “drop cube” will be understood as referring to the cube in the room, despite this action being unlikely. That action will of course fail.
Dialog can handle more advanced scenarios as well, such as: The player is holding an open red box and a closed blue box, and decides to “drop box”. Both alternatives are equally likely, so the game asks: Did you want to drop the open red box or the closed blue box? Now the player types in “open box”. But this could be understood either as an answer to the question, or as a new command entirely. So the game will now ask:
Did you want to:
drop the open red box, or
open the closed blue box?
But what we don’t see explicitly, is that the parser also understood “open box” to refer to the act of opening the red box. But this was deemed unlikely, because the red box is already open, so it doesn’t show up in the list.
That’s cool. My parser works almost the same. The difference is that after asking the question about which box, the parser first considers the next user input to be an answer to the question. If parsing it as an answer fails, it will parse the input as a new command.
Like this:
[code]> drop box
Which box do you mean? The open red box or the closed blue box?
open box
Open red box: dropped.
x box
Which box do you mean? The open red box or the closed blue box?
i
You are carrying:
a closed blue box.[/code]
But it’s merely a design choice. I felt it is valid to assume they will answer the question and it may be distracting to point out their answer could also mean something else.
I had no issues compiling a Hello World under Windows. The binary was quite compact, and the syntax appears terse and well-considered. Definitely a promising start.
Is there going to be a bug tracker and/or suggestions site? I ask because I don’t envision the comments section of your home page scaling well with the back-and-forth of systematic development.
If the project garners enough attention (such as yours!), I’ll add that kind of infrastructure. For now it’s much more flexible for me to work locally.
I’ve been playing around a bit. It’s quite a pleasant system, but actions still confuse me. Not how they work per se, but actions as performed by NPCs.
For instance, when you tell Igor to go fetch something, how does that work with the action model in the generic sense? Is there some equivalent to the I7 “Instead of an actor going north: …” construct?
NPC support is currently very limited in Dialog. That’s an area where I think the standard library needs to grow.
PCs and NPCs are such different entities that there’s no obvious benefit from forcing them into the same abstraction. Action-handling routines would just split up into two cases again, all over the code. So I think it makes more sense to add new predicates for actions taken by NPCs, e.g. ‘(prevent $ as $)’.
But in many situations, it would be overkill to represent NPC actions with data structures at all. Just add predicates for e.g. wandering through an obvious exit at random, narrating it if the current room (of the PC) is involved. Then query those predicates from tick handlers.
In the case of Igor, I would use a global variable to track his current fetch goal. On every tick, if he is not holding the object, he would move one step closer to it, and possibly pick it up. Otherwise he would move one step closer to the PC and possibly hand it over. Pathfinding routines already exist, but NPC movement routines would have to be implemented.
That’s a perspective I hadn’t considered. It might be the reason why my I7 projects tend to falter when the time comes for handling actions.
One thing makes me curious though. I’d have expected at least z5 to be a natural fit for the use case laid out in the manual, but it seems Dialog exclusively targets z8 and zBlorb. Obviously z8 is more immediately useful, but it did make me wonder about your future plans for the compiler.
I’m fooling around with it, and I have noticed a curious problem, probably I missed something, but anyway:
the examples in the documentation don’t show the first (or only) room’s description at the start. banner &c. is shown fine, but not the first room’s description, whose shown up regularly with look.
The CoD example shows fine the first room (the foyer) but I can’t figure why CoD works but not the documentation examples.
Ah, yes. The default ‘(intro)’ doesn’t invoke the ‘[look]’ action at the end. You can easily add ‘(try [look])’ to the end of your own intro. But perhaps this is a confusing default. I’ll consider changing it.
In the Cloak of Darkness, the intro predicate ends by moving the player into the foyer, using ‘(enter #foyer)’. This predicate in turn invokes ‘[look]’ at the end (just like when you’re entering a room during gameplay).
Yep, I’ll have to come up with better default responses for those. Thanks!
Hmm, I feel that there must be some different approach that’s more in the spirit of the language. There are already named constants, in the form of dictionary words. Sets of flags could be represented by lists of words. The downside is that currently, with the exception of single-character words, all such constants would end up in the game dictionary too, but perhaps that can be avoided with some cleverness in the compiler.
Per-object boolean properties should be modelled by predicates (traits) of course.