📄 randomword.c
字号:
}/* Check that the word does not contain illegal combinations that may span syllables. Specifically, these are: 1. An illegal pair of units between syllables. 2. Three consecutive vowel units. 3. Three consecutive consonant units. The checks are made against units (1 or 2 letters), not against the individual letters, so three consecutive units can have the length of 6 at most.*/improper_word (units, size)register unsigned short int *units;register unsigned short int size;{ register unsigned short int unit_count; register boolean failure; failure = FALSE; for (unit_count = 0; !failure && (unit_count < size); unit_count++) { /* * Check for ILLEGAL_PAIR. This should have been caught * for units within a syllable, but in some cases it * would have gone unnoticed for units between syllables * (e.g., when saved_unit's in get_syllable() were not * used). */ if ((unit_count != 0) && (digram[units[unit_count - 1]][units[unit_count]] & ILLEGAL_PAIR)) failure = TRUE; /* * Check for consecutive vowels or consonants. Because * the initial y of a syllable is treated as a consonant * rather than as a vowel, we exclude y from the first * vowel in the vowel test. The only problem comes when * y ends a syllable and two other vowels start the next, * like fly-oint. Since such words are still * pronounceable, we accept this. */ if (!failure && (unit_count >= 2)) { /* Vowel check. */ if ((((rules[units[unit_count - 2]].flags & VOWEL) && !(rules[units[unit_count - 2]].flags & ALTERNATE_VOWEL)) && (rules[units[unit_count - 1]].flags & VOWEL) && (rules[units[unit_count]].flags & VOWEL)) || /* Consonant check. */ (!(rules[units[unit_count - 2]].flags & VOWEL) && !(rules[units[unit_count - 1]].flags & VOWEL) && !(rules[units[unit_count]].flags & VOWEL))) failure = TRUE; } } return (failure);}/* Treating y as a vowel is sometimes a problem. Some words get formed that look irregular. One special group is when y starts a word and is the only vowel in the first syllable. The word ycl is one example. We discard words like these.*/boolean have_initial_y (units, size)register unsigned short int *units;register unsigned short int size;{ register unsigned short int unit_count; register unsigned short int vowel_count; register unsigned short int normal_vowel_count; vowel_count = 0; normal_vowel_count = 0; for (unit_count = 0; unit_count <= size; unit_count++) /* Count vowels. */ if (rules[units[unit_count]].flags & VOWEL) { vowel_count++; /* Count the vowels that are not: 1. y, 2. at the start of the word. */ if (!(rules[units[unit_count]].flags & ALTERNATE_VOWEL) || (unit_count != 0)) normal_vowel_count++; } return ((vowel_count <= 1) && (normal_vowel_count == 0));}/* Besides the problem with the letter y, there is one with a silent e at the end of words, like face or nice. We allow this silent e, but we do not allow it as the only vowel at the end of the word or syllables like ble will be generated.*/boolean have_final_split (units, size)register unsigned short int *units;register unsigned short int size;{ register unsigned short int unit_count; register unsigned short int vowel_count; vowel_count = 0; /* Count all the vowels in the word. */ for (unit_count = 0; unit_count <= size; unit_count++) if (rules[units[unit_count]].flags & VOWEL) vowel_count++; /* Return TRUE iff the only vowel was e, found at the end if the word. */ return ((vowel_count == 1) && (rules[units[size]].flags & NO_FINAL_SPLIT));}/* Generate next unit to password, making sure that it follows these rules: 1. Each syllable must contain exactly 1 or 2 consecutive vowels, where y is considered a vowel. 2. Syllable end is determined as follows: a. Vowel is generated and previous unit is a consonant and syllable already has a vowel. In this case, new syllable is started and already contains a vowel. b. A pair determined to be a "break" pair is encountered. In this case new syllable is started with second unit of this pair. c. End of password is encountered. d. "begin" pair is encountered legally. New syllable is started with this pair. e. "end" pair is legally encountered. New syllable has nothing yet. 3. Try generating another unit if: a. third consecutive vowel and not y. b. "break" pair generated but no vowel yet in current or previous 2 units are "not_end". c. "begin" pair generated but no vowel in syllable preceding begin pair, or both previous 2 pairs are designated "not_end". d. "end" pair generated but no vowel in current syllable or in "end" pair. e. "not_begin" pair generated but new syllable must begin (because previous syllable ended as defined in 2 above). f. vowel is generated and 2a is satisfied, but no syllable break is possible in previous 3 pairs. g. Second and third units of syllable must begin, and first unit is "alternate_vowel".*/char *get_syllable (syllable, length, units_in_syllable, syllable_length)char *syllable;unsigned short int length;unsigned short int *units_in_syllable;unsigned short int *syllable_length;{ register unsigned short int unit; register short int current_unit; register unsigned short int vowel_count; register boolean rule_broken; register boolean want_vowel; register boolean want_another_unit; int unsigned tries; int unsigned short last_unit; int short length_left; unsigned short int hold_saved_unit; static unsigned short int saved_unit; static unsigned short int saved_pair[2]; /* This is needed if the saved_unit is tries and the syllable then discarded because of the retry limit. Since the saved_unit is OK and fits in nicely with the preceding syllable, we will always use it. */ hold_saved_unit = saved_unit; /* Loop until valid syllable is found. */ do { /* Try for a new syllable. Initialize all pertinent syllable variables. */ tries = 0; saved_unit = hold_saved_unit; (void) strcpy (syllable, ""); vowel_count = 0; current_unit = 0; length_left = (short int) length; want_another_unit = TRUE; /* This loop finds all the units for the syllable. */ do { want_vowel = FALSE; /* This loop continues until a valid unit is found for the current position within the syllable. */ do { /* * If there are saved_unit's from the previous * syllable, use them up first. */ if (saved_unit != 0) { /* * If there were two saved units, the first is * guaranteed (by checks performed in the previous * syllable) to be valid. We ignore the checks * and place it in this syllable manually. */ if (saved_unit == 2) { units_in_syllable[0] = saved_pair[1]; if (rules[saved_pair[1]].flags & VOWEL) vowel_count++; current_unit++; (void) strcpy (syllable, rules[saved_pair[1]].unit_code); length_left -= strlen (syllable); } /* * The unit becomes the last unit checked in the * previous syllable. */ unit = saved_pair[0]; /* The saved units have been used. Do not try to reuse them in this syllable (unless this particular syllable is rejected at which point we start to rebuild it with these same saved units. */ saved_unit = 0; } else /* * If we don't have to scoff the saved units, * we generate a random one. If we know it has * to be a vowel, we get one rather than looping * thruogh until one shows up. */ if (want_vowel) unit = random_unit (VOWEL); else unit = random_unit (NO_SPECIAL_RULE); length_left -= (short int) strlen (rules[unit].unit_code); /* Prevent having a word longer than expected. */ if (length_left < 0) rule_broken = TRUE; else rule_broken = FALSE; /* First unit of syllable. This is special because the digram tests require 2 units and we don't have that yet. Nevertheless, we can perform some checks. */ if (current_unit == 0) { /* * If the shouldn't begin a syllable, don't * use it. */ if (rules[unit].flags & NOT_BEGIN_SYLLABLE) rule_broken = TRUE; else /* * If this is the last unit of a word, * we have a one unit syllable. Since each * syllable must have a vowel, we make sure * the unit is a vowel. Otherwise, we * discard it. */ if (length_left == 0) if (rules[unit].flags & VOWEL) want_another_unit = FALSE; else rule_broken = TRUE; } else { /* * There are some digram tests that are * universally true. We test them out. */ /* Reject ILLEGAL_PAIRS of units. */ if ((ALLOWED (ILLEGAL_PAIR)) || /* Reject units that will be split between syllables when the syllable has no vowels in it. */ (ALLOWED (BREAK) && (vowel_count == 0)) || /* Reject a unit that will end a syllable when no previous unit was a vowel and neither is this one. */ (ALLOWED (END) && (vowel_count == 0) && !(rules[unit].flags & VOWEL))) rule_broken = TRUE; if (current_unit == 1) { /* Reject the unit if we are at te starting digram of a syllable and it does not fit. */ if (ALLOWED (NOT_BEGIN)) rule_broken = TRUE; } else { /* * We are not at the start of a syllable. * Save the previous unit for later tests. */ last_unit = units_in_syllable[current_unit - 1]; /* Do not allow syllables where the first letter is y and the next pair can begin a syllable. This may lead to splits where y is left alone in a syllable. Also, the combination does not sound to good even if not split. */ if (((current_unit == 2) && (ALLOWED (BEGIN)) && (rules[units_in_syllable[0]].flags & ALTERNATE_VOWEL)) || /* If this is the last unit of a word, we should reject any digram that cannot end a syllable. */ (ALLOWED (NOT_END) && (length_left == 0)) || /* Reject the unit if the digram it forms wants to break the syllable, but the resulting digram that would end the syllable is not allowed to end a syllable. */ (ALLOWED (BREAK) && (digram[units_in_syllable [current_unit - 2]] [last_unit] & NOT_END)) || /* Reject the unit if the digram it forms expects a vowel preceding it and there is none. */ (ALLOWED (PREFIX) && !(rules[units_in_syllable [current_unit - 2]].flags & VOWEL))) rule_broken = TRUE; /* The following checks occur when the current unit is a vowel and we are not looking at a word ending with an e. */ if (!rule_broken && (rules[unit].flags & VOWEL) && ((length_left > 0) || !(rules[last_unit].flags & NO_FINAL_SPLIT))) /* Don't allow 3 consecutive vowels in a syllable. Although some words formed like this are OK, like beau, most are not. */ if ((vowel_count > 1) && (rules[last_unit].flags & VOWEL)) rule_broken = TRUE; else /* Check for the case of vowels-consonants-vowel, which is only legal if the last vowel is an e and we are at the end of the word (wich is not happening here due to a previous check. */ if ((vowel_count != 0) && !(rules[last_unit].flags & VOWEL)) { /* Try to save the vowel for the next syllable, but if the syllable left here is not proper (i.e., the resulting last digram cannot legally end it), just discard it and try for another. */ if (digram[units_in_syllable
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -