Python Terminal Game - Two-Player Soldier Battle

I did the blog post on medium. Go there for more information including the link to Github!

Your attack method concerns me.

def attack(self, other_player):
    if self.weapon == tommy_gun:
        damage_check = 5
        print("{self} attacked {other_player} for {damage} damage!".format(self=self.name, other_player = other_player.name, damage = damage_check))
        print('')
        other_player.lose_health(damage_check)
    if self.weapon == gatling_gun:
        damage_check = 10
        print("{self} attacked {other_player} for {damage} damage!".format(self=self.name, other_player = other_player.name, damage = damage_check))
        print('')
        other_player.lose_health(damage_check)

You’re assuming global objects like tommy_gun inside your Player instance, which is awkward. You’re also not really taking advantage of having a Weapon object at all.

Rather, I’d want to see something like:

def attack(self, other_player):
    damage_check = self.weapon.damage_check
    print("{self} attacked {other_player} for {damage} damage!".format(self=self.name, other_player = other_player.name, damage = damage_check))
    print('')
    other_player.lose_health(damage_check)

For available weapons, I’d do something like:

class Weapon:
    def __init__(self, name, type1, weight, speed, damage_check):
        self.name, self.type1, self.weight, self.speed, self.damage_check = name, type1, weight, speed, damage_check

class Weapons:
    def __init__(self):
        self.items = [
            Weapon('Tommy Gun', 'machine gun', 20, 80, 5),
            Weapon('Gatling Gun', 'Heavy Laser Weapon', 80, 20, 10),
            Weapon('12 Gauge Shotgun', 'shotgun', 45, 50, 7),
            # more in future?
        ]

    def choices(self):
       return ", ".join("{} [{}]".format(x.name,i + 1) for (i, x) in enumerate(self.items))
    
    def player_choose(self):
        # we have a list, can we match the input to the list?
        # loop until they give us what we want
        while True:
            try:
                # we want a number, but they might enter junk
                choice = int(input("Which weapon do you want? Your choices are {}: ".format(self.choices())))
                choice -= 1
                if choice<0 or choice>= len(self.items):
                    print("Out of range")
                else:
                    return self.items[choice]
            except ValueError:
                print("You must choose a number")

weapons = Weapons()

player_one_weapon = weapons.player_choose()
print("Player one chooses {}".format(player_one_weapon.name))

Note, that pick int from list logic can be generalized. You’d probably get quite a bit of use out of such a thing, Give it a go.

1 Like

Thanks for all of the feedback! Yeah - I knew I wasn’t taking advantage of the weapons class as much as I should. I don’t know why setting the damage_check as a parameter wasn’t obvious to me. I don’t think I’ve learned about the try: except process in the player_choose function you show, but it looks interesting. I also need to study the choices(self) method you show, because that doesn’t make sense to me at first glance.

Yeah, that one is a little arcane if you’ve never seen the moving parts before. It uses enumerate to tack an index on there. A list-comprehension to build the items with those numbers. And a string join to put it together.

Another way to write it would be:

def choices(self):
    names = [] # empty list
    i = 1 # current number
    for item in self.items:
        name = "{} [{}]".format(item.name, i) # formatted name
        names.append(name) # add name the list
        i += 1 # inc our counter
    return ", ".join(names) # join the list with commas

Oh, and that safe int input can be found here. Man, that site is popping up a lot.

Thanks for the information! sorry for the late response. I’ll check out the Real Python site more too. Looks interesting.