Help! Only killing 1 Ogre in Patrol Buster with Clojure

Hey guys,

I’m a total newbie with coding. Would be awesome if you could help me out here.
After attacking the first ogre coming at me it doesn’t repeat the loop for some reason.

(dotimes [n 10]
    (let [enemy (.findNearestEnemy this)]
         (if enemy
             (.attack this enemy)
         )))

Does someone detect the error here?

Please put three backticks -> ` (aka the other single quote, probably on the same key as tilde ~) before and after your code. See FAQ also.

Great, thanks for formatting that. Unfortunately I don’t recognize the language you are using, but am guessing the [n 10] means to go through the loop 10 times? If so, that’s not enough.

In other languages here, like python, you’d just use “loop” which runs until you finish or break out of the loop. If there is not a similar way to do that, you might just increase the 10 to 1,000?

And btw, if you’re new to coding, you may want to go with javascipt or python as those are more commonly used here (hence, easier to discuss and get help with), though I presume you have some reason for using whatever language you are using.

The default code for that level is:

(dotimes [n 1000]

But increasing n doesn’t seem to do the trick, the hero still just stands there after killing the first ogre. I don’t know if this is a bug in the “experimental” clojure parser or if the loop burns through all n before the next ogre appears??? (not even [n 100000000000000])

Yes, I have the same problem. If I increase the number of loops it still attacks only 1 enemy…

Hmm, yes it looks like it goes through the loops really fast. I put a

(.say this "end")

after the loop, and it does come up really quickly.

Interestingly I also put a ‘say’ command in at the start of the loop:

(dotimes [n 5000]
    (.say this "start")
    (let [enemy (.findNearestEnemy this)]
         (if enemy
             (.attack this enemy)
         )))

Which then works - I think because ‘say’ takes quite a while, so this means it doesn’t burn through the loop to quickly :smile:

1 Like

@nick This also basically happens in python if I change “loop:” to “while n < 1000000000” (this might be the problem in my inf-loop post meaning it is looping over “nothing” (if “False”) really fast.)

If I pick a lower n (like clojures default 1000) it gets to the say before the others ogres come out…

Hmm, which is interesting . . . why did the hero lock up BEFORE killing the first ogre for the really big n

If I change my python code here to “while True:” I get the “hard limit of 1000000 exceeded” error

testing a different problem I noticed this in the default text on the level (“Desert Combat”) I was using to test:

# Always take an action inside a while loop, or it'll go infinite!
1 Like

Basically, only the attack takes game-time in your loop, so if you don’t attack, you loop around and look for an enemy again before anything has changed, so your loop will run through infinite n all at the same moment after the first ogre dies (or until it exceeds the execution limit or times out).

This is why we use the simple loop construct in the other languages, to hide players from having to think about infinite loops and making each loop iteration take at least one frame if no other action is taken. But we haven’t implemented any sort of simple loop for Clojure, so you would have to fake it by doing something like this:

(dotimes [n 1000]
    (let [enemy (.findNearestEnemy this)]
         (if enemy
             (.attack this enemy)
             (.say this "Waiting for an enemy to show up.")
         )))

Or you could use wait or moveXY or any other action that takes time to complete.

We’re tracking progress on simple loops for other languages here: https://github.com/codecombat/codecombat/issues/1570

1 Like

if i were u first i would say to myself is " what does my “character” want to do?", then what i would do is to tell my “character” is to attack the enemy. Whenever it is possible. So so far the program is:

loop:
enemy = self.findNearestEnemy()
if enemy:
self.attack(enemy)

Now i told it to attack the enemy. But i want it to move to the middle of the “arena” so then i would use another command like:

else:
self.moveXY(40, 30)

and since i am using an if statement i would use if/else.
So our whole program would be like this:

loop:
enemy = self.findNearestEnemy()
if enemy:
self.attack(enemy)
else:
self.moveXY(40, 30)
# If there is an enemy, attack it!

Your code is for the programming language Python, which is not the same as Clojure.

Also I already told you how to present your code properly, please do it!

Insert a “changing” moveXY into the dotimes and it should work (changing so the hero keeps moving 'causing a non-excessively loop-eating wait for more enemies.)

(dotimes [n 40]
    (.moveXY this 30 (+ n 10))
    (let [enemy (.findNearestEnemy this)]
        (if enemy
            (.attack this enemy)
        )))

In addition to the loop completing too quickly, do does not seem to work. While one can work around the problem by adding .say and omitting do, this adds too much delay in “Back to Back”.

Even dotimes fails to work within an if. The only way I could find to get “Back to Back” working was the following and construct and a different .moveXY position:

(dotimes [n 1000]
    (let [enemy (.findNearestEnemy this)]
        (if enemy (and (.attack this enemy) (.attack this enemy))
            (.moveXY this 34 34)
        )
    )
    (.say this "message")
)

This bug is very frustrating!

I like your sneaky (and attack attack). Another way to work around the lack of an explicit (do …) statement is an implicit one: (when true (…) (etc) )

Again a changing moveXY does the time eating workaround job but this time since you have to guard the peasants you need something more sophisticated than my last one:

Spoiler
(.moveXY this 40 (+ 34 (- (mod n 3) 1)))

(how visible are spoilers, to you? I don’t know if I it is my screen or what, but they are invisible to me.)

@Vlevo: your spoiler is hidden beneath a triangle I have to click to open. Please tell me how you created that, as there’s nothing in the posting toolbar for it.

Part of the problem with the Clojure track in this game is that it creates a Catch 22. I am legitimately trying to learn the Clojure language by playing the game, but the bugs force me to use constructs the game has not yet revealed in order to complete levels intended to teach the language. In particular, when and and have not yet been introduced. The and was a fortunate, educated guess. One would have to already know Clojure or look up elsewhere the syntax to come up with the innermost operation in your spoiler.

1 Like

Well, I didn’t do the “triangle-spoiler” somebody else edited it to do that.
My post a couple of posts up is still the way I did it. [ spoiler ] … [ / spoiler ]

I just checked and I got a private message from the “Editor” and he suggests looking at the FAQ again to learn a new way to do spoilers (the triangle-kind). I haven’t looked yet but the old one can’t do code inside a spoiler, I believe this was/is the reason for the new way.

here is a test of the new way.

Spoiler

Yeah, it works. [ details = Spoiler ] no spaces [ / detail ] now to go read the FAQ again, to see what it says (I “edited” my previous post to see what he did.).

I agree the clojure problems do make it difficult. I don’t know any clojure either, I didn’t even know it existed prior to starting here at code combat a couple of weeks ago. The “when true” I had to look up. The “(+ (mod n 3) 1)” idea I worked out for myself from previous coding experience (well ‘%’ didn’t work so I had to look up how to do modulo in clojure).

@Vlevo @jllogan
That was me, and apparently the FAQ got a revert (which I can’t really explain…).
I was indeed testing something new, sorry for you being my guinea pigs.
I’m trying to fix the FAQ, just keep the discussion going.

@nick ick what about while loop for Clojure. I get book 3 but for while loop there is no example. and I think is not working

Won’t work for me either.

@Vlevo what can we do for an equivalent of the while loop for Clojure? (We should add something to the programming.UsesSnippets documentation for the Programmaticon III for while, but I’m not sure what to add.)

While works in Clojure.

(while condition body)

(while (< 4 5)
    (.say this "I'm")
    (.say this "Loopy")
)

Works fine. I’d have to see their code to tell if anything else is going on.