• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Warcraft III Name Generator v2.4.0.0

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
This program will generate random Wc3 names.
You can generate both male and female names.

It's always somewhat difficult to come up with character names while modding in Wc3.

This program can generate close to a hundred million unique names.
Just keep generating names until one that sounds good comes up.

This works on:
  • Windows 7
  • Windows Vista
  • Windows XP

Thank you, and Happy Mapping!

If you are not running a Windows OS, you can use D.O.G's version of this tool because it's written in Java and can thus run on any Java-supporting operating system!

The source code is available here.

Keywords:
wc3, name, warcraft, gen, generator, namegen, object editor, dota, hero, names, original, creator, program, c++, C++, windows 7, windows vista, window
Contents

Warcraft III Name Generator v2.4.0.0 (Binary)

Reviews
Vengeancekael Date: 2012/Oct/02 22:21:30 [Please do not send me a message, use Staff Contact] Comment: [Approved] Updated and improved a lot, this tool is highly recommended to map makers, story writers, etc.! Staff Contact - Rules...
Level 21
Joined
Dec 9, 2007
Messages
3,096
This didn't take me 20 lines :c (I feel n00bish now)

Code:
// The source code used to be here, but I removed it for ... senseless reasons

Don't.
You exe, for example, doesn't require a database, a web server or an internet connection.
If you'd make what he said, you'd need to fill a database with name, which would be a lot of boring work.
 
Level 23
Joined
Jan 1, 2009
Messages
1,610
Don't.
You exe, for example, doesn't require a database, a web server or an internet connection.
If you'd make what he said, you'd need to fill a database with name, which would be a lot of boring work.

an Internetconnection is quite a harsh requirement these days hm?
I'm just saying that for such a ...marginal purpose I wouldn't and don't need an .exe. You could basically do the same in php and editing etc. would be easier.

Those Namegeneratos exist (google) and the database was just an extensible idea.

tl;dr - I see absolutely no purpose in an .exe without interface/commandline based for such a marginal task.
 
Major update.

File size down from 120KB to 25KB :D
I recoded it from a clean C++ application to a very ugly C-esque application.
The next step is to use C strings, but I don't think that would make as much a difference as removing <iostream>/<iomanip> did.

Also, you can now dump all the generated names in one execution of the program into a text file just by pressing 'D'.
I also added the option to quit by pressing 'Q' so I can ensure that the program's int main() will return 0 telling windows that the execution was successful. I don't know how console applications handle Window events.
 
Here you go, I made the code much better.

Only flaw is that I'm not using <random> and this thing is platform specific, but that's what you get when you ask me to make it do stuff with the clipboard :).
Also, <conio.h> is not present on Linux or Mac OS systems because it is not in the C++ standard. It's an old extension from the days of MS-DOS.

C++:
#include <iostream>
#include <string>
#include <utility>
#include <vector>
#include <fstream>
#include <cstdlib>
#include <ctime>
#include <conio.h>
#include <locale>

// Yes, this application will only work 
// on Windows.
#include <Windows.h>

const std::vector<std::string> vowels
{
	"a", "e", "i", "o", "u"
};

const std::vector<std::string> consonants
{
	"b", "c",  "d",  "f", "g", 
	"h", "j",  "k",  "l", "m",
	"n", "p",  "q",  "r", "s",
	"t", "v",  "w",  "x", "y",
	"z", "ch", "sh", "th"
};

const std::vector<std::string> female_suffix
{
	"ona", "ena", "ana", "una", "ina",
	"ora", "era", "ara", "ura", "ira"
};

const std::vector<std::string> male_suffix
{
	"thor", "don", "din",  "gon", "thar",
	"kon",  "kin", "mag",  "gin", "mace",
	"dex",  "tex", "mech", "lag", "bei",
	"ven",  "den", "dan",  "nero"
};

const std::vector<std::string> clan_prefix
{
	"War",     "Black",  "Mage",  "Dark",  "Eagle",
	"Thunder", "Silver", "Demon", "Blood", "Iron",
	"Frost"
};

const std::vector<std::string> clan_suffix
{
	"song", "rock", "fire", "wing", "horn",
	"hand", "hoof", "claw", "eye",  "wood",
	"fist", "bane"
};

void print_welcome_message() {
	std::cout << "\n Warcraft III Name Generator v2.4.0.0"
			  << "\n By Magtheridon96"
			  << "\n Special Thanks to D.O.G."
			  << '\n'
			  << "\n This program will generate Warcraft III character names."
			  << "\n There are nearly a hundred million possible names."
			  << '\n';
}

void print_instructions() {
	std::cout << "\n Commands:"
			  << "\n  'm' - Generate a male name."
			  << "\n  'f' - Generate a female name."
			  << "\n  'c' - Clear the screen."
			  << "\n  'd' - Dump all the generated names to a file."
			  << "\n  'q' - Quit the application."
			  << "\n The last generated name will be copied."
			  << "\n\n";
}

//
// The expected range has the same properties as 
// C++ standard iterator ranges. [begin, end)
//
// get_random_int(0, 4) -> [0 ... 3]
//
int get_random_int(int begin, int end) {
	return begin + std::rand() % (end - begin);
}

const std::string& get_random_vowel() {
	return vowels[get_random_int(0, vowels.size())];
}

const std::string& get_random_consonant() {
	return consonants[get_random_int(0, consonants.size())];
}

const std::string& get_random_male_suffix() {
	return male_suffix[get_random_int(0, male_suffix.size())];
}

const std::string& get_random_female_suffix() {
	return female_suffix[get_random_int(0, female_suffix.size())];
}

const std::string& get_random_clan_prefix() {
	return clan_prefix[get_random_int(0, clan_prefix.size())];
}

const std::string& get_random_clan_suffix() {
	return clan_suffix[get_random_int(0, clan_suffix.size())];
}

void seed_random_number_generator() {
	std::srand(std::time(0));
}

std::string get_male_name() {
	std::string name = "";
	int i = get_random_int(0, 2);

	switch (i) {
		case 0:
			name += get_random_consonant();
			name += get_random_vowel();
			break;
		case 1:
			name += get_random_vowel();
			name += get_random_consonant();
			name += get_random_vowel();
			break;
		case 2:
			name += get_random_consonant();
			name += get_random_vowel();
			name += get_random_consonant();
			name += get_random_vowel();
			break;
		default:
			// This is never supposed to happen.
			break;
	}

	name += get_random_male_suffix();

	if (std::islower(name[0]))
		name[0] = std::toupper(name[0]);

	name += " ";
	name += get_random_clan_prefix();
	name += get_random_clan_suffix();

	return name;
}

std::string get_female_name() {
	std::string name = "";
	int i = get_random_int(0, 2);

	switch (i) {
		case 0:
			name += get_random_vowel();
			name += get_random_consonant();
			break;
		case 1:
			name += get_random_consonant();
			name += get_random_vowel();
			name += get_random_consonant();
			break;
		case 2:
			name += get_random_vowel();
			name += get_random_consonant();
			name += get_random_vowel();
			name += get_random_consonant();
			break;
		default:
			// This is never supposed to happen.
			break;
	}

	name += get_random_female_suffix();

	if (std::islower(name[0]))
		name[0] = std::toupper(name[0]);

	name += " ";
	name += get_random_clan_prefix();
	name += get_random_clan_suffix();

	return name;
}

void clear_screen() {
	// This function is not standard, but it will work here.
	// Don't use this in portable software, seriously.
	// Everything in conio.h is not standard compliant.
	// ISO C++ does not mention this shit.
	clrscr();
}

void dump_file(const std::string& all) {
	std::ofstream file("Generated Names.txt");
	file << all;
}

// This function is Windows specific.
// C++ does not know what a 'clipboard' is.
void copy_to_clipboard(const std::string& name) {
	const char* output = name.c_str();
	const std::size_t size = name.length() + 1;
	
	HGLOBAL memory = GlobalAlloc(GMEM_MOVEABLE, size);
	memcpy(GlobalLock(memory), output, size);
	GlobalUnlock(memory);
	
	OpenClipboard(0);
	EmptyClipboard();
	SetClipboardData(CF_TEXT, memory);
	CloseClipboard();
}

int main() {
	std::string all_names;

	print_welcome_message();
	print_instructions();

	seed_random_number_generator();

	bool quit = false;

	while (!quit) {
		// The standard input stream is buffered, which is why it's not 
		// possible to get a single key stroke without making it unbuffered.
		// The simplest work around is to use a platform specific function.
		// This application is only meant to work on Windows anyway.
		char i = std::tolower(_getch());

		std::string text;
		std::string name;

		switch (i) {
			case 'm':
				name = get_male_name();
				text = "(M)  " + name + "\r\n";
				std::cout << text;
				all_names += text;
				copy_to_clipboard(name);
				break;
			case 'f':
				name = get_female_name();
				text = "(F)  " + name + "\r\n";
				std::cout << text;
				all_names += text;
				copy_to_clipboard(name);
				break;
			case 'c':
				clear_screen();
				print_instructions();
				break;
			case 'd':
				dump_file(all_names);
				std::cout << "[System] Dumped to file." << std::endl;
				break;
			case 'q':
				quit = true;
				break;
			default:
				break;
		}
	}

	return 0;
}
 
Last edited:
I was wondering, why are you not 'using namespace std', when you can omit all 'std::' by it?...

Because "using namespace std" pollutes the global namespace quite heavily, and I prefer not to do that. It's a terrible practice.

and #include <string>, isnt it that string is a keyword already?...

string isn't a keyword, string is a type defined based on class basic_string.
The only primitives in C++ are integral and floating point datatypes. (strictly of course, that means char, bool, int, double, long, float, short, long long, long double, etc...)

isnt it that instead of *output, why cant it be &name?...

Because std::string and char* are not the same thing. The WinAPI functions expect a const char*, and the method std::string::c_str returns a const char*, so I cached it in a variable for readability.
&name would return the memory address of the name string class instance.

You don't have to worry _at all_ about micro-optimizations and pedantic shit in C++. If you have a half-decent compiler, snippets of code that do the same thing will have the same assembly. (Compile with -O2)
Compilers are very smart nowadays.
 
Top