Note: You should complete this assignment in identified pairs (not more than two students). You should submit your assignments separately, but you will receive the same grade as your partner. You may do this assignment by yourself, if you are so inclined…but then you cannot discuss the homework with any other students (or reference any other students in your header).

In this assignment, you’ll use classes to create a simplified Pokémon Game. Using your interface, the players should be able to:

You will practice working with classes and object-oriented programming techniques by building a simiplified Pokémon-like game. You’ll have lots of freedom to determine the game mechanics. Because most of us are new to Object-Oriented Programming, this assignment is structured a little more like a lab to help you get started.

Challenge 1: Creating a class definition

Recall from lecture that classes function as blueprints for building objects in Python. They bundle together data (inside attributes) and actions (inside methods) in ways that are both logical and easy to maintain/extend. In this first challenge, we’ll create a generic Pokemon class.

Create a Pokemon class. The class definition should include:

  • a constructor that takes in a name parameter
  • the constructor should initialize the following attributes (don’t forget that all attributes/methods should be members of the Pokemon class – use the word self!):
    • name = the value contained in the name parameter passed to the constructor
    • pokemon_type = "NORMAL"
    • max_hp = a random integer (you decide the range)
    • current_hp = max_hp
    • attack_power = a random integer (greater than 0 but less than hp)
    • defensive_power = a random integer (greater than 0 but less than hp)
    • fainted = False
  • a method called printStats() that prints the Pokémon’s stats to the screen
  • a method called defend() that decreases the value of current_hp by some amount (you determine by how much, but it should probably be related to defense in some way) and setting fainted = True if current_hp falls below 0
  • a method called attack(opponent) that takes in an opponent (another Pokemon instance) and decreases its current_hp by calling opponent.defend()
  • a method called revive() that if fainted = True sets current_hp = max_hp/2 and fainted = False and returns True, otherwise returns False

Test out your class by creating an instance of the Pokemon class in your main() function, calling .printStats() once to see the starting stats, calling .defend() until the Pokemon faints, and then calling .revive() and .printStats() again.

Challenge 2: Creating a simple battle() function

Woohoo, you’ve got your Pokémon class working! Unfortunately, the game isn’t very much fun by yourself.

Create a battle() function that takes two Pokemon instances (one belonging to each player), and alternates between them.

On each player’s turn, their Pokemon will attack the other player’s Pokemon, and the defending Pokemon will then print its stats. You may want to print additional information to the screen to make gameplay more interesting.

Test your battle() function by creating a second Pokemon instance within your main() function, and calling battle() on the two instances.

Challenge 3: Extending the class definition

In the actual game, there is more than one kind of Pokémon, each with its own special kinds of attack.

Add three or more subclasses that extend the Pokemon class, modifying the pokemon_type if necessary and overriding the attack() method (which may do different kinds of damage depending on the opponent). For example:

class Pikachu(Pokemon):

  self.type = "ELECTRIC"
  
  def self.attack(opponent):
      if (opponent.type == "GROUND"):
        # super-effective
        # do twice as much damage
      elif (opponent.type == "ELECTRIC" or opponent.type = "FLYING"):
        # not effective
        # do half as much damage
    

Test out your subclasses by creating instances of them in your main() function, and then calling battle() repeatedly to see how they fare against one another.

Final Challenge: Coder’s Choice!

Add some additional functionality to make the game more interesting: you might implement a more complex formula for .attack()/.defend(), add multiple kinds of .attack() and allow the player to choose between them, use ASCII art to make the game more visually appealing… how far you go is entirely up to you!

Recommendation: if you find yourself adding the same functionality to every subclass (e.g. if you want your Pokémon to have a nickname, etc.), consider changing the parent class instead!




Grading criteria (9 points):

Style points (3 points):

The submission:

  • runs without syntax errors and includes the complete and correct course header
  • uses appropriate, informative variable names, inline comments, and descriptions of each function 
  • program is organized into classes (with methods and attributes), and includes a main() function (which is not called when the module is imported)

First level (2 points)

The program:

  • The users can select their Pokémon, which creates appropriate instances of the Pokemon class
  • The stats of the selected Pokémon are randomly generated and printed to the screen

Second level (3 points)

  • The game alternates between players and on each player’s turn, their Pokémon attacks (and the defending player defends) - stats are updated accordingly
  • When a Pokémon faints, the player may revive them at most twice (stats updated accordingly; this counts as their turn)
  • When one Pokémon’s current_hp reaches 0 and they are out of revives, the game ends and a message is printed congratulating the battle winner

Third level (1 point)

  • Your Choice: add some additional functionality to make your game more exciting!



Submission

Recommended Submission: April 12, 2019 at 9:00PM (EST).

Last Submission: April 14, 2019 at 9:00PM (EST).

Go to our Moodle Page and submit your hmwk9.py file.