(Solved) : Undoable Battle Goals Create Class Hierarchy Game Actors Use Stack Template Along Command Q42752511 . . .

Undoable battle——————————————————————————————-Goals:——————————————————————————————- Create a class hierarchy for game actors Use the Stack (template) along with the Command Pattern to create an undoable action Simulate a battle between two Actors with the ability to undo moves——————————————————————————————-Program Overview:——————————————————————————————- This program will consist of several Actors (Knight, Ghost, and Warrior) that are capable of performing attacks and healing. You will run a simulation of a battle between these actors with a running “history” of moves. The simulation will first prompt you to select a player and an opponent. Once the two are set, and a battle has begun, There will be 3 options available: 1) Player attacks Opponent 2) Opponent attacks Player 3) Undo last move The first two will invoke an attack from one player to another. The third option will undo the last move that was done with a technique discussed below. After each choice, the updated player information is printed (Player, type, health), (Opponent, type health) This will proceed until a character is dead. ——————————————————————————————-Undoable Commands Overview:——————————————————————————————-In many modern applications, we have the option to undo certain actions we perform. For example in Microsoft word, we can hit CTRL+Z after typing some text to bring the document back to it’s original state. In practice this is done with the use of a Stack ADT holding references to “commands”. A command comes from the Command Pattern, one of the many Design Patterns which came out of this (now classic) book: https://www.amazon.com/Design-Patterns-Object-Oriented-Addison-Wesley-Professional-ebook/dp/B000SEIBB8This book outlines 23 patterns to solve commonly recuring problems in software engineering. One of those patterns is the Command pattern. (I highly reccomend picking up a copy of this book once you are more comfortable with C++. Design patterns are fundamental to architecting non-trivial software systems)The essense of the command pattern is to represent some action (think function executing) as an object. This is done in the following way: An abstract class is created known as Command (or ICommand with the I standing for interface). This class will have an virtual Execute method. Because Command is abstract, we never create instances of it. Instead we derive from it to create “concrete” Commands.These classes which derive from ICommand will have to implement the Execute method. Polymorphism allows us to have collections of commands which we can execute (by invoking the Execute() method), and having each command do it’s own thing. For example imagine we have some application state (a global integer in this case). We want some Commands to change that state. So we create an ICommand and two concrete commands which derive form ICommand. We can then have a vector of commands which we can execute and each one will perform it’s own specific implementation of Execute. //————————————–int state = 0; class ICommand{ public: virtual void Execute()=0;};class IncrementCommand: public ICommand { public: void Execute(){ state++; }};class DecrementCommand: public ICommand{ public: void Execute(){ state–; } };int main(void){ vector<ICommand*> commands; commands.push_back(new IncrementCommand()); commands.push_back(new IncrementCommand()); commands.push_back(new DecrementCommand()); for(auto c : commands){ c->Execute(); } cout << state << endl; // Should be 1; }//———————————————-This is the essence of the command pattern, but it’s not quite what we need. If we want undo functionality, we also need a way to revert the state to how it was before the action. For this we can modify our example above by having our Commands not only Execute, but also Undo to reverse the effects Execute had on state.://————————————–int state = 0; class ICommand{ public: virtual void Execute()=0;};class IUndoableCommand: public ICommand{ public: virtual void Undo()=0;};class IncrementCommand: public IUndoableCommand { public: void Execute(){ state++; } void Undo(){ state–; }};class DecrementCommand: public IUndoableCommand{ public: void Execute(){ state–; } void Undo(){ state++; }};int main(void){ vector<IUndoableCommand*> commands; commands.push_back(new IncrementCommand()); commands.push_back(new IncrementCommand()); for(auto c : commands){ c->Execute(); } commands[1]->Undo(); commands[0]->Undo(); cout << state << endl; // Should be 0; }//———————————————-This command pattern takes us part of the way towards undo functionality but we need to consider how we can keep a history of commands with the ability to undo them. Notice that currently I have to Undo the commands in the opposite order I executed them. This should remind you of the Stack ADT we discussed, where we have a LIFO processing order (Last In First Out). If we keep a stack of state changes (i.e. IUndoableCommands), we have a running history of everything we did to alter our state. As actions are executed, they are pushed onto the stack with the last action being on the top. If we need to undo an action we can look at the top of our stack (stack.Top()) and call the Undo method of that IUndoableCommand object. After we pop it off the stack (and potentially delete it if it’s a pointer). We can repeat this for all the elements in our stack until we run through the entire history of state changes to get back to the initial condition. Example:int main(void){ stack<IUndoableCommand*> stack; IUndoableCommand* command1 = new IncrementCommand(); IUndoableCommand* command2 = new IncrementCommand(); // Perform increment (state should be 1) command1->Execute(); stack.Push(command1); // Perform another increment (state should be 2) command2->Execute(); stack.Push(command2); // Undo last action (state should be 1); stack.Top()->Undo(); stack.Pop(); cout << state << endl; // State should be 1}The last thing we need to do is to make sure we manage memoryWe want a CommandManager class to take care of maintaining a stack, and one that will release the resources once we are done working with this stack. See Commands4.cpp for the final example:——————————————————————————————-Classes for our Battle simulator:——————————————————————————————- We will incorporate the Undoable command pattern to help us preserve a history of BattleMoves done by our Actors. Our Project will be broken up into several classes The hierarchies will look as follows:Actor—– General game character with the following ADT spec: public: Actor(int health, string type); DoMove(MoveManager mgr, MoveType, Actor* other) Hit(int damage); //public method to hit THIS actor with damage Heal(int amount); //public method to heal this actor with an amount GetMoves() //vector of MoveTypes IsDead() protected: string type; int health; vector<MoveType> From Actor we will derive: Ghost Will have AttackOne and Heal in vector of MoveTypes, and 100 health Knight Will have AttackTwo and Heal in vector of MoveTypes, and 100 health Warrior Will have AttackOne and AttackTwo in vector of MoveTypes, and 100 healthActorFactory————This class will return actors given a type (enum or string is OK)the implementation is below: “`class ActorFactory{ public: static Actor* CreateActor(ActorType actor){ switch(actor){ case ActorType::Ghost: return new Ghost; case ActorType::Knight: return new Knight; case ActorType::Warrior: return new Warrior; } }};“`IMove—–Will be our “Command”. It will allow both Execute and Undo public: void virtual Execute()=0; void virtual Undo()=0; BattleMove———-A battle move will derive from IMove. It will add two actor pointers. The BattleMove can either hurt the opponent, or heal the player. ADT spec: private: Actor* self Actor* other The constructor will take in the self and other pointers(Note: Each battle move will have an Execute method. That execute will either work on self (if heal) or other (if attack)) Therefore when we construct a movewe should pass in the self and other pointers to any kind of concrete BattleMove implementation. From BattleMove we will derive: AttackOne Will generate a random damage between 10 and 15 Execute will call the Hit method of other and save the actualDamage done in a local variable. Undo will call the Heal method of other with the saved actualDamage variable (to undo the damage) AttackTwo Will generate a random damage between 0 and 25 Same logic as attack one Heal Will generate a random heal amount between 10 and 15 Execute will call Heal on self with the actual heal amount and save it in a member variable. Undo will call Hit on self to undo the Heal (with amount stored in the member variable) An enumeration or array of const char *’s to go with BattleMove (MoveType)An enumeration or array of const char *’s to go with Actor types (ActorType)These will make it easy to set up a switch/case statement to instantiate the correct moves and actors based on user input.BattleMoveFactory—————–This class will create Battle Moves. The implementation is provided below“`#pragma once#include “enums.hpp”#include “Actor.hpp”#include “BattleMove.hpp”class MoveFactory{ public: static BattleMove* BuildMove(MoveType type, Actor* self, Actor* other){ BattleMove* m; switch(type){ case MoveType::AttackOne: m = new AttackOne(self, other); break; case MoveType::AttackTwo: m = new AttackTwo(self, other); break; case MoveType::Heal: m = new Heal(self, other); break; default: cerr << “Unexistent: ” << (int)type; throw “Non-existent move”; } return m; }};“`To use this class, an Actor can use the static method MoveFactory::BuildMove(moveType, this, otherActor) to get back a *BattleMove MoveManager———–Analogous to our CommandManager class. Will hold on to a stack (use the template implementation of stack from the lecture code on Templates) of IMove*’s and will be referenced by every actor. Whenever an actor performs a move, it will go through the MoveManager’s method so that history is recorded on the stack. “`void Actor::DoMove(MoveManager& mgr, MoveType moveType, Actor* other){ cout << *this << ” used: ” << MoveTypeStrings[static_cast<int>(moveType)] << endl; mgr.ExecuteMove(MoveFactory::BuildMove(moveType, this, other));} “`Move manager will have ExecuteMove() and UndoLastMove() methods defined, a constructor to initialize a stack, as well as a destructor to delete all the IMove*’s still in the stack. ExecuteMove will take an IMove * as argument, execute the move, and push it onto the stackUndoMove will undo the last move in the stack (make sure to delete after an undo)Also make sure the destructor in the underlying stack implementaion deletes all the items still in the stack on destruction Runner——This will be the class to run the battle. First it will prompt the user for a choice of player 1 and player 2. Then it will allow the user to select one of three choices mentioned in the first sectio. After each choice, If it is a move, select a random move from the actor’s list of moves and DoMove with it (passing in the movemanager to take care of it). If the choice is an undo, invoke the MoveManager’s UndoLastMove() method. Make sure to check for a stackEmpty exception. After a move print the state of each character. Some sample output: Select a player:1) Ghost2) Knight3) Warrior1You selected: 1Select an opponent:1) Ghost2) Knight3) Warrior3You selected: 3Beginning match!Ghost, (100)Warrior, (100)———————————–Choose move:1) P1 -> P22) P2 -> P13) Undo1Ghost, (100) used: HealGhost, (100) is healed by 13 hp.[Player: Ghost, (113)][Opponent: Warrior, (100)]Choose move:1) P1 -> P22) P2 -> P13) Undo2Warrior, (100) used: AttackOneGhost, (113) is hit with 12 damage.[Player: Ghost, (101)][Opponent: Warrior, (100)]Choose move:1) P1 -> P22) P2 -> P13) Undo1Ghost, (101) used: HealGhost, (101) is healed by 12 hp.[Player: Ghost, (113)][Opponent: Warrior, (100)]Choose move:1) P1 -> P22) P2 -> P13) Undo2Warrior, (100) used: AttackOneGhost, (113) is hit with 12 damage.[Player: Ghost, (101)][Opponent: Warrior, (100)]Choose move:1) P1 -> P22) P2 -> P13) Undo3Ghost, (101) is healed by 12 hp.[Player: Ghost, (113)][Opponent: Warrior, (100)]

Expert Answer


Answer to Undoable battle ——————————————————————————————- Goals: —-…

Leave a Comment

About

We are the best freelance writing portal. Looking for online writing, editing or proofreading jobs? We have plenty of writing assignments to handle.

Quick Links

Browse Solutions

Place Order

About Us

× How can I help you?