/*
 *
 * hook.c -- update allowable hooks
 *
 * This code is copyright 1995 by James A. Cherry, jac@doe.carleton.ca.
 * It is not to be redistributed or modified without his permission.
 *
 */

#include "funddefs.h"
#include "globals.h"
#include "botutil.h"
#include "proto.h"

void UpdateHooks( newlet, placed, xinc, yinc )
    struct plrlet *newlet;
    int placed, xinc, yinc;
/* Given a board, fill in the hook tables appropriately.  Messy! */
{
    struct plrlet *currlet;
    int i, j, bpos;
    int dx, dy;
    int x, y, sx, sy;
    int bbx, bby, bex, bey, bsx, bsy, esx, esy;
    int found;
    char c;
    char vword[20];
    
    bpos = 0;
    dx = 1 - xinc;
    dy = 1 - yinc;
    for( i = 0; i <= placed; i++ ) {
	if( i < placed ) {
	    currlet = &(newlet[i]);
	    x = currlet->x;
	    y = currlet->y;
	} else {
	    x = newlet[0].x;
	    y = newlet[0].y;
	    dx = xinc;
	    dy = yinc;
	}
/* Mark used squares */
	HHook[y][x][26] = -2;
	VHook[y][x][26] = -2;
	sx = x;
	sy = y;
	while( Board[y][x] >= 'A' && x - dx > 0 && y - dy > 0 ) {
	    x -= dx;
	    y -= dy;
	}
	if( Board[y][x] < 'A' ) {
	    bbx = x;
	    bby = y;
	    if( x - dx > 0 && y - dy > 0 ) {
		x -= dx;
		y -= dy;
		while( Board[y][x] >= 'A' && x - dx > 0 && y - dy > 0 ) {
		    x -= dx;
		    y -= dy;
		}
		if( Board[y][x] < 'A' ) {
		    bsx = x + dx;
		    bsy = y + dy;
		} else {
		    bsx = x;
		    bsy = y;
		}
	    } else {
		bsx = x;
		bsy = y;
	    }
	} else {
	    bbx = x - dx;
	    bby = y - dy;
	    bsx = x;
	    bsy = y;
	}
	x = sx;
	y = sy;
	while( Board[y][x] >= 'A' && x + dx < 16 && y + dy < 16 ) {
	    x += dx;
	    y += dy;
	}
	if( Board[y][x] < 'A' ) {
	    bex = x;
	    bey = y;
	    if( x + dx < 16 && y + dy < 16 ) {
		x += dx;
		y += dy;
		while( Board[y][x] >= 'A' && x + dx < 16 && y + dy < 16 ) {
		    x += dx;
		    y += dy;
		}
		if( Board[y][x] < 'A' ) {
		    esx = x;
		    esy = y;
		} else {
		    esx = x + dx;
		    esy = y + dy;
		}
	    } else {
		esx = x + dx;
		esy = y + dy;
	    }
	} else {
	    bex = x + dx;
	    bey = y + dy;
	    esx = bex + dx;
	    esy = bey + dy;
	}
	if( bbx > 0 && bby > 0 ) {
	    j = 0;
	    for( x = bsx, y = bsy; x != bex || y != bey; x += dx, y += dy ) {
		if( Board[y][x] < 'A' ) bpos = j;
		vword[j++] = Board[y][x];
	    }
	    vword[j] = '\0';
	    found = 0;
	    for( c = 'A'; c <= 'Z'; c++ ) {
		vword[bpos] = c;
		if( BinSearch( vword ) ) {
		    found++;
		    if( ( xinc == 1 && i != placed )
			|| ( xinc == 0 && i == placed ) )
			HHook[bby][bbx][c - 'A'] = 1;
		    else
			VHook[bby][bbx][c - 'A'] = 1;
		} else {
		    if( ( xinc == 1 && i != placed )
			|| ( xinc == 0 && i == placed ) )
			HHook[bby][bbx][c - 'A'] = 0;
		    else
			VHook[bby][bbx][c - 'A'] = 0;
		}
	    }
	    if( ( xinc == 1 && i != placed )
		|| ( xinc == 0 && i == placed ) )
		HHook[bby][bbx][26] = found;
	    else
		VHook[bby][bbx][26] = found;
	}
	if( bex < 16 && bey < 16 ) {
	    j = 0;
	    for( x = bbx + dx, y = bby + dy; x != esx || y != esy; x += dx, y += dy ) {
		if( Board[y][x] < 'A' ) bpos = j;
		vword[j++] = Board[y][x];
	    }
	    vword[j] = '\0';
	    found = 0;
	    for( c = 'A'; c <= 'Z'; c++ ) {
		vword[bpos] = c;
		if( BinSearch( vword ) ) {
		    found++;
		    if( ( xinc == 1 && i != placed )
			|| ( xinc == 0 && i == placed ) )
			HHook[bey][bex][c - 'A'] = 1;
		    else
			VHook[bey][bex][c - 'A'] = 1;
		} else {
		    if( ( xinc == 1 && i != placed )
			|| ( xinc == 0 && i == placed ) )
			HHook[bey][bex][c - 'A'] = 0;
		    else
			VHook[bey][bex][c - 'A'] = 0;
		}
	    }
	    if( ( xinc == 1 && i != placed )
		|| ( xinc == 0 && i == placed ) )
		HHook[bey][bex][26] = found;
	    else
		VHook[bey][bex][26] = found;
	}
    }
}

void print_hooks()
/* Output hook tables to logfile. */
{
    int i, j;
    
    LPrint( "\n" );
    for( i = 1; i < 16; i++ ) {
	for( j = 1; j < 16; j++ )
	    LPrint( " %2d", HHook[i][j][26] );
	LPrint( "\n" );
    }
    LPrint( "\n" );
    for( i = 1; i < 16; i++ ) {
	for( j = 1; j < 16; j++ )
	    LPrint( " %2d", VHook[i][j][26] );
	LPrint( "\n" );
    }
    LPrint( "\n" );
}

void dump_internals()
/* Dump internal structures to logfile. */
{
    int r, c, i;
    
    print_hooks();
    LPrint( "My Words:" );
    for( i = 0; i < MyWLen; i++ )
	LPrint( " %s", MyWList[i] );
    LPrint( "\nTheir Words:" );
    for( i = 0; i < TheirWLen; i++ )
	LPrint( " %s", TheirWList[i] );
    LPrint( "\nBoard:\n" );
    for( r = 1; r < 16; r++ ) {
	for( c = 1; c < 16; c++ )
	    LPrint( "%c ", Board[r][c] );
	LPrint( "\n" );
    }
    LPrint( "Tiles left: " );
    for( i = 0; i < 27; i++ )
	LPrint( "%d ", TilesLeft[i] );
    
}

void CalcHooks()
/* Calculate hooks, given a board. */
{
    int placed, xinc, yinc;
    struct plrlet newlet[15];
    int r, sr, c, sc, i;
    
/* Next line was moved from botutil3.c to here to avoid problems with
   critique seg faulting. */
    MyWLen = 0; TheirWLen = 0;
    xinc = 1;
    yinc = 0;
    for( r = 1; r < 16; r++ ) {
	c = 1;
      in_looph:
	while( Board[r][c] < 'A' && c < 16 ) c++;
	if( c == 16 ) continue;
	placed = 0;
	sc = c;
	while( Board[r][c] >= 'A' && c < 16 ) {
	    newlet[placed].x = c;
	    newlet[placed].y = r;
	    c++;
	    placed++;
	}
	if( placed > 1 ) {
	    UpdateHooks( newlet, placed, xinc, yinc );
/* Assume horiz. words are mine.  Bogus, but not really important. */
	    for( i = 0; i < placed; i++ )
		MyWList[MyWLen][i] = Board[r][sc + i];
	    MyWList[MyWLen][i] = '\0';
	    MyWLen++;
	}
	if( c < 16 ) goto in_looph;
    }
    
    xinc = 0;
    yinc = 1;
    for( c = 1; c < 16; c++ ) {
	r = 1;
      in_loopv:
	while( Board[r][c] < 'A' && r < 16 ) r++;
	if( r == 16 ) continue;
	placed = 0;
	sr = r;
	while( Board[r][c] >= 'A' && r < 16 ) {
	    newlet[placed].x = c;
	    newlet[placed].y = r;
	    r++;
	    placed++;
	}
	if( placed > 1 ) {
	    UpdateHooks( newlet, placed, xinc, yinc );
/* Assume vert. words are theirs. */
	    for( i = 0; i < placed; i++ )
		TheirWList[TheirWLen][i] = Board[sr + i][c];
	    TheirWList[TheirWLen][i] = '\0';
	    TheirWLen++;
	}
	if( r < 16 ) goto in_loopv;
    }
/*  dump_internals(); */
}
