File "/tmp/algo17285577351142377855/gamelib/game_map.py", line 91, in in_arena_bounds x, y = location ValueError: not enough values to unpack (expected 2, got 0)

So when trying to run my algo, this happens. I never messed with game_map at all so I am pretty confused on what I did

File "/tmp/algo17285577351142377855/gamelib/game_map.py", line 91, in in_arena_bounds
    x, y = location
ValueError: not enough values to unpack (expected 2, got 0)

What are you passing into the function in_area_bounds? This is a python error that occurs when you are expecting a list and don’t have the right number of elements in that list (in your case, 0).

If [1,2] is a python list, then:

x, y = [1,2]
debug_write("X: " + str(x))
debug_write("Y: " + str(y))

will output:

X: 1
Y: 2

This is what the in_arena_bounds function does with x, y = location where location is the parameter you passed to the function. You will recieve this error if location cannot be broken into two parts (either too many or too few elements). Thus, you should check what value you are passing into the function.

ah ok, turns out instead of making an empty list [[]], and extending it, I make an empty list [], and append it.
Thanks for your help!

Had this error pop up again, have a list mylist = [[1, 2]] and

for location in mylist:
    if game_state.can_spawn(ENCRYPTOR, location):

this gives the error
ValueError: not enough values to unpack (expected 2, got 0)
could you explain what I am doing wrong? @Isaac

Hmmm, I copied your code and it didn’t give me any errors and looks fine to me. I would recommend printing out the value of location at several points in your code. Is it defined somewhere else before or inside the loop? Anywhere mylist gets rewritten?

here is all of the code:

Traceback (most recent call last):
  File "/tmp/algo8725213104168874298/algo_strategy.py", line 426, in 
    algo.start()
  File "/tmp/algo8725213104168874298/gamelib/algocore.py", line 65, in start
    self.on_turn(game_state_string)
  File "/tmp/algo8725213104168874298/algo_strategy.py", line 121, in on_turn
    self.algo_strategy(game_state)
  File "/tmp/algo8725213104168874298/algo_strategy.py", line 141, in algo_strategy
    self.adaptive_replacing1(game_state)
  File "/tmp/algo8725213104168874298/algo_strategy.py", line 316, in adaptive_replacing1
    if game_state.can_spawn(DESTRUCTOR, location) and (game_state.get_resource(game_state.CORES)) >= 5:
  File "/tmp/algo8725213104168874298/gamelib/game_state.py", line 276, in can_spawn
    if not self.game_map.in_arena_bounds(location):
  File "/tmp/algo8725213104168874298/gamelib/game_map.py", line 91, in in_arena_bounds
    x, y = location
ValueError: not enough values to unpack (expected 2, got 0)

inside of 316, the code is this:
if game_state.can_spawn(DESTRUCTOR, location) and (game_state.get_resource(game_state.CORES)) >= 5:

I checked the for loop, for location in firewall_footprints:

and firewall footprints is declared inside of on_game_start

global firewall_footprints
firewall_footprints = [[1, 2]]

Can you figure out what is going on? @Isaac

Do you say global firewall_footprints inside your other function? The error is because you are declaring functions global and then using them inside of a function. Generally, global variables are a bad idea (in any language). A much safer method here would be to declare firewall_footprints as a part of the AlgoStrategy class.

So in your __init__():

self.firewall_footprints = []

in on_game_start() (or you could just initalize it inside __init__()):

self.firewall_footprints = [[1,2]]

anywhere else you use it you must add the self, so in the code you posted:

for location in self.firewall_footprints:
    if game_state.can_spawn(DESTRUCTOR, location) and (game_state.get_resource(game_state.CORES)) >= 5:
        game_state.attempt_spawn(ENCRYPTOR, location)

is there a better way to not use self.

If you want to be able to use it anywhere inside of the AlgoStrategy class, no, there is not. An alternative would be to pass it as a parameter basically everywhere, which can get confusing and messy quite quickly if you want to use more variables like this.

This is the big benefit of classes, you can access the data for that class anywhere inside it safely because it is inherent to that class. Using global variables is an option, but actually makes things more confusing for the reasons you are finding out now. It has to do with how python declares scope. For example:

myVar = 'global'

def test():
    myVar = 'local'
    debug_write(myVar)

test()

will output:

 local

You can offset this using global myVar but it is far easier to remember to just use self.

ok, can you help me with why my code says

game_state is not defined all of the time?

This is all about scope, where you declare a variable (where it is first used, eg myVar = 0) declares it’s scope. The scope is ended when an indentation level is decreased. For example:

def foo():
    myVar = 0
print (myVar)

will throw the exception myVar is not defined because it was not declared in that scope.

This also be shown here:

myVar = 2
def foo():
    myVar = 0
print (myVar)

will output 2 not 0 because the first myVar is not the same as the second myVar, even though they have the same name. The second myVar’s scope ends when the function ends.

When you pass parameters, you are passing that variable to be used inside another function (there are caveats and exceptions here so note that I am simplifying the details of this). For example:

def bar(param):
    print (param)
    param += 1

def foo():
    myVar = 0
    bar(myVar)
    print (myVar)

foo()

Here several important things happen. First, foo is called (at the bottom). Second, myVar is created inside foo()'s scope and initialized to 0. Then, bar is called with myVar as a parameter. The key here is that when print(param) is called, param is not the same variable as myVar. Rather, myVar was copied to param, and now param is in the scope of bar. Bar prints param, the copy, adds 1 to param and then returns to function foo. Then foo prints out myVar. myVar is still 0, because even though param was incremented by 1, that is a different variable. So the output of the above would be:

0
0

This is because an integer (number) is what is called immutable in python. A list or object would be called mutable. Things that are immutable will work like above, things that are mutable will work differently. Here is an example of a mutable:

def bar(param):
	print (param)
	param.append(2)

def foo():
	myList = [1]
	bar(myList)
	print (myList)

foo()

which outputs:

[1]
[1, 2]

Classes and Objects

The classic example for classes and objects is with blueprints. If you have a house, the blueprint for how to build the house would be the class, and the actual house itself would be the object. In strongly typed languages (C++, Java, etc) this is much more regulated and certain structures are forced. In python, you are much more free to do what you want (and thus more room for errors like the one you are experiencing).

game_state is an object made from the class GameState. You can see it is created using game_state = gamelib.GameState(self.config, turn_state) (ignore the gamelib part for now, I’ll answer that in your other thread).

When game_state is not defined, it means you are trying to use game_state when it has not been created (just like any other variable). Thus, you must pass it as a parameter everywhere you want to use it or declare it as part of the class (and thus the object when you make it). Whenever you get that error, it means it is not in the scope of where you are using it.