Took me awhile (about an hour and half) to make it but it works i guess....
It's also quite a bit sloppy. If anyone wants to clean up and add some functionality for a better example, please do so. I also didn't have the traps and treasure move although it should be relatively simple to add.
Also, although 508 lines looks like a lot, according to cloc only 375 of those are code; so I've only really added 140 lines (cloc says your original version is 235 lines of actual code).
I don't understand one major bug; the ClearScreen() function only works the first time it is called for me (on Arch Linux). I don't know how the windows version will fare for those of you on windows (credit to Duoas for both versions). It looks a lot better if you create a custom board by passing -e on the command-line...
Also, what's with the messages? I changed them if that was OK (if not, just change them back).
Serves you right, mate. Anyone with more money than me is bound to be cursed. That's why our world sucks.
Congrats, you win, rich bastard. Buy me a new computer!.
It's just text. Bear in mind that it's only really 375 lines of executable code. The rest is comments and blank lines. I'll try and fix it up a little.
Blitz Coder, graphical games can get up to thousands upon thousands of lines of code.
Plus, the excessive amounts of lines in C++ comes through declarations instead of actual implementation. Procedural is smaller normally in this sense. The extra size doesn't make it slower. In this case, it just adds functionality and perhaps makes the executable a bit bigger.
1) I SUCK at naming classes. Actor in this context is simply something that does something visually in the game. Change it if you wish.
2) The inherited classes were going to have some extra functionality with bHasTreasure and bDead. Moving them of course is a lot of trouble and I figured I'd leave it like that for when I decided to do it. You can change it to typedefs if you want.
3) The Move<insertdirectionhere> functions pose a problem for a few reasons. One being that they don't use a user to move, they call the default user inside of the main class. I mentioned making it multiplayer and for that to happen, you'd need to pass a user.
But doing this also requires that the person implementing main create his own users which is fine if they really want to. The Move() function I think is more flexible and lets you do this though so I left them both in there.
4) The parameter _user for Board() and user, the member object, are different. What you pass to Board() is actually the character that represents the user. In order for the game to be single player or multiplayer, the most dynamic way to do it is to actually let the person implementing main instantiate his own User objects and then pass it to Board which is possible but not tested or do I know if it works.
5) And I made this out of boredom and relatively fast. Most of the goofy stuff came from my boredom lol
Things I think I could have done better:
I really think that I could have come up with a better positioning system. For instance, it's not that difficult to make the grid fit to that of the Cartesian grid. It would also be good to implement a 2D vector class and then pass that around. Really though, it's an example, and I thought I was getting to advanced lol. Good work chris.
Minor Changes: http://codepad.org/LgxU2Sjv
You can change whatever you want. I honestly don't care. Most of the functionality I added was random and is strange also made for a good wake up call for around 8 o'clock in the morning.
This is a major bug fix: http://codepad.org/pnE7FXVe
* Fixed the error message on whole words.
* Added parameter to move functions.
* Fixed awkward silence if nothing is entered.
* Fixed bug where the user would disappear if attempting to move off the edge.
Some new code that does some of what I wanted: http://codepad.org/usIaozvp
Uses ncurses coordinates which helps easily implement my coordinate plane.
I suppose I could get rid of it though, I wanted it mainly to fix the problem with screen clearing. In this case, we don't even refresh, we just move directly to the users, traps, and treasures locations and add them to the grid.
Not finished of course. Since this is a little bit beyond a beginners challenge now, I don't know if I'm going to even finish it lol.
That was a good idea, using curses. I started writing my own; maybe I'll use ncurses too. I virutally the whole thing inside of 40 minutes, I haven't done the dungeoncrawl::draw() function yet, though, so nothing is printed. I also have internal support for multiple players but I can't think of a way of choosing a character. There has to be a limit or we'll end up with X being a player and X being treasure.
@computerquip,
I realised yesterday that the ClearScreen function I added had a bug. I copied Duoas' code wrong (so it's not his fault). Lines 220 and 221 (in the original code) should swap.
/**
* bunny(): construct a new bunny and assign it a random name
*/
bunny()
{
/* Read in the list of names */
std::ifstream bunny_name_file;
bunny_name_file.open(BUNNY_NAME_FILE);
std::vector <std::string> names = new std::vector<std::string>();
if (bunny_name_file.is_open()) {
while (bunny_name_file.good()) {
std::string line;
std::getline(bunny_name_file, line);
names.push_back(line);
}
bunny_name_file.close();
} else {
delete names;
return;
}
/* Choose the name */
size_t name_line = get_random<size_t>(0, names.size());
/* Set up the new bunny */
gender = get_random<gender_t>(MALE, FEMALE);
colour = get_random<colour_t>(COLOUR_WHITE, COLOUR_SPOTTED);
age = 0;
name = names.at(name_line);
back = new node;
if (back->prev)
back->prev->next = back;
else
front = tail;
/* Cleanup */
delete names;
}
@Names: To prevent using resources, I made a static vector that's accessible by the bunny class. So when you create a new bunny, it can access an already made list of names. The only downside is you have to call InitNames before you construct any bunny which is hardly a downside and easy to fix, but it's a one time thing and it will never have to be called again. After that, you can do: name = names[rand() % names.size()]; This one line accounts for the size of the name list, grabs a random name, and assigns each bunny a name.
@List: For now, I'm just using a std::list, although it's not difficult to implement my own.
@Duplicate names: Another problem I came across is stopping duplicate names. For now I'm allowing it since the challenege doesn't say anything about it but I thought up a few solutions to it.
1) Have two lists, a first name list, and a last name, lowering the probability of duplicate names exponentially.
2) Make a vector of used names and iterate through the list, restarting when the list is filled.
@Output: I decided to use tied ostreams to give output to files and console. I'm having a problem with it which I'm probably making a dunce mistake with, shown in the codepad post given below.
Well, my name list is 15.3 kiB. That's why I DMA'd the name list. People are too bläse about memory usage; although it's hard to decide whether it's better to read 15k several times and never store it for more than how ever long it takes to do an std::vector::at and a string assignment, or if I should read it once and store it once. It's the memory usage vs. CPU usage battle.
I think I'll use an std::list to store my bunnies too. I can't be asked to implement my own; it means I have to write push_back, push_front, etc. etc. versions.
Is there an std::ringbuffer or something similar? That would be useful for memory wastage.
Edit: your rand % 99 should be rand % 101 for the 2% randomness thing.
@Output,
I created (with help) a little while ago my own implementation for this: