Python
Clean up the code
Recall that once a subclass inherits from a parentclass, it automatically has access to all of the parents' methods.Sometimes, the subclass needs to do extra things within a methodwhich the parent does not do. For example, both UserPlayer andBasicMonster have their specialized __init__ methods which overridethe one from Player. Discuss the following question with yourpartner: What are the other methods that are being overridden by asubclass in the set of classes you've been given?
Some of these methods are not necessary to override.Clean up your classes by moving the methods that could just be putin the Player class up into the Player class
and remove any unneeded repetition of these methodswithin subclasses.
import random
import time
class Player:
'''
The Player class includes things that every player has,
which is name and hp (health points).
'''
def __init__(self, name: str, hp: int, strength: int) ->None:
self.name = name
self.hp = hp
self.strength = strength
 Â
class UserPlayer(Player):
'''
UserPlayer inherits from Player, because it is a morespecific
type of Player. This type of Player is controlled by theuser.
'''
 Â
def __init__(self, name: str) -> None:
'''
Construct a UserPlayer with the given name, and a set
hp and strength. Also define mp for magic, a list
of possible moves they can make, and an inventory
dictionary of items they can use.
'''
super().__init__(name, 50, 10) # assign attributes name, hp,strength
 Â
self.mp = 50
self.moves = ['attack', 'magic attack', 'defend']
self.inventory = {'potion': 1, 'ether': 1} # potion should restorehp, ether restores mp
def attack(self, other: 'Player') -> None:
'''
Attack the Player by calling that Player's take_hitmethod.
The attack power is based on your own strength.
'''
 Â
other.take_hit(self.strength)
def take_hit(self, strength: int) -> None:
'''
Lose some hp based on the given.
Print message about how much hp you lost.
'''
 Â
power = random.randint(strength//2, strength)
print(\"{} was attacked, and lost {} hp.\".format(self.name,power))
self.hp = self.hp - power
def magic_attack(self, other):
pass
def defend(self):
pass
 Â
def make_move(self, opponent: 'Player') -> None:
'''
Make a move based on user input.
'''
 Â
not_valid = True
while not_valid:
move = input(\"What move do you want to take? a: attack, m: magic,d: defend\n\")
not_valid = False
if move == \"a\":
self.attack(opponent)
elif move == \"m\":
self.magic_attack(opponent)
elif move == \"d\":
self.defend()
else:
print(\"Invalid input. Try again.\")
not_valid = True
class Monster(Player):
'''
Monster class represents a Computer controlled player.
The make_move method is thus different for the Monster,
where the move is randomly chosen based on a randomly
generated number, rather than through user input.
'''
 Â
def make_move(self, opponent):
move = self.moves[random.randint(0, len(self.moves)-1)]
if move == \"basic attack\":
self.attack(opponent)
elif move == \"special attack\":
self.special_attack(opponent)
 Â
class BasicMonster(Monster):
'''
BasicMonster class represents a basic type of Monster.
We inherit the make_move from the Monster class, and this
BasicMonster only has those two moves, so we don't need
to add the make_move method here again.
'''
 Â
def __init__(self) -> None:
'''
Construct a BasicMonster with a name, hp, strength
and list of moves.
'''
 Â
super().__init__('Basic Monster', 50, 10) # assign attributes name,hp, strength
# the super call above uses the original Player class's initmethod
self.moves = ['basic attack']
# Question: What does the following code do?
if self.hp < 25:
self.moves.append = ['special attack']
def attack(self, other: 'Player') -> None:
'''
Attack the Player by calling that Player's take_hitmethod.
The attack power is based on your own strength.
'''
 Â
other.take_hit(self.strength)
def take_hit(self, strength: int) -> None:
'''
Lose some hp based on the given.
Print message about how much hp you lost.
'''
 Â
power = random.randint(strength//2, strength)
print(\"{} was attacked, and lost {} hp.\".format(self.name,power))
self.hp = self.hp - power
 Â
def special_attack(self, other):
'''
Attack the Player with a special attack thatexceeds
your usual strength.
'''
power = random.randint(strength, strength*2)
other.take_hit(40)
 Â
class Game:
def __init__(self, p1: 'Player', p2: 'Player') -> None:
'''
Construct a Game with the given players.
'''
self.players = (p1, p2)
self.turn = 0 # keep track of whose turn it is out of the twoplayers
def whose_turn(self, count: int) -> 'Player':
'''
Return the Player whose turn it is.
'''
if count % 2 == 0:
next_player = self.players[0]
else:
next_player = self.players[1]
return next_player
def play_game(self) -> None:
'''
Play the game, with each player taking turns making a move,until
one player runs out of hp.
'''
 Â
# print out the starting state of the game
print(self)
print('------------')
 Â
winner = None
while (not winner):
if (self.players[0].hp <= 0):
winner = self.players[1]
elif (self.players[1].hp <= 0):
winner = self.players[0]
else:
# if no one has won yet, play one turn of the game (one playermakes one move)
self.play_one_turn()
 Â
print('And {} is the winner!!!'.format(winner.name))
def play_one_turn(self) -> None:
'''
Play one turn of the game based on which player's turn it is.
Print state of game that results from this turn.
'''
 Â
current_player = self.whose_turn(self.turn) # get the Player whoseturn it currently is
other_player = self.whose_turn(self.turn-1) # get the other Playerin the game
print(\"{}'s TURN\".format(current_player.name))
# if the player is the computer, wait 2 seconds before
# showing the player's move to make the gameflow feel morenatural
if (isinstance(current_player,Monster)):
time.sleep(1)
 Â
current_player.make_move(other_player)
 Â
# print current state of game
print(self)
print('------------')
 Â
self.turn += 1
def __str__(self) -> str:
'''
Return string representation of state of game.
'''
 Â
return \"Player 1 hp: {}, Player 2 hp:{}\".format(self.players[0].hp, self.players[1].hp)
def main():
'''Prompt the user to configure and play the game.'''
name = input(\"What is p1's name? \")
 Â
p1 = UserPlayer(name) # make the first player a User at position(0,0)
p2 = BasicMonster()
 Â
g = Game(p1, p2)
g.play_game()
if __name__ == '__main__':
main()
 Â