Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Object reference and changing multiple values

I work on Twine 2, with story format Harlowe 1.2.3.
I wanted to prepare a few objects, e.g:
(set: $object1 to (datamap: "name", "Object 1", "value", 1))
(set: $object2 to (datamap: "name", "Object 2", "value", 2))

and then I want to create an object which is the reference to one of this previous objects
e.g.:
(set: $currentObject to $object1)
Now everything's ok, when I call : (print: $currentObject's name) the result is "Object 1", when I change: (set: $currentObject to $object2) and call again (print: $currentObject's name) the result is proper: "Object 2".
When I change one of the values of datamap (set: $currentObject' value to 5) and when I change the current object and back to previous one - everything seems to work fine. The problem is when I want to change more than one value of current object.
E.g.:
This works:
(set: $currentObject to $object1) ... (set: $currentObject's value to 5) ... now I can change current object, then back to object1 and the value is changed,

This don't work and I don't know why:
(set: $currentObject to $object1) ... (set: $currentObject's value to 5, $currentObject's name to "New Object's name")
and change object to $object2 and then I back to the object1 - it shows the old, unchanged values.
I don't know why, when a I change 1 value - everything's ok, when I want to change more - it don't work at all.

Comments

  • When you modify an element/property of a Harlowe Collection data type the following process** occurs:

    1. A 'copy' of the collection referenced by the specified variable is made.

    2. The relevant element/property of the 'copy' is assigned the new value.

    3. The specified variable is changed to reference the modified 'copy' collection.

    This is easily demonstrated by the following test-case:
    Create an Array and assign a reference to it to a second variable then compare the 2nd element of both references:
    {(set: $array1 to (array: "A", "B", "C"))
    (set: $array2 to $array1)} \
    A1 - (print: $array1's 2nd)
    A2 - (print: $array2's 2nd)
    
    Modify the 2nd element of the array using the first reference then compare them again:
    (set: $array1's 2nd to "D")\
    A1 - (print: $array1's 2nd)
    A2 - (print: $array2's 2nd)
    
    Modify the 2nd element again and repeat the comparison:
    (set: $array1's 2nd to "E")\
    A1 - (print: $array1's 2nd)
    A2 - (print: $array2's 2nd)
    
    Create a DataMap and assign a reference to it to a second variable then compare the 'Second' property of both references:
    {(set: $map1 to (datamap: "First", "A", "Second", "B", "Third", "C"))
    (set: $map2 to $map1)} \
    DM1 - (print: $map1's Second)
    DM2 - (print: $map2's Second)
    
    Modify the 'Second' property of the map using the first reference then compare them again:
    (set: $map1's Second to "D")\
    DM1 - (print: $map1's Second)
    DM2 - (print: $map2's Second)
    
    Modify the 'Second' property again and repeat the comparison:
    (set: $map1's Second to "E")\
    DM1 - (print: $map1's Second)
    DM2 - (print: $map2's Second)
    

    ** For practical purposes I have simplified the technical information, this means that it is not 100% accurate but the end results are the same.
  • Thanks for the answer. That's actually a little different case because my goal is to change the second object:
    (set: $array2's 2nd to "D")\
    A1 - (print: $array1's 2nd)
    A2 - (print: $array2's 2nd)
    
    And then:
    (set: $array2's 2nd to "E")\
    A1 - (print: $array1's 2nd)
    A2 - (print: $array2's 2nd)
    

    And again, the first "set" is ok, but the second change - is not.
    Is there any posibility to change values of original object by reference object.
    I'm affraid, in my case, the only option is to change $currentObject and if something has to be changed - check if $currectObject is object1 or object2 or... and then change the original object, but it will make my code much longer.
  • change the second object
    When you do two initial assignments like the following:
    (set: $map1 to (datamap: "First", "A", "Second", "B", "Third", "C"))
    (set: $map2 to $map1)
    
    ... there is no 'second object', you have two variables referencing the same collection object.
    That's actually a little different case...
    It is actually the same case because it does not matter which of the two (reference) variables ($map1 or $map1) you use to access the original collection object during the property update the end result is the same, after the update each of those reference variables will point to their own unique collection object.
    Is there any possibility to change values of original object by reference object.
    Not that I know of, for the reasons I stated previously.
  • edited April 2017
    greyelf wrote: »
    ... there is no 'second object', you have two variables referencing the same collection object.
    So why changing one of them do not affect to another?
    Maybe there's something weird with the datamap or rather the references in this script language, which I don't understand but e.g. in Java something like this works without any problems:
    object1.name = "First object";
    object2.name = "Second object";
    tempObject = object1;
    tempObject.name = "Another object";
    System.out.println(object1.name);  // Output is: "Another object"
    object1.name = "Different object";
    System.out.println(tempObject.name);  // Output is: "Different object"
    
    Now I can swap objects and everything just works.


    Generally, I just want to make a game with different locations:
    (set: $location1 to (datamap: 
    "name", "Location 1",
    "settlers", 0,
    "food", 0,
    "water", 0))
    (set: $location2 to (datamap: 
    "name", "Location 2",
    "settlers", 0,
    "water",
    "food"))
    
    (set: currentLocation to $location)
    

    Then I want to allow to change the current location
    e.g. (main passage "LOCATION", which is the main game page)
    (if: $currentLocation is not $location1)[(link: "Location 1")[(set: $currentLocation to $location1)(goto: "LOCATION")]]
    (if: $currentLocation is not $location2)[(link: "Location 2")[(set: $currentLocation to $location2)(goto: "LOCATION")]]
    
    On every location I want to search for some supplies (search supplies passage):
    (set: $currentLocation's water to it + (either: 1,2,3))
    (set: $currentLocation's food to it + (either: 1,2,3))
    
    And now the problem occurs. When I change only the first value (water) - it's ok, but when I change both of the values something strange is happen with the $currentLocation variable - in the main passage (LOCATION) the both links are available, which means $currentLocation is neither $location1 nor $location2. When I change the location the only first values (water) are correct, the second changed value remains as original "0". That's really strange.
  • ...in Java something like this works without any problems.
    That is because Java handle property assignment (eg. object.property = "value") differently than Harlowe.

    So why changing one of them do not affect to another?
    Obviously the first time I explained what is happen in Harlowe was not clear enough, so this time I will use more detailed descriptions as well as the same variable names as your example.

    1. Initial creation of the datamap collection object and assignment of the two variables.
    (set: $location1 to (datamap:
    	"name", "Location 1",
    	"settlers", 0,
    	"food", 0,
    	"water", 0))
    
    (set: $currentLocation to $location1)
    
    location1 water: (print: $location1's water) food: (print: $location1's food)
    currentLocation water: (print: $currentLocation's water) food: (print: $currentLocation's food)
    
    At this point both $location1 and $currentLocation are referencing the same object.


    2. Changing the value of the water property of a specified reference variable.
    note: It does not matter which reference variable you use, the outcome is the same.
    (set: $currentLocation's water to it + (either: 1,2,3))
    
    location1 water: (print: $location1's water) food: (print: $location1's food)
    currentLocation water: (print: $currentLocation's water) food: (print: $currentLocation's food)
    
    The result of the above assignment is:


    2a. The water property of the original collection object is updated.

    2b. A 'copy' of the updated collection object is made, lets call this non-original for simplicity sake.

    2c. The (non-specified) $location1 variable still references the original collection object.

    2d. The (specified) $currentLocation variable now references the non-original collection object.

    outcome: The two variables are no longer referencing the same object but all the properties of each of the two collection objects appear to have the same values.


    3. Changing the value of the food property of a specified reference variable.
    (set: $currentLocation's food to it + (either: 1,2,3))
    
    location1 water: (print: $location1's water) food: (print: $location1's food)
    currentLocation water: (print: $currentLocation's water) food: (print: $currentLocation's food)
    
    The result of the above assignment is:

    3a. The food property of the non-original collection object is updated.

    3b. A 'copy' of the updated non-original collection object is made, lets call this other for simplicity sake.

    3b. The (non-specified) $location1 variable still references the original collection object, which was not changed.

    3d. The (specified) $currentLocation variable now references the other collection object.

    outcome: The food property of each of the two collection objects, the original referenced by $location1 and the other referenced by $currentLocation, now have different values.
  • Thank you very much for your help!
    Now I understand how it works, more or less.

    In my case (if we take my example from previous post), is the only way to change the values on currently visited location something like this (I've tested it and it should work now) ?

    First passage (initialisation):
    [[NEXT]]
    (set: $location1 to (datamap:
    	"name", "Location 1",
    	"settlers", 0,
    	"food", 0,
    	"water", 0
    ))
    (set: $location2 to (datamap:
    	"name", "Location 2",
    	"settlers", 0,
    	"food", 0,
    	"water", 0
    ))
    (set: $currentLocation to $location1)
    

    Passage: "NEXT"
    Location 1:
    (print: $location1)
    Location 2:
    (print: $location2)
    currentLocation:
    (print: $currentLocation)
    
    (link: "add settlers in current location")[
    (if: $currentLocation's name is "Location 1")[(set: $location1's settlers to it +10)
    (set: $currentLocation to $location1)(goto: "NEXT")]
    (if: $currentLocation's name is "Location 2")[(set: $location2's settlers to it +10)
    (set: $currentLocation to $location2)(goto: "NEXT")]]
    
    Change location:
    (link: "change current location to location1")
    [(set: $currentLocation to $location1)(goto: "NEXT")]
    (link: "change current location to location2")
    [(set: $currentLocation to $location2)(goto: "NEXT")]
    

    It seems to me that now everything works as it should.
    Is it the only way to obtain the same (or similar) results? To use $currentLocation more like a temporary datamap and only for checking/printing current locations values and then assign $currentLocation to the right location based on the name.
    For now I have no idea how can I improve this or there is any chance to make it better.
    Any suggestions?
Sign In or Register to comment.