Mind the Trap - Alternative.. block

In this level, co-ordinates of the map should be removed as the goal can be achieved by an alternative strategy that is not emphasizing on the fact that self.attack pauses the program during its execution (as mentioned in the Game Menu). The alternative strategy is as follows:

alternative algorithm (not for those who haven't completed this yet)
  1. find enemies first.
  2. define an empty list.
  3. append each element of enemies into the new list if the x-position of the element is <= 42 (thus not beyond the mine)
  4. killing each enemy in this new list

Also: It is possible to jump the mine field and kill all of themā€¦ but shoes maybe expensive at this stageā€¦

Since this is interfering with the goal of the level to teach how some commands pause a program while it is not completed (like self.attack), alternative strategy like what I wrote should be blocked.

Note: I realized and learned the goal nowā€¦ despite being in glacier

ā€¦or just summon your friends and command them to victory (or deathā€¦)

ā€¦or self.say(self.findNearest(self.findByType("fire-trap")).pos) and adjust your strategy to that.


By the way, shouldnā€™t the level be called ā€œMind the minesā€? :smile:

Summoning is not available till later levels. So new players wonā€™t be trying that.

This is awesome:

ā€˜Mind the minesā€™ indeed sounds better to me atleast

1 Like

The level should not be displaying the coordinates under the mouse cursor. If it is, thatā€™s strange.


If you come back to ā€œearlierā€ levels with more programming knowledge, or higher level gear, and you find some fun way to beat a level differently, weā€™re ok with that :slight_smile: So things like jumping the mines or summoning soldiersā€¦ we wonā€™t try to stop that, so long as a player who is playing the game from the beginning will learn the concept in the intended way.

I did restrict it to basic melee heroes, though, because the level wasnā€™t working as intended with some ranged attacks available.

The idea of this level is to:

  • learn about the dangers of attacking distant enemies
  • practice using flags to move into range of enemies, to make some later levels like Siege of Stonehold less intimidating

There will be at least one more flag tactics level coming up soon :flags:

About the name, mines are also known as ā€œFire Trapsā€. :slight_smile:

Thanks for the feedback!

1 Like

@Catsync - Co-ordinates not displayed under cursor. Confirmed. So, should be fine for new players. I got position of mine by clicking on it and checking it position in bottom left menu. They can also be found out using position of hazards I guess.

ā€œfireā€“trapā€ ā€¦ had totally forgotten what they were called :stuck_out_tongue:

Fyi, while the coordinates donā€™t show with mouseover, they do show when you click a mob and check their coordinates. Iā€™m not sure if that is also not intended. Tho at a certain point, you have programmatic access to target coordinates, so youā€™re always going to be able to suss them out if you want to.

Is it intended that the isPathClear() method doesnā€™t work here?

The following code, SafePath returns a ā€œtrueā€ when it should not as there are traps in the way. I know at least 2 different ways of fixing it, but neither should be necessaryā€¦

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)), 2)
    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:
            isFree = isFree and self.isPathClear(s, t)
    return isFree

def SafeMove(tarA):
    tarLoc = Vector.add(Vector.normalize(Vector.subtract(tarA, self.pos)),self.pos)
    pathRisk = not(SafePath(tarLoc))
    angle = 0
    while pathRisk and angle < 2* Math.PI:
        vecA = Vector.normalize(Vector.subtract(tarLoc, self.pos))
        vecA = Vector.multiply(Vector.normalize(Vector.rotate(vecA, 0.5)),5)
        angle = angle + 0.5
        tarLoc = Vector.add(self.pos, vecA)
        pathRisk = not(SafePath(tarLoc))
    self.move(tarLoc)


loop:
    enemies = self.findEnemies()
    enemy = self.findNearest(enemies)
    if enemy:
        # Only attack if the enemy distance is < 10 meters
        if self.distanceTo(enemy) < 30:
            if self.distanceTo(enemy) > self.attackRange:
                if self.canCast("chain-lightning", enemy) and len(enemies ) > 3:
                    self.cast("chain-lightning", enemy)
            else:               
                self.attack(enemy)
        else:
            SafeMove(enemy.pos)