|
|
c m s c 214
f a l l 2 0 0 1 |
FAQ
Answers to the latest question. First, "out of memory" questions have been answered in the FAQ since probably project 2. Basically, you've somehow corrupted memory (used a bad pointer, deallocated bad memory, etc). I suggest tarring the file, going to WAM, and running purify to locate the error.
If you're asking "am I allowed to add public methods, or create a new class, or make something protected?", the answer is yes. If you're saying, "can I hardcode?", the answer is NO! Get the project to work at your convenience.
There are two ways. Here's the easier way. In Team, write a "clone()" method. This will make a copy of the "*this" object. The copy creates a shallow copy of Team (with pointers pointing to players from the original).
Then, call the "clone()" method on the BST. You will need to
write a BST "clone()" method. This method will call "cloneRec()"
and pass it root. This is the rough idea of how the code will look.
void BST::cloneRec( Node *curr )
{
if ( curr != NULL )
{
Data temp = curr->getData()->clone(); // calls clone on player
curr->setData( temp ); // adjust pointers
cloneRec( curr->getLeft() );
cloneRec( curr->getRight() );
}
}
You can write a "destruct()" method for Team, which will
call the "destruct()" method for BST, which will recurse the
tree deleting only Player objects (letting the real destructor
delete nodes afterwards).
You would need to write a setData() to get this to work.
Yes. Use the same syntax as players leaving a team, except put "Robot" in front, as usual.
The robot may rejoin a team, too.
In the base class, you should either define virtual functions (write code for it), or put "= 0" in the header file to indicate that it's pure virtual. For Item, you need to define virtual functions since the class is not abstract. In Player, you can define them, or put "= 0" to indicate its a pure virtual function.
Yes, but in this one case, we'll allow it to slide. Normally, this would be considered "making the project easier" and be borderline hardcoding, but we will merely deduct points if you do this, thus if you are running out of time, you would simply print the tree again.
Player * Fighter::clone() const
{
return new Fighter( *this );
}
This function is virtual in the Player class. This will
allow you to construct a clone of the BST down to the player
objects in the BST.
No. Only when a Fighter becomes a Knight and a Mage becomes a Wizard.
No. They remain in the room in which they were disabled.
Admittedly, this terminology favors someone who knows about role playing games. A robot initially has hit points set to the strength of the robot. You can think of it like "gas" or "energy". Thus, this is a new data member. If a robot is hit, the hit points decrease (the robot has less energy). When it becomes 0, the robot is disabled.
The strength of the robot should remain at its initial value. This is for the purposes of computing experience points.
Yes, it will. For a novice. For Wizards and Knights, dropping items does not change experience points.
Give a few rules, and people become very creative. No, you won't be allowed to pick up a second sword. You can only pick it up if you are a Knight at the time you pick it up. Similar rules apply for Wizards.
At this point, no. The project is sufficiently large, that we'll forgo this process. However, you may still want to run your project through "purify" just to see where the leaks, memory overruns are. This may help avoid errors.
The real difficulty lies in deciding how to deallocate memory. Normally, a BST would manage the memory of any dynamically allocated objects (such as Players). Yet, it often doesn't, and so this makes everything painful
We won't test this. That way, we won't have to deal with upgrades, etc. (Technically, if you DID implement this, you would have to upgrade players).
No. Once disabled, you can assume we won't have commands to manipulate the robot. The only thing you have to handle is a player attempting to attack a robot that's disabled.
Yes, you can. This update function would take a Player * pointer parameter, and find it in the BST, and replace the corresponding Player * object in the BST with the parameter.
Why would this be used? If you're doing extra credit, then you may want to upgrade a Fighter to a Knight. You go into your ArrayList of Player *, and replace the Fighter object with the Knight. However, this means you have a NEW object stored. Your BST (the one that stores pointers to players) will still point to the old Fighter (after all, it stores pointers, which are merely addresses). You need it to point to the Knight.
The update would pass in a Knight object, then call locate(), find the node, and replace it with Fighter. That way, it's updated in the BST as well. (You may want to make a function in Team that makes this call to BstSortedList).
This is only a suggestion. There are other ways to handle this.
Ian L. writes this question. It brings up something rather interesting. Throughout the project, there's been an issue of how to manage dynamic memory.
For example, last semester, the BST class stored its own copies of objects. Thus, if there was a Player object pointed to by a Node, then that object was dynamically allocated by the BST, and therefore the destructor would deallocate it. This made it very clear whose responsibility it was to destroy the memory.
However, this semester, the project has become more interesting. In the Parser, you created an ArrayList of Player * objects. For many (but not all students), it was convenient, in Project 2, to make the BST nodes point to Players in the ArrayList. However, since ArrayList maintains the Player objects, the BST copy constructors, assignment operators, etc. did a SHALLOW copy. That is, they copied the pointers, but do not create a dynamically allocated copies of the Player objects. That way, any copy still refers to the original Player object in the ArrayList.
So, here's the idea. First, the Parser should handle dynamic allocation of Players (Mages and Fighters) as well as Items (regular, rings, and swords). Who handles the deallocation?
Several ways to handle this. First, since all Items belong to someone (rooms, robots, players), then when rooms, robots, or players are destroyed, they should deallocate items. Players (and robots, if you dynamically allocate robots) can be destroyed at the end of main() by going through the ArrayList in a loop and calling delete. This is assuming that the ArrayList contains all Players. If it doesn't, then you would delete that, then have Team delete Players.
Brian K., a TA, also suggests another way. Keep an ArrayList of all Item *'s and all Player *'s (you should already have this for Players), and at the end of main(), write a loop that goes element by element calling delete. Thus, ArrayList and BST would no longer delete the pointers they store (but they must still delete the array and nodes in the BST respectively).
Recall that a player can hold rings and normal items (if they are a Fighter/Knight) or swords and normal items (if they are a Mage/Wizard). Thus, you need to be able to store Item, Ring, Sword. You can't do this without using pointers. So, the answer is the second: ArrayList<Item *> treasure.
Recall this is extra credit. If a Player starts off with 1500 experience points or more, they start as an expert (Knight or Wizard). This occurs if the amount of money they carry is 1500 points or more. If a Player reaches 1500 points or more, they become an expert. At that point, their experience points freeze. Becoming an expert means creating a new object (dynamically) of the expert type. You MUST do this, if you wish to gain extra credit.
To make it easier for TAs to grade, write an upgrade() function for Mage and Fighter.
getPower() for rings and swords return back strings. Create a large string concatentating both of them. For example, if the power for one sword is "slices" and the power for a second sword is "dices", then the power for both is "slices and dices" (returned as a string).
Yes, for novices.
No. A Wizard can only hold a maximum of two rings (a Knight can only hold a maximum of two swords). Any attempt to carry more will fail. I will need to add an additional message to handle that. Basically, it will say they are already holding the maximum weapons. However, a Mage can carry as many swords as his/her strength permits. This will go into the treasure they hold.
You'll only have to handle a player attacking a robot. You don't have to write code for players attacking players or robots attacking robots. You will have to handle a player attacking a robot outside the dungeon.
Yes, you'll be given more specs for that soon.
No. The current ArrayList should be fine. You should write a sort214Ptr which will sort an ArrayList of pointers. Unlike SortedList, ArrayList does not refer to an explicit key (which is what causes the problem in the first place).
Add a new data member to store it.
Yes, they are. That was intentional. Normally, one would make Rings and Swords somewhat different, but this allows you to code less by making changes via cut-n-paste.
No. Alas, when the derived class destructor is run, it always calls the base class destructor. If it's pure virtual, the compiler won't have any code to run. So you must make the base class desrtuctor plain virtual and implement the destructor, but leave the body blank in the base class destructor.
No. The goal is to have you store things using base class pointers (i.e., Item *). If you keep it seperate, you won't be dealing with virtual functions as much. The only time you can keep it separate is for Fighters with swords and Mages with rings. They will not keep their weapond with their treasure. However, Rooms should keep them all together.