From 5389ec05ada690e3fb34ecf2799f8cd8701f576e Mon Sep 17 00:00:00 2001 From: Quietust Date: Sat, 4 Jan 2025 22:05:33 -0600 Subject: [PATCH] add Translation::GenerateName() (fixes #5166) Also available from Lua as "dfhack.generateName(...)" --- docs/changelog.txt | 2 + docs/dev/Lua API.rst | 4 + library/LuaApi.cpp | 2 + library/include/Types.h | 1 + library/include/modules/Translation.h | 3 + library/modules/Translation.cpp | 438 ++++++++++++++++++++++++++ plugins/strangemood.cpp | 140 +------- 7 files changed, 453 insertions(+), 137 deletions(-) diff --git a/docs/changelog.txt b/docs/changelog.txt index df35659e69..385012c6a8 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -54,6 +54,7 @@ Template for new versions: ## New Tools ## New Features +- ``Translation::GenerateName``: generates in-game names, reimplemented based on DF's own logic. Also available in Lua as "dfhack.GenerateName". - `stockpiles`: add simple import/export dialogs to stockpile overlay panel ## Fixes @@ -66,6 +67,7 @@ Template for new versions: ## Misc Improvements - `strangemood`: add ability to choose Stone Cutting and Stone Carving as the mood skill - `suspendmanager`: add more specific messages for submerged jobsites and those managed by `buildingplan` +- `strangemood`: moved name generation logic into Translation module (and fixed some bugs) ## Documentation - Added example code for creating plugin RPC endpoints that can be used to extend the DFHack API diff --git a/docs/dev/Lua API.rst b/docs/dev/Lua API.rst index a3c94550f8..5e71e3dea6 100644 --- a/docs/dev/Lua API.rst +++ b/docs/dev/Lua API.rst @@ -953,6 +953,10 @@ can be omitted. Convert a ``df.language_name`` (or only the last name part) to string. +* ``dfhack.GenerateName(name,language,type,major_selector,minor_selector)`` + + Dynamically generate a name using the same logic the game itself uses. + * ``dfhack.df2utf(string)`` Convert a string from DF's CP437 encoding to UTF-8. diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index a5225c57c8..9d20fcc111 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -88,6 +88,7 @@ distribution. #include "df/job.h" #include "df/job_item.h" #include "df/job_material_category.h" +#include "df/language_word_table.h" #include "df/material.h" #include "df/map_block.h" #include "df/nemesis_record.h" @@ -1374,6 +1375,7 @@ static const LuaWrapper::FunctionReg dfhack_module[] = { WRAP(isMapLoaded), WRAP(isSiteLoaded), WRAPM(Translation, TranslateName), + WRAPM(Translation, GenerateName), WRAP(df2utf), WRAP(utf2df), WRAP(df2console), diff --git a/library/include/Types.h b/library/include/Types.h index 337d4bcaef..53b6aee18a 100644 --- a/library/include/Types.h +++ b/library/include/Types.h @@ -33,6 +33,7 @@ distribution. #include "df/general_ref_type.h" #include "df/specific_ref_type.h" +#include "df/language_name_type.h" namespace df { struct building; diff --git a/library/include/modules/Translation.h b/library/include/modules/Translation.h index 8de74e71d7..f0371c1c0c 100644 --- a/library/include/modules/Translation.h +++ b/library/include/modules/Translation.h @@ -38,6 +38,7 @@ distribution. namespace df { struct language_name; struct language_translation; + struct language_word_table; } namespace DFHack @@ -58,6 +59,8 @@ DFHACK_EXPORT std::string capitalize(const std::string &str, bool all_words = fa // translate a name using the loaded dictionaries DFHACK_EXPORT std::string TranslateName (const df::language_name * name, bool inEnglish = false, bool onlyLastPart = false); + +DFHACK_EXPORT void GenerateName(df::language_name *name, int language_index, df::language_name_type nametype, df::language_word_table *major_selector, df::language_word_table *minor_selector); } } #endif diff --git a/library/modules/Translation.cpp b/library/modules/Translation.cpp index e10587938b..85463220ac 100644 --- a/library/modules/Translation.cpp +++ b/library/modules/Translation.cpp @@ -33,11 +33,14 @@ distribution. #include "DataDefs.h" #include "modules/Translation.h" +#include "modules/Random.h" #include "df/d_init.h" #include "df/language_name.h" #include "df/language_translation.h" #include "df/language_word.h" +#include "df/language_name_component.h" +#include "df/language_word_table_index.h" #include "df/world.h" #include @@ -255,3 +258,438 @@ string Translation::TranslateName(const df::language_name * name, bool inEnglish return out; } + +Random::MersenneRNG rng; +bool rng_inited = false; +// void word_selectorst::choose_word(int32_t &index,short &asp,WordPlace place) +void ChooseWord (const df::language_word_table *table, int32_t &index, df::part_of_speech &asp, df::language_word_table_index place) +{ + if (table->parts[place].size()) + { + int offset = rng.df_trandom(table->parts[place].size()); + index = table->words[place][offset]; + asp = table->parts[place][offset]; + } + else + { + index = rng.df_trandom(world->raws.language.words.size()); + asp = (df::part_of_speech)(rng.df_trandom(9)); + Core::getInstance().getConsole().printerr("Impoverished Word Selector"); + } +} + +// void generatename(namest &name,int32_t language_index,short nametype,word_selectorst &major_selector,word_selectorst &minor_selector) +void Translation::GenerateName(df::language_name *name, int language_index, df::language_name_type nametype, df::language_word_table *major_selector, df::language_word_table *minor_selector) +{ + CHECK_NULL_POINTER(name); + CHECK_NULL_POINTER(major_selector); + CHECK_NULL_POINTER(minor_selector); + if (!rng_inited) + { + rng.init(); + rng_inited = true; + } + for (int i = 0; i < 100; i++) + { + if ((nametype != language_name_type::LegendaryFigure) && (nametype != language_name_type::FigureNoFirst)) + { + *name = df::language_name(); + if (language_index == -1) + language_index = rng.df_trandom(world->raws.language.translations.size()); + name->type = nametype; + name->language = language_index; + } + name->has_name = 1; + if (name->language == -1) + name->language = rng.df_trandom(world->raws.language.translations.size()); + + int r; // persistent random number for various cases + switch (nametype) + { + case language_name_type::Figure: + case language_name_type::FigureNoFirst: + case language_name_type::FigureFirstOnly: + case language_name_type::TrueName: + if (nametype != language_name_type::FigureNoFirst) + { + name->first_name = ""; + int32_t index; + df::part_of_speech asp; + ChooseWord(major_selector, index, asp, language_word_table_index::FirstName); + // language_handlerst::addnativesyllable(index, name->first_name, name->language) + if (name->language >= 0 && (size_t)name->language < world->raws.language.translations.size()) + { + auto trans = world->raws.language.translations[name->language]; + if (index >= 0 && (size_t)index < trans->words.size()) + name->first_name.append(trans->words[index]->c_str()); + } + } + if (nametype != language_name_type::FigureFirstOnly) + { + switch (rng.df_trandom(2)) + { + case 0: + ChooseWord(major_selector, name->words[language_name_component::FrontCompound], name->parts_of_speech[language_name_component::FrontCompound], language_word_table_index::FrontCompound); + ChooseWord(minor_selector, name->words[language_name_component::RearCompound], name->parts_of_speech[language_name_component::RearCompound], language_word_table_index::RearCompound); + break; + case 1: + ChooseWord(minor_selector, name->words[language_name_component::FrontCompound], name->parts_of_speech[language_name_component::FrontCompound], language_word_table_index::FrontCompound); + ChooseWord(major_selector, name->words[language_name_component::RearCompound], name->parts_of_speech[language_name_component::RearCompound], language_word_table_index::RearCompound); + break; + } + } + break; + case language_name_type::Artifact: + case language_name_type::ElfTree: + case language_name_type::River: + r = rng.df_trandom(3); + if (r < 2) + { + switch (rng.df_trandom(2)) + { + case 0: + ChooseWord(major_selector, name->words[language_name_component::FrontCompound], name->parts_of_speech[language_name_component::FrontCompound], language_word_table_index::FrontCompound); + ChooseWord(minor_selector, name->words[language_name_component::RearCompound], name->parts_of_speech[language_name_component::RearCompound], language_word_table_index::RearCompound); + break; + case 1: + ChooseWord(minor_selector, name->words[language_name_component::FrontCompound], name->parts_of_speech[language_name_component::FrontCompound], language_word_table_index::FrontCompound); + ChooseWord(major_selector, name->words[language_name_component::RearCompound], name->parts_of_speech[language_name_component::RearCompound], language_word_table_index::RearCompound); + break; + } + } + if (r == 0) + break; + // fall through if r > 0 + case language_name_type::LegendaryFigure: + // if it was this specific type, 1/3 chance to just pick an Adjective and then bail out + // 40d didn't appear to have this logic + if (nametype == language_name_type::LegendaryFigure && !rng.df_trandom(3)) + { + ChooseWord(major_selector, name->words[language_name_component::FirstAdjective], name->parts_of_speech[language_name_component::FirstAdjective], language_word_table_index::Adjectives); + break; + } + // fall through + case language_name_type::ArtImage: + r = rng.df_trandom(2); + ChooseWord(r ? major_selector : minor_selector, name->words[language_name_component::TheX], name->parts_of_speech[language_name_component::TheX], language_word_table_index::FirstName); + + switch (rng.df_trandom(50) ? rng.df_trandom(2) : rng.df_trandom(3)) + { + case 0: + ChooseWord(r ? minor_selector : major_selector, name->words[language_name_component::OfX], name->parts_of_speech[language_name_component::OfX], language_word_table_index::OfX); + break; + case 2: + ChooseWord(r ? minor_selector : major_selector, name->words[language_name_component::OfX], name->parts_of_speech[language_name_component::OfX], language_word_table_index::OfX); + r = rng.df_trandom(2); + // fall through + case 1: + ChooseWord(r ? minor_selector : major_selector, name->words[language_name_component::FirstAdjective], name->parts_of_speech[language_name_component::FirstAdjective], language_word_table_index::Adjectives); + if (!rng.df_trandom(100)) + ChooseWord(r ? minor_selector : major_selector, name->words[language_name_component::SecondAdjective], name->parts_of_speech[language_name_component::SecondAdjective], language_word_table_index::Adjectives); + break; + } + if (!rng.df_trandom(100)) + { + r = rng.df_trandom(2); + ChooseWord(r ? minor_selector : major_selector, name->words[language_name_component::HyphenCompound], name->parts_of_speech[language_name_component::HyphenCompound], language_word_table_index::TheX); + } + break; + case language_name_type::Civilization: + case language_name_type::World: + case language_name_type::Region: + case language_name_type::EntitySite: + case language_name_type::NomadicGroup: + case language_name_type::MigratingGroup: + case language_name_type::Vessel: + case language_name_type::MilitaryUnit: + case language_name_type::Religion: + case language_name_type::MountainPeak: + case language_name_type::Temple: + case language_name_type::Keep: + case language_name_type::MeadHall: + case language_name_type::CraftStore: + case language_name_type::WeaponStore: + case language_name_type::ArmorStore: + case language_name_type::GeneralStore: + case language_name_type::FoodStore: + case language_name_type::War: + case language_name_type::Battle: + case language_name_type::Siege: + case language_name_type::Road: + case language_name_type::Wall: + case language_name_type::Bridge: + case language_name_type::Tunnel: + case language_name_type::HighPriest: + case language_name_type::Tomb: + case language_name_type::OutcastGroup: + case language_name_type::PerformanceTroupe: + case language_name_type::Library: + case language_name_type::PoeticForm: + case language_name_type::MusicalForm: + case language_name_type::DanceForm: + case language_name_type::Festival: + case language_name_type::CountingHouse: + case language_name_type::Guildhall: + case language_name_type::NecromancerTower: + case language_name_type::Hospital: + ChooseWord(major_selector, name->words[language_name_component::TheX], name->parts_of_speech[language_name_component::TheX], language_word_table_index::FirstName); + + switch (rng.df_trandom(50) ? rng.df_trandom(2) : rng.df_trandom(3)) + { + case 0: + ChooseWord(minor_selector, name->words[language_name_component::OfX], name->parts_of_speech[language_name_component::OfX], language_word_table_index::OfX); + break; + case 2: + ChooseWord(minor_selector, name->words[language_name_component::OfX], name->parts_of_speech[language_name_component::OfX], language_word_table_index::OfX); + // fall through + case 1: + ChooseWord(minor_selector, name->words[language_name_component::FirstAdjective], name->parts_of_speech[language_name_component::FirstAdjective], language_word_table_index::Adjectives); + if (!rng.df_trandom(100)) + ChooseWord(minor_selector, name->words[language_name_component::SecondAdjective], name->parts_of_speech[language_name_component::SecondAdjective], language_word_table_index::Adjectives); + break; + } + if (!rng.df_trandom(100)) + { + r = rng.df_trandom(2); + ChooseWord(minor_selector, name->words[language_name_component::HyphenCompound], name->parts_of_speech[language_name_component::HyphenCompound], language_word_table_index::TheX); + } + break; + case language_name_type::Squad: + r = rng.df_trandom(2); + ChooseWord(r ? major_selector : minor_selector, name->words[language_name_component::TheX], name->parts_of_speech[language_name_component::TheX], language_word_table_index::FirstName); + + switch (rng.df_trandom(50) ? rng.df_trandom(2) : rng.df_trandom(3)) + { + case 0: + ChooseWord(r ? minor_selector : major_selector, name->words[language_name_component::OfX], name->parts_of_speech[language_name_component::OfX], language_word_table_index::OfX); + break; + case 2: + ChooseWord(r ? minor_selector : major_selector, name->words[language_name_component::OfX], name->parts_of_speech[language_name_component::OfX], language_word_table_index::OfX); + r = rng.df_trandom(2); + // fall through + case 1: + ChooseWord(r ? minor_selector : major_selector, name->words[language_name_component::FirstAdjective], name->parts_of_speech[language_name_component::FirstAdjective], language_word_table_index::Adjectives); + if (!rng.df_trandom(100)) + ChooseWord(r ? minor_selector : major_selector, name->words[language_name_component::SecondAdjective], name->parts_of_speech[language_name_component::SecondAdjective], language_word_table_index::Adjectives); + break; + } + if (!rng.df_trandom(100)) + { + r = rng.df_trandom(2); + ChooseWord(r ? minor_selector : major_selector, name->words[language_name_component::HyphenCompound], name->parts_of_speech[language_name_component::HyphenCompound], language_word_table_index::TheX); + } + // If TheX is a singular noun, then switch it to Plural if possible + if (name->parts_of_speech[language_name_component::TheX] == part_of_speech::Noun) + { + int word = name->words[language_name_component::TheX]; + if (word >= 0 && (size_t)word < world->raws.language.words.size() && world->raws.language.words[word]->forms[part_of_speech::NounPlural].length() > 0) + name->parts_of_speech[language_name_component::TheX] = part_of_speech::NounPlural; + } + break; + case language_name_type::Site: + case language_name_type::Monument: + case language_name_type::Vault: + switch (rng.df_trandom(2)) + { + case 0: + ChooseWord(major_selector, name->words[language_name_component::FrontCompound], name->parts_of_speech[language_name_component::FrontCompound], language_word_table_index::FrontCompound); + ChooseWord(minor_selector, name->words[language_name_component::RearCompound], name->parts_of_speech[language_name_component::RearCompound], language_word_table_index::RearCompound); + break; + case 1: + ChooseWord(minor_selector, name->words[language_name_component::FrontCompound], name->parts_of_speech[language_name_component::FrontCompound], language_word_table_index::FrontCompound); + ChooseWord(major_selector, name->words[language_name_component::RearCompound], name->parts_of_speech[language_name_component::RearCompound], language_word_table_index::RearCompound); + break; + } + break; + case language_name_type::Dungeon: + r = rng.df_trandom(3); + if (r < 2) + { + ChooseWord(minor_selector, name->words[language_name_component::FrontCompound], name->parts_of_speech[language_name_component::FrontCompound], language_word_table_index::FrontCompound); + ChooseWord(major_selector, name->words[language_name_component::RearCompound], name->parts_of_speech[language_name_component::RearCompound], language_word_table_index::RearCompound); + } + if (r != 0) + { + ChooseWord((r == 2 || rng.df_trandom(2)) ? major_selector : minor_selector, name->words[language_name_component::TheX], name->parts_of_speech[language_name_component::TheX], language_word_table_index::FirstName); + switch (rng.df_trandom(50) ? rng.df_trandom(2) : rng.df_trandom(3)) + { + case 0: + ChooseWord(minor_selector, name->words[language_name_component::OfX], name->parts_of_speech[language_name_component::OfX], language_word_table_index::OfX); + break; + case 2: + ChooseWord(minor_selector, name->words[language_name_component::OfX], name->parts_of_speech[language_name_component::OfX], language_word_table_index::OfX); + // fall through + case 1: + ChooseWord(minor_selector, name->words[language_name_component::FirstAdjective], name->parts_of_speech[language_name_component::FirstAdjective], language_word_table_index::Adjectives); + if (!rng.df_trandom(100)) + ChooseWord(minor_selector, name->words[language_name_component::SecondAdjective], name->parts_of_speech[language_name_component::SecondAdjective], language_word_table_index::Adjectives); + break; + } + if (!rng.df_trandom(100)) + { + r = rng.df_trandom(2); + ChooseWord(r ? minor_selector : major_selector, name->words[language_name_component::HyphenCompound], name->parts_of_speech[language_name_component::HyphenCompound], language_word_table_index::TheX); + } + } + break; + case language_name_type::FalseIdentity: + if (rng.df_trandom(3)) + { + r = rng.df_trandom(2); + ChooseWord(r ? major_selector : minor_selector, name->words[language_name_component::TheX], name->parts_of_speech[language_name_component::TheX], language_word_table_index::FirstName); + + switch (rng.df_trandom(50) ? rng.df_trandom(2) : rng.df_trandom(3)) + { + case 0: + ChooseWord(r ? minor_selector : major_selector, name->words[language_name_component::OfX], name->parts_of_speech[language_name_component::OfX], language_word_table_index::OfX); + break; + case 2: + ChooseWord(r ? minor_selector : major_selector, name->words[language_name_component::OfX], name->parts_of_speech[language_name_component::OfX], language_word_table_index::OfX); + r = rng.df_trandom(2); + // fall through + case 1: + ChooseWord(r ? minor_selector : major_selector, name->words[language_name_component::FirstAdjective], name->parts_of_speech[language_name_component::FirstAdjective], language_word_table_index::Adjectives); + if (!rng.df_trandom(100)) + ChooseWord(r ? minor_selector : major_selector, name->words[language_name_component::SecondAdjective], name->parts_of_speech[language_name_component::SecondAdjective], language_word_table_index::Adjectives); + break; + } + if (!rng.df_trandom(100)) + { + r = rng.df_trandom(2); + ChooseWord(r ? minor_selector : major_selector, name->words[language_name_component::HyphenCompound], name->parts_of_speech[language_name_component::HyphenCompound], language_word_table_index::TheX); + } + // If TheX is a plural noun, then switch it to singular if possible + if (name->parts_of_speech[language_name_component::TheX] == part_of_speech::NounPlural) + { + int word = name->words[language_name_component::TheX]; + if (word >= 0 && (size_t)word < world->raws.language.words.size() && world->raws.language.words[word]->forms[part_of_speech::Noun].length() > 0) + name->parts_of_speech[language_name_component::TheX] = part_of_speech::Noun; + } + break; + } + if (!rng.df_trandom(2)) + { + switch (rng.df_trandom(2)) + { + case 0: + ChooseWord(major_selector, name->words[language_name_component::FrontCompound], name->parts_of_speech[language_name_component::FrontCompound], language_word_table_index::FrontCompound); + ChooseWord(minor_selector, name->words[language_name_component::RearCompound], name->parts_of_speech[language_name_component::RearCompound], language_word_table_index::RearCompound); + break; + case 1: + ChooseWord(minor_selector, name->words[language_name_component::FrontCompound], name->parts_of_speech[language_name_component::FrontCompound], language_word_table_index::FrontCompound); + ChooseWord(major_selector, name->words[language_name_component::RearCompound], name->parts_of_speech[language_name_component::RearCompound], language_word_table_index::RearCompound); + break; + } + } + else + { + name->first_name = ""; + int32_t index; + df::part_of_speech asp; + ChooseWord(major_selector, index, asp, language_word_table_index::FirstName); + // language_handlerst::addnativesyllable(index, name->first_name, name->language) + if (name->language >= 0 && (size_t)name->language < world->raws.language.translations.size()) + { + auto trans = world->raws.language.translations[name->language]; + if (index >= 0 && (size_t)index < trans->words.size()) + name->first_name.append(trans->words[index]->c_str()); + } + } + ChooseWord(major_selector, name->words[language_name_component::FirstAdjective], name->parts_of_speech[language_name_component::FirstAdjective], language_word_table_index::Adjectives); + break; + case language_name_type::MerchantCompany: + case language_name_type::CraftGuild: + ChooseWord(major_selector, name->words[language_name_component::TheX], name->parts_of_speech[language_name_component::TheX], language_word_table_index::FirstName); + + switch (rng.df_trandom(50) ? rng.df_trandom(2) : rng.df_trandom(3)) + { + case 0: + ChooseWord(minor_selector, name->words[language_name_component::OfX], name->parts_of_speech[language_name_component::OfX], language_word_table_index::OfX); + break; + case 2: + ChooseWord(minor_selector, name->words[language_name_component::OfX], name->parts_of_speech[language_name_component::OfX], language_word_table_index::OfX); + r = rng.df_trandom(2); + // fall through + case 1: + ChooseWord(minor_selector, name->words[language_name_component::FirstAdjective], name->parts_of_speech[language_name_component::FirstAdjective], language_word_table_index::Adjectives); + if (!rng.df_trandom(100)) + ChooseWord(minor_selector, name->words[language_name_component::SecondAdjective], name->parts_of_speech[language_name_component::SecondAdjective], language_word_table_index::Adjectives); + break; + } + if (!rng.df_trandom(100)) + { + r = rng.df_trandom(2); + ChooseWord(minor_selector, name->words[language_name_component::HyphenCompound], name->parts_of_speech[language_name_component::HyphenCompound], language_word_table_index::TheX); + } + // If TheX is a plural noun, then switch it to Singular if possible + if (name->parts_of_speech[language_name_component::TheX] == part_of_speech::NounPlural) + { + int word = name->words[language_name_component::TheX]; + if (word >= 0 && (size_t)word < world->raws.language.words.size() && world->raws.language.words[word]->forms[part_of_speech::Noun].length() > 0) + name->parts_of_speech[language_name_component::TheX] = part_of_speech::Noun; + } + break; + default: + break; + } + + int adj1 = name->words[language_name_component::FirstAdjective]; + int adj2 = name->words[language_name_component::SecondAdjective]; + if (adj1 != -1 && adj2 != -1 && (size_t)adj1 < world->raws.language.words.size() && (size_t)adj2 < world->raws.language.words.size() && + world->raws.language.words[adj1]->adj_dist < world->raws.language.words[adj2]->adj_dist) + { + std::swap(name->words[language_name_component::FirstAdjective], name->words[language_name_component::SecondAdjective]); + std::swap(name->parts_of_speech[language_name_component::FirstAdjective], name->parts_of_speech[language_name_component::SecondAdjective]); + } + bool reject = false; + if ((name->parts_of_speech[language_name_component::TheX] == df::part_of_speech::NounPlural) && (name->parts_of_speech[language_name_component::OfX] == df::part_of_speech::NounPlural)) + reject = true; + if (name->words[language_name_component::FrontCompound] != -1) + { + int word = name->words[language_name_component::FrontCompound]; + if (name->words[language_name_component::RearCompound] == word) reject = true; + if (name->words[language_name_component::OfX] == word) reject = true; + if (name->words[language_name_component::HyphenCompound] == word) reject = true; + if (name->words[language_name_component::FirstAdjective] == word) reject = true; + if (name->words[language_name_component::SecondAdjective] == word) reject = true; + if (name->words[language_name_component::TheX] == word) reject = true; + } + if (name->words[language_name_component::RearCompound] != -1) + { + int word = name->words[language_name_component::RearCompound]; + if (name->words[language_name_component::OfX] == word) reject = true; + if (name->words[language_name_component::HyphenCompound] == word) reject = true; + if (name->words[language_name_component::FirstAdjective] == word) reject = true; + if (name->words[language_name_component::SecondAdjective] == word) reject = true; + if (name->words[language_name_component::TheX] == word) reject = true; + } + if (name->words[language_name_component::HyphenCompound] != -1) + { + int word = name->words[language_name_component::HyphenCompound]; + if (name->words[language_name_component::OfX] == word) reject = true; + if (name->words[language_name_component::FirstAdjective] == word) reject = true; + if (name->words[language_name_component::SecondAdjective] == word) reject = true; + if (name->words[language_name_component::TheX] == word) reject = true; + } + if (name->words[language_name_component::FirstAdjective] != -1) + { + int word = name->words[language_name_component::FirstAdjective]; + if (name->words[language_name_component::OfX] == word) reject = true; + if (name->words[language_name_component::SecondAdjective] == word) reject = true; + if (name->words[language_name_component::TheX] == word) reject = true; + } + if (name->words[language_name_component::SecondAdjective] != -1) + { + int word = name->words[language_name_component::SecondAdjective]; + if (name->words[language_name_component::OfX] == word) reject = true; + if (name->words[language_name_component::TheX] == word) reject = true; + } + if (name->words[language_name_component::TheX] != -1) + { + int word = name->words[language_name_component::TheX]; + if (name->words[language_name_component::OfX] == word) reject = true; + } + if (!reject) + return; + } +} diff --git a/plugins/strangemood.cpp b/plugins/strangemood.cpp index 62496570a0..33783b666f 100644 --- a/plugins/strangemood.cpp +++ b/plugins/strangemood.cpp @@ -24,6 +24,7 @@ #include "df/item.h" #include "df/job.h" #include "df/job_item.h" +#include "df/language_name_category.h" #include "df/language_word.h" #include "df/map_block.h" #include "df/material.h" @@ -144,141 +145,6 @@ int getCreatedMetalBars (int32_t idx) return 0; } -void selectWord (const df::language_word_table &table, int32_t &word, df::part_of_speech &part, int mode) -{ - if (table.parts[mode].size()) - { - int offset = rng.df_trandom(table.parts[mode].size()); - word = table.words[mode][offset]; - part = table.parts[mode][offset]; - } - else - { - word = rng.df_trandom(world->raws.language.words.size()); - part = (df::part_of_speech)(rng.df_trandom(9)); - Core::getInstance().getConsole().printerr("Impoverished Word Selector"); - } -} - -void generateName(df::language_name &output, int language, const df::language_word_table &table1, const df::language_word_table &table2) -{ - for (int i = 0; i < 100; i++) - { - output = df::language_name(); - if (language == -1) - language = rng.df_trandom(world->raws.language.translations.size()); - output.type = language_name_type::Artifact; - output.language = language; - output.has_name = 1; - if (output.language == -1) - output.language = rng.df_trandom(world->raws.language.translations.size()); - int r, r2, r3; - r = rng.df_trandom(3); - if (r == 0 || r == 1) - { - if (rng.df_trandom(2)) - { - selectWord(table2, output.words[0], output.parts_of_speech[0], 0); - selectWord(table1, output.words[1], output.parts_of_speech[1], 1); - } - else - { - selectWord(table1, output.words[0], output.parts_of_speech[0], 0); - selectWord(table2, output.words[1], output.parts_of_speech[1], 1); - } - } - if (r == 1 || r == 2) - { - r2 = rng.df_trandom(2); - if (r2) - selectWord(table1, output.words[5], output.parts_of_speech[5], 2); - else - selectWord(table2, output.words[5], output.parts_of_speech[5], 2); - r3 = rng.df_trandom(3); - if (rng.df_trandom(50)) - r3 = rng.df_trandom(2); - switch (r3) - { - case 0: - case 2: - if (r3 == 2) - r2 = rng.df_trandom(2); - if (r2) - selectWord(table2, output.words[6], output.parts_of_speech[6], 5); - else - selectWord(table1, output.words[6], output.parts_of_speech[6], 5); - if (r3 == 0) - break; - r2 = -r2; - case 1: - if (r2) - selectWord(table1, output.words[2], output.parts_of_speech[2], 3); - else - selectWord(table2, output.words[2], output.parts_of_speech[2], 3); - if (!(rng.df_trandom(100))) - selectWord(table1, output.words[3], output.parts_of_speech[3], 3); - break; - } - } - if (rng.df_trandom(100)) - { - if (rng.df_trandom(2)) - selectWord(table1, output.words[4], output.parts_of_speech[4], 4); - else - selectWord(table2, output.words[4], output.parts_of_speech[4], 4); - } - if (output.words[2] != -1 && output.words[3] != -1 && - world->raws.language.words[output.words[3]]->adj_dist < world->raws.language.words[output.words[2]]->adj_dist) - { - std::swap(output.words[2], output.words[3]); - std::swap(output.parts_of_speech[2], output.parts_of_speech[3]); - } - bool next = false; - if ((output.parts_of_speech[5] == df::part_of_speech::NounPlural) && (output.parts_of_speech[6] == df::part_of_speech::NounPlural)) - next = true; - if (output.words[0] != -1) - { - if (output.words[6] == -1) next = true; - if (output.words[4] == -1) next = true; - if (output.words[2] == -1) next = true; - if (output.words[3] == -1) next = true; - if (output.words[5] == -1) next = true; - } - if (output.words[1] != -1) - { - if (output.words[6] == -1) next = true; - if (output.words[4] == -1) next = true; - if (output.words[2] == -1) next = true; - if (output.words[3] == -1) next = true; - if (output.words[5] == -1) next = true; - } - if (output.words[4] != -1) - { - if (output.words[6] == -1) next = true; - if (output.words[2] == -1) next = true; - if (output.words[3] == -1) next = true; - if (output.words[5] == -1) next = true; - } - if (output.words[2] != -1) - { - if (output.words[6] == -1) next = true; - if (output.words[3] == -1) next = true; - if (output.words[5] == -1) next = true; - } - if (output.words[3] != -1) - { - if (output.words[6] == -1) next = true; - if (output.words[5] == -1) next = true; - } - if (output.words[5] != -1) - { - if (output.words[6] == -1) next = true; - } - if (!next) - return; - } -} - command_result df_strangemood (color_ostream &out, vector & parameters) { if (!Translation::IsValid()) @@ -1231,10 +1097,10 @@ command_result df_strangemood (color_ostream &out, vector & parameters) // Generate the artifact's name if (type == mood_type::Fell || type == mood_type::Macabre) - generateName(unit->status.artifact_name, unit->name.language, world->raws.language.word_table[0][2], world->raws.language.word_table[1][2]); + Translation::GenerateName(&unit->status.artifact_name, unit->name.language, language_name_type::Artifact, &world->raws.language.word_table[0][language_name_category::ArtifactEvil], &world->raws.language.word_table[1][language_name_category::ArtifactEvil]); else { - generateName(unit->status.artifact_name, unit->name.language, world->raws.language.word_table[0][1], world->raws.language.word_table[1][1]); + Translation::GenerateName(&unit->status.artifact_name, unit->name.language, language_name_type::Artifact, &world->raws.language.word_table[0][language_name_category::Artifact], &world->raws.language.word_table[1][language_name_category::Artifact]); if (!rng.df_trandom(100)) unit->status.artifact_name = unit->name; }