/* * EXAMPLE: Structured Name Generation (The "Brain") * * Unlike the random motor babbler, this program applies high-level linguistic * constraints to the articulatory physics engine. It defines specific phoneme * subsets (Languages) and grammar rules (Syllable Structure) to guide the mouth. * * It demonstrates that by constraining the chaos of the physics engine with * simple rules (Attractor States), we can generate distinct, recognizable * "accents" or "languages". */ #include #include #include #include #include "articulator.h" #include "transcriber.h" extern char RAW_OUTPUT_BUFFER[]; extern const phoneme_t PHONEME_DB[]; extern const ortho_rule_t ORTHO_IPA[]; extern const ortho_rule_t ORTHO_POLISH[]; extern const ortho_rule_t ORTHO_HUNGARIAN[]; extern const ortho_rule_t ORTHO_GERMAN[]; extern const ortho_rule_t ORTHO_CYRILLIC[]; extern const ortho_rule_t ORTHO_ORCISH[]; /* --- LANGUAGE DEFINITIONS --- */ /* Standard Fantasy/English-ish */ const char* LANG_COMMON[] = {"p", "b", "t", "d", "k", "g", "m", "n", "f", "v", "s", "z", "ʃ", "h", "r", "l", "w", "j", "i", "u", "e", "o", "a", "ə", "ɪ", "ɛ", "æ", "ɔ", NULL}; const char* LANG_SLAVIC[] = { // Vowels (Simple 6 system) "i", "u", "e", "o", "a", "ɨ", // ɨ is Polish 'y' // Consonants "p", "b", "t", "d", "k", "g", "m", "n", "ɲ", // n, ń "f", "v", "s", "z", "x", // f, w, s, z, ch "ts", "dz", // c, dz "ʃ", "ʒ", "tʃ", "dʒ", // sz, ż, cz, dż "ɕ", "ʑ", "tɕ", "dʑ", // ś, ź, ć, dź "l", "r", "j", "w", // l, r, j, ł NULL}; /* Harsh/Orcish (Back of throat, Guttural) */ const char* LANG_ORCISH[] = {"k", "g", "q", "ɢ", "ʔ", "x", "χ", "ʁ", "h", "p", "b", "t", "d", "u", "o", "ɑ", "ɔ", NULL}; /* Soft/Elvish (Liquids, Fricatives, Front Vowels) */ const char* LANG_ELVISH[] = {"p", "b", "t", "d", "m", "n", "f", "v", "s", "z", "ʃ", "ʒ", "θ", "ð", "l", "ʎ", "r", "w", "j", "i", "y", "e", "ø", "a", "ɛ", "œ", NULL}; /* --- FILTER HELPER --- */ /* Check if an IPA symbol exists in the allowed list */ int is_allowed(const char* ipa, const char** allowed_list) { for (int i = 0; allowed_list[i] != NULL; i++) { if (strcmp(ipa, allowed_list[i]) == 0) return 1; } return 0; } /* --- UPDATED GENERATOR --- */ void generate_name(const char* race_name, const char** allowed_sounds, int syllables) { printf("\n=== Generating %s Name (%d syl) ===\n", race_name, syllables); // 1. Build Index Cache for this Language int v_indices[100], v_count = 0; int c_indices[100], c_count = 0; for (int i = 0; PHONEME_DB[i].ipa != NULL; i++) { // Only add if it's in the allowed list if (is_allowed(PHONEME_DB[i].ipa, allowed_sounds)) { if (is_vowel_index(i)) { if (v_count < 100) v_indices[v_count++] = i; } else { if (c_count < 100) c_indices[c_count++] = i; } } } if (v_count == 0 || c_count == 0) { printf("Error: No sounds found for %s\n", race_name); return; } // 2. Build Sequence (C-V-C pattern) int len = 0; int seq[100]; for (int s = 0; s < syllables; s++) { // Onset if (rand() % 10 < 7) seq[len++] = c_indices[rand() % c_count]; // Nucleus seq[len++] = v_indices[rand() % v_count]; // Coda if (rand() % 10 < 4) seq[len++] = c_indices[rand() % c_count]; } // 3. Simulate & Transcribe simulate_sequence(seq, len); } int main(void) { srand(time(NULL)); char word[256]; for (int i = 0; i < 3; i++) { generate_name("Human", LANG_COMMON, 2 + i); printf("RAW: \"%s\"\n", RAW_OUTPUT_BUFFER); transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_IPA); printf("IPA: \"%s\"\n", word); transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_POLISH); printf(" PL: \"%s\"\n", word); transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_HUNGARIAN); printf(" HU: \"%s\"\n", word); transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_GERMAN); printf(" DE: \"%s\"\n", word); transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_CYRILLIC); printf(" RU: \"%s\"\n", word); transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_ORCISH); printf("ORC: \"%s\"\n", word); } for (int i = 0; i < 3; i++) { generate_name("Slavic", LANG_SLAVIC, 2 + i); printf("RAW: \"%s\"\n", RAW_OUTPUT_BUFFER); transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_IPA); printf("IPA: \"%s\"\n", word); transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_POLISH); printf(" PL: \"%s\"\n", word); transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_HUNGARIAN); printf(" HU: \"%s\"\n", word); transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_GERMAN); printf(" DE: \"%s\"\n", word); transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_CYRILLIC); printf(" RU: \"%s\"\n", word); transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_ORCISH); printf("ORC: \"%s\"\n", word); } for (int i = 0; i < 3; i++) { generate_name("Orcish", LANG_ORCISH, 2 + i); printf("RAW: \"%s\"\n", RAW_OUTPUT_BUFFER); transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_IPA); printf("IPA: \"%s\"\n", word); transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_POLISH); printf(" PL: \"%s\"\n", word); transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_HUNGARIAN); printf(" HU: \"%s\"\n", word); transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_GERMAN); printf(" DE: \"%s\"\n", word); transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_CYRILLIC); printf(" RU: \"%s\"\n", word); transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_ORCISH); printf("ORC: \"%s\"\n", word); } for (int i = 0; i < 3; i++) { generate_name("Elvish", LANG_ELVISH, 2 + i); printf("RAW: \"%s\"\n", RAW_OUTPUT_BUFFER); transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_IPA); printf("IPA: \"%s\"\n", word); transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_POLISH); printf(" PL: \"%s\"\n", word); transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_HUNGARIAN); printf(" HU: \"%s\"\n", word); transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_GERMAN); printf(" DE: \"%s\"\n", word); transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_CYRILLIC); printf(" RU: \"%s\"\n", word); transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_ORCISH); printf("ORC: \"%s\"\n", word); } return 0; }