/*

File PlainWord.m

Letters and words lie at the heart of the crossword puzzle search.  The search currently proceeds one letter at a time; looking one word at a time can be construed as a special case.  Words have only one function: to keep track of the possibilities that remain.

*/

#import <appkit/appkit.h>
#import <stdlib.h>

#import "Plain.h"
#import "Puzzle.h"
#import "FunctionCache.h"


/* 行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行  */


@implementation PlainWord

- (countTable) getCount		{	return count;	}


/* 行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行  */


- initPuzzle: (id) thePuzzle
{
	[super  init];
	puzzle = thePuzzle;
	
	return self;
}


- setSquares: (id) theSquares
{
	int		i;
	
	i = n = [squares = theSquares  count];
	last = 0;
	pattern[n] = '\0';
	while (i--) pattern[i] = WILDCARD;
	[self  update];
	
	return self;
}


- free
{
	[squares  free];
	[super  free];
	
	return self;
}


/* 行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行  */


- changeLetter: (int) i  to: (char) c
{
	pattern[last = i] = c;
	[self  update];
	
	return self;
}


/* 行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行  */


- update;
{
	id				state, dictionary;
	id				match;
	wordIndex		* index;
	char			* key;
	char			string [MAXLETTERS];
	countTable		numbers;
	int				i, j;
	
	state = [puzzle  getState];
	dictionary = [puzzle  getDictionary];
	
	if (numbers = (countTable) [[state  getCountCache]  find: pattern])
	{
		for (i = 0; i < MAXLETTERS; i++)
		for (j = 0; j < LETTERS; j++) count[i][j] = numbers[i][j];
	}
	
	else if ((match = [dictionary  find: pattern  changeAt: last]))
	{
		for (i = 0; i < MAXLETTERS; i++)
		for (j = 0; j < LETTERS; j++) count[i][j] = 0;
	
		i = [match  count];
		while (i--)
		{
			[dictionary  read: string  word: WORD(match, i)  forLength: n];
			[self  processWord: string];
		}
		
		numbers = (countTable) malloc(sizeof(int) * LETTERS * MAXLETTERS);
		key = (char *) malloc(n + 1);
		strcpy(key, pattern);
		
		for (i = 0; i < MAXLETTERS; i++)
		for (j = 0; j < LETTERS; j++) numbers[i][j] = count[i][j];
		
		[[state  getCountCache]  add: key  value: numbers];
	}
	
	else
	{
		index = [dictionary  getIndex];
		
		for (i = 0; i < n; i++)
		for (j = 0; j < LETTERS; j++)
					count[i][j] = (* index)[n].linkTable[j][i].n;
	}
	
	[squares  makeObjectsPerform: @selector(update)];
	return self;
}


- processWord: (char *) string
{
	int		j;
	
	for (j = 0; j < n; j++)
				count[j][string[j] - 'a']++;
	
	return self;
}


@end