# Talk:Gem
This is the program I wrote to generate the table of gems. -- Killian 08:52, 19 October 2006 (UTC)

#include 

<string>
#include <iostream>
#include <cstdlib>
#include <sstream>

using std::string;

using std::cout;
using std::endl;

using std::atoi;

using std::stringstream;

#define GEM(name,desc,prob,wt,gval,nutr,mohs,glass,color) \
	printrow(name,desc,prob,wt,gval,nutr,mohs,glass,color)

#define ROCK(name,desc,kn,prob,wt,gval,sdam,ldam,mgc,nutr,mohs,glass,color) \
	printrow(name,desc,prob,wt,gval,nutr,mohs,glass,color)

const char *GEMSTONE = "gemstone";
const char *GLASS    = "glass";
const char *MINERAL  = "mineral";

const char *CLR_WHITE   = "white";
const char *CLR_RED     = "red";
const char *CLR_ORANGE  = "orange";
const char *CLR_BLUE    = "blue";
const char *CLR_BLACK   = "black";
const char *CLR_GREEN   = "green";
const char *CLR_YELLOW  = "yellow";
const char *CLR_MAGENTA = "magenta";
const char *CLR_BROWN   = "brown";
const char *CLR_GRAY    = "gray";

/* Need forward declaration. */
string mkdesc(const char *name, const char *desc, const char *material);

string mksymbol(const char *name,
				const char *desc,
				const char *material,
				const char *color) {
	string ascii = string("{{") + color + string("|*}}");
	string tile  = "[[Image:" + mkdesc(name, desc, material) + ".png]]";

	return ascii + " " + tile;
}

/* Don't display "stone" after the name. */
const string NO_STONE[] = {
	"dilithium crystal",
		"ruby",
		"diamond",
		"sapphire",
		"black opal",
		"emerald",
		"opal",
		""
};

string stone(const char *name, const char *material) {
	if (name == "flint") { return " stone"; }
	else if (material == "glass"
		|| material == "mineral") { return ""; }
	else {
		for (const string *sp = NO_STONE; *sp&nbsp;!= ""; ++sp) {
			if (*sp == name) { return ""; }
		}

		return " stone";
	}
}

/* Name should be a wikilink. */
const string LINK_NAME[] = {
	"dilithium crystal",
	"luckstone",
	"loadstone",
	"touchstone",
	"flint",
	"rock",
	""
};

bool link(const char *name) {
	for (const string *sp = LINK_NAME; *sp&nbsp;!= ""; ++sp) {
		if (*sp == name) {
			return true;
		}
	}
	return false;
}

string mkname(const char *name, const char *material) {
	bool dolink = link(name);

	return string("'''")
		+ (dolink&nbsp;? "[["&nbsp;: "")
		+ name
		+ stone(name, material)
		+ (dolink&nbsp;? "]]"&nbsp;: "")
		+ string("'''");
}

string mkdesc(const char *name, const char *desc, const char *material) {
	if (!desc) { return string(name); }
	else {
		string gem = (material == string("mineral"))&nbsp;? "stone"&nbsp;: "gem";
		return string(desc) + " " + gem;
	}
}

string mkcost(int gval) {
	stringstream ss;
	string sgval;
	ss &lt;&lt; gval;
	ss &gt;&gt; sgval;

	return sgval + " [[Zorkmid|zm]]";
}

string mkweight(int wt) {
	stringstream ss;
	string swt;
	ss &lt;&lt; wt;
	ss &gt;&gt; swt;

	return string("[[Weight|") + swt + string("]]");
}

string mkhard(int mohs) {
	return (mohs &gt;= 8)&nbsp;? string("HARD")&nbsp;: string("soft");
}

string mkmaterial(const char *material) {
	return string("[[") + material + string("]]");
}

typedef const char *S;
typedef int I;

void pre(void) {
	cout &lt;&lt; "<!-- This table was generated by a program; see the talk page. -->\r\n";
	cout &lt;&lt; "{| class=\"prettytable\"\r\n";
	cout &lt;&lt; "! *&nbsp;!! Name&nbsp;!! Description&nbsp;!! Cost&nbsp;!! Weight&nbsp;!! Hardness&nbsp;!! Material\r\n";
}

void printrow(S name, S desc, I prob, I wt, I gval, I nutr, I mohs, S glass, S color) {
	cout &lt;&lt; "|-" &lt;&lt; "\r\n";
	cout &lt;&lt; "| " &lt;&lt; mksymbol(name, desc, glass, color);
	//printf("|| %s ", mkname(name, glass));
	cout &lt;&lt; "|| " &lt;&lt; mkname(name, glass);
	//printf("|| %s ", mkdesc(name, desc, glass));
	cout &lt;&lt; "|| " &lt;&lt; mkdesc(name, desc, glass);
	//printf("|| %s ", mkcost(gval));
	cout &lt;&lt; "|| " &lt;&lt; mkcost(gval);
	//printf("|| %s ", mkweight(wt));
	cout &lt;&lt; "|| " &lt;&lt; mkweight(wt);
	//printf("|| %s ", mkhard(mohs));
	cout &lt;&lt; "|| " &lt;&lt; mkhard(mohs);
	//printf("|| %s ", mkmaterial(glass));
	cout &lt;&lt; "|| " &lt;&lt; mkmaterial(glass);

	printf("\r\n");
}

void mid(void) {
	cout &lt;&lt; "|-\r\n";
	cout &lt;&lt; "| colspan=7 |\r\n";
}

void post(void) {
	cout &lt;&lt; "|}\r\n";
	cout &lt;&lt; "<!-- End generated table. -->\r\n";
}

int main() {

	pre();

GEM("dilithium crystal", "white",      2,  1, 4500, 15,  5, GEMSTONE, CLR_WHITE),
GEM("diamond", "white",                3,  1, 4000, 15, 10, GEMSTONE, CLR_WHITE),
GEM("ruby", "red",                     4,  1, 3500, 15,  9, GEMSTONE, CLR_RED),
GEM("jacinth", "orange",               3,  1, 3250, 15,  9, GEMSTONE, CLR_ORANGE),
GEM("sapphire", "blue",                4,  1, 3000, 15,  9, GEMSTONE, CLR_BLUE),
GEM("black opal", "black",             3,  1, 2500, 15,  8, GEMSTONE, CLR_BLACK),
GEM("emerald", "green",                5,  1, 2500, 15,  8, GEMSTONE, CLR_GREEN),
GEM("turquoise", "green",              6,  1, 2000, 15,  6, GEMSTONE, CLR_GREEN),
GEM("citrine", "yellow",               4,  1, 1500, 15,  6, GEMSTONE, CLR_YELLOW),
GEM("aquamarine", "green",             6,  1, 1500, 15,  8, GEMSTONE, CLR_GREEN),
GEM("amber", "yellowish brown",        8,  1, 1000, 15,  2, GEMSTONE, CLR_BROWN),
GEM("topaz", "yellowish brown",       10,  1,  900, 15,  8, GEMSTONE, CLR_BROWN),
GEM("jet", "black",                    6,  1,  850, 15,  7, GEMSTONE, CLR_BLACK),
GEM("opal", "white",                  12,  1,  800, 15,  6, GEMSTONE, CLR_WHITE),
GEM("chrysoberyl", "yellow",           8,  1,  700, 15,  5, GEMSTONE, CLR_YELLOW),
GEM("garnet", "red",                  12,  1,  700, 15,  7, GEMSTONE, CLR_RED),
GEM("amethyst", "violet",             14,  1,  600, 15,  7, GEMSTONE, CLR_MAGENTA),
GEM("jasper", "red",                  15,  1,  500, 15,  7, GEMSTONE, CLR_RED),
GEM("fluorite", "violet",             15,  1,  400, 15,  4, GEMSTONE, CLR_MAGENTA),
GEM("obsidian", "black",               9,  1,  200, 15,  6, GEMSTONE, CLR_BLACK),
GEM("agate", "orange",                12,  1,  200, 15,  6, GEMSTONE, CLR_ORANGE),
GEM("jade", "green",                  10,  1,  300, 15,  6, GEMSTONE, CLR_GREEN),

	mid();

GEM("worthless piece of white glass", "white",   77, 1, 0, 6, 5, GLASS, CLR_WHITE),
GEM("worthless piece of blue glass", "blue",     77, 1, 0, 6, 5, GLASS, CLR_BLUE),
GEM("worthless piece of red glass", "red",       77, 1, 0, 6, 5, GLASS, CLR_RED),
GEM("worthless piece of yellowish brown glass", "yellowish brown", 77, 1, 0, 6, 5, GLASS, CLR_BROWN),
GEM("worthless piece of orange glass", "orange", 76, 1, 0, 6, 5, GLASS, CLR_ORANGE),
GEM("worthless piece of yellow glass", "yellow", 77, 1, 0, 6, 5, GLASS, CLR_YELLOW),
GEM("worthless piece of black glass",  "black",  76, 1, 0, 6, 5, GLASS, CLR_BLACK),
GEM("worthless piece of green glass", "green",   77, 1, 0, 6, 5, GLASS, CLR_GREEN),
GEM("worthless piece of violet glass", "violet", 77, 1, 0, 6, 5, GLASS, CLR_MAGENTA),

	mid();

ROCK("luckstone", "gray",	0, 10,  10, 60, 3, 3, 1, 10, 7, MINERAL, CLR_GRAY),
ROCK("loadstone", "gray",	0, 10, 500,  1, 3, 3, 1, 10, 6, MINERAL, CLR_GRAY),
ROCK("touchstone", "gray",	0,  8,  10, 45, 3, 3, 1, 10, 6, MINERAL, CLR_GRAY),
ROCK("flint", "gray",		0, 10,  10,  1, 6, 6, 0, 10, 7, MINERAL, CLR_GRAY),
ROCK("rock", (char *)0,		1,100,  10,  0, 3, 3, 0, 10, 7, MINERAL, CLR_GRAY),

	post();
}

Contents

1 Loadstone a pun by devteam?
2 Worthless gems and pricing?
3 Striking
4 notes for refactoring
5 Throwing at cross-aligned unicorns
6 Unidentified sell price column

Loadstone a pun by devteam?
Loadstones existed in early editions of D&amp;D.

Worthless gems and pricing?
Anyone know what's up with [this?]

Pricing of gems in shops has been changed since that spoiler was written. The other parts are still up to date, however. -Tjr 18:07, February 11, 2010 (UTC)
Striking
Will gems shatter if shot by striking (like crystal plate mail does)? --AileTheAlien 14:54, 29 April 2011 (UTC)

No.  It used to be that worthless gems, being made of glass, would, but this was fixed a long time ago.  The problem was it provided an easy way to identify valuable gems (see kickboxing). -Ion frigate 20:11, 29 April 2011 (UTC)
notes for refactoring
gem prices aren't random, they just look random to the uninitiated.

Throwing at cross-aligned unicorns
This seems like a bad idea.  Random luck adjustment means you're likely to lower your luck if you have maxed it, or have a decent chance of making it negative if you haven't.  It seems like it'd be a much better idea to simply throw the gems at a coaligned unicorn, and then use a pet to kill it if when you want your gems back.  A well-trained warhorse is more than a match for one. -Ion frigate 01:53, 30 September 2011 (UTC)

I've never bothered since the expected luck gain is 0 and there's no readily available way to see what the result was. However if you know you have 0 base luck and a blessed luckstone you can safely do this. Bad luck will time out while good luck will not, so as long as you can wait for the potentially bad luck to time out you have a chance to get a small increase to luck with little risk. You can even recover the gems directly if you're strong enough, as you won't have to worry about a luck penalty for killing it. -- Qazmlpok 02:04, 30 September 2011 (UTC)
IMHO the only reason it should be mentioned at all is completeness. --Tjr 03:08, 30 September 2011 (UTC)
Unidentified sell price column
The unidentified sell price column is out of date because it hasn't been updated since 3.4.3 and nobody really cares about this esoteric mechanic enough to calculate and update the prices.  The code that determines the sell price is in [1], but the actual values depend on the object type ids from onames.h, which are generated by makedefs and depend on the number of objects defined before the gems, which probably also depends on the particular compilation flags (some objects like scroll of mail precede the gems and are conditionally defined).  This could probably be done using a template to calculate the values given, and the value of the first defined gem (DILITHIUM_CRYSTAL) in onames.h should be given to allow readers to verify it.  Alternatively, the column could be removed for being a nightmare to maintain while not being very useful (and replaced by a mention and a source code reference), and somebody who cares enough could make an external web page or something that we could link to, whcih would calculate the sell prices, using as input the value of DILITHIUM_CRYSTAL in onames.h. Cathartes (talk) 03:27, 15 April 2022 (UTC)
↑ src/shk.c in NetHack 3.6.6, line 2340

</sstream></cstdlib></iostream></string>