Binary Deployment - Not Understanding Error


#1

This is my latest post for help on the glacier.

I’m pretty happy with my code for Binary Deployment, but apparently The Computer is not:

My hero will loyally say the binary sequence passed to him, though this isn’t displayed in the screenshot. Why can’t the for-loop use it then? I’m guessing from the ominous presence of the word ‘object’ that this is a byproduct of OOP, but if that’s the case, I don’t understand what is an object and what not. We’ve had to use len(whatever) inside for-loops many times already, so why not this?

While I’m on the subject, how come when I use n = map(s) I only come out with an empty list? Is this programmed into the level, or is there something about map that I’m not getting?


#2

It have to be range(len(s))


#3

I’m grateful for that.

I hadn’t realized that the troops aren’t auto-summoned to the right position, so now I’m on to the next part of the challenge…


#4

And, as it would happen, the next challenge gets me my favorite error message:

f_undefined

I’m not sure what to about posting code, because I’m not sure what’s generating the error. I don’t think it’s my binary/ternary convertors, so I’ll leave them out.

Code:
def getThere(p):
    while hero.pos != p:
        if hero.distanceTo(p) < 25 and hero.isReady("blink"):
            hero.blink(p)
        elif hero.isReady("phase-shift"):
            hero.phaseShift()
        elif hero.isReady("jump") and hero.distanceTo(p) > 30:
            hero.jumpTo(p)
        else:
            hero.move(p)
        
        if hero.pos == p:
            break


def summoner(s):
    if len(s) < 8:
        e = 8 - len(s)
        for i in range(e):
            global s
            s = '0' + s
            return s
    
    for i in range(0,7):
        n = s[i]
        if n == '0':
            getThere({'x': hero.pos.x + (5 * i), 'y': hero.pos.y}
            hero.summon("soldier")
        elif n == '1':
            hero.summon("archer")
        elif n == '2':
            hero.summon("griffin-rider")

while True:
    paladins = hero.findByType("paladin")
    for pal in paladins:
        getThere({'x': pal.pos.x + 5, 'y': pal.pos.y})
        n = pal.deployment
        toSummon = decToBinary(n)
        summoner(toSummon)
    warlocks = hero.findByType("warlock")
    for war in warlocks:
        getThere({'x': war.pos.x + 5, 'y': war.pos.y})
        n = war.deployment
        toSummon = decToTrenary(n)
        summoner(toSummon)

Any ideas?


#5
toSummon = decToTrenary(n) # check spelling!

If you want a slightly harder challenge, try writing one function to handle base conversions:

def convertDecimalNumberToBase(number, base):
    # number -- the decimal number to convert
    # base   -- the base that the number will be converted to
    # return an array holding each digit of the converted number

# example calls
toSummon = convertDecimalNumberToBase(n, 2) # paladins
toSummon = convertDecimalNumberToBase(n, 3) # warlocks
Going above and beyond:
def changeBase(digitArray, startingBase, endingBase):

(bonus lol, hover your mouse over that previously-blurred line of code)


The map Function

map is used for applying a function to each element of a list.

map should accept 2 arguments:

  • The first argument is the function to apply
  • The second argument is the list with elements yet to be processed

map will return a list with processed values. (Except in Python 3)


Official Python 2.7 Documentation

CodeCombat's implementation
map: function(fn, iterable) {
  // TODO: support additional iterables passed
  var ret = new pythonRuntime.objects.list();
  for (var i in iterable) ret.push(fn(iterable[i]));
  return ret;
},

source

Calling map with only 1 argument:

  1. an empty list is created and stored into ret
  2. no iterable was supplied, so the for loop doesn’t do anything
  3. ret, still an empty list, is returned

#6

I have already made decToBinary and decToTrenary, I just left them out in order not to needlessly post code. (That was one of my most successful usages of Stack Overflow to date.) You’re right about merging them into one function, though. If you wanted to go all out, you could make it a general-purpose base convertor that takes three arguments, I suppose - number, number’s base, and base to convert to. Unnecessary for the level, though.

Thanks for the help with map, though I need to kick another issue before I really get this. It’s actually not the undefined ‘f’, which was a missing ) in the summoner function (try to find it!), but rather that the loop in getThere won’t terminate when the hero gets to the target pos - I guess that however CC is reading the hero’s position for the sake of comparison for the while is different than the format assigned to the variable it’s being compared to. I need a different way of getting there and stopping to get there once the hero’s there.

After that, I’ll see if my implementation for the summoner works, and maybe play around with map. Thanks for the help.


#7

I’m playing around with the locations. Here’s what my hero says when I ask him (in this case, Ritic - is Ritic a he?) to say the p variable set by getThere:

binary_2

hmmm… that looks like some weird dictionary-like thing that I don’t recognize… What happens if I try to access p['x']?

binary_3

Fascinating. But if I make the while-loop into while hero.pos.x != p['x'] or hero.pos.y != p['y']:, then the level doesn’t run, and on reload gives me the infinite loop or really slow message. Time for a new idea…


#8

Pretty good guess.
hero.pos is one object, and p is another object.
Here, the != and == operators are evaluating if hero.pos is/is not the same object as p.
hero.pos and p may have the same x and y values, but they won’t be the same object except for the case when you call getThere(hero.pos).

# instead of
while hero.pos != p:
# use
while hero.distanceTo(p) > 1:

Also, this can cause potential issues:

elif hero.isReady("jump") and hero.distanceTo(p) > 30:
    hero.jumpTo(p)

I would change it to:

elif hero.isReady("jump") and hero.distanceTo(p) > 30:
    hero.jumpTo(hero.pos.add(p.subtract(hero.pos).normalize().multiply(15)))
    # if p is not an instance of Vector, use this instead:
    # hero.jumpTo(hero.pos.add(Vector(p.x, p.y).subtract(hero.pos).normalize().multiply(15)))

I’m not sure if faster heroes jump further, but ~15 units is the max distance that the free heroes can jump.


#9

That’s the kind of thing that’s so obvious once I see it that it makes me ask myself how I missed it. (I have a lot of experience with things like that, so trust me. :wink: )

About the jumping - faster heroes jump farther, but I’ll play around with it. Here’s some playing:

[“Life was so much simpler with sloppy jumpTo parameters” - Shmoogy]


#10

Maybe this?

hero.jumpTo(hero.pos.add(Vector(p.x, p.y).subtract(hero.pos).normalize().multiply(40)))