The def line is only run once, evaluating the expressions there and saving the results before any instances of dungeonRoom are instantiated.

You could think of that code having a static initializer which creates constants:


Then it just uses them when creating new dungeonRooms as follows:

 def __init__(self, height=_init_height, width=_init_width, origin=_init_origin):

Can you just move the random calls into the contents of the __init__ function?

Edit: example:

def __init__(self, arg=None):
    if arg is None:

(More info here if you want.)


Sorry, I don’t really understand the question… I’m just making it up as I go, starting with a ‘room’ object of randomly defined width/height/origin, then I place it into a large list that contains every point in the map.


No worries, seeding is the first place my mind goes when seeing repeated “random” numbers, but in this case I was on the wrong track, and Romalar’s suggestion should fix the problem.

For reference, random.seed() sets up the random number generator. If you call it without any arguments, it will use the current system time as a source of pseudo-randomness. But if you call it with a specific number, it will use that, which can be useful for testing as it can ensure you get the same sequence of die rolls each time. If you were calling seed with a constant value before each time you initialized a room, you’d see them each come out with the same random values. But that wasn’t your problem here.


I see, thanks.

That worked, thanks!

I removed the ‘else’ statements from your example as it seems each arg would always be None to begin with. Maybe I’m making a mistake by doing that, but the code seems to run OK.

I may have to go back to the textbooks for a deeper understanding of objects soon. It’s just more fun to make stuff…


It’s worth noting that in C++ / C# you wouldn’t even be able to do this: the default values have to be compile-time constants. In effect the same is true in Python, it just doesn’t make it so obvious.

I think I’d write it as:

def __init__(self, height=None, width=None, origin=None)
    self.height = height or random.randint(3,9)


Dungeons? Aren’t you supposed to be working on Derpspace? Lazy devs.


If the person calling the code specifies other values, you want to copy them into the object’s values. That’s what the else block is for. If you always want the values to be random, then you don’t even need to have an argument, just set self.blah to random.


That’s actually why I figured this out right away. I didn’t know for certain how Python implemented this until I looked it up, but I knew it was the likely cause due to how those languages structure it and how OOP constructs are typically implemented under the hood. It’s nice when all that random info in your head synergizes well.


Shhh! Don’t tell!

However, the good news is my amazing room-generating algorithm can also be applied to… Starbases!


Another question for the Pythonians around here.

I’m doing a simple ASCII checkers game (turns out that a text based UI is pretty lousy for checkers, but I just want to get the logic and maybe even take a stab at AI).

So, I have a Board object and its grid list (defaulting to “.” elements) gets populated with Os and Xs based on the ‘position’ values of Piece objects.

I’m currently emptying the board each turn – blanking it back to all “.” and then feeding in the latest Piece positions to add the Os and X’s. Then I draw the board again.

The wrinkle is in my clearBoard(self) function for the Board object.

When I code it this way (Board.grid is a list object):

self.grid=["." for i in range(64)]

it works fine. (This is identical code to the snippet in Board’s init function setting up the grid initially)

But I was originally trying to code it this way:

for i in self.grid:

(assume correct indentation)

When I wrote the function like that, it did nothing; the Os and Xs remained.

Any idea what gives? Does it have anything to do with the way lists work?

DERPSPACE: Encounter at Regula O.S.S. |OT| A bold new space game by Gordon Cameron

For the “for i in self.grid” command, what you’re doing is creating a loop, and within the loop’s scope, you’re creating a variable i. Each iteration of the loop is assigning the value of the grid element to i before the loop code block starts. (Technically, it’s creating an iterator over the list I think, but the effect is as above).

When you assign i = “.”, you aren’t modifying self.grid, you’re simply re-assigning the value of the local variable i.

What you’re doing is kind of like this:

for x in range(0, length(grid)):
    i = grid[x]
    i = "."

(Markdown tip, three backticks (the thing above tab with the tilde) make a code block.)


Also, unrelated to the current issue, but you might want to look into using a 2D array for the grid. That’s basically an array of arrays, addressed like grid[x][y]. That way you have one variable for the row and another for the column, which should simplify your display and AI logic.


I almost mentioned that, since it’s kind of conceptually cleaner, but if you make a getValueOfPos(x, y) function with some division and modulo math, it’s pretty much the same.


I will definitely look into that. I’ve assumed there’s a better way to do a grid than just make a single list and then finagle the ± values into weird contortions for object movement. I just didn’t know what it was :)


By the way, is it OK to use ‘while True:’ as the basis of a core program loop, or is there a more elegant way to do that?


That’s fine for a game loop, but you can refine it slightly by doing:

done = False
while done == False:
Code here

That way you can terminate the loop from within by setting done to True.

Incidentally, if you want to see how people program games in Python, have a look at PyWeek ( PyWeek is a game jam for Python, there are a lot of past entries with source code to look at and they have links to some good resources for Python games programming on their forum.