thy.c (9359B)
1 /* See LICENSE file for copyright and license details. 2 * 3 * thy: a pseudo-elizabethan context-free grammar 4 * This program constructs fragments using a "Mad Libs"-like text engine. 5 */ 6 #include <stdarg.h> 7 #include <stdlib.h> 8 #include <time.h> 9 #include <unistd.h> 10 11 #define W(s, l) do { if (write(1, s, l)) {} } while (0) 12 13 void 14 tiny_printf(const char *fmt, ...) { 15 va_list args; 16 va_start(args, fmt); 17 18 while (*fmt) { 19 if (*fmt == '%' && *(fmt + 1) == 's') { 20 const char *s = va_arg(args, const char *); 21 if (s) { 22 int len = 0; 23 while (s[len]) len++; 24 W(s, len); 25 } 26 fmt += 2; 27 } else { 28 W(fmt++, 1); 29 } 30 } 31 va_end(args); 32 } 33 34 const char *Noun[] = { 35 "mirror", "furnace", "skeleton", "biscuit", "mountain", "delusion", 36 "microcosm", "jelly", "ocean", "truth", "science", "product", "insect", 37 "tyranny", "creature", "theory", "life", "beast", "breast", "hope", "gland", 38 "convexity", "concavity", "doom", "season", "corrosion", "passion", "fate", 39 "vessel", "pain", "chemical", "mandible", "ray", "spirit", "feeling", 40 "radiance", "dirt", "vacuum", "art", "homunculus", "engine", "text", 41 "wheel", "vent", "lard", "memory", "apparel", "domicile", "behavior", 42 "government", "sound", "prison", "being", "sustenance", "death", "worm", 43 "stone", "color", "crystal", "gastropod", "flesh", "fire" 44 }; 45 const char *Verb1[] = { 46 "indulge", "lament", "caress", "exalt", "destroy", "avenge", "batter", 47 "stretch", "deceive", "shun", "manifest", "witness", "actualize", "embrace", 48 "levitate", "pardon", "sniff", "banish", "falsify", "pilot", "hark", 49 "consider", "render", "forget", "remember", "approach", "castigate", 50 "liquify", "debase", "sing", "hydrate", "chill", "rescue", "hoist", 51 "extrude", "desire", "impede", "thrum", "suffer", "texturize", "bungle", 52 "dance", "beat", "bleed", "soak", "work", "calm", "tether", "blast", 53 "digest", "smear", "rock", "roll", "sustain", "gather", "exhume", 54 "rehydrate", "prepare", "purify" 55 }; 56 const char *Verb2[] = { 57 "yearns for", "is like", "appears as", "reveals", "extracts", "is" 58 }; 59 const char *Adj[] = { 60 "mortal", "shining", "joyful", "austere", "melancholy", "small", "lordly", 61 "massive", "effulgent", "wandering", "gentle", "weaponized", "sentimental", 62 "correct", "motile", "youthful", "incomplete", "haughty", "furtive", 63 "vital", "offending", "pungent", "shriveled", "noisome", "hallowed", 64 "flabby", "zesty", "mechanized", "little", "burning", "fatal", "elusive", 65 "merry", "plastic", "juicy", "televised", "sphere-like", "modified", 66 "augmented", "noble", "pneumatic", "hylic", "psychic", "bad", "pupigerous", 67 "nodulous", "cycloid", "forbidden", "lurid", "fine", "platinum", "blue", 68 "monochrome", "spreading", "mutant", "revolving", "corporeal", "hideous", 69 "mild", "shrunken", "glum", "petty", "clean", "mutable", "leather", "scaly", 70 "spongy", "tendrillar", "refulgent", "porcelein" 71 }; 72 const char *Adv[] = { 73 "thinly", "strongly", "invisibly", "slowly", "woozily", "grimly", "greatly", 74 "mostly", "partially", "totally", "blatantly", "pleasantly", "luxuriously", 75 "expansively", "utterly", "rapidly", "crudely", "mercifully", "delicately", 76 "wrongfully", "arrogantly", "horribly", "wonderfully", "ostensibly", 77 "remarkably", "miraculously", "accidentally" 78 }; 79 const char *Prep[] = { 80 "above", "below", "amidst", "near", "far beyond", "inside", "thanks to", 81 "outside", "out of", "despite", "astride", "in", "beside", "of" 82 }; 83 const char *Sense[] = { 84 "shiver", "pressure", "texture", "friction", "warmth", "chill", "weight", 85 "echo", "resonance", "murmur", "thrum", "discord", "silence", "cadence", 86 "glow", "shadow", "radiance", "glimmer", "shimmer", "haze", "aura", "scent", 87 "stink", "perfume", "savor", "aftertaste", "pungency", "breath", 88 "intuition", "dread", "premonition", "vertigo", "ache", "yearning", "sting" 89 }; 90 const char *Det[] = { 91 "his", "her", "its", "our", "their", "the", "thy", "this", "that", "thine", 92 "another", "a", "an", "some", "every", "my", "mine", "those", "these" 93 }; 94 const char *Question[] = { 95 "who", "what", "where" 96 }; 97 const char *SubjPronoun[] = { 98 "he", "she", "it", "they", "we", "who", "naught", "someone" 99 }; 100 const char *ObjPronoun[] = { 101 "him", "her", "it", "them", "us", "whom", "thee", "nothing", "thou" 102 }; 103 const char *SortOf[] = { 104 "sort of", "kind of", "like", "almost" 105 }; 106 const char *Condition[] = { 107 "if", "when", "though", "while", "whenever", "since", "unless", "once" 108 }; 109 const char *Vocative[] = { 110 "o", "alas,", "behold,", "hail,", "farewell,", "stay,", "hark," 111 }; 112 const char *Coord[] = { 113 "and", "but", "for", "yet", "or", "nor", "so" 114 }; 115 const char *WillDoth[] = { 116 "doth", "may", "can", "will", "shall", "must", "hath", "might" 117 }; 118 const char *PosPronoun[] = { 119 "hers", "his", "yours", "theirs", "ours", "its" 120 }; 121 const char *Conj2[] = { 122 "but", "though", "yet" 123 }; 124 const char *REEZ[] = { 125 "and ease", "and chronologies", "and grease", "and debris", 126 "with expertise", "and TVs", "and bourgeoisies", "and industries", 127 "without cease", "in three", "in twos and threes", "by degrees", "and ZZZs", 128 "and memories", "breeze", "trees", "seas", "crease", "lees", "fleece", 129 "police", "freeze" 130 }; 131 const char *IRE[] = { 132 "fire", "ire", "wire", "mire", "things expire'd", "desire", "spire", 133 "attire", "pyre", "higher", "liar", "dire", "prior", "cypher" 134 }; 135 const char *ACE[] = { 136 "face", "grace", "suitcase", "pace", "solace", "base", "case", "trace" 137 }; 138 const char *ISS[] = { 139 "terrace", "space", "populace", "surface", "waste", "place" 140 }; 141 const char *AND[] = { 142 "land", "hand", "sand", "strand", "brand", "unmanned", "planned", 143 "command", "grand", "unplanned", "fanned", "bland", "banned", 144 "contraband", "expand", "reprimand", "unhand", "demand" 145 }; 146 147 #define PICK(arr) (arr[rand() % (sizeof(arr) / sizeof(arr[0]))]) 148 149 void 150 generate_prose(void) { 151 int template_choice = rand() % 17; 152 153 switch (template_choice) { 154 case 0: /* Transitive Metaphor */ 155 tiny_printf("%s %s %s %s %s\n", 156 PICK(Det), PICK(Noun), PICK(Verb2), 157 PICK(Adj), PICK(Noun)); 158 break; 159 160 case 1: /* Auxiliary Question */ 161 tiny_printf("%s %s %s %s %s %s?\n", 162 PICK(Question), PICK(WillDoth), PICK(Adv), 163 PICK(Verb1),PICK(Det), PICK(Noun)); 164 break; 165 166 case 2: /* Attributive Approximation */ 167 tiny_printf("%s %s %s %s %s\n", 168 PICK(SubjPronoun), PICK(Verb2), PICK(SortOf), 169 PICK(Adj), PICK(Noun)); 170 break; 171 172 case 3: /* Vocative */ 173 tiny_printf("%s %s, %s %s %s %s\n", 174 PICK(Vocative), PICK(Noun), PICK(Det), 175 PICK(Noun), PICK(Verb1), PICK(ObjPronoun)); 176 break; 177 178 case 4: /* Relative */ 179 tiny_printf("%s %s %s, %s %s %s %s?\n", 180 PICK(Question), PICK(Adj), PICK(Noun), 181 PICK(Verb1), PICK(SortOf), PICK(Det), 182 PICK(Noun)); 183 break; 184 185 case 5: /* Paradox */ 186 tiny_printf("%s %s %s %s %s %s\n", 187 PICK(Det), PICK(Noun), PICK(Verb2), 188 PICK(Det), PICK(Adj), PICK(Noun)); 189 break; 190 191 case 6: /* Modal Adverbial */ 192 tiny_printf("%s %s %s %s %s %s\n", 193 PICK(SubjPronoun), PICK(WillDoth), PICK(Adv), 194 PICK(Verb1), PICK(Det), PICK(Noun)); 195 break; 196 197 case 7: /* Prepositional Opener */ 198 tiny_printf("%s %s %s, %s %s %s\n", 199 PICK(Prep), PICK(Det), PICK(Noun), 200 PICK(Det), PICK(Noun), PICK(Verb1)); 201 break; 202 203 case 8: /* Conditional */ 204 tiny_printf("%s %s %s %s, %s %s %s %s\n", 205 PICK(Condition), PICK(SubjPronoun), PICK(WillDoth), 206 PICK(Verb1), PICK(Det), PICK(Noun), PICK(WillDoth), 207 PICK(Verb1)); 208 break; 209 210 case 9: /* Inverse Conditional */ 211 tiny_printf("%s %s %s %s %s %s %s %s\n", 212 PICK(Det), PICK(Noun), PICK(WillDoth), 213 PICK(Verb1), PICK(Condition), PICK(SubjPronoun), 214 PICK(WillDoth), PICK(Verb1)); 215 break; 216 217 case 10: /* Possessive Existential */ 218 tiny_printf("%s %s's %s %s %s %s\n", 219 PICK(Det), PICK(Noun), PICK(Noun), 220 PICK(Verb2), PICK(Det), PICK(Noun)); 221 break; 222 223 case 11: /* Sensory Attestation */ 224 tiny_printf("%s %s %s of %s %s %s %s\n", 225 PICK(Det), PICK(Adj), PICK(Sense), 226 PICK(Noun), PICK(Verb2), PICK(Det), 227 PICK(Noun)); 228 break; 229 230 case 12: /* Negative Sensory */ 231 tiny_printf("no %s %s %s %s %s %s %s %s\n", 232 PICK(Sense), PICK(Prep), PICK(Det), 233 PICK(Noun), PICK(WillDoth), PICK(Verb1), 234 PICK(Det), PICK(Noun)); 235 break; 236 237 case 13: 238 tiny_printf("%s %s %s %s\n", 239 PICK(Det), PICK(Noun), PICK(Verb2), 240 PICK(AND)); 241 tiny_printf("%s %s %s %s\n", 242 PICK(Det), PICK(Adj), PICK(Noun), 243 PICK(AND)); 244 break; 245 246 case 14: 247 tiny_printf("%s %s %s %s\n", 248 PICK(Det), PICK(Noun), PICK(Verb1), 249 PICK(REEZ)); 250 tiny_printf("%s %s %s %s %s\n", 251 PICK(Prep), PICK(Det), PICK(Adj), 252 PICK(Noun), PICK(REEZ)); 253 break; 254 255 case 15: 256 tiny_printf("%s %s %s %s\n", 257 PICK(Vocative), PICK(Noun), PICK(Verb2), 258 PICK(IRE)); 259 tiny_printf("%s %s %s %s\n", 260 PICK(Det), PICK(Noun), PICK(WillDoth), 261 PICK(IRE)); 262 break; 263 264 case 16: 265 tiny_printf("%s %s %s %s %s\n", 266 PICK(SubjPronoun), PICK(Adv), PICK(Verb1), 267 PICK(Det), PICK(ACE)); 268 tiny_printf("%s %s %s %s\n", 269 PICK(Coord), PICK(Verb1), PICK(Det), 270 PICK(ISS)); 271 break; 272 default: break; 273 } 274 } 275 276 int 277 main(void) { 278 srand((unsigned int)time(NULL)); 279 int lines = (rand() % 2) + 1; 280 for (int i = 0; i < lines; i++) 281 generate_prose(); 282 return 0; 283 }