I really like the concept and the lesson it teaches.
Although I was able to pass it with just a couple of lines of code due to catching an extremely easy seed I think you might want to put more explanation into the help file.
“There are multiple ways to tackle this problem. Dynamic fire-trap avoidance using vectors? Evaluating the static mines and creating a path through them?”
You might consider adding a bit more explanation, a little hint, for each of these two options.
I guess the original idea is to use vectors and dynamic avoidance of traps, as you suspect. After all, this is a glacier level, teaching “advanced techniques”.
However, it is not really enforced: the traps are in the same place in every seed, so yes, you can win with a rather simple code in a few resubmits.
I think it’s a good level, however, my only suggestion is to try and randomize the firetraps. I was able to win the level by adding 2 lines of code to code already there, and resubmitting until I got an easy seed.
Odd error in terms of interaction between firetraps and .isPathClear
I was using SafeMove(potion.targetPos) and am running straight into the firetraps. Can anyone identify why .isPathClear is not identifying the fact there are firetraps on the route?
def SafePath(tarA):
vecA = Vector.subtract(tarA, self.pos)
# This creates a 90° rotated, 1 m long vector realtive to vec.
normV = Vector.multiply(Vector.normalize(Vector.rotate(vecA, 1.5708)), 0.5)
targetL = [tarA, Vector.add(tarA, normV), Vector.subtract(tarA, normV)]
startL = [self.pos, Vector.add(self.pos, normV), Vector.subtract(self.pos, normV)]
isFree = True
for s in startL:
for t in targetL:
if s and t:
isFree = isFree and self.isPathClear(s, t)
else:
isFree = False
return isFree
def SafeMove(tarA):
tarLoc = tarA
cAngle = 0
adjAngle = 0.25
while (not(SafePath(tarLoc)) and (cAngle < 2*Math.PI)):
vecA = Vector.normalize(Vector.subtract(tarLoc, self.pos))
adjAngle2 = adjAngle
vecB = Vector.multiply(Vector.rotate(vecA, adjAngle2),5)
tarLoc = Vector.add(self.pos, vecB)
cAngle = cAngle + adjAngle2
self.move(tarLoc)
I guess that fire traps are considered as point objects, so if isPathClear() “misses” it by even 0.1m, it will return “clear”. Unfortunately, our hero is not a point object, and if he/she wants to walk 0.1m close to a trap, then… well… KABOOM!
Also, Brewball, while it appears on the Glacier world, does not beyond to the world, in a sense, that is, it’s not registered as in Kelvintaph Glacier and so redirects you to the “Undefined” screen.
I’m guessing you are correct Ant. Recommendations:
Either fix isPathClear for mines or add a warning to the players.
Let players know how close they can get to a mine before it blows. (I think it is in the 2-3 range.)
Are you aware that on a bad seed, the suggested code can generate more than 1 potion in the air at a time? The current suggested code automatically goes after the first potion when the second potion could have less hang time. I would suggest adding code to prevent this from occurring.
The scattered mines seems like an improvement and Omarn doesn’t throw double potions any more. My previous solution still worked for all the tests I tried.
I also tried implementing a flag-following strategy and can say that it is possible, but tricky, to pass just by manually controlling your character. Maybe restrict the use of flags.
Firetraps are not generated immediately. If I want to detect the firetraps before everything (they’re static, so it shouldn’t be in the loop), I get this result:
I just checked and my customized strategy still worked with the changes. Very nice level now, thanks! I don’t see either the warning or the note, but that simply may be because I didn’t reload the code.
Only thing I might recommend is not making all of the obstacles hazards. You could add some ice pillars as well so that folks don’t just need to check hazards but actually might need to use isPathClear … [Not a full maze, mind you, just a couple of random pillars that folks could run into … ]
loop:
potion = self.findFriendlyMissiles()[0]
firetraps = self.findHazards()
# Remember that a Fire Trap will trigger if you move closer than 3 meters!
omarn = self.findByType(“potion-master”)[0]
if potion:
dest = potion.targetPos
# Go get the potion.
if self.isReady(“dash”):
self.dash(potion.pos)
else:
self.move(potion.pos)
else:
if omarn and self.distanceTo(omarn) > 10:
# Move back to Omarn.
self.move(omarn.pos)
# Warning: isPathClear doesn’t work with Hazards!
else:
self.say(“Hup, hup!”)
loop:
potion = self.findFriendlyMissiles()[0]
firetraps = self.findHazards()
# Remember that a Fire Trap will trigger if you move closer than 3 meters!
omarn = self.findByType("potion-master")[0]
if potion:
dest = potion.targetPos
# Go get the potion.
if self.isReady("dash"):
self.dash(potion.pos)
else:
self.move(potion.pos)
else:
if omarn and self.distanceTo(omarn) > 10:
# Move back to Omarn.
self.move(omarn.pos)
# Warning: isPathClear doesn't work with Hazards!
else:
self.say("Hup, hup!")