code form etiquette

This is the place for queries that don't fit in any of the other categories.

code form etiquette

Postby Wommbatt » Wed Aug 21, 2013 1:59 pm

Hey everyone. Quick question on form etiquette.

background info:
In a game I'm making I find myself using 2 functions: a home menu and a main-game while loop. To make things work at the moment I have the home menu call the main-game loop. Then when a round of play ends the while loop then calls the home menu function.

Now for the questions:
Does this solution generate an endless series of function calls that just consume resources?
Is there a better, more efficient way to leave the one function and go to the other?

-wommbatt
Wommbatt
 
Posts: 24
Joined: Thu Jun 13, 2013 2:15 pm

Re: code form etiquette

Postby Mekire » Wed Aug 21, 2013 2:11 pm

While you probably won't have issues with this approach in a small program, it is certainly not the correct structure. It also sounds like a major memory leak (which takes work to accomplish in python).

A game (and many other types of program for that matter) should have a class that handles the main loop (singular). The different states (your menu and your play phase) of your program should be objects (class instances) within that control class (ideally held in a dictionary). The controlling class keeps track of which state currently has control and updates the current state during the main loop.

-Mek
User avatar
Mekire
 
Posts: 828
Joined: Thu Feb 07, 2013 11:33 pm
Location: Amakusa, Japan

Re: code form etiquette

Postby Somelauw » Wed Aug 21, 2013 6:54 pm

Wommbatt wrote:Does this solution generate an endless series of function calls that just consume resources?

yes, it could even create a stack overflow

Is there a better, more efficient way to leave the one function and go to the other?

probably yes. How about simply ending the main-loop or returning from the subfunction?

You might want to post some code to clarify your question.
Join the #python-forum IRC channel on irc.freenode.net!
Somelauw
 
Posts: 57
Joined: Tue Feb 12, 2013 8:30 pm

Re: code form etiquette

Postby Wommbatt » Thu Aug 22, 2013 1:08 pm

Well, right now this is what I've got, I've butchered the non relevant bits of the code out of it so it wont look quite so jumbled

Code: Select all
'''Main Game Loop'''
def game():
    while 1:
        print('A', enemy.name, 'approaches')
        print(enemy)
   
        action = get_action()
        if action is None:
            continue

        if action == "a":
            player_attack()
            if enemy.hp <= 0:
                print("You've defeated", enemy.name)
                main_menu()
            print(enemy)

'''Game setup'''
print("what is your name adventurer?")
player_name = input("> ")
player = Player(player_name)
enemy = Creature()

'''Game start'''
def main_menu():
    print("Press 'n' for a new game")
    new_game = input("> ")
    if new_game == "n":
        game()

main_menu()


How would I go about setting up different states?
-wommbatt
Wommbatt
 
Posts: 24
Joined: Thu Jun 13, 2013 2:15 pm

Re: code form etiquette

Postby Somelauw » Thu Aug 22, 2013 3:04 pm

A way to write your code without infinite recursion could be:

Code: Select all
def game():
    while enemy.health > 0:
        print('A', enemy.name, 'approaches')
        print(enemy)
   
        action = get_action()
        if action is None:
            continue

        if action == "a":
            player_attack()
            print(enemy)

    if enemy.health <= 0:
        print("You've defeated", enemy.name)   

def main_menu():
    new_game = "n"

    while new_game == "n":
        print("Press 'n' for a new game")
        new_game = input("> ")

        if new_game == "n":
            game()

if __name__ == "__main__":
    '''Game setup'''
    print("what is your name adventurer?")
    player_name = input("> ")
    player = Player(player_name)
    enemy = Creature()

    main_menu()
Join the #python-forum IRC channel on irc.freenode.net!
Somelauw
 
Posts: 57
Joined: Tue Feb 12, 2013 8:30 pm

Re: code form etiquette

Postby Wommbatt » Fri Aug 23, 2013 12:58 pm

So I tried your suggestion Somelauw. and it certainly took care of the infinite looping. I had to make some changes due to an unexpected issue which of course caused another problem lol. So here's the slightly changed code:

Code: Select all
'''Main Game Loop'''
def game():
    enemy = Creature()   ***** relocated *****
    print('A', enemy.name, 'approaches')
    while enemy.hp > 0:
        print(enemy)
   
        action = get_action()
        if action is None:
            continue

        if action == "a":
            player_attack()
            print(enemy)
           
        if enemy.hp <= 0:
            print("You've defeated", enemy.name)

'''Game start'''
def main_menu():
    new_game = "n"

    while new_game == "n":
        print("Press 'n' for a new game")
        new_game = input("> ")

        if new_game == "n":
            game()
           
if __name__ == "__main__":
    '''Game setup'''
    print("what is your name adventurer?")
    player_name = input("> ")
    player = Player(player_name)

    main_menu()


So that is the important change along with the rest of the code.
I made the change because leaving that call where it was didn't allow for a new enemy to generate, and putting it there I had hoped that with each new call of the game would set a new enemy. Instead I get an annoying "global 'enemy' not set" error when I use the "player_attack()" call.

The "Creature()" call is.... well I'll show you:

Code: Select all
class Creature(object):
    def __init__(self):
        self.new_enemy()
           
    def new_enemy(self):
        '''
        This sets a new enemy
        Can be called using "enemy = creature()"
        Can also be called using "enemy.new_enemy()"
        '''
        self.creature_tuple = random.choice(LORE)
        self.name = self.creature_tuple[0]
        self.level = self.creature_tuple[1]
        self.hp = self.creature_tuple[2]
        self.max_hp = self.creature_tuple[2]
        self.defense = self.creature_tuple[3]
        self.attack = self.creature_tuple[4]


I thought that class variables were global by nature.
Am I wrong on that?
Any insight as to why this is arguing with me now?

-wommbatt
Wommbatt
 
Posts: 24
Joined: Thu Jun 13, 2013 2:15 pm

Re: code form etiquette

Postby Somelauw » Fri Aug 23, 2013 10:03 pm

Wommbatt wrote:I thought that class variables were global by nature.
Am I wrong on that?
Any insight as to why this is arguing with me now?

-wommbatt


enemy is not a class variable. It's a local variable local to the function game.
A class variable would look like follows:
Code: Select all
class C:
     class_variable = 5


The variable enemy is created in the function game and can only be used in that function, unless you pass it to another function or return it.
A quick way to solve your problem, it to pass "enemy" as a parameter to the function player_attack.
Join the #python-forum IRC channel on irc.freenode.net!
Somelauw
 
Posts: 57
Joined: Tue Feb 12, 2013 8:30 pm

Re: code form etiquette

Postby Wommbatt » Fri Aug 23, 2013 11:53 pm

My goodness, how simple the solutions that I just don't think of.

Thanks again Somelauw
-wommbatt
Wommbatt
 
Posts: 24
Joined: Thu Jun 13, 2013 2:15 pm


Return to General Coding Help

Who is online

Users browsing this forum: No registered users and 3 guests