RPG table handling routines (2/2)

Flame Bait joshua at athertn.Atherton.COM
Fri Dec 14 04:55:55 AEST 1990


If you missed part one of this post, you can get it from the archiver
server at atherton.com.  Send email to archive-server at atherton.com which
contains an empty subject line, but has these lines in its body:

path your at email.address
send programs table03a.shar

Sending email containing just `help' or `index' may also be useful.

Joshua Levy (joshua at 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



More information about the Alt.sources mailing list