Using "this" for persistent variables across multiple chooseAction calls


#1

Whenever I seem to use the this for persistent variables, the value of this.varaibleName seems to get stuck to whatever it is set to the first time.

Here is some code that demonstrates the issue. This was ran on Brawlwood, on the humans side, under the chooseAction() for the solider.

this.foo = function() {
    this.state = "true";
};

this.bar = function() {
    this.state = "false";
};

if (this.now() > 3.0) {
    this.foo();
} else {
    this.bar();
}

this.say(this.state);

Any soldiers spawned before 3 seconds are stuck saying false forever, while the soldiers spawned after 3 seconds say true. Unless I am mistaken, the soldiers spawned before the 3 second mark should say true after 3 seconds.

I found a possibly related issue, but the last post was in January, and the related github bug entry is marked as closed. link: Having trouble with 'this' variables in programming.Programmable methods

I suspect it might be something I am doing wrong, but I can’t figure out what. Any help would be greatly appreciated. Thanks!


#2

Having the same issue here:

if( typeof this.a === 'undefined' )
{
    this.a = 0;
}
else
{
    this.a++;
}

this.say( this.a );

Says ‘0’ forever, as does the fix shown in the related thread:

this.fun = function()
{
    if( typeof this.a === 'undefined' )
    {
        this.a = 0;
    }
    else
    {
        this.a++;
    }
};

this.fun();

this.say( this.a );

#3

I can confirm. The code below (which is given to us as an example of this functionality) will always say the speaker’s max hp as opposed to their current this.health value.

this.lastHealth = this.health;
this.say(this.lastHealth);

It seems to stay defined at whatever value it is initially given as opposed to a new value each time we choose our action.


#4

Thanks for the code samples, guys–all that code looks like it should work, so I’ll see what I can do to fix my transpiler up for that. Is this all in Brawlwood or Dungeon Arena?

I’ve started a GitHub issue to track this over here: https://github.com/codecombat/codecombat/issues/621


#5

I had issues relating to this under Dungeon Arena. Scrapped the code thinking it was me. I can probally recreate it if required.


#6

I have the same issue, and it started just after the weekend where ProtectAPI was enabled, HOWEVER, I believe the problem may be more subtle that that.

previously since this.x===undefined seemed a little iffy, I chose to do if(this.built.length===0 ) to run my “constructor” code. however, that also broke at the same time that this.x===undefined broke.


#7

I’m having the problem in both Brawlwood and Dungeon Arena. The code works as expected on the singleplayer maps for me.


#8

I think I’ve fixed this; give it another shot. (Might need a cache clear.)


#9

I confirm it’s fixed! great job.


#10

Shouldn’t a full re-run of all the brawlwood ai’s (recalculate the whole ladder) be run now that ProtectAPI is up and “this” is fixed?


#11

That’s a good point. Michael is working on it.


#12

I am afraid this is NOT fixed yet. Without persistence obtained by glomming to ‘this’, its hard to write anything non-trivial. I tried in the tutorials (Dungeon Arena).


#13

@Hannofcart Can you post some simple sample code that’s not working?


#14

This is now working for me :slight_smile:


#15
function Spawner()
{
}
Spawner.prototype.setBase = function(base){
    this.builder = base;  
};
Spawner.prototype.update = function(){
    this.builder.build('soldier');  
};

var base = this;
if(!this.spawner){
    this.spawner = new Spawner();
    this.spawner.setBase(base);
}
this.spawner.update();

The code above (when used inside the chooseAction() method of Base) will only generate a soldier once. Please point out if I am misunderstanding something.


#16

Hmm, yeah, that doesn’t work–got a bit too complex for my transpiler so far, I guess. I’m tracking it here. Will see what I can do.

Until then, if you were to add methods to this directly, it might work better. (Except don’t try to set the update method on this, because it won’t let you–it already has one.)