creating endless rooms/region

ender
21 Nov 2009, 18:56
I'm fairly new to Quest. I've been using IF7 for a while but recently decided I wanted to try quest because of the ingame interface. I've purchased the pro version.

I am building a game with a single building that is surrounded by a haunted forest. Rather than keeping the player from entering the forest or manually creating a huge number of rooms with the same description ... I thought there must be some way to programatically allow the player to enter the forest and just wander around from 'room to room' until they realize the forest is more or less endless and there is little point in wandering around in it.

I thought of two solutions to this ...

1. Some kind of loop where the player is really going back to the same room all the time ... but then the problem is how to keep track of the way back so they can return to the rest of the game....

2. automatically creating new rooms ... and I really don't understand quest well enough to really even know what problems will arise ..

I've worked on it for several hours and have come to a dead end, so I decided to ask for help.

So my questions for the community are:

1. Is either solution possible?

2. If both solutions are possible, which would be the better?

3. Is there a better solution than either of these?

4. Any ideas about how I might go about implementing this? If you can just point me in the right direction I can probably go from there, I'm not asking someone to do the work for me ... also, I'm experienced with programming concepts and terms so feel free to throw them out ...

Thanks,

Wonderjudge
21 Nov 2009, 19:16
The best solution in my opinion would be the endlessly returning to the same room. If you want to make it so that the player can't just one click back out of the forest then I suggest assigning variables to keep track of the players location. ie
every time a player goes east incremement the variable east1 by one and every time he goes west decrement it until 0 then start incrementing the west1 variable.
As there are so many directions it would be complicated to do.
The only other problem with the one room thing is players dropping items. A dropped item would show up in the room no matter what the variables were set to. You could make it so that players can't drop item there however.
Wonderjudge.

Alex
21 Nov 2009, 22:18
Here's a solution. It dynamically creates more and more forest as the player keeps exploring. The player can retrace their steps.

One downside is you have to retrace your steps exactly - that may or may not be what you're after. If you want the player to be able to go north, east, south then west and end up where they started, this solution will need refining somewhat.


define game <Forest>
asl-version <410>
start <house>
startscript {
set numeric <counter; 0>
set string <oldroom;>
}
afterturn {
if (#quest.currentroom# <> #oldroom#) and property <#quest.currentroom#; isforest> and not property <#quest.currentroom#; createdforest> then do <createforest(#quest.currentroom#)>
set <oldroom; #quest.currentroom#>
}
end define

define room <house>
south <forest>
end define

define room <forest>
script do <createforest(forest)>
north <house>
end define

define procedure <createforest>
set numeric <start; %counter%>
for <i; 1; 4> {
create room <forest%counter%>
inc <counter>
}

flag on <create north>
flag on <create south>
flag on <create east>
flag on <create west>

set string <p; $parameter(1)$>
if ($findexit(#p#; north)$ <>) then flag off <create north>
if ($findexit(#p#; south)$ <>) then flag off <create south>
if ($findexit(#p#; east)$ <>) then flag off <create east>
if ($findexit(#p#; west)$ <>) then flag off <create west>

set string <northplace; forest%start%>
set string <southplace; forest{%start%+1}>
set string <eastplace; forest{%start%+2}>
set string <westplace; forest{%start%+3}>
if flag <create north> then {
create exit north <$parameter(1)$; #northplace#>
create exit south <#northplace#; $parameter(1)$>
property <#northplace#; isforest>
}
if flag <create south> then {
create exit south <$parameter(1)$; #southplace#>
create exit north <#southplace#; $parameter(1)$>
property <#southplace#; isforest>
}
if flag <create east> then {
create exit east <$parameter(1)$; #eastplace#>
create exit west <#eastplace#; $parameter(1)$>
property <#eastplace#; isforest>
}
if flag <create west> then {
create exit west <$parameter(1)$; #westplace#>
create exit east <#westplace#; $parameter(1)$>
property <#westplace#; isforest>
}
property <$parameter(1)$; createdforest>
end define

ender
21 Nov 2009, 23:56
Thank you both very much.

I had also come up with Wonderjudges thought .... which is what I had been working on but the calculations were becoming so bulky that it seemed like there should be a more elegant solution ... I didn't even think of the possiblity of problems with dropping objects though. So that creates a big problem.

Alex's solution sounds pretty good except the need to retrace the route exactly ... but that might work ... it is a haunted forest after all ... could say the forest closes in around them as they travel, forcing them to return retrace their steps... hmm... if I come up with a better solution I'll post it.

Thanks.

Freak
22 Nov 2009, 01:20
Implementing a large number of rooms with a single room (or rather, one room for the all the rooms, and one object cache) is a well-known Inform trick:
- give every object a maze-location property
- right before the player moves from a maze room:
- - loop over all objects in the maze room
- - - set that object's maze-location property appropriately
- - - move it to the cache room
-
- right before the player moves to a maze room:
- - loop over all objects in the cache room
- - - if the object's maze-location property matches the destination
- - - - move that object to the maze
- - - - clear its maze-location property

(See the middle part of Hunter in Darkness, for one example of this.) Not sure how difficult this is to do in Quest.

Alternately, if you really insist on dynamically creating rooms:
- Create a class ForestRoom
- - Every ForestRoom has properties coord_x and coord_y
- - The west property is a routine playerto <$get_forest_room(this.coord_x-1, this.coord_y)$>
- - ( similar with the other exit routines )
-
- Create a function $get_forest_room(x,y)$
- - Set variable #rv# to the string <Forest_Room_%x%_%y%>
- - Check whether room #rv# exists. If not:
- - - Create a new ForestRoom with internal name = #rv#, coord_x = %x%, coord_y = %y%.
- - return #rv#

(Code is written in an Inform 6-ish way. It shouldn't be too difficult to change it to Quest.)

ender
22 Nov 2009, 02:21
You read my mind a little bit ... after my last post I went back to it and decided to try to do it all in one room .... but using cordinates.... my inital building being 0,0 .... and then just increase, decrease the x/y as they go ... and so if they get to -1,0 and then head in the direction of 0,0 it takes them back to the building... and it worked well ... worried about people getting lost... thinking about creating a magic compass that always points back to the building ... not sure how hard it would be ...

Still had problems with the objects ... but I think your cycling over the objects in the room would be good ... maybe give them a property called 'position' with their x,y cordinate and when I go back to that x,y cord bring them back into play ... might create lag though, because I would need to run the script on EVERY object in the game to check if it had the current rooms x,y cords.

The grid system could be nice, because I could assign rooms positions too ... so I could have 'easter egg' rooms hidden in the endless forest... not sure if I will do that, but its nice to have the possibility ... but I like to keep my room count low ... especially with similar rooms...

So all of this is really good stuff. Thanks everyone. You're ideas and experience have really helped.

ender
22 Nov 2009, 04:24
Okay. This is solved. Here is my solution...

It uses one room as an 'endless room'.

This code is pretty rough, so bear with me ... I did this in a seperate 'game' that was just for testing this function. I'm sure I'll refine it a lot before I put it in my finished game, but I wanted to post it as is because I'll probably forget later.

I'm not including the full code of the module, just the relevant parts to make this work.

The basic idea is that you define an 'endless room' ... in this example its 'test2' .... and then you give two properties (x and y) to any room you want to NOT be part of the endless room ... I wrote a procedure that I put into all the exits in the endless room that does all the processing ... you also need to put it into any exit that are in another room that goes TO the endless room ... rooms without x, y coordinates are ignored. (this way you could create several rooms as the interior of a building without them having any impact on the 'endless room'... if you exit from a room without coordinates to the endless room, make sure you use a script to set the global x,y variables correctly otherwise the virtual positioning could be off.) The way it handles objects is to cycle through the list of objects in the room and assign them x and y properties of the current grid point and make them inaccessible as you leave... as you enter it checks the room for inaccessible objects with the current grid point assigned to them and makes them accessible. So objects aren't a problem.

The best feature (as far as I'm concerned) is that this system allows you distribute real rooms anywhere in your 'wilderness' grid just by assigning them grid coordinates and putting the procedure into any exit that goes back to the 'wilderness' ... this has a lot of potential for letting you do things like make spaces between towns without needing to create every single cell... the next step will be to add in barriers (i.e. once you reach grid point -64 you can't go any further west.... and get a message like "There is the grand canyon in your way! you can't go further west!") and sub 'wilderness' ... for doing things like roads ... i.e. specifying another 'endless' room that covers multiple grid points ... maybe do that by giving it sequential x values like 64, 65, 66.... but thats for another time ... what I've got will solve my immediate issues... feel free to improve, use, and do whatever with it.... (if you make significant improvements or add new features, please send me a copy)



define room <test2>
north do <EndlessRoom(n)>
south do <EndlessRoom(s)>
east do <EndlessRoom(e)>
west do <EndlessRoom(w)>
end define

define procedure <EndlessRoom>
for each object in <test2> {
if exists <#quest.thing#> then {
property <#quest.thing#; x=%x%>
property <#quest.thing#; y=%y%>
hide <#quest.thing#> } }
select case <$parameter(1)$> {
case <n> inc <y; 1>
case <s> dec <y; 1>
case <e> inc <x; 1>
case <w> dec <x; 1>
}
set <roomtemp; >
for each room in game if ( #(quest.thing):y# = %y% ) and ( #(quest.thing):x# = %x% ) then set string <roomtemp; #quest.thing#>
if ( #roomtemp# <> ) then goto <#roomtemp#> else {
for each object in <test2> if ( #(quest.thing):y# = %y% ) and ( #(quest.thing):x# = %x% ) then show <#quest.thing#>
goto <test2> }
end define

Wonderjudge
29 Nov 2009, 14:56
I actually have implement this in a game I uploaded called the maze. The object thing is a little laggy on my computer but my computer is old. I also gave different room descriptions in some parts And I have directions. The maze is 300 different rooms all in one room. The directions you could go were tricky. I stored the directions in string variables.
ie. north1=ynynynynynynnnnyn..... etc when the player goes to the next room it checks Mid (ypos*15+xpos,1).
If it is a 'y' then it creates the exit if it is 'no' then it destroys it. I also put gates so if the direction check mid contains a different character. example red gate = 'r' . then it will show the exit but you can't get by it till you deal with the red gate.
Wonderjudge
(aka Tim Hamilton)