Making TADS Friendlier

Yes, you can customize all the included JS / HTML / CSS files and still host it on IFDB. All of those resources are part of the T3 image and fully under your control.

Personally I like TADS 3’s server-side solution. I have long been wanting to be able to create a multiuser interactive storytelling experience, and now I can do just that. Granted, this is mostly theoretical right now; as I have no desire to code the multiuser equivalent of the Adv3Web library on my own, it seems I still have a while to wait. More realistically, I can soon relive the joys of watching people play my IF in real time—a joy I have not experienced in 15 years—even if they live hundreds of miles away.

This is also one of my chief pleasures. I do not think taking advantage of the new web browser system will make me feel like a “heavy-duty programmer”. Of course, this may be a relative thing. Before using TADS 3 I had only tried making text adventures using BASIC and Ruby.

Here is where we find agreement. Eric has definitely done a great service to our community.

Fair enough; that explains your otherwise seemingly puzzling comment! :smiley:

Still, as a matter of fact, when I wrote the Tour Guide I intended it as a sequel to Getting Started, not as yet another alternative introductory guide. Does that need to be made clearer? I get the impression that some people may indeed be using the Tour Guide as a way into TADS 3, and perhaps that approach does suit certain people coming to TADS 3 from a certain kind of background, but I wouldn’t want the total newbie to think it was a third possible basic introduction, since it was never meant to be that.

Perhaps what’s needed is one very short and basic Newbie guide that covers the absolute basics of writing, compiling and running the most basic of TADS 3 games (two rooms and one portable object, for instance) and then directs the reader to a choice of Getting Started or Learning TADS 3 (or the Tour Guide?) based on their previous experience and the kind of approach they think might best suit them. Any thoughts, anyone?

– Eric

Looking at “The Web UI” in the System Manual, I’m not finding any instructions on how I might do that. I’m sure it’s possible, and maybe there are comments in those various files that will explain the process. When I glance at layoutwin.js, however, the comments seem less than entirely elucidatory, if there is such a word.

I probably sound like I’m complaining again. Realistically, this is an immensely complex IF authoring system, and it’s being created entirely by volunteer labor. Expecting that it would also include a nice copy of “T3 Web Programming for Dummies” would be silly to the point of arrogance. (Insert 15-second clip of Monty Python’s “Upper-Class Twit” sketch.)

The bottom line, I think, is that we’re still in an evolving or unfolding posture here. The software now exists, but the process of exploring it and learning to use it remains to be undertaken.

I’ve just emailed you about this. I have an idea how to approach it, and I’m probably volunteering to do the work…

MJR: well a game file decoder and a disassembler I could definitely do. I’ll probably start after I’ve made a new Glulx terp though. Then maybe the remains of what is needed could be filled in by other members of the TADS community.

As to the intrinsics/library, well you won’t need to wait around for other implementations any more than you need to wait for bundled versions of TADS (like Gargolye) to update. I presume there is a way to detect which intrinsics are supported, or do stories that need one that isn’t just crash? Either way a JS terp could behave the same as the C one does. They too would need to be specified.

As to the speed of a VM-in-a-VM, well that’s why I’m so excited by JS terps. The more we can do that appeals to the JS VMs’ strengths, the faster our IF VMs will be. It’s my hope (and expectation?) that eventually I’ll be able to get a JS Glulx interpreter that is faster than Glulxe. The same could be true for TADS.

I’m also interested in an answer to that question, speaking as someone who enjoy Mac programming. I’m not saying that I’m ready to start working on a Mac TADS IDE (there is only so much time available and so on) but it is something I’m considering a little bit. And while I’m far from a professional programmer, I have done programming similar enough to believe I could pull it off.

Uli Kusterer’s website is zathras.de. You should be able to reach him from the contact page there. I don’t recall what he said about the source code, but the guy who created the Talking Moose has to be a friendly sort…

Google Native Client (NaCl) also has much promise. Not “better” than JS, but it allows for running the current T3VM (C++) inside the browser, at native speed. Building a NaCl TADS terp should be relatively easy (I’m interested in toying around with this one of these days.) JS is still better in supporting more browsers though, since right now NaCl is only supported by Chrome and only when running on x86 and ARM CPUs (even though those two CPUs cover pretty much 99% of everything there is.)

Ok. I’ve sent him an e-mail.

That much would be a great start. You’re quite right that once the core VM is in place, the intrinsics would work well as parallel projects that multiple people could pursue, because they plug in to the VM through a well-defined interface. In fact, I’d bet that building out the intrinsics in a JS version would be a heck of a lot easier than in the base C++ version, because the C++ version has to deal with the usual C++ memory management hassles.

Well, I didn’t meant to suggest that the C++ version would have to wait for a JavaScript terp, rather that the JS terp would constantly have to catch up to the C++ version. The constantly expanding intrinsics make it a moving target.

(Gargoyle isn’t quite analogous in this respect, by the way, because it bundles the original C++ versions of the intrinsics. For Gargoyle it’s a matter of integrating new base code rather than implementing new functionality, so it’s a different order of magnitude of work.)

It works like dynamic linking on Unix or Windows - the dependencies are resolved symbolically at load time, so the loader determines if something’s missing, and terminates with an error if so.

There’s a very rough overview in the section “Direct Javascript Programming” in that chapter. It basically maps out the organization of the .js files and the main Javascript classes and objects, but doesn’t get into anything nearly as specific as how-tos. Given how new this all is, I don’t even know yet what kind of how-tos will actually be interesting. As you think of concrete things you want to do with it, ask here and I’ll try to help, and hopefully over time we can develop some of that discussion into how-to guides and/or more SysMan material.

The dialog boxes could look better and skinning them should be easy. So if you are willing to publish it as a free extension and can draw a png image how exactly it should look like, I offer to do the HTML/CSS/JS programming.

Mjroberts, I hope it’s ok if such an extension recycle some of your existing code. In fact it’s a double question because I’ve also programmed a little extension to allow opening a chat window in multiplayer cooperative game session so the players can not only play together, but also chat about the game on side.

Absolutely. That’s all part of the library, which is under essentially an “attribution” license. The details are in license.txt, but the high-level version is you can do pretty much whatever you want with it as long as you keep the copyright notice with it.

That’s fantastic - I had something similar on my long list of things that I had to cut or delay to finally get a release out.

Hopefully friendly advice and a little suggestion for any new manuals. Stop discouraging people. A few bits:

Learning TADS 3:
“…but at first sight it can look quite overwhelming, since there seems to be so much to learn. TADS 3 in fact makes many common IF coding tasks extremely easy, but there is a lot to learn, and it’s very hard to produce anything worthwhile with it without first mastering the basics.”

“In order to master (or even become moderately competent at) a complicated system like TADS 3 (and TADS undoubtedly is complicated)…”

Getting Started in TADS 3:
“Fortunately, it’s not nearly as hard as it looks to set up a new game project.”

TADS 3 Tour Guide:
“It can also seem rather overpowering to new users of TADS 3, because there is so much to learn, and one hardly knows where to start looking for what one needs.”

You keep reading little asides that suggest things are going to be hard (-- but don’t worry! not necessarily as hard as they look --) or how complicated everything is. It’s about the most discouraging way to teach people or encourage people. Imagine a professor who started his classes by constantly talking about how hard and difficult everything was going to be. (It may be true; but constantly reinforcing that rather than, say, the thrill of learning or discovery is the wrong way to go.)

At this point, I’ve given up on the manuals and I’m just going through games that have their source code available. The library reference is utterly amazing and makes learning TADS quite easy. Likewise, except for a few things I either missed or didn’t find at all, the System Manual is quite well done. The Technical Manual is also really nice. Although there, too, we see things like:

“It’s not that TADS 3 does not allow you to change or suppress these messages, it’s that it’s not always immediately obvious how to do it, and that if you don’t know how to do it, wrestling with these bits of extra text can become an exercise in frustration.”

“A[t] first sight (or even second, third or fourteenth sight) the command execution cycle in the adv3 library … is pretty complex.”

Again, all this may be true to some extent that will vary by person: but, sheesh, lay off the editorializing. Let people come to this conclusion on their own – or maybe they won’t, if the documentation does its job. But setting people up to think everything is so complicated – or constantly reinforcing how complex everything is – is an odd approach to take in my opinion. I’m hoping any new documentation will mollify that stuff a bit. I’m happy to be a proofreader when new material is available.

You might be right that Eric’s editorializing sends a negative message. I’m not sure. I think his intent was probably to reassure people that they’re not alone in feeling that T3 is a difficult system to learn. Different readers may interpret those bits in different ways, but I don’t know that anyone has ever said, “Gee, this is easy and fun!” Anyone who had that reaction, please step forward…

Personally, if I had to learn T3 strictly from the LRM and source code of games, I’d shoot myself. I’ve been working on a new game, and I use the Tour Guide, the LRM, and Learning T3 constantly, with not infrequent trips to the Technical Manual. But then, I’ve used them all enough that I know where to look. I’m not reading them from cover to cover, as if they were novels.

As a TADS newbie with a background in CS/AI and Scheme programming, maybe it is useful to explain the big hurdles I experience - with all the disclaimers: I am grateful for both system and documentation, and think people have done a wonderful job.

I chose TADS because of its power - which means I want to deviate from the trodden path. Yes, I did read the Tour guide as an introduction, because it suited my level, but all three books leave me with the impression that I am walking upon a thin crust of solid ground on top of a vulcano - one step besides the indicated path and I may disappear in molten magma (i.e. my game will crash). I won’t feel at ease until I know what is under my feet.

My WIP (taking “progress” with a cartload of salt) starts with a room in which nothing is possible - everything causes a question, and the only action is saying “yes”, upon which the real game starts with another player character in another room (or saying “no” and having the game end there and then).

So how do I create this unconnected room, this temporary player character, and these two commands. There is quite a bit in the docs on commands with direct and possibly indirect objects, but I can’t find anything on making local commands without objects (of course I want local commands, because the rest of my game should not suffer from this one start room).

So there I am, groping blindly around trying to find answers to questions such as:

  • Where do I find the minimal actor, that doesn’t have a standard reaction to “Jump” and its ilk?
  • Ought I to DefineIAction(Yes) and in its execAction undefine it? That feels really ugly.
  • Where does “You must be more specific about whom you want to talk to.” come from? I can’t find it by searching the source code in Workbench.
  • Somewhere the conversation system must be kicking in. Should I use that, and have some invisible listener react to the “yes” or “no”? Making the room itself an actor causes the game to crash…
  • Will assigning to gPlayerChar suffice to jump from the first room into the real game?
  • Why isn’t there a subjFor, analogous to dobjFor and iobjFor? Or is there but I just haven’t seen it?

I know I would be most helped by documentation that started with the bare-bones TADS system, and worked its way up from there, so that at all times I would know (roughly at least) what was underneath. That would give me the assurance that I might not know everything, but that what I know would be complete in itself. I might end up writing code that duplicates existing features, but as I learn about the library I could bit by bit correct that, and at least my code would be working and I would know what it did. Right now I can copy bits from other games or from the documentation, and write variations on that that work (by trial and error), but I don’t know why they work, because I have no idea what is underneath.

If I had more time and energy I might read linearly through the code library…

Maybe I am alone in preferring this style of learning, but here it is - it is at least a data point.
Biep.

I appreciate that you were illustrating a problem rather than necessarily asking for help here, but it may be that you’ve made this particular problem a bit harder than it actually is. A coding pattern such as the following could go a long way towards what you’re after here without the need to implememt any special commands or alternate player characters:

startRoom: Room 'Unconnected Room'
    "This room seems somewhat unconnected. "
       
    roomBeforeAction()
    {
        if(gAction.ofKind(SystemAction))
            return;
        
        if(gActionIs(Yes))
        {
            "You said yes! ";
            me.moveIntoForTravel(realStartRoom);
            me.lookAround(true);
        }
        else
            "Did you really mean that? ";        
        exit;
    }
    
;

I’m not quite sure what you mean by the “bare bones TADS System” unless you mean the language as opposed to the library, in which case the TADS 3 System Manual describes that. But I suspect that isn’t quite what you mean; in which case you may very well be right that the only way to gain the kind of thorough understanding you want of what’s under the hood is to study the library source code, though this task can be made easier by doing so with the aid of the Library Reference Manual, which no TADS 3 programmer can avoid having to get to grips with sooner or later if they want to achieve something at all off the beaten track.

– Eric

It’s in msg_neu.t. What will trip you up about searching msg_neu.t is that its code is chock-full of parameter substitutions. The trick is to search for character strings that are not produced by any of these substitutions. I found that message by searching for “specific about”.

First of all, Eric and Jim, thanks for the practical help. Eric, with your code I get some messages in the debug log, but that log disappears before I can read them and the game starts fine. Apart from defining alternate messages for incomplete and ununderstood commands, this seems to do what I want - but it also illustrates the larger problem, because I had no idea such an approach was even possible. (“The command execution cycle” mentions roomBeforeAction, but doesn’t mention ‘exit’ in that context. Does an ‘exit’ anywhere in those functions and methods end the cycle - nothing more, nothing less?)

A text catering for my idiosyncratic approach to learning might:

  • Start with the BNF and the meaning of the main types and constructs in the language.

  • Add the system-defined shorthand forms, such as:
    [list]
    [*]name: Class … --> global.name = new Class …

  • “string” --> for say(‘string’)
    [/:m]
    [
    ]Introduce the user-definable surface-grammar-changing constructs, such as:

  • Templates

  • Macros

  • Propertysets
    [/:m]
    [
    ]Introduce the main Class-Object structures in big strokes, always explaining how specific behaviour is achieved.

  • Things

  • Actors

  • Actions

  • Commands

  • Movement, connectors, rooms

  • Et cetera - here it slowly grows towards the Tour Guide, but more “under the hood”.
    [/*:m][/list:u]
    That way I would know how commands are interpreted when I start using them, and I would know the room had a say in their interpretation (as I just learned from Eric’s code). Every new chapter might add detail to the mechanisms described so far, but the basics would at least be known. Right now the only way to learn about the call chain for command interpretation is to grok the whole of “The command execution cycle” in one go. I am sure the library has a certain modularity, and the text would reflect that.

I am not looking for every nook and cranny, and if in a later chapter an extra detour is described, that’s fine with me. After all, one cannot describe that command execution passes through the room before rooms have been introduced.

I imagine such a document might be a wiki, where people can freely add and polish the text as it stands at any moment. And the above set-up is of course based on my very limited understanding, and probably quite wrong.

Would such a document help other people, or is it just me who is weird in that respect?
Thanks again,
Biep.

BTW, would actorAction() be the check part of what I called subjFor()?