Python list functions not working?


#1

Note: the following issue may be a lack of my python knowledge, or a bug (possibly linked to the issue described in the linked topic).

Anyway, I’d be happy to get some answers.


So. I want to manipulate lists. For example remove the enemy hero from the list of enemies; or add myself to the list of friends, etc. However, the lists do not change.

Examples:

enemies = self.findEnemies()
self.say(enemies)
# output: Alpha, Bravo, Charlie

enemies.remove("Alpha")
self.say(enemies)
# output: Alpha, Bravo, Charlie

enemies.append("Delta")
self.say(enemies)
# output: Alpha, Bravo, Charlie

enemies.pop[0]
self.say(enemies)
# output: Alpha, Bravo, Charlie

del enemies[0]
# unexpected token

self.say(type(enemies))
# type is not defined

If I convert such a list using list() I get absolutely the same results, but in square brackets:

enemies = list(self.findEnemies())
self.say(enemies)
# output: [Alpha, Bravo, Charlie]

enemies.remove("Alpha")
self.say(enemies)
# output: [Alpha, Bravo, Charlie]

# etc.

If I compile the list myself then .append() works, but the rest doesn’t:

targets = self.findEnemies()
enemies = []
for target in targets:
    enemies.append(target)

self.say(enemies)
# output: [Alpha, Bravo, Charlie]

…or even worse: .remove() removes the last element, not the one in the parameter:

# enemies comes from the above code
enemies.remove("Alpha")
self.say(enemies)
# output: [Alpha, Bravo] (!!!)

I can make a workaround by creating the lists myself, and add/exclude certain items manually. However, it’s far from the desired behavior…


#2

I don’t know how Python lists work, but when you use findEnemies() it returns a list of enemy objects (is that the right term?), not the names of the enemy. (I think say just pretty prints that for you, maybe calling the toString() method (JS)).

Maybe there’s a filter function you could use. In JS I’ve been using Array.prototype.filter for quite a while.

Another option would be to use list comprehensions. Probably more practical in your case.

# just simple examples, they are really powerful
filtered = [enemy for enemy in enemies if enemy.type != "scout"]
notHero = [friend for friend in friends if friend.id != "Hero Placeholder"]

As for appending I’m pretty sure you could use something like

```
friends.append(self)

</del>

<del>Though doing something like that causes some more problems (can't command yourself if you were to command every friend)</del>

#3

You can’t change the lists due to the API-Protection. This mechanism stops you from changing values at other objects. For example you can’t change the health of an enemy, assign to your own position (basically teleporting) or change arrays/lists you got from the system. The last one is an sad and unintended side-effect, and is as far as I know not currently tackled by any programmer.
The programmers would have to decide for every single object they give to the player via methods or fields whether it should be protected or not. As this is way to much work and new methods/fields are introduced monthly they have chosen that protecting everything was easiest.


To make it easier for you to compile the desired lists, look at this:

onlyThrowers = [e for e in self.findEnemies() if e.type == "thrower"]

onlyHighHP = [e for e in self.findEnemies() if e.health >= 500 and e.health < 1000] #We don't attack too strong enemies ;)

#4

Thanks to both of you for highlighting the concept of list comprehension! It seems indeed very powerful!


OK, so the API-Protection prevents me from changing the lists received from the system (e.g. enemies = self.findEnemies() )

But what about the lists that I created, like the enemies list created with the above mentioned code?

targets = self.findEnemies()    # this should be protected by the API
enemies = []                    # but this should not be protected
for target in targets:
    enemies.append(target)

# or with my new knowledge:

enemies = [target for target in self.findEnemies()]

This enemies list is not created by the system, so it should not be protected… or am I missing something?

Thanks


#5

Well, you can modify your own lists, right? I don’t know why some functions do not work as they should, but in the worst case (e.g. bug is not fixable) you could use list-comprehensions every time you want to filter something out ([e for e in myList if e.someProperty is not someValue]).

That is unfortunate, but I’m not fluent enough with Python to think of another (more efficient way). Can you maybe open an issue on GitHub about this, describing what and what doesn’t work as expected? Don’t include the API-protection-stuff, that is already known.


#6

Then why can I use splice and Math functions in my program?


#7

I don’t know. Maybe this operation works as intended, while others like remove doesn’t.

I don’t know where in the code the Python is translated to Javascript, but the error is possibly there.