Difference between revisions of "NetHackWiki:Skill table generator"
Jump to navigation
Jump to search
(here's my table-generating program) |
(now supports skill-specific and role-specific tables) |
||
Line 4: | Line 4: | ||
#include <string> | #include <string> | ||
#include <iostream> | #include <iostream> | ||
+ | #include <cctype> | ||
using std::string; | using std::string; | ||
using std::cout; | using std::cout; | ||
using std::endl; | using std::endl; | ||
+ | using std::toupper; | ||
typedef int Skill; | typedef int Skill; | ||
Line 62: | Line 64: | ||
const Skill P_FIRST_COMBAT = P_BARE_HANDED_COMBAT; | const Skill P_FIRST_COMBAT = P_BARE_HANDED_COMBAT; | ||
const Skill P_LAST_COMBAT = P_RIDING; | const Skill P_LAST_COMBAT = P_RIDING; | ||
+ | |||
+ | const Skill P_FIRST = P_DAGGER; | ||
+ | const Skill P_LAST = P_RIDING; | ||
const Skill P_NONE = 0; | const Skill P_NONE = 0; | ||
Line 126: | Line 131: | ||
const string | const string | ||
− | skill_full_name(Skill s) { | + | init_cap(const string &c) { |
+ | string s(c); | ||
+ | |||
+ | string::iterator i = s.begin(); | ||
+ | |||
+ | if (i) { *i = toupper(*i); } | ||
+ | |||
+ | return s; | ||
+ | } | ||
+ | |||
+ | const string | ||
+ | skill_full_name(const Skill &s) { | ||
if (P_FIRST_WEAPON <= s && s <= P_LAST_WEAPON) { | if (P_FIRST_WEAPON <= s && s <= P_LAST_WEAPON) { | ||
return skill_raw_name(s) + string(" skill"); | return skill_raw_name(s) + string(" skill"); | ||
Line 139: | Line 155: | ||
const char * | const char * | ||
− | level_char(Level l) { | + | level_char(const Level &l) { |
switch (l) { | switch (l) { | ||
case P_RESTRICTED: return "-"; | case P_RESTRICTED: return "-"; | ||
Line 147: | Line 163: | ||
case P_MASTER: return "'''''M'''''"; | case P_MASTER: return "'''''M'''''"; | ||
case P_GRAND_MASTER: return "'''''GM'''''"; | case P_GRAND_MASTER: return "'''''GM'''''"; | ||
+ | default: return "???"; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | const char * | ||
+ | level_full(const Level &l) { | ||
+ | switch (l) { | ||
+ | case P_RESTRICTED: return "''(restricted)''"; | ||
+ | case P_BASIC: return "Basic"; | ||
+ | case P_SKILLED: return "Skilled"; | ||
+ | case P_EXPERT: return "Expert"; | ||
+ | case P_MASTER: return "Master"; | ||
+ | case P_GRAND_MASTER: return "Grand Master"; | ||
default: return "???"; | default: return "???"; | ||
} | } | ||
Line 182: | Line 211: | ||
{ "Wizard", "Wiz", Skill_W }, | { "Wizard", "Wiz", Skill_W }, | ||
}; | }; | ||
+ | |||
+ | bool | ||
+ | is_restricted(const Role &r, const Skill &s) { | ||
+ | for (const def_skill *sp = r.skills; sp->skill != P_NONE; ++sp) { | ||
+ | if (sp->skill == s) { | ||
+ | return false; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | return true; | ||
+ | } | ||
void | void | ||
Line 206: | Line 246: | ||
cout << level_char(P_RESTRICTED); | cout << level_char(P_RESTRICTED); | ||
+ | } | ||
+ | |||
+ | void | ||
+ | print_role_skill_level_full(const Role &r, const Skill &s) { | ||
+ | for (const def_skill *sp = r.skills; sp->skill != P_NONE; ++sp) { | ||
+ | if (sp->skill == s) { | ||
+ | cout << level_full(sp->level); | ||
+ | return; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | cout << level_full(P_RESTRICTED); | ||
+ | } | ||
+ | |||
+ | void | ||
+ | print_warning(void) { | ||
+ | cout << "<!-- GENERATED PAGE; DO NOT EDIT DIRECTLY -->" << endl; | ||
+ | } | ||
+ | |||
+ | void | ||
+ | print_noinclude(void) { | ||
+ | cout << "<noinclude>" << endl; | ||
+ | |||
+ | cout << | ||
+ | "This page was generated using [[Wikihack:Skill table generator]]. " | ||
+ | "Instead of editing this page, edit that program, and re-generate " | ||
+ | "this page." | ||
+ | << "</noinclude>" << endl; | ||
+ | } | ||
+ | |||
+ | void | ||
+ | print_skill_link(const Skill &s) { | ||
+ | cout << "[[" << skill_full_name(s) | ||
+ | << "|" << skill_raw_name(s) << "]]"; | ||
+ | } | ||
+ | |||
+ | void | ||
+ | print_role_skills(const Role &r, const Skill &first, const Skill &last) { | ||
+ | for (Skill s = first; s <= last; ++s) { | ||
+ | if (is_restricted(r, s)) { continue; } | ||
+ | |||
+ | cout << "|-" << endl; | ||
+ | cout << "| "; | ||
+ | |||
+ | print_skill_link(s); | ||
+ | |||
+ | cout << " || "; | ||
+ | print_role_skill_level_full(r, s); | ||
+ | cout << endl; | ||
+ | } | ||
} | } | ||
void | void | ||
do_skill_table(const Skill &first, const Skill &last) { | do_skill_table(const Skill &first, const Skill &last) { | ||
− | + | print_warning(); | |
cout << "{| class=\"prettytable\"" << endl; | cout << "{| class=\"prettytable\"" << endl; | ||
Line 226: | Line 316: | ||
cout << "|"; | cout << "|"; | ||
− | + | print_skill_link(s); | |
− | + | ||
− | |||
for (int i = 0; i < NUM_ROLES; i++) { | for (int i = 0; i < NUM_ROLES; i++) { | ||
const Role &r = ROLES[i]; | const Role &r = ROLES[i]; | ||
Line 240: | Line 329: | ||
} | } | ||
− | cout << "|}" | + | cout << "|}"; |
+ | |||
+ | print_noinclude(); | ||
} | } | ||
+ | void | ||
+ | do_role_skill_table(const Role &r) { | ||
+ | print_warning(); | ||
+ | |||
+ | cout << "{| class=\"prettytable\"" << endl; | ||
+ | |||
+ | cout << "! colspan=\"2\" style=\"font-size:larger\" | " | ||
+ | << r.long_name << " skills" << endl; | ||
+ | |||
+ | cout << "|-" << endl; | ||
+ | cout << "! Skill !! Maximum level" << endl; | ||
+ | |||
+ | cout << "|-" << endl; | ||
+ | cout << "| colspan=\"2\" align=\"center\" | ''Weapon skills''" << endl; | ||
+ | |||
+ | print_role_skills(r, P_FIRST_WEAPON, P_LAST_WEAPON); | ||
+ | |||
+ | cout << "|-" << endl; | ||
+ | cout << "| colspan=\"2\" align=\"center\" | ''Combat skills''" << endl; | ||
+ | |||
+ | print_role_skills(r, P_FIRST_COMBAT, P_LAST_COMBAT); | ||
+ | |||
+ | cout << "|-" << endl; | ||
+ | cout << "| colspan=\"2\" align=\"center\" | ''Spell skills''" << endl; | ||
+ | |||
+ | print_role_skills(r, P_FIRST_SPELL, P_LAST_SPELL); | ||
+ | |||
+ | cout << "|}"; | ||
+ | |||
+ | print_noinclude(); | ||
+ | } | ||
+ | |||
+ | void | ||
+ | do_skill_role_table(const Skill &s) { | ||
+ | print_warning(); | ||
+ | |||
+ | cout << "{| class=\"prettytable\"" << endl; | ||
+ | |||
+ | cout << "! colspan=\"2\" style=\"font-size:larger\" | " | ||
+ | << init_cap(skill_full_name(s)) << endl; | ||
+ | |||
+ | cout << "|-" << endl; | ||
+ | cout << "! Role !! Maximum level" << endl; | ||
+ | |||
+ | for (int i = 0; i < NUM_ROLES; ++i) { | ||
+ | const Role &r = ROLES[i]; | ||
+ | |||
+ | if (is_restricted(r, s)) { continue; } | ||
+ | |||
+ | cout << "|-" << endl; | ||
+ | cout << "| [[" << r.long_name << "]]"; | ||
+ | cout << " || "; | ||
+ | print_role_skill_level_full(r, s); | ||
+ | cout << endl; | ||
+ | } | ||
+ | |||
+ | cout << "|}"; | ||
+ | |||
+ | print_noinclude(); | ||
+ | } | ||
void | void | ||
print_usage(const char *name) { | print_usage(const char *name) { | ||
cout << "Usage:" << endl; | cout << "Usage:" << endl; | ||
− | cout << " " << name << " weapon" << endl; | + | cout << " " << name << " weapon|combat|spell" << endl; |
− | cout << " " << name << " | + | cout << " " << name << " {Role}|{Rol}" << endl; |
− | cout << " " << name << " | + | cout << " " << name << " {Skill}" << endl; |
} | } | ||
Line 264: | Line 415: | ||
do_skill_table(P_FIRST_SPELL, P_LAST_SPELL); | do_skill_table(P_FIRST_SPELL, P_LAST_SPELL); | ||
} else { | } else { | ||
+ | for (int i = 0; i < NUM_ROLES; ++i) { | ||
+ | const Role &r = ROLES[i]; | ||
+ | if (arg == r.long_name || arg == r.short_name) { | ||
+ | do_role_skill_table(r); | ||
+ | exit(0); | ||
+ | } | ||
+ | } | ||
+ | for (Skill s = P_FIRST; s <= P_LAST; ++s) { | ||
+ | if (arg == skill_raw_name(s)) { | ||
+ | do_skill_role_table(s); | ||
+ | exit(0); | ||
+ | } | ||
+ | } | ||
print_usage(argv[0]); | print_usage(argv[0]); | ||
} | } |
Revision as of 05:26, 4 November 2006
Here's the program I used to generate Template:Weapon skill table, Template:Combat skill table, and Template:Spell skill table. u_init_snippet.inc
should be the struct def_skill
definitions in u_init.c, from Skill_A[]
to Skill_W[]
. -- Killian 04:36, 4 November 2006 (UTC)
#include <string> #include <iostream> #include <cctype> using std::string; using std::cout; using std::endl; using std::toupper; typedef int Skill; const Skill P_DAGGER = 1; const Skill P_KNIFE = 2; const Skill P_AXE = 3; const Skill P_PICK_AXE = 4; const Skill P_SHORT_SWORD = 5; const Skill P_BROAD_SWORD = 6; const Skill P_LONG_SWORD = 7; const Skill P_TWO_HANDED_SWORD = 8; const Skill P_SCIMITAR = 9; const Skill P_SABER = 10; const Skill P_CLUB = 11; const Skill P_MACE = 12; const Skill P_MORNING_STAR = 13; const Skill P_FLAIL = 14; const Skill P_HAMMER = 15; const Skill P_QUARTERSTAFF = 16; const Skill P_POLEARMS = 17; const Skill P_SPEAR = 18; const Skill P_JAVELIN = 19; const Skill P_TRIDENT = 20; const Skill P_LANCE = 21; const Skill P_BOW = 22; const Skill P_SLING = 23; const Skill P_CROSSBOW = 24; const Skill P_DART = 25; const Skill P_SHURIKEN = 26; const Skill P_BOOMERANG = 27; const Skill P_WHIP = 28; const Skill P_UNICORN_HORN = 29; const Skill P_FIRST_WEAPON = P_DAGGER; const Skill P_LAST_WEAPON = P_UNICORN_HORN; const Skill P_ATTACK_SPELL = 30; const Skill P_HEALING_SPELL = 31; const Skill P_DIVINATION_SPELL = 32; const Skill P_ENCHANTMENT_SPELL = 33; const Skill P_CLERIC_SPELL = 34; const Skill P_ESCAPE_SPELL = 35; const Skill P_MATTER_SPELL = 36; const Skill P_FIRST_SPELL = P_ATTACK_SPELL; const Skill P_LAST_SPELL = P_MATTER_SPELL; const Skill P_BARE_HANDED_COMBAT = 37; const Skill P_MARTIAL_ARTS = 38; const Skill P_TWO_WEAPON_COMBAT = 39; const Skill P_RIDING = 40; const Skill P_FIRST_COMBAT = P_BARE_HANDED_COMBAT; const Skill P_LAST_COMBAT = P_RIDING; const Skill P_FIRST = P_DAGGER; const Skill P_LAST = P_RIDING; const Skill P_NONE = 0; typedef int Level; const Level P_RESTRICTED = 0; const Level P_BASIC = 1; const Level P_SKILLED = 2; const Level P_EXPERT = 3; const Level P_MASTER = 4; const Level P_GRAND_MASTER = 5; const char * skill_raw_name(Skill s) { switch (s) { case P_DAGGER: return "dagger"; case P_KNIFE: return "knife"; case P_AXE: return "axe"; case P_PICK_AXE: return "pick-axe"; case P_SHORT_SWORD: return "short sword"; case P_BROAD_SWORD: return "broad sword"; case P_LONG_SWORD: return "long sword"; case P_TWO_HANDED_SWORD: return "two-handed sword"; case P_SCIMITAR: return "scimitar"; case P_SABER: return "saber"; case P_CLUB: return "club"; case P_MACE: return "mace"; case P_MORNING_STAR: return "morning star"; case P_FLAIL: return "flail"; case P_HAMMER: return "hammer"; case P_QUARTERSTAFF: return "quarterstaff"; case P_POLEARMS: return "polearms"; case P_SPEAR: return "spear"; case P_JAVELIN: return "javelin"; case P_TRIDENT: return "trident"; case P_LANCE: return "lance"; case P_BOW: return "bow"; case P_SLING: return "sling"; case P_CROSSBOW: return "crossbow"; case P_DART: return "dart"; case P_SHURIKEN: return "shuriken"; case P_BOOMERANG: return "boomerang"; case P_WHIP: return "whip"; case P_UNICORN_HORN: return "unicorn horn"; case P_ATTACK_SPELL: return "attack"; case P_HEALING_SPELL: return "healing"; case P_DIVINATION_SPELL: return "divination"; case P_ENCHANTMENT_SPELL: return "enchantment"; case P_CLERIC_SPELL: return "clerical"; case P_ESCAPE_SPELL: return "escape"; case P_MATTER_SPELL: return "matter"; case P_BARE_HANDED_COMBAT: return "bare hands"; case P_MARTIAL_ARTS: return "martial arts"; case P_TWO_WEAPON_COMBAT: return "two weapon combat"; case P_RIDING: return "riding"; default: return "<STRANGE SKILL>"; } } const string init_cap(const string &c) { string s(c); string::iterator i = s.begin(); if (i) { *i = toupper(*i); } return s; } const string skill_full_name(const Skill &s) { if (P_FIRST_WEAPON <= s && s <= P_LAST_WEAPON) { return skill_raw_name(s) + string(" skill"); } if (P_FIRST_SPELL <= s && s <= P_LAST_SPELL) { return skill_raw_name(s) + string(" spells"); } return string(skill_raw_name(s)); } const char * level_char(const Level &l) { switch (l) { case P_RESTRICTED: return "-"; case P_BASIC: return "b"; case P_SKILLED: return "S"; case P_EXPERT: return "E"; case P_MASTER: return "M"; case P_GRAND_MASTER: return "GM"; default: return "???"; } } const char * level_full(const Level &l) { switch (l) { case P_RESTRICTED: return "(restricted)"; case P_BASIC: return "Basic"; case P_SKILLED: return "Skilled"; case P_EXPERT: return "Expert"; case P_MASTER: return "Master"; case P_GRAND_MASTER: return "Grand Master"; default: return "???"; } } struct def_skill { Skill skill; Level level; }; struct Role { const char *long_name; const char *short_name; const def_skill *skills; }; #define STEED #define TOURIST #include "u_init_snippet.inc" const int NUM_ROLES = 13; const Role ROLES[NUM_ROLES] = { { "Archeologist", "Arc", Skill_A }, { "Barbarian", "Bar", Skill_B }, { "Caveman", "Cav", Skill_C }, { "Healer", "Hea", Skill_H }, { "Knight", "Kni", Skill_K }, { "Monk", "Mon", Skill_Mon }, { "Priest", "Pri", Skill_P }, { "Rogue", "Rog", Skill_R }, { "Ranger", "Ran", Skill_Ran }, { "Samurai", "Sam", Skill_S }, { "Tourist", "Tou", Skill_T }, { "Valkyrie", "Val", Skill_V }, { "Wizard", "Wiz", Skill_W }, }; bool is_restricted(const Role &r, const Skill &s) { for (const def_skill *sp = r.skills; sp->skill != P_NONE; ++sp) { if (sp->skill == s) { return false; } } return true; } void print_header(void) { cout << "! Skill \\ Role"; for (int i = 0; i < NUM_ROLES; i++) { const Role &r = ROLES[i]; cout << " !! [[" << r.long_name << "|" << r.short_name << "]]"; } cout << endl; } void print_role_skill_level(const Role &r, const Skill &s) { for (const def_skill *sp = r.skills; sp->skill != P_NONE; ++sp) { if (sp->skill == s) { cout << level_char(sp->level); return; } } cout << level_char(P_RESTRICTED); } void print_role_skill_level_full(const Role &r, const Skill &s) { for (const def_skill *sp = r.skills; sp->skill != P_NONE; ++sp) { if (sp->skill == s) { cout << level_full(sp->level); return; } } cout << level_full(P_RESTRICTED); } void print_warning(void) { cout << "" << endl; } void print_noinclude(void) { cout << "" << endl; cout << "This page was generated using Wikihack:Skill table generator. " "Instead of editing this page, edit that program, and re-generate " "this page." << "" << endl; } void print_skill_link(const Skill &s) { cout << "[[" << skill_full_name(s) << "|" << skill_raw_name(s) << "]]"; } void print_role_skills(const Role &r, const Skill &first, const Skill &last) { for (Skill s = first; s <= last; ++s) { if (is_restricted(r, s)) { continue; } cout << "|-" << endl; cout << "| "; print_skill_link(s); cout << " || "; print_role_skill_level_full(r, s); cout << endl; } } void do_skill_table(const Skill &first, const Skill &last) { print_warning(); cout << "{| class=\"prettytable\"" << endl; print_header(); for (Skill s = first; s <= last; ++s) { if (s == (P_LAST_WEAPON/2 + 1)) { cout << "|-" << endl; print_header(); } cout << "|-" << endl; cout << "|"; print_skill_link(s); for (int i = 0; i < NUM_ROLES; i++) { const Role &r = ROLES[i]; cout << " || "; print_role_skill_level(r, s); } cout << endl; } cout << "|}"; print_noinclude(); } void do_role_skill_table(const Role &r) { print_warning(); cout << "{| class=\"prettytable\"" << endl; cout << "! colspan=\"2\" style=\"font-size:larger\" | " << r.long_name << " skills" << endl; cout << "|-" << endl; cout << "! Skill !! Maximum level" << endl; cout << "|-" << endl; cout << "| colspan=\"2\" align=\"center\" | Weapon skills" << endl; print_role_skills(r, P_FIRST_WEAPON, P_LAST_WEAPON); cout << "|-" << endl; cout << "| colspan=\"2\" align=\"center\" | Combat skills" << endl; print_role_skills(r, P_FIRST_COMBAT, P_LAST_COMBAT); cout << "|-" << endl; cout << "| colspan=\"2\" align=\"center\" | Spell skills" << endl; print_role_skills(r, P_FIRST_SPELL, P_LAST_SPELL); cout << "|}"; print_noinclude(); } void do_skill_role_table(const Skill &s) { print_warning(); cout << "{| class=\"prettytable\"" << endl; cout << "! colspan=\"2\" style=\"font-size:larger\" | " << init_cap(skill_full_name(s)) << endl; cout << "|-" << endl; cout << "! Role !! Maximum level" << endl; for (int i = 0; i < NUM_ROLES; ++i) { const Role &r = ROLES[i]; if (is_restricted(r, s)) { continue; } cout << "|-" << endl; cout << "| [[" << r.long_name << "]]"; cout << " || "; print_role_skill_level_full(r, s); cout << endl; } cout << "|}"; print_noinclude(); } void print_usage(const char *name) { cout << "Usage:" << endl; cout << " " << name << " weapon|combat|spell" << endl; cout << " " << name << " {Role}|{Rol}" << endl; cout << " " << name << " {Skill}" << endl; } int main(int argc, const char **argv) { if (argc == 2) { const string arg(argv[1]); if (arg == "weapon") { do_skill_table(P_FIRST_WEAPON, P_LAST_WEAPON); } else if (arg == "combat") { do_skill_table(P_FIRST_COMBAT, P_LAST_COMBAT); } else if (arg == "spell") { do_skill_table(P_FIRST_SPELL, P_LAST_SPELL); } else { for (int i = 0; i < NUM_ROLES; ++i) { const Role &r = ROLES[i]; if (arg == r.long_name || arg == r.short_name) { do_role_skill_table(r); exit(0); } } for (Skill s = P_FIRST; s <= P_LAST; ++s) { if (arg == skill_raw_name(s)) { do_skill_role_table(s); exit(0); } } print_usage(argv[0]); } } else { print_usage(argv[0]); } }