New feature

Published September 01, 2006
Advertisement
I've just added my text adventure language's equivalent of a switch statement, the select statement. The following are examples of its use:

f(int v){    select(v)        {        1: out "one",end;        2:{ out "three"; out end; }        3: out "three",end;        }}f(int v){    select(v)        {        1: out "one",end;        2:{ out "three"; out end; }        3: out "three",end;        }    else out "some other value",end;}f(int v){    select(v)        {        1: out "one",end;        2:{ out "three"; out end; }        3: out "three",end;        }    else        {        int x=v*2;        out "whatever it is, it is half of ",x,end;        }}


It is unlike C++ switch in that any expression can form the equivalent of the case section and you don't need break statements. By default a single statement follows the case colon and you need to use braces to have multiple statements execute under a single case. You can't fall through like with a C++ switch - if you match a case, only those instructions following the case are executed.

The optional else section is roughly equivalent to C++ default and is executed if none of the cases in the select body are matched.

It wasn't too bad to implement. A minor problem is that in order for it to work, it has to duplicate the top of the math stack before evaluating the case expression and performing a comparision (comparisions are performed on the top two items on the math stack in the vm, like every other binary operation). This means that at the end of the select statement, an additional mpop instruction is needed.

Unfortunately, since it is possible to nest select statements indefinately and to have return statements executed in the case sections, it was necessary to have an external counter track the depth of select-nesting at any point and then issue that number of mpop instructions in the event of a return statement.

Feels like a bit of a hack but wasn't particularly hard to code and I've tested it fairly thoroughly, including creating local variables inside select statements and returning from deeply nested positions and the vm is not complaining that the math stack is either underflown or still has data at the termination of the program.

From a text adventure point of view, this feature will be most useful for switching on verbs e.g.

void response(word vb,word nn){    select(vb)        {        #get: on_get(nn);        #drop: on_drop(nn);        #quit: exit();        }    else        {        out "I don't understand.",end; clear_commands();        }}


sort of thing.

So on it goes. Next I need to implement some kind of system for recording connections between locations. I want this to be built in rather than expressed via the language because I want to provide route-finding features in the vm rather than have to implement them in the language directly.

Anyway, I've rambled enough for one night.
Previous Entry Back to work (sigh)
Next Entry Bingo
0 likes 2 comments

Comments

Mushu
I'm going to make a completely unfair argument from a C++ viewpoint about your last example (the verb selection) -

rather than hardcoding such a thing (in C++), it would be more awesome to do something like -

std::map< std::string, boost::function< void( word ) > > what_to_do_with_verbs

to translate between a verb and a function which is associated with the verb. I'm not sure how far you're planning on developing your language (or if its even an issue for you!), but I enjoy over-engineering everything, and this method allows for more robust dynamic content. I guess.

:D
September 01, 2006 01:48 PM
Aardvajk
Rock on, Mushu. It is for responses like that that I love GameDev so much. I totally agree with your totally unfair point of view [smile].

Of course if I was writing a text adventure in C++, I would want to implement some kind of absraction like that. However, I am writing a language for writing text adventures so the case is slightly different.

Actually, the capacity for function pointers would be a real asset for this language. Not so much in terms of switching flow on a verb as to allow for assigning a specific response function to a character, or a subset of characters that, if it returned false, handed control back to a standard response function. At the moment this behaviour has to be per-character coded in my language. If function pointers were properly supported, you could pretty much write a universal framework and your specific text adventure would consist of just providing objects and their personal response functions that would only have to deal with the ways their responses differed from the standard.

I had previously abandoned the idea as too complicated to implement but to be honest, the complicated bit would be declaring function pointers in the complier, not actually implementing it in the vm. Every "call" instruction just operates on the address register, which can be transferred to and from the math register, so technically I could implement this in the compiler right now without even changing the vm.

And so I should, I feel. I am far too drunk at the moment, but I thank you for your inspiration and will have a proper think about it in the morning, or perhaps the afternoon.

[EDITING NOW] I should also point out that I have been revisiting this project, on and off, for about five years now and the biggest challenge has always been finding a balance between an inflexible language ideally suited for writing text adventures and a fully functional C compiler that spits out byte code for a vm. Ye gods - I am now back where I started. I must immediately implement anonymous unions, a heap and a fully standards-compliant exception handling mechanism.

Actually (rambling like a drunken idiot now) that reminds me - I would like to think that this project, which translates my high level language into assembly-like instructions for a very basic vm - has given me some insight into how my complier translates my C or C++ code into assembley instructions but no matter how much I think about it (and my job is quite dull so I think about it a lot) I still have NO IDEA how exception handling is implemented at the assembley level. Does my head in a bit.
September 01, 2006 02:10 PM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement
Advertisement