2015-05-12 22:13:22

if you haven't seen my previous topic here i'm working on a monopoly game. i have since resolved, or hopefully, my issues in that thread. however like it often does more errors and things have cropped up since.
my current issue i'm trying to plow my way through is how to see what the arguments are when an object is initialized.
my error here is on line 68. it says type error __init takes 4  arguments 2 given. i'm not sure why this is saying it. any help on this would really be greatly appreciated. also, if anyone could elp me with my global variables. i know i use them all the time in this. not really sure if i should be using return. and if so how to implement it in my case.

code follows:

from random import randint
from sys import exit

board = ("Go", "Mediterranean Avenue", "Community Chest", "Baltic Avenue", "Income Tax", "Reading Railroad", "Oriental Avenue", "Chance", "Vermont Avenue", "Connecticut Avenue", "Jail", "St. Charles Place", "Eletric Company", "States Avenue", "Virginia Avenue", "Pennsylvania Railroad", "St. James Place", "Community Chest", "Tennessee Avenue", "New York Avenue", "Free Parking", "Kentucky Avenue", "Chance", "Indiana Avenue", "Illinois Avenue", "B. & O. Railroad", "Atlantic Avenue", "Ventnor Avenue", "Water Works", "Marvin Gardens", "Go to Jail", "Pacific Avenue", "North Carolina Avenue", "Community Chest", "Pennsylvania Avenue", "Short Line Rail Road", "Chance", "Park Place", "Luctury Tax", "Boardwalk")


#main player class
class Player(object):

#main player init function. will be expanded later. just basics for now.
    def __init__(self, name, cash, position):
        self.name = name
        self.cash = cash
        self.position = position

#Player method handling piece movement around the board.
    def movement(self):
        global die1
        global player
        global current_position
        new_position = die1 + self.position
        if new_position >= 40:
            temp = self.position + die1 - 40
            new_position = temp
        else:
            pass
        print "you move %d squares and are now on square %s." % (die1, board[new_position])
        current_position = new_position
        print "now you are on square %s for your next roll." % board[current_position]
        self.position = new_position
        game.change_turn()


#Player method handling die rolling. will be expanded later to include 2 dice with logic for playing more turns if player rolls #doubles.
    def roll(self):
        global die1
        die1 = randint(1,6)
       
       

#player method for handling input as to what the player wants to do on his or her turn. will be more robust later.
    def turn(self):
        global current_position
        global player
        current_position = board[self.position]
        print "okay %S. you are on square %s." % (self.name, current_position)
        choice = raw_input("what would you like to do?")
        if choice == "roll":
            player.roll()
        else:
            print "woops. don't understand."
        player.turn()
        print "you rolled a %d. great job! now lets see what we can do with it." % die1
        player.movement()


#main class for setting up a game of monopoly.
class Session(object):

#init function for setting up the list that players will be put into in order for them to be cycled through during gameplay.
    def __init__(self):
        self.player_list = []

#method for adding players to the list
    def add_player(self, player):
        self.player_list.append(player)

#method for removing players from the list when out of the game.
   def remove_player(self, player):
        self.player_list.remove(player)

#method for setting who's playing to pass it off to the player class. contains error. see above.
    def set_turn(self):
        global current_player
        global player
        global p1
        global p2
        player = Player(self.player_list[current_player])
        print "now its %r." % current_player

#method for changing players to move the game along.
    def change_turn(self):
        global current_player
        next_player = (current_player + 1) % len(self.player_list)
        current_player = next_player
        game.set_turn()


#starting method to begin gameplay
    def start(self):
        global current_player
        print "lets start the game."
        print "we have %r players playing." % len(self.player_list)
        print "player 1 will start for now."
        current_player = 0
        game.set_turn()




   
#initializing my players
p1 = Player("kyle", 1500, 0)
p2 = Player("computer", 1500, 0)

#initializing game session and adding the players to the list
game = Session()
game.add_player(p1)
game.add_player(p2)
game.start()

I don’t believe in fighting unnecessarily.  But if something is worth fighting for, then its always a fight worth winning.
check me out on Twitter and on GitHub

2015-05-13 04:02:00

Hi,
The reason Python is saying this is because one of the following conditions are being met:

  1. You are calling the function within a class. In this case, try .__init__(self, arguments).

  2. You are calling it in another class, but not adding the self attribute along with it.

If this does not help you, something else is cropping up and I don't know how to fix it.

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.
My Github

2015-05-13 04:08:48

As far as I can understand it, you're passing a class instance to a class, which flips out because the __init__ attribute takes more arguments, and it doesn't take an instance. Try removing the player() thing around your player assigning.

This is not a signature.

2015-05-13 06:22:14

lol dhruv i at first typed out this big long message. then i understood what you were saying. yay. its fixed.
but any help from anyone on how i can be more pythonic would be awesome.

I don’t believe in fighting unnecessarily.  But if something is worth fighting for, then its always a fight worth winning.
check me out on Twitter and on GitHub

2015-05-17 23:42:57

Hello,
I am not 100% sure you are understanding classes correctly.
Any thing can be a class, so the die, the player, the locations...
The player list should not be a class, it should be a variable. (Unless you are making the board a class, in that case, you could add everything that is on the board, including the players, to the class).

In a python program there are constants:

board = ["Go", "Mediterranean Avenue", "Community Chest", "Baltic Avenue", "Income Tax"]
player_list = [player1, player2] #I would make this an iterator actually so you can just call next(player_list).


Very rarely should you use globals, if you insist, make them in another module. And if you do have globals, define them always, always at the top of the module. That way you can see how many globals you have smile.

Then, realize that you can access constants (like your location list or player list) anywhere in the module without modifying them (You can modify lists though).
So take advantage of name-spaces being the same (if you have self.player in one place and it is an object, you can modify it in 2 places and it will be updated both places.
player = Player(name="joe")

player.name = "sam"

def change_name(object):
    object.name = "function changed"

change_name(player)
print(player.name)

return would be something basic, so an iterator like function like:
def change_player(current_player):
    if current_player == player_list[0]:
        return player_list[1]
    else:
        return player_list[0]

Then your change turn can call this function and set self.current_player as the result.


But I would make board a class and make that the master engine/put everything that would be globals there.
Then pass in more arguments and return stuff that the functions in board can process. You should always ask yourself if it would be easier and cleaner to not use globals.

A function should only be like 10 lines max, so if it is longer than that you should consider cutting it up into smaller functions. It can be larger, but if a function is too big, it is too complex. You should also use more docstrings
def change_player(current_player):
    """Alternates between player 1 and 2"""

That way you know what it does when you come back to your code after 3 months.

If you have not yet, read pep 8 and look for articles that talk about becoming more pythonic. Also, read up on how to use globals. They have their place, but most of the time you can use something else.

2015-05-18 18:59:44

i know anything can be a class. one thing i really liked was that in my tutorial i was learning from at http://learnpythonthehardway.org the guy said when figuring out what classes you'll need for a project use nouns from your game and the verbs that those nouns do should be methods within those classes. i really like that idea so i'm running with that right now. as this is my first big project i know i'm not going to stick to this way of doing things. hopefully my coding will get better and more refined as i work on it more and discover what does and doesn't work for me. i'm running with this now. so in my example players do all the rolling dice, moving around the board, buying and selling properties; so it makes no sense to shove that over into a board class.  my code has also expanded as well since this version posted above. my board is now apart of the session class and is a list of square objects; subclassed to be properties, railroads, utilities, etc.
the reason i have my change_turn method like i do so that its flexible and can take many different numbers of players. once i clean my code up more and make everything working like its supposed to, i'll not have the players hard coded into the source code. i'll get input from the player as to how many players he or she wants and all that sort of stuff.  i also eventually want players to be able to play over the internet with their friends, be able to play locally on the same computer, or if i can code a good AI system, against computer opponents. but now, i just want to even see if i can even code a monopoly game. i have a few more things left to add. i'm working on implementing rent being charged when a player lands on  an owned property. i want to get that solid because the things i need to put in after that depend on rent working well: buying houses and hotels. and obviously paying rent on those improved properties. the chance and community chest decks are already in the session class i just need to code the card objects to fill them. and i also need to add mortgaging properties, selling houses, and a check to see if someone goes bankrupt and needs to be removed from the game.  while monopoly does seem like its an eternal game, it actually isn't. lol
i don't know if its the fact i just don't understand return all that well, but i just couldn't think of anything that would work in place of those global vars. i need to use them across the different methods to keep track of values.
while i initially reject the idea that functions should be limited to 10 lines, i'll see what i can do with it.  as long as its commented well and the word choice of names for things isn't overly obscure, i think any pythonian should be able to follow whats going on.  i do understand the need for well-written optimized code, just as long as your not doing all of this extraneous stuff that isn't needed in a function; taking up CPU power and what not.  refine it, get it down as small as you can and as long as its staying on topic as it pertains to the function you should be good.  just my opinion guys. no need to call the python police on me if i'm trashing python laws or anything.

I don’t believe in fighting unnecessarily.  But if something is worth fighting for, then its always a fight worth winning.
check me out on Twitter and on GitHub