While indentations save lives, more indentations won’t save more lives
You indented the if, but at this point it is unnecessary (and actually causes an error).
The correct line-up is:
loop:
enemy = self.findNearestEnemy()
if enemy:
distance = self.distanceTo(enemy)
if distance < 5:
self.cleave(enemy)
else:
self.attack(enemy)
At this point I want to add that cleave only does 15 damage, your sword does 30 damage. If you know that you only engage one enemy, it makes more sense to only attack. Just a general hint.
The solution we are trying to suggest for this level is:
loop:
enemy = self.findNearestEnemy()
if enemy:
# Find the distance to the enemy with distanceTo.
distance = self.distanceTo(enemy)
# If the distance is less than 5 meters...
if distance < 5:
# ... if "cleave" is ready, cleave!
if self.isReady("cleave"):
self.cleave(enemy)
# ... else, just attack.
else:
self.attack(enemy)
So it’s supposed to be a nested if where you only attack when you are within 5m, but you cleave if cleave is ready. I think this is too complex for this level, so we need to figure out something else.
With the code below she’d start off with 515 and end with 55.
loop:
enemy = self.findNearestEnemy()
if enemy:
distance = self.distanceTo(enemy)
if distance < 5:
if self.isReady("cleave"):
self.cleave(enemy)
else:
self.attack(enemy)
I didn’t like that.
So I wanted her to:
cleave
check for cleave ready
no cleave ready (then attack)
cleave ready (cleave)
So I changed the code… but this is what she did istead:
First Group:
same as above.
Second Group:
she’d attack one by one (before cleave was ready)
then she’d cleave (although no one was there)
Final Group:
she’d move to the next group
hit them one by one and then cleave
So I added self.say “This is Code Combat!” to try to catch what was happening in the loop.
After I did that she wouldn’t cleave anymore after defeating the second group in hand to hand combat. She’d go to the next group and when they were w/in 5 she would cleave.
Here’s the code I used.
loop:
enemy = self.findNearestEnemy()
if enemy:
distance = self.distanceTo(enemy)
if distance < 5:
if self.isReady("cleave"):
self.say("This is Code Combat!")
self.cleave(enemy)
self.shield()
else:
self.shield()
self.attack(enemy)
else:
self.shield()
self.attack(enemy)
I do not feel this was the most efficient way, but she started with 515 health and ended with 275.
So in my code above… the last part (the second else) wasn’t needed. Unfortunately I cannot see inside the loops yet, but I’m hoping with practice I can.
I promise any errors you see this time are not copy and paste related.
I am going to take you up on your longer post though. I can tell this is going to destroy me unless I get a handle on it.
Oh! and also I don’t get what you said. I’m inside of a loop. So why is it attacking enemies that are not present since it is in the loop where ‘if enemy’ is true? #confused
loop:
enemy = self.findNearestEnemy()
if enemy: # First if
distance = self.distanceTo(enemy)
if distance < 5: # Second if
#cleave maybe
else: # this else corresponds to the second if
#attack
Let’s say there is an enemy. The first if is true, so distance is now 4.5 (because I say so).
The second if is now true aswell (because there is an enemy). You cleave the enemy, and he’s dead now.
The loop starts again. Because of your awesome cleave, all enemies are dead now. enemy is now undefined. The first if becomes false. distance stays the same value as before, which is still 4.5
The second if sees that 4.5 < 5 and enters. You now try to target an undefined-enemy. This results in … I actually don’t know what this results in, most likely the result you saw. I thought this just throws an error…
But your code would still be problematic. Given you didn’t found an enemy, but somehow distance is greater than 5. You then would enter the else-path. What happens? You self.attack(undefined). Still strange behaviour.
Now comes the twist… I have no idea why the code runs through. This is most likely related to some kind of error-catching-mechanism, that catches the error silently and simply continues your code. Do you have by any chance a red circle with a white cross below your feet?
EDIT: I just tested your code… completly error-free. But as soon as I add a self.say(enemy) after enemy = self.findNearestEnemy() or a self.say(distance) just before the second if, I get
cripes… well … i should probably stop until it’s explained then because what you said makes total sense and because it didn’t error out and I’m building my own theory based on this experience; it would be a bad idea to continue based on what you just said.
i want the code to error out and not tell me it’s ok if it’s not.
I think what’s happening is that your distance variable is still defined from earlier iterations through the loop even later on when there is no enemy.
I tried adding { … I get the same result. I don’t think my character is fighting back at all. I will try to get better armor, but I also want my code to work.
loop {
var enemy = this.findNearestEnemy();
if (enemy) {
var distance = this.distanceTo(enemy);
if (distance < 5) {
if (this.isReady("cleave")) {
this.cleave();
}
}
}
else {
this.attack(enemy);
}
}
Always try to say your code as a (or multiple) sentence.
Find the nearest enemy. If there is an enemy, check the distance to it. [Cleave maybe]. If there is no enemy, attack that enemy.
If you spell it out like this, you see the problem (seriously, this is how I debug sometimes).
You probably want that else somewhere else.
loop {
var enemy = this.findNearestEnemy();
if (enemy) {
var distance = this.distanceTo(enemy);
if (distance < 5 && this.isReady("cleave")) {
this.cleave(enemy);
}
else {
this.attack(enemy);
}
}
}
This code says:
Find the nearest enemy. If there is an enemy, get the distance to it. If the distance is smaller than 5 and cleave is ready, cleave the enemy. If either distance is greater or equals than 5 or cleave is not ready, attack the enemy. If there is no enemy, do nothing.
Hey eddietwang, I just loaded up your code on my end and it seems to work fine–you beat the level. If you’re still seeing this bug, can I get you to open up the JS console and look for some stack trace details on what is leading to that error in the error logs?
As best as I can figure out it should go something like this:
(dotimes [n 1000]
(let [enemy (.findNearestEnemy this)]
(if enemy
;; Find the distance to the enemy with distanceTo
(let [distance (.distanceTo this enemy)]
;; If the distance is less than 5 meters...
(if (< distance 5)
;; ... if "cleave" is ready, cleave!
(if (.isReady this "cleave")
(.cleave this enemy)
;; ... else, just attack.
(.attack this enemy))
(.moveXY this (+ (- (mod n 3) 1) 40) 31) ;; um, "borrowed" from Vlevo
)
)
(.moveXY this 40 (+ (- (mod n 3) 1) 31))
)
)
)
I run up and down, so the last move command must be working. Then as soon as the enemies spawn I just stand there doing nothing.