程序代写代做代考 go data structure crawler Java html c++ compiler game Table of contents

Table of contents
1. Introduction
1.1. Learning Outcomes
2. Task Description
2.1. Work Plan
2.2. Design Patterns
2.3. Class Diagram
2.4. Code Structure and Namespaces 2.5. MenuInterface
2.6. Game
2.7. Dungeon (Rooms, Walls, Doors)
2.8. Building a Dungeon Level
2.9. Example Dungeon Level
2.10. Items & Creatures
2.11. Viewing a Dungeon Level
2.12. Generating a Dungeon Level Randomly
3. Documentation
4. Code Style
5. Version Control
6. Implementation Rules and Hints 7. Submission Details
8. Academic Misconduct
/

1. Introduction
Added 13 Sep 2020:
Incorporated the clarifications that have been made through the forums into the specification, so that they are easy to see when reviewing your own work prior to submission. Sections updated include: Class Diagram, Game, Dungeon (Rooms, Walls, Doors).
Added 5 Sep 2020:
Clarification of the use of streams for the MenuInterface in the ‘MenuInterface’ section.
Added 4 Sep 2020:
Clarification of the ‘isPassage’ function for RoomeEdges, in the ‘Dungeon (Rooms, Walls, Doors)’ section.
Added 3 Sep 2020:
Link to an the Wikipedia article on (bit)Masks added to the ‘Building a Dungeon Level’ section.
Added 28 Aug 2020:
Clarifications about the generation, version control, and submission of the HTML documentation from doxygen. Sections affected: ‘Documentation’, ‘Version Control’, and ‘Submission Details’
Changed 27 Aug 2020:
Made the display of Wall edges of Rooms more explicit. It was quite implicit previously. Added some explanation to the use of enumerations in the section ‘Dungeon (Rooms, Walls, Doors)’
(I’ve cleaned up the changes from between the initial release to the completed version.)
This document specifies the requirements for the first assignment of the Software Development with C++ course, SP5 2020. This assignment will develop your skills by allowing you to put into practice what has been taught in class during the first 5 weeks of the course.
The assignment will require you to implement, test, and debug an application using object-oriented methods and the application of appropriate design patterns. In addition, you must use version control to keep track of your implementation as you progress through the assignment and you must use Doxygen to document your classes with appropriate comments and generate the HTML documentation. The work in this assignment is to be performed individually and will be submitted via LearnOnline in two parts:
1. Implementation: the C++ implementation will be due at the end of Week 8—due by 20 September 2020 11:59 PM.
2. Self-reflection 1: before you work has been marked, you will need to briefly indicate how you feel you went with the assignment and any challenges you had, which will be due at the end of the mid- semester break—due by 4 October 2020 11:59 PM.
3. Self-reflection 2: after your work has been marked, you will be asked to briefly reflect on whether the result you received matches what your expectations were, which will be due at the end of Week 9— due by 11 October 2020 11:59 PM.
Refer to section Submission Details for specific instructions on submitting your source code. Be sure to follow them closely.
/

If any parts of this specification appear unclear, please ensure you seek clarification: the earlier the better.
/

1.1. Learning Outcomes
After completing this assignment, you will have learnt to:
Apply Object-Oriented principles (encapsulation, reuse, etc.) and Design Patterns as demonstrated in a provided software design
Implement the software design in C++ using class inheritance and polymorphism features
Write well-behaved constructors and destructors for C++ classes
Use C++ pointers (including smart pointers) and dynamic memory allocation and management Use stream I/O and manipulators for formatted input and output
Write code adhering to coding standards, guidelines and good programming practices
/

2. Task Description
Roguelike Dungeon Crawler games are a genre of game that exhibit features typically attributed to the 1980s computer game Rogue [https://en.wikipedia.org/wiki/Rogue_(video_game)]. In general, the goal of a Roguelike game is to clear a dungeon, level-by-level, until the final level is completed. Common features of a Roguelike game include:
procedurally generated dungeons,
randomised items and weapons,
permanent death, and
a variety of creatures to fight that get progressively more difficult deeper into the dungeon.
Within each level of a dungeon there typically exists distinct rooms where monsters are encountered and items are waiting to be looted.
In this assignment, you will implement the beginnings of a simple text-based Roguelike Dungeon Crawler game that fulfils the following specification. You will not be required to implement the gameplay itself, but only the construction of dungeon levels. Each dungeon level will comprise a set of rooms, connected by doors, with the possibility of a random monster and/or loot items (weapons or consumables such as potions); the items and monsters will not be completely game capable, but rather placeholders that to be implemented in detail later to give the game its functionality (not part of this assignment). A text-based menu will allow the user to generate dungeon levels with a small set of parameters and display them to the console.
The aim of the assignment is to allow you to practise creating an object-oriented design and implementing it in C++ using the features learnt so far, namely: class inheritance 􏰀 and polymorphism, dynamic memory allocation, and smart pointers. The focus of the assignment is on using appropriate Design Patterns and learning how objects fit together to realise complex data structures and behaviour. While the main design has been done for you, you will be responsible for the internal implementation details for which you must still consider the Good Object-Oriented Principles (or Clean Code principles) discussed in the Week 3 Workshop Object-Oriented Thinking (refer to the Week 3 Workshop Completed Example 􏰀 and Object-Oriented Thinking Video 􏰀).
You will need to implement the game in C++ based on the UML Class diagram and the requirements in the remainder of this specification. The provided UML Class Diagram will illustrate the public interfaces of the required classes; you will need to provide the detail in your implementation but you are not required to update the diagram with those details—of course, if it helps you to visualise what you are doing you may.
For this assignment you will need to interact with the dungeon level creation through the command line. A brief example of the menu interaction is provided below. Further examples will be provided in the relevant sections of the specification. For additional examples, or clarifications on specific behaviour, please run through the Dungeon Builder Reference Implementation (to be released) provided. The text descriptions of your implementation do not have to exactly match the reference implementation, but you may use it as a guide to see how the user interaction works.
You will not be provided with any skeleton code. You must create the Qt Creator Project and the classes from scratch. Make sure the project is configured for C++17 and that you scope the classes within the specified namespaces as described in the requirements.
/

/
The following conventions are used when illustrating example output:
a ‘>’ at the beginning of a line indicates the command line prompt
indicates input entered by the user (you do not need to make it appear as orange when running the application)
user input surrounded by square brackets ‘[…]’ indicates a specific key press hitting after other input is implied
bold orange text
[En
ter
]

> dungeon_builder.exe
Welcome to: So you built your first dungeon? Well then, build another!
Developed by Matt Selway
COMP 3023 Software Development with C++
*Press Enter to continue*
> [Enter]
What would you like to do?
(g)enerate the example level
(r)andom dungeon level
(q)uit
>g
Creating Example Dungeon Level…
Dungeon level created!
What would you like to do?
(d)escribe the dungeon level
(v)iew the dungeon level
(r)eturn to the main menu
>d
Example Dungeon Level
Size: 3 x 3
Type: Dark Cave (Basic Dungeon)
What would you like to do?
(d)escribe a room
(r)eturn to previous menu
>d
Which room would you like to describe? (1-9) >1
Room *1* is…
A dark and empty chamber. (Rock Chamber)
To the NORTH is the entrance to the dungeon level.
To the SOUTH is an Open Doorway to another chamber.
To the EAST is an Open Doorway to another chamber.
To the WEST is a Rock Wall.
*Press Enter to continue*
> [Enter]
What would you like to do?
(d)escribe a room
(r)eturn to previous menu
>d
Which room would you like to describe? (1-9) >5
Room *5* is…
A chamber that glitters like a thousand stars in the torchlight. (Quartz Chamber)
/

To the NORTH is an Open Doorway to another chamber.
To the SOUTH is an Open Doorway to another chamber.
To the EAST is an Open Doorway to another chamber.
To the WEST is a One-Way Door from another chamber.
There is a Goblin to fight.
There is a Short Sword to pick up.
*Press Enter to continue*
> [Enter]
What would you like to do?
(d)escribe a room
(r)eturn to previous menu
>r
What would you like to do?
(d)escribe the dungeon level
(v)iew the dungeon level
(r)eturn to the main menu
>v
Example Dungeon Level
+—-I—-+ +———+ +———+ |||||| | >–< X--X ML | |||||| +----v----+ +----v----+ +----v----+ ||| +----v----+ +----^----+ +----@----+ |||||| | >–> ML >–< | |||||| +----X----+ +----v----+ +---------+ || +----X----+ +----^----+ +---------+ |||||| | L @--@ >—< M* O |||||| +---------+ +---------+ +---------+ *Press Enter to continue* > [Enter]
What would you like to do?
(d)escribe the dungeon level
(v)iew the dungeon level
(r)eturn to the main menu
>r
What would you like to do?
(g)enerate the example level
(r)andom dungeon level
/

The description that follows is the detailed requirements necessary to perform your implementation of the Dungeon Builder.
/
(q)uit >q
*Are you sure you want to quit? (y/n) * >y
Goodbye!

2.1. Work Plan
Important: All classes and functionality that relate only to the Magical Dungeon type are optional, including the builder class, rooms, walls, items, etc. They are not required to complete this assignment. Some bonus marks are assigned if the Magical Dungeon type and its components are implemented. See section Building a Dungeon Level for the table of classes and to which dungeon type they relate.
To complete the second part of this assignment, you will need to perform the following steps:
1. Read the assignment specification carefully.
2. Read the Implementation Rules and Hints Section again.
3. Create a new Qt Creator project, do not forget to initialise a Git repository within the project folder.
4. Implement the initial menu interface with placeholders ready to hook in the functionality—refer to
section Menu.
5. Implement the interfaces and abstract classes for the dungeon components (e.g., DungeonLevel,
Room, Wall, Doorway)—refer to section Dungeon (Rooms, Walls, and Doors).
6. Implement the interfaces and abstract classes for the Builder Pattern 􏰀—refer to section The
Dungeon Builder.
7. Implement (some of) the basic dungeon classes, including their creation according to the example
layout: walls and OpenDoorways only, no special door types, no creatures nor items—refer to section Dungeon (Rooms, Walls, Doors) for component structure and sections Building a Dungeon Level and Example Dungeon Level for their construction.
Do not worry about full dungeon ‘viewing’ at the moment. But you will want to implement the dungeon ‘description’ so that you can see what is being constructed.
You can also insert output statements during construction to ensure that things are working as
expected, just remember to remove them later.
8. Add the additional Doorway types and update the construction of the example layout to use them.
9. Add items and creatures using the Prototype Pattern 􏰀—refer to section Item & Creatures.
Remember: These are just non-functional elements of the dungeons for this assignment.
10. Update the example level generation to include the creatures and items.
11. Implement the dungeon level display to the console—refer to section Viewing a Dungeon Level.
12. Implement the random dungeon level generation—refer to section Generating a Dungeon Level
Randomly.
13. (Optional) Implement the second dungeon type: Magical Dungeon, all of its components, and its
builder—refer to section Dungeon (Rooms, Walls, Doors) .
14. Generate Doxygen-based HTML documentation.
15. Submit your assignment.
After completing the implementation (or even earlier) be sure to generate your HTML documentation from your Doxygen comments included in your project files. You will then need to gather your entire project, including the git repository, and submit it to LearnOnline. See section Submission Details for the full requirements of submission.
Important: As you implement the functionality you should tick, highlight, or otherwise mark the requirements that you have completed. This will help you keep track of your progress and ensure you have addressed all of the requirements in your submission. If you are unsure of a requirement, ask and/or use the reference implementation for guidance.
/

/
Note: The above sequence of tasks is a suggestion that will lead you through a logical progression of incremental functionality until you have a completed application. It is highly recommended that you follow the suggestion to maximise your marks, as marking is allocated based on functional completeness. For example, completing all of the structural elements for all classes (i.e., data members and constructors) without any generation functionality will receive fewer marks than having some generation functionality that only incorporates the minimal structural implementation necessary to achieve that functionality.

2.2. Design Patterns
There are 3 Design Patterns incorporated in the design of the Dungeon Builder:
Singleton (simple version) Builder
Prototype
The main focus of the assignment is the Builder Pattern 􏰀; however, it also illustrates multiple patterns working together as, generally, no Design Pattern is used in complete isolation.
All of the relevant Design Patterns are listed under Week 4, including readings and LinkedIn Learning videos. The main source for the Design Patters is the book:
Gamma, E, Helm, R, Johnson, R and Vlissides, J 1995, Design patterns : elements of reusable object- oriented software, Addison-Wesley, Boston, Massachussets.
For convenience, links to the readings and LinkedIn Learning videos are provided below:
Singleton
Note: the online resources below do not properly discuss the extensible Singleton. That is fine for the moment as we are only using the simple version. Just be aware that the simple Singleton has issues with extensibility and testability.
Singleton Pattern 􏰀
Singleton Pattern (Alternative Description) 􏰀 Singleton Pattern Video 􏰀
Builder
Builder Pattern 􏰀 Builder Pattern Video 􏰀
There is also a recording of an ad-hoc example I created in 2018. Just be careful to ignore any discussion of the assignment as it is not relevant for this one: Parsing with the Builder Pattern Example 􏰀.
Prototype
Prototype Pattern 􏰀
Prototype Pattern (Alternative Description) 􏰀 Prototype Pattern Video 􏰀
Be aware that the C++ examples from the book are for an older version of C++. If using them for guidance, they must be updated to C++ 17.
/

2.3. Class Diagram
The Design is shown below and can be downloaded as a UMLet file: Dungeon Builder Design Diagram 􏰀. UMLet [http://umlet.com/] is a simple and free UML editor that can be used for this assignment.
When translating the design into code, you will need to consider when the data members and function parameters need to be normal variables, references, or pointers (including appropriate smart pointers); in particular, you will need to consider what type of pointer or smart pointer is appropriate to implement each association in the class diagram. There are 2 exceptions: (1) you MUST use bare pointers for the ‘opposite’ association between 2 doorways; and you MUST use bare pointers, the ‘new’, and ‘delete’ operators for the associations in the builder and the classes. You may decide the most appropriate pointer type for the other associations. A key thing to consider when making these decisions is that of ‘ownership’: i.e., who is it that owns the pointer and is responsible for ensuring its deallocation when it is no longer needed.
You will also need to consider whether the different elements should be or not, including member functions. Moreover, the diagram only shows the public interface of the classes: your implementation will need to add private/protected data members and member functions. Remember the Object-Oriented Principles to create good internal structures and adhere to the public interface, e.g., keep your functions small (do one thing only), use delegation (talk to your neighbours), etc. Make sure your implementation maintains separation of concerns and does not start to make a class take on more responsibilities than it is supposed to (Single Responsibility Principle). Also remember the Don’t Repeat Yourself (a.k.a. DRY) principle. This applies to data members in class hierarchies (e.g., a data member should only appear once in the hierarchy) as well as to the duplication of functions.
You MAY add public methods if you feel they are necessary for your implementation (there are some that are necessary); however, be careful you are not revealing internal state that should not need to be revealed (Information Hiding).
All classes MUST have appropriate constructors and destructors, even if they are only the default implementations. Take particular care of destructors when dealing with polymorphic classes, i.e., those classes with functions, and those classes that use pointers (particularly bare pointers).
All objects that can be described MUST overload the output stream operator << . This will facilitate the display of objects by the class. DungeonLevel Game const virtual MenuInterface / «concrete prototype» Weapon + clone() {override} MenuInterface + MenuInterface(display : std::ostream, input : std::istream) + displayWelcome(author : std::string, title : std::string) + run() «enum, unsigned» DungeonLevelBuilder:: MoveConstraints None = 0 OriginImpassable = 1 DestinationImpassable = 2 OriginLocked = 4 DestinationLocked = 8 «prototype» Item + Item(name : std::string) + clone() : Item + name() : std::string + displayCharacter() : char «concrete prototype» Consumable + clone() {override} «singleton» «director, Builder» Game - theInstance : Game + instance() : Game - Game() + setDungeonType(DungeonLevelBuilder) + createExampleLevel() + createRandomLevel(name : std::string, width : int, height : int) + displayLevel(display : std::ostream) + randomDouble() : double Delete the following: + Game(other : Game) + operator= (other: Game) builder 1 return theInstance; * prototypeItems «builder» «client, Prototype» DungeonLevelBuilder {The build functions should have default implementations that do nothing. Hence the member functions are not abstract, but the class still is.} + buildDungeonLevel(name : std::string, width : int, height: int) + buildRoom(id : int) : Room + buildDoorway(origin : Room, destination : Room, direction : Direction, constraints : MoveConstraints) + buildEntrance(room : Room, direction : Direction + buildExit(room : Room, direction : Direction + buildItem(Room) + buildCreature(Room) + getDungeonLevel() : DungeonLevel These are very simple placeholders in this assignment. They implement the Prototype pattern and a have name, that is it. Additional functionality would be added later if the game were to be implemented in full. «prototype» AbstractCreature + AbstractCreature(name : std::string) + clone() : AbstractCreature + name() : std::string + displayCharacter() : char «concrete prototype» Monster + clone() {override} In contrast to the standard pattern description, getDungeonLevel() can be on the abstract builder. prototypeCreatures * return deep copy of self «concrete builder» 0..1 MagicalDungeonLevelBuilder level + buildDungeonLevel(...) {override} + buildRoom(...) {override} + buildDoorway(...) {override} + buildEntrance(...) {override} + buildExit(...) {override{ + buildItem(...) {override} + buildCreature(...) {override} Be sure to use appropriate C++11 containers, e.g., std::array, std::vector, std::map, rather than plain C-arrays. «product» BasicDungeonLevel + BasicDungeonLevel(...) + description() {override} 0..1 level «concrete builder» BasicDungeonLevelBuilder + buildDungeonLevel(...) {override} + buildRoom(...) {override} + buildDoorway(...) {override} + buildEntrance(...) {override} + buildExit(...) {override{ + buildItem(...) {override} + buildCreature(...) {override} «product» MagicalDungeonLevel + MagicalDungeonLevel(...) + description() {override} DungeonLevel + DungeonLevel( name : std::string, width : int, height : int ) + addRoom(Room) : boolean + retrieveRoom(int) : Room + width() : int + height() : int + numberOfRooms : int + name() : std::string + description() : std::string + display() : std::string[*] level 0..1 Override 'description' or otherwise support a different description for each type of Room. There are a couple of ways to do it, which do you prefer? Add member functions for setting the RoomEdge depending on what is most appropriate for your implementation. For example, setEdge(Direction, RoomEdge) or setNorth(RoomEdge). edges 4 You will need to determine how to get the necessary information to Doorways and Walls, to ensure they display the correct character and have the correct description. In particular, OneWayDoor. The classes derived from RoomEdge will need to override the abstract member functions at an appropriate level. They have been omitted from the derived classes in this diagram for brevity. opposite 0..1 rooms * RockWall {specific to basic dungeons} ... RockChamber {specific to basic dungeons} ... Room + Room(id : int) + description() : std::string + display() : std::string[*] + id() : int + item() : Item + setItem(newItem : Item) + creature() : AbstractCreature + setCreature( newCreature : AbstractCreature) «enum, unsigned» Direction North South East West Wall ... MagicWall {specific to magical dungeons} ... QuartzChamber {specific to basic dungeons} ... RoomEdge + description() : std::string + displayCharacter() : char + isPassage() : bool EnchantedLibrary {specific to magical dungeons} ... Doorway ... + connect(opposite : Doorway) + isEntrance() : bool + isExit() : bool AlchemistsLaboratory {specific to magical dungeons} ... OneWayDoor ... OpenDoorway ... BlockedDoorway ... LockedDoor ... / 2.4. Code Structure and Namespaces When you create you classes, you MUST structure them according to the following namespaces. When using your classes elsewhere in your code, do not forget to use the correct scope. Remember that the file/folder structure does not impact your namespaces. You may place all of the files for your code in the root folder of your project, but you must ensure that you have appropriate namespace declarations within your files. If you like, you may create a folder structure that mirrors the namespace structure, but you must ensure that you have appropriate namespace declarations within your files. core dungeon basic common magical creatures items core core::creatures Game MenuInterface core::dungeon AbstractCreature Monster core::dungeon::common core::items Consumeable Item Weapon Doorway DungeonLevel DungeonLevelBuilder Room RoomEdge Wall core::dungeon::basic BlockedDoorway LockedDoor OneWayDoor OpenDoorway BasicDungeonLevel BasicDungeonLevelBuilder RockChamber QuartzChamber RockWall core::dungeon::magical AlchemistsLaboratory EnchantedLibrary MagicalDungeonLevel MagicalDungeonLevelBuilder MagicWall / 2.5. MenuInterface User interaction with the application will be performed through the class. This class has the sole responsibility of commandline IO in the application, i.e., it handles the display of the menu options, processes the inputs from the user, and handles menu navigation but MUST NOT perform any application logic itself (e.g., creation of the example dungeon level). The main collaboration of the class is with the of the class and most of the functionality will be realised by delegating to the member functions Singleton. Game Game The MUST be passed to the constructor. MUST NOT refer to cin/cout directly: instead references to the input and output streams All user inputs MUST be validated. If an invalid input is given, a warning MUST be displayed to the user MenuInterface MenuInterface and the current menu options redisplayed. The function of the application will need to instantiate a object, execute the function, which outputs the header similar to that shown below, and then executes the function, which will enter the event-loop for the menu interactions. The basic event loop is: 1. display the current menu options, 2. wait for user input, 3. process user input (validate and take action), 4. repeat. There are 3 menus in the application: 1. Main Menu—allows you to generate a dungeon level or quit the application 2. Dungeon Describe/View Menu—allows you to choose whether to describe or view the dungeon level 3. Dungeon Exploration Menu—allows you to select specific rooms in the dungeon level to be described. There are also some additional prompts that will occur when some of the menu items are selected, such as prompting for the name of the dungeon when generating a random dungeon level. The following diagram illustrates the flow of the menus and prompts for the execution of the application: reading from input is implied. MenuInterface MenuInterface main() MenuInterface displayWelcome(...) run() Welcome to:
Developed by
COMP 3023 Software Development with C++
/

Display Main Menu
[‘g’]
Generate Example Level
Heh
Generate Random Level
Display Describe/View Menu
[‘q’] Confirm?
[‘n’]
[‘r’]
[‘y’]
[‘r’]
Display Main Menu
Display Describe/View Menu
[‘v’] Display Level
[‘d’] Describe Level
Display Exploration Menu
[‘r’]
[valid room number] Describe Room
Display Exploration Menu
Below are some simple examples of the menu interactions. More detail can be found in related sections., e.g., for the random level generation.
Main Menu
/

Dungeon Describe/View Menu
/
What would you like to do?
(g)enerate the example level
(r)andom dungeon level
(q)uit
>g
Creating Example Dungeon Level…
Dungeon level created!
[output omitted]
What would you like to do?
(g)enerate the example level
(r)andom dungeon level
(q)uit
>r
What would you like to call the level?
> Small dark cave
How many rows in *Small dark cave*? >2
How many columns in *Small dark cave*? >2
What type of dungeon level is it? (b)asic or (m)agical >b
Creating Small dark cave…
Dungeon level created!
[output omitted]
What would you like to do?
(g)enerate the example level
(r)andom dungeon level
(q)uit
>q
*Are you sure you want to quit? (y/n) * >y
Goodbye!

Dungeon Exploration Menu
/
What would you like to do?
(d)escribe the dungeon level
(v)iew the dungeon level
(r)eturn to the main menu
>d
Small dark cave
Size: 2 x 2
Type: Dark Cave (Basic Dungeon)
[output omitted]
What would you like to do?
(d)escribe the dungeon level
(v)iew the dungeon level
(r)eturn to the main menu
>v
Small dark cave +—-I—-+ +———+ |||| | >–< | |||| +----v----+ +----v----+ || +----v----+ +----^----+ |||| | >–> M*L | |||| +———+ +—-O—-+
*Press Enter to continue*
> [Enter]
What would you like to do?
(d)escribe the dungeon level
(v)iew the dungeon level
(r)eturn to the main menu
>r
Returning to main menu. [output omitted]

While the descriptions of menu items do not have to exactly match the samples provided, the keys typed to select a particular action must conform to the table below for consistency across implementations. Note that it should not matter if the typed character is uppercase or lowercase. If in doubt, refer to the reference implementation and follow its example.
Command
Character
Command
Character
Command
Character
Main Menu
Describe/View Menu
Exploration Menu
Generate Example Level
g
Describe the Dungeon Level
d
Describe a Room
d
Random Dungeon Level
r
View the Dungeon Level
v
Return to Previous Menu
r
Quit
q
Return to main menu
r
/
What would you like to do?
(d)escribe a room
(r)eturn to previous menu
>d
Which room would you like to describe? (1-4)
>1
Room *1* is…
A dark and empty chamber. (Rock Chamber)
To the NORTH is the entrance to the dungeon level.
To the SOUTH is an Open Doorway to another chamber.
To the EAST is an Open Doorway to another chamber.
To the WEST is a Rock Wall.
*Press Enter to continue*
> [Enter]
What would you like to do?
(d)escribe a room
(r)eturn to previous menu
>r

2.6. Game
􏰁 As discussed in the forum, the member function was missing some information and can be implemented by either:
1. passing in a reference to an , OR
2. returning the character grid representing current dungeon level.
The UML class diagram has since been updated to illustrate the first option, which fits better with the name of the function.
Game::displayLevel()
std::ostream
The class is a Singleton that provides the primary functionality for the application, but will not be a complete game for this assignment. The key functionality of the class for the moment is the construction of dungeon levels: both the example dungeon level and randomised dungeon levels. For that it acts in the ‘Director’ role of the Builder Pattern 􏰀.
The class itself follows the Singleton Pattern 􏰀. This means that there is only ever one instance of the class and it can be accessed across the entire application. This is useful as it enables all parts of the application to access information globally that it may need to perform its function as well as access common utility functions (i.e., ). Care must be taken with Singletons as, generally speaking, globals are considered bad practice due to a large number of things becoming dependent on them. However, it is common to have something that acts as the ‘access point’ to the whole application, so it is important that it be well defined, both structurally and behaviourally. That is where a Singleton is an improvement over the standard use of global variables: rather than an arbitrary set of global variables the Singleton provides a well- defined access point to the shared information. While this increases the dependencies on the one thing, this is more controlled than having many dependencies all over the place and (if done well) makes it more manageable.
You will need to refer to the description of the Singleton Pattern 􏰀 and the Dungeon Builder Class Diagram to implement the class as a Singleton. Note that ‘underlined’ text in UML Class Diagrams indicate that a member is a class member, i.e., is static.
You will also want to use the following definition of the member function:
Game
Game
Game
randomDouble()
Game
randomDouble()
/

The remainder of the functionality of will be described in the relevant sections.
Game
/
// Do not forget to include the headers
#include
#include
double Game::randomDouble() {
return _realDistribution(_randomGenerator);
}
// Where the class declaration includes the private data members (using class member initialis
ation for convenience)
std::mt19937 _randomGenerator{uint32_t(time(nullptr))}; //!< Mersenne Twister random number ge nerator seeded by current time std::uniform_real_distribution _realDistribution{0.0, 1.0}; //!< For random numbers be tween 0.0 & 1.0 2.7. Dungeon (Rooms, Walls, Doors) 􏰁 As discussed in the forum, the class needs member functions for accessing/mutating the s at each . These were left out of the UML class diagram because you may choose to implement them in a way that is most suited for the rest of your implementation. There are basically two alternatives: , ; or , ..., , , etc. Both interfaces can be mapped onto the different internal implementations so it is no big deal which you use. One will map more naturally, however, so choose whichever you prefer. Room RoomEdge Direction setEdge(RoomEdge, Direction) edgeAt(Driection) : RoomEdge setNorth(RoomEdge) , setSouth(RoomEdge) getNorth() : RoomEdge getSouth() : RoomEdge A dungeon level consists of a connected set of rooms and are to be represented by the class. The example level 􏰀 has 9 rooms arranged in a 3x3 grid, while a randomly generated level may have 1 room up to 16 rooms, depending on the 'width' (i.e., the number of columns) of the dungeon level and its 'height' (i.e., the number of rows) it contains. A dungeon level MUST have at least 1 row/column and up to 4 rows/columns. For example, a 1x1 (width x height) has only 1 room, a 2 x 3 has 6 rooms in 2 columns and 3 rows, and a 4x4 has 16 rooms arranged in 4 columns and 4 rows. Dungeon levels are also given a 'name'. Each room of a dungeon level (represented by the class) must be identifiable by a number ( ) so that they can be retrieved from the dungeon object using the numeric identifier independently of its storage container (e.g., , , etc.). The numeric identifier should start at 1 and increment by 1 for each room. Each room has an edge ( ) in each of 4 directions: North, South, East, and West. The directions are represented by the nested enumeration class . In each of these directions, there may be a wall (the class) or a doorway (the class). Doorways are connected to adjacent rooms via a doorway in the opposing direction. For example, if a room has a doorway to the north, the northern room has an 'opposite' doorway to the south and these doorways are connected to one another. DungeonLevel Room integer std::vector std::map RoomEdge Room::Direction Wall Doorway objects MUST be connected to one another using bare pointers in the C++ implementation. When two objects are connected (via , both objects must be in a consistent state such that they are connected to one another and any previously connected objects are no longer connected. Doorway Doorway Doorway::connect(opposite) Doorway Doorway To declare the enumerations as 'unsigned' as indicated in the UML Class diagram, you should use a definition such as the following: enum class Direction : unsigned { ... } // Make sure this is in the correct scope / Most doorways are connected to each other to allow movement between rooms in both directions. There are different types of doorways, however, which allow or disallow movement in different situations. These include: —the standard concrete doorway implementation that allows unrestricted movement between rooms —a concrete doorway implementation that cannot be entered from the room that contains it, but allows movement from the 'opposite' side which MUST be an or —a type of doorway that does not allow movement between rooms; the 'opposite' end of a MUST be another —a concrete doorway implementation that does not allow movement between rooms and can be 'unlocked' (if the gameplay were to be implemented) There are two special cases of the : the entrance to the dungeon level, and the exit out of the level. These are special because they have no 'opposite' doorway. The member function MUST return when the RoomEdge (specifically a Doorway) is connected to another, forming a "passage". That is, walls, entrance, and exit will return . Each room may contain a monster ( ), an item ( or ), or both. Monsters and Items are basically just placeholders for this assignment, more details are provided in the Items & Creatures 􏰀 section. There are two types of dungeon that can be constructed: a "basic" dungeon ( ), and a "magical" dungeon ( ). Each dungeon type will be populated with their own sets of room types ( and its class hierarchy), monster types ( and its class hierarchy using the Prototype Pattern 􏰀), and item types ( and its class hierarchy, using the Prototype Pattern 􏰀). Each element of a dungeon level will require descriptions that are displayed to the user on request through the 'Explore Dungeon Menu'' (refer to the MenuInterface 􏰀 section). The information to be contained in those descriptions is defined below. Describing a Dungeon and its Components OpenDoorway OneWayDoor OneWayDoor OpenDoorway LockedDoor BlockedDoorway BlockedDoorway BlockedDoorway LockedDoor RoomEdge::isPassage() true false Monster Weapon Consumable BasicDungeon MagicalDungeon Room Monster Item / When using the nested enumerations you may run into issues with cyclic dependencies of the header files between "room.h" and "roomedge.h", for example. The trick to resolving this issue is to use forward declarations as described in the Week 3 Lecture (Week 3 - Compilation, Inheritance, Operator Overloading and Documentation 􏰀), slide 28. You can also refer to the 'ForwardDeclarationExample' of the Example Projects - Preprocessor, Inheritance, Operator Overloading 􏰀 resources. Remember that when you use a forward declaration, uses of that type (e.g., return types, parameter types, or data member types) must be pointers or references (this is because the forward declaration does not provide any details of the type's content, which the compiler needs if it is not a pointer or reference). If you keep the nested enumeration, you will need to use the forward declaration in "room.h" to give access to the type 'RoomEdge'. You cannot do it the other way around as you will not be able to access the nested enumeration. Don't forget to #include the complete header files in your source files, though. Using a forward declaration in the implementation will typically not work. When asked to describe the dungeon level, the description of the dungeon level itself MUST be provided. The description of the dungeon MUST include its 'name', its 'dimensions' (i.e., width x height), and its type. For example, Which follows the form: The dungeon level may then be further described through the 'Explore Dungeon Menu' in which a description of each room MUST be provided to the user (based on the user's selection). The description of a room includes what the room "looks like", that is: where the doors are located and their type, the description of the monster (if present), and the description of the item (if present). Descriptions of walls may also be included. Furthermore, descriptions of monsters and items may be omitted if they are not present. An example description for a with the dungeon entrance to the , an to the South , a to the , a to the , a 'Goblin' , and a 'Short Sword' , may look like the following: Example Dungeon Level Size: 3 x 3 Type: Dark Cave (Basic Dungeon)
Size: x
Type:
QuartzChamber
North
OpenDoorway
Weapon
LockedDoor
East
OneWayDoor
West
Monster
A chamber that glitters like a thousand stars in the torchlight. (Quartz Chamber)
To the NORTH is the entrance to the dungeon level.
To the SOUTH is an Open Doorway to another chamber.
To the EAST is a Locked Door to another chamber.
To the WEST is a One-Way Door from another chamber.
There is a Goblin to fight.
There is a Short Sword to pick up.
The exact descriptions are up to you, but they MUST indicate the type of , the type of thing at each ( s optional), and the (by its name) and (by its name) if present.
The dungeon level ‘Entrance’ and ‘Exit’ MUST also be distinguished from ordinary s.
Room
Direction
Wall
Monster
Item
OneWayDoor
/

2.8. Building a Dungeon Level
The game will include two dungeon types: a basic dungeon ( class), and a magical dungeon ( class). Each dungeon type can contain different types of rooms, walls, doors, monsters, and/or items. (Refer to section Items & Creatures 􏰀 for details of the monsters and items and their incorporation into the dungeon level.)
To construct the composite dungeon level object we will be using the Builder Pattern 􏰀. The Builder Pattern 􏰀 helps us to construct complex composite objects of different types using a general process. The Builder Pattern 􏰀 has 4 roles (which have been annotated on the UML Class diagram using stereotype notation):
(Abstract)Builder—describes the generic interface used for creating the Product and its parts (i.e., rooms, doorways, monsters, and items);
ConcreteBuilder—implements the Builder interface to construct specific Product type and its parts (e.g., basic dungeon level and its components): it tracks the object and ensures it is constructed correctly by encapsulating the constraints around the valid types of parts for each dungeon type (see below); Director—the entity that instructs the creation of the composite object using the Builder interface; Product—the thing being constructed and its parts, in this case dungeon level objects and its rooms, doorways, etc.
Each dungeon type will have its own concrete builder class ( and
, respectively) that manages the creation of the dungeon object and each of its components. The class (Director) will need to instruct the builder on what type of component to build
(the Product) in a general sense (i.e., dungeon, room, doorway, creature, or item) using the
interface (AbstractBuilder), along with any information needed to put the component
in the correct location (e.g., item in a room) or connect them together (e.g., the rooms to be connected by doorways). The (concrete) builder will then use the provided information to instantiate an appropriate object (according to the allowable combinations below), insert the object where it belongs, and connect the objects as required (using the interfaces provided by the components).
BasicDungeonLevel
MagicalDungeonLevel
BasicDungeonLevelBuilder
MagicalDungeonLevelBuilder
Reminder: Be careful when creating a new dungeon level that any previous dungeon level (in the or in the ) has been cleaned up appropriately.
Game
DungeonLevelBuilder
The
interface is as follows (in abstract form, refer to the UML class diagram):
buildDugeonLevel(name, width, height)—creates the appropriate concrete object with the given name, width, and height parameters. The object MUST be constructed as a bare pointer and NOT using smart pointers.
buildRoom(id)—creates a concrete object with the specified identifier (‘id’) and adds it to the dungeon level currently under construction; the concrete type of MUST be chosen randomly buildDoorway(origin, destination, direction, constraints)—creates concrete object at the origin room in the specified direction , a second concrete object at the destination room in the opposite direction, and adhering to the specified constraints: see the section on the ‘constraints’ parameter below.
buildEntrance(room, direction)—creates a concrete object, representing the dungeon level “entrance”, at the specified room in the given direction. While we are implementing the the entrance and exit as simply special cases of , by abstracting the creation of the entrance and encapsulating it in its own function we are not tied to using the as the only implementation of the entrance
(and exit); this means we could change our implementation or add a new implementation that represents
DungeonBuilder
Game
DungeonLevelBuilder
DungeonLevel
Room
Room
Doorway
Doorway
OneWayDoor
Doorway
OneWayDoor
/

the entrance and exit differently. The implementation for this assignment may just delegate to buildDoorway(…) with appropriate arguments, but this is an implementation detail on which you may decide.
buildExit(room, direction)—same as previous except it creates the dungeon level “exit” buildItem(room)—creates a random item (weapon or consumable) and adds it to the given room; the random item MUST be from one of the valid items for the specific dungeon type being constructed buildCreature(room)—creates a random creature (Monster) and adds it to the given room; the random creature MUST be from one of the valid monsters for the specific dungeon type being constructed getDungeonLevel()—returns the constructed concrete ; this should be considered transfer of ownership, hence, subsequent calls will return no dungeon level object until after buildDungeonLevel(…) is called again. Note: we have adapted the standard Builder Pattern 􏰀 to our context by placing this function at the level of the AbstractBuilder rather than the ConcreteBuilders; this is because we know we always want a object, it is only the concrete type of dungeon level that differs.
A short video explaining one aspect of the dungeon level construction is available on Panopto.
DungeonLevel
DungeonLevel
Note: For components that have a choice, simply choose one at random. For example, when creating a room for the basic dungeon type, “toss a coin” and create a or based on the result; when adding an item or creature, randomly select one of the prototypes managed by the builder object (more on this in the Items & Creatures section). If you like, you may weight the things being selected such that some occur more frequently than others: for example, may be more common than where the latter only occurs 25% of the time, as opposed to the 50% of a coin toss.
RockChamber
QuartzChamber
RockChamber
QuartzChamber
The ‘constraints’ Parameter of buildDoorway(…)
The ‘constraints’ parameter of buildDoorway(…) is used to specify, in an implementation independent way, whether it would be possible to move between the specified rooms using the new concrete Doorway objects. The data type of the parameter is the nested enumeration DungeonLevelBuilder::MoveConstraints, rather than a particular concrete type of Doorway, which means the Builder interface is not dependent on the specific implementation classes of Doorway. The enumeration values are used as a bitmask to specify zero on more constraints on the movement between the rooms (the Wikipedia page on masks provides a concise description if you are unsure what a bitmask is). These values will need to be mapped into creating instances of the appropriate concrete Doorway classes. The following table lists the values of the enumeration and their meaning.
DungeonLevelBuilder::MoveConstraints
OriginImpassable 1 The doorway at the origin room cannot be moved through. Maps to a OneWayDoor unless the DestinationImpassable bit is also set, in
Constant Name
Value
Description
None
0
There are no constraints on the either the origin nor destination doorways. Maps to OpenDoorways at both rooms.
which case it maps to BlockedDoorway.
/

Constant Name
Value
Description
DestinationImpassable
2
The doorway at the destination room cannot be moved through. Maps to a OneWayDoor unless the OriginImpassable bit is also set, in which case it maps to BlockedDoorway.
OriginLocked
4
The doorway at the origin room is “locked”. Maps to a LockedDoor.
DestinationLocked
8
The doorway at the destination room is “locked”. Maps to a LockedDoor
To utilise the enumeration as a bitmask you will need to cast appropriately and utilise the bitwise operators ‘|’ (bitwise or) and ‘&’ (bitwise and). For example,
// assuming MoveConstraints is accessible in the current scope
// the following combination indicates that it is both origin locked and destination im
passable,
// which would cause the creation of a LockedDoor at the origin and a OneWayDoor at the
destination Room.
static_cast(static_cast(MoveConstraints::OriginLocked) | sta
tic_cast(MoveConstraints::DestinationImpassable))
To simplify the use of the enumeration, you should provide operator overloads for the ‘|’ and ‘&’ operators with values as the operands.
Example Build Sequence
The following sequence diagram illustrates an example sequence of function calls to construct a concrete dungeon level through the Builder interface.
MoveConstraints
MoveConstraints
/

Example Message Sequence for Building a Dugeon Level
: MenuInterface
User
make selections and set parameters
create…Level(…)
: Game
aConcreteDungeonLevelBuilder : DungeonLevelBuilder
setDungeonType(aConcrete DungeonLevelBuilder)
buildDungeonLevel(name, width, height)
buildRoom(id1)
room1
new


buildRoom(idN)
buildEntrance(roomA, directionA)


roomN
buildDoorway(originRoom1, destinationRoom1, direction1, constraints1)
buildExit(roomB, directionB)
buildItem(roomX)


buildCreature(roomY)
getDungeonLevel()


dungeon level

Your implementation does not have to be completely linear like this: it is just a basic template that applies to both the createExampeLevel as well as createRandomLevel. Your implementation may incorporate loops to reduce code duplication, for example.
Dungeon Element Combinations
The supported combinations of dungeon elements are listed in the following table.
/

Note: the constraints below are encapsulated as business rules in the builder rather than encoding them into the design as associations or hard constraints. This allows components to be mixed-and- matched in new dungeon types without having to modify the design.
Dungeon Element Combinations
Element Name
Class Name
Type
In Basic Dungeon?
In Magical Dungeon?
Rock Chamber
RockChamber
Room
Yes
No
Quartz Chamber
QuartzChamber
Room
Yes
No
Enchanted Library (optional)
EnchantedLibrary
Room
No
Yes
Alchemist’s Laboratory (optional)
AlchemistsLaboratory
Room
No
Yes
Rock Wall
RockWall
Wall
Yes
No
Magic Wall (optional)
MagicWall
Wall
No
Yes
Open Doorway
OpenDoorway
Doorway
Yes
Yes
One-Way Door
OneWayDoor
Doorway
Yes
Yes
Blocked Doorway
BlockedDoorway
Doorway
Yes
Yes
Locked Door
Locked Door
Doorway
Yes
Yes
Health Potion
Consumable
Item
Yes
Yes
Molotov Cocktail
Consumable
Item
Yes
Yes
Smoke Bomb
Consumable
Item
Yes
No
Resistance Potion (optional)
Consumable
Item
No
Yes
Boomerang
Weapon
Item
Yes
Yes
Short Sword
Weapon
Item
Yes
No
Battle Axe
Weapon
Item
Yes
No
Wizard’s Staff (optional)
Weapon
Item
No
Yes
Magic Wand (optional)
Weapon
Item
No
Yes
Goblin
Monster
AbstractCreature
Yes
Yes
Werewolf AbstractCreature Yes No
Monster
/

Element Name
Class Name
Type
In Basic Dungeon?
In Magical Dungeon?
Evil Wizard
Monster
AbstractCreature
Yes
Yes
Dragon (optional)
Monster
AbstractCreature
No
Yes
Note that the monsters and items are prototypical instances (following the Prototype Pattern 􏰀) and not defined as individual classes.
/

2.9. Example Dungeon Level
When the user selects the ‘generate the example level’ option from the main menu, the application MUST generate a dungeon level conforming to the following diagram with the name ‘Example Dungeon Level’. The example dungeon level will be constructed as the Basic Dungeon type. While the layout of the dungeon level is defined, the monsters and items that appear MUST still be randomised. The construction of the example dungeon level MUST use the builder classes and member functions, and not be a completely independent implementation.
The layout diagram uses the following symbols:
Large green rectangles represent rooms with the numbers indicating their ID
Small blue bars joining rooms represent connected pairs of doors
One Way Doors are blue bars and indicated by a directional arrow (this includes the Entrance and Exit). Grey walls on the blue bars represent Blocked Doorways.
Padlocks on a blue par represent Locked Doors.
Orange faces represent monster locations, the one with horns is a ‘boss’ monster
Yellow trophies represent item locations
The in game visualisation must match the following:
/

/
+—-I—-+ +———+ +———+ |||||| | >–< X--X ML | |||||| +----v----+ +----v----+ +----v----+ ||| +----v----+ +----^----+ +----@----+ |||||| | >–> ML >–< | |||||| +----X----+ +----v----+ +---------+ || +----X----+ +----^----+ +---------+ |||||| | L @--@ >—< M* O |||||| +---------+ +---------+ +---------+ 2.10. Items & Creatures Creatures Dungeons, specifically rooms, can be inhabited by numerous foul monsters. There can be at most one monster per room and a monster never leaves the room in which it is created. All monsters must derive from the class and conform to the Prototype Pattern 􏰀—this design leaves scope for other types of creatures other than just monsters. The monsters are basically placeholders in this assignment to give a little detail to the content of the dungeon levels. You only need to implement the functionality required to clone (according to the prototype pattern 􏰀) a monster, describe it (i.e., display its name), and display it in the dungeon view with its display character. The Prototype Pattern 􏰀 allows us to create 'types' of things as represented by their prototypical instance. Additional instances of the 'type' are created by copying or 'cloning' the prototype. There are several monster types that may be chosen randomly to populate the dungeon level, their names are: Goblin Werewolf Evil Wizard Dragon The prototypical instances of these types MUST be configured by the appropriate concrete builder instance (refer to the Building a Dungeon Level section for the required combinations). To add a creature to a room, one of the configured prototypes is chosen, cloned, and the copy is added to the room. The monster in the final room of the dungeon level, i.e., the room with the exit from the level, MUST be a 'boss' monster. In the actual gameplay a 'boss' would be more powerful than an ordinary monster; however, in this assignment being a boss will be represented simply by prefixing the creature's name with 'Elite'. For example, a boss of type Goblin would be named 'Elite Goblin'. Optional: You may make monsters more interesting by giving them a Weapon. If you do so, cloning the Monster MUST create a deep-copy, i.e., the copy of the Monster MUST have its own copy of the Weapon. A shallow copy would occur if multiple Monster objects have references (or pointers) back to the same Weapon object. Items The rooms of each dungeon level can also be populated with s, which are either s (that a player could pick-up to increase their power) or s (that a player could use to gain temporary effects). It does not matter exactly what these items or effects are but, as with the monsters, items are handled using the Prototype Pattern 􏰀. There can be at most one item per room. You only need to implement the functionality required to clone (according to the prototype pattern 􏰀) an item, describe it (i.e., display its name), and display it in the dungeon view with its display character. Prototypical instances of the items MUST be configured by the appropriate concrete builder implementations (refer to the Building a Dungeon Level section for the required combinations). The following are the names of the weapons: Boomerang Short Sword Battle Axe / AbstractCreature Item Weapon Consumable Wizard's Staff Magic Wand The consumable items include: Health Potion Molotov Cocktail Smoke Bomb Resistance Potion To add an item to a room, one of the configured prototypes is chosen (whether it be a weapon or consumable), cloned, and the copy is added to the room. / 2.11. Viewing a Dungeon Level When the user chooses to 'view' the dungeon level the dungeon level as a whole MUST be displayed on the console/terminal using the defined characters to indicate the different dungeon level elements. This section describes how the different elements are to be displayed, and provides some suggestions on how to implement it appropriately, while preserving encapsulation, information hiding, and appropriate assignment of responsibilities. ! You MUST ONLY output to the console in the class. There MUST NOT be any use of in the member functions of and to preserve separation of concerns ( handles input/output). MenuInterface cout display() DungeonLevel Room MenuInterface Individual Rooms Each room MUST be displayed as an 11x5 square of characters using the '-' (hyphen) character for the North/South edges, and the character '|' (pipe) for the East/West edges, and the character '+' (plus) at the corners. For example, an empty room would appear as follows: This basic shape will have different symbols to indicate different elements of the room, such as doorways, monsters, and items. The following symbols will be used: Dungeon level Entrance/In: (capital 'i') Dungeon level Exit/Out: (capital 'o') Doorways passable in the appropriate direction (North, South, East, West, respectively): (hat), (lowercase 'v'), (right-angle bracket), (left-angle bracket) Locked Door: (at symbol) Blocked Doorway: (capital 'x') Monster: (capital 'm') "Boss" Monster (the monster in the room with the exit): (capital 'm' followed by asterisk) Loot item: (capital 'l') Walls (all types): (hyphen) or (pipe) for North/South and East/West directions, respectively +---- ----+ || || +---- ----+ I O ^ v >
< @ M X M* L - | Doorway symbols MUST be shown in the centre of the edge at which a is present. s will always use the appropriate directional arrow to indicate the ability to move to/from s and the neighbouring room. For example, Doorway OpenDoorway OneWayDoor +----^----+ || <> || +—-v—-+
/

Indicates an at each direction of the room where the “arrows” are pointing outwards, towards the neighbouring rooms, while
Indicates a at each direction where the “arrows” are pointing inwards, indicating that it cannot be traversed out of the current room.
The other indicators (including entrance and exit) are shown instead of the “arrows”, for example:
shows the dungeon level entrance at the North, the dungeon level exit at the South, a to the East, and a to the West.
Monster and Loot characters appear in the centre of the room, with the ‘M’ to the left-of-centre and the ‘L’ to the right-of-centre. The very centre character will be the ‘*’ if the monster is a “boss”. For example, the following illustrate rooms with only a monster, only a loot item, and both.
Monster
Loot item (weapon or consumable)
Monster and Loot item
+—-v—-+ || >< || +----^----+ OneWayDoor Doorway +----I----+ || @X || +----O----+ BlockedDoorway LockedDoor +---------+ || |M| || +---------+ +---------+ || |L| || +---------+ +---------+ || |ML| || +---------+ Boss Monster and Loot item / OpenDoorway Dungeon Level For the complete dungeon level, each room is separated by two space characters horizontally, and one newline character vertically. For example, a 2x2 dungeon level (with only walls at the edges) may appear as follows: +---------+ +---------+ |||| |||| |||| +---------+ +---------+ +---------+ +---------+ |||| |||| |||| +---------+ +---------+ When s are present between the rooms, they should appear "linked" by two the hyphens "--" for East/West connections, and the pipe '|' for North/South connections. This connection MUST appear regardless of the type of the Doorway . There are no "connections" for the entrance and exit of the dungeon level. For example, Doorway +----I----+ +---------+ |||| | >—< | |||| +----v----+ +----X----+ || +----v----+ +----X----+ |||| | @--< | |||| +---------+ +----O----+ Implementation Suggestions You should treat the display output as a matrix of characters using a list ( or ) of strings ( ): each string in the list will be a row, while each character in a string is a column. There should be no newline characters in this representation. std::vector std::array std::string / +---------+ || | M*L | || +---------+ Outputting the final representation of the level to the console is then simply outputting each row to the console with a newline in between. Create each string with the appropriate number of characters (11 for a single room representation for example), by filling it with space characters or the basic room boundary, to prevent errors accessing specific indices of the matrix. Consider the most appropriate list type for and : the representation of a room is always 11x5, while the representation of the level itself may differ depending on the width/height selection made by the user on dungeon creation. The final representation created by MUST reuse the output for each individual room and NOT reimplement the generation of each room's representation. The dungeon level is made up of components (which in turn may comprise other components) and each component should know how to most effectively utilise its information. DungeonLevel Room DungeonLevel::display() / 2.12. Generating a Dungeon Level Randomly When the user chooses to create a random dungeon level, the application MUST prompt the user for the following details: the name of the new dungeon level; the type (basic or magical) of the new dungeon level; and the size (width and height) of the new dungeon level. The prompts may appear as follows What would you like to call the level? > Small dark cave
How many rows in *Small dark cave*? >2
How many columns in *Small dark cave*? >2
What type of dungeon level is it? (b)asic or (m)agical >b
The name of the dungeon level MUST NOT be empty.
The width of the dungeon level MUST be in the range 1-4, i.e., The height of the dungeon level MUST be in the range 1-4, i.e.,
When the user has completed entering the parameters of the new dungeon level, the application MUST use the interface to instantiate a new dungeon level with random components according to the rules described in this section. Refer to sections Dungeon (Rooms, Walls, Doors) and Building a Dungeon Level for information on the different components and how to construct them.
The random dungeon level will have a number of rooms equal to . That is, a minimum of 1, for a 1×1, and a maximum of 16, for a 4×4.
The entrance (In doorway) to the random dungeon level MUST be in one of the rooms of the first row.
The entrance may be added to any edge (choose one at random) that cannot be connected to another room, e.g., the North edge and possibly the West edge (for the first room in the row) or the East edge (for the last room in the row).
The exit (Out doorway) from the random dungeon level MUST be in one of the rooms of the last row.
The exit may be added to any edge (choose one at random) that cannot be connected to another room, e.g., the South edge and possibly the West edge (for the first room in the row) or the East edge (for the last room in the row).
Doorways MUST be added to each room randomly according to the following rules:
Each non-corner room MUST have at least two doorways (including the entrance and exit): this helps reduce the chances of degenerate dungeon levels that do not have a path from beginning to end.
DungeonLevelBuilder
/

Each corner room MUST have at least one doorway (excluding the entrance and exit): this prevents corner rooms from almost always being connected to both neighbouring rooms.
There is a 40% chance that an individual doorway is traversable, 30% chance that it is locked, and 30% chance that it is impassable.
Rooms may contains Monsters and/or Items under the following conditions: There is a 25% chance that a room will contain a Monster.
There is a 35% chance that a room will contain an Item: 65% chance that the Item is a Consumable and a 35% chance that it is a Weapon.
The room with the exit MUST ALWAYS contain a Monster (that is a ‘boss’) and an Item.
The room with the entrance MUST NOT have a Monster NOR an Item; except if the room also contains the exit.
Care must be taken with a 1×1 dungeon level as some of the rules overlap. For example, the entrance and exit have may potentially be placed on the same edge and you do not want to accidentally replace the entrance or exit.
/

3. Documentation
Your code must be documented appropriately using Doxygen comments. See Documentation with Doxygen 􏰀 for getting started with Doxygen if you did not already set it up in Week 3.
Read pages 48-53 of the course textbook for guidelines on good commenting, as well as the style guide. Document as you go, not all at the end. One strategy is to write a brief comment about what the “1 thing” the function is supposed to do when you declare it, then refer to that comment while implementing it: this helps maintain focus when implementing the function and helps stop yourself from making it do more than the ‘1’ thing it is supposed to do.
Document sparingly: most of the marks are for implementation not comments. The intent is to keep you in the habit of good practice and introduce you to tools such as doxygen.
Focus on the public and protected interfaces: often private functions do not need comments if they are small and clear as to what they achieve.
Comment blocks must be used in your header file to document your classes and class members.
Private members should also be documented when it is not obvious for what they are used—but first check if the code can be improved as clean code is better than comments.
Use comments sparingly in source files, document blocks of code (switch statements, if else groups, loops, etc.) rather than individual statements: do not comment individual statements, unless the outcome of the statement is not obvious.
You can add comments to ‘main.cpp’ that include the (or if using javadoc style) annotation to document the ‘main page’ of the generated HTML.
! Configure Doxygen to generate only the HTML documentation. We are not interested in the other formats and they will only bloat your submission file.
\mainpage
@mainpage
/

4. Code Style
You must write you code conforming to the code style set for this course. See http://codetips.dpwlabs.com/style-guide 􏰂
/

5. Version Control
You must use version control to keep track of your progress during implementation, using git. You should perform regular commits as you implement features and fix errors. Your commit comments should reflect the context of the changes that were made in each commit—a fellow developer can always diff the contents to see exactly what changed but that does not provide the context. You should try to ensure each commit comment contains a short subject line.
Your submission will comprise your entire version control repository, so it should be specific to the assignment. For example, if you use git, you must create the git repository in the root directory for your assignment. Do not commit your assignment to a repository created in a parent folder or any other location. Your repository must contain all source files required to compile and run your program (including a Doxygen config file) but must not include any generated or extraneous files. You can use the ‘.gitignore’ file to specify files and folders you do not want to include in the repository, such as the generated documentation files/folders.
You can ensure a clean folder for submission by cloning your assignment, generating the HTML documentation from Doxygen, and zipping the new folder. This will not modify your working directory while providing all committed files and their version history.
You do not have to use an online version control repository such as GitHub. If you do use an online repository, ensure that the assignment is private, i.e., cannot be seen by people other than yourself.
/

6. Implementation Rules and Hints
! You must consider when and where it is appropriate to use smart pointers vs. bare pointers and the effect this choice may have on constructors, destructors, etc. In most cases the choice is up to you with the exception of the connection between two doors, doors must be connected via bare pointers.
! Be sure to check for null pointers ( ) before attempting to use an object through a pointer and reset pointers to null where appropriate.
! Smart Pointers – the Dungeon class uses the smart pointer to store and retrieve the rooms (among other things). You must use the template function to create the rooms to pass to the function . The below code snippet is an example of adding a room to a dungeon:
! The and classes may not be the only occurrence of smart pointers in your implementation.
! The provided project uses namespaces. Be careful to ensure you are accessing classes with appropriate scopes. Remember to use the scope operator , e.g., .
! The game will need to keep track of (at least) the current room, the character, and the previous room/door.
! Casts – in your code, casts should only need to be performed between a base class pointer and a derived class. When doing so, a dynamic cast should be performed (using ). For example, to cast an shared pointer to a pointer you would use the following code snippet:
! Remember, if the cast is successful, the pointer will be non- .
! It is recommended that you test individual components as you go, rather than trying to test the whole application through the menu-driven interface. Writing code to test specific elements will speed up development as you will not need to constantly enter data through the menu interface.
! You may change the descriptions of items, creatures, actions, etc., if you like.
! Type defines – if you know what you are doing, you may define type aliases for the shared pointer types for use in the and your classes. Alternatively use appropriate declarations.
Dungeon
nullptr
Dungeon::addRoom
std::shared_ptr
std::make_shared()
Dungeon d = Dungeon{};
d.addRoom(std::make_shared(/* constructor arguments go here */));
Room
::
core::dungeon::BasicDungeon
dynamic_pointer_cast
Weapon
Enchantment
std::shared_ptr weapon = …; // Wherever the value comes from
std::shared_ptr enchantment = std::dynamic_pointer_cast(weapon);
nullptr
MenuInterface
using
/

7. Submission Details
You MUST submit your complete Qt Creator Project, including git repository, inside a single ZIP file to LearnOnline (Assessment Item 2 – Assignment Implementation). The ZIP file MUST include the following:
All source files required to compile and run your program
The Doxygen config file and the HTML documentation generated using Doxygen tools Your version control directory (‘.git’ folder)
Your ZIP file MUST NOT include any generated or extraneous files (other than the HTML documentation as stated above).
A cover-page is not required as one is generated for you by LearnOnline upon submission.
The deadline for submission is 20 September 2020 11:59 PM. After which time the submission will be
considered late and attract a penalty as detailed in the course outline 􏰀.
You will then need to complete the first part of the self-reflection exercise by 4 October 2020 11:59 PM.
Details to be released.
After you have received the mark for your implementation, you must complete the second half of the self- reflection exercise by 11 October 2020 11:59PM. Details to be released.
/

8. Academic Misconduct
This is an individual assignment: your submitted files will be checked against those of other student, and other sources, for instances of plagiarism.
Students are reminded that they should be aware of the academic misconduct guidelines available from the University of South Australia website.
Deliberate academic misconduct, such as plagiarism, is subject to penalties. Information about Academic integrity can be found in Section 9 of the Assessment Policies and Procedures Manual at:
https://i.unisa.edu.au/policies-and-procedures/codes/assessment-policies/
/