Yet Another Question About Cloning Rooms... [SOLVED]

Hello again,
I have yet another problem with my room-cloning game. It will create rooms over other existing rooms.
I have noticed that I can, for example, that I can start in a room, go east once, go north twice, then west once and then south and the game will rebuild a room over my existing rooms. Are there any scripts that can check if a room is being built over?

My scripts are in an earlier post.

Thank you again


If you want to make it recognise the existence of a room, you will need to first have some concept of a room having a location. As far as Quest is concerned, rooms are connected by exits. They don't have a location. Only the map engine gives them coordinates.

I would suggest you give each room a couple of attributes for its coordinates. One thought might be naming them something like room1_4 or similar. Then you can use GetObject to test if the room already exists before creating it.

I think you could make your 'create room' function work something like:

  • if (room doesn't exist) {
    • create the room
  • }
  • if (room is not visited) {
    • create an exit to the room
  • }

That way you can have loops in the path (it creates an exit to an existing room rather than creating a new one) so long as the player hasn't already been to the room on the other side.


Hmm, I believe this may be a bit beyond my coding experience.
Also, would this mean that I would have to go through every room that I had created before (the rooms that are not clones) and add in coordinates for them?


I tried this with this code in each 'create room' function:

create ("room_"+game.xpos+"_"+game.ypos)
obj = GetObject("room_"+game.xpos+"_"+game.ypos)

and then changed the code in the room that is continually being cloned to:

if (game.pov.parent.visited=false) {
  sortedw = FilterByType(ScopeExitsForRoom(game.pov.parent),"westdirection")
  sortede = FilterByType(ScopeExitsForRoom(game.pov.parent),"eastdirection")
  sorteds = FilterByType(ScopeExitsForRoom(game.pov.parent),"southdirection")
  sortedn = FilterByType(ScopeExitsForRoom(game.pov.parent),"northdirection")
  if (not ListCount(sortede)=0) {
    game.xpos = game.xpos-1
  }
  if (not ListCount(sortedw)=0) {
    game.xpos = game.xpos+1
  }
  if (not ListCount(sortedn)=0) {
    game.ypos = game.ypos-1
  }
  if (not ListCount(sorteds)=0) {
    game.ypos = game.ypos+1
  }
}
if (game.pov.parent.visited=false) {
  if (ListCount(sortede)=0) {
    clonexposroom (game.pov.parent, game.pov.parent, woods)
  }
  if (ListCount(sortedw)=0) {
    clonexnegroom (game.pov.parent, game.pov.parent, woods)
  }
  if (ListCount(sortedn)=0) {
    cloneyposroom (game.pov.parent, game.pov.parent, woods)
  }
  if (ListCount(sorteds)=0) {
    cloneynegroom (game.pov.parent, game.pov.parent, woods)
  }
}

but for some reason, this causes several problems.

The first time I try to go north, the map shows the yellow player dot moving south. The next time, it appears to work fine. Going south appears to be fine.

Another problem is going west or east. If I try to go west, the map shows the player moving south and a room is show on the map to the east (right). If I try to go east, the map also shows the player moving south, but this time it creates a room to the west.

The coordinates of the player when moving east and west work fine when moving in one direction but when trying to move back in the opposite direction, it takes several turns for the game to change the coordinates. Also, during this time, the map goes absolutely crazy.

Also, whenever I leave the starting room (which is not cloned), I want it to show the geometric coordinates of the player but instead it says, only if I go north or south, "You are in room_0_0" no matter which room I am in. Afterwards it works well and displays the coordinates fine.


First thing I notice is that you have cloneyposroom for north and cloneynegroom for south; which seems to be the opposite way around from how Quest's map coordinates work. That likely isn't an issue, because the two coordinate systems shouldn't affect each other, but it could lead to confusion at some point.

in the room that is continually being cloned

I'm a little confused by your terminology. You talk about a room being cloned, but you seem to be creating new rooms, not cloning.

It's hard to work out what the issue is here, because I don't seem to have the full context. Individual snippets of code without explanation of how they connect together don't give the full picture. Is it possible to share the game? Or to post all of the relevant code (including the function headers) from full code view?

I think I could get my head around this more easily if I could walk through the code in my head, following what the state of your variables is at each point.


Sure, I'll share the game. Here's the link. My terminology was just an error.


This seems like there's an awful lot of repeated code for the new room; which is tripping over itself.

So… what you are doing is:

  • Enter the first room. game.xpos and game.ypos are both zero
  • If we haven't visited this room before:
    • Check if there are exits to the east. If so, subtract 1 from game.xpos. (There aren't, so it's still 0)
    • Check if there are exits to the west. If so add 1 to game.xpos. (There aren't, so it's still 0)
    • Check if there are exits to the north. If so subtract 1 from game.ypos. (There aren't, so it's still 0)
    • Check if there are exits to the south. If so add 1 to game.ypos. (There aren't, so it's still 0)
  • If we haven't visited this room before:
    • Check if there are exits to the east. There aren't, so try to create the room specified by xpos and ypos (currently room0_0)
      • The room already exists (it's this one), so just create an "east" exit leading to it
    • Check if there are exits to the west. There is, the reverse exit for the one you just created, so do nothing.
    • Check if there are exits to the north. There aren't, so try to create the room specified by xpos and ypos (currently room0_0)
      • The room already exists (it's this one), so just create an "north" exit leading to it
    • Check if there are exits to the south. There is, the reverse exit for the one you just created, so do nothing.

I would suggest that each room, rather than the game, has an X and Y coordinate. And it doesn't seem efficient to have a separate function for each direction.

So you'd probably be better with just one function, something like:

<function name="createnewroom" parameters="fromRoom, direction, template">
  // Work out the coordinates of the new room:
  xpos = fromRoom.xpos
  ypos = fromRoom.ypos
  switch (direction) {
    case ("north") {
      ypos = ypos - 1
      reverse = "south"
    }
    case ("south") {
      ypos = ypos + 1
      reverse = "north"
    }
    case ("west") {
      xpos = xpos - 1
      reverse = "east"
    }
    case ("east") {
      xpos = xpos + 1
      reverse = "west"
    }
  }

  // Work out the name of the "new" room
  roomname = "room"+xpos+"_"+ypos
  // (can't have a negative number in a room name, so change it to a letter)
  roomname = Replace (roomname, "_-", "_n")
  roomname = Replace (roomname, "-", "w")
  obj = GetObject (roomname)

  // If the room doesn't exist, create it
  if (obj = null) {

    // If you have 'special' rooms that appear at specific coords, or something like that
    // or if there is a chance of a room being a different type of terrain
    // you could include code here to check for those xpos/ypos and change what is created

    create (roomname)
    obj = GetObject (roomname)
    obj.xpos = xpos
    obj.ypos = ypos

    foreach (attribute, Split("enter;firstenter;exitslistprefix;descprefix;isroom;beforefirstenter;description;prefix;usedefaultprefix")) {
      set (obj, attr, GetAttribute (template, attr))
    }
    obj.parent = fromRoom.parent
    obj.visited = false
  }

  // Now, we know that obj exists, whether we just created it or it was there before
  // But we only want to create doors into it if we haven't been there before.
  //    It would be weird creating new exits to a place the player has already been
  if (not GetBoolean (obj, "visited")) {
    create exit (direction, fromRoom, obj, direction+"direction")
    create exit (reverse, obj, fromRoom, reverse+"direction")
  }
</function>

(That's pretty much the structure I suggested before: Check if the room exists before creating it, and then check if it's already been visited before creating new exits in it. Just moving the xpos/ypos calculations inside the function)

And then your beforefirstenter script would be:

exits = ScopeExitsForRoom (this)
foreach (direction, Split("north;south;east;west")) {
  if (ListCount (FilterByType (exits, direction+"direction")) = 0) {
    createnewroom (this, direction, woods)
  }
}

Thank you so much, this works well.

Would you have any tips on how to continue the creation of rooms pretty much endlessly? Like in an open-world rpg.

Should I put code in the beforefirstenter script of the room that is the template that creates more rooms? If so, what should I put as the room's xpos and ypos?


Would you have any tips on how to continue the creation of rooms pretty much endlessly? Like in an open-world rpg.

Should I put code in the beforefirstenter script of the room that is the template that creates more rooms? If so, what should I put as the room's xpos and ypos?

I assumed that was the intention; if every room has that beforefirstenter script, it should keep on creating rooms as far as the player walks.

If so, what should I put as the room's xpos and ypos?

You shouldn't need to, I think. Every time that script creates a room, it sets its xpos and ypos based on the adjacent room. The only room you need to give coordinates for is the first one, which I suspect would be 0_0.

As far as creating an open world, I think the next additions would be adding things to the rooms to make them distinct. You could do this when creating the rooms; or you could give the template rooms a beforefirstenter script that adds items or description to the room after creating the adjacent areas.

How you go about this would depend very much on the type of game you're trying to create. I've used a room-creation system before to both make a faerie woodland (where the map distorts itself and rooms move around on the map) and a random dungeon generator (with a dozen different room types which can be chosen at random); and the systems involved are quite different.

I'd be happy to help out with any further coding issues :)


Thank you so much!

This has given me some very interesting ideas to think over.


This topic is now closed. Topics are closed after 60 days of inactivity.

Support

Forums