Spectrum is now read-only. Learn more about the decision in our official announcement.


An exciting game of programming and Artificial Intelligence


Level 4 spoilers? Invalid player code: warriorhealth is not defined

June 6, 2018 at 10:08pm

Level 4 spoilers? Invalid player code: warriorhealth is not defined

June 6, 2018 at 10:08pm
Hello! I am new to javascript, so I sincerely apologize if this is a dumb question, but I've been stuck here for two days and I'd really appreciate some advice. I am on level 4 of the beginner tower, and am trying to get my warrior to only rest if a function called considerRest() returns true. The problem is that when I try to assign to the variable warriorhealth at the end of the playturn loop, I get an error that this variable is undefined. I tried defining the variable outside of the playTurn() loop as a global variable (just below the Player class declaration), but that returns unexpcted identifier errors. I then tried declaring it in a constructor, but I suppose that is not in the same scope and is treated as a different variable. I tried declaring the variable at the end of the playTurn() loop and then my code runs, but then the considerRest() function always returns true, presumably because warriorhealth is undefined, so if(warriorhealth > will always return true. My code is as follows;
1 class Player {
2 constructor() {
3 var warriorhealth = 20;
4 }
5 playTurn(warrior) {
7 function hunt() {
8 warrior.think("is something ahead?");
9 //feel ahead
10 var feelResult = warrior.feel();
11 //if empty, check health, then walk forward. if not, attack
12 if (feelResult.isEmpty()) {
13 warrior.think("there is nothing there. Should I rest?");
14 if (considerRest()) {
16 } else {
17 warrior.walk();
18 }
19 } else if (feelResult.isUnit()) {
20 warrior.think("who is there?");
21 var unit = feelResult.getUnit();
22 if (unit.isEnemy()) {
23 warrior.think("it is an enemy!");
24 warrior.attack();
25 }
26 }
27 }//hunt
29 function considerRest() {
30 if ( < 20 ) {
31 warrior.think("he could use a rest.");
32 warrior.think("[ " + warriorhealth + " > " + + " ]");
33 if (warriorhealth > {
34 warrior.think("it is not safe.");
35 return false;
36 } else {
37 warrior.think("rest would be wise.");
38 return true;
39 }
40 } else {
41 warrior.think("I am fine, I will go on.");
42 return false;
43 }
44 }//considerRest()
46 hunt();
47 warriorhealth =;
49 }//playTurn(warrior)
50 }//Player{}
Note I strayed from camelcase naming convention for the variable warriorhealth only because I was quickly switching back and forth between warriorhealth and, trying to test if that is the problem. I plan to fix that as soon as I figure out this problem preventing my code from running.
I've also tried different combinations like trying to assign to Player.warriorhealth, constructor.warriorhealth, warrior.warriorhealth (I clearly don't know how this api works).
Thank you very much for your time!

June 7, 2018 at 2:13am
Your considerRest() function could have the warrior as a parameter and you call it like this.considerRest(warrior) inside your players turn function.
Thank you so much for your response!
I added warrior as a parameter in the considerRest function, and then modified the call to that function to be this.considerRest(warrior); as you suggested. This resulted in the error, "cannot read property of 'think' in undefined. I noticed that you specified, "inside your players turn function", so I also tried calling it from within that function instead of from within my hunt() function (which is inside of the player turn), just in case that matters, and got the same result.
So I have always had trouble understanding the use of the this command. I have been working in java for awhile now, and I understand that 'this' represents the current instantiation of an object, but something has never clicked for me and so I have tried to avoid writing code in such a way that I have to use 'this'. In this warrior ai script I have tried making the object explicit by calling 'warrior.whatever()' instead of 'this.whatever()', so I'm guessing that this error is the result of the program not knowing that I am referring to the warrior object because I am perhaps mixing techniques? I'm still struggling to see what is causing this confusion, however.
I would really appreciate any advice on this issue, as well as any resources or tips for understanding the 'this' keyword (preferably for dummies!). Thank you again so much for your response, I definitely think you've helped me narrow down the problem.

June 8, 2018 at 6:15am
you need to use this.warriorhealth not var warriorhealth
`var warriorhealth` will create a variable that is scoped to the contstructor and will not be defined elsewere
`this.warriorhealth` will create a property on the class allowing access as long as the class exits
you will need to access it via this.warriorhealth as well

June 9, 2018 at 3:21pm
Thank you so much for your response! I am so sorry for the trouble, but I am just not getting the 'this' command. I followed Alex Lewis' instructions and it relieved the error, only to replace it with "cannot read property 'think' of undefined". This part of the code worked previously, so I must have changed something in my experimentation such that it is no longer aware of the (object?) warrior. I tried changing all instances of warrior.think() to this.think(), which gave the same result. I commented out all think() statements and the error moved on to being triggered by feel() and then eventually my own considerRest() function.
I think this means that there is a problem with how I am passing the warrior object to... one of the functions? (playTurn, hunt, and considerRest). I did notice that my hunt() definition was function hunt(warrior) {, whereas my call to this function was merely hunt();. I know in java that would have resulted in a compile error because the call doesn't have the same number of parameters, so I added warrior into the call as well, to seemingly no effect. I also went through most possible combinations of 'warrior' or empty parameters in all of the definitions and calls after failing to reason what the problem was. My brute force method yielded no fruit, and thus I am still at a loss.
I still think the issue is that I am passing warrior to one or more of these functions incorrectly, and/or that I am misusing the 'this' keyword(because i'm still not understanding it's use). I'm going to try to do some more research on it later today in hopes that I can come up with something.
Am I correct that warrior is an object that I am passing to some of these functions? I guess I could probably benefit from reading warriorjs' source code to figure out what these objects and functions that I am using even are, but I'm a little intimidated by the prospect.
Sorry for the long-winded plea, I just want you guys to know I am putting thought into it before asking for help. Thanks.

July 18, 2018 at 2:17pm
To shed some clarity on this, could you publish your code on GH and provide a link to the correct file here? That may be a little easier to look at and provide direction on.

August 16, 2018 at 12:04am
I'm stuck on this level. I alredy know how to check wether i'm losing hp with, I tried moving two steps from the archer but it keeps hitting me. Any hint? :)

October 5, 2018 at 8:31pm
Hello! Sorry I didn't get back to you guys sooner! I took some time to just study and practice basic javascript stuff and have worked on a few projects in the meantime. Today I went back at it and was able to complete the fourth level of the tower, albeit with a little bit of trial an error. I guess I'm still not comfortable with the way the 'this' keyword works, but at least I can move on in the tower and keep practicing! I plan to revisit this sometime when I'm a little better to see if I can figure out what I've been doing wrong.
I believe that the archer has your warrior at a disadvantage when you keep your distance, so perhaps that is not the best move...