Quest 4.1 Beta is now available
Alex
26 Apr 2009, 17:03- Quest Pro users can download it from http://www.axeuk.com/mydownloads
- If you're not a Quest Pro user, you can download the trial version from http://www.axeuk.com/quest/quest410beta.exe
Please note this version is intended for testing only - we strong recommend you keep backup copies of any game you're working on. We also recommend you install to a separate folder so you can keep your existing Quest installation.
Also please note that the documentation has not yet been updated.
Below is an overview of what's new. For further details, you can check the VERSIONS.TXT and VERSIONS-QDK.TXT files the folder where you installed Quest.
Quest Packager (part of Quest Pro only)
This is a new product that lets you create a setup EXE file for your game, so your users can install it just like any Windows application. No longer do you need to tell people to download Quest separately - you can just send them an EXE file that will install your game for you. This opens up the possibility of submitting your game to software download sites, greatly increasing the number of people you can reach!
Quest
- Lockable exits
- Exits are implemented as objects, so you can check their status using the Object Debugger.
- You can now do "for each exit in game/<room>" to iterate through all exit objects.
- You can now specify a script when using "create exit".
- You can now destroy directional exits e.g. "destroy exit <room1; northeast>"
- QSG files no longer save redundant property and action information, so saving and loading games is now much more efficient.
- For ASL 410 and later, the "visited" property for a room is now set only after the description for the room is printed, so you can print a different description if the player has visited the room before.
- New error "defaultwait" lets you specify default prompt for the "wait" command.
- Can now use "for each room in game" to get a list of rooms in the game.
The following bugs have been fixed:
- objects overriding actions specified by more than one type wouldn't override correctly.
- objects and rooms created via the "create" command didn't pick up the "default" and "defaultroom" types. This has been fixed only for ASL 410 and later to preserve backwards compatibility.
QDK
QDK has had major internal changes, and has a cleaner look.
- New toolbars
- Word-processor style text editor is now used for editing room descriptions, text blocks, and "print a message" scripts.
- Procedures, functions, timers, object types, status variables, synonyms, menus and resources are now accessed via the tree instead of the menus.
- "Back" and "Forward" buttons on the toolbar
- New exit editor for rooms combines the old "Compass" and "Go to" tabs, and allows for editing lockable exits.
Because QDK now uses some .NET 2.0 SP1 components, QDK no longer runs on Windows 98 or earlier. Windows 2000 or later is required to run QDK.
Other changes
As reported earlier, QuestNet Server is no longer part of Quest 4.1.
Testing
As this is a beta release, please be aware that you will almost certainly encounter bugs. Please do report any you find - please email me at alex@axeuk.com. As we have done with previous betas, I will be awarding the people who submit the most helpful bug reports with free Amazon vouchers. So please get testing and let me know your feedback!
paul_one
26 Apr 2009, 21:04BUT, we'll see how it pans out.
Overcat
26 Apr 2009, 22:59It is nice to define 'exit' object types and then let your exits inherit the different functionality. Much better than having to code each individual exit separately. Objects are better because they can have properties that define their state - in the case of an exit: open, closed, locked, unlocked, openable, lockable, etc. If an exit isn't an object then you've got to use global variables, which for me causes no end of anxiety.


Thanatos
27 Apr 2009, 02:38Alex
28 Apr 2009, 19:06paul_one
28 Apr 2009, 19:09The exit may have a DOOR - which is an object.
This object would hold the properties locks/closed/open/etc.
Plus, this means that the exit properties will either have to have a special Quest type, or special actions/properties defined for it... Making exits different to all other objects (we're getting back into the territory of "People are different to Objects" again - which we moved away from for this very reason).
I really don't see what the gain is with objects rather then properties/actions on the room itself (ie, a blank/null/empty exit property means no exit. Same with actions).
Is this just because it's used as TADS and someone went "oh, they're used over there" ?
Overcat
28 Apr 2009, 19:48for each exit in room <#quest.currentroom#> {
'do something
}
To me it makes more sense to treat exits as objects. I was assuming that exits would be implemented like this:
define exit <North>
end define
But they're not implemented so. They are still tags, like north <gotoRoom>, or north {}. You can, however, add actions, properties, and I'm assuming types during run-time with:
property <room.north; SomeProperty>
action <room.north; SomeAction>
type <room.north; SomeType>
This is cool - but how do I add properties, actions, and types during design-time? I don't think I can.
paul_one
28 Apr 2009, 20:46- Sorry, that's the first thought that jumped in there.
For iterating through objects, you can always do some funky thing with #quest.doorways# and #quest.places# - but yes, iterating through exits is quite helpful.
.. I don't quite understand the need for changing them to objects in order to achieve this feat though..
I was assuming that exits would be implemented like this:
That is introducing a new "exit" terminology.
IE, a room is a sort of object (basically a container), a normal object is an object (can also contain other objects), an exit is a sort of... object that ... the player interacts in a specific way with.. to move from one room to another....
So I get the feeling that treating exits as objects is to allow them to have a generic action ("destruct", or "unlock").
.. But would you really want people to type "punch north", "unlock east" etc?
If you would make them type "unlock door" - then isn't it much better to have the door as an object itself, which the exit relies on?
Overcat
29 Apr 2009, 19:49Hmmm... Do you really want to iterate over an exit when you're doing a "for each object in..." loop?
The best solution (for me) would be a 'for each object of type <type> in <room>/game'. We can achieve the same effect ourselves with:
for each object in game {
if type <#quest.thing#; Actor> then {
'logic
}
}
But I have the feeling that it would be faster if Quest did this behind the scenes. And I don't mind 'for each object in...' looping over exits: they should be objects, as far as I'm concerned.
So I get the feeling that treating exits as objects is to allow them to have a generic action ("destruct", or "unlock").
I think that's a darn good reason.

.. But would you really want people to type "punch north", "unlock east" etc?
This is easily avoided by not giving your exits names such as 'north' and 'south', which, as far as I can see, you still must do with 4.1. (You could name them whatever you want with the 'define exit <ExitName>' syntax.) You can override Quest's default handling of travel with custom commands so that a player can still type 'n', or 'e'. A property on each exit object can determine where the object sent the player. I use a naming convention on the exit object itself because it's faster to see if an object with a given name exists in a room than it is to loop through all the objects for a specific property or type. (ie. Cabin_North is the name of the north exit object in the room called 'Cabin'. If Cabin_North is 'here', the player can travel north; if not, then they can't.)
I can understand, however, how one would perceive an exit as a property of a location, rather than as an object. We have 360 degrees of infinitely precise freedom in reality, whereas in games we've digitized motion: directions are in discrete chunks. (And so are the locations.) Whether or not each of those directions is linked to an object (like a door) is, in my opinion, irrelevant as to whether the direction should be treated as an object in and of itself. Moving somewhere, anywhere, involves a description of some sort, even if it just be 'east' or 'west'. I think an exit object might allow better programmatic control over the description and effects of movement.
As an example, consider NPC automation:
west {
if here <BigRock> then {
msg <There's a big rock in the way!>
}
else {
goto <NextRoom>
}
}
How the heck is an NPC supposed to interact with that? The exit script is referencing the object, so the NPC has no way of knowing the big rock is linked with going west. Further, how do I tell who attempted to use the exit? (Which might be important.)
If the exit is an object with properties and actions, I can make the NPC interact with the object. The NPC can scrutinize the exit to see if they should even attempt to go that way. They can also discover something about the exit that they couldn't possibly know before attempting to use it, and then respond to that discovery. Additionally, all the logic for the behaviour of an exit object can stay with the exit, no matter if the player or an NPC attempts to use it.
As a final argument, why forbid an exit the inherent benefit of being an object? Is anything gained by limiting an exit as a single property or script of a location? I don't see it. (Not to say there's nothing to see - just that I can't see it yet.) You can always treat an object like a property, but you can't treat a property like an object (not easily, and not efficiently, anyway). All that said, I'm still open to any further arguments as to why exits shouldn't be objects.
paul_one
30 Apr 2009, 01:03Overcat wrote:Hmmm... Do you really want to iterate over an exit when you're doing a "for each object in..." loop?
The best solution (for me) would be a 'for each object of type <type> in <room>/game'. We can achieve the same effect ourselves with:
What I mean is - if you want to remove all the objects from a room, someone blindly going "for each object in <room> -> move it to <room3>" or some such coding muck up (kick north -> you kick north far-far away).
This means you have to code AROUND exits being objects - rather then what is actually a pretty straight forward object interaction mechanism.
[quote]So I get the feeling that treating exits as objects is to allow them to have a generic action ("destruct", or "unlock").
I think that's a darn good reason.

Which as I explained, exits are not objects.
A "door" is an object in the way of an object, so is a board, so is a teleporter (the fact you need to supply energy to "open" the exit doesn't mean it IS an exit).
... The exit is only something in two states.. Either it IS an exit, or it isn't. An "exit" can't be locked, or interacted with in any real way.
On the other hand, a door, wooden boards, bricks and morter. These can all be interacted with - or interact with the room - to change the exit from one state to the other.
[quote].. But would you really want people to type "punch north", "unlock east" etc?
This is easily avoided by not giving your exits names such as 'north' and 'south', which, as far as I can see, you still must do with 4.1. (You could name them whatever you want with the 'define exit <ExitName>' syntax.) You can override Quest's default handling of travel with custom commands so that a player can still type 'n', or 'e'. A property on each exit object can determine where the object sent the player. I use a naming convention on the exit object itself because it's faster to see if an object with a given name exists in a room than it is to loop through all the objects for a specific property or type. (ie. Cabin_North is the name of the north exit object in the room called 'Cabin'. If Cabin_North is 'here', the player can travel north; if not, then they can't.)[/quote]
But it still works no matter what you call it. "widderkin" or "turnwise" or anything.
What you've now introduced above is:
*) Overriding player movement
*) Special treatment of the <exit> object type in ALL commands
*) Special treatment of the <exit> object type for ALL object interactions - not just the ones the player wants to interact with but whatever you want to do automatically to objects too.
*) Special naming convention which voids the benefit of the "for each exit in <room>" loop.
You've just added complexity with no benefit (ie functionality) for what reason?
I can imagine that you'd want a walk and a run action on the exit, so you have two different ways of going through it (and possibly more).
BUT, you can code all of that through a procedure/function which your exit can call in ASL-400 (the proc/func would refer to the room/objects passed to it similar to the #quest.self# or #quest.thing# variables that aren't too well documented).
.. I can actually see some benefit from that - multiple actions against a direction... But that can be easily mirrored in normal ASL-400.
From what I can see you get the gain of interacting with exits like objects... Which as I said before, isn't actually true at all, and can be quite negative.
I can understand, however, how one would perceive an exit as a property of a location, rather than as an object. We have 360 degrees of infinitely precise freedom in reality, whereas in games we've digitized motion: directions are in discrete chunks. (And so are the locations.) Whether or not each of those directions is linked to an object (like a door) is, in my opinion, irrelevant as to whether the direction should be treated as an object in and of itself. Moving somewhere, anywhere, involves a description of some sort, even if it just be 'east' or 'west'. I think an exit object might allow better programmatic control over the description and effects of movement.
Sorry - you seem to say you don't care if it's one way or the other with that, or am I not reading it right?
And movement needing a "description"? A room, and object have numerous properties.. The desk is black. The room is wide and long.
True, an exit can be large or tiny - but that's about it.
As an example, consider NPC automation:
west {
if here <BigRock> then {
msg <There's a big rock in the way!>
}
else {
goto <NextRoom>
}
}
How the heck is an NPC supposed to interact with that? The exit script is referencing the object, so the NPC has no way of knowing the big rock is linked with going west. Further, how do I tell who attempted to use the exit? (Which might be important.)
If the exit is an object with properties and actions, I can make the NPC interact with the object. The NPC can scrutinize the exit to see if they should even attempt to go that way. They can also discover something about the exit that they couldn't possibly know before attempting to use it, and then respond to that discovery. Additionally, all the logic for the behaviour of an exit object can stay with the exit, no matter if the player or an NPC attempts to use it.
So instead of having that, you have:
def obj <west>
action <move> if here <stone> then _
msg <no way> _
else _
goto <next room>
end def
.... aaaaaand in what way can the NPC scrutinize this?
.... You'd give it a SPECIAL action right? - like "NPC" - and have it return either the room or "FALSE" so that it can move into that room or see the exit cannot be traversed yet? (it's the first idea which seems pretty simple and logical to me)
I would argue the exit would not currently exist.
The exit would be "created" once the rock was moved/destroyed.
All that would be left out is the player typing "w" or "go west" - which would return "I cannot go there" instead of the nicer "there appears to be a rock in the way". Which you can have as the normal "default" exit script (ie west msg <There's a big rock in the way>).
The NPC would get to the room, use the properties to check all the exits (or go through the "for each exit in") to pick an available room.
As a final argument, why forbid an exit the inherent benefit of being an object? Is anything gained by limiting an exit as a single property or script of a location? I don't see it. (Not to say there's nothing to see - just that I can't see it yet.) You can always treat an object like a property, but you can't treat a property like an object (not easily, and not efficiently, anyway). All that said, I'm still open to any further arguments as to why exits shouldn't be objects.
You close asking for any benefits of correcting exit usage in ASL-400 (I'm NOT saying that ASL410 is a mistake here.. I'm saying that exits are not treated as "proper" properties/actions in ASL-400).
You gain the fact that: Rooms are rooms (basically big objects) and objects are objects. Rather then treating Rooms as rooms, objects as objects, and objects as exits - or vice versa.
You gain the fact you don't need to code around properties actually being objects.
You say you're limiting an exit from interaction as an object, and that's entirely true - since exits aren't objects.
You also say treating properties as objects is near impossible - again true, since properties aren't objects.
A property is a value (whatever this value is).
.. The value of an "exit" is where it leads (and if you want to be picky how big it is).
You can change a property (the desk could be red, or yellow, the exit could move or point to another place) but you can never "interact" with an exit.
I tried thinking of a hole, and plugging it up with a bolder... Or any exit being blocked by a large rock or anything.
That comes down to the bolder blocking up the hole itself - not the exit "down".
Or it would block the doorway, or cave, or path.
All of those would mean the boulder would have an action on it to block up the direction.
Freak
30 Apr 2009, 02:16Overcat
30 Apr 2009, 13:16What I mean is - if you want to remove all the objects from a room, someone blindly going "for each object in <room> -> move it to <room3>" or some such coding muck up (kick north -> you kick north far-far away).
This means you have to code AROUND exits being objects - rather then what is actually a pretty straight forward object interaction mechanism.
I think it's pretty straight forward to "code AROUND" them. It's not like you're circumnavigating the globe any time you want to avoid a certain kind of object.
Which as I explained, exits are not objects.
A "door" is an object in the way of an object, so is a board, so is a teleporter (the fact you need to supply energy to "open" the exit doesn't mean it IS an exit).
... The exit is only something in two states.. Either it IS an exit, or it isn't. An "exit" can't be locked, or interacted with in any real way.
On the other hand, a door, wooden boards, bricks and morter. These can all be interacted with - or interact with the room - to change the exit from one state to the other.
I understand that in real life exits are not objects! But in a coded representation of the real world, any concept can be programmatically structured - in this case, an exit can be an object. There seems to be a disconnect between what I mean by 'object' and what you mean by 'object'. When I say 'object' I am speaking in a programming sense. I can abstract exits into a class (in ASL's case, a type), and then create instances of that class. I can use the properties and actions defined by the exit type to mutate the instances into all the different kinds of exits I can think of - including exits that are just that: exits with no other noun than the direction (east, west, etc.)
As a parallel, I have an 'event' type in a library file that I use to define event objects. Events are no more objects in the real world than are exits, but I still create them as programming objects. Rather than coding all the different kinds of events that are possible wherever I need them, I create a single type and manipulate properties/actions to achieve the effects I want.
[quote]This is easily avoided...then they can't.)
What you've now introduced above is:
*) Overriding player movement
*) Special treatment of the <exit> object type in ALL commands
*) Special treatment of the <exit> object type for ALL object interactions - not just the ones the player wants to interact with but whatever you want to do automatically to objects too.
*) Special naming convention which voids the benefit of the "for each exit in <room>" loop.[/quote]
First off, overriding player movement doesn't take a lot of work, and it allows me to do what I want: use exits as programming objects. (The fact that I can override movement is a good thing. If folks are happy with the default way things work, then by all means.) Secondly, you don't need to treat an exit object in a special way for 'ALL commands'. Thirdly, excluding a specific type of object from a for each loop is not that much extra script, especially if you're organized. Fourthly, the naming convention mentioned above was used before 4.1. I haven't decided whether to keep doing it that way or not. We'll see.
You've just added complexity with no benefit (ie functionality) for what reason?
I can imagine that you'd want a walk and a run action on the exit, so you have two different ways of going through it (and possibly more).
BUT, you can code all of that through a procedure/function which your exit can call in ASL-400 (the proc/func would refer to the room/objects passed to it similar to the #quest.self# or #quest.thing# variables that aren't too well documented).
I see a lot of benefit. If I haven't clearly explained what those benefits are in previous posts, then that is my fault.
[quote]I can understand...effects of movement.
Sorry - you seem to say you don't care if it's one way or the other with that, or am I not reading it right?
And movement needing a "description"? A room, and object have numerous properties.. The desk is black. The room is wide and long.
True, an exit can be large or tiny - but that's about it.[/quote]
No - I care. I was attempting to convey that I can understand how one would declare 'exits are not objects'. But, that's because we're using the word 'object' in two different ways.
Exits can have all sorts of description involved with them. A thin tree trunk over a fast-flowing river; a rope spanning a crevice; an open window; a magical portal; the mouth of a giant worm. It makes more sense (to me) to have an exit object with properties/actions that determine what is reported to the player when they travel (or attempt to travel) in a certain direction.
It boils down to how you view the construction of the world behind the scenes. One view is that you can move in any direction you want unless an object exists to block the way. Another view is that you can only move in a direction if an object exists that allows you to move that way. In either case an object is the determining factor. Exits are the objects that allow (or disallow) travel in any direction (even if you're standing in open space). Those objects may become nouns (as in doors and windows), or they may not (as in when your moving across a desert.) If I don't specifically script an object that allows travel in a particular direction, then travel in that direction is not possible. I would still need yet other objects to disallow travel, however, like a dense brush or retaining wall. In both of those cases I could get creative later and let the player travel via those objects by turning them into exits with a tiny bit of inherited code. (The player could get a machete to hack through the brush or a ladder to scale the wall.)
def obj <west>
action <move> if here <stone> then _
msg <no way> _
else _
goto <next room>
end def
.... aaaaaand in what way can the NPC scrutinize this?
Obviously that doesn't change anything. Throw some standardized properties on the object and the NPC can determine whether or not they should attempt to use the exit.
.... You'd give it a SPECIAL action right? - like "NPC" - and have it return either the room or "FALSE" so that it can move into that room or see the exit cannot be traversed yet? (it's the first idea which seems pretty simple and logical to me)
That could work. But I still don't understand your seeming aversion to 'SPECIAL' code. Your example here is no more special than declaring actions or properties on anything at all, which is a fundamental part of ASL.
All that would be left out is the player typing "w" or "go west" - which would return "I cannot go there" instead of the nicer "there appears to be a rock in the way". Which you can have as the normal "default" exit script (ie west msg <There's a big rock in the way>).
The NPC would get to the room, use the properties to check all the exits (or go through the "for each exit in") to pick an available room.
What if I want the NPC to automatically discover the rock and attempt to find a way around it? In that method there is nothing to indicate that it may be possible to do something to get around the rock.
You close asking for any benefits of correcting exit usage in ASL-400
No - I indicated I was open to reasons as to why exits shouldn't be objects. So far the main argument against exits implemented as objects seems to be cognitive dissonance. Making an exit an object isn't 'more complicated' - just as making an event an object isn't more complicated. It's just a natural programming technique, as Freak mentions here:
Just because something is represented in the game as an object doesn't mean it's necessarily an object in the room. It's a common technique to have an object used solely for structuring data.
Freak
30 Apr 2009, 17:45Overcat, could you produce hypothetical code of a small game that would illustrate the usefulness of exit objects?
Also, is it possible to have some sort of intermediate, that has simple connections for the bulk of the connections, but allows using exit objects when needed?
paul_one
30 Apr 2009, 17:46Mockery is very welcome

First : oops, I clicked Edit on your post Overcat - I hit back immediately but just incase it shows up.
.. I didn't touch your post at all.
Secondly: Freak, I'm well aware of the object construct for programming.
I disagree that an object should be used for every individual piece of data though, and that it should be used specifically.
Thirdly, I'll reply to some of Overcats bits (since much of it is too-ing and fro-ing between us both as repetition).
I think it's pretty straight forward to "code AROUND" them. It's not like you're circumnavigating the globe any time you want to avoid a certain kind of object.
I'm not saying it isn't reletively easy to do.
I'm saying it's an added piece of now needed work.
You've gone from "opt-in" to "opt-out".
I understand that in real life exits are not objects! But in a coded representation of the real world, any concept can be programmatically structured - in this case, an exit can be an object. There seems to be a disconnect between what I mean by 'object' and what you mean by 'object'. When I say 'object' I am speaking in a programming sense. I can abstract exits into a class (in ASL's case, a type), and then create instances of that class. I can use the properties and actions defined by the exit type to mutate the instances into all the different kinds of exits I can think of - including exits that are just that: exits with no other noun than the direction (east, west, etc.)
What I mean by "object" is two fold:
a) Any Quest object (something in the room used for 'interaction' using #@object# etc.
b) A 'thing' which holds more then one piece of information/function based around the "properties/methods/functions" of programming.
As a parallel, I have an 'event' type in a library file that I use to define event objects. Events are no more objects in the real world than are exits, but I still create them as programming objects. Rather than coding all the different kinds of events that are possible wherever I need them, I create a single type and manipulate properties/actions to achieve the effects I want.
Don't quite see how that would work since events are not generic enough?
I'm trying to think of "events" as storyline plot events which would print text, move objects about and possibly change object properties - not to mention events would have to be interchangable, the same "event" called from different places, and using different parameters.
And I don't quite see how grouping all those separate parts into one group would make much sense - but I will continue to stew on it.
I don't think we need discuss this part further.
[quote]What you've now introduced above is:
*) Overriding player movement
*) Special treatment of the <exit> object type in ALL commands
*) Special treatment of the <exit> object type for ALL object interactions - not just the ones the player wants to interact with but whatever you want to do automatically to objects too.
*) Special naming convention which voids the benefit of the "for each exit in <room>" loop.
First off, overriding player movement doesn't take a lot of work, and it allows me to do what I want: use exits as programming objects. (The fact that I can override movement is a good thing. If folks are happy with the default way things work, then by all means.) Secondly, you don't need to treat an exit object in a special way for 'ALL commands'. Thirdly, excluding a specific type of object from a for each loop is not that much extra script, especially if you're organized. Fourthly, the naming convention mentioned above was used before 4.1. I haven't decided whether to keep doing it that way or not. We'll see.[/quote]
My point was that it went from being able to, to a requirement.
How many different ways are there for interacting with objects?
In order to use the direction object, you need to code up how you use them (I haven't read the new docu so I don't know what standard 'interactions' are performed by Quest on the exit-objects, sorry).
You then need to change *ALL* "command <#command# #@objects#> ..." to "command <#command# #@object#> if not type <#object#;exit> ..." (can't remember if it's "not type", or "type not") - as any command you miss out could effect an exit in the most strangest way.
As I said before, the "ease" of checking, double checking, and triple checking is not in question here.
Exits can have all sorts of description involved with them. A thin tree trunk over a fast-flowing river; a rope spanning a crevice; an open window; a magical portal; the mouth of a giant worm. It makes more sense (to me) to have an exit object with properties/actions that determine what is reported to the player when they travel (or attempt to travel) in a certain direction.
I would argue that a tree trunk is "a room".
If it isn't a room by itself, then it would be part of the description of the room (I imagined a tunnel/air duct as a similar device to the tree).
Again, I see it coming back to player interaction with the exit object.
It boils down to how you view the construction of the world behind the scenes.
Yes I agree, I think you're combining an exit and object (rope, hole, tree, etc) in order for interact.
Sorry, haven't read the rest and really need to pop out.
Will try to respond soon.
Sorry for the length of this (again) but am liking the argument

Alex
30 Apr 2009, 19:45If you want to iterate through exit objects, use "for each exit in <room>/game".
For commands, exit objects are only in scope for "go (to)". Because exits are now objects, they automatically benefit from the existing disambiguation features, so you can use abbreviations - "go sup" works instead of having to type the full "go to supermarket".
There's no "define exit" block in this version although I may well add that in Quest 4.2. This would add the possibility of specifying alt-names for exits and that sort of thing.
With exits the way they were in Quest 4.0, it would have been hard for me to add built-in locking functionality - where would the data go? How would you read whether an exit was locked? I could have added a new "north.locked" property to the room, but that's a bit inelegant, and what about non-directional "go to" exits, which didn't have corresponding properties at all? There really was no better way of implementing the functionality than to make exits become objects. That way they benefit from all the existing functionality - so there was no need to update the savegame format, no need to introduce a new mechanism for reading the state of the exit, etc.
I'll write a proper blog post about the changes soon.
paul_one
30 Apr 2009, 21:41.. I actually typed out a lot of how that would be the better way to approach it in my eyes (I just skimmed my post and saw I removed it... DOH!).
That gets rid of the whole exits-as-objects issue for me and simple allows you to add object functionality to the exit.
I shall crawl back in my hole now

Overcat
01 May 2009, 11:47Overcat, could you produce hypothetical code of a small game that would illustrate the usefulness of exit objects?
Sure. I see them specifically useful for NPC interaction, so I'll make something with a wandering NPC.
Also, is it possible to have some sort of intermediate, that has simple connections for the bulk of the connections, but allows using exit objects when needed?
Yes. I'll attempt to show that in the example. I think you can do this by checking to see if the normal property for the exit has been defined for the room - if it has, you use it; if it hasn't, you check for an exit object that goes in that direction.
from Paul:
Note: I am trying to stop myself using caps to exaggerate words as it makes me sound smarmy and aggressive.
Mockery is very welcome.
Yeah, it's always hard without voice inflection and facial expression to judge the tone of someone's message. I hope I wasn't coming across as confrontational, either.
Yes I agree, I think you're combining an exit and object (rope, hole, tree, etc) in order for interact.
Yep.
Sorry for the length of this (again) but am liking the argument.
Me too. You're making good points that force me to think. I don't mind being shown that I'm doing something the hard way!
from Alex:
Exit objects are not in the same scope as regular objects. You don't need to worry about excluding them from "for each" loops or player commands...
Sweet.
Although you wouldn't have had to exclude them from player commands anyway, even if they were in the same scope. If you construct commands {} in the same fashion as verbs {}, objects will only respond to the commands if they have a corresponding action.
command <someVerb #@object#> {
if action <#object#; someVerb> then {
doaction <#object#; someVerb>
}
else {
msg <You cannot someVerb #(object):prefix# #@object#.>
}
}
This is a good way to go, I think: all the logic about the verb activity is stored on the object (and/or its type). For commands with two nouns the same trick can be employed.
A useful way of building things:
define type <punchable>
action <BeforePunch> {
doaction <$thisobject$; OnPunch>
}
action <OnPunch> {
'code default functionality here
doaction <$thisobject$; AfterPunch>
}
action <AfterPunch> {
}
end define
define object <NPC_RonBurgundy> {
type <punchable>
end define
define game <SomeGame>
...
verb <punch: BeforePunch> msg <You cannot punch #(quest.lastobject):prefix# #quest.lastobject#.>
...
end define
The BeforePunch action contains nothing but a pass to the default functionality in OnPunch, but it is there for "gatekeep" logic: code that guards the normal functionality with extra conditionals (should particular objects require it). The AfterPunch action similarly contains nothing, but is there for "corollary" logic: code that runs as a result of the default functionality executing (should particular objects require it).
define object <NPC_JuliaRoberts> {
type <punchable>
action <BeforePunch> {
if (#player:gender# <> female) then {
msg <You wouldn't hit a lady.>
}
else {
doaction <$thisobject$; OnPunch>
}
}
end define
define object <NPC_HomerSimpson>
type <punchable>
action <AfterPunch> {
msg <Homer: "Doh!">
}
end define
Then there's context: punching items obviously has a different effect than punching actors, so:
define type <item>
take
type <punchable>
action <OnPunch> {
'other effects
doaction <$thisobject$; AfterPunch>
}
end define
define object <apple> {
type <item>
end define
Structuring things this way also allows you to map one verb to another, should the verbs be synonymous in a given context. For instance, the player might attempt to "turn" a screw, which is definitely different than attempting to turn a valve: the valve changes state, but the screw comes loose from whatever it was fastened into. You may already have "unscrew" and "turn" verbs implemented, in which case it would be handy to just map the "turn" verb for the screw to the "unscrew" verb:
define object <screw> {
type <unscrewable>
action <BeforeTurn> {
doaction <$thisobject$; BeforeUnscrew>
}
end define
There's no "define exit" block in this version although I may well add that in Quest 4.2. This would add the possibility of specifying alt-names for exits and that sort of thing.
Cool. For 4.1 I still don't know how to add properties and actions to the exit object during design-time. (Can do so at run-time). Perhaps your blog post will elucidate.
from Paul:
That gets rid of the whole exits-as-objects issue for me and simple allows you to add object functionality to the exit.
We both win!
Alex
01 May 2009, 12:43
For 4.1 I still don't know how to add properties and actions to the exit object during design-time. (Can do so at run-time).
You can't - and I can't think of a good way of doing so without a "define exit" block.
Ugly workaround would be to create a type for each exit and then apply the type to the exit at run-time. You could even loop through all exit objects in your startscript, and apply the type within the loop, perhaps.
Since you can't apply properties and actions to exits in v4.0 anyway I don't think is a big issue for v4.1, is it? I can't think that adding properties and actions to an exit would be that common.
Overcat
02 May 2009, 11:02Ugly workaround would be to create a type for each exit and then apply the type to the exit at run-time. You could even loop through all exit objects in your startscript, and apply the type within the loop, perhaps.
Thought of that, but there's no way for me to automatically know which exit is supposed have certain properties/actions altered on the type for given effects. The startscript would then have a big select case to manually modify each exit. S'okay - will work something out!
Since you can't apply properties and actions to exits in v4.0 anyway I don't think is a big issue for v4.1, is it? I can't think that adding properties and actions to an exit would be that common.
I admit, the number of users who like to script by hand seems to be dismally low. But adding properties and actions to exits could become common?

paul_one
02 May 2009, 12:15So type <one> would contain everything for exit <one>.
Type <two> would contain exit <two>.
.. etc..
Overcat
02 May 2009, 16:36Overcat - I think he means, instead of having one type - have many.
So type <one> would contain everything for exit <one>.
Type <two> would contain exit <two>.
.. etc..
Oh, I see. So for SomeRoom.north, create a SomeRoom.north type?
startscript {
for each exit in game {
type <#quest.thing#; #quest.thing#>
}
}
Only problem is if I've decided to use the default exit functionality for some of the exits, and therefore haven't defined a type by the same name, then I'll throw the error: "ERROR: No such type 'SomeRoom.north'". I guess that doesn't matter much for the final product, though. Thanks!
Alex
25 May 2009, 18:29There are still a number of bugs I'm aware of which need to be looked at, so we're not at "release candidate" stage yet, but we're getting closer

I've updated the help file now (the tutorial still needs updating though).
Alex
25 May 2009, 21:42In my tests, "Beyond Exile" on textadventures.co.uk was taking several minutes to save and load - this was even after the earlier improvements I'd made to saving QSG files. In the latest build, saving is pretty much instant, and loading only takes a couple of seconds. Nice!
I've also improved the performance of the CAS compiler when compiling large games.