! 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.
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;
}
}