Python代写:CSSE1001-Pokemon-Finding-Game

Introduction

For this request, you will be writing code that supports a simple Pokemon finding game. The basic idea of the application is that you explore multiple levels in search for Pokemon, which are then registered in your Dex. Rather than using functions, like request 1, you will be using Object-Oriented Programming (OOP). Further, you will be using the Model View Controller (MVC) design pattern. Your task is to write the Model. The View and Controller are provided, along with support code.

As is typical with projects where more than one person is responsible for writing code, there needs to be a way of describing how the various components interact. This is achieved by defining an Application Programming Interface (API). For this request, you must implement your classes according to the API that has been specified, which will ensure that your code will interact properly with the supplied View/Controller code.

One benefit to adhering to MVC is that the model can be developed and tested independently of the view or controller. It is recommended that you follow this approach. This means testing your model iteratively as you develop your code.

request Tasks

Download files

The first task is to download a2.py and a2_files.zip. The file a2.py is for your request. Do not modify the request file outside the area provided for you to write your code.

Important Definitions

While Pokemon is an irregular plural (meaning that its plural takes the same form as its singular, like sheep and fish), for the purposes of this request, multiple Pokemon are referred to as Pokemons for clarity.

Positions & Coordinates

A position is represented by a (row, column) pair of numbers.
A cell position is a position where the row and column are both integers. It represents the position of where an object in the game could be located.
A wall position is a position where either the row or column value is a float ending in .5 and the other is an integer. The .5 represents that the wall is located at a boundary betweeen two cell positions for that row or column.

Expecting, Registering, & Catching

Catching a Pokemon refers to the player adding it to their collection. Whilst moving around the game world, the player catches a Pokemon by moving onto a cell in which that Pokemon exists. When a Pokemon is caught, it is removed from the game world.
A Pokedex, henceforth abbreviated as Dex, maintains a registry of Pokemon that the player is expected to catch. A Pokemon is registered in a Dex when the player catches that Pokemon. Registering a Pokemon that has already been registered has no effect.

Game Data

Game data can be loaded using either load\game_file(file) or load_game_url(url) from the support file. These functions will raise errors if the file/url do not exist or provide invalid JSON, as specified in their docstring comments. Game data consists of the following structure, comments added for clarity:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
levels: [ # List of levels in game
{
terrain: str, # Name of the terrain type
rows: int, # Number of rows
columns: int, # Number of columns
player: (int, int), # Player's starting position
pokemons: [ # List of pokemon existing in level
{name: str, position: (int, int)},
...
],
walls: [ # List of walls existing in level
(int, int),
...
]
},
...
]
}

For example, game data is a dictionary, containing the string “levels” as a key, whose value is a list of level data. Further, level data is a dictionary with multiple keys. The string “terrain” is one key that has a value that is a string indicating the name of the terrain. The string “walls” is another key that has a value that is a list of pairs of integers, each representing the location of a wall in the level.

Write the code

There are several classes you need to write and these are described below. It is highly recommended that you review the support file, a2_support.py, before writing your code, as this contains many useful constants and functions. Do not use global variables in your code.

Commenting

Each class and method that you write must have a suitable docstring comment, as specified in the course notes.

The GameObject Class

GameObject is the superclass for objects that exist in the game grid. Instances of GameObject are to be constructed with GameObject(name, position), where name is a string representing the name of the object and position is a grid position. Further, the following methods are to be implemented:

  • set_position(self, position) Sets the position to position, which either is a cell position or None.
  • get_position(self) Returns the current position of the instance.
  • set_name(self, name) Sets the name to name.
  • get_name(self) Returns the name of the instance.
  • str(self) Returns a human readable representation of this instance, according to GAME_OBJECT_FORMAT in the support file.

The Pokemon Class

Pokemon inherits from GameObject and is used for managing the name and position of Pokemon within the game.
Instances of Pokemon are to be constructed with Pokemon(name, position, terrain), where name and position are as they are for GameObject, and terrain is a string representing the terrain in which the Pokemon exists.
Further, the following methods are to be implemented:

  • set_terrain(self, terrain) Sets the terrain to terrain.
  • get_terrain(self) Returns the terrain of the instance.
  • str(self) Returns a human readable representation of this instance, according to POKEMON_FORMAT in the support file.
1
2
3
4
5
6
7
8
>>> mew = Pokemon("Mew", (20, 20), "Mountain")
>>> str(mew)
'Mew @ (20, 20) from Mountain'
>>> mew.get_terrain()
'Mountain'
>>> mew.set_terrain("Grass")
>>> str(mew)
'Mew @ (20, 20) from Grass'

The Wall Class

Wall inherits from GameObject and implements no additional functionality. It is used for representing a wall in the game.

The Player Class

Player inherits from GameObject and is used for representing a player within a grid.
Instances are to be constructed with Player(name), where name is as it is for GameObject.
A Player must contain the following:

  • A Dex to register all the Pokemon that the Player encounters.
  • A list of Pokemon that the Player has caught, in the order they were caught.

The following methods are to be implemented:

  • get_pokemons(self) Returns a list of all Pokemon that this Player has caught, in the order they were caught.
  • register_pokemon(self, pokemon) Catches the pokemon and adds to the Player’s Dex, where pokemon is a Pokemon, provided it is expected by the Player’s Dex. Otherwise, this method should raise an UnexpectedPokemonError.
  • str(self) Returns a human readable representation of this instance, according to PLAYER_FORMAT in the support file.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
>>> mew = Pokemon("Mew", (20, 20), "Grass")
>>> d1 = Pokemon("Dragonite", (1, 1), "Mountain")
>>> d2 = Pokemon("Dragonite", (1, 3), "Mountain")
>>> brock = Player(DEFAULT_PLAYER_NAME)
>>> str(brock)
'Ash @ None has caught 0'
>>> brock.set_name("Brock")
>>> brock.set_position((1,1))
>>> brock.register_pokemon(mew)
Traceback (most recent call last):
... # truncated for brevity
a2_support.UnexpectedPokemonError: Mew is not expected by this Dex.
>>> brock.get_dex().expect_pokemons(['Mew', 'Dratini', 'Dragonair', 'Dragonite'])
>>> brock.register_pokemon(mew)
>>> brock.register_pokemon(d1)
>>> brock.register_pokemon(d2)
>>> str(brock)
'Brock @ (1, 1) has caught 3'
>>> for pokemon in brock.get_pokemons(): print(pokemon)
Mew @ (20, 20) from Grass
Dragonite @ (1, 1) from Mountain
Dragonite @ (1, 3) from Mountain
>>> print(brock.get_dex())
2 Registered: Dragonite, Mew
2 Unregistered: Dragonair, Dratini
>>> brock.reset_pokemons()
>>> str(brock)
'Brock @ (1, 1) has caught 0'
>>> print(brock.get_dex())
0 Registered:
0 Unregistered:

The Dex Class

The Dex class manages a registry of Pokemon that have been encountered. For the Dex class, pokemon refers only to the name of a pokemon, and not an instance of the Pokemon class.

Instances are to be constructed using Dex(pokemon_names), where pokemon_names is a list of poke- mon names to be expected by this Dex. In order for a Dex to be complete, all the Pokemon that are expected must also be registered.

A Dex must contain a dictionary whose keys are pokemon names that are expected by this Dex, and whose values indicate whether the corresponding pokemon is registered in this Dex (True: registered; False: unregistered).

Further, the following methods must be defined for the Dex class.

The Level Class

The Level class manages data pertaining to an individual level in the game. A Level is considered complete when its Dex has no unregistered pokemon. N.b. It is possible to complete a level without having caught all pokemon that exist in that level, since there may be duplicate Pokemon.

Instances are to be constructed with Level(player, data), where player is an instance of Player, and data is a dictionary of a single level’s data. When initialised, a Level should instruct the player’s Dex to expect all the Pokemon that could be encountered in the current level. If a level contains an invalid position (player start, pokemon, wall, etc.), it must raise an InvalidPositionError.

The Game Class

The Game class manages data pertaining to an entire game. Its constructor requires no arguments.

  • An instance of the Player class, which will be used when instantiating each Level.
  • A list of Levels in the order in which they are loaded. This list will be empty until either the load_file or load_url method is called, but upon loading a game, this list must contain instances of the Level class, one for each level in the game data.

Assessment and Marking Criteria

In addition to providing a working solution to the request problem, the assessment will involve discussing your code submission with a tutor. This discussion will take place in the practical session you have signed up to in week 10. You must attend that session in order to obtain marks for the request.

In preparation for your discussion with a tutor you may wish to consider:

  • any parts of the request that you found particularly difficult, and how you overcame them to arrive at a solution;
  • whether you considered any alternative ways of implementing a given function;
  • where you have known errors in your code, their cause and possible solutions (if known).