I wonder if some kindly person could help me out here? This whole TADS thing is proving to be a difficult nut to crack. In fact, I’m even scratching my head over the kind of nutcracker I should be using to try and make a dent in it. Having spent all evening following the avuncular Eric Eve through the many-mirrored maze of the Adv3Lite manuals, I still can’t quite find what I’m looking for, even though I’m sure it’s in there somewhere…
What I’m trying to do is something like this: I have some objects (they may as well be books). Say there are four of them (but they’re just called “some books”). When the player takes a book I want it to be one of the four, at random. The player can only have one book at a time (if they want another one, they have to put the first one back). So I want to either a) pre-define four distinct book objects with different names and descriptions and then bring one of them into play, at random, when the player takes a book, or b) define a single book object and dynamically change its name and description to a different name and description, at random, from my choice of four options, when the player takes it.
Now, I know exactly how I’d do this in Adventuron, but I’m beginning to realise (with mounting horror and panic) that TADS isn’t Adventuron at all! Should I be using an EventList for this? The addVocab(voc) method? Or some other flavour of witchcraft? Any pointers (even just to which bit of the manual(s) I should be looking at) would be a tremendous help!
I’d probably go the route of creating four book objects. Then you might need a staticBooks object to handle dobjFor Take when as yet no individuals are taken. The action in Take could be a simple rand([book1,book2,book3,book4]).moveInto(me); with an appropriate msg. There are pretty straightforward ways of forcing the book swap as well. I’ll wait to see if any of the Lite pros jump on this, else I can try to give you some more specific code…
I feel you on what you’re saying, too, because I know exactly how I’d do this in adv3, but I wouldn’t be able to code in Lite with doing some research…
+ bookPile: Fixture, Surface 'a pile of books;;book'
"You see a pile of <<spellNumber(books.length)>> books. "
// the books in the pile are stored in a private list, rather than the
// 'contents' list every Thing has ... that's because we don't want to put the
// individual books into scope for the player to see or choose from
books = [ redBook, blueBook, greenBook, orangeBook ]
dobjFor(Take) {
verify() {
logical;
}
check () {
if (books.length < 4)
"You can only take one book at a time.";
}
action() {
// select one
local book = rand(books);
// remove it
books -= book;
"You take <<book.theName>> from the pile. ";
book.moveInto(gPlayerChar);
}
}
// for PUT book ON pile
checkInsert(obj) {
if (!obj.ofKind(Book))
"You can only put books on the pile. ";
else if (books.indexOf(obj) != nil)
"That book is already on the pile. ";
}
iobjFor(PutOn) {
action() {
// move the book out of the player's inventory
gDobj.moveInto(nil);
// put the book back on the pile
books += gDobj;
}
}
;
class Book: Thing
;
redBook: Book 'a red book'
;
blueBook: Book 'a blue book'
;
greenBook: Book 'a green book'
;
orangeBook: Book 'an orange book'
;
If I understand what you’re saying, you want the collective books to appear as a single object until one is taken. The player is only allowed to take one. If they want more, they have to return the book to the pile and try again.
adv3Lite has a CollectiveGroup class, but I don’t think it does quite what you want here. If it was okay for the individual books to be visible in the group, and the player could pick which one they wanted, a far better choice would be to use a standard Container (PUT book IN bookcase) or a standard Surface (PUT book ON pile) and be done with it. It’s the way the individual books “disappear” into the pile that requires some custom code to make happen.
Like I said, I banged this out, so this might not work well in all contingencies, but it should give you a starting point to work from.
You could also consider making the book return an implicit action:
check { /* empty */ }
action {
local b = me.allContents.valWhich({x:x.ofKind(OneAtATimeBook)});
// or perhaps: local b = gAction.scopeList.valWhich({x:x.ofKind(OneAtATimeBook)});
if(b) tryImplicitAction(PutOn,b,bookPile);
// if there was any reason we couldn't get rid of our current book
// (it was in a locked box, etc.), we need to know
if(me.allContents.valWhich({x:x.ofKind(OneAtATimeBook)})) {
"You can't have more than one etc.";
exit; }
// Then the usual handling...
}
If the player can take one of the “books” out of the book pile’s location, however, and drop it somewhere, then you have more work on your hands if you’re determined for there to be only one book in the game world at a time. Unless you’re simply preventing the player from leaving that room with a book…
I’ve never looked at Adventuron, so I can’t comment on that. My experience (going back a few years) is that when I first started learning T3 I found it difficult and intimidating, but as I became more familiar with it, it got easier. There’s definitely a “TADS way of doing things.”
EventLists, for example, are almost entirely about creating variable text outputs, such as giving an NPC a ShuffledEventList output to replace “Bob does not respond.” What you’ve described is four distinct books, so trying to manipulate one book object by changing its vocabulary is not the TADS way. Your objects are distinguishable, so, as Jim Nelson suggested, create a Book class and make four distinct objects. That’s the TADS way.
I would suggest that you read the Learning document first. There are some advanced topics for which you’ll need the Library Manual. The Library Reference Manual is a different beast entirely; it’s not properly a manual at all, it’s a gigantic cross-linked database. When you’re first learning TADS, just ignore the LRM. Later on, it will become super-useful, but at the outset you won’t know what you’re looking for in it. That’s my experience, anyway.
Also, by the way, if you’re using Windows, a utility called Auto Hot Key will save you any amount of typing. For instance, you can set it up so that one simple macro key combination spews out:
dobjFor() {
verify() {}
check() {}
action() {}
}
…and then moves the cursor insertion point back up between the top row of parentheses so you can type the action name (Take or whatever).
There’s no standard library in Adventuron. Everything - doors, containers, actions, conversations, NPCs, the lot - has to be built from scratch. That makes it limited in some ways (it wasn’t designed to make the sort of very long, convoluted narrative games that I like to make) but gives it a certain appeal to the DIY enthusiast, and means that the author understands, more or less, how each of their wonky Heath Robinson contraptions works. In stark contrast, TADS is massively fully featured and seems to have a class for everything already built in - secret doors, bunches of grapes, the kitchen sink etc, etc. It also assumes a basic level of programming knowledge that I really don’t have (but aside from that, Eric Eve’s documentation is very good; I’ve read the Learning manual and have the others on hand). So yes, it’s hard and intimidating and feels, at the moment, a little like attempting to scale a diamond-coated cliff face, in carpet slippers. But I’m the stubborn and determined type (or an awkward sod, as you please), so will carry on chipping away and apologise in advance for the silly questions that are bound to crop up along the way.
I’m sorry to come back about this, Jim, as I really should be able to figure this out…but it’s giving me an ‘index out of range’ runtime error when I’m already holding one book and attempt to get another, and I can’t work out why. Any ideas?
As John asked, if you’ve made changes to the class, I’d need to see those to debug the problem. (You can DM them to me if you want.) Also, what commands are you entering to cause the issue? When I do this:
> TAKE BOOK
> TAKE BOOK
I get back “You can only take one book at a time.”
Hmm - I hoped it would be a simple solution. I don’t think I did change anything. But I will fiddle around with it a bit more to try and work out what the problem is, as well as what on earth the stack trace means. I’ll come back after a bit more head scratching…