General Code Help

Yes.

The former. When applied to objects, the == operator does not check for equality, but for identity. Even if two objects, obj1 and obj2, would otherwise be equal (like when you have two copies of the same object, or two vectors with the same contents), “obj1 == obj2” will evaluate to nil, because they are not the same object. This is because objects in TADS use reference semantics.

Note that this only applies to objects. Other types use value semantics. Two different variables for example will be equal if they contain the same number. Also note that lists are value types, not objects.

Thanks, Real. How do I check if two objects are the same? I need to test if my creature target on Monster class target member = target found in a loop of room contents so I can update the actual obj health after damage.

I added more info in my post.

But I’m not sure I understand the question. You want to check if two objects are the same object? You just use “==”.

Sorry, I guess the message was a little confusing:

“When applied to objects, the == operator does not check for equality, but for identity.”

That’s what I want to do.

“Even if two objects, obj1 and obj2, would otherwise be equal (like when you have two copies of the same object, or two vectors with the same contents), “obj1 == obj2” will evaluate to nil, because they are not the same object.”

That’s what’s making it confusing because two copies of the same object is exactly what I have. I have a monster class with a member called target. I set that target by looping over room contents and choosing a random Actor. I’ve applied damage in my attack function but now I have to update the actual room object from my member target.

They are the same object, but they don’t have all the same values anymore.

== will work, or will that give ‘nil’ in return.

That leads me to another question.

If I do this:

local room = self.getOutermostRoom();

And update room.contents will that affect the actual contents in the room or just that copy. Kind of a dumb question at this point, but getting worried now, lol.

I don’t understand:

“They are the same object, but they don’t have all the same values anymore.”

If they are the same object, they have the same values.

No, they have the same members, but different values. I’ve updated the target in the target member on the class. It shouldn’t be the same as the object in the room, unless there is a pointer.

I still don’t understand. You said you have two copies of the same object. How do you make a copy of an object?

Yeah, that’s what’s messing us up. I don’t know if it’s making a copy by reference or a copy by val.

 local room = self.getOutermostRoom();
 local roomObjects = room.contents;
 local targetList = [];

I then looped over the roomObjects list and if it was kindOf Actor and !Monster it is a Actor that gets added. If it was kindOf Monster and Actor it was a monster that got added. I select a target from the target list randomly depending on if the monster can target just characters or other monsters too. That gets added to target on my Monster class.

Here’s a member list on Monster:

 name = ''
    desc = ''
    mp = 0
    isAgressive = nil
    getsAgressive = nil
    getsAgressiveOnlyStruck = nil
    agressiveChance = 0
    canFly = nil
    isFlying = nil
    canBurrow = nil
    hasBurrowed = nil
    canClimb = nil
    isClimbing = nil
    canSwim = nil
    hasSwam = nil
    hasDoubleAttack = nil
    doubleAttackChance = nil
    willTargetMonsters = nil
    willTargetSameTypeMonster = nil
    spells = []
    attacks = []
    specials = [] // a list of specials by string 'fly' 'swim' 'burrow' 'climb' 
    rewards = []
    cutScenes = []
    upperGold = 0
    lowerGold = 0
    lowerXP = 0
    upperXP = 0
    atkCounter = 0
    atkCount = 0
    target = nil
    targetChance = 0
    targetActorChance = 0
    changeTargetChance = 0
    spellChance = 0
    specialChance = 0
    specialEndChance = 0
    hitsTaken = 0
    actionDaemon = nil

Now when I update my target in my attack function I assume I’m just updating a shallow copy and now need to set the hp on that target to the hp on the room object again. I don’t want to just be updating shallow copies in my class.

 attack(attacks)
    {
        // attack
        
        local normalAttacks = [];
        
        foreach(local x in attacks)
        {
            
            if(!x.isSpecial)
            {
                
                normalAttacks = normalAttacks.append(x);
                
            }
            
        }
        
        if(normalAttacks.length() >= 1)
        {
            // making attack
            
            local ind = self.roll(1, normalAttacks.length());
            
            local attack = normalAttacks[ind];
            
            local dmgRoll = self.roll(attack.lowerDmg, attack.upperDmg);
            
            local damage = (dmgRoll) - (self.target.armourClass + self.target.defBonus);
            
            damage = max(0, damage);
            
            self.target.hp = self.target.hp - damage;
            
            self.target.hp = max(0, self.target.hp);
  
            
            // loop to find actual target in room and apply damage
            
            
            
            // output damage desc
            if(!attack.hasLongDesc)
            {
            
                "<<self.name>> <<attack.verb>> <<self.target.name>> for <<damage>>dmg.";
            
            }else{
                
                // use attack long description
                
                local indCount = attack.longDescriptions.length();
                local descInd = self.roll(1, indCount);
                
                "<<attack.longDescriptions[descInd]>>";
                
   
                // end use attack long description
            }
                // show attack output
            
            // end making attack
        }
        
       // end attack
    }

Basically:

- looping through room contents
if(room.cur == self.target)
{

   cur.hp = self.target.hp
 
}

What is messing me up is my understanding of accessing the actual object, as apposed to making a copy of it to store elsewhere, lol.

if I call:

room = obj.getOutermostRoom();
roomContents = room.contents

When I edit roomContents am I updating actual room objects, or a shallow copy? If I would be updating the actual value of the room object, wouldn’t it be the same for my target on Monster class?

The ‘contents’ property is a list, so it uses value semantics. ‘roomContents’ is a copy. See:

tads.org/t3doc/doc/sysman/list.htm

Quote from that page:

“even if several variables refer to a list value, each variable effectively has its own private copy of the list, so changes made to one variable’s list won’t affect any others.”

However, it’s not advisable to modify the ‘contents’ property. It should be treated as an internal property. When you want to remove an object from a location, use moveInto(). There are a lot of things that need to happen when moving an object from one location to another. It’s not just a matter of putting it or removing it from the ‘contents’ property.

That answers one question. It is a shallow copy. So how do I update the original?

This section of code can’t be completed if I can’t access the original object in the room:

 local ind = self.roll(1, normalAttacks.length());
            
 local attack = normalAttacks[ind];
            
 local dmgRoll = self.roll(attack.lowerDmg, attack.upperDmg);
          
 local damage = (dmgRoll) - (self.target.armourClass + self.target.defBonus);
           
 damage = max(0, damage);
            
 self.target.hp = self.target.hp - damage;
            
 self.target.hp = max(0, self.target.hp);
                        
  // loop to find actual target in room and apply damage

You don’t. You use moveInto() instead of trying to modify the ‘contents’ property.

Now I’m horribly confused. What object? We were talking about the ‘contents’ property, which is a list. If you use the = operator with it, you take a shallow copy of the list. All the contents of that list are the same objects as those in the original list, they are not copies.

I don’t need moveInto, because I’m not adding a new object to the room. I’m trying to update an object that already exists in the room.

I want to transfer my target.hp onto the actual object. I’ll simplify the code.

class Monster
     target = nil

set_target()
{

   local room = self.getOutermostRoom();
   local roomObjects = room.contents;

   foreach(local x in roomObjects)
  {

      self.target = random index from roomObjects if type Actor
  
   }

}

attack()
{

    self.target.hp - 10;

} 

updateTarget()
{
 
   // make room object that is the target have hp = self.target.hp 

}

;

I’m stuck in the updateTarget part of my logic. If I’m working with a copy, how do I do the update part?

‘self.target’ IS the object you want. As said before, objects in TADS are not copied. They use reference semantics:

local obj1 = someObj;
local obj2 = obj1;

‘someObj’, ‘obj1’ and ‘obj2’ are all the same object. It doesn’t matter if you write ‘obj1.hp = 10’ or ‘someObj.hp = 10’. It will modify the ‘hp’ property of the same object.

Sorry, I could have swore you said value semantics, lol. Sorry about that. So every time I do this:

local room = self.getOutermostRoom();
local roomObjects = room.contents;

Tads 3 has internally used pointers to give me actual memory access to the original objects for each object in the list? Or in the least, effectively gave me the equivalent. Even if I transfer an object from the list to a member, like my target member?

Yes. It’s a pointer underneath, but that pointer is never exposed to you.

perfec :slight_smile: Sorry that was difficult lol. Thanks for the aid.

I hate to ask a simple bug question but my switch case isn’t working in dobjFor(Wield). The error complains about unbalanced braces. I’ve taken all the code out and still has the same complaint.

Edit: Nevermind, sorry. My error was spelling switch as stwich.

I’m making a wield verb but it’s giving me problems with gDobj being a nil object reference. It’s right at the start. There’s more code, but it’s all inside the if statement.

dobjFor(Wield)
 {
       
      verify()
        {
        
              if(!gDobj.isHeldBy(gActor))
              {

              } 

         }

  }

The global variables (gDobj, gIobj, …) are not known till the very end the the verify process. The global variables are not normally used in verify for that reason. If you change your code to what I have below the nil object reference should go away.

dobjFor(Wield)
 {
       
      verify()
        {
        
              if(gDobj && !gDobj.isHeldBy(gActor))
              {

              } 

         }

  }

That is basically checking to make sure gDobj is non nil before going any further.