//
//  MIMIC - Jeremy Ruston, 27-10-92
//  A program which babbles on loosely in the style of a given text files
//
//


#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <time.h>


void main(int argc,char *argv[]);
void init(void);
void learn(char *filename);
void mimic(void);
unsigned choose(unsigned limit);


int mlen; // Length of matched substring
char *text; // Pointer to sample text
long textlen; // Length of sample text


void main(int argc,char *argv[])
{
	int t,n;
	mlen = 4;
	if(argc<2)
		{
		printf("MIMIC: [<filename> | /x]\n");
		printf("where x is substring length to match\n");
		}
	else
		{
		init();
		for(t=1;t<=argc-1;t++)
			if(argv[t][0]=='/')
				{
				sscanf(argv[t]+1,"%d",&n);
				if((n>1) && (n<256))
					mlen = n;
				}
			else
				learn(argv[t]);
		if (textlen>mlen)
			while(1)
				mimic();
		}
	exit(0);
}

void init(void)
{
	textlen = 0;
	text = NULL;
}

void learn(char *filename)
{
	FILE *f;
	long len;
	char *newtext;
	f = fopen(filename,"rb");
	if(f==NULL)
		printf("(*** Cannot open ***)");
	else
		{
		fseek(f,0,SEEK_END);
		len = ftell(f);
		fseek(f,0,SEEK_SET);
		newtext = (char *)realloc(text,(size_t)(textlen+len));
		if(newtext!=NULL)
			{
			text = newtext;
			fread((void *)(text+textlen),sizeof(char),(size_t)len,f);
			textlen += len;
			}
		fclose(f);
		}
}

void mimic(void)
{
	int inc,t,p,nomatch;
	char prev[256],c;
	printf("\n(Substring match length is %d)\n\n",mlen);
	srand((unsigned)time(NULL));
	for(t=0;t<mlen;t++)
		{
		prev[t] = text[t];
		putchar(prev[t]);
		}
	inc = 1;
	do{
		p = choose((int)textlen)-inc;
		do{
			p=p+inc;
			while(p<0)                             
				p+=textlen;
			while(p>=textlen)
				p-=textlen;
			nomatch = 0;
			for(t=0;t<mlen;t++)
				if(text[(p+t)%textlen]!=prev[t])
					nomatch = 1;
		}while(nomatch);
		inc = -inc;
		c = text[(p+mlen)%textlen];
		putchar(c);
		for(t=0;t<mlen-1;t++)
			prev[t] = prev[t+1];
		prev[mlen-1] = c;
	}while(!kbhit());
	getchar();
}

// Lousey little function to return a random integer from 0 to limit-1
unsigned choose(unsigned limit)
{
	return(rand() % limit);
}
