Script for 'back'

OurJud
12 Dec 2016, 20:18

Instead of conventional compass directions, I'm using go [room name] during interior locations such as houses.

As there's a fair bit of flitting back and forth between rooms I would like to provide an option to use back and/or b to switch between rooms, so that instead of:

You are in the hallway. The kitchen is at the far end.
> go kitchen

You are in the kitchen. The doorway leads back to the hallway.
> go hallway

You are in the hallway. The kitchen is at the far end.
>

they can use:

You are in the hallway. The kitchen is at the far end.
> go kitchen

You are in the kitchen. The doorway leads back to the hallway.
> b

You are in the hallway. The kitchen is at the far end.
>

Is there a global script of some sort that would do this? I'm thinking something along the lines of a command with back; b; go back and then a script: goto PreviousLocation


OurJud
12 Dec 2016, 20:36

There's an undo script, so a custom command with the following script does what I want.

undo
ShowRoomDescription

But it displays a message saying Undo: go living room

Any way to disable this? I've found the default Undo command in libraries, but I get errors if I customise it.

It also throws this error if I try to switch back and forth between two rooms with b

Error running script: The given key was not present in the dictionary.

The Pixie
12 Dec 2016, 21:26

What happens if the play goes to a room, picks something up, and then does BACK?


OurJud
12 Dec 2016, 22:27

Ah! Yes, they'll put it down. Well spotted.

Any ideas then? Is there any kind of PreviousLocation script or jiggery pokery Black Magic that will do this?


hegemonkhan
12 Dec 2016, 23:30

you got to code/script that in... you need to store/save the old location/room to an Object Attribute, and then you can use that Object Attribute to go back to your previous location/room, but it's slightly more tricky too (to properly handle the correct value/room/location being put/stored/saved into your Object Attribute), see below, for example of such a scripting for moving:

// initially:

game.previous_room = room
game.current_room = room

// before/as you move to a new location/room, you're still in the old room: room

game.previous_room = game.current_room // you haven't moved yet to the new location/room, so we're storing/saving this old room/location: room
MoveObject (game.pov, room2) // now, you're moving to, and in, the new room: room2
game.current_room = game.pov.parent // game.current_room = game.pov.parent = room2

// if we were to move to room3, executing the moving script again:

game.previous_room = game.current_room // you haven't moved yet to the new location/room, so we're storing/saving this old room/location: room2
MoveObject (game.pov, room3) // now, you're moving to, and in, the new room: room3
game.current_room = game.pov.parent // game.current_room = game.pov.parent = room3

// if we were to move to room4, executing the moving script again:

game.previous_room = game.current_room // you haven't moved yet to the new location/room, so we're storing/saving this old room/location: room3
MoveObject (game.pov, room4) // now, you're moving to, and in, the new room: room4
game.current_room = game.pov.parent // game.current_room = game.pov.parent = room4

// etc etc etc

hegemonkhan
12 Dec 2016, 23:49

and the 'back' Command, would be something like this, an example:

<command name="back_command">
  <pattern>back</pattern>
  <script>
    MoveObject (game.pov, game.previous_room)
  </script>
</command>

if you want to be able to (selectively choose how many) 'go backs multiple times', then you'd need to store/save (add) each of the previous rooms to an Objectlist Attribute instead, and the 'back' Command would be this:

<command name="selective_multiple_back_command">
  <pattern>back #text#</pattern>
  <script><![CDATA[
    if (IsInt (text) and GetInt (text) > 0 and GetInt (text) <= ListCount (game.previous_room_objectlist_attribute)) {
      x_variable = GetInt (text) 
      MoveObject (game.pov, ObjectListItem (game.previous_room_objectlist_attribute, ListCount (game.previous_room_objectlist_attribute) - x_variable))
    } else {
      msg ("Wrong input, your inputted value must be an integer greater than zero and an integer less than or equal to the number of items in your previous room Objectlist Attribute")
    }
  ]]></script>
</command>

// depends on what you want with design... we may need to remove those old locations from our Objectlist Attribute, or maybe you want/need to have two Objectlist Attributes, one that doesn't change and one that does change. I can explain why, if you don't see the design concept of why these would be needed to be done, if it's what your design requires.


if you just want it to go back multiple times --- no selection:

<command name="non_selective_multiple_back_command">
  <pattern>non_select_multiple_back</pattern>
  <script>
    object_variable = ObjectListItem (game.previous_room_objectlist_attribute, ListCount (game.previous_room_objectlist_attribute) - 1)
    MoveObject (game.pov, object_variable)
    list remove (game.previous_room_objectlist_attribute, object_variable)
  </script>
</command>

OurJud
13 Dec 2016, 00:58

Thanks, hege, but if the only way to do this is to use that first block of code for EVERY single location, I can do without it.

I just hoped there was some function like GotoPreviousLocation in the same way there's a ShowRoomDescription.


hegemonkhan
13 Dec 2016, 06:01

in terms of going back to a previous location, this works for every/any location and going to any location (just like ShowRoomDescription), such a place to put the scripting so you only have to place it once (no redundent code of copy-paste), would be to use the special (specifically) 'changedparent' Script Attribute on/for your 'game.pov' Player Object, for example:

<object name="room">
</object>

<object name="room_1">
</object>

<object name="room_2">
</object>

<object name="room_3">
</object>

<object name="room_4">
</object>

<object name="room_99">
</object>

<object name="player">
  <attr name="parent" type="object">room</attr> // initial location
  <attr name="previous_room" type="object">room</attr> // initial (object reference) value
  <attr name="current_room" type="object">room</attr> // initial (object reference) value
  <attr name="changedparent" type="script">
    this.previous_room = this.current_room
    this.current_room = this.parent
  </attr>
</object>

<command name="goto_previous_room_command">
  <pattern>goto_previous_room</pattern>
  <script>
    MoveObject (game.pov, game.pov.previous_room)
  </script>
</command>

or you could try putting the scripting into here, IF you're moved into the room BEFORE this scripting is run (you have to see if it works or not --- if it doesn't work, then the scripting is run before you're moved into the room):

(I did try this myself quite some time ago, so-but I this: forgot / don't remember, and I am too lazy to test it again myself, so you can test/try it, lol)

'game' Game Object -> 'Scripts' Tab -> 'Script when entering a room' Script -> (add new script / set it up: see below)

game.pov.previous_room = game.pov.current_room
game.pov.current_room = game.pov.parent

this is an example of when/if using this (aka: you have the Attributes added/within your 'game.pov' Object):

<object name="room">
</object>

<object name="player">
  <attr name="parent" type="object">room</attr>
  <attr name="previous_room" type="object">room</attr>
  <attr name="current_room" type="object">room</attr>
</object>

The Pixie
13 Dec 2016, 08:19

You should think what you want to happen if the player does:

BACK
BACK

Would that leave the player in the original room, or two locations away? If the latter, change the changedparent script for the player to save the past locations in an object list.


hegemonkhan
13 Dec 2016, 12:18

yes, indeed, my latest/previous post is just a very simple example design of directly going back to the previous room only (ie: you can continuously do this: roomA <----> roomB).


My earlier posts give examples of more advanced handling design.


It also synchronously depends upon how OurJud designs his/her game too... Exits' and/or move-scripting's, and their paths', design...


OurJud
13 Dec 2016, 16:42

All in all, given how complicated and time-consuming adding this script would be, not to mention the conflicts it could cause, it's not really a workable idea.


TinFoilMkIV
14 Dec 2016, 17:47

If you're still considering this at all I think I have a method for basic back functionality. Basically use a 'changedparent' script on the player to save their previous location. Then have back check the current exits 'to' attribute to see if any match the previous room, if yes, then go there, if no let the player know they have no way to get back from there.

If you wanted to get somewhat fancy with multiple backs allowed you'd have to make a list out of previous locations then just remove the latest each time you went back.

ie:

player 'changedparent' script
prevroom = oldvalue
back command
//check for exit leading to previous room
foreach (exit , ScopeExits ()) {
if (exit.to = game.pov.prevroom) {
destination = exit.alias
}
}
//if found go there
if(IsDefined ("destination")){
HandleSingleCommand ("go " + destination)
}
//if not then no path is available
else {
msg("There doesn't seem to be a way back from here")
}


OurJud
14 Dec 2016, 17:59

Thanks for this, TinFoil, but my aim was to save people having to type go [room name] in full every time. This was before I realised they could just use the first letter of the room, meaning go k does the same as go kitchen which is far less of a pain.


TinFoilMkIV
14 Dec 2016, 18:45

No worries, I wanted to see if I could get it for myself as well even though I have no immediate use for it either. Seems like it should be a useful bit of code to know.


OurJud
14 Dec 2016, 19:27

Yes, definitely. Any snippets like this are worth cataloguing. Maybe an idea to post it in the library with full usage instruction - where it goes, etc.


hegemonkhan
14 Dec 2016, 21:13

Sequentially going back (pushing/popping onto/off a stack --- via a list with quest: add/remove item from list, or even without removing items as well, iterating a stack: using an Attribute to hold the value that determines the index number for the list item) and selectively going back (using 'get input' and a list), isn't too code-wise complex, my previous post gave an example of each of these, as well as a simple immediate/single back too.

The curious question is what is the data size of a list/dictionary in quest, laughs. How many items can a list/dictionary have?