I don’t know if there’s a definitive answer to this question, but how much of the logic of an IF programming system has to be embedded at the parser level? Take I7 for example. It makes it seem like everything is controllable by the programmer on the language level, but really so many things are built-in and can’t be changed. Even the template layer is limited.
Some of the new development systems don’t even open the action processing or text manipulation to the language at all. I would think that a lot of these things could be made more accessible, but obviously some design approach is innate in the way the parser reads the story/library.
I’m interested in people’s thoughts on this.
Check out the way Dialog is structured. Although the language is specialised to suit some of the common requirements of IF systems (and the architecture of the z-machine, its original compliation target), the parser and world model are fully implemented in Dialog code within the library, so you can change any logic you want by modifying the library code.
I’m not well versed in TADS, but I believe the same is true of TADS 3 (which was one of the significant differences between it and TADS 2, where the parser was part of the interpreter).
What are the things you want to change?
Inform 7/10 is a very large and complex system, sometimes things can be changed but it requires a huge learning curve to know how to do it.
I am very familiar with Inform 6, and know you could change anything, but it is often difficult without expertise knowledge. For example, I wanted to change disambiguation to use a menu, but I didn’t have enough experience with how PunyInform does it to be confident my changes would work reliably, as disambiguation is a feature which is deeply embedded in the parser code.
In summary, the issue exists with any system I think, if it doesn’t do what you want “out of the box”, it may be possible but beyond the amount of time/effor you are willing to put in.
Everyone known that I tend to be extreme in adaptive prose (and bad english…), so a major issue I have is that with both I7/10 and TADS3 is that isn’t possible to get the actual player’s input, so, AFAICT is impossible having this (hammer/tool being the same object in the example):
>TAKE HAMMER
ok, you take the hammer.
>GET TOOL
ok, you get the tool.
Best regards from Italy,
dott. Piergiorgio.
Wait, we had a thread about this not so long ago. I don’t remember though if we had a solution.
Interesting thread. From what I know Inform 6 for example allows to control parsing process on low level, so you can probably accept any kind of grammar.
ADL, which I’m most familiar with, has standard template with actor, verb, noun(s) with optional adjectives as direct-object and one optional indirect object with preposition.
AdvSys has it more restricted.
With ADL you can use “all”, “but” words to specify all objects or exclude some objects respectively. All is given by standard ADL library, which has key features that make adventure creating easier.
If I remember correctly, some other “non-standard” commands can be accepted by ADL.
But probably neither ADL nor AdvSys have some kind of parser-level calls to extract words.
There are built-ins in every language, but when API allows, such in-line functions can be specified, to change some behavior.
But I can’t think of use-cases for custom grammar, in standard text-adventure parser.
Something I expressed multiple times in my let’s play of Basic Inform/Standard Rules was a wish that Inform used more natural language in SR. There are a lot of cases where natural language phrases are nicknames for i6 routines. It would be nice if natural language authors could see these functions and intervene if desired.
This isn’t to take away from what I think BI/SR accomplishes, but I wish natural language authors could access or intervene with regard to some of these routines.
It’s definitely not impossible, as Inform (and TADS, I’m sure) can tailor output based on the content of the player’s command. The problem—or risk, I should say—is that tinkering with the player’s command carries risk, since it’s hard to account for all of the possibilities. A lot of authors would probably rather leave it alone. But something like this really ought to be fine. If an author also has a “stool” somewhere in the game world, though, they will have to take care!
lab is a room.
the hammer is in lab.
understand "tool" as the hammer.
to say the questionable substitution:
if the player's command includes "tool":
say "tool";
otherwise:
say "hammer";
the printed name of the hammer is "[the questionable substitution]".
If “tool” was specified as synonym to “hammer” and player typed “get hammer” or “get tool” and we want to display the main item’s name or actually typed, it’s a matter of taking the item’s main name using matching, or using the typed noun. It should be quite easy, even in ADL/AdvSys, I believe.
The typed noun is stored in a variable (direct-object). The same goes for main item’s name.
I hope I understood this problem correctly.
P.S. Yes, the typed noun-phrase is stored in variable in ADL or AdvSys. So it doesn’t require low-level parsing. Don’t know about Inform 7 and how variables are handled there.
For Non-English. Or having two player characters which different education level. They would speak differently. (This is an idea I had long time ago. But it would probably drive the player crazy.)
Extracting the words from the player’s input using custom routine can be sometimes useful. Either from full line or its already parsed parts.
I remember that I had problems with “bag of coins” and “bag of seed” to implement in AdvSys, where Inform probably could do it easily.
Games - let’s say in Polish language - are quite more difficult to program, as we must either have Polish dictionary loaded, or provide all the cases of nouns. Grammar should be easier though.
You’ll want Subcommands!
Which doesn’t really change any of the core arguments at the top of this thread, though, because adding this capability was really annoying and this extension is incompatible with anything else that touches the parser.
Yes-ish. The parser is written in I6 code, but the parsing tables are handled by the I6 compiler. If you want to change how parsing works fundamentally, you’ll need to ditch those tables and build your own, and without macros that’s a miserable experience for the author.
Ah, that’s right! I forgot about subcommands! I liked it a lot, but I think something else in my project was giving it trouble.
Yeah, unfortunately only one extension can touch the parser at a time. Which is not ideal.
I didn’t mean fundamental customization, but mentioned word-extracting (from whole line or its parsed parts, like direct-object) to detect special words..
Thank you for giving information about this technical aspect of Inform 6. I didn’t know that parser is written in Inform 6 itself.
In my opinion such Inform 6 abilities are its advantage rather than disadvantage.
As I said the standard text-adventure parser is enough in 90% of the cases. With discussed exceptions.
I would rephrase this question as: how much of the parser needs to be built into the language?
Dialog says, basically none of it. The only part of the parser that’s built into the language is “give me a list of objects matching filter X, such that their property Y contains all the words Z”. Which sounds (and is!) rather convoluted, but it mostly exists for efficiency—it’s the part of the parser that was too slow when written in high-level Dialog code. Everything else is pure, author-editable Dialog, which is how I was able to rip out the entire English parser and replace it with a Hittite parser (noun case, no conjunctions between nouns, verb at the end, pronouns at the beginning) while keeping the world model generally intact.
TADS 2 (not 3) says, all of it! Parsing is so frequent that, for efficiency, it’s all handled in the interpreter, not in author-facing code. There’s no way to change it.
Inform 7 says, the concept of an “action” is fundamental to the language, on the level of integers and strings. If you really want to, you can rip out the parser and change its internals, but the basic concept of an “action” has to remain intact. There’s no way to represent, say, an action with three nouns in it, or an adverb. (Why would we want to include an adverb, or anything that’s not a noun? Dialog handles “put X on Y”, “put X in Y”, “put X under Y”, “put X behind Y”, and so on as a single action with three arguments. Inform has to treat them all as entirely separate actions.)
Inform 6 says, “actions” can be whatever you want them to be; in the default library (and PunyInform), an “action” is stored in a bunch of global variables. You can fill in those variables however you like; the parser is all pure I6. But the compiler generates a bunch of tables for the parser to use, so if you want any of the syntactic sugar around grammar lines, those tables have to use a specific format and a specific set of tokens. Want to add a new parser token? Gotta change the compiler.
ZIL says basically the same thing as Inform 6 (an “action” is a bunch of global variables, the parsing is done in ZIL code). But ZIL, unlike any of these other languages, has an elaborate macro system, so the format of these compiler-generated tables can also be defined in ZIL! Those macros are so arcane that Infocom’s documentation says “only one person understands how any of this works, go ask him”, but in theory they can be changed on a project-by-project basis.
So, how much of the parser has to be built into the language? I would say as much or as little as you want. All these systems do it differently, and all of them work perfectly well. (Though TADS 2 was replaced by TADS 3 with an author-accessible parser, so…)
Thank you everyone for your responses. I think I created confusion with my question because I used the word “parser” instead of “compiler”. My main intention was to ask a more fundamental question. How much of an IF system is a programming language and how much is a library? Really, a model world and ways to interact with it is just data in a structured library. I could see a model where all that information is just tables in an SQL style database and can be converted or compiled any way a client wants.
One can also have the same discussion about the IF parser. Is it not just a table of words and how they combine with one another?
Also something that varies a lot! But that’s probably no surprise from a programming standpoint; look at C versus C++ versus JavaScript versus Python to see what different designers consider so fundamental that it has to be built into the language/compiler itself.
In the IF world:
- The fundamentals in Dialog are lists, and…that’s kind of it. Objects (i.e. symbols) and dictionary words and variables don’t get nearly as much attention. Everything else is built out of that via the standard library, which handles everything specific to IF.
- Inform 7 has a very specific world model built into the language itself. Facts like “only people can wear clothes” are deeply ingrained into the compiler; if you don’t want that, well…don’t use Inform 7!
- In Inform 6, the fundamentals are basically just what the Z-machine provides: routines, strings, objects, registers. The parsing tables and object classes are the only big exceptions, where the compiler is distinctly opinionated about what sort of Z-code file it’s producing.
- TADS, to my understanding, is more on the C++ side of things, with a core language that’s able to do anything (but none of that simply or concisely), and then an elaborate standard library that implements all sorts of components an author might need. You could write your own vector implementation if you wanted, but most people will use
std::vector. It’s standard, after all!
I’d say the biggest differentiator between IF languages and most(?) general purpose languages is the ability to attach a property to an individual object without needing to define it on a class first.
Well, you could, but it would be much slower because the TADS 3 vector class is implemented as native code in the interpreter. (As is its equivalent of Inform 6’s grammar lines, IIRC, but I’m not quite certain where the line is between intrinsic classes and the library in that regard.)
I think it’s not a question of what’s fundamental enough to build into the language/compiler. It’s a question of what the designer could not avoid building in, and what they were later forced to lift out or work around because of user pressure.
This is sort of equivalent to your earlier phrasing: “How much needs to be built into the language?” But the emphasis is on what we can possibly manage to avoid building in.
You mentioned that I6 has no way to define a new grammar token type. But one of the built-in tokens is “a routine that can do anything”. This takes the pressure off needing to define new ones, so the token model has persisted more or less unchanged.
Inform 7 has a very specific world model built into the language itself.
It’s pretty clear that this is supposed to be completely customizable with relations. The problem is that the system isn’t powerful enough to add more world-model relations! I7 adds “incorporation” to the underlying I6 world model, but it does it in a hacky way which can’t be duplicated by the user.
If you could add more world-model relations (in a way that works smoothly with “holder of”, “to have”, efficient iteration of contents, etc, etc) it would not make the world model less fundamental. It would just fix a big hole in it.