Description
Gameplay
Key Cave Adventure Game is a single-player dungeon-crawler game where the player
adventurously explores a dungeon. The objective is for the player to find the key and get out of
the dungeon through the door. This game is full of adventure. The game play utilises simple key
commands. The positions of Entities are always represented as (row, col). The game’s grid
should always be a square.
Commands
Input Action
‘-DIRECTION-’ Direction to move in
‘I -DIRECTION-’ ‘I W’ would investigate the Entity in the given
direction.
‘H’ Help text (see examples at end)
‘Q’ Quit
Table 1. List of valid actions.
Input Direction
‘W’ Up
‘S’ Down
‘A’ Left
‘D’ Right
Table 2. List of valid Directions.
Character Description
‘#’ WALL
‘O’ PLAYER
‘K’ KEY
‘D’ DOOR
‘ ’ SPACE
Table 3. List of characters used in the game
The Player can move within the dungeon by using any of the valid direction inputs outlined in
Table 2. The Player must collect the KEY by walking into it and then the DOOR can be
unlocked.
Game over
The Player wins the game by collecting the KEY and heading to the DOOR. This message
should display: You have won the game with your strength and honour!
If the Player runs out of moves before they collect the KEY and unlock the DOOR then the
Player loses the game. This message should display: You have lost all your strength and
honour.
The player loses a move count when they:
– Successfully moving to a new position.
– Unsuccessfully moving to a new position. E.g. The new position is a Wall.
– Investigating an Entity in a given direction
As seen in the Example game play
Getting Started
Files
a2.py – file where you write your submission
gamen.txt – the nth dungeon layout. There will be multiple provided. “game1.txt” is the best one
to start from.
To start, download a2_files.zip from Blackboard and extract the contents. This folder contains all
the necessary files to start this assignment. You will be required to implement your assignment
in a2.py. Do not modify any files from a2.zip except a2.py. The only file that you are required to
submit is a2.py. Some support code has been provided to assist with implementing the tasks.
Classes
Many modern software programs are implemented with classes and this assignment will give
you some practice in working with them. The class structure that you will be working with is
shown diagrammatically in Figure 1.
In Figure 1 an arrow with a solid head indicates that one class stores an instance of another
class. (This is analogous, say, to a list storing instances of strings within it, say,
sample_list=[‘dog’, ‘cat’]). In Figure 1, for example, GameApp points to Display meaning that
GameApp contains an instance of Display.
An arrow with an open head indicates that one class is a subclass of another class. I.e. one
class inherits from another. E.g. Item is a subclass of Entity.
You can add classes to reduce code duplication. This can include adding your own private
helper methods. However, you must include the classes outlined below.
Figure 1. Class structure for the software program
Entity
A generic Entity within the game.
Each Entity has an id, and can either be collided with (two entities can be in the same position)
or not (two entities cannot be in the same position.) The collidable attribute should be set to
True for an Entity upon creation. Entity should be constructed with Entity(). Entity should have
the following methods defined:
get_id(self) -> str: Returns a string that represents the Entity’s ID.
set_collide(self, collidable: bool): Set the collision state for the Entity to be
True.
can_collide(self) -> bool: Returns True if the Entity can be collided with (another
Entity can share the position that this one is in) and False otherwise.
__str__(self) -> str: Returns the string representation of the Entity. See example
output below.
__repr__(self) -> str: Same as str(self).
Examples
>>> entity = Entity()
>>> entity.get_id()
‘Entity’
>>> entity.can_collide()
True
>>> str(entity)
“Entity(‘Entity’)”
>>> repr(entity)
“Entity(‘Entity’)”
>>> entity = Entity()
>>> entity.can_collide()
True
>>> entity.set_collide(False)
>>> entity.can_collide()
False
(Note that Entity should never be set to False, this is just an example)
Wall
A Wall is a special type of an Entity within the game.
The Wall Entity cannot be collided with. Wall should be constructed with Wall(). Wall should
have the following methods defined:
get_id(self) -> str: Returns a string that represents the Wall’s ID.
set_collide(self, collidable: bool): Set the collision state for the Wall to be
False.
can_collide(self) -> bool: Returns True if the Wall can be collided with and False
otherwise.
__str__(self) -> str: Returns the string representation of the Wall. See example output
below.
__repr__(self) -> str: Same as str(self).
Examples
>>> wall = Wall()
>>> wall.get_id()
‘#’
>>> wall.can_collide()
False
>>> str(wall)
“Wall(‘#’)”
>>> repr(wall)
“Wall(‘#’)”
>>> wall.set_collide(True)
>>> wall.can_collide()
True
(Note that Wall should never be set to True, this is just an example)
Item
An Item is a special type of an Entity within the game. This is an abstract class.
By default the Item Entity can be collided with. Item should be constructed with Item(). Item
should have the following methods defined:
get_id(self) -> str: Returns a string that represents the Item’s ID.
set_collide(self, collidable: bool): Set the collision state for the Item to be True.
can_collide(self) -> bool: Returns True if the Item can be collided with and False
otherwise.
on_hit(self, game: GameLogic): This function should raise the NotImplementedError.
Examples
>>> game = GameLogic()
>>> item = Item()
>>> item.can_collide()
True
>>> item.on_hit(game)
Traceback (most recent call last):
File “
item.on_hit(game)
File “/Users/…/a2.py”, line 75, in on_hit
class Item(Entity):
NotImplementedError
>>> str(item)
“Item(‘Entity’)”
>>> repr(item)
“Item(‘Entity’)”
Key
A Key is a special type of Item within the game.
The Key Item can be collided with. Key should be constructed with Key(). Key should have the
following methods defined:
get_id(self) -> str: Returns a string that represents the Key’s ID.
set_collide(self, collidable: bool): Set the collision state for the Key to be True.
can_collide(self) -> bool: Returns True if the Key can be collided with and False
otherwise.
on_hit(self, game: GameLogic) -> None: When the player takes the Key the Key
should be added to the Player’s inventory. The Key should then be removed from the dungeon
once it’s in the Player’s inventory.
(hint: Move onto the Player and GameLogic class and come back to this when they are partly
implemented.)
__str__(self) -> str: Returns the string representation of the Key. See example output
below.
__repr__(self) -> str: Same as str(self).
Examples
>>> key = Key()
>>> key.get_id()
‘K’
>>> key.can_collide()
True
>>> str(key)
“Key(‘K’)”
>>> repr(key)
“Key(‘K’)”
(below are example of the on_hit() method)
>>> game = GameLogic()
>>> game.get_game_information()
{(1, 3): Key(‘K’), (3, 2): Door(‘D’), (0, 0): Wall(‘#’), (0, 1):
Wall(‘#’), (0, 2): Wall(‘#’), (0, 3): Wall(‘#’), (0, 4): Wall(‘#’),
(1, 0): Wall(‘#’), (1, 2): Wall(‘#’), (1, 4): Wall(‘#’), (2, 0):
Wall(‘#’), (2, 4): Wall(‘#’), (3, 0): Wall(‘#’), (3, 4): Wall(‘#’),
(4, 0): Wall(‘#’), (4, 1): Wall(‘#’), (4, 2): Wall(‘#’), (4, 3):
Wall(‘#’), (4, 4): Wall(‘#’)}
>>> player = game.get_player()
>>> player.get_inventory()
[]
>>> player.set_position((1,3))
>>> key.on_hit(game)
>>> player.get_inventory()
[Key(‘K’)]
>>> game.get_game_information()
{(3, 2): Door(‘D’), (0, 0): Wall(‘#’), (0, 1): Wall(‘#’), (0, 2):
Wall(‘#’), (0, 3): Wall(‘#’), (0, 4): Wall(‘#’), (1, 0): Wall(‘#’),
(1, 2): Wall(‘#’), (1, 4): Wall(‘#’), (2, 0): Wall(‘#’), (2, 4):
Wall(‘#’), (3, 0): Wall(‘#’), (3, 4): Wall(‘#’), (4, 0): Wall(‘#’),
(4, 1): Wall(‘#’), (4, 2): Wall(‘#’), (4, 3): Wall(‘#’), (4, 4):
Wall(‘#’)}
MoveIncrease
MoveIncrease is a special type of Item within the game.
The MoveIncrease Item can be collided with. MoveIncrease should be constructed with
MoveIncrease(int: moves=5) where moves describe how many extra moves the Player will be
granted when they collect this Item, the default value should be 5. MoveIncrease should have
the following methods defined:
get_id(self) -> str: Returns a string that represents the MoveIncrease’s ID.
set_collide(self, collidable: bool): Set the collision state for the MoveIncrease
to be True.
can_collide(self) -> bool: Returns True if the MoveIncrease can be collided with and
False otherwise.
on_hit(self, game: GameLogic) -> None: When the player hits the MoveIncrease
(M) item the number of moves for the player increases and the M item is removed from the
game. These actions are implemented via the on_hit method. Specifically, extra moves should
be granted to the Player and the M item should be removed from the game.
(hint: Move onto the Player and GameLogic class and come back to this when they are partly
implemented.)
__str__(self) -> str: Returns the string representation of the MoveIncrease. See
example output below.
__repr__(self) -> str: Same as str(self).
Examples
>>> move_increase = MoveIncrease()
>>> move_increase.get_id()
‘M’
>>> move_increase.can_collide()
True
>>> str(move_increase)
“MoveIncrease(‘M’)”
>>> repr(move_increase)
“MoveIncrease(‘M’)”
(below are example of the on_hit() method)
>>> game = GameLogic()
>>> game.get_game_information()
{(1, 6): Key(‘K’), (6, 3): Door(‘D’), (0, 0): Wall(‘#’), (0, 1):
Wall(‘#’), (0, 2): Wall(‘#’), (0, 3): Wall(‘#’), (0, 4): Wall(‘#’),
(0, 5): Wall(‘#’), (0, 6): Wall(‘#’), (0, 7): Wall(‘#’), (1, 0):
Wall(‘#’), (1, 4): Wall(‘#’), (1, 7): Wall(‘#’), (2, 0): Wall(‘#’),
(2, 7): Wall(‘#’), (3, 0): Wall(‘#’), (3, 7): Wall(‘#’), (4, 0):
Wall(‘#’), (4, 1): Wall(‘#’), (4, 2): Wall(‘#’), (4, 7): Wall(‘#’),
(5, 0): Wall(‘#’), (5, 7): Wall(‘#’), (6, 0): Wall(‘#’), (6, 7):
Wall(‘#’), (7, 0): Wall(‘#’), (7, 1): Wall(‘#’), (7, 2): Wall(‘#’),
(7, 3): Wall(‘#’), (7, 4): Wall(‘#’), (7, 5): Wall(‘#’), (7, 6):
Wall(‘#’), (7, 7): Wall(‘#’), (6, 6): MoveIncrease(‘M’)}
>>> player = game.get_player()
>>> player.set_position((6,6))
>>> player.moves_remaining()
12
>>> move_increase.on_hit(game)
>>> player.moves_remaining()
17
>>> game.get_game_information()
{(1, 6): Key(‘K’), (6, 3): Door(‘D’), (0, 0): Wall(‘#’), (0, 1):
Wall(‘#’), (0, 2): Wall(‘#’), (0, 3): Wall(‘#’), (0, 4): Wall(‘#’),
(0, 5): Wall(‘#’), (0, 6): Wall(‘#’), (0, 7): Wall(‘#’), (1, 0):
Wall(‘#’), (1, 4): Wall(‘#’), (1, 7): Wall(‘#’), (2, 0): Wall(‘#’),
(2, 7): Wall(‘#’), (3, 0): Wall(‘#’), (3, 7): Wall(‘#’), (4, 0):
Wall(‘#’), (4, 1): Wall(‘#’), (4, 2): Wall(‘#’), (4, 7): Wall(‘#’),
(5, 0): Wall(‘#’), (5, 7): Wall(‘#’), (6, 0): Wall(‘#’), (6, 7):
Wall(‘#’), (7, 0): Wall(‘#’), (7, 1): Wall(‘#’), (7, 2): Wall(‘#’),
(7, 3): Wall(‘#’), (7, 4): Wall(‘#’), (7, 5): Wall(‘#’), (7, 6):
Wall(‘#’), (7, 7): Wall(‘#’)}
Door
A Door is a special type of an Entity within the game.
The Door Entity can be collided with (The Player should be able to share its position with the
Door when the Player enters the Door.) Door should be constructed with Door(). Door should
have the following methods defined:
get_id(self) -> str: Returns a string that represents the Door’s ID.
set_collide(self, collidable: bool): Set the collision state for the Door to be True.
can_collide(self) -> bool: Returns True if the Door can be collided with and False
otherwise.
on_hit(self, game: GameLogic) -> None: If the Player’s inventory contains a Key
Entity then this method should set the ‘game over’ state to be True.
(hint: Move onto the Player and GameLogic class and come back to this when they are partly
implemented.)
__str__(self) -> str: Returns the string representation of the Door. See example output
below.
__repr__(self) -> str: Same as str(self).
If the Player’s Inventory does not contain a Key Entity then the following message should be
displayed: “You don’t have the key!”
Examples
>>> door = Door()
>>> door.get_id()
‘D’
>>> door.can_collide()
True
>>> str(door)
“Door(‘D’)”
>>> repr(door)
“Door(‘D’)”
(below are example of the on_hit() method)
>>> key = Key()
>>> game = GameLogic()
>>> game.get_game_information()
{(1, 3): Key(‘K’), (3, 2): Door(‘D’), (0, 0): Wall(‘#’), (0, 1):
Wall(‘#’), (0, 2): Wall(‘#’), (0, 3): Wall(‘#’), (0, 4): Wall(‘#’),
(1, 0): Wall(‘#’), (1, 2): Wall(‘#’), (1, 4): Wall(‘#’), (2, 0):
Wall(‘#’), (2, 4): Wall(‘#’), (3, 0): Wall(‘#’), (3, 4): Wall(‘#’),
(4, 0): Wall(‘#’), (4, 1): Wall(‘#’), (4, 2): Wall(‘#’), (4, 3):
Wall(‘#’), (4, 4): Wall(‘#’)}
>>> player = game.get_player()
>>> game.won()
False
>>> player.set_position((3,2))
>>> door.on_hit(game)
You don’t have the key!
>>> player.get_inventory()
[]
>>> player.set_position((1,3))
>>> key = Key()
>>> key.on_hit(game)
>>> player.get_inventory()
[Key(‘K’)]
>>> player.set_position((3,2))
>>> door.on_hit(game)
>>> game.won()
True
Player
A Player is a special type of an Entity within the game.
The Player Entity can be collided with. The Player should be constructed with
Player(move_count: int) where moves represents how many moves a Player can have for the
given dungeon they are in (see GAME_LEVELS).
Player should have the following methods defined:
get_id(self) -> str: Returns a string that represents the Player’s ID.
set_collide(self, collidable: bool): Set the collision state for the Player to be
True.
can_collide(self) -> bool: Returns True if the Player can be collided with and False
otherwise.
set_position(self, position: tuple
get_position(self) -> tuple
position of the Player. If the Player’s position hasn’t been set yet then this method should return
None.
change_move_count(self, number: int): number to be added to the Player’s move
count.
moves_remaining(self) -> int: Returns an int representing how many moves the
Player has left before they reach the maximum move count.
add_item(self, item: Entity): Adds the item to the Player’s Inventory.
get_inventory (self) -> list
inventory. If the Player has nothing in their inventory then an empty list should be returned.
__str__(self) -> str: Returns the string representation of the Player. See example
output below.
__repr__(self) -> str: Same as str(self).
Examples
>>> player = Player(5)
>>> print(player.get_position())
None
>>> player.set_position((1,2))
>>> player.get_position()
(1, 2)
>>> player.moves_remaining()
5
>>> player.change_move_count(2)
>>> player.moves_remaining()
7
>>> player.get_inventory()
[]
>>> key = Key()
>>> player.add_item(key)
>>> player.get_inventory()
[Key(‘K’)]
>>> str(player)
“Player(‘O’)”
>>> repr(player)
“Player(‘O’)”
(Hint: you might want to specify some attributes for this class including: move_count, inventory and
position. You can create and initialise the values to be None if you wish.)
GameLogic
GameLogic contains all the game information and how the game should play out. By default,
GameLogic should be constructed with GameLogic(dungeon_name=”game1.txt”).
GameLogic should have the following methods defined:
get_dungeon_size(self) -> int: Returns the width of the dungeon as an integer.
init_game_information(self) -> dict
method should return a dictionary containing the position and the corresponding Entity as the
keys and values respectively. This method also sets the Player’s position. At the start of the
game this method should be called to find the position of all entities within the current dungeon.
get_game_information(self) -> dict
dictionary containing the position and the corresponding Entity, as the keys and values, for the
current dungeon.
get_player(self) -> Player: This method returns the Player object within the game.
(hint: you should now be able to finish off all the Entity classes/subclasses.)
get_entity(self, position: tuple
given position in the dungeon. Entity in the given direction or if the position is off map then this
function should return None.
get_entity_in_direction(self, direction: str) -> Entity: Returns an Entity
in the given direction of the Player’s position. If there is no Entity in the given direction or if the
direction is off map then this function should return None.
collision_check(self, direction: str) -> bool: Returns False if a player can
travel in the given direction, they won’t collide. True, they will collide, otherwise
new_position(self, direction: str) -> tuple
integers that represents the new position given the direction.
move_player(self, direction: str) -> None: Update the Player’s position to place
them one position in the given direction.
check_game_over(self) -> bool: Return True if the game has been lost and True
otherwise. (Hint: think about how the player can lose the game)
set_win(self, win: bool) -> None: Set the game’s win state to be True or False.
won(self) -> bool: Return game’s win state.
See example outputs below.
Note that the type hints (eg. select: bool) shown in the methods above are purely for your own
understanding. Type hints do not need to be used in your assignment.
Examples
>>> game = GameLogic()
>>> game.get_positions(PLAYER)
[(2, 1)]
>>> game.get_positions(WALL)
[(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 0), (1, 2), (1, 4), (2,
0), (2, 4), (3, 0), (3, 4), (4, 0), (4, 1), (4, 2), (4, 3), (4, 4)]
>>> game.init_game_information()
{(1, 3): Key(‘K’), (3, 2): Door(‘D’), (0, 0): Wall(‘#’), (0, 1):
Wall(‘#’), (0, 2): Wall(‘#’), (0, 3): Wall(‘#’), (0, 4): Wall(‘#’),
(1, 0): Wall(‘#’), (1, 2): Wall(‘#’), (1, 4): Wall(‘#’), (2, 0):
Wall(‘#’), (2, 4): Wall(‘#’), (3, 0): Wall(‘#’), (3, 4): Wall(‘#’),
(4, 0): Wall(‘#’), (4, 1): Wall(‘#’), (4, 2): Wall(‘#’), (4, 3):
Wall(‘#’), (4, 4): Wall(‘#’)}
>>> game.get_player()
Player(‘O’)
>>> game.get_positions(KEY)
[(1, 3)]
>>> game.get_entity((2,1))
>>> game.get_entity((1,3))
Key(‘K’)
>>> game.get_entity_in_direction(“W”)
>>> game.get_entity_in_direction(“D”)
>>> game.get_entity_in_direction(“A”)
Wall(‘#’)
>>> game.get_game_information()
{(1, 3): Key(‘K’), (3, 2): Door(‘D’), (0, 0): Wall(‘#’), (0, 1):
Wall(‘#’), (0, 2): Wall(‘#’), (0, 3): Wall(‘#’), (0, 4): Wall(‘#’),
(1, 0): Wall(‘#’), (1, 2): Wall(‘#’), (1, 4): Wall(‘#’), (2, 0):
Wall(‘#’), (2, 4): Wall(‘#’), (3, 0): Wall(‘#’), (3, 4): Wall(‘#’),
(4, 0): Wall(‘#’), (4, 1): Wall(‘#’), (4, 2): Wall(‘#’), (4, 3):
Wall(‘#’), (4, 4): Wall(‘#’)}
>>> game.get_dungeon_size()
5
>>> game.get_player().get_position()
(2, 1)
>>> game.move_player(“W”)
>>> game.get_player().get_position()
(1, 1)
>>> game.collision_check(“W”)
True
>>> game.collision_check(“S”)
False
>>> game.new_position(“W”)
(0, 1)
>>> game.new_position(“S”)
(2, 1)
>>> game.check_game_over()
False
>>> game.won()
False
>>> game.set_win(True)
>>> game.won()
True
GameApp
GameApp acts as a communicator between the GameLogic and the Display. GameApp should
be constructed with GameApp(). GameApp should have the following methods defined:
play(self) -> None: Handles the player interaction.
(Hint: this is similar to the main function in a1)
entity_in_direction(self, direction) -> Entity: Returns the Entity in a given
direction.
draw(self) -> None: Displays the dungeon with all Entities in their positions. This method
should also display the player’s remaining move count.
(hint: Look at a2_support.py)
See example outputs below.
Note that the type hints (eg. select: bool) shown in the methods above are purely for your own
understanding. Type hints do not need to be used in your assignment.
Examples 1
#####
# #K#
#O #
# D #
#####
Moves left: 7
Please input an action: H
Here is a list of valid actions: [‘I’, ‘Q’, ‘H’, ‘W’, ‘S’, ‘D’, ‘A’]
#####
# #K#
#O #
# D #
#####
Moves left: 7
Please input an action: D
#####
# #K#
# O #
# D #
#####
Moves left: 6
Please input an action: D
#####
# #K#
# O#
# D #
#####
Moves left: 5
Please input an action: I D
Wall(‘#’) is on the D side.
#####
# #K#
# O#
# D #
#####
Moves left: 4
Please input an action: W
#####
# #O#
# #
# D #
#####
Moves left: 3
Please input an action: S
#####
# # #
# O#
# D #
#####
Moves left: 2
Please input an action: S
#####
# # #
# #
# DO#
#####
Moves left: 1
Please input an action: A
You have won the game with your strength and honour!
Examples 2
#####
# #K#
#O #
# D #
#####
Moves left: 7
Please input an action: D
#####
# #K#
# O #
# D #
#####
Moves left: 6
Please input an action: W
That’s invalid.
#####
# #K#
# O #
# D #
#####
Moves left: 5
Please input an action: S
You don’t have the key!
#####
# #K#
# #
# D #
#####
Moves left: 4
Please input an action: D
#####
# #K#
# #
# DO#
#####
Moves left: 3
Please input an action: W
#####
# #K#
# O#
# D #
#####
Moves left: 2
Please input an action: W
#####
# #O#
# #
# D #
#####
Moves left: 1
Please input an action: S
You have lost all your strength and honour.
Example 3
########
# # K#
#O #
# #
### #
# #
# D M#
########
Moves left: 12
Please input an action: D
########
# # K#
# O #
# #
### #
# #
# D M#
########
Moves left: 11
Please input an action: D
########
# # K#
# O #
# #
### #
# #
# D M#
########
Moves left: 10
Please input an action: D
########
# # K#
# O #
# #
### #
# #
# D M#
########
Moves left: 9
Please input an action: D
########
# # K#
# O #
# #
### #
# #
# D M#
########
Moves left: 8
Please input an action: D
########
# # K#
# O#
# #
### #
# #
# D M#
########
Moves left: 7
Please input an action: W
########
# # O#
# #
# #
### #
# #
# D M#
########
Moves left: 6
Please input an action: S
########
# # #
# O#
# #
### #
# #
# D M#
########
Moves left: 5
Please input an action: S
########
# # #
# #
# O#
### #
# #
# D M#
########
Moves left: 4
Please input an action: S
########
# # #
# #
# #
### O#
# #
# D M#
########
Moves left: 3
Please input an action: S
########
# # #
# #
# #
### #
# O#
# D M#
########
Moves left: 2
Please input an action: S
########
# # #
# #
# #
### #
# #
# D O#
########
Moves left: 6
Please input an action: A
########
# # #
# #
# #
### #
# #
# D O #
########
Moves left: 5
Please input an action: A
########
# # #
# #
# #
### #
# #
# DO #
########
Moves left: 4
Please input an action: A
You have won the game with your strength and honour!
Example 4
#####
# #K#
#O #
# D #
#####
Moves left: 7
Please input an action: d
That’s invalid.
#####
# #K#
#O #
# D #
#####
Moves left: 7
Please input an action: I M
That’s invalid.
#####
# #K#
#O #
# D #
#####
Moves left: 7
Please input an action: Q
Are you sure you want to quit? (y/n): n
#####
# #K#
#O #
# D #
#####
Moves left: 7
Please input an action: Q
Are you sure you want to quit? (y/n): y
Marking
Item Marks
Entity (including Wall and Door) 1
Item (including Key and MoveIncrease) 1.5
Player 2.5
GameLogic 3
GameApp 3
Functionality Assessment
The functionality will be marked out of 11. Your assignment will be put through a series of tests
and your functionality mark in any given item category will be proportional to the number of tests
you pass. You will be given the majority (but not all) of the functionality tests before the due date
for the assignment so that you can gain a good idea of the correctness of your assignment
yourself before submitting. You should make sure that your program meets all the specifications
given in the assignment. That will ensure that your code passes all the tests. Note: Functionality
tests are automated, therefore, string outputs need to exactly match what is expected.
Code Style
The style of your assignment will be assessed by one of the tutors, and you will be marked
according to the style rubric provided with the assignment. The style mark will be out of 4.
Assignment Submission
Your assignment must be submitted via the Assignment 2 submission link on Blackboard. You
must submit a Python file containing your implementation of the assignment. Late submission of
the assignment will not be accepted. Do not wait until the last minute to submit your assignment,
as the time to upload it may make it late. Multiple submissions are allowed, so ensure that you
have submitted an almost complete version of the assignment well before the submission
deadline. Your latest on-time, submission will be marked. Ensure that you submit the correct
version of your assignment. In the event of exceptional circumstances, you may submit a
request for an extension. See the course profile for details of how to apply for an extension.
Requests for extensions must be made no later than 48 hours prior to the submission deadline.
The expectation is that with less than 48 hours before an assignment is due it should be
substantially completed and a2.py submittable. Applications for extension, and any supporting
documentation (e.g. medical certificate), must be submitted via my.UQ. You must retain the
original documentation for a minimum period of six months to provide as verification should you
be requested to do so.
Change log
Wall class description:
>>> wall.set_collide(True)
>>> wall.can_collide()
>>> enitty.can_collide()
>>> entity.set_collide(True)
>>> enitty.can_collide()
The collision_check() method was described twice so the duplicate was deleted. This method still needs
to be implemented. And updated description.
Please input an action: I D
Wall(‘#’) is on the D side.
Please input an action: I E
Wall(‘#’) is on the E side.
set_win(self, win: bool) -> None: Set the game’s win state to be True or False.
and
won(self) -> bool: Return game’s win state.
check_game_over(self) -> bool: Return True if the game has been lost and True
otherwise.
MoveIncrease type hint order was incorrect. Should be MoveIncrease(int: moves=5)
The game’s grid should always be a square.
More game play examples (Example 4)
GameApp.draw()’s description. This method should also display the player’s remaining move
count.
The player loses a move count when they:
– Successfully moving to a new position.
– Unsuccessfully moving to a new position. E.g. The new position is a Wall.
– Investigating an Entity in a given direction
As seen in the Example game play
GameApp.entity_in_direction(self, direction) is removed!



