Importing game_state

I am very desperate, I have tried many, many things. currently, I have a new module, filled with functions, but no matter what I do:

  File "/tmp/algo8966065283470086680/algo_strategy.py", line 142, in algo_strategy
    groupings.bits1()
  File "/tmp/algo8966065283470086680/gamelib/groupings.py", line 412, in bits1
    for location in scrambler_locations and (game_state.get_resource(BITS)) >= bits:
NameError: name 'game_state' is not defined

Another thing, How do I use the __init__ module?

So I want to clarify a bit about what import does and how to use it. Literally, any python file can (technically) be used as a module. For example:

*Note: I am assuming for these little demos that file 1 and 2 are always in the same directory

# file1
import file2
print ('in primary file')

# file2
print ('this is from the imported file')

outputs:

this is from the imported file
in primary file

But this obviously does not happen when you import a library because it doesn’t output a bunch of info when you do import gamelib for example. This is because everything is in functions or classes. So here is another example:

# file1
import file2
print ('in primary file')

# file2
def foo():
    print ('this is from the imported file')

outputs:

in primary file

because foo was never called. In contrast:

# file1
import file2

foo()
print ('in primary file')

# file2
def foo():
    print ('this is from the imported file')

outputs:

NameError: name 'foo' is not defined

This is because foo is not inside the scope of file1, it is inside the scope of file2. If you are familiar with C++, etc this is akin to a namespace (just ignore if you’re not familiar with this). To make this work you have to tell python that foo() is part of file2, not file1. So like this:

# file1
import file2

file2.foo()
print ('in primary file')

# file2
def foo():
    print ('this is from the imported file')

outputs:

this is from the imported file
in primary file

But what if you have a massive python file and you really don’t need everything inside of it. You just want certain parts of the file. This is where the from ____ import ____ comes from. For example:

# file1
from file2 import foo

foo()
bar()
print ('in primary file')

# file2
def foo():
    print ('this was imported')
def bar():
    print ('this was not imported')

outputs:

this was imported
NameError: name 'bar' is not defined

The error is thrown because you did not import the entire file, just the function foo(). Note that with this different syntax I do not specify file2.foo(), just foo().


This covers basic importing another file. What if you want to import a whole bunch of files that are inside a folder, and control what you get from them. Python handles this by specifying that __init__.py is where it looks when you import a folder.

Looking at the init file for the gamelib folder:

"""
The gamelib package contains modules that assist in algo creation
"""

from .algocore import AlgoCore
from .util import debug_write
from .game_state import GameState
from .unit import GameUnit
from .game_map import GameMap
from .advanced_game_state import AdvancedGameState

__all__ = ["advanced_game_state", "algocore", "game_state", "game_map", "navigation", "unit", "util"]

We can see that this uses almost exactly the same syntax that I have above, with the exception that there is a period in front of each file name. The __all__ is essentially a list of modules that are required when you import gamelib. This primarily happens/is necessary when you do from gamelib import * (meaning import all), which is not recommended.

Thus, in your code it prevents you from having to import a ton of files, instead you just do import gamelib and now you have access to all of those other files.

So to use the GameState class, eg make an object from that class, you would do gamelib.GameState in the same way when we imported other modules from the examples above. And thus, this matches the syntax for creating a GameState object that we see in the code: game_state = gamelib.GameState(self.config, turn_state)

2 Likes

so I do from gamelib.GameState import can_spawn, attempt_spawn, get_resource
because that didn’t work… @Isaac

currently my module is inside of gamelib, so I would assume import game_state would work but it doesnt.

Those functions are a part of the GameState class. This means they are used on an object of that class type. So game_state is an object of type GameState (the syntax here is consistent, class is capitalized). So to use those functions you would do game_state.can_spawn, etc because they are part of that game_state object (which got them from the class).

so what do I write? I don’t know how…

this is my code:

def bits1(bits=0, side='A'):
    if side=='A':
        scrambler_locations = [[26, 12], [1, 12]]
        for location in scrambler_locations and (game_state.get_resource(BITS)) >= bits:
            if game_state.can_spawn(SCRAMBLER, location):
                game_state.attempt_spawn(SCRAMBLER, location)

It has the game_state.can_spawn
What I am having issue with is importing game_state, which my algo doesn’t want to do

Where is this code located? Is it in the module inside gamelib directory or is it in the algo_strategy.py file?

that code is inside of the a .py file, inside of gamelib

inside of algo strategy I say
module.bits1()

then it tells me that game_state is not defined

So think about the scope inside that file you are using. If you are using game_state, then you need to import it just with import game_state at the top of your file. However, I think this next bit is where the confusion is coming in. game_state is the name of a file containing the GameState class. game_state is also the name of an object inside the AlgoStrategy class. The way to use can_spawn, etc is to create an object from the GameState class and then call the function from that object - this is what AlgoStrategy does. You cannot call these functions without creating a GameState object. Even if you create a GameState object, your can_spawn function will not work as expected because it is not the same object that is inside the AlgoStrategy class.

If you plan on using the game_state object, you need to pass it as a parameter.

So in AlgoStrategy:

module.bits1(game_state)

in module:

def bits1(game_state, bits=0, side='A'):
if side=='A':
    scrambler_locations = [[26, 12], [1, 12]]
    for location in scrambler_locations and (game_state.get_resource(BITS)) >= bits:
        if game_state.can_spawn(SCRAMBLER, location):
            game_state.attempt_spawn(SCRAMBLER, location)

well time to rewrite all of my code :stuck_out_tongue:

ok after adding game_state to every other line of code, now the error is

  File "/tmp/algo10304890926305530212/gamelib/groupings.py", line 412, in bits1
    for location in scrambler_locations and (game_state.get_resource(BITS)) >= bits:
NameError: name 'BITS' is not defined

Doesn’t game_state take care of that too?

change it to be game_state.BITS.

(game_state.get_resource(game_state.BITS))
like that?
that gives a
TypeError: 'bool' object is not iterable @Isaac

You are doing for location in scrambler_locations and (game_state.get_resource(BITS)) >= bits:. You cannot have an and with the for loop. It should be:

for location in scrambler_locations:
    if game_state.get_resource(BITS) >= bits:

gotcha, time to rewrite my code again lol

so now it says NameError: name 'SCRAMBLER' is not defined
but when I change it to game_state.SCRAMBLER it says
'GameState' object has no attribute 'SCRAMBLER' @Isaac

If you look in the GameState class, you can see everything that can be accessed using the game_state object. Everything that has self.____ can be accessed. So if you look in GameState under the function __init__ you will see all the data you can access.

You should also see a line:

SCRAMBLER = config["unitInformation"][5]["shorthand"]

as you can see, this does not have a self attached, meaning it’s scope is only in the __init__ function and it cannot be accessed outside of that function. You can make it part of the class by adding somewhere beneath it inside __init__

self.SCRAMBLER = SCRAMBLER

do I have to do that for DESTRUCTOR and FILTER as well?

Yes, if you want to use them as part of the class.