Play Home Contribute GitHub Join Us Discourse Staff Members GitHub Contribution Guides Team

Stuck on "Stillness in Motion" Clojure


I don’t know if I’m writing it wrong, but there’s 4 levels I can’t get past because of nested if statements. Here’s my code for “Stillness in Motion” in which my character does nothing and dies. Am I doing something wrong or is this a bug?

(dotimes [n 1000]
(let [enemy (.findNearestEnemy this)]
     (if enemy
        (when true 
              (let [distance (.distanceTo this enemy)]
                (if (< distance 5)
                    (.attack this enemy)
                    (.moveXY this 40 34))))
        (.shield this))))

I’ve tried switching the (when true) with a (do) but still doesn’t work. Please help, I want to continue playing, but there’s no more levels I can complete!


@Vlevo Have you done this one in Clojure, or can you check it out? Wonder what’s going on; the code looks good to me at first glance.


Hei, sorry about the delay. (says, the poet who don’t know it)

The problem is that she(?) is using good Clojure

Unfortunately there are still some problems with that in the transpile chain. The Clojure bit creates anonymous functions for the “dotimes” and for the "let"s, and everything would be fine BUT Aether (by adding “var …” to the top of all functions) wipes all the variables used in these functions. So anything defined outside of the inner let is blank leading to the hero doing one of two things:

  if no enemy, shield (yay)
  if enemy, moveXY  (boo)

So it is the nested “let” statements that are causing the problem. (see nesting below)

Changing the inner “let” to “def” removes the anonymous function (that wipes important variables) and so works.

(def distance (.distanceTo this enemy))
  (.moveXY this 40 34)))   ;; removed the ")" left over from the "let"

Another way would be to remove the “let distance” altogether since “distance” is only used in the “if condition”

    (if (< (.distanceTo this enemy) 5)

This method also removes the “when true” since it is no longer necessary (now only one statement in the true clause):

  (if enemy
    (if (< (.distanceTo this enemy) 5)
      (.attack this enemy)
      (.moveXY this 40 34))

The problem I describe is real and would stop the code from working but isn’t the actual current culprit, if it was then there would be an error when trying to get the distance to the “blank enemy”. . . . The REAL current problem is that the nesting for dotimes - let - let is too deep. The hero never moves because that piece of code vanishes into the void, but instead as soon as an enemy enters the screen the dotimes loop runs through all 1000 iterations and exists (since it noes nothing (the true clause for “if enemy”) really really fast).

My solutions work because they remove BOTH problems the “too deep nesting” and the “var wiping of external to the function variables”.