Mapping everything

E.K.Virtanen
25 Oct 2020, 15:26

Hi,

my idea is to reveal the whole map at the start of the game. Now i did find something usefull from tutorials, however im not sure where i should write that example script.

Tutorial is at https://docs.textadventures.co.uk/quest/showing_a_map.html
and bit after halfway there is subject Mapping everywhere


if (not GetBoolean(room, "genvisited")) {
  room.genvisited = true
  Grid_CalculateMapCoordinates (room, game.pov)
  // Grid_DrawRoom (room, false, game.pov)
  foreach (exit, AllExits()) {
    if (exit.parent = room) {
      VisitRoom (exit.to)
    }
  }
}

Im using a desktop version of Quest.

Thanks, E.K.


Pertex
25 Oct 2020, 16:27

It is described exactly in the tutorial! Your code must be put into a function called "VisitRoom" and this function must be called in the start script of the game


Pykrete
25 Oct 2020, 17:25

Question! I've always wondered this, but keep forgetting to ask. Will doing this have any effect on room before/after first time scripts? I use those a lot.


E.K.Virtanen
25 Oct 2020, 19:28

Ok, did find button code view. That solved my problem.

What Pykrete asked interests me too tho.


mrangel
25 Oct 2020, 20:33

(I see you have a solution; but I don't like the code in that tutorial. My inner programmer wants to see if I can improve it)

It seems a little inefficient to do this recursively.
Also, you're looping over AllExits() once for every room. Might be faster to create a lookup table first.

Wouldn't it be more elegant to do something like:

exits_by_room = new Dictionary()
foreach (exit, AllExits()) {
  if (HasObject (exit, "parent") and HasObject (exit, "to") and DoesInherit (exit, "direction")) {
    if (DictionaryContains (exits_by_room, exit.parent.name)) {
      list = DictionaryItem (exits_by_room, exit.parent.name)
    }
    else {
      list = NewObjectList()
      dictionary add (exits_by_room, exit.parent.name, list)
    }
    list add (exit.to)
  }
}

// The next line sets the coordinates for the current room to zero. Only necessary if the starting room hasn't been drawn yet
game.pov.grid_coordinates = QuickParams (game.pov.paren.name, QuickParams ("x", 0, "y", 0, "z", 0))

rooms_to_scan = NewObjectList()
roomnumber = 0
list add (rooms_to_scan, game.pov.parent)

while (roomnumber < ListCount (rooms_to_scan)) {
  room = ListItem (rooms_to_scan, roomnumber)
  roomnumber = roomnumber + 1
  Grid_CalculateMapCoordinates (room, game.pov)
  // Grid_DrawRoom (room, false, game.pov)
  if (DictionaryContains (exits_by_room, room.name)) {
    roomlist = DictionaryItem (exits_by_room, room.name)
    foreach (room, roomlist) {
      if (not ListContains (rooms_to_scan, room)) list add (rooms_to_scan, room)
    }
  }
}

(yeah, it's more code. But I think it should also be more efficient and more robust)

(also, if you're curious about stuff like that, you could print out the rooms_to_scan list; as it will contain a list of all rooms in order of distance from the starting point)


E.K.Virtanen
25 Oct 2020, 21:09

Coding is not the problem. Been done that for ages. But for me knowing the code causes a problem. I spend 95% of time thinking of fastest and most optimized way to code. End result is half a million lines of code, not a single finished game or program ;)

For me, getting used to this new way to work makes problem. Before everything was on that ide and i controlled everything. So yes, this works for both ways.


Pykrete
26 Oct 2020, 18:22

I suppose I could answer my own question by inserting the code and running the game, then seeing if my scripts still work. d'oh! Will report back later.


mrangel
26 Oct 2020, 20:22

Question! I've always wondered this, but keep forgetting to ask. Will doing this have any effect on room before/after first time scripts? I use those a lot.

No. Those rely on the attribute visited, which is set by the function OnEnterRoom.


And now I think about it, Grid_CalculateMapCoordinates is still looping over all exits to find the ones for the rooms it's calculating. That's inefficient. Realistically, it might make more sense to divide the map up into "worlds". Initially each room is its own world. Then you loop over all exits, and if the exit connects rooms that are in different worlds, you loop over all rooms in the smaller world and add on an offset to their coordinates to join those two worlds together. I think that makes the complexity O(N log N) with respect to the number of rooms.

I did wonder if it might be possible to modify Grid_CalculateMapCoordinates in a way that it doesn't recalculate the coordinates of the adjoining room each time the player moves; because that seems rather an inefficient way to do it, especially when you're having to consider so many exits every time. And I think it could be done, but you would instead need to manually recalculate the map if any room or exit's grid size changes. I'm going to try rewriting some of the grid library to make it more efficient; but not today, as I'm currently on chapter 498 of the story I'm writing, and I've put off finishing it for way too long.