joshua@athertn.Atherton.COM (Flame Bait) (12/14/90)
The routines are designed to write character generation programs, but should be useful for lots of other RPG type applications. There are routines to read in tables, print them, free them, and use them in several different ways. In addition there are some rolling routines which take text strings like "2d4+2" or "1d100" and roll them. The table routines are designed to be object oriented, so you can add new types of tables, and new operations on tables fairly easily. Finally, there are two simple applications, a computer buzzphase generator and a cyberpunk style name generator. I'm planning a 0.5 release to be followed by a 1.0 release, so please email me any problems you have or improvements you make. If you use these routines to write a program longer than 200 lines, please send me its source, so I can include it in my regression testing, and also so I can get a feel for how people are using this package. Thanks. Joshua Levy (joshua@atherton.com) (408) 734-9822 #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # Makefile # RANDOM # README # UPDATES # doc # apps # This archive created: Fri Nov 30 12:07:14 1990 # By: Flame Bait () export PATH; PATH=/bin:/usr/bin:$PATH if test -f 'Makefile' then echo shar: "will not over-write existing file 'Makefile'" else sed 's/^X//' << \SHAR_EOF > 'Makefile' X# X# Makefile for the table and random utility packages X# and some programs which use them. X# by Joshua Levy X# X Xsetup: X cd src ; make libs X cd src ; make execs X cd tst ; make X cd apps ; make X Xclean: X cd src ; make clean X cd apps ; make clean X cd tst ; make clean X cd doc ; make clean X rm -f *~ "*/*~" core X Xshar: clean X shar -p X [A-Z]* doc apps > tablea.shar X shar -p Y src tst > tableb.shar X SHAR_EOF fi if test -f 'RANDOM' then echo shar: "will not over-write existing file 'RANDOM'" else sed 's/^X//' << \SHAR_EOF > 'RANDOM' X XThis is a very brief into to the random number routines. Version 0.3 XBy Joshua Levy X XNote that this is a "presentation layer" random number package. XIt relies on random(3) to generate random number, but presents Xthem to the user in a more useful way, as well as providing Xlogging facilities. X XTo make the *.o file: cc -c random.c XTo make a test executable: cc -DTEST -o rndtest random.c X XInclude the header file (random.h) in you programs. X XTo test the routines make rndtest and try these two UNIX commands: X rndtest <rndtnorm.ts X rndtest <rndtacid.ts SHAR_EOF fi if test -f 'README' then echo shar: "will not over-write existing file 'README'" else sed 's/^X//' << \SHAR_EOF > 'README' X XREADME file for table: a package to manipulate tables (Version 0.3) XBy Joshua Levy X XThis is a set of subroutines to handle tables, such as are commonly used in XFRP and computer games. It also includes some random number routines. X XTo make this stuff, unshar the two files and run make. This should produce Xseveral executables: X in the apps directory, bw and cname X in the src directory tbtest, rndtest, and tb2tbl X XTo use these routines in your own program, you must link with table.a Xand random.o, which are in the src directory. X XThere is documentation in the doc directory, and testing shell scripts in Xthe tst directory. X XRead the file called UPDATES for some change history, but it is not complete. X XIf you find these routine useful, please help me maintain them by doing one Xof the following things: X Write a new test suite, which tests stuff currently untested, or acid X tests something. X Add a new table type. X Add a new message type, or a new option to the print message, (a print X in LaTeX message would be great, so would pre loaded C code). X Send me a sample application. X Extend the random routines. X XThanks. X XJoshua Levy X905 W. Middlefield Apt. 946 XMountain View, CA X94043 X(408) 734-9822 Xjoshua@atherton.com X XLegal Stuff: X XThis package (source code and documentation) is covered by the GNU XGENERAL AGREEMENT, commonly known as the "copyleft". If you want Xto do something not allowed by the copyleft, contact the author Xto arrange a seperate agreement. X X X SHAR_EOF fi if test -f 'UPDATES' then echo shar: "will not over-write existing file 'UPDATES'" else sed 's/^X//' << \SHAR_EOF > 'UPDATES' X XChanges to the Table and Random routines since version 0.1. XListed newest changes to oldest. XBy Joshua Levy X XKnown problems with 0.3: X XShould be able to put comments in table files (starting with '#') X XThe ra_roll routine needs to accept more types of dice rolls. For example, X it should know about "discard the worst dice roll", "ignore rolls under N", X and so on. X X X XChanges from 0.2 to 0.3: X XAdded new message tb_many, to roll many times on the same table, returing Xdifferent answers each time. X XThere is now documenation specifically describing how to add new table types. X XAdded a new table type, the SimpleBig type. X XThe ra_random man page does documents the ra_logging and ra_float call. X XNeed an ra_query routine to return a roll's min, max, average, and legality. X XChanges from 0.1 to 0.2: XAdded log/replace facility to random number generator. XAdded crude floating point generator. XRemoved some untested macros from the table.h file. XCleaned and commented the code. XFixed bugs in and improved the table.man manual page. XReplaced the random number test program with a better one. XStarted a test suite for the random number generator. SHAR_EOF fi if test ! -d 'doc' then mkdir 'doc' fi cd 'doc' if test -f 'random.man' then echo shar: "will not over-write existing file 'random.man'" else sed 's/^X//' << \SHAR_EOF > 'random.man' X.ig XC X% nroff -man random.man | more X%n nroff -man random.man | lpr X%t ptroff -man random.man -Plw X.XC X.TH RA_RANDOM 3 "November 1990" X.SH NAME Xra_random \- random number generation routines X.SH SYNOPSIS X.nf X#include "random.h" X Xint ra_roll(str) char *str ; X Xchar *ra_card() X Xint ra_random(max) int max ; X Xint ra_seed(seed) int seed ; X Xdouble ra_float() X Xint ra_query(str,what) char *str ; int what ; X Xint ra_logging(state,filename) int state ; char *filename ; X.fi X.SH DESCRIPTION X.IP ra_roll XThis routine takes a text representation of a dice roll, and returns a Xnumber rolled. Sample dice rolls are "1d10", "2d4", "3d10+2", or "4d4-1". X.IP ra_card XThis call returns a random card from a playing deck (minus jokers). XThe returned pointer is to a static string containing a number and a lower Xcase letter, for example "4s" or "12d" for the four of spades and queen Xof diamonds, respectively. X.IP ra_random XTakes a number and returns a random number between 1 and the number passed Xin. X.IP ra_seed XInitializes the random number stream. It's one argument is the new seed. XUse a seed of zero for debugging (for reproducablity) but some other number Xfor real use. X.IP ra_float XThis call returns a random floating point number between 0 and 1. I'm not Xreally sure how random it is though; it is experimental. X.IP ra_query XThis function returns information about a dice roll. The roll you are Xasking about is the first argument. The second argument controls what Xis returned: X.RS X.IP RA_MAX XReturns the largest number this roll can generate. X.IP RA_MIN XReturns the small number this roll can generate. X.IP RA_AVE XReturns the average number which this roll will generate. X.IP RA_LEGAL XReturns true (1) if the string passed in is a legal dice roll. Returns Xfalse (0) if it is not. X.RE X.sp 1 X.IP ra_logging XThis routine enables or disables logging an playback of random numbers. XIt is designed help testing/debugging by recreating the same random number Xstream over and over. The first argument is the command, the second is Xa file name. The commands are in random.h: X.RS X.IP RA_NORMAL XReturns to the normal state. Random number are generated on the fly and Xnot logged. The second argument is ignored. X.IP RA_PLAY XRandom numbers are not generated, but read from the file passed in as the Xsecond argument. By convention these files end in ".rl" for random log. X.IP RA_LOG XRandom number are generated on the fly and stored in a random log file Xfor later playback. The log file name is the second command. X.RE X.sp 1 XIn theory, both play and log can be active at the same time, but this is Xan untested configuration. Both play and log are turned off by normal. X.IP ra_stddev X<<NOT YET IMPLEMENTED>> X.SH "EXAMPLES" X.nf XNot done yet. Look at random.c, tablesimple.c and tablemulti.c. X.fi X.SH "SEE ALSO" X.PP XThese routines use random(3) to generate random numbers. X.SH "BUGS" X.IP \(bu XThese routines rely on the local C library to provide raw random numbers. XThey should come with there own generator. X.SH AUTHOR X.PP XThe random routines were written by Joshua Levy. X.br Xjoshua@atherton.com Home: (415) 968-3718 Work: (408) 734-9822 X.IP "\(co 1989 Joshua Levy" XThis man page and the code it describes is covered by the GNU general Xpublic license, commonly called the "copyleft". It can only be used or Xredistributed under the terms of that agreement. Persons or corporations Xwishing to use this code in ways not allowed by the GNU license should Xcontact the author to discuss other licensing agreements. X.br SHAR_EOF fi if test -f 'tb-execs.man' then echo shar: "will not over-write existing file 'tb-execs.man'" else sed 's/^X//' << \SHAR_EOF > 'tb-execs.man' X.ig XC X% nroff -man tb-execs.man | more X%n nroff -man tb-execs.man | lpr X%t ptroff -man tb-execs.man -Plw X.XC X.TH TABLE-EXECS 1 "Dec 27th 1989" X.SH NAME Xtable-exec \- the executables shipped with table: table, tb2tbl, rndtest, bw X.SH SYNOPSIS X.nf Xtable <table.file> <number> Xtb2tbl <table.file> Xrndtest Xtbtest Xbw <seed> <number> X.fi X.SH DESCRIPTION X.IP table XThis is a simple front end to the table routines, designed for testing. XTable takes two arguments. The name of the file containing the table, Xand the number of times to roll on that table. Neither of these arguments Xare optional. X.IP tb2tbl XThis program takes one argument, a table file, which it translates Xinto troff/tbl format and write to the standard output. X.IP rndtest XThis is a simple front end to the random number generation routines, Xdesigned for testing. It takes no arguments, but interactively reads in Xan executes commands, untill it reads a quit or an EOF. The commands it Xaccepts are: X.RS X.IP "seed <new-seed>" XThis calls the ra_seed routine, which changes the seed number used by the Xunderlieing random number generator. X.IP "roll <number> <dice>" XThis calls the ra_roll routine <number> times. <Dice> is the dice roll to Xuse. X.IP "card <number>" XThis calls the ra_card routine <number> times. X.IP "log <what> <where>" XThis calls the ra_logging routine. X.RE X.IP tbtest XThis is a simple front end to the table routines, designed for testing. XIt takes no arguments, but reads commands from a script. The commands Xit knows about are: X.RS X.IP "read" XReads in a table and makes it the current table. It takes one argument, Xthe file to read in the table from. X.IP "free" XFrees the current table. X.IP "use" XUses the current table. X.IP "many" XUses the current table many times. X.IP "back" X.IP "print" XPrints out the current table. X.IP "help" XPrints out some help. X.IP "quit" XTo exit from the program. X.RE X.IP bw XA buzzphase generator. Its first argument is a random number seed, Xand its second is the number of phrases it should generate. They Xare written to the standard output, one per line. X.SH EXAMPLES X.nf Xtable simp1.tab 10 Xtable multi1.tab 5 Xtb2tbl bw2.tab | tbl | nroff -me | col | more Xbw 0 10 Xbw 10 10 X.fi X.SH "SEE ALSO" X.PP Xra_random(3), table(3). X.SH "BUGS" X.SH AUTHOR X.PP XThese programs were written by Joshua Levy at Atherton Technology. X.br Xjoshua@atherton.com Home: (415) 968-3718 Work: (408) 734-9822 X.IP "\(co 1989 Joshua Levy" XThis man page and the code it describes is covered by the GNU general Xpublic license, commonly called the "copyleft". It can only be used or Xredistributed under the terms of that agreement. Persons or corporations Xwishing to use this code in ways not allowed by the GNU license should Xcontact the author to discuss other licensing agreements. X.br SHAR_EOF fi if test -f 'Makefile' then echo shar: "will not over-write existing file 'Makefile'" else sed 's/^X//' << \SHAR_EOF > 'Makefile' X Xclean: X rm -f *~ *.bak #*# SHAR_EOF fi if test -f 'table.man' then echo shar: "will not over-write existing file 'table.man'" else sed 's/^X//' << \SHAR_EOF > 'table.man' X.ig XC X% nroff -man table.man | more X%n nroff -man table.man | lpr X%t ptroff -man table.man -Plw X.XC X.TH TABLE 3 "Feb 22th 1990" X.SH NAME Xtable \- table handling routines for role playing and computer games X.SH SYNOPSIS X.nf X#include "table.h" X Xint tb_read(filename,table) char *filename ; table_t **table ; X Xint tb_use(table,...,result) table_t *table ; ... char **result ; X Xint tb_print(table,filename,way) table_t *table ; char *filename ; int way ; X Xint tb_many(table,num,...,result) table_t *table ; int num ; ... char **result ; Xint tb_free(table) table_t *table ; X Xint tb_query(table,query,result) table_t *table ; int query ; int *result ; X.fi X.SH DESCRIPTION X.IP tb_read XGiven a pointer to a pointer to a table, and the name of a file, this Xroutine reads the text representation of a table into the table variable, Xusing malloc(3) to allocate memory as needed. X.IP tb_use XGiven a poniter to a table, a pointer to a pointer to characters, and X(optionally) other arguments, this routine uses the table and a random Xnumber generator to "roll" on the table. The number and type of optional Xarguments depends on the type of table being used. Simple tables Xrequire no extra arguments, but multi and change tables require a Xstring which determines which column on the table to use. For example: X X.nf Xtable_t *foo ; Xchar *result ; Xtb_use(foo,&result) ; /* assumes foo is a simple table */ Xtb_use(foo,"column1",&result) ; /* assumes foo is a multi table */ Xtb_use(foo,"column1",&result) ; /* assumes foo is a change table */ X.fi X XNote that the result points at a static buffer, which must not be changed Xand which may disappear during the next tb_use call. X.IP tb_print XGiven a pointer to a table and a file name, this routine prints out a Xcopy of the file. The third argument determines the form the table is Xprinted out in. Right now, 1 prints it out in troff/tbl format, and X0 is reserved for future work. This routine is useful for debugging, as Xwell as to generate documentation. X.IP tb_many XThis routine is similar to tb_use, execpt that it returns several rolls Xfrom the table which are different. The extra argument ``num'' is the Xnumber of rolls. The result should be an array of character pointers Xlarge enough to hold all the answers. X.IP tb_free XGiven a pointer to a table, this routines frees the space associated Xwith the table. After calling this routine the only function call which Xis legal on the table is tb_read. This routine calls free(3). X.IP tb_query XGiven a pointer to a table, and a question about that table, result will Xbe filled with the answer to the question. Currently supported queries Xinclude: X.RS X.IP TB_Q_MAX XReturns the largest roll which can be made on this table. X.IP TB_Q_MIN XReturns the smallest roll which can be made on this table. X.IP TB_Q_AVE XReturns the average roll made on this table. X.RE X.bp X.SH "TABLE TYPES" X.PP XThis package support several different types of tables, and new types Xcan be added with a recompile (see the man page on table-add). Here Xis a description of all of the table types which are currently supported. X.IP "Simple" XThis is the simplest form of table. It is a list of rolls and the results Xfor each roll. An example would be a table of possible races for NPCs, or Xa list of possible home towns. X.IP "Multiple" XThese tables contain one column for the dice roll, but several columns Xeach of which contains a result in different situations. An example Xmight be a PC hight table, with different columns for each race. Or a Xyearly income table, with different columns for each class. When using Xthese tables, you must specify which column is important. X.IP "SimpleBig" XThis table is very similar to the simple table. The difference is in Xformatting. This table is designed to return large chuncks of text, Xlike sentences and paragraphs. The simple tables are designed to return Xwords or lines. X.bp X.SH "FILE FORMATS" X.PP XThe files read by tb_read must be formatted correctly. The format for Xeach type of table (simple, multi, etc.) is different, but the first Xline is always the same: the name of the table followed by its type. X.PP XSimple tables have a line with the type of roll to make and the number Xof rows in the table, seperated by a tab. The third line is the source Xof the table. The fourth, and all following lines, are rows of the table, Xeach row contains a number (or two numbers seperated by a dash) followed Xby a tab, and the result. X.PP XMultiple tables are more complicated. Their second row is the roll, the Xnumber of rows, and the number of columns; all separated by tabs. The number Xof columns does not include the results column. The third line is the source Xof the table. The fourth line are the column headers; each header is Xseparated by a tab. The first column is used for the roll, so it is Xuntitled. The fifth line, and all other rows are rows of the table; they Xstart with the roll and then have each result. Each field is separated by Xa tab. X.bp X.SH "EXAMPLE FILES" X.LP XHere is a sample simple table file (The `::' charaters are tabs): X.nf XPay-off results table::Simple X2d6::9 Xp13 of The Complete Tavern X2::Banker loses triple, passes dice X3::Banker loses double, passes dice X4::Banker loses double X5::Banker loses X6::Banker loses half of bet X7::Stand off, rethrow X8-9::Banker wins bet X10-11::Banker double bet X12::Banker triple bet X.fi X.LP XHere is an example multiple table file ("::" are tabs): X.nf XBasic Test::Multiple X2d6::6::4 Xmy mind X-::Elf::Human::Dwarf::Troll X2::e2::h2::d2::t2 X3::e3::h3::d3::t3 X4-7::e4::h4::d4::t4 X8-9::e8::h8::d8::t8 X10::e10::h10::d10::t10 X11-12::e11::h11::d11::t11 X.fi X.bp X.SH "EXAMPLE CODE" X.nf X/* X * Routine to tralate a table stored in file infile into a troff/tbl X * document, which is in outfile. X */ Xtb2tbl(infile,outfile) char *infile ; char *outfile ; X{ X table_t *tab ; X int sts ; X X sts = tb_read(infile,&tab) ; assert(sts==TB_E_OK) ; X sts = tb_print(tab,outfile,1) ; assert(sts==TB_E_OK) ; X sts = tb_free(tab) ; assert(sts==TB_E_OK) ; X} X/* X * Routine read in a table, and then rolls on it repeatedly, printing X * the result of each roll to the screen. X */ X Xroll(tabfile,times) char *tabfile ; int times ; X{ X table_t *tab ; X char *str ; X int sts ; X int i ; X X sts = tb_read(infile,&tab) ; assert(sts==TB_E_OK) ; X for(i=0 ; i<times ; i++) { X sts = tb_use(tab,&str) ; X printf("result %d was %s\\n",i+1,str) ; X } X sts = tb_free(tab) ; assert(sts==TB_E_OK) ; X} X.fi X.bp X.SH DIAGNOSTICS X.TP 15 XTB_E_OK XEverything worked fine. X.TP 15 XTB_E_MISC XGeneral purpose error message. Something went wrong. X.TP 15 XTB_E_NOTYET XFeature not yet implemented. X.TP 15 XTB_E_NOFILE XThe external table file you wanted to read does not exist. X.TP 15 XTB_E_NO_COL XNo column in the table iwth that name. For multiple column tables, you Xmust pass a column name to tb_use or tb_choose, but your name does not Xmatch one in the table. X.TP 15 XTB_E_NOTYPE XThe type of the table you passed to a tb_ routine is not a legal type. XCurrently the legal types are 1 (Simple) and 2 (Multi). Either you are Xexperimenting with new types, or (more likely) the table pointer you Xpassed to a tb_routine points to garbage. X.TP 15 XTB_E_TOOMANY XYou have asked the tb_many routine for too many answers. The the table Xonly contains 10 possible answers (for example) and you ask for 12, Xyou will get this error. Since tb_many must return as many unique answers Xas you ask for, it will return this error if there are not that many Xunique answers in the table. X.SH "SEE ALSO" X.PP XThese routines use ra_random(3) to generate random numbers. X.SH "BUGS" X.IP \(bu XUsing strange file names to specify stdout and stderr in tb_print is Xa sleezy hack. Also, there is no way to write this to a file descriptor Xwhich is already open. X.SH AUTHOR X.PP XThe table routines were written by Joshua Levy at Atherton Technology. X.br Xjoshua@atherton.com Home: (415) 968-3718 Work: (408) 734-9822 X.IP "\(co 1989 Joshua Levy" XThis man page and the code it describes is covered by the GNU general Xpublic license, commonly called the "copyleft". It can only be used or Xredistributed under the terms of that agreement. Persons or corporations Xwishing to use this code in ways not allowed by the GNU license should Xcontact the author to discuss other licensing agreements. X.br X X SHAR_EOF fi if test -f 'tb-add.man' then echo shar: "will not over-write existing file 'tb-add.man'" else sed 's/^X//' << \SHAR_EOF > 'tb-add.man' X.ig XC X% nroff -man tb-add.man | more X%n nroff -man tb-add.man | lpr X%t ptroff -man tb-add.man -Plw X.XC X.TH TABLE-ADD 3 "Feb 22th 1990" X.SH NAME Xtable-add \- instructions for adding new table and messagte types to the table routines X.SH SYNOPSIS X.PP XThis page describes how to add new table types to the table package. XIt also discusses how to add new messages. X(It is not really tested, but should give you a flavor of what to do.) X.SH OVERVIEW X.PP XThe code in table.c is a very simple dispatch mechanism for a very Xsimple object oriented system. To add a new table type you must Xfirst tell the dispatch system about it, and then write the "message Xhandling" or method routines, which the dispatcher will call for you. X.PP XThe most complicated of these routines is the read routine, which Xreads the table from a disk file. This routine implicitly defines Xthe text format used to store the new table type. The format is Xvery important, since that is how tables are created and modified Xby people. X.SH DESCRIPTION X.IP "Create a sample table file." XI always start with the format of the table file. I Xcreate a sample which will be used as the first test case. The cat Xcommand with the -e and -t flags is great for making sure you put Xtabs in all the right price. Here are the guidelines I use in designing Xthese files: X.RS X.IP 1 XThe first line should contain the table's title and its type. X.IP 2 XThe second line should contain the dice roll used on this tabel, Xand all information about the size of the table. After reading Xthe first two lines, the tb_read routine should have enough Xinformation to allocate space for the table structure. X.IP 3 XThe third line should contain the source of this table. A title and Xpage number, or the person who came up with the table are fine here. X.IP 4 XOther lines might contain other control type information. X.IP 5 XFinally, the lines which describe the actual table. Ideally, the Xfile should look like the table, so that it is as easy as possible Xto copy tables from books and magazine articles. X.RE X.IP "Add a new type to the tba_type table." XAbout a third of the way down the table.c file is an array of structures Xcalled tba_type. Add a new structure to this array and the second to last Xitem. The first field in the structure should be the (capitalized) name Xof your new table type. The second field should be it's unique number. XA sample new structure is "{"New",10}". The new list would like like this: X{"Simple", 1}, {"Multiple",2}, {"New",3}, {NULL, 0}. The number you used Xshould be one more than the number currently in use. X.IP "Add new methods to the dispatch tables." XRight after the tba_type array are the arrays used to dispatch messages. XAdd your routines after the routines already there. If a given message Xis legal, then put in illegal. Note that table type 0 does not exist, Xso an message sent to 0 is illegal. That is why the first entry in each Xarray is illegal. X.IP "Create the new data structure." XThis is pretty easy. Make sure the first field is an integer called Xtype, so that the structure overlay code works correctly. They just Xtranslate each field from you table file to be a field in your structure. XWhere possible, try to have similar fields in other table structures Xoverlay with fields in your structure. This data structure, as well Xas the declarations for your new method functions should be put in a Xfile called tablenew.h. Add this file to the other .h files included Xin table.h. Your structure should be called tablenew_t. X.IP "Naming Convensions" X.PP XThe file which contains your methods should be named tablenew.c, assuming Xyour file type is called new. The any public functions which you write, Xespecially method functions, should be named tb_new_ followed by the name Xof the message (read, print, use, many, free). X.IP "Write Methods" X.RS X.IP "read" XThe first method I write is the read routine, since it is the most Xdifficult, and required for all the other routines. <<<add>>> X.IP XThe interface for this program should look like this: X.br Xint tb_new_read(rt,fp,title) table_t **rt ; FILE *fp ; char *title ; X.br X.IP "tbl" XThe second method I write is the tbl routine, since it tests the read Xroutine and makes sure that all the data really is put into the table Xstructure properly. X.IP XThe interface for this program should look like this: X.br Xint tb_new_tbl(tab,fp,way) table_t *tab ; FILE *fp ; int way ; X.br X.IP "use" X.IP XThe interface for this program should look like this: X.br Xint tb_new_use(tab,result) table_t *tab ; char **result ; X.br X.IP "free" X.IP XThe interface for this program should look like this: X.br Xint tb_new_free(rt) table_t *rt ; X.br X.RE X.IP "Modify the tb_use routine." X.IP "Add new table type to the test suite." X<<When there is a test suite for tables:>> X.SH "EXAMPLE CODE" X.PP XCurrently there are two table types, simple and multi. Both other these Xcan be used as sample code, to help you understand how all the pieces fit Xtogether. X.SH DIAGNOSTICS X.PP XAll tb_ functions return a negative integer to show that an error Xhas occured. This error codes are listed in table.h, and should be Xused by your code as much as possible. If you need to add an new Xerror code follow these steps: X.IP 1 XAdd the code to table.h using the same format as the error codes already Xthere. X.IP 2 XModify the tb_error routine to print out a useful error message Xwhen the new error occures. X.SH "ADDING MESSAGES" X.PP XTo add a new message to the table routines, you should follow the following Xsteps. <example> X.IP "Add new handler routine." X.IP "Add new message array." X.IP "Add declarations to each table types's .h file" X.IP "Add message handlers to old table types." X.SH REPORTING X.PP XIf you implement a new useful table type, please email it to me, so that XI can integrate it with future releases of the table subroutine package. XThis is imporant, since otherwise, if I add a new type, and you add a Xnew type, they will likely have the same table type number, and cause Xall sorts of problems. The same is true of new error numbers. X.SH AUTHOR X.PP XThe table routines were written by Joshua Levy at Atherton Technology. X.br Xjoshua@atherton.com Home: (415) 968-3718 Work: (408) 734-9822 X.IP "\(co 1989 Joshua Levy" XThis man page and the code it describes is covered by the GNU general Xpublic license, commonly called the "copyleft". It can only be used or Xredistributed under the terms of that agreement. Persons or corporations Xwishing to use this code in ways not allowed by the GNU license should Xcontact the author to discuss other licensing agreements. X.br SHAR_EOF fi if test -f 'tb-script.man' then echo shar: "will not over-write existing file 'tb-script.man'" else sed 's/^X//' << \SHAR_EOF > 'tb-script.man' X.ig XC X% nroff -man table-script.man | more X%n nroff -man table-script.man | lpr X%t ptroff -man table-script.man -Plw X.XC X.TH TABLE-SCRIPT 1 "DEC 1st 1989" X.SH NAME Xtb-script \- the script language to manipulate tables. X.SH SYNOPSIS X.nf Xtbscript <script.file> [<executable>] X.fi X.SH DESCRIPTION X.PP XThis man page describes a piece of software which is not finished Xyet. If you would like it, email me. X.PP X.SH EXAMPLES X.LP XHere is a sample script file. X.nf XSTART X TABLE(one) ; X RESULT(res) ; X X READ("simp1.tab",one) ; X USE(one,res) ; X PRINT(res) ; XEND X.fi X.SH "SEE ALSO" X.PP Xra_random(3), table(3), *.ts for examples X.SH "BUGS" X.SH AUTHOR X.PP XThese programs were written by Joshua Levy at Atherton Technology. X.br Xjoshua@atherton.com Home: (415) 968-3718 Work: (408) 734-9822 X.IP "\(co 1989 Joshua Levy" XThis man page and the code it describes is covered by the GNU general Xpublic license, commonly called the "copyleft". It can only be used or Xredistributed under the terms of that agreement. Persons or corporations Xwishing to use this code in ways not allowed by the GNU license should Xcontact the author to discuss other licensing agreements. X.br SHAR_EOF fi cd .. if test ! -d 'apps' then mkdir 'apps' fi cd 'apps' if test -f 'bw.c' then echo shar: "will not over-write existing file 'bw.c'" else sed 's/^X//' << \SHAR_EOF > 'bw.c' X/* X * BW.C X * Computer Buzzword Generator X * By Joshua Levy X * From specification by . X */ X X#include <stdio.h> X#include <assert.h> X#include <string.h> X#include <ctype.h> X X#include "random.h" X#include "table.h" X Xmain(argc,argv) int argc ; char *argv[] ; X{ X table_t *first, *second, *third ; X char *result1, *result2, *result3 ; X long seed=0 ; X int count=1 ; X int i ; X int sts ; X X /* parse the command line arguments */ X if (argc<=1) { X printf("usage: bw <seed> <number>\n") ; X printf("This will cause generation of <number> of buzzwords.\n") ; X printf("Using <seed> and a random number seed.\n") ; X printf("Seed defaults to 0, count to 1. Buzzword example:\n\n"); X } X if (argc>=2) X seed = atol(argv[1]) ; X if (argc>=3) X count = atoi(argv[2]) ; X X /* X * Initialize the random number generater and the three tables. X */ X ra_seed(seed) ; X sts = tb_read("bw1.tab",&first) ; assert(sts==TB_OK) ; X sts = tb_read("bw2.tab",&second) ; assert(sts==TB_OK) ; X sts = tb_read("bw3.tab",&third) ; assert(sts==TB_OK) ; X X /* X * Print out the three tables (mostly for debugging). X sts = tb_tbl(first,"",0) ; assert(sts==TB_OK) ; X sts = tb_tbl(second,"",0) ; assert(sts==TB_OK) ; X sts = tb_tbl(third,"",0) ; assert(sts==TB_OK) ; X */ X X for(i=0 ; i<count ; i++) { X sts = tb_use(first,&result1) ; assert(sts==TB_OK) ; X sts = tb_use(second,&result2) ; assert(sts==TB_OK) ; X sts = tb_use(third,&result3) ; assert(sts==TB_OK) ; X printf("%s %s %s\n",result1,result2,result3) ; X } X X /* these three frees are not really needed, since the program will end */ X sts = tb_free(first) ; assert(sts==TB_OK) ; X sts = tb_free(second) ; assert(sts==TB_OK) ; X sts = tb_free(third) ; assert(sts==TB_OK) ; X} X X SHAR_EOF fi if test -f 'Makefile' then echo shar: "will not over-write existing file 'Makefile'" else sed 's/^X//' << \SHAR_EOF > 'Makefile' XI=-I../src XS=../src X Xall: cname bw X Xcname: cname.c X cc -o cname cname.c $I $S/random.o $S/table.a -lm X Xbw: bw.c X cc -o bw bw.c $I $S/random.o $S/table.a -lm X Xclean: X rm -f bw cname *~ #*# core X SHAR_EOF fi if test -f 'APPS' then echo shar: "will not over-write existing file 'APPS'" else sed 's/^X//' << \SHAR_EOF > 'APPS' X XThis directory contains some sample applications programs Xwhich have been built on top of the table routines. More Xcomplex examples will be put in subdirectories. X XThe first two examples are pretty trivial (and right now there are no others). X Xbw: Computer buzzphrase generator X This is an example of the simple table type. X Xcname: Cyberpunk style name generator X This is an example of the multi table type. X SHAR_EOF fi if test -f 'buzzwords' then echo shar: "will not over-write existing file 'buzzwords'" else sed 's/^X//' << \SHAR_EOF > 'buzzwords' XFrom athertn!hpda!hplabs!hpfcso!hpldola!hp-lsd!oldcolo!weekley Tue Nov 7 12:33:35 PST 1989 XArticle 5316 of comp.misc: XPath: athertn!hpda!hplabs!hpfcso!hpldola!hp-lsd!oldcolo!weekley X>From: weekley@oldcolo.UUCP (Bob Weekley) XNewsgroups: comp.misc XSubject: COMPUTER BUZZWORD GENERATOR XKeywords: computer buzzword generator XMessage-ID: <[41]comp.misc@oldcolo.UUCP> XDate: 5 Nov 89 13:10:04 GMT XLines: 51 X X X EXPANDED "COMPUTER BUZZWORD" GENERATOR X X The microcomputer revolution has created new words that are as Xincomprehensible as they are sophisticated. We have recently updated a Xtechnique developed in the 1960's called the "Instant Buzzword Generator" Xto help you master this obscure jargon. With it you can create an almost Xendless variety of intelligent-sounding technical terms. X XINSTRUCTIONS: Simply select a number from each of the three columns below Xand combine the words into your own computer buzzword phrases. For example, Xselect "10," "16," and "5" and you generate X "Ergonomic Transitional Capability" Xan expression bound to command instant respect...and confusion! X WATCH YOUR LANGUAGE! X X EXPANDED "COMPUTER BUZZWORD" GENERATOR X 1. Integrated 1. Digital 1. Language X 2. Synchronous 2. Logical 2. Compatability X 3. Sectore 3. Memory 3. Management X 4. On-line 4. Random 4. Options X 5. Batched 5. Default 5. Capability X 6. Relational 6. Third-Generation 6. Network X 7. Dynamic 7. Incremental 7. Parameters X 8. Parallel 8. Interpretive 8. Self-test X 9. Responsive 9. Floppy 9. Matrix X 10. Ergonomic 10. De-bugged 10. Hardware X 11. Alphanumeric 11. Password 11. Device X 12. Optical 12. Protocol 12. Refresh X 13. Functional 13. Run-time 13. Compiler X 14. Formatted 14. Analog 14. Controller X 15. Mnemonic 15. Pixel 15. Flexability X 16. Acknowledged 16. Transitional 16. Contingency X 17. User-friendly 17. Intelligent 17. Duplex X 18. Addressable 18. Virtual 18. Eprom X 19. Enhanced 19. Buffered 19. Subroutine X 20. Monitored 20. Vertical 20. Access X XNote: This all came from a very clever, beautifuly executed, two sided Xfolding Xwhatsoever with LBM. Their card is so fantastic, I thought everyone might Xenjoy it. X ---------------------- XRobert R. Weekley @ oldcolo.UUCP X THE OLD COLORADO CITY ELECTRONIC COTTAGE X | Standard | 2502 W. Colorado Ave. #203; C.S., CO 80904 X |Disclaimer| (719) 632-3391 [8-N-1]; 632-4848 [voice] X X "Freedom is the opportunity for self dicipline" -Dwight D. Eisenhower X----------------------------------------------------------------------------- X- X X SHAR_EOF fi if test -f 'bw1.tab' then echo shar: "will not over-write existing file 'bw1.tab'" else sed 's/^X//' << \SHAR_EOF > 'bw1.tab' XEXPANDED "COMPUTER BUZZWORD" GENERATOR (Table 1) Simple X1d20 20 XBusiness Card by LONG BEACH MICRO; L.B. Calif. X1 Integrated X2 Synchronous X3 Sectore X4 On-line X5 Batched X6 Relational X7 Dynamic X8 Parallel X9 Responsive X10 Ergonomic X11 Alphanumeric X12 Optical X13 Functional X14 Formatted X15 Mnemonic X16 Acknowledged X17 User-friendly X18 Addressable X19 Enhanced X20 Monitored X SHAR_EOF fi if test -f 'bw2.tab' then echo shar: "will not over-write existing file 'bw2.tab'" else sed 's/^X//' << \SHAR_EOF > 'bw2.tab' XEXPANDED "COMPUTER BUZZWORD" GENERATOR (Table 1) Simple X1d20 20 XBusiness Card by LONG BEACH MICRO; L.B Calif X1 Digital X2 Logical X3 Memory X4 Random X5 Default X6 Third-Generation X7 Incremental X8 Interpretive X9 Floppy X10 De-bugged X11 Password X12 Protocol X13 Run-time X14 Analog X15 Pixel X16 Transitional X17 Intelligent X18 Virtual X19 Buffered X20 Vertical X X SHAR_EOF fi if test -f 'bw3.tab' then echo shar: "will not over-write existing file 'bw3.tab'" else sed 's/^X//' << \SHAR_EOF > 'bw3.tab' XEXPANDED "COMPUTER BUZZWORD" GENERATOR (Table 1) Simple X1d20 20 XBusiness Card by LONG BEACH MICRO; L.B Calif X1 Language X2 Compatability X3 Management X4 Options X5 Capability X6 Network X7 Parameters X8 Self-test X9 Matrix X10 Hardware X11 Device X12 Refresh X13 Compiler X14 Controller X15 Flexability X16 Contingency X17 Duplex X18 Eprom X19 Subroutine X20 Access SHAR_EOF fi if test -f 'cname.c' then echo shar: "will not over-write existing file 'cname.c'" else sed 's/^X//' << \SHAR_EOF > 'cname.c' X/* X * CNAME.C X * A Cyberpunk style name generator. X * By Joshua levy X * X% cc -g -I.. -o cname cname.c ../table.a ../random.o X */ X X#include <stdio.h> X#include <string.h> X#include <ctype.h> X#include <assert.h> X X#include "random.h" X#include "table.h" X Xextern char *optarg ; X Xmain(argc,argv) int argc ; char *argv[] ; X{ X table_t *table1 ; X char *result1 ; X char *result2 ; X int count=1, i ; X int sts=0 ; X int seed=0 ; X int ch ; X X if (argc<=1) { X printf("usage: cname -r <rand> -c <count>\nAn example result is:\n") ; X } X while ((ch=getopt(argc,argv,"c:r:")) != -1) { X switch (ch) { X case 'c': count = atoi(optarg) ; break ; X case 'r': seed = atoi(optarg) ; break ; X } X } X ra_seed(seed) ; X tb_read("cname.tab",&table1) ; X assert(sts==TB_OK) ; X X for(i=0 ; i<count ; i++) { X sts = tb_use(table1,"1",&result1) ; X assert(sts==TB_OK) ; X sts = tb_use(table1,"2",&result2) ; X assert(sts==TB_OK) ; X printf("%s%s\n",result1,result2) ; X } X X sts = tb_free(table1) ; X assert(sts==TB_OK) ; X} X X SHAR_EOF fi if test -f 'cname.tab' then echo shar: "will not over-write existing file 'cname.tab'" else sed 's/^X//' << \SHAR_EOF > 'cname.tab' XCyberpunk Style Name Generator Multiple X1d13 13 2 Xmy mind X- 1 2 X1 Live Wire X2 Jack Up X3 Cool Hand X4 Silver Lake X5 Black Ball X6 Jump Down X7 Flash Life X8 Lazer Burn X9 Quick Silver X10 Soft War X11 Low Heat X12 Cyber Punk X13 Comp Sci SHAR_EOF fi cd .. exit 0 # End of shell archive
joshua@athertn.Atherton.COM (Flame Bait) (12/14/90)
If you missed part one of this post, you can get it from the archiver server at atherton.com. Send email to archive-server@atherton.com which contains an empty subject line, but has these lines in its body: path your@email.address send programs table03a.shar Sending email containing just `help' or `index' may also be useful. Joshua Levy (joshua@atherton.com) (408) 734-9822 #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # src # tst # This archive created: Fri Nov 30 12:07:15 1990 # By: Flame Bait () export PATH; PATH=/bin:/usr/bin:$PATH if test ! -d 'src' then mkdir 'src' fi cd 'src' if test -f 'random.h' then echo shar: "will not over-write existing file 'random.h'" else sed 's/^Y//' << \SHAR_EOF > 'random.h' Y/* Y * RANDOM.H Y * By Joshua Levy Y * Header file for any program using random.c Y * Y * See random.c for documentation. Y */ Y Y#ifndef RANDOM_H Y#define RANDOM_H 1 Y Yextern char *ra_card() ; Yextern int ra_roll() ; Yextern int ra_random() ; Yextern int ra_query() ; Yextern void ra_seed() ; Yextern int ra_logging() ; Yextern double ra_float() ; Y Y/* The current version of the random routines */ Y#define RA_VERSION 2 Y Y/* states, to be passed as the first argument to ra_logging */ Y#define RA_NORMAL 0 Y#define RA_PLAY 1 Y#define RA_LOG 2 Y Y/* errors, returned from those routines which return integers */ Y#define RA_OK 0 /* success */ Y#define RA_E_STATE -100 Y#define RA_E_NOFILE -101 Y#define RA_E_BADQUERY -102 Y Y/* types of queries */ Y#define RA_MAX 1 Y#define RA_MIN 2 Y#define RA_AVE 3 Y#define RA_LEGAL 4 Y Y#endif SHAR_EOF fi if test -f 'random.c' then echo shar: "will not over-write existing file 'random.c'" else sed 's/^Y//' << \SHAR_EOF > 'random.c' Y/* Y * RANDOM.C Y * Random routines for FRP games Y * By Joshua Levy Y * Y% cc -g -c random.c Y%t cc -g -DTEST -o rndtest random.c -lm Y * Y * This modual has five "functional" entry points: Y * int ra_roll(str) char *str ; Y * char *ra_card() Y * int ra_random(n) int n ; Y * int ra_float() Y * int ra_query(str,quest) char *str ; int quest ; Y * int ra_gasdev() ; Y * int ra_range(low,middle,high) int low, middle, high ; Y * Y * and two "state" entry points: Y * Y * void ra_seed(seed) long seed ; Y * This initializes the random number generator, if it is not called Y * the random number generator will be in an unknown state. Passing Y * zero will usually generate a repeatable series of numbers and is Y * good for debugging. A different number should be used "for real". Y * int ra_logging(state,filename) int state ; char *filename ; Y * This allows the program to log all of the random numbers it Y * generates, and also use random number from the log, if desired. Y * Y * Configuation Y * I have used random and srandom, since they are available on my Y * UNIX system, and are better than rand and srand which are more Y * widely available. Y */ Y Y#include <sys/types.h> Y#include <stdio.h> Y#include <assert.h> Y#include <values.h> /* only used for MAXINT */ Y Y#include "random.h" Y Ystatic int ra_state = RA_NORMAL ; Ystatic FILE *ra_log = NULL , *ra_play = NULL ; Y Y/* Y * If you want to use a different random number generator, you Y * should only need to change things on this page, from here down. Y */ Y Yextern long random() ; Y Yint ra_random(n) unsigned int n ; Y{ Y int result ; Y int s ; Y Y if (ra_state & RA_PLAY) { Y assert(ra_play) ; Y s = fscanf(ra_play,"%d ",&result) ; Y if (s==EOF) { Y#ifndef REPEAT Y printf("ra_random: prematurely reached end of logging file.\n") ; Y printf(" continuing with random numbers\n") ; Y fclose(ra_play) ; Y ra_play = (FILE*)NULL ; Y ra_state ^= RA_PLAY ; Y result = random()%n+1 ; Y#else Y fseek(ra_play,0L,0) ; Y s = fscanf(ra_play,"%d ",&result) ; Y#endif Y } Y } else { Y result = random()%n+1 ; Y } Y if (ra_state & RA_LOG) { Y assert(ra_log) ; Y fprintf(ra_log,"%d ",result) ; Y } Y return result ; Y} Y Yvoid ra_seed(seed) int seed ; Y{ Y srandom(seed) ; Y} Y Yint ra_logging(state,filename) int state ; char *filename ; Y{ Y char buf[100] ; Y time_t made ; Y Y if ( state!=RA_NORMAL && state!=RA_PLAY && state!=RA_LOG ) Y return RA_E_STATE ; Y if (state>0) Y ra_state |= state ; Y else if (state<0) Y ra_state ^= state ; Y else /*state==0*/ Y ra_state = state ; Y switch (state) { /* remember the switch fall through rules */ Y case RA_NORMAL: Y if (ra_play) { fclose(ra_play) ; ra_play = (FILE*)NULL ; } Y if (ra_log) { fclose(ra_log) ; ra_log = (FILE*)NULL ; } Y break ; Y case -RA_PLAY: Y if (ra_play) { fclose(ra_play) ; ra_play = (FILE*)NULL ; } Y break ; Y case -RA_LOG: Y if (ra_log) { fclose(ra_log) ; ra_log = (FILE*)NULL ; } Y break ; Y case RA_PLAY: Y ra_play = fopen(filename,"r") ; Y if (!ra_play) Y return RA_E_NOFILE ; Y fgets(buf,sizeof(buf),ra_play) ; Y /* right now, no check is made */ Y break ; Y case RA_LOG: Y ra_log = fopen(filename,"w") ; Y if (!ra_log) Y return RA_E_NOFILE ; Y made = time((time_t*)0) ; Y fprintf(ra_log,"ra_log_file %d %s",RA_VERSION,ctime(&made)) ; Y break ; Y } Y return ra_state ; Y} Y Ychar *ra_card() Y{ Y static char ret[10] ; Y static char allsuites[5] = "cdhs" ; Y Y int card = ra_random(12) ; Y int suit = ra_random(4)-1 ; Y Y sprintf(ret,"%d%c",card,allsuites[suit]) ; Y return ret ; Y} Y Y/* Y * Bug: first number is required: 1d20 , 1d100, etc. Y * (d20 will fail for example) Y */ Yra_roll(t) char *t ; Y{ Y int num=0, del=0 ; Y unsigned int type=0 ; Y char dice='d', sign='+' ; Y int v=0 ; Y int i ; Y int s ; Y Y s = sscanf(t,"%d%c%u%c%d",&num,&dice,&type,&sign,&del) ; Y if (s==3) { Y sign = '+' ; Y del = 0 ; Y } Y for(i=0 ; i<num ; i++) Y v += ra_random(type) ; Y if (sign=='+') Y v += del ; Y else Y v -= del ; Y return v ; Y} Y Yint ra_query(roll,what) char *roll ; int what ; Y{ Y int num=1, del=0 ; Y unsigned int type=0 ; Y char dice='d', sign='+' ; Y int v=0 ; Y int i ; Y int s ; Y int legal=1 ; Y Y if (roll[0]=='d' || roll[0]=='D') { Y s = sscanf(roll,"%c%u%c%d",&dice,&type,&sign,&del) ; Y s += 1 ; Y } else { Y s = sscanf(roll,"%d%c%u%c%d",&num,&dice,&type,&sign,&del) ; Y } Y if (s!=5 && s!=3) { Y legal = 0 ; Y } Y if (s==3) { Y sign = '+' ; Y del = 0 ; Y } else { Y if (sign=='-') Y del = -del ; Y } Y if (dice!='d' && dice!='D') { Y legal = 0 ; Y } Y switch (what) { Y case RA_MAX: Y return num*type+del ; Y case RA_MIN: Y return num+del ; Y case RA_AVE: Y return (num*(type/2))+del ; Y case RA_LEGAL: Y return legal ; Y default: Y return RA_E_BADQUERY ; Y } Y /*NOTREACHED*/ Y} Y Yfloat ra_float() Y{ Y float x ; Y x = (ra_random(MAXLONG)-1)/(MAXLONG+1.0) ; Y return x ; Y} Y Y/* Y * The following routine is taken from SOFTWARE RECIPIES IN C Y * By Press, Flannery, and a cast of thousands. Y * Look on page 217 (section 7.2) Y */ Yfloat ra_gasdev() Y{ Y static int iset=0 ; Y static float gset ; Y float fac,r,v1,v2 ; Y Y if (iset==0) { Y do { Y v1 = 2.0*ra_float()-1.0 ; Y v2 = 2.0*ra_float()-1.0 ; Y } while (r >= 1.0) ; Y fac = sqrt(-2.0*log(r)/r) ; Y gset = v1*fac ; Y iset = 1 ; Y return v2*fac ; Y } else { Y iset=0 ; Y return gset ; Y } Y} Y Yra_range(low,middle,high) int low ; int middle ; int high ; Y{ Y float temp ; Y Y temp = ra_gasdev() ; Y temp = temp/3.0 ; Y if (temp==0.0) return middle ; Y if (temp>0.0) return (int) (middle+(temp*(high-middle))) ; Y if (temp<0.0) return (int) (middle-(temp*(middle-low))) ; Y return middle ; Y} Y#if 0 Y/* Y * It should be used when you need to implement rules like: "the player Y * can allocate 4 skill points amoung the following six rules." This Y * would be implemented with a call like ra_allocate(4,6,"flat"). Y * total is the total number of things to be allocated. Y * bins is the number of places things can go. Y * method is the algorithm you want to use to do the allocation. Y * legal methods are: any dice roll, at floating point text. Y * This routine returns an array of integers of bins size, which is static Y * and will be reused with the next call. Y */ Yint *ra_allocate(total,bins,method) int total ; int bins ; char *method ; Y{ Y ; Y} Y#endif Y Y#if TEST Y Y#define CHECK_ARG_COUNT(num) \ Y if (num!=count-1) { \ Y printf("rndtest (%s): got %d args, but expeced %d args\n", \ Y comm,count-1,num) ; \ Y continue ; } \ Y Ymain() Y{ Y char buf[1000] ; Y char arg1[20], arg2[20], arg3[20], arg4[20] ; Y char comm[20] ; Y int count ; Y int echo = 0 ; Y int i,m ; Y Y while (fgets(buf,sizeof(buf),stdin)) { Y if (echo) Y printf("%s",buf) ; Y count = sscanf(buf,"%s %s %s %s %s",comm,arg1,arg2,arg3,arg4) ; Y if (!strcmp(comm,"quit")) { Y exit(0) ; Y } else if (!strncmp(comm,"#",1)) { Y continue ; Y } else if (!strcmp(comm,"echo")) { Y echo = 1 ; Y } else if (!strcmp(comm,"roll")) { Y CHECK_ARG_COUNT(2) ; Y m = atoi(arg1) ; Y for(i=0 ; i<m ; i++) Y printf("%d ",ra_roll(arg2)) ; Y printf("\n") ; Y } else if (!strcmp(comm,"query")) { Y CHECK_ARG_COUNT(2) ; Y m = atoi(arg1) ; Y if (!m) { Y if (!strcmp(arg1,"RA_MIN")) Y m = RA_MIN ; Y else if (!strcmp(arg1,"RA_MAX")) Y m = RA_MAX ; Y else if (!strcmp(arg1,"RA_AVE")) Y m = RA_AVE ; Y else if (!strcmp(arg1,"RA_LEGAL")) Y m = RA_LEGAL ; Y } Y printf("%d\n",ra_query(arg2,m)) ; Y } else if (!strcmp(comm,"card")) { Y CHECK_ARG_COUNT(1) ; Y m = atoi(arg1) ; Y for(i=0 ; i<m ; i++) Y printf("%s ",ra_card()) ; Y printf("\n") ; Y } else if (!strcmp(comm,"seed")) { Y CHECK_ARG_COUNT(1) ; Y ra_seed(atoi(arg1)) ; Y } else if (!strcmp(comm,"log")) { Y CHECK_ARG_COUNT(2) ; Y ra_logging(atoi(arg1),arg2) ; Y } else if (!strcmp(comm,"float")) { Y CHECK_ARG_COUNT(1) ; Y m = atoi(arg1) ; Y for(i=0 ; i<m ; i++) { Y printf("%g ",ra_float()) ; Y if (!(i%5)) printf("\n") ; Y } Y printf("\n") ; Y } else if (!strcmp(comm,"gasdev")) { Y CHECK_ARG_COUNT(1) ; Y m = atoi(arg1) ; Y for(i=0 ; i<m ; i++) Y printf("%g ",ra_gasdev()) ; Y printf("\n") ; Y } else if (!strcmp(comm,"range")) { Y CHECK_ARG_COUNT(4) ; Y m = atoi(arg1) ; Y for(i=0 ; i<m ; i++) Y printf("%g ",ra_range(atoi(arg2),atoi(arg3),atoi(arg4))) ; Y printf("\n") ; Y } else { Y printf("Illegal test command. Legal commands are:\n") ; Y printf("quit, roll, card, seed, float, log, query, gasdev, and range.\n") ; Y printf("Note that these are all lower case names.\n") ; Y } Y } Y printf("\n") ; Y exit(0) ; Y} Y Y#endif Y SHAR_EOF fi if test -f 'tablesimple.h' then echo shar: "will not over-write existing file 'tablesimple.h'" else sed 's/^Y//' << \SHAR_EOF > 'tablesimple.h' Y/* Y * TABLESIMPLE.H Y * By Joshua Levy Y * This header routine should only be included in table.c and tablesimple.c! Y * It must be before the include file for table.h Y */ Yextern int tb_simple_back() ; Yextern int tb_simple_choose() ; Yextern int tb_simple_free() ; Yextern int tb_simple_print() ; Yextern int tb_simple_read() ; Yextern int tb_simple_use() ; Y Ytypedef struct { Y int first ; Y int last ; Y char *result ; Y} simplerow_t ; Y Ytypedef struct { Y int type ; Y char *title ; Y char roll[10] ; Y char *source ; Y int numrows ; Y simplerow_t rows[1] ; Y} simpletable_t ; Y Y SHAR_EOF fi if test -f 'tablemulti.h' then echo shar: "will not over-write existing file 'tablemulti.h'" else sed 's/^Y//' << \SHAR_EOF > 'tablemulti.h' Y/* Y * TABLEMULTI.H Y * By Joshua Levy Y * Y * This header routine should only be included in table.c and tablemulti.c! Y * It must be before the include file for table.h Y */ Y Yextern int tb_multi_back() ; Yextern int tb_multi_choose() ; Yextern int tb_multi_free() ; Yextern int tb_multi_print() ; Yextern int tb_multi_read() ; Yextern int tb_multi_use() ; Y Ytypedef struct { Y int first ; Y int last ; Y char *result[1] ; Y} multirow_t ; Y Ytypedef struct { Y int type ; Y char *title ; Y char roll[10] ; Y char *source ; Y int numrows ; Y int numcols ; Y char **colnames ; Y multirow_t *rows[1] ; Y} multitable_t ; Y Y SHAR_EOF fi if test -f 'Makefile' then echo shar: "will not over-write existing file 'Makefile'" else sed 's/^Y//' << \SHAR_EOF > 'Makefile' Y# Y# Makefile for the table and random utility packages Y# and some programs which use them. Y# by Joshua Levy Y# Y YL = table.a random.o -lm YN = table.a random.o YH = table.h random.h YD = Y#D= -DNEEDDUP YR = ranlib # BSD needs ranlib Y#R = ls # Since SysV does not have ranlib, this is a no op Y Yexecs: rndtest table tb2tbl tbtest Y Ylibs: table.a random.o Y Yall: execs libs Y Yrandom.o: random.c random.h Y cc -g -c random.c Y Ytablesimpbig.o: tablesimpbig.c table.h Y cc -g -c tablesimpbig.c $D Y Ytablemulti.o: tablemulti.c table.h Y cc -g -c tablemulti.c $D Y Ytablesimple.o: tablesimple.c table.h Y cc -g -c tablesimple.c $D Y Ytable.o: table.c table.h Y cc -g -c table.c $D Y Ytable.a: table.h table.o tablesimple.o tablemulti.o tablesimpbig.o Y ar r table.a table.o tablesimple.o tablemulti.o tablesimpbig.o Y $R table.a Y Y# table to troff/tbl conversion program Ytb2tbl: table.c $H $N Y cc -o tb2tbl -g -DTB2TBL table.c $L $D Y Y# table test program Ytable: table.c $H $N Y cc -o table -g -DTEST table.c $L $D Y Ytbtest: tbtest.c $H $N Y cc -o tbtest -g -DTEST tbtest.c $L $D Y Y# random number test program Yrndtest: random.c random.h Y cc -g -DTEST -o rndtest random.c -lm Y Yclean: Y rm -f *~ *.o *.a table tb2tbl rndtest core Y SHAR_EOF fi if test -f 'tablesimple.c' then echo shar: "will not over-write existing file 'tablesimple.c'" else sed 's/^Y//' << \SHAR_EOF > 'tablesimple.c' Y/* Y * TABLESIMPLE.C Y * Code supporting rolling on simple tables Y * By Joshua Levy Y * Y * COMPILING Y * Y% cc -g -c tablesimple.c Y */ Y Y#include <stdio.h> Y#include <assert.h> Y#include <string.h> Y#include <ctype.h> Y Y#include "table.h" Y Yint parse_range(str,first,last) char *str ; int *first ; int *last ; Y{ Y int n ; Y Y n = sscanf(str,"%d-%d",first,last) ; Y if (n==1) Y *first = *last = atoi(str) ; Y return n ; Y} Y Y Yint tb_simple_read(rt,fp,title) table_t **rt ; FILE *fp ; char *title ; Y{ Y simpletable_t *t ; Y char buf[1000] ; Y char roll[10] ; Y int rows ; Y int sts ; Y int r ; Y Y sts = (int)fgets(buf,sizeof(buf),fp) ; Y assert(sts) ; Y sts = sscanf(buf,"%s %d",roll,&rows) ; Y assert(sts==2) ; Y t = (simpletable_t*) Y MALLOC(sizeof(simpletable_t)+sizeof(simplerow_t)*(rows-1)) ; Y assert(t) ; Y t->title = strdup(title) ; Y strncpy(t->roll,roll,sizeof(t->roll)) ; Y t->numrows = rows ; Y sts = (int)fgets(buf,sizeof(buf),fp) ; Y assert(sts) ; Y t->source = strdup(strtok(buf,"\n")) ; Y for(r=0 ; r<rows ; r++) { Y sts = (int)fgets(buf,sizeof(buf),fp) ; Y assert(sts) ; Y sts=parse_range(strtok(buf,"\t\n"),&t->rows[r].first,&t->rows[r].last); Y assert(sts>0) ; Y t->rows[r].result = strdup(strtok((char*)0,"\n")) ; Y assert(t->rows[r].result) ; Y } Y *rt = (table_t*)t ; Y return 0 ; Y} Y Yint tb_simple_use(tab,result) table_t *tab ; char **result ; Y{ Y simpletable_t *t ; Y int r,i ; Y Y t = (simpletable_t*)tab ; Y r = ra_roll(t->roll) ; Y for(i=0 ; i<t->numrows ; i++) { Y if (r>=t->rows[i].first && r<=t->rows[i].last) { Y *result = t->rows[i].result ; Y return TB_OK ; Y } Y } Y *result = NULL ; Y return -1 ; Y} Y Yint tb_simple_print(tab,fp,way) table_t *tab ; FILE *fp ; int way ; Y{ Y simpletable_t *t ; Y char tmp[10] ; Y int r ; Y Y t = (simpletable_t*)tab ; Y switch (way) { Y case 1: Y fprintf(fp,".TS\ncB s\ncI s.\n") ; Y fprintf(fp,"%s\n",t->title) ; Y fprintf(fp,"(roll %s)\n",t->roll) ; Y fprintf(fp,".T&\n") ; Y fprintf(fp,"r l.\n") ; Y for(r=0 ; r<t->numrows ; r++) { Y if (t->rows[r].first==t->rows[r].last) Y sprintf(tmp,"%d",t->rows[r].first) ; Y else Y sprintf(tmp,"%d-%d",t->rows[r].first,t->rows[r].last) ; Y fprintf(fp,"%s\t%s\n",tmp,t->rows[r].result) ; Y } Y fprintf(fp,".TE\n") ; Y break ; Y default: Y return TB_E_NOTYET ; Y } Y return TB_OK ; Y} Y Yint tb_simple_free(t) table_t *t ; Y{ Y int r ; Y simpletable_t *st ; Y Y st = (simpletable_t*)t ; Y FREE(st->title) ; Y FREE(st->source) ; Y for(r=0 ; r<st->numrows ; r++) Y FREE(st->rows[r].result) ; Y FREE(st) ; Y return TB_OK ; Y} Y Yint tb_simple_choose(t) table_t *t ; Y{ Y return TB_E_NOTYET ; Y} Y Yint tb_simple_back(t,find,res) table_t *t ; char *find ; char **res ; Y{ Y simpletable_t *tab = (simpletable_t *)t ; Y int i ; Y Y assert(find) ; Y assert(res) ; Y assert(t) ; Y Y *res = NULL ; Y for(i=0 ; i<tab->numrows ; i++) { Y if (!strcmp(find,tab->rows[i].result)) { Y *res = (char*)&tab->rows[i].first ; Y break ; Y } Y } Y return TB_OK ; Y} SHAR_EOF fi if test -f 'tablemulti.c' then echo shar: "will not over-write existing file 'tablemulti.c'" else sed 's/^Y//' << \SHAR_EOF > 'tablemulti.c' Y/* Y * TABLEMULTI.C Y * Code supporting rolling on multiple collumn tables Y * By Joshua Levy Y * Y * COMPILING Y * Y% cc -g -c tablemulti.c Y */ Y Y#include <stdio.h> Y#include <assert.h> Y#include <string.h> Y#include <ctype.h> Y Y#include "table.h" Y Yint tb_multi_read(rt,fp,title) table_t **rt ; FILE *fp ; char *title ; Y{ Y register multitable_t *t ; Y register int c,r ; Y char buf[1000] ; Y char roll[10] ; Y int rows,cols ; Y int sts ; Y Y sts = (int)fgets(buf,sizeof(buf),fp) ; Y assert(sts) ; Y sts = sscanf(buf,"%s %d %d",roll,&rows,&cols) ; Y assert(sts==3) ; Y t = (multitable_t*) Y MALLOC(sizeof(multitable_t)+sizeof(multirow_t*)*(rows-1)) ; Y assert(t) ; Y t->title = strdup(title) ; Y strncpy(t->roll,roll,sizeof(t->roll)) ; Y t->numrows = rows ; Y t->numcols = cols ; Y sts = (int)fgets(buf,sizeof(buf),fp) ; Y assert(sts) ; Y t->source = strdup(strtok(buf,"\n")) ; Y /* read in the column names */ Y t->colnames = (char **)calloc(cols+1,sizeof(char*)) ; Y assert(t->colnames) ; Y sts = (int)fgets(buf,sizeof(buf),fp) ; Y assert(sts) ; Y assert(strtok(buf," \t\n")) ; /* get rid of first dash */ Y for(c=0 ; c<t->numcols ; c++) { Y t->colnames[c]=strdup(strtok((char*)0,"\t\n")) ; Y } Y t->colnames[c] = NULL ; Y Y for(r=0 ; r<rows ; r++) { Y t->rows[r] = (multirow_t*) Y MALLOC(sizeof(multirow_t)+sizeof(char*)*(t->numcols-1)) ; Y sts = (int)fgets(buf,sizeof(buf),fp) ; Y assert(sts) ; Y sts=parse_range(strtok(buf,"\t\n"),&t->rows[r]->first, Y &t->rows[r]->last); Y assert(sts>0) ; Y for(c=0 ; c<t->numcols ; c++) { Y t->rows[r]->result[c] = strdup(strtok((char*)0,"\t\n")) ; Y assert(t->rows[r]->result[c]) ; Y } Y Y } Y Y *rt = (table_t*)t ; Y return 0 ; Y} Y Yint tb_multi_use(tab,col,result) table_t *tab ; char *col ;char **result ; Y{ Y register multitable_t *t ; Y int ncol ; Y int i,r ; Y Y t = (multitable_t*)tab ; Y Y for(r=0 ; r<t->numcols ; r++) Y if (!strcmp(t->colnames[r],col)) { Y ncol = r ; Y break ; Y } Y if (r==t->numcols) Y return TB_E_NO_COL ; Y Y r = ra_roll(t->roll) ; Y Y for(i=0 ; i<t->numrows ; i++) { Y if (r>=t->rows[i]->first && r<=t->rows[i]->last) { Y *result = t->rows[i]->result[ncol] ; Y return TB_OK ; Y } Y } Y Y return TB_E_MISC ; Y} Y Yint tb_multi_print(tab,fp,way) table_t *tab ; FILE *fp ; int way ; Y{ Y register multitable_t *t ; Y int r,c ; Y Y t = (multitable_t*)tab ; Y switch (way) { Y case 1: Y fprintf(fp,".TS\ncB\ncI\ncI.\n") ; Y fprintf(fp,"%s\n",t->title) ; Y fprintf(fp,"(roll %s)\n",t->roll) ; Y fprintf(fp,"%s\n",t->source) ; Y fprintf(fp,".T&\n") ; Y fprintf(fp,"rI ") ; Y for(c=0 ; c<t->numcols ; c++) Y fprintf(fp,"c%c",c==t->numcols-1?'.':' ') ; Y fprintf(fp,"\nRoll\t") ; Y for(c=0 ; c<t->numcols ; c++) Y fprintf(fp,"%s%c",t->colnames[c], Y c==t->numcols-1?'\n':'\t') ; Y Y for(r=0 ; r<t->numrows ; r++) { Y if (t->rows[r]->first==t->rows[r]->last) Y fprintf(fp,"%d\t",t->rows[r]->first) ; Y else Y fprintf(fp,"%d-%d\t",t->rows[r]->first,t->rows[r]->last) ; Y for(c=0 ; c<t->numcols ; c++) Y fprintf(fp,"%s%c",t->rows[r]->result[c], Y c==t->numcols-1?'\n':'\t') ; Y } Y fprintf(fp,".TE\n") ; Y break ; Y default: Y return TB_E_NOTYET ; Y } Y return TB_OK ; Y} Y Yint tb_multi_free(t) table_t *t ; Y{ Y int r,c ; Y multitable_t *mt ; Y Y mt = (multitable_t *)t ; Y Y FREE(mt->title) ; Y FREE(mt->source) ; Y for(c=0 ; c<mt->numcols ; c++) { Y FREE(mt->colnames[c]) ; Y } Y for(r=0 ; r<mt->numrows ; r++) { Y FREE(mt->rows[r]) ; Y for(c=0 ; c<mt->numcols ; c++) { Y FREE(mt->rows[r]->result[c]) ; Y } Y } Y FREE(mt->colnames) ; Y FREE(mt) ; Y Y return TB_OK ; Y} Y Yint tb_multi_choose(t) table_t *t ; Y{ Y return TB_E_NOTYET ; Y} Y Yint tb_multi_back(t,find,data,res) table_t *t ; char *find, *data, **res ; Y{ Y multitable_t *tab = (multitable_t *)t ; Y int i,k ; Y Y assert(t) ; Y assert(find) ; Y assert(res) ; Y Y *res = NULL ; Y if (!data) { Y /* If no data, search the whole table */ Y for(i=0 ; i<tab->numrows ; i++) { Y for(i=0 ; i<tab->numcols ; i++) { Y if (!strcmp(find,tab->rows[i]->result[k])) { Y *res = tab->rows[i]->result[k] ; Y break ; Y } Y } Y } Y } else { Y /* other wise, just search the row in question */ Y for(i=0 ; i<tab->numcols ; i++) { Y if (!strcmp(data,tab->colnames[k])) Y break ; Y } Y if (k==tab->numcols) Y return TB_E_MISC ; Y for(i=0 ; i<tab->numrows ; i++) { Y if (!strcmp(find,tab->rows[i]->result[k])) { Y *res = (char*)&tab->rows[i]->first ; Y break ; Y } Y } Y } Y return TB_OK ; Y} SHAR_EOF fi if test -f 'tablesimpbig.c' then echo shar: "will not over-write existing file 'tablesimpbig.c'" else sed 's/^Y//' << \SHAR_EOF > 'tablesimpbig.c' Y/* Y * TABLESIMPBIG.C Y * Code supporting rolling on big but simple tables Y * By Joshua Levy Y * Y * COMPILING Y * Y% cc -g -c tablesimpbig.c Y */ Y Y#include <stdio.h> Y#include <assert.h> Y#include <string.h> Y#include <ctype.h> Y Y#include "table.h" Y Y Yint tb_simpbig_read(rt,fp,title) table_t **rt ; FILE *fp ; char *title ; Y{ Y simpletable_t *t ; Y simplerow_t *row ; Y char buf[1000] ; Y char roll[10] ; Y int rows ; Y int sts ; Y int r,i ; Y int lines ; Y char *cp ; Y Y sts = (int)fgets(buf,sizeof(buf),fp) ; Y assert(sts) ; Y sts = sscanf(buf,"%s %d",roll,&rows) ; Y assert(sts==2) ; Y t = (simpletable_t*) Y MALLOC(sizeof(simpletable_t)+sizeof(simplerow_t)*(rows-1)) ; Y assert(t) ; Y t->title = strdup(title) ; Y strncpy(t->roll,roll,sizeof(t->roll)) ; Y t->numrows = rows ; Y sts = (int)fgets(buf,sizeof(buf),fp) ; Y assert(sts) ; Y t->source = strdup(strtok(buf,"\n")) ; Y for(r=0 ; r<rows ; r++) { Y sts = (int)fgets(buf,sizeof(buf),fp) ; Y assert(sts) ; Y row = &t->rows[r] ; Y sts=parse_range(strtok(buf,"\t\n"),&row->first,&row->last); Y assert(sts>0) ; Y lines = atoi(strtok((char*)0,"\n")) ; Y row->result = (char*)malloc(132*lines+1) ; Y assert(row->result) ; Y for(i=0,cp=row->result ; i<lines ; i++) { Y sts = (int)fgets(cp,(unsigned)132,fp) ; Y assert(sts) ; Y cp += strlen(cp) ; Y } Y *cp = '\0' ; Y } Y *rt = (table_t*)t ; Y return 0 ; Y} Y Yint tb_simpbig_print(tab,fp,way) table_t *tab ; FILE *fp ; int way ; Y{ Y simpletable_t *t ; Y char tmp[10] ; Y int r ; Y Y t = (simpletable_t*)tab ; Y switch (way) { Y case 1: Y fprintf(fp,".TS\ncB s\ncI s\n") ; Y fprintf(fp,"r lw(5i).\n") ; Y fprintf(fp,"%s\n",t->title) ; Y fprintf(fp,"(roll %s)\n",t->roll) ; Y for(r=0 ; r<t->numrows ; r++) { Y if (t->rows[r].first==t->rows[r].last) Y sprintf(tmp,"%d",t->rows[r].first) ; Y else Y sprintf(tmp,"%d-%d",t->rows[r].first,t->rows[r].last) ; Y fprintf(fp,"%s\tT{\n%sT}\n",tmp,t->rows[r].result) ; Y } Y fprintf(fp,".TE\n") ; Y break ; Y default: Y return TB_E_NOTYET ; Y } Y return TB_OK ; Y} SHAR_EOF fi if test -f 'table.c' then echo shar: "will not over-write existing file 'table.c'" else sed 's/^Y//' << \SHAR_EOF > 'table.c' Y/* Y * TABLE.C Y * Code supporting rolling on tables Y * By Joshua levy Y * Y * COMPILING Y * Y * This line creates a simple test program: Y% cc -g -DTEST -o table table.c tablesimple.o tablemulti.o random.o Y * Y * This line creates an 'o' file to include in other programs: Y%o cc -g -c table.c Y * Y * INTERFACE Y * There is one data type: Y * table_t Y * and seven interfaces in this file: Y * tb_read(table,file) table_t **table ; char *file ; Y * tb_use(table,...,result) table_t *table ; char **result ; Y * tb_free(table) table_t *table ; Y * tb_print(table,way) table_t *table ; int way ; Y * tb_many(table,count,...,result) table_t *table ; count int ; char **result ; Y * tb_choose(table,which,...,result) table_t *table ; int which ; char **result ; Y * tb_back(table,lookfor,result) table_t *table ; char *lookfor ; char **result ; Y * Y * ADDING NEW TABLES Y * This is supposed to be the framework for an object oriented package, Y * which support many different types of tables. This is the (untested) Y * procedure for adding a new table type (refered to as a foo table): Y * create tablefoo.h Y * Containing declarations for the functions in tablefoo.c. Y * create tablefoo.c Y * It should contain at least three entry points: tb_foo_read, Y * tb_foo_free, and tb_foo_use. I also suggest tb_foo_print,mostly Y * for debugging. Y * modify table.h Y * So that it includes tablefoo.h. Y * modify table.c Y * So that the tba_* tables contain pointers the new routines. Y * Note: I do not recommend adding new tables at this time. I'm hoping Y * for a "real" release in a month or three, and I'll have better support Y * for new table types then. Y */ Y Y#include <stdio.h> Y#include <string.h> Y#include <ctype.h> Y#include <varargs.h> Y Y#include "random.h" Y#include "table.h" Y Yextern int illegal() ; Y Y#define assert(ex) {if (!(ex)){fprintf(stderr,"Assertion failed: file %s, line %d\n", __FILE__, __LINE__);fprintf(stderr,"sts is %d\n",sts);exit(1);}} Y Yextern int tb_do_query() ; Y Y/* Y * Data Tables. Y * These arrays form a simple dispatch mechanism. Y */ Y Y/* maps type name to type number */ Ytypedef struct { char *typ ; int t } mapper ; Y Ymapper tba_type[] = { Y {"Simple", 1}, {"Multiple",2}, {"SimpleBig",3}, {NULL, 0}, Y} ; Y Y/* table of read routines indexed by type number */ Yint (*tba_read[])() = { Y illegal, tb_simple_read, tb_multi_read, tb_simpbig_read, Y} ; Y Y/* table of use routines indexed by type number */ Yint (*tba_use[])() = { Y illegal, tb_simple_use, tb_multi_use,tb_simple_use, Y} ; Y Y/* table of print routines indexed by type number */ Yint (*tba_print[])() = { Y illegal, tb_simple_print, tb_multi_print,tb_simpbig_print, Y} ; Y Y/* table of choose routines indexed by type number */ Yint (*tba_choose[])() = { Y illegal, tb_simple_choose, tb_multi_choose,tb_simple_choose, Y} ; Y Y/* table of back routines indexed by type number */ Yint (*tba_back[])() = { Y illegal, tb_simple_back, tb_multi_back, tb_simple_back, Y} ; Y Y/* table of free routines indexed by type number */ Yint (*tba_free[])() = { Y illegal, tb_simple_free, tb_multi_free,tb_simple_free, Y} ; Y Y/* table of query routines indexed by type number */ Yint (*tba_query[])() = { Y illegal, tb_do_query, tb_do_query, tb_do_query, Y} ; Y Y/* Y * A couple of utility routines Y */ Y#ifdef NEEDDUP Ychar *strdup(str) char *str ; Y{ Y char *ret = (char*)malloc(strlen(str)+1) ; Y Y if (ret) Y strcpy(ret,str) ; Y return ret ; Y} Y#endif Y Yint map(text,mappi) char *text ; mapper mappi[] ; Y{ Y int i ; Y for(i=0 ; mappi[i].typ ; i++) Y if (!strcmp(mappi[i].typ,text)) Y return mappi[i].t ; Y return 0 ; Y} Y Yint illegal() Y{ Y fprintf(stderr,"Attempt to send a message to an illegal type of table.\n"); Y fprintf(stderr,"Exiting program.\n") ; Y exit(-2) ; Y} Y Yint tb_do_query(tab,query,res) table_t *tab ; int query ; int *res ; Y{ Y return ra_query(((alltable_t*)tab)->roll,query,res) ; Y} Y Y/* Y * the read utilities for tables Y */ Yint tb_read(file,table) char *file ; table_t **table ; Y{ Y char buf[1000] ; Y FILE *fp ; Y char *cp ; Y char *name ; Y char *type ; Y int sts=0 ; Y int t ; Y Y fp = fopen(file,"r") ; Y if (!fp) Y return TB_E_NOFILE ; Y Y cp = fgets(buf,sizeof(buf),fp) ; Y assert(cp) ; Y name = strtok(buf,"\t\n") ; Y type = strtok((char*)0,"\t\n") ; Y assert(type) ; Y if (!(t = atoi(type))) Y t = map(type,tba_type) ; Y assert(t) ; Y sts = tba_read[t](table,fp,name) ; Y assert(sts!=-1) ; Y (*table)->type = t ; Y FCLOSE(fp) ; Y return TB_OK ; Y} Y Y/* Y * Dump the table in a way that can be used by tbl/troff Y */ Yint tb_print(table,file,way) table_t *table ; char *file ; int way ; Y{ Y FILE *fp ; Y int sts=0 ; Y Y if (!file) Y fp = stderr ; Y else if (!file[0]) Y fp = stdout ; Y else Y fp = fopen(file,"r") ; Y assert(fp) ; Y Y sts = tba_print[table->type](table,fp,way) ; Y if (file && file[0]) Y FCLOSE(fp) ; Y return sts ; Y} Y Y/* Y * use a table. Y */ Yint tb_use(table,arg1,arg2) table_t *table ; char *arg1 ; char *arg2 ; Y{ Y int sts ; Y Y switch (table->type) { Y case 1: Y case 3: Y sts = tba_use[table->type](table,arg1) ; Y break ; Y case 2: Y sts = tba_use[table->type](table,arg1,arg2) ; Y break ; Y default: Y sts = TB_E_NOTYPE ; Y } Y return sts ; Y} Y Y/* Y * free a table. Y */ Yint tb_free(table) table_t *table ; Y{ Y return tba_free[table->type](table) ; Y} Y Y/* Y * use a table many times. Y */ Yint tb_many(table,count,arg1,arg2) table_t *table ; char *arg1 ; char *arg2 ; Y{ Y int sts ; Y int r ; Y char *tmp ; Y char **res ; Y int got=0 ; Y int bad ; Y Y if (count>table->all.num) Y return TB_E_TOOMANY ; Y while (got<count) { Y /* Y * first, we roll on the table Y */ Y switch (table->type) { Y case 1: Y case 3: Y res = (char**)arg1 ; Y sts = tb_use(table,&tmp) ; Y break ; Y case 2: Y res = (char**)arg2 ; Y sts = tb_use(table,arg1,&tmp) ; Y break ; Y default: Y sts = TB_E_NOTYPE ; Y } Y if (sts!=0) Y return sts ; Y /* Y * second, we see if we've gotten this result before Y */ Y for(r=0,bad=0 ; r<got ; r++) { Y if (!strcmp(res[r],tmp)) Y bad=1 ; Y } Y /* Y * finally, if not, we add it two our list Y */ Y if (!bad) { Y res[got++] = tmp ; Y } Y } Y return sts ; Y} Y Y/* Y * choose from a table. Y */ Yint tb_choose(table,which,arg1,arg2) table_t *table; int which; char *arg1, *arg2 ; Y{ Y int sts ; Y Y switch (table->type) { Y case 1: Y case 3: Y sts = tba_choose[table->type](table,which,arg1) ; Y break ; Y case 2: Y sts = tba_choose[table->type](table,which,arg1,arg2) ; Y break ; Y default: Y sts = TB_E_NOTYPE ; Y } Y return sts ; Y} Y/* Y * use a table backwards Y */ Yint tb_back(table,which,va_alist) table_t *table; char *which ; va_dcl Y{ Y int sts ; Y char **ret ; Y char *arg ; Y va_list list ; Y Y va_start(list) ; Y switch (table->type) { Y case 1: Y case 3: Y ret = va_arg(list,char**) ; Y sts = tba_back[table->type](table,which,ret) ; Y break ; Y case 2: Y arg = va_arg(list,char*) ; Y ret = va_arg(list,char**) ; Y sts = tba_back[table->type](table,which,arg,ret) ; Y break ; Y default: Y sts = TB_E_NOTYPE ; Y } Y va_end(list) ; Y return sts ; Y} Y Yint tb_query(t,q,r) table_t *t ; int q ; int *r ; Y{ Y return tba_query[t->type](t,q,r) ; Y} Y Y Y#ifdef TEST Y Ymain(argc,argv) int argc ; char *argv[] ; Y{ Y table_t *table ; Y char text[100] ; Y char *result ; Y int count, i ; Y int sts=0 ; Y Y assert(argc==3) ; Y count = atoi(argv[2]) ; Y Y tb_read(argv[1],&table) ; Y assert(sts==TB_OK) ; Y Y sts = tb_print(table,"",0) ; Y assert(sts==TB_OK) ; Y Y switch (table->type) { Y case 1: Y for(i=0 ; i<count ; i++) { Y sts = tb_use(table,&result) ; Y assert(sts==TB_OK) ; Y printf("%d %s\n",i+1,result) ; Y } Y break ; Y case 2: Y printf("Enter column: ") ; Y fgets(text,sizeof(text),stdin) ; Y text[strlen(text)-1] = '\0' ; Y for(i=0 ; i<count ; i++) { Y sts = tb_use(table,text,&result) ; Y assert(sts==TB_OK) ; Y printf("%d %s\n",i+1,result) ; Y } Y break ; Y default: Y sts = TB_E_NOTYPE ; Y } Y Y sts = tb_free(table) ; Y assert(sts==TB_OK) ; Y Y} Y#endif Y Y Y#ifdef TB2TBL Y Ymain(argc,argv) int argc ; char *argv[] ; Y{ Y table_t *table ; Y int sts ; Y int i ; Y Y for(i=1 ; i<argc ; i++) { Y sts = tb_read(argv[i],&table) ; assert(sts==TB_OK) ; Y sts = tb_print(table,"",0) ; assert(sts==TB_OK) ; Y sts = tb_free(table) ; assert(sts==TB_OK) ; Y } Y} Y#endif SHAR_EOF fi if test -f 'tbtest.c' then echo shar: "will not over-write existing file 'tbtest.c'" else sed 's/^Y//' << \SHAR_EOF > 'tbtest.c' Y/* Y * TBTEST.C Y * Test program for the tb (table) subsystem. Y * By Joshua levy Y */ Y Y#include <stdio.h> Y#include <string.h> Y#include <ctype.h> Y#include <assert.h> Y#include <errno.h> Y Y#include "random.h" Y#include "table.h" Y Ymain(argc,argv) int argc ; char *argv[] ; Y{ Y table_t *table ; Y char line[200] ; Y char *result ; Y char *results[10] ; Y char *comm ; Y char *arg1, *arg2, *arg3 ; Y int count, i ; Y int sts=0 ; Y int n ; Y int quer, num ; Y Y while (fgets(line,sizeof(line),stdin)) { Y comm = strtok(line," \t\n") ; Y if (!comm || comm[0]=='#') Y continue ; Y arg1 = strtok(NULL,TB_WHITE) ; Y arg2 = strtok(NULL,TB_WHITE) ; Y arg3 = strtok(NULL,TB_WHITE) ; Y if (!strcmp(comm,"quit")) { Y exit(0) ; Y } else if (!strcmp(comm,"read")) { Y sts = tb_read(arg1,&table) ; Y if (sts!=TB_OK) Y printf("tb_read returned an error (%d) errno=%d\n",sts,errno) ; Y } else if (!strcmp(comm,"free")) { Y sts = tb_free(table) ; Y if (sts!=TB_OK) Y printf("tb_print returned an error (%d)\n",sts) ; Y } else if (!strcmp(comm,"use")) { Y switch (table->type) { Y case 1: Y case 3: Y count = arg1?atoi(arg1):0 ; Y for(i=0 ; i<count ; i++) { Y sts = tb_use(table,&results[i]) ; Y } Y break ; Y case 2: Y count = arg2?atoi(arg2):0 ; Y for(i=0 ; i<count ; i++) { Y sts = tb_use(table,arg1,&results[i]) ; Y } Y break ; Y default: Y printf("Table is of an unknown type\n") ; Y } Y if (sts==TB_OK) { Y for(i=0 ; i<count ; i++) Y printf("%d %s\n",i+1,results[i]) ; Y } else { Y printf("tb_use returned an error (%d)\n",sts) ; Y } Y } else if (!strcmp(comm,"back")) { Y switch (table->type) { Y case 1: Y case 3: Y sts = tb_back(table,arg1,&result) ; Y break ; Y case 2: Y sts = tb_back(table,arg1,arg2,&result) ; Y break ; Y default: Y printf("Table is of an unknown type\n") ; Y } Y if (sts==TB_OK) { Y printf("%d\n",result?*(int*)result:-1) ; Y } else { Y printf("tb_back returned an error (%d)\n",sts) ; Y } Y } else if (!strcmp(comm,"many")) { Y switch (table->type) { Y case 1: Y case 3: Y n = atoi(arg1) ; Y sts = tb_many(table,n,results) ; Y break ; Y case 2: Y n = atoi(arg2) ; Y sts = tb_many(table,n,arg1,results) ; Y break ; Y default: Y printf("Table is of an unknown type\n") ; Y } Y if (sts==TB_OK) { Y for(i=0 ; i<n ; i++) Y printf("%d %s\n",i,results[i]) ; Y } else { Y printf("tb_many returned an error (%d)\n",sts) ; Y } Y } else if (!strcmp(comm,"print")) { Y sts = tb_print(table,"",1) ; Y if (sts!=TB_OK) Y printf("tb_print returned an error (%d)\n",sts) ; Y } else if (!strcmp(comm,"query")) { Y if (!strcmp(arg1,"max")) quer = TB_Q_MAX ; Y if (!strcmp(arg1,"min")) quer = TB_Q_MIN ; Y if (!strcmp(arg1,"ave")) quer = TB_Q_AVE ; Y if (!strcmp(arg1,"legal")) quer = TB_Q_LEGAL ; Y sts = tb_query(table,quer,&num) ; Y if (sts==TB_OK) Y printf("%d\n",num) ; Y else Y printf("tb_query returned an error (%d)\n",sts) ; Y } else if (!strcmp(comm,"help")) { Y printf("Here is a BNF of the commands:\n") ; Y printf("\tquit\n") ; Y printf("\tread <file>\n") ; Y printf("\tfree\n") ; Y printf("\tuse [<column>] <count>\n") ; Y printf("\tback\n") ; Y printf("\tmany [<column>] <count>\n") ; Y printf("\tprint\n") ; Y printf("\tquery <query>\n") ; Y printf("\thelp\n") ; Y } else { Y printf("Illegal command.\n") ; Y } Y } Y} Y Y SHAR_EOF fi if test -f 'tbtest' then echo shar: "will not over-write existing file 'tbtest'" else sed 's/^Y//' << \SHAR_EOF > 'tbtest' YYN{YLXOJYcI s. YYYYYYYYYYYYYYYYYYYYYYYYYYcB YcI YcI. YYYYYYRoll YYYYYYYYYYYYYYYYcB s YcI s YYYYY%sT} YYYYYYYYYYYYYYYYYYYYYYYYYYYYYY|BYBYBY'SHAR_EOF chmod +x 'tbtest' fi if test -f 'tablesimpbig.h' then echo shar: "will not over-write existing file 'tablesimpbig.h'" else sed 's/^Y//' << \SHAR_EOF > 'tablesimpbig.h' Y/* Y * TABLESIMPBIG.H Y * By Joshua Levy Y * This header routine should only be included in table.c and tablesimple.c! Y * It must be before the include file for table.h Y */ Yextern int tb_simpbig_read() ; Yextern int tb_simpbig_print() ; Y SHAR_EOF fi if test -f 'table.h' then echo shar: "will not over-write existing file 'table.h'" else sed 's/^Y//' << \SHAR_EOF > 'table.h' Y/* Y * TABLE.H Y * Header file for table.c users Y * By Joshua Levy Y */ Y Y#ifndef TABLE_H Y#define TABLE_H 1 Y Ytypedef struct { /* not currently used, should be a range of numbers */ Y int first ; Y int last ; Y} range_t ; Y Y#include "tablesimple.h" Y#include "tablemulti.h" Y#include "tablesimpbig.h" Y Ytypedef struct { Y int type ; Y char *title ; Y char roll[10] ; Y char *source ; Y int num ; Y} alltable_t ; Y Ytypedef union { /* This is the handle users use to manipulate tables. */ Y int type ; Y alltable_t all ; Y simpletable_t simple ; Y multitable_t multi ; Y} table_t ; Y Y/* Y * GENERAL PURPOSE MACROS Y */ Y#define TB_WHITE "\t \n\f" /* white space */ Y Y/* Y * error return values Y */ Y#define TB_OK 0 /* success */ Y#define TB_E_MISC -1 /* general error: something went wrong */ Y#define TB_E_NOTYET -2 /* feature or subroutine not yet implemented */ Y#define TB_E_NOFILE -3 /* file doesn't exist */ Y#define TB_E_NO_COL -4 /* no column in the table with that name */ Y#define TB_E_NOTYPE -5 /* that type of table is not supported */ Y#define TB_E_TOOMANY -6 /* there are not that many possible results */ Y Y/* Y * lint help Y */ Y#define FREE(ptr) (void)free((char*)ptr) Y#define MALLOC(size) malloc((unsigned int)size) Y#define FCLOSE(fp) (void)fclose(fp) Y Y Y/* Y * functional interface Y */ Yextern int tb_read() ; Yextern int tb_print() ; Yextern int tb_use() ; Yextern int tb_free() ; Yextern int tb_many() ; Yextern int tb_query() ; Y#ifdef NEEDDUP Yextern char *strdup() ; Y#endif Y Y/* Y * Queries Y */ Y#include "random.h" Y#define TB_Q_MIN RA_MIN Y#define TB_Q_MAX RA_MAX Y#define TB_Q_AVE RA_AVE Y#define TB_Q_LEGAL RA_LEGAL Y Y Y#endif SHAR_EOF fi cd .. if test ! -d 'tst' then mkdir 'tst' fi cd 'tst' if test -f 'twodice.tab' then echo shar: "will not over-write existing file 'twodice.tab'" else sed 's/^Y//' << \SHAR_EOF > 'twodice.tab' YTest of two dice table TwoDice Y1d6 1d4 6 4 YFrom my own mind Y1-1 1-2 1-3 1-4 Y2-1 2-2 2-3 2-4 Y3-1 3-2 3-3 3-4 Y4-1 4-2 4-3 4-4 Y5-1 5-2 5-3 5-4 Y6-1 6-2 6-3 6-4 SHAR_EOF fi if test -f 'multi1.tab' then echo shar: "will not over-write existing file 'multi1.tab'" else sed 's/^Y//' << \SHAR_EOF > 'multi1.tab' YBasic Test Multiple Y2d6 6 4 Ymy mind Y- Elf Human Dwarf Troll Y2 e2 h2 d2 t2 Y3 e3 h3 d3 t3 Y4-7 e4 h4 d4 t4 Y8-9 e8 h8 d8 t8 Y10 e10 h10 d10 t10 Y11-12 e11 h11 d11 t11 Y SHAR_EOF fi if test -f 'simp1.tab' then echo shar: "will not over-write existing file 'simp1.tab'" else sed 's/^Y//' << \SHAR_EOF > 'simp1.tab' YPay-off results table Simple Y2d6 11 Yp13 of The Complete Tavern Y2 Banker loses triple, passes dice Y3 Banker loses double, passes dice Y4 Banker loses double Y5 Banker loses Y6 Banker loses half of bet Y7 Stand off, rethrow Y8 Banker wins bet Y9 Banker wins bet Y10 Banker double bet Y11 Banker double bet Y12 Banker triple bet SHAR_EOF fi if test -f 'chch1.tab' then echo shar: "will not over-write existing file 'chch1.tab'" else sed 's/^Y//' << \SHAR_EOF > 'chch1.tab' YBasic Inebriation Table ChangingChances Y1d100 7 5 Yp17 of The Complete Tavern YElf Human Dwarf Troll Frame Y01-10 01-05 01 - Skinny Y11-35 06-15 02-04 - Slender Y36-70 16-30 05-10 01-02 Slim Y71-90 31-70 11-30 03-10 Normal Y91-96 71-85 31-65 11-40 Husky Y97-99 86-95 66-90 41-80 Heavy Y00 96-00 91-00 81-00 Huge Y SHAR_EOF fi if test -f 'rndtnorm.ts' then echo shar: "will not over-write existing file 'rndtnorm.ts'" else sed 's/^Y//' << \SHAR_EOF > 'rndtnorm.ts' Y# Y# RANDOM.C test script Y# Handles normal situations. Y# by Joshua Levy Y# Yecho Y# normal test 1 Yseed 0 Ycard 20 Ycard 20 Ycard 20 Yroll 35 1d10 Yroll 35 1d10 Yquit SHAR_EOF fi if test -f 'rndterror.ts' then echo shar: "will not over-write existing file 'rndterror.ts'" else sed 's/^Y//' << \SHAR_EOF > 'rndterror.ts' Y# Y# RANDOM.C test script Y# Test errors Y# by Joshua Levy Y# Yecho Y# error test 1 Yseed 0 Yroll 1 1d-7 Yroll 1 -1d7 Yroll 1 2e3 Yroll 1 foo Yquit SHAR_EOF fi if test -f 'rndtacid.ts' then echo shar: "will not over-write existing file 'rndtacid.ts'" else sed 's/^Y//' << \SHAR_EOF > 'rndtacid.ts' Y# Y# RANDOM.C test script Y# Test in acid Y# by Joshua Levy Y# Yecho Y# acid test 1 Yseed 0 Yroll 10 1d999 Yroll 10 999d1 Yroll 100 1d7 Yquit SHAR_EOF fi if test -f 'test.ts' then echo shar: "will not over-write existing file 'test.ts'" else sed 's/^Y//' << \SHAR_EOF > 'test.ts' YSTART Y TABLE(one) ; Y RESULT(res) ; Y Y READ("simp1.tab",one) ; Y USE(one,res) ; Y PRINT(res) ; YEND SHAR_EOF fi if test -f 'simpbig1.tab' then echo shar: "will not over-write existing file 'simpbig1.tab'" else sed 's/^Y//' << \SHAR_EOF > 'simpbig1.tab' YPay-off results table SimpleBig Y1d6 4 Ymy mind (Joshua Levy) Y1-2 3 YThis three line response was Ygenerated when you rolled a Y1 or a 2. Y3 2 YThis two line response was generated when you rolled a 3. YIt is not as big as the 1-2 roll, but bigger than the 4 roll. Y4 1 YThis one line response was generated when you rolled a 4. Y5-6 5 YThis very long response was returned when you rolled Yeither a five or a six. It has got to take up five Ylines so I am padding it with a lot of filler. This Ysort of big table might be useful for generating plots Yand personality descriptions. Y SHAR_EOF fi if test -f 'Makefile' then echo shar: "will not over-write existing file 'Makefile'" else sed 's/^Y//' << \SHAR_EOF > 'Makefile' Y# Y# Makefile for the table and random utility packages Y# and some programs which use them. Y# by Joshua Levy Y# Y YO= tablemulti.o tablesimple.o random.o YH= table.h random.h YB= ../src Y Y# some test routines Y# note that 'ts' stands for test script Y# Regress is spelt with one 's' because there is a utility on our Y# system called "regress". Y Y# A list of all the tests Ytest: preamble rnd table # query Y Y# The tests which are organized by table type. Ytable: preamble simp multi simpbig Y Y# The tests which are organized by command. Ycomms: preamble query Y Yclean: Y rm -f /tmp/regres* core Y Ypreamble: Y @echo "You should see a list of zeros." Y Yrnd: $B/rndtest Y @regres $B/rndtest rndtnorm.ts rndtnorm.mst Y @regres $B/rndtest rndtacid.ts rndtacid.mst Y @regres $B/rndtest rndtquery.ts rndtquery.mst Y Ysimp: $B/tbtest Y @regres $B/tbtest simp1.ts simp1.mst Y Ymulti: $B/tbtest Y @regres $B/tbtest multi1.ts multi1.mst Y Ysimpbig: $B/tbtest Y @regres $B/tbtest simpbig1.ts simpbig1.mst Y Yquery: $B/tbtest Y @regres $B/tbtest tbquery.ts /dev/null SHAR_EOF fi if test -f 'simp2.tab' then echo shar: "will not over-write existing file 'simp2.tab'" else sed 's/^Y//' << \SHAR_EOF > 'simp2.tab' YHawaiian Language Known Simple Y1d14 5 YJoshua Levy's Mind Y1-4 English Y5-7 Japanese Y8-11 Pidgin Y12-13 Samoan Y14 Chinese SHAR_EOF fi if test -f 'regres' then echo shar: "will not over-write existing file 'regres'" else sed 's/^Y//' << \SHAR_EOF > 'regres' Y#!/bin/csh Y$1 <$2 >/tmp/regres.$$ Ydiff $3 /tmp/regres.$$ >/tmp/regres.$$.diff Ysetenv RESULT `wc -l /tmp/regres.$$.diff | awk '{print $1;}'` Yecho ${RESULT} Yif (${RESULT} == 0) rm /tmp/regres.$$ /tmp/regres.$$.diff Y SHAR_EOF chmod +x 'regres' fi if test -f 'rndtnorm.mst' then echo shar: "will not over-write existing file 'rndtnorm.mst'" else sed 's/^Y//' << \SHAR_EOF > 'rndtnorm.mst' Y# normal test 1 Yseed 0 Ycard 20 Y8d 1s 9d 6c 5c 2c 2d 6c 2d 7h 12d 8c 1s 8h 10h 1c 12c 8c 6d 9d Ycard 20 Y6h 7s 4s 4c 10h 3c 12d 1s 6s 2h 7d 11d 6d 10s 3h 5c 1h 12s 11h 8s Ycard 20 Y5d 12c 11c 4s 4d 10d 3s 8c 2c 4s 7s 8h 11h 2c 2c 4d 10h 10c 11d 8h Yroll 35 1d10 Y1 6 8 3 9 7 5 8 8 6 8 8 10 3 9 6 8 10 10 9 3 7 6 8 7 2 2 8 9 4 8 1 1 5 5 Yroll 35 1d10 Y1 4 10 9 3 7 6 2 6 10 10 3 9 2 2 9 6 10 5 3 7 6 5 6 6 10 3 8 10 9 2 2 4 3 10 Yquit SHAR_EOF fi if test -f 'rndtacid.mst' then echo shar: "will not over-write existing file 'rndtacid.mst'" else sed 's/^Y//' << \SHAR_EOF > 'rndtacid.mst' Y# acid test 1 Yseed 0 Yroll 10 1d999 Y839 597 985 192 282 732 930 191 515 997 Yroll 10 999d1 Y999 999 999 999 999 999 999 999 999 999 Yroll 100 1d7 Y5 2 4 4 1 6 6 4 3 2 5 4 4 2 3 3 3 2 5 1 5 1 2 2 7 6 1 3 2 1 2 4 1 3 5 1 2 1 4 2 3 6 5 4 6 5 6 1 7 1 6 2 1 7 4 7 4 2 7 3 3 7 6 3 7 1 1 6 1 3 5 3 1 1 4 6 5 7 5 2 7 3 4 1 1 5 5 4 6 3 6 1 7 2 1 4 2 2 3 2 Yquit SHAR_EOF fi if test -f 'rndterror.mst' then echo shar: "will not over-write existing file 'rndterror.mst'" else sed 's/^Y//' << \SHAR_EOF > 'rndterror.mst' SHAR_EOF fi if test -f 'simp1.ts' then echo shar: "will not over-write existing file 'simp1.ts'" else sed 's/^Y//' << \SHAR_EOF > 'simp1.ts' Yread simp1.tab Yprint Yuse 10 Yuse 10 Ymany 3 Yfree Y SHAR_EOF fi if test -f 'simp1.mst' then echo shar: "will not over-write existing file 'simp1.mst'" else sed 's/^Y//' << \SHAR_EOF > 'simp1.mst' Y.TS YcB s YcI s. YPay-off results table Y(roll 2d6) Y.T& Yr l. Y2 Banker loses triple, passes dice Y3 Banker loses double, passes dice Y4 Banker loses double Y5 Banker loses Y6 Banker loses half of bet Y7 Stand off, rethrow Y8 Banker wins bet Y9 Banker wins bet Y10 Banker double bet Y11 Banker double bet Y12 Banker triple bet Y.TE Y1 Banker loses Y2 Banker loses Y3 Banker loses half of bet Y4 Banker loses double, passes dice Y5 Stand off, rethrow Y6 Banker double bet Y7 Stand off, rethrow Y8 Banker wins bet Y9 Stand off, rethrow Y10 Banker loses half of bet Y1 Banker loses Y2 Banker double bet Y3 Banker loses double Y4 Banker wins bet Y5 Banker loses Y6 Stand off, rethrow Y7 Stand off, rethrow Y8 Banker loses Y9 Banker double bet Y10 Banker double bet Y0 Banker wins bet Y1 Banker double bet Y2 Stand off, rethrow SHAR_EOF fi if test -f 'simpbig1.ts' then echo shar: "will not over-write existing file 'simpbig1.ts'" else sed 's/^Y//' << \SHAR_EOF > 'simpbig1.ts' Yread simpbig1.tab Yprint Yuse 10 Yuse 10 Ymany 5 Yfree Y SHAR_EOF fi if test -f 'simpbig1.mst' then echo shar: "will not over-write existing file 'simpbig1.mst'" else sed 's/^Y//' << \SHAR_EOF > 'simpbig1.mst' Y.TS YcB s YcI s Yr lw(5i). YPay-off results table Y(roll 1d6) Y1-2 T{ YThis three line response was Ygenerated when you rolled a Y1 or a 2. YT} Y3 T{ YThis two line response was generated when you rolled a 3. YIt is not as big as the 1-2 roll, but bigger than the 4 roll. YT} Y4 T{ YThis one line response was generated when you rolled a 4. YT} Y5-6 T{ YThis very long response was returned when you rolled Yeither a five or a six. It has got to take up five Ylines so I am padding it with a lot of filler. This Ysort of big table might be useful for generating plots Yand personality descriptions. YT} Y.TE Y1 This one line response was generated when you rolled a 4. Y Y2 This three line response was Ygenerated when you rolled a Y1 or a 2. Y Y3 This three line response was Ygenerated when you rolled a Y1 or a 2. Y Y4 This two line response was generated when you rolled a 3. YIt is not as big as the 1-2 roll, but bigger than the 4 roll. Y Y5 This three line response was Ygenerated when you rolled a Y1 or a 2. Y Y6 This one line response was generated when you rolled a 4. Y Y7 This three line response was Ygenerated when you rolled a Y1 or a 2. Y Y8 This three line response was Ygenerated when you rolled a Y1 or a 2. Y Y9 This three line response was Ygenerated when you rolled a Y1 or a 2. Y Y10 This very long response was returned when you rolled Yeither a five or a six. It has got to take up five Ylines so I am padding it with a lot of filler. This Ysort of big table might be useful for generating plots Yand personality descriptions. Y Y1 This one line response was generated when you rolled a 4. Y Y2 This very long response was returned when you rolled Yeither a five or a six. It has got to take up five Ylines so I am padding it with a lot of filler. This Ysort of big table might be useful for generating plots Yand personality descriptions. Y Y3 This very long response was returned when you rolled Yeither a five or a six. It has got to take up five Ylines so I am padding it with a lot of filler. This Ysort of big table might be useful for generating plots Yand personality descriptions. Y Y4 This three line response was Ygenerated when you rolled a Y1 or a 2. Y Y5 This very long response was returned when you rolled Yeither a five or a six. It has got to take up five Ylines so I am padding it with a lot of filler. This Ysort of big table might be useful for generating plots Yand personality descriptions. Y Y6 This three line response was Ygenerated when you rolled a Y1 or a 2. Y Y7 This three line response was Ygenerated when you rolled a Y1 or a 2. Y Y8 This very long response was returned when you rolled Yeither a five or a six. It has got to take up five Ylines so I am padding it with a lot of filler. This Ysort of big table might be useful for generating plots Yand personality descriptions. Y Y9 This two line response was generated when you rolled a 3. YIt is not as big as the 1-2 roll, but bigger than the 4 roll. Y Y10 This two line response was generated when you rolled a 3. YIt is not as big as the 1-2 roll, but bigger than the 4 roll. Y Ytb_many returned an error (-6) SHAR_EOF fi if test -f 'multi1.ts' then echo shar: "will not over-write existing file 'multi1.ts'" else sed 's/^Y//' << \SHAR_EOF > 'multi1.ts' Yread multi1.tab Yprint Yuse Elf 10 Yuse Dwarf 10 Ymany Elf 3 Ymany Dwarf 2 Yfree Y SHAR_EOF fi if test -f 'multi1.mst' then echo shar: "will not over-write existing file 'multi1.mst'" else sed 's/^Y//' << \SHAR_EOF > 'multi1.mst' Y.TS YcB YcI YcI. YBasic Test Y(roll 2d6) Ymy mind Y.T& YrI c c c c. YRoll Elf Human Dwarf Troll Y2 e2 h2 d2 t2 Y3 e3 h3 d3 t3 Y4-7 e4 h4 d4 t4 Y8-9 e8 h8 d8 t8 Y10 e10 h10 d10 t10 Y11-12 e11 h11 d11 t11 Y.TE Y1 e4 Y2 e4 Y3 e4 Y4 e3 Y5 e4 Y6 e10 Y7 e4 Y8 e8 Y9 e4 Y10 e4 Y1 d4 Y2 d10 Y3 d4 Y4 d8 Y5 d4 Y6 d4 Y7 d4 Y8 d4 Y9 d11 Y10 d10 Y0 e8 Y1 e10 Y2 e4 Y0 d4 Y1 d3 SHAR_EOF fi if test -f 'mult1.mst' then echo shar: "will not over-write existing file 'mult1.mst'" else sed 's/^Y//' << \SHAR_EOF > 'mult1.mst' Y.TS YcB YcI YcI. YBasic Test Y(roll 2d6) Ymy mind Y.T& YrI c c c c. YRoll Elf Human Dwarf Troll Y2 e2 h2 d2 t2 Y3 e3 h3 d3 t3 Y4-7 e4 h4 d4 t4 Y8-9 e8 h8 d8 t8 Y10 e10 h10 d10 t10 Y11-12 e11 h11 d11 t11 Y.TE Y1 e4 Y2 e4 Y3 e4 Y4 e3 Y5 e4 Y6 e10 Y7 e4 Y8 e8 Y9 e4 Y10 e4 Y1 d4 Y2 d10 Y3 d4 Y4 d8 Y5 d4 Y6 d4 Y7 d4 Y8 d4 Y9 d11 Y10 d10 Y0 e8 Y1 e10 Y2 e4 Y0 d4 Y1 d3 SHAR_EOF fi if test -f 'rndtquery.ts' then echo shar: "will not over-write existing file 'rndtquery.ts'" else sed 's/^Y//' << \SHAR_EOF > 'rndtquery.ts' Y# Y# RNDTQUERY.TS Y# Handles queries. Y# by Joshua Levy Y# Y# Justifications: Y# 1d10 and 3d6 are very common rolls. Y# 1d9+1 is the Cyberpunk stat generation roll. Y# 3d4-2 is my attempt at a bell shaped 1-10 roll. Y# Yquery RA_MIN 1d10 Yquery RA_MIN 3d6 Yquery RA_MIN 1d9+1 Yquery RA_MIN 3d4-2 Yquery RA_MAX 1d10 Yquery RA_MAX 3d6 Yquery RA_MAX 1d9+1 Yquery RA_MAX 3d4-2 Yquery RA_AVE 1d10 Yquery RA_AVE 3d6 Yquery RA_AVE 1d9+1 Yquery RA_AVE 3d4-2 Yquery RA_LEGAL 1d10 Yquery RA_LEGAL 3d6 Yquery RA_LEGAL 1d9+1 Yquery RA_LEGAL 3d4-2 Yquery RA_LEGAL 1-10 Yquery RA_LEGAL d4 Yquit SHAR_EOF fi if test -f 'rndtquery.mst' then echo shar: "will not over-write existing file 'rndtquery.mst'" else sed 's/^Y//' << \SHAR_EOF > 'rndtquery.mst' Y1 Y3 Y2 Y1 Y10 Y18 Y10 Y10 Y5 Y9 Y5 Y4 Y1 Y1 Y1 Y1 Y0 Y1 SHAR_EOF fi if test -f 'tbquery.ts' then echo shar: "will not over-write existing file 'tbquery.ts'" else sed 's/^Y//' << \SHAR_EOF > 'tbquery.ts' Y# Y# TBQUERY.TS Y# This test script tests the query facility. Y# Yread simp1.tab Yquery max Yquery min Yquery ave Yquery legal Yfree Y# Yread multi1.tab Yquery max Yquery min Yquery ave Yquery legal Yfree Y# Yread simpbig1.tab Yquery max Yquery min Yquery ave Yquery legal Yfree Y SHAR_EOF fi if test -f 'rndtgas.ts' then echo shar: "will not over-write existing file 'rndtgas.ts'" else sed 's/^Y//' << \SHAR_EOF > 'rndtgas.ts' Yseed 0 Ygasdev 10 Ygasdev 2 Ygasdev 30 Yquit Y SHAR_EOF fi cd .. exit 0 # End of shell archive