eliot/game/board_search.c
2004-04-08 09:43:06 +00:00

266 lines
9.6 KiB
C

/* Eliot */
/* Copyright (C) 1999 Antoine Fraboulet */
/* antoine.fraboulet@free.fr */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 2 of the License, or */
/* (at your option) any later version. */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, write to the Free Software */
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* $Id: board_search.c,v 1.1 2004/04/08 09:43:06 afrab Exp $ */
#include <stdio.h>
#include <string.h>
#include <dic.h>
#include "tiles.h"
#include "bag.h"
#include "rack.h"
#include "round.h"
#include "results.h"
#include "board.h"
#include "board_internals.h"
#include "debug.h"
/*
* computes the score of a word, coordinates may be changed to reflect
* the real direction of the word
*/
static void
Boardsearch_evalmove(
tile_t tiles[BOARD_REALDIM][BOARD_REALDIM],
int points[BOARD_REALDIM][BOARD_REALDIM],
char joker[BOARD_REALDIM][BOARD_REALDIM],
Results results, Round word)
{
int i,pts,ptscross;
int l,t,fromrack;
int len,row,col,wordmul;
fromrack = 0;
pts = 0;
ptscross = 0;
wordmul = 1;
len = Round_wordlen(word);
row = Round_row(word);
col = Round_column(word);
for(i=0; i < len; i++)
{
if (tiles[row][col+i])
{
if (! joker[row][col+i])
pts += Tiles_points[Round_gettile(word,i)];
}
else
{
if (! Round_joker(word,i))
l = Tiles_points[Round_gettile(word,i)] *
Board_tile_multipliers[row][col+i];
else
l = 0;
pts += l;
wordmul *= Board_word_multipliers[row][col+i];
t = points[row][col+i];
if (t >= 0)
ptscross += (t + l) * Board_word_multipliers[row][col+i];
fromrack++;
}
}
pts = ptscross + pts * wordmul + 50 * (fromrack == 7);
Round_setbonus(word,fromrack == 7);
Round_setpoints(word,pts);
if (Round_dir(word) == VERTICAL) {
Round_setrow(word,col);
Round_setcolumn(word,row);
}
Results_addsorted(results,word);
if (Round_dir(word) == VERTICAL) {
Round_setrow(word,row);
Round_setcolumn(word,col);
}
}
static void
ExtendRight(Dictionary dic,
tile_t tiles[BOARD_REALDIM][BOARD_REALDIM],
unsigned int cross[BOARD_REALDIM][BOARD_REALDIM],
int points[BOARD_REALDIM][BOARD_REALDIM],
char joker[BOARD_REALDIM][BOARD_REALDIM],
Rack rack, Round partialword,
Results results, unsigned int n, int row, int column, int anchor)
{
tile_t l;
unsigned int succ;
if (! tiles[row][column]) {
if (Dic_word(dic,n) && column > anchor)
Boardsearch_evalmove(tiles,points,joker,results,partialword);
for(succ = Dic_succ(dic,n); succ ; succ = Dic_next(dic,succ)) {
l = Dic_chr(dic,succ);
if (cross[row][column] & (1 << l)) {
if (Rack_in(rack,l)) {
Rack_remove(rack,l);
Round_addrightfromrack(partialword,l,0);
ExtendRight(dic,tiles,cross,points,joker,
rack,partialword,results,
succ,row,column + 1,anchor);
Round_removerighttorack(partialword,l,0);
Rack_add(rack,l);
}
if (Rack_in(rack,(tile_t)JOKER_TILE)) {
Rack_remove(rack,(tile_t)JOKER_TILE);
Round_addrightfromrack(partialword,l,1);
ExtendRight(dic,tiles,cross,points,joker,
rack,partialword,results,
succ,row,column + 1,anchor);
Round_removerighttorack(partialword,l,1);
Rack_add(rack,JOKER_TILE);
}
}
}
} else {
l = tiles[row][column];
for(succ = Dic_succ(dic,n); succ ; succ = Dic_next(dic,succ)) {
if (Dic_chr(dic,succ) == l) {
Round_addrightfromboard(partialword,l);
ExtendRight(dic,tiles,cross,points,joker,
rack,partialword,
results,succ,row,column + 1,anchor);
Round_removerighttoboard(partialword,l);
}
}
}
}
static void
LeftPart(Dictionary dic,
tile_t tiles[BOARD_REALDIM][BOARD_REALDIM],
unsigned int cross[BOARD_REALDIM][BOARD_REALDIM],
int points[BOARD_REALDIM][BOARD_REALDIM],
char joker[BOARD_REALDIM][BOARD_REALDIM],
Rack rack, Round partialword,
Results results, int n, int row, int anchor, int limit)
{
tile_t l;
int succ;
ExtendRight(dic,tiles,cross,points,joker,rack,
partialword,results,n,row,anchor,anchor);
if (limit > 0) {
for(succ = Dic_succ(dic,n); succ ; succ = Dic_next(dic,succ)) {
l = Dic_chr(dic,succ);
if (Rack_in(rack,l)) {
Rack_remove(rack,l);
Round_addrightfromrack(partialword,l,0);
Round_setcolumn(partialword,Round_column(partialword) - 1);
LeftPart(dic,tiles,cross,points,joker,
rack,partialword,results,
succ,row,anchor,limit - 1);
Round_setcolumn(partialword,Round_column(partialword) + 1);
Round_removerighttorack(partialword,l,0);
Rack_add(rack,l);
}
if (Rack_in(rack,JOKER_TILE)) {
Rack_remove(rack,JOKER_TILE);
Round_addrightfromrack(partialword,l,1);
Round_setcolumn(partialword,Round_column(partialword) - 1);
LeftPart(dic,tiles,cross,points,joker,
rack,partialword,results,
succ,row,anchor,limit - 1);
Round_setcolumn(partialword,Round_column(partialword) + 1);
Round_removerighttorack(partialword,l,1);
Rack_add(rack,JOKER_TILE);
}
}
}
}
static void
Board_search_aux(Dictionary dic,
tile_t tiles[BOARD_REALDIM][BOARD_REALDIM],
unsigned int cross[BOARD_REALDIM][BOARD_REALDIM],
int points[BOARD_REALDIM][BOARD_REALDIM],
char joker[BOARD_REALDIM][BOARD_REALDIM],
Rack rack,Results results, Direction dir)
{
int row,column,lastanchor;
Round partialword;
partialword = Round_create();
for(row = 1; row <= BOARD_DIM; row++) {
Round_init(partialword);
Round_setdir(partialword,dir);
Round_setrow(partialword,row);
lastanchor = 0;
for(column = 1; column <= BOARD_DIM; column++) {
if (! tiles[row][column] &&
(tiles[row][column - 1] || tiles[row][column + 1] ||
tiles[row - 1][column] || tiles[row + 1][column]))
{
if (tiles[row][column - 1]) {
Round_setcolumn(partialword,lastanchor + 1);
ExtendRight(dic,tiles,cross,points,joker,
rack,partialword,results,
Dic_root(dic),row,lastanchor + 1,column);
} else {
Round_setcolumn(partialword,column);
LeftPart(dic,tiles,cross,points,joker,
rack,partialword,results,
Dic_root(dic),row,column,column -
lastanchor - 1);
}
lastanchor = column;
}
}
}
Round_destroy(partialword);
}
void
Board_search(Dictionary dic,Board board, Rack rack,Results results)
{
Board_search_aux(dic,board->tiles_r,board->cross_r,
board->point_r,board->joker_r,
rack,results,HORIZONTAL);
Board_search_aux(dic,board->tiles_c,board->cross_c,
board->point_c,board->joker_c,
rack,results,VERTICAL);
}
void
Board_search_first(Dictionary dic, Board board, Rack rack, Results results)
{
Round partialword;
int row = 8,column = 8;
partialword = Round_create();
Round_setrow(partialword,row);
Round_setcolumn(partialword,column);
Round_setdir(partialword,HORIZONTAL);
LeftPart(dic,board->tiles_r,board->cross_r,board->point_r,board->joker_r,
rack,partialword,results,Dic_root(dic),row,column,
Rack_ntiles(rack) - 1);
Round_destroy(partialword);
}