In that spirit, here is my implementation. It does exactly as the spec orders (and nothing more), except for a few minor things. I did warn you previously that it wasn't C++ - in fact, I don't even know if a C++ compiler will compile this at all. In short, if your code looks like mine, YOU FAIL.
#include <conio.h>#include <windows.h>#include <assert.h>#include <stdio.h>#include <stdlib.h>#include <time.h>#define bool int#define true 1#define false 0void random_seed(unsigned int seed) { srand(seed);}int random_range(int min, int max) { return min + (rand() % (max - min));}int roll(int ndice, int nsides){ int i = 0; int r = 0; for (i = 0; i < ndice; ++i) r += random_range(1,nsides); return r;}int strength_modifier(int strength){ return (strength - 10) / 2;}int dexterity_modifier(int dexterity){ return strength_modifier(dexterity);}int constitution_modifier(int constitution){ return strength_modifier(constitution);}#define BLACK 0#define BLUE 1#define GREEN 2#define CYAN 3#define RED 4#define MAGENTA 5#define BROWN 6#define LIGHTGREY 7#define DARKGREY 8#define LIGHTBLUE 9#define LIGHTGREEN 10#define LIGHTCYAN 11#define LIGHTRED 12#define LIGHTMAGENTA 13#define YELLOW 14#define WHITE 15void set_color(unsigned int font_color, unsigned int background_color){ SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE) , (background_color << 4) | font_color );}void press_any_key(){ printf("Press any key to continue...\n"); _getch();}char input(){ char input = _getch(); _putch(input); _putch('\n'); return input;}void output_hr(){ printf("==============================\n");}void error(const char* message){ set_color(LIGHTRED,BLACK); printf("Error : %s\n", message);}void invalid_input(){ error("Invalid input. Please try again.");}bool boolean_prompt(){ while (true) { set_color(WHITE,BLACK); printf(" (y)es, (n)o : "); switch (input()) { case 'y' : return true; case 'n' : return false; default : return false; } }}typedef struct{ char* name; int attack_dice_number; int attack_dice_sides; float cost; int critical_min; int critical_repeat;} Weapon;Weapon weapon_table[] = { {"Unarmed Strike", 1, 2, 1, 20, 2}, {"Brass Knuckles", 1, 4, 1, 20, 2}, {"Dagger", 1, 4, 2, 19, 2}, {"Mace", 1, 6, 5, 20, 2}, {"Handaxe", 1, 6, 6, 20, 3}, {"Shortsword", 1, 6, 6.5, 19, 2}, {"Scimitar", 1, 6, 7, 18, 2}, {"Morningstar", 1, 8, 8, 20, 2}, {"Spear", 1, 8, 9, 20, 3}, {"Longsword", 1, 8, 9.5, 19, 2}, {"Greatclub", 1, 10, 11, 20, 2}, {"Halberd", 1, 10, 12, 20, 3}, {"Bastard Sword", 1, 10, 12.5, 19, 2}, {"Greataxe", 1, 12, 16.0, 20, 3}, {"Greatsword", 2, 6, 20, 19, 2}};#define max_weapon 14typedef struct{ char* name; int armor_class; int max_dex_mod; float cost;} Armor;Armor armor_table[] = { {"Unarmored", 0, 255, 0}, {"Padded Armor", 1, 8, 5}, {"Leather Armor", 2, 6, 10}, {"Hide Armor", 3, 4, 15}, {"Studded Leather", 3, 5, 25}, {"Scale Mail", 4, 3, 50}, {"Chain Shirt", 4, 4, 100}, {"Chainmail", 5, 2, 150}, {"Breastplate", 5, 3, 200}, {"Splint Mail", 6, 0, 225}, {"Banded Mail", 6, 1, 250}, {"Half-Plate", 7, 0, 600}, {"Full Plate", 8, 1, 1000}};#define max_armor 12typedef struct{ char name[20]; int strength; int dexterity; int constitution; int level; int experience; float gold; int weapon; int armor; int max_hit_points;} Character;void name_character(Character* character){ int pos = 0; char input = '\0'; bool done = false; do { memset(character->name,'\0',20); pos = 0; set_color(WHITE,BLACK); printf("Enter character name : "); do { input = _getch(); _putch(input); if (input != '\r') character->name[pos] = input; pos += 1; } while(input != '\r' && pos < 19); _putch('\n'); printf("Is that the name you want? "); done = boolean_prompt(); } while (!done);} unsigned char roll_stat(){ return random_range(8,20);}void roll_stats(Character* character){ bool done = false; do { character->strength = roll_stat(); character->dexterity = roll_stat(); character->constitution = roll_stat(); output_hr(); printf("Strength : %d\n",character->strength); printf("Dexterity : %d\n",character->dexterity); printf("Constitution : %d\n",character->constitution); output_hr(); printf("Keep these stats? "); done = boolean_prompt(); } while (!done);} void create_player(Character* player){ bool player_named = false; bool stats_rolled = false; player->level = 1; player->experience = 0; player->gold = 0; player->armor = 0; player->weapon = 0; while (true) { set_color(WHITE,BLACK); output_hr(); printf("Create Character\n"); output_hr(); printf("Menu Options:\n"); printf("a. Name Character\n"); printf("b. Roll for Stats\n"); printf("r. Return to previous menu\n"); output_hr(); printf("Choice : "); switch (input()) { case 'a' : name_character(player); player_named = true; break; case 'b' : roll_stats(player); player->max_hit_points = 10 + constitution_modifier(player->constitution); stats_rolled = true; break; case 'r' : if (!player_named) { error("You havn't named your player."); break; } if (!stats_rolled) { error("You havn't rolled any stats."); break; } return; default : invalid_input(); } }}void purchase_armor(Character* character){ char identifier = 0; char selection = 0; int i = 0; if (character->armor == max_armor) { printf("You already have the best armor.\n"); press_any_key(); } while (true) { set_color(WHITE,BLACK); output_hr(); printf("Armor available\n"); output_hr(); printf("a : No selection. Go back.\n"); identifier = 'b'; for (i = character->armor + 1; i <= max_armor; ++i, ++identifier) { _putch(identifier); printf(" : %s - %f gold\n",armor_table.name, armor_table.cost); } output_hr(); printf("Choice : "); selection = input(); if (selection == 'a') { printf("Return? Are you sure? "); if (boolean_prompt()) return; else continue; } selection -= 'b'; selection += character->armor; selection += 1; if (character->gold < armor_table[selection].cost) { error("You can't afford that."); continue; } printf("You selected %s. Is that what you want? ", armor_table[selection].name); if (boolean_prompt()) { character->armor = selection; character->gold -= armor_table[selection].cost; } else continue; }}void purchase_weapon(Character* character){ char identifier = 0; char selection = 0; int i = 0; if (character->weapon == max_weapon) { printf("You already have the best weapon.\n"); press_any_key(); } while (true) { set_color(WHITE,BLACK); output_hr(); printf("Weapons available\n"); output_hr(); printf("a : No selection. Go back.\n"); identifier = 'b'; for (i = character->weapon + 1; i <= max_weapon; ++i, ++identifier) { _putch(identifier); printf(" : %s - %f gold\n",weapon_table.name, weapon_table.cost); } output_hr(); printf("Choice : "); selection = input(); if (selection == 'a') { printf("Return? Are you sure? "); if (boolean_prompt()) return; else continue; } selection -= 'b'; selection += character->weapon; selection += 1; if (character->gold < weapon_table[selection].cost) { error("You can't afford that."); continue; } printf("You selected %s. Is that what you want? ", weapon_table[selection].name); if (boolean_prompt()) { character->weapon = selection; character->gold -= weapon_table[selection].cost; } else continue; }}void purchase_equipment(Character* character){ while (true) { set_color(WHITE,BLACK); output_hr(); printf("Purchase Equipment\n"); output_hr(); printf("Menu Options:\n"); printf("a. Purchase Armor\n"); printf("b. Purchase Weapon\n"); printf("r. Return to previous menu\n"); output_hr(); printf("Choice : \n"); switch (input()) { case 'a' : purchase_armor(character); break; case 'b' : purchase_weapon(character); break; case 'r' : return; default : invalid_input(); } }}void view_stats(Character* character){ set_color(WHITE,BLACK); output_hr(); printf(character->name); printf("\n"); printf("Level : %d\n", character->level); printf("Experience : %d\n", character->experience); printf("Gold : %f\n", character->gold); printf("Hit points : %d\n", character->max_hit_points); printf("Strength : %d\n", character->strength); printf("Dexterity : %d\n", character->dexterity); printf("Constitution : %d\n", character->constitution); printf("Weapon : %s\n", weapon_table[character->weapon].name); printf("Armor : %s\n", armor_table[character->armor].name); output_hr(); press_any_key();}int roll_hit_points(int levels, int con_mod){ int r = 0; int i = 0; for (i = 0; i < levels; ++i) r += roll(1,10) + con_mod; return r;}int experience_table[6] = { 300, 150, 75, 35, 15, 5 };int experience_reward(int winner_level, int loser_level){ int difference = (loser_level - winner_level) * -1; if (difference < 0) difference = 0; if (difference > 5) difference = 5; return experience_table[difference];}float gold_table[6] = { 25, 12, 6, 3, 1, 0.5f };float gold_reward(int winner_level, int loser_level){ int difference = (loser_level - winner_level) * -1; if (difference < 0) difference = 0; if (difference > 5) difference = 5; return gold_table[difference];}int experience_required(int level){ if (level == 0) return 0; return ( (level - 1) * 1000) + experience_required(level - 1);}bool battle(Character* character, int opponent_level){ int p_hit_points = character->max_hit_points; int o_hit_points = roll_hit_points(opponent_level + 1,1); int p_initiative = roll(1,20) + dexterity_modifier(character->dexterity); int o_initiative = roll(1,20); int p_random_part, p_attack_roll, p_damage, p_total_damage, p_armor_check; int o_random_part, o_attack_roll, o_damage, o_total_damage, o_armor_check; int i = 0; float ngold; int nexperience; int hit_points_gained; bool p_crit = false; bool o_crit = false; if (o_initiative > p_initiative) goto MID_LOOP; while (true) { set_color(WHITE,BLACK); printf("%s : %d, Level %d : %d\n", character->name, p_hit_points, opponent_level, o_hit_points); //player strike p_random_part = roll(1,20); p_attack_roll = p_random_part + strength_modifier(character->strength) + character->level; o_armor_check = 15; p_crit = false; if (p_attack_roll > o_armor_check) { //player attacks! p_damage = roll(weapon_table[character->weapon].attack_dice_number, weapon_table[character->weapon].attack_dice_sides) + strength_modifier(character->strength); p_total_damage = p_damage; if (p_random_part >= weapon_table[character->weapon].critical_min) { p_crit = true; for (i = 0; i < weapon_table[character->weapon].critical_repeat; ++i) p_total_damage += p_damage; } set_color(p_crit ? YELLOW : LIGHTBLUE, BLACK); printf("%s hit Level %d opponent for %d damage!\n", character->name, opponent_level, p_total_damage); o_hit_points -= p_total_damage; if (o_hit_points <= 0) { //award experience and gold ngold = gold_reward(character->level,opponent_level); nexperience = experience_reward(character->level,opponent_level); character->gold += ngold; character->experience += nexperience; printf("You gained %d experience and %f gold.\n", nexperience, ngold); if (character->experience >= experience_required(character->level + 1)) { character->level += 1; hit_points_gained = roll_hit_points(1, constitution_modifier(character->constitution)); character->max_hit_points += hit_points_gained; set_color(YELLOW,BLACK); printf("LEVEL UP! Hit Points +%d.\n", hit_points_gained); } return true; } } else { set_color(RED,BLACK); printf("%s totally missed!\n", character->name); } Sleep(1000);MID_LOOP : set_color(WHITE,BLACK); printf("%s : %d, Level %d : %d\n", character->name, p_hit_points, opponent_level, o_hit_points); o_crit = false; o_random_part = roll(1,20); o_attack_roll = o_random_part + opponent_level; p_armor_check = 10 + armor_table[character->armor].armor_class + min( armor_table[character->armor].max_dex_mod, dexterity_modifier(character->dexterity) ); if (o_attack_roll > p_armor_check) { o_damage = roll(1,6+opponent_level); o_total_damage = o_damage; if (o_random_part == 20) { o_crit = true; o_total_damage += o_damage; } set_color(o_crit ? YELLOW : RED ,BLACK); printf("Level %d hit %s for %d damage!\n",opponent_level,character->name,o_total_damage); p_hit_points -= o_total_damage; if (p_hit_points <= 0) { printf("xXxXX DEAD XXxXx\n"); return false; } } else { set_color(LIGHTBLUE,BLACK); printf("Level %d totally missed!\n",opponent_level); } Sleep(1000); }}bool fight(Character* character, int* max_fought){ int level = 0; char selection = 0; char prefix = 0; while (true) { set_color(WHITE,BLACK); output_hr(); printf("Fight!\n"); output_hr(); printf("a. return\n"); prefix = 'b'; for (level = 0; level <= min(*max_fought + 1, 20); ++level, ++prefix) { _putch(prefix); printf(". Level %d.\n",level); } output_hr(); printf("Choice : "); selection = input(); if (selection < 'a' || selection > 'b' + *max_fought) invalid_input(); else { if (selection == 'a') return true; selection -= 'b'; selection = min(selection, 20); printf("Fight? "); if (boolean_prompt()) { if (!battle(character, selection)) return false; if (selection == *max_fought) (*max_fought) += 1; } } }}void main_menu(){ Character player; bool player_created = false; int max_fought = 0; while (true) { if (!player_created) max_fought = 0; set_color(WHITE,BLACK); output_hr(); printf("Main Menu\n"); output_hr(); printf("Menu Options:\n"); printf("a. Create Character\n"); printf("b. Purchase Equipment\n"); printf("c. View Stats\n"); printf("d. Fight!\n"); printf("q. Quit\n"); output_hr(); printf("Choice : "); switch (input()) { case 'a' : if (player_created) { printf("You already have a character. Really create a new one? "); if (boolean_prompt()) { create_player(&player); player_created = true; } } else { create_player(&player); player_created = true; } break; case 'b' : if (!player_created) error("You need to create a character first."); else purchase_equipment(&player); break; case 'c' : if (!player_created) error("You need to create a character first."); else view_stats(&player); break; case 'd' : if (!player_created) error("You need to create a character first."); else player_created = fight(&player,&max_fought); break; case 'q' : return; default : invalid_input(); } }}int main(int argc, char* argv[]){ srand((unsigned)time(0)); main_menu(); return 0;}
Allow me to reiterate. I have given you an example of how NOT to do it. (That said, it's not ugly code. It's just C.)