! prand.h ! release 1 ! Copyright 2001 Anson Turner. ! ! To use: ! Prior to including the file, you may declare constant PS_TAB_SIZE, ! which determines the number of strings the system can remember. ! (If unspecified, it defaults to 1000.) Of course, it also consumes ! that many words of dynamic memory. ! ! Call prand() with up to 7 strings as parameters, e.g.: ! ! prand("blue ","red ","green ","speckled onyx "); ! ! The routine will print one of the strings at random, except that ! it will not print the same string a second time until all of the ! strings have been printed at least once. Thus, if the above call ! was repeated 4 times, the results might be: ! ! green blue speckled onyx red ! ! But *not*: ! ! blue green red green ! ! Because "green" would have been printed twice, while "speckled onyx" ! would not have been printed at all. ! ! A note about strings in Inform is in order. Each double-quoted ! string in the source is compiled into a static string, which is ! accessed via its address in memory. Two strings which may contain ! the exact same set of characters are nevertheless completely ! different strings as far as the system is concerned. Thus: ! ! prand ("blue ","red "); prand ("blue ","red "); ! ! could very well result in: ! ! red red ! ! After all the strings in the call have been printed once, the output ! becomes completely random. (Not in the sense that you will get ! _Hamlet_ by running it enough times, but rather that it will ! randomly choose one of the strings without concern for repetition.) ! ! Note that prand() returns the "index" of the string chosen, meaning, ! for example, if it prints the second string, it returns 2. ! ! strand() can be used if you want to choose from more than 7 strings, ! by embedding calls to it within a call to prand(). E.g.: ! ! prand(strand("one","two","three","four"), ! strand("five","six","seven","eight")) ! ! This method will allow, somewhat inefficiently, up to 49 strings. If ! you want more, you could always embed strand() calls within strand() ! calls, but don't, because it's insane. ! ! All of the above describes what happens when the global prand_options ! is 0. If it is set to something, most likely by calling one of the ! wrapper functions, prand() may behave differently. ! ! prand_options takes a bitmap with the following possible components: ! ! PRAND_SEQUENTIAL_FIRST Prints the strings in the order they are ! given, then becomes random. ! ! PRAND_HOLD_ON_LAST After all the strings have been printed ! once, keeps repeating the last one printed. ! ! PRAND_RETURN_STRING Instead of returning the index of the ! string printed, returns the string itself ! (that is, its address). ! ! PRAND_DONT_PRINT Does not print anything, merely returning ! either the index or the string. It also ! does not record the string as having been ! printed. ! ! PRAND_NEW_ONLY If all the strings have already been ! printed once, does nothing. ! ! PRAND_USE_PRINTX (This option only applies if using my ! alternative library, Platypus.) ! Filters the printed string through ! PrintX(). ! ! The wrapper functions, and the options they use, are: ! ! prandonce() PRAND_NEW_ONLY and PRAND_SEQUENTIAL_FIRST ! prandlast() PRAND_HOLD_ON_LAST and PRAND_SEQUENTIAL_FIRST ! prandseq() PRAND_SEQUENTIAL_FIRST ! strand() PRAND_RETURN_STRING and PRAND_DONT_PRINT ! ! You can, of course, also set prand_options manually before calling ! prand(). (Note that prand_options is reset to 0 after calling any ! wrapper function.) You can also define your own wrappers. But you ! knew that already. System_file; Default PS_TAB_SIZE = 1000; Array printed_strings --> PS_TAB_SIZE; Array ps_temp->7; Global ps_tab_entries; Global ps_tab_index = -1; Global prand_options; Constant PRAND_SEQUENTIAL_FIRST = $1; Constant PRAND_HOLD_ON_LAST = $2; Constant PRAND_RETURN_STRING = $4; Constant PRAND_DONT_PRINT = $8; Constant PRAND_NEW_ONLY = $10; Constant PRAND_USE_PRINTX = $20; [ prandonce s1 s2 s3 s4 s5 s6 s7 a; prand_options = PRAND_NEW_ONLY + PRAND_SEQUENTIAL_FIRST; a = prand(s1,s2,s3,s4,s5,s6,s7); prand_options = false; return a; ]; [ prandlast s1 s2 s3 s4 s5 s6 s7 a; prand_options = PRAND_HOLD_ON_LAST + PRAND_SEQUENTIAL_FIRST; a = prand(s1,s2,s3,s4,s5,s6,s7); prand_options = 0; return a; ]; [ strand s1 s2 s3 s4 s5 s6 s7 a; prand_options = PRAND_RETURN_STRING + PRAND_DONT_PRINT; a = prand(s1,s2,s3,s4,s5,s6,s7); prand_options = 0; return a; ]; [ prandseq s1 s2 s3 s4 s5 s6 s7 a; prand_options = PRAND_SEQUENTIAL_FIRST; a = prand(s1,s2,s3,s4,s5,s6,s7); prand_options = 0; return a; ]; [ prand s1 s2 s3 s4 s5 s6 s7 i a str fl c; if (s1) { a++; i = FindByWord(s1, printed_strings, ps_tab_entries); if (i == -1) { ps_temp->c = 1; c++; } } if (s2) { a++; i = FindByWord(s2, printed_strings, ps_tab_entries); if (i == -1) { ps_temp->c = 2; c++; } } if (s3) { a++; i = FindByWord(s3, printed_strings, ps_tab_entries); if (i == -1) { ps_temp->c = 3; c++; } } if (s4) { a++; i = FindByWord(s4, printed_strings, ps_tab_entries); if (i == -1) { ps_temp->c = 4; c++; } } if (s5) { a++; i = FindByWord(s5, printed_strings, ps_tab_entries); if (i == -1) { ps_temp->c = 5; c++; } } if (s6) { a++; i = FindByWord(s6, printed_strings, ps_tab_entries); if (i == -1) { ps_temp->c = 6; c++; } } if (s7) { a++; i = FindByWord(s7, printed_strings, ps_tab_entries); if (i == -1) { ps_temp->c = 7; c++; } } if (c) { if (prand_options & PRAND_SEQUENTIAL_FIRST) a = ps_temp->0; else a = ps_temp->(random(c)-1); jump prandlab01; } if (prand_options & PRAND_NEW_ONLY) rfalse; if (prand_options & PRAND_HOLD_ON_LAST == 0) a = random(a); jump prandlab03; .prandlab01; fl = 1; if (ps_tab_index > -1) { i = ps_tab_index; ps_tab_index++; if (ps_tab_index > PS_TAB_SIZE) ps_tab_index = 0; } else { i = FindByWord(0, printed_strings, PS_TAB_SIZE); if (i == -1) { i = 0; ps_tab_index = 0; #ifdef DEBUG; print "***printed_strings table full!***^"; #endif; } } .prandlab03; switch(a) { 1: str = s1; 2: str = s2; 3: str = s3; 4: str = s4; 5: str = s5; 6: str = s6; 7: str = s7; } if (prand_options & PRAND_DONT_PRINT) jump prandlab04; if (fl) { ps_tab_entries++; printed_strings-->i = str; } #ifdef platypus_version; if (prand_options & PRAND_USE_PRINTX) PrintX(str); else print (string) str; #endif; #ifndef platypus_version; print (string) str; #endif; .prandlab04; if (prand_options & PRAND_RETURN_STRING) return str; return a; ];