From: duncan@ossian.spd.eee.strathclyde.ac.uk (Duncan C Thomson)
Newsgroups: soc.culture.esperanto
Subject: Esperanta Skrablo / Scrabble in Esperanto (parto 1 el 2)
Date: 13 Oct 92 16:28:37 GMT
Organization: SPD, Strathclyde University, Glasgow, Scotland
Originator: duncan@ossian

Jen esperanta versio de skrablo `shar'-formate.

Atentu mian subskribon je la fino...

	-Duncan


#!/bin/sh
# to extract, remove the header and type "sh filename"
if `test ! -s ./Makefile`
then
echo "writing ./Makefile"
cat > ./Makefile << '\Rogue\Monster\'
skrablo: cmove.o misc.o init.o smain.o pmove.o score.o
		/bin/cc smain.o cmove.o misc.o init.o pmove.o score.o -o skrablo -lcurses -ltermcap
cmove.o pmove.o init.o misc.o score.o smain.o: scrab.h globals.h
\Rogue\Monster\
else
  echo "will not over write ./Makefile"
fi
if `test ! -s ./cmove.c`
then
echo "writing ./cmove.c"
cat > ./cmove.c << '\Rogue\Monster\'
/*
 *
 * cmove.c -- computer move algorithm
 *
 */

#include "scrab.h"
#include "globals.h"

int b1, b2, ntiles;
int tilev[7];
struct plrlet newlet[7];

computer_move( plr )
  int plr;
{
	int retcode;

	clear_prompt();
	printw( "\n  Trasercxante tabulo...\n" );
	refresh();
	init_cmove( plr );
	if( board[8][8] < 'A' ) {
		retcode = first_move( plr );
	} else {
		retcode = cpu_move( plr );
	}
	if( retcode == -1 ) {
		move( 21, 0 );
		printw( "  CPU ne povis ludi\n" );
		press_return();
		game_done++;
	} else game_done = 0;
}

init_cmove( plr ) {
	int i;

	b1 = -1;
	b2 = -1;
	for( i = 0; i < 7; i++ ) {
		if( plr_tiles[plr][i] == CH_BL ) {
			if( b1 < 0 ) b1 = i;
			else b2 = i;
		}
	}
	ntiles = 0;
	for( i = 0; i < 7; i++ ) {
		if( plr_tiles[plr][i] != 0 ) {
			tilev[i] = plr_tiles[plr][i] - 'A';
			if( plr_tiles[plr][i] == CH_BL ) tilev[i] = 28;
			ntiles++;
		} else tilev[i] = 29;
	}
	chead = NULL;
}

int first_move( plr )
  int plr;
{
	long ind, eind;
	int used[7];
	char tword[16], dummy[8], ch;
	int i, j, le;
	int xinc, yinc;
	struct plrlet *currlet;

	for( ind = wlen[2], eind = wlen[8]; ind < eind; ind++ ) {
		strcpy( tword, &(words[wptr[ind]]) );
		le = strlen( tword );
		for( i = 0; i < 7; i++ ) used[i] = 0;
		for( i = 0; i < le; i++ ) {
			ch = tword[i];
			for( j = 0; j < 7; j++ ) {
				if( ch == plr_tiles[plr][j] && used[j] == 0 ) {
					used[j] = 1;
					break;
				}
			}
			if( j == 7 ) {
				if( b1 < 0 ) break;
				if( used[b1] == 1 ) {
					if( b2 < 0 ) break;
					else used[b2] = 1;
				} else used[b1] = 1;
			}
		}
		if( i != le ) continue;
		for( i = 0; i < le; i++ ) dummy[i] = '*';
		dummy[le] = '\0';
		for( xinc = 1, yinc = 0; xinc >= 0; xinc--, yinc++ ) {
			for( i = 9 - le; i < 9; i++ ) {
				for( j = 0; j < le; j++ ) {
					currlet = &(newlet[j]);
					currlet->x = 8;
					currlet->y = 8;
					if( yinc == 0 ) currlet->x = i + j;
					else currlet->y = i + j;
				}
				eval_score( tword, dummy, le, le, 1, yinc );
			}
		}
	}
	if( chead == NULL ) return( -1 );
	pick_word( plr );
	return( 1 );
}

pick_word( plr )
  int plr;
{
	int i, j, n, w, dir;
	int sd4, mean, pn, bar;
	compmove *moveptr, *tptr, *uptr;
	scoreent *schead, *rptr, *sptr;

	if( plr_skills[plr] == SKILL_EXPERT ) moveptr = chead;
	else {
/*		move( 18, 0 );
		printw( "Poentaraj distribuoj: " ); */
		tptr = chead;
		i = -1;
		j = 0;
		n = 0;
		schead = NULL;
		for( ;; ) {
			if( tptr != NULL && tptr->score == i ) j++;
			else {
				if( i != -1 ) {
/*					printw( "%d-%d,", i, j ); */
					sptr = (scoreent *) malloc( SC_SIZE );
					sptr->next = NULL;
					sptr->score = i;
					sptr->num = j;
					if( schead == NULL ) schead = sptr;
					else rptr->next = sptr;
					rptr = sptr;
				}
				if( tptr != NULL ) {
					i = tptr->score;
					j = 1;
					n++;
				}
			}
			if( tptr == NULL ) break;
			tptr = tptr->next;
		}
		sd4 = ( n * 40 ) / 200;
		mean = ( n * mean_pcts[SKILL_LEVELS - plr_skills[plr]] + 50 ) / 100;
		pn = get_random() % 2;
		bar = get_random() % normal_sum;
		for( i = 0; i < 40; i++ ) {
			if( bar - normal_dist[i] > 0 ) bar -= normal_dist[i];
			else break;
		}
		if( pn == 0 ) mean += ( i * sd4 ) / 40;
		else mean -= ( i * sd4 ) / 40;
		j = sd4 / 40;
		if( j > 1 )
			while( ( bar - normal_dist[i] / j ) > 0 ) {
				bar -= normal_dist[i] / j;
				if( pn == 0 ) mean++;
				else mean--;
			}
		if( mean < 0 ) mean = 0;
		else if( mean > n - 1 ) mean = n - 1;

/*		move( 21, 0 );
		printw( "  %d elektoj; %d meze, %d dir, %d bar.", n, mean, pn, bar );
		printw( "  Fina elekto: %d.", mean );
		press_return(); */

		rptr = schead;
		while( mean-- > 0 ) rptr = rptr->next;
		i = rptr->score;
		j = get_random() % rptr->num;
		moveptr = chead;
		while( moveptr->score != i ) moveptr = moveptr->next;
		while( j-- > 0 ) moveptr = moveptr->next;
		rptr = schead;
		while( rptr != NULL ) {
			sptr = rptr->next;
			free( (scoreent *) rptr );
			rptr = sptr;
		}
	}

	for( i = 0; i < moveptr->placed; i++ )
		plr_tiles[plr][moveptr->newlet[i].tilepos] = 0;
	dir = moveptr->dir;
	w = find_new_words( &(moveptr->newlet[0]), moveptr->placed, 1 - dir, dir );
	display_words( plr, &(moveptr->newlet[0]), w, moveptr->placed );
	tptr = chead;
	while( tptr != NULL ) {
		uptr = tptr->next;
		free( (compmove *) tptr );
		tptr = uptr;
	}
}

int cpu_move( plr )
  int plr;
{
	int sx, sy, dir, xinc, yinc;
	int x, y;
	int blank, tile, oldbl;

	for( sy = 1; sy < 16; sy++ ) {
		for( sx = 1; sx < 16; sx++ ) {
			for( dir = 0; dir < 2; dir++ ) {
				xinc = 1 - dir;
				yinc = dir;
				x = sx;
				y = sy;
				blank = 0;
				tile = 0;
				oldbl = 0;
				if( x - xinc > 0 && y - yinc > 0 )
					if( board[y - yinc][x - xinc] >= 'A' ) continue;
				while( x < 16 && y < 16 && blank < ntiles ) {
					if( board[y][x] < 'A' ) blank++;
					if( board[y][x] >= 'A' ||
						( x - xinc > 0 && y - yinc > 0 &&
						  board[y - yinc][x - xinc] >= 'A' ) ||
						( x + xinc < 16 && y + yinc < 16 &&
						  board[y + yinc][x + xinc] >= 'A' ) ||
						( x - yinc > 0 && y - xinc > 0 &&
						  board[y - xinc][x - yinc] >= 'A' ) ||
						( x + yinc < 16 && y + xinc < 16 &&
						  board[y + xinc][x + yinc] >= 'A' ) )
						tile++;
					if( blank > oldbl && tile > 0 ) {
						oldbl = blank;
						move( BOARD_UY + sy - 1, BOARD_LX + sx - 1 );
						refresh();
						try_tiles( sx, sy, blank, dir );
					}
					x += xinc; y += yinc;
				}
			}
		}
	}
	if( chead == NULL ) return( -1 );
	pick_word( plr );
	return( 1 );
}

try_tiles( sx, sy, placed, dir )
  int sx, sy, placed, dir;
{
	int xinc, yinc, x, y;
	int i, j, k, w;
	int let[28], tlet[28], bt, tbt;
	int used[7], tileind[7], index[7], stack[7], blankloc[7];
	int level, len;
	long f, ef;
	char c, tword[16], ttword[16], dword[16];

/*	clear_rect( 20, 0, 21, 79 );
	printw( "  try_tiles() called with (%2d,%2d), %d tiles, dir %d",
	  sy, sx, placed, dir ); */

	xinc = 1 - dir;
	yinc = dir;
	x = sx;
	y = sy;
	for( i = 0; i < placed; i++ ) {
		while( board[y][x] >= 'A' ) {
			x += xinc;
			y += yinc;
		}
		newlet[i].x = x;
		newlet[i].y = y;
		newlet[i].letter = CH_BL;
		newlet[i].blankchar = '*';
		x += xinc;
		y += yinc;
	}
	w = find_new_words( &newlet[0], placed, xinc, yinc );
	for( i = 0; i < w - 1; i++ ) {
		stack[i] = 0;
		blankloc[i] = new_words[i].blankloc;
		if( dir == 0 )
			index[i] = new_words[i].startx - new_words[w - 1].startx;
		else
			index[i] = new_words[i].starty - new_words[w - 1].starty;
	}
	for( i = 0; i < 28; i++ ) let[i] = -1;
	bt = 0;
	for( i = 0; i < 7; i++ ) {
		used[i] = 0;
		if( tilev[i] < 28 ) {
			let[tilev[i]]++;
			if( let[tilev[i]] == 0 ) let[tilev[i]]++;
		} else if( tilev[i] == 28 ) bt++;
	}
	level = 0;
	strcpy( tword, new_words[w - 1].letters );
	strcpy( ttword, new_words[w - 1].letters );
	len = strlen( tword );
	do {
		if( level != w - 1 ) {
			if( level < w - 1 ) {
				c = stack[level];
				if( let[c] > 0 || bt > 0 ) {
					new_words[level].letters[blankloc[level]] = c + 'A';
					f = bin_search( new_words[level].letters );
				} else f = 0;
			} else {
				level = w - 2;
				if( level < 0 ) break;
				c = stack[level];
				if( let[c] >= 0 ) let[c]++;
				else bt++;
				used[tileind[level]] = 0;
				f = 0;
			}
			if( f == 0 ) {
				for( ;; ) {
					stack[level]++;
					if( stack[level] == 28 ) {
						level--;
						if( level >= 0 ) {
							c = stack[level];
							if( let[c] >= 0 ) let[c]++;
							else bt++;
							used[tileind[level]] = 0;
							continue;
						}
					}
					break;
				}
			} else {
				tword[index[level]] = c + 'A';
				if( let[c] > 0 ) let[c]--;
				else {
					bt--;
					c = 28;
				}
				for( i = 0; i < 7; i++ ) {
					if( tilev[i] == c && used[i] == 0 ) {
						used[i] = 1;
						tileind[level] = i;
						break;
					}
				}
				level++;
				if( level < w - 1 ) stack[level] = 0;
			}
		} else {

/*			clear_rect( 20, 0, 21, 79 );
			printw( "  (%2d,%2d)  Tileind[]:", sy, sx );
			for( i = 0; i < w - 1; i++ )
				printw( " %d", tileind[i] );
			printw( "  Stack[]:" );
			for( i = 0; i < w - 1; i++ )
				printw( " %2d", stack[i] );
			printw( "  Used[]:" );
			for( i = 0; i < 7; i++ )
				printw( " %d", used[i] );
			printw( "  Words: %d\n", w );
			for( i = 0; i < w - 1; i++ )
				printw( "  %s", new_words[i].letters );
			printw( "  %s", tword );
			press_return(); */

			for( f = wlen[len], ef = wlen[len + 1]; f < ef; f++ ) {
				strcpy( dword, &(words[wptr[f]]) );
				for( i = 0; i < len; i++ )
					if( tword[i] >= 'A' && tword[i] != dword[i] ) break;
				if( i < len ) continue;
				for( i = 0; i < 28; i++ ) tlet[i] = let[i];
				tbt = bt;
				for( i = 0; i < len; i++ ) {
					if( tword[i] >= 'A' ) continue;
					c = dword[i] - 'A';
					if( tlet[c] <= 0 && tbt == 0 ) break;
					if( tlet[c] > 0 ) tlet[c]--;
					else tbt--;
				}
				if( i < len ) continue;
				eval_score( dword, ttword, len, placed, w, dir );
			}
			level = w;
		}
	} while( level >= 0 );

}

eval_score( dword, tword, len, placed, w, dir )
  char *dword, *tword;
  int len, placed, w, dir;
{
	int xinc, yinc;
	int i, j, k;
	int tused[7];
	char c;
	int score;
	compmove *newptr, *ptr1, *ptr2;

	xinc = 1 - dir;
	yinc = dir;
	for( i = 0; i < 7; i++ ) tused[i] = 0;
	for( i = 0, k = 0; i < len; i++ ) {
		if( tword[i] >= 'A' ) continue;
		c = dword[i];
		for( j = 0; j < 7; j++ ) {
			if( c == tilev[j] + 'A' && tused[j] == 0 ) {
				tused[j] = 1;
				break;
			}
		}
		if( j == 7 ) {
			if( b1 < 0 ) break;
			if( tused[b1] == 1 ) {
				if( b2 < 0 ) break;
				else {
					j = b2;
					tused[b2] = 1;
				}
			} else {
				j = b1;
				tused[b1] = 1;
			}
		}
		if( j == 7 ) {
			move( 20, 0 );
			printw( "*** Morta eraro en eval_score()" );
			exit_window();
			exit( 1 );
		}
		if( j != b1 && j != b2 ) newlet[k].letter = c;
		else {
			newlet[k].letter = CH_BL;
			newlet[k].blankchar = c;
		}
		newlet[k++].tilepos = j;
	}
	i = find_new_words( &newlet[0], placed, xinc, yinc );
	score = 0;
	for( i = 0; i < w; i++ ) score += new_words[i].score;
	newptr = (compmove *) malloc( CM_SIZE );
	if( newptr == NULL ) {
		move( 20, 0 );
		printw( "*** Morta eraro: memoro ne restas en eval_score()" );
		exit_window();
		exit( 1 );
	}
	newptr->next = NULL;
	newptr->score = score;
	newptr->placed = placed;
	newptr->dir = dir;
	for( i = 0; i < placed; i++ ) {
		newptr->newlet[i].x = newlet[i].x;
		newptr->newlet[i].y = newlet[i].y;
		newptr->newlet[i].letter = newlet[i].letter;
		newptr->newlet[i].blankchar = newlet[i].blankchar;
		newptr->newlet[i].tilepos = newlet[i].tilepos;
	}
	if( chead == NULL ) chead = newptr;
	else if( score > chead->score ) {
		newptr->next = chead;
		chead = newptr;
	} else {
		ptr1 = chead;
		while( ptr1 != NULL && score <= ptr1->score ) {
			ptr2 = ptr1;
			ptr1 = ptr1->next;
		}
		newptr->next = ptr1;
		ptr2->next = newptr;
	}

/*	clear_rect( 21, 0, 21, 79 );
	printw( "  (%2d,%2d) %d Vortoj:", newlet[0].y, newlet[0].x, dir );
	for( i = 0; i < w - 1; i++ )
		printw( "  %s %d", new_words[i].letters, new_words[i].score );
	printw( "  %s %d; Poentaro: %3d", new_words[w - 1].letters,
		new_words[w - 1].score, score );
	refresh(); */
}
\Rogue\Monster\
else
  echo "will not over write ./cmove.c"
fi
if `test ! -s ./globals.h`
then
echo "writing ./globals.h"
cat > ./globals.h << '\Rogue\Monster\'
/*
 *
 * globals.h -- external variables
 *
 */

extern char board[16][16];

extern char words[900000];
extern long wptr[90000];
extern long wlen[90000];
extern long dict_size;
extern int dict_changed;

extern char plr_tiles[4][7];
extern int plr_scores[4];
extern int plr_skills[4];
extern int mean_pcts[SKILL_LEVELS];
extern int tiles_left[29];
extern int players;

extern char your[4][7];
extern char you[4][5];
extern int human_player;

extern int b1x, b1y, b2x, b2y;

extern compmove *chead;

extern int game_done;
extern int abort;

extern struct another_word new_words[8];

extern struct let_distrib letters[29];

extern int normal_dist[40];
extern int normal_sum;
\Rogue\Monster\
else
  echo "will not over write ./globals.h"
fi
if `test ! -s ./init.c`
then
echo "writing ./init.c"
cat > ./init.c << '\Rogue\Monster\'
/*
 *
 * init.c -- static declarations
 *
 */

#include "scrab.h"

char board[16][16];

char words[900000];
long wptr[90000];
long wlen[17];
long dict_size;
int dict_changed;

char plr_tiles[4][7];
int plr_scores[4];
int plr_skills[4];
int mean_pcts[SKILL_LEVELS] = { 10, 20, 35, 50, 70 };
int tiles_left[29];
int players;

char your[4][7];
char you[4][5];
int human_player;

int b1x, b1y, b2x, b2y;

compmove *chead;

int game_done;
int abort;

struct another_word new_words[8];

struct let_distrib letters[29] = {
   8, 1,    2, 4,    1, 4,    3, 2,    8, 1,    2, 3,
   2, 3,    1, 8,    8, 1,    3, 2,    4, 2,    4, 1,
   4, 2,    6, 1,    8, 1,    3, 2,    2, 4,    6, 1,
   6, 1,    4, 1,    4, 1,    2, 3,    1, 8,    1, 4,
   1,10,    1, 5,    2, 3,    1,10,    2, 0 };

int normal_dist[40] = { 1000, 995, 980, 956, 923, 882, 835, 783,
	726, 667, 607, 546, 487, 430, 375, 325, 278, 236, 198, 164,
	135, 110, 89, 71, 56, 44, 34, 26, 20, 15, 11, 8, 6, 4, 3, 2,
	2, 1, 1, 0 };
int normal_sum;
\Rogue\Monster\
else
  echo "will not over write ./init.c"
fi
if `test ! -s ./misc.c`
then
echo "writing ./misc.c"
cat > ./misc.c << '\Rogue\Monster\'
/*
 *
 * misc.c -- miscellaneous routines
 *
 */

#include "scrab.h"
#include "globals.h"

char spaces[81] =
"                                        \
										";

read_words() {
	FILE *fp;
	char inp[16], tinp[16];
	int i, tlen, rlen;
	long pt, wr;

	fp = fopen( DICT_FILE, "r" );
	if( fp == NULL ) {
		move( 4, 0 );
		printw( "Eraro: ne povis trovi vortaran dosieron '%s'\n", DICT_FILE );
		exit_window();
		exit( 1 );
	}
	printw( "Legante vortaron...\n" );
	refresh();
	pt = 0;
	wr = 0;
	tlen = 2;
	wlen[tlen] = wr;
	tinp[0] = '\0';
	while( fscanf( fp, "%s", inp ) != EOF ) {
		rlen = strlen( inp );
		if( rlen < 2 || rlen > 15 ) {
			move( 4, 0 );
			printw( "Eraro en vortara dosiero je vorto %s: vortoj longu inter 2 kaj 15\n", inp );
			printw( "literoj.\n" );
			exit_window();
			exit( 1 );
		}
		if( rlen < strlen( tinp ) ||
			( strcmp( tinp, inp ) > 0 && strlen( tinp ) == rlen ) ) {
			move( 4, 0 );
			printw( "Eraro en vortara dosiero je vortoj %s kaj %s.\n",
					  tinp, inp );
			printw( "La vortaro ordigxu de plej mallongaj al plej longaj vortoj, kaj\n" );
			printw( "alfabete (laux ASCII) ene de cxiu samlonga vortaro." );
			exit_window();
			exit( 1 );
		}
		for( i = 0; i < rlen; i++ ) {
			if( inp[i] >= 'a' && inp[i] <= '|' ) inp[i] = inp[i] - 'a' + 'A';
			else if( inp[i] < 'A' || inp[i] > '\\' ) {
				move( 4, 0 );
				printw( "Eraro en vortara dosiero je vorto %s: vortoj enhavu nur alfabetajn\n", inp );
				printw( "literojn (A -> |).\n" );
				exit_window();
				exit( 1 );
			}
		}
		if( rlen > tlen ) {
			tlen = rlen;
			wlen[tlen] = wr;
		}
		strcpy( &words[pt], inp );
		wptr[wr++] = pt;
		pt += rlen + 1;
		strcpy( tinp, inp );
	}
	dict_size = pt;
	wlen[16] = wr;
	fclose( fp );
}

clear_rect( y1, x1, y2, x2 )
  int y1, x1, y2, x2;
{
	int i;

	for( i = y1; i <= y2; i++ ) {
		move( i, x1 );
		printw( "%s", &spaces[79 - ( x2 - x1 )] );
	}
	move( y1, x1 );
}

clear_prompt() {
	clear_rect( 19, 0, 23, 78 );
	move( 19, 0 );
}

clear_turn() {
	clear_rect( 18, 0, 18, 79 );
	move( 18, 0 );
}

press_return() {
	char c;

	move( 23, 0 );
	printw( "Press <RETURN> -> " );
	refresh();
	do {
		c = getch();
		if( c == 'q' || c == 'Q' ) abort = 1;
	} while( c != '\n' );
}

print_board() {
	int i, j;

	for( i = 1; i < 16; i++ ) {
		move( BOARD_UY + i - 1, BOARD_LX );
		for( j = 1; j < 16; j++ ) {
			if( board[i][j] >= 'A' ) standout();
			if( ( i == b1y && j == b1x ) || ( i == b2y && j == b2x ) )
				addch( board[i][j] - 'A' + 'a' );
			else if( board[i][j] == CH_DW ) addch( 'o' );
			else addch( board[i][j] );
			if( board[i][j] >= 'A' ) standend();
		}
	}
	refresh();
}

print_tiles() {
	int i, j;

	clear_rect( TILE_RACKS_Y, TILE_RACKS_X,
				  TILE_RACKS_Y + 7, TILE_RACKS_X + 24 );
	for( i = 0; i < players; i++ ) {
		move( TILE_RACKS_Y + i * 3, TILE_RACKS_X - 4 );
		if( plr_skills[i] != 0 ) printw( "(%d)", plr_skills[i] );
		move( TILE_RACKS_Y + i * 3, TILE_RACKS_X );
		if( i == human_player )
			printw( "Viaj literoj" );
		else
			printw( "%s literoj", you[i] );
		for( j = 0; j < 7; j++ ) {
			addch( ' ' );
			if( plr_tiles[i][j] > 0 ) {
#ifndef PRINT_CPU_TILES
				if( i == human_player || game_done == players )
#endif
					addch( plr_tiles[i][j] );
#ifndef PRINT_CPU_TILES
				else addch( '-' );
#endif
			} else addch( ' ' );
		}
		move( TILE_RACKS_Y + i * 3 + 1, TILE_RACKS_X + 5 );
		printw( "Poentoj   %3d", plr_scores[i] );
	}
	move( TILE_RACKS_Y + 12, TILE_RACKS_X - 4 );
	i = 0;
	if( b1x != 0 ) i++;
	if( b2x != 0 ) i++;
	printw( "Senliteraj ludiloj gxis nun: %d", i );
	if( b1x != 0 ) {
		move( TILE_RACKS_Y + 13, TILE_RACKS_X + 3 );
		printw( "Vico %2d, Kolono %2d (%c)", b1y, b1x, board[b1y][b1x] );
	}
	if( b2x != 0 ) {
		move( TILE_RACKS_Y + 14, TILE_RACKS_X + 3 );
		printw( "Vico %2d, Kolono %2d (%c)", b2y, b2x, board[b2y][b2x] );
	}
	move( TILE_RACKS_Y + human_player * 3, TILE_RACKS_X - 1 );
	refresh();
}

char draw_tile() {
	int i, tleft;
	int tile;

	tleft = 0;
	for( i = 0; i < 29; i++ )
		tleft += tiles_left[i];

	if( tleft == 0 ) return( 0 );
	tile = get_random() % tleft;
	for( i = 0;; i++ ) {
		if( tile - tiles_left[i] >= 0 )
			tile -= tiles_left[i];
		else
			break;
	}
	tiles_left[i]--;
	print_tiles_left( tleft - 1 );
	return( i == 28 ? CH_BL : i + 'A' );
}

print_tiles_left( t )
  int t;
{
	move( TILES_LEFT_Y, TILES_LEFT_X );
	printw( "Literoj restas: %3d", t );
}

char get_key() {
	char c;

	c = getch();
	if( c >= 'a' && c <= '|' ) c = c - 'a' + 'A';
/*	if( c == '\033' )
		if( getch() == '[' ) {
			c = getch();
			if( c == 'A' ) c = 'K';
			else if( c == 'B' ) c = 'J';
			else if( c == 'C' ) c = 'L';
			else if( c == 'D' ) c = 'H';
			else c = '\0';
		} else c = '\0'; */
	return( c );
}

seed_random() {
	struct timeval tp;

	gettimeofday( &tp, 0 );
	srandom( tp.tv_sec % 65536 - 32768 );
}

long get_random() {
	return( (long) random() );
}
\Rogue\Monster\
else
  echo "will not over write ./misc.c"
fi
if `test ! -s ./pmove.c`
then
echo "writing ./pmove.c"
cat > ./pmove.c << '\Rogue\Monster\'
/*
 *
 * pmove.c -- player move routines
 *
 */

#include "scrab.h"
#include "globals.h"


player_move() {
	char c;
	int xpos, ypos, done;

	xpos = BOARD_LX;
	ypos = BOARD_UY;
	for( ;; ) {
		clear_prompt();
		printw( "  Uzu la 'hjkl' klavojn por movi la tapsignon.\n" );
		printw( "  Tajpu <REIRI> je malplena kvadrato por ekmeti literojn surtabule.\n" );
		printw( "  Tajpu <SPACO> por reordigi viajn literojn.\n" );
		printw( "  Tajpu '.' por uzi vian vicon por preni novajn literojn.\n" );
		refresh();
		done = 0;
		do {
			move( ypos, xpos );
			refresh();
			c = get_key();
			switch( c ) {
			  case 'H':
				if( xpos > BOARD_LX ) xpos--;
				break;
			  case 'L':
				if( xpos < BOARD_RX ) xpos++;
				break;
			  case 'J':
				if( ypos < BOARD_LY ) ypos++;
				break;
			  case 'K':
				if( ypos > BOARD_UY ) ypos--;
				break;
			  case '\n':
				if( board[ypos - BOARD_UY + 1][xpos - BOARD_LX + 1] < 'A' )
					done = place_tiles( xpos, ypos );
				break;
			  case ' ':
				done = rearrange_tiles();
				break;
			  case '.':
				done = draw_new_tiles();
				break;
			}
		} while( done == 0 );
		if( done == 1 ) break;
	}
	if( c == '.' ) game_done++;
	else game_done = 0;
}

int place_tiles( xpos, ypos )
  int xpos, ypos;
{
	char c;
	int xinc, yinc;
	int i, j, t1, t2, ct1, ct2, tile;
	struct plrlet newlet[7];
	int placed;
	int err, xt, yt;

	clear_prompt();
	printw( "  Kiadirekte vi volus meti viajn literojn:" );
	printw( " horizontale aux\n  vertikale (h/v)? " );
	refresh();
	c = get_key();
	if( c != 'H' && c != 'V' ) return( -1 );
	if( c == 'H' ) {
		xinc = 1;
		yinc = 0;
	} else {
		xinc = 0;
		yinc = 1;
	}
	show_instructions();
	placed = 0;
	for( ;; ) {
		move( ypos, xpos );
		refresh();
		c = get_key();
		if( c == '-' || c == 127 || c == 8 ) {
			if( placed == 0 ) break;
			--placed;
			do {
				xpos -= xinc;
				ypos -= yinc;
			} while( board[ypos - BOARD_UY + 1][xpos - BOARD_LX + 1] >= 'A' );
			move( ypos, xpos );
			addch( newlet[placed].oldlet );
			plr_tiles[human_player][newlet[placed].tilepos]
			  = newlet[placed].letter;
			print_tiles();
		} else if( c == 27 ) {
			while( placed-- > 0 ) {
				do {
					xpos -= xinc;
					ypos -= yinc;
				} while( board[ypos - BOARD_UY + 1][xpos - BOARD_LX + 1] >= 'A' );
				move( ypos, xpos );
				addch( newlet[placed].oldlet );
				plr_tiles[human_player][newlet[placed].tilepos]
				  = newlet[placed].letter;
			}
			print_tiles();
			break;
		} else if( c == '\n' ) {
			if( placed == 0 ) break;
			clear_prompt();
			err = 0;
			if( board[8][8] == CH_DW ) {
				if( placed < 2 ) {
					printw( "  Je la unua movo, vi devas meti almenaux du ludilojn!\n" );
					err = 1;
				} else {
					for( i = 0; i < placed; i++ )
						if( newlet[i].x != 8 || newlet[i].y != 8 ) err++;
					if( err == placed )
						printw( "  Je la unua movo, vi devas meti ludilon sur la centra kvadrato!\n" ); 
					else err = 0;
				}
			} else {
				for( i = 0; i < placed; i++ ) {
					xt = newlet[i].x;
					yt = newlet[i].y;
					if( board[yt][xt - 1] >= 'A' || board[yt][xt + 1] >= 'A'
					  || board[yt - 1][xt] >= 'A' || board[yt + 1][xt] >= 'A' )
						break;
				}
				if( i == placed ) {
					printw( "  Vi devas almeti je parto de la ekzistanta ludilaro!\n" );
					err = 1;
				}
			}
			if( err == 0 ) {
				clear_prompt();
				for( tile = 0, t1 = -1, t2 = -1, i = 0; i < placed; i++ )
					if( newlet[i].letter == CH_BL ) {
						tile++;
						if( t1 == -1 ) {
							t1 = i;
							ct1 = newlet[i].blankchar;
						} else if( t2 == -1 ) {
							t2 = i;
							ct2 = newlet[i].blankchar;
						}
					}
				for( i = 0, xt = 2; i < tile; i++ ) {
					if( i == 0 ) j = t1;
					else if( i == 1 ) j = t2;
					if( newlet[j].blankchar == CH_BL ) {
						clear_rect( 20, 0, 20, 79 );
						printw( "  Kiu litero vi volas ke la " );
						if( tile == 2 && i == 0 ) printw( "unua " );
						else if( tile == 2 ) printw( "dua " );
						printw( "senlitero estu? " );
						refresh();
						do {
							c = get_key();
						} while( c < 'A' || c > '\\' );
						newlet[j].blankchar = c;
					}
					move( 22, xt );
					if( tile == 2 && i == 0 ) printw( "Unua s" );
					else if( tile == 2 ) printw( "Dua s" );
					else printw( "S" );
					printw( "enlitero estas " );
					if( index( "AEFHILMNORSX", newlet[j].blankchar ) != 0 ) {
						printw( "n" );
						xt++;
					}
					printw( " %c.", newlet[j].blankchar );
					xt += 28;
				}
				clear_rect( 20, 0, 20, 79 );
				printw( "  Tajpu <REIRI> por fini vian vicon.  alikaze, pusxu 'n'. -> " );
				refresh();
				do {
					c = getch();
				} while( c != '\n' && c != 'N' && c != 'n' );
				if( c == '\n' ) break;
				if( t1 != -1 ) newlet[t1].blankchar = ct1;
				if( t2 != -1 ) newlet[t2].blankchar = ct2;
			} else press_return();
			show_instructions();
		} else {
			if( xpos > BOARD_RX || ypos > BOARD_LY ) continue;
			tile = -1;
			for( i = 0; i < 7; i++ ) {
				if( c == plr_tiles[human_player][i] ) tile = i;
				else if( plr_tiles[human_player][i] == CH_BL && tile == -1 )
					tile = i;
			}
			if( tile == -1 ) continue;
			if( plr_tiles[human_player][tile] == CH_BL )
				newlet[placed].blankchar = c;
			newlet[placed].letter = plr_tiles[human_player][tile];
			plr_tiles[human_player][tile] = 0;
			newlet[placed].x = xpos - BOARD_LX + 1;
			newlet[placed].y = ypos - BOARD_UY + 1;
			newlet[placed].oldlet =
			  board[ypos - BOARD_UY + 1][xpos - BOARD_LX + 1];
			if( newlet[placed].oldlet == CH_DW ) newlet[placed].oldlet = 'o';
			newlet[placed].tilepos = tile;
			addch( newlet[placed].letter );
			do {
				xpos += xinc;
				ypos += yinc;
			} while( board[ypos - BOARD_UY + 1][xpos - BOARD_LX + 1] >= 'A'
			  && xpos <= BOARD_RX && ypos <= BOARD_LY );
			print_tiles();
			placed++;
		}
	}
	if( placed <= 0 ) return( -1 );
	err = find_new_words( &newlet[0], placed, xinc, yinc );
	display_words( human_player, &newlet[0], err, placed );
	return( 1 );
}

show_instructions() {
	clear_prompt();
	printw( "  Tajpu la literon por meti en cxiun kvadraton, kaj '%c' por senlitera ludilo.\n", CH_BL );
	printw( "  Se vi tajpas literon, kiun vi ne havas, kaj vi havas senliteron, gxi\n" );
	printw( "  metigxos por vin auxtomate.\n" );
	printw( "  Tajpu '-' por retroiri, <ESK> por nuligi, kaj <REIRI> kiam vi finos.\n" );
	refresh();
}

int rearrange_tiles() {
	char c;
	int i, j;

	clear_prompt();
	printw( "  Cxiu litero, kiun vi tajpas, movigxos al la fino de via literujo.\n" );
	printw( "  Tajpu '%c' por senlitero, kaj <REIRI> kiam vi finos.\n",
		  CH_BL );
	refresh();
	print_tiles();
	do {
		c = get_key();
		for( i = 0; i < 7; i++ ) {
			if( c == plr_tiles[human_player][i] ) {
				for( j = i; j < 6; j++ )
					plr_tiles[human_player][j] = plr_tiles[human_player][j + 1];
				plr_tiles[human_player][6] = c;
				print_tiles();
				break;
			}
		}
	} while( c != '\n' );
	return( -1 );
}

disp_instr() {
	clear_rect( 19, 0, 20, 79 );
	printw( "  Tajpu la literojn, kiujn vi volas malpreni, uzu '%c' por senlitera ludilo.\n", CH_BL );
	printw( "  Tajpu '-' por retroiri, <ESK> por nuligi, kaj <REIRI> kiam vi finos.\n" );
	refresh();
}

int draw_new_tiles() {
	char c, tile[7];
	int i, j, plr;
	int used[7];

	clear_prompt();
	disp_instr();
	plr = human_player;
	j = 0;
	for( i = 0; i < 7; i++ ) {
		used[i] = 0;
		tile[i] = plr_tiles[plr][i];
	}
	for( ;; ) {
		clear_rect( 22, 0, 22, 79 );
		printw( "  Literoj por malpreni:" );
		for( i = 0; i < 7; i++ )
			if( used[i] != 0 ) printw( " %c", tile[i] );
		print_tiles();
		c = get_key();
		if( c == '\n' ) {
			if( j != 0 ) {
				clear_rect( 19, 0, 20, 79 );
				printw( "  Tajpu <REIRI> por firmigi vian elekton.  Alikaze, tajpu 'n'. -> " );
			} else {
				clear_rect( 19, 0, 20, 79 );
				printw( "  Tajpu <REIRI> por pasi la vicon.  Alikaze, tajpu 'n'. -> " );
			}
			refresh();
			do {
				c = getch();
			} while( c != '\n' && c != 'N' && c != 'n' );
			if( c == '\n' ) break;
			disp_instr();
		} else if( c == '-' || c == 127 || c == 8 ) {
			if( j > 0 ) {
				for( i = 0; i < 7; i++ )
					if( used[i] == j ) {
						used[i] = 0;
						plr_tiles[plr][i] = tile[i];
						j--;
						break;
					}
			} else {
				j = -1;
				break;
			}
		} else if( c == 27 ) {
			for( i = 0; i < 7; i++ )
				if( used[i] != 0 ) plr_tiles[plr][i] = tile[i];
			print_tiles();
			j = -1;
			break;
		} else {
			for( i = 0; i < 7; i++ ) {
				if( c == plr_tiles[plr][i] ) {
					j++;
					used[i] = j;
					plr_tiles[plr][i] = 0;
					break;
				}
			}
		}
	}
	if( j == -1 ) return( -1 );
	for( i = 0; i < 7; i++ )
		if( used[i] != 0 ) {
			c = tile[i] - 'A';
			if( tile[i] == CH_BL ) c = 28;
			tiles_left[c]++;
		}
	for( i = 0; i < 7; i++ )
		if( used[i] != 0 ) plr_tiles[plr][i] = draw_tile();
	print_tiles();
	return( 1 );
}
\Rogue\Monster\
else
  echo "will not over write ./pmove.c"
fi
if `test ! -s ./score.c`
then
echo "writing ./score.c"
cat > ./score.c << '\Rogue\Monster\'
/*
 *
 * score.c -- find score for a turn
 *
 */

#include "scrab.h"
#include "globals.h"


int find_new_words( newlet, placed, xinc, yinc )
  struct plrlet (*newlet)[];
  int placed, xinc, yinc;
{
	struct plrlet *currlet;
	int i, w, j;
	int dx, dy;
	int x, y;
	int score, mult, tsc, cptr, blloc;
	char c, ch;

	w = 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;
		}
		if( ( y - dy > 0 && x - dx > 0 && board[y - dy][x - dx] >= 'A' )
		  || ( y + dy < 16 && x + dx < 16 && board[y + dy][x + dx] >= 'A' )
		  || i == placed ) {
			while( board[y - dy][x - dx] >= 'A' && x - dx > 0 && y - dy > 0 ) {
				x -= dx;
				y -= dy;
			}
			new_words[w].startx = x;
			new_words[w].starty = y;
			new_words[w].dir = dy;
			score = 0;
			mult = 1;
			cptr = 0;
			blloc = -1;
			for( ;; ) {
				c = board[y][x];
				if( c >= 'A' ) {
					if( ( x != b1x || y != b1y ) && ( x != b2x || y != b2y ) )
						score += letters[c - 'A'].points;
					new_words[w].letters[cptr++] = c;
				} else {
					for( j = 0; j < placed; j++ )
						if( x == ((*newlet)[j]).x && y == ((*newlet)[j]).y )
							break;
					if( j == placed ) break;
					if( blloc == -1 ) blloc = cptr;
					else blloc = -2;
					ch = ((*newlet)[j]).letter;
					if( ch == CH_BL ) {
						tsc = 0;
						new_words[w].letters[cptr++] = ((*newlet)[j]).blankchar;
					} else {
						tsc = letters[ch - 'A'].points;
						new_words[w].letters[cptr++] = ch;
					}
					if( c == CH_DL ) tsc *= 2;
					else if( c == CH_TL ) tsc *= 3;
					else if( c == CH_DW ) mult *= 2;
					else if( c == CH_TW ) mult *= 3;
					score += tsc;
				}
				x += dx;
				y += dy;
				if( x > 15 || y > 15 ) break;
			}
			score *= mult;
			if( placed == 7 && i == placed ) score += 50;
			new_words[w].length = cptr;
			new_words[w].letters[cptr] = '\0';
			new_words[w].blankloc = blloc;
			new_words[w].score = score;
			if( i != placed || cptr != 1 ) w++;
		}
	}
	return( w );
}

long bin_search( word )
  char *word;
{
	long f, l, m;
	int found;

	f = wlen[strlen( word )];
	l = wlen[strlen( word ) + 1] - 1;
	found = 0;
	do {
		m = ( f + l ) / 2;
		if( strcmp( word, &(words[wptr[m]]) ) > 0 )
			f = m + 1;
		else if( strcmp( word, &(words[wptr[m]]) ) < 0 )
			l = m - 1;
		else {
			found = 1;
			f = m;
			l = m;
		}
	} while( f < l );
	if( strcmp( word, &(words[wptr[f]]) ) == 0 
		|| strcmp( word, &(words[wptr[l]]) ) == 0 ) found = 1;
	return( found );
}

display_words( plr, newlet, nwords, placed )
  int plr, nwords, placed;
  struct plrlet (*newlet)[];
{
	int i, j, xloc, score;
	char c, tile, *word;
	int x, y;
	int illword, ind[8];
	int shift;

	clear_turn();
	clear_prompt();
	move( 18, 0 );
	printw( "  %s faris tiujn vortojn:\n", you[plr] );
	refresh();
	score = 0;
	illword = 0;
	printw( "    " );
	xloc = 4;
	for( i = 0; i < nwords; i++ ) {
		word = &(new_words[i].letters[0]);
		if( strlen( word ) + xloc + 2 > 79 ) {
			printw( "\n    " );
			xloc = 4;
		}
		printw( "%s  ", word );
		score += new_words[i].score;
		if( bin_search( word ) == 0 ) {
			ind[illword++] = i;
		}
	}
	move( 21, 0 );
	if( illword != 0 ) {
		if( plr != human_player ) {
			printw( "*** Morta eraro en display_words()\n" );
			exit_window();
			exit( 1 );
		}
		for( i = 0; i < illword; i++ ) {
			clear_rect( 21, 0, 22, 79 );
			printw( "  %s ne enestas la komputilan vortaron.\n",
			  &(new_words[i].letters[0]) );
			printw( "  Cxu gxi ja estas vorto (j/n)? " );
			refresh();
			do {
				c = get_key();
			} while( c != 'J' && c != 'N' );
			if( c == 'N' ) break;
			clear_rect( 21, 0, 22, 79 );
			printw( "  Enmetante %s en la vortaron...",
			  &(new_words[i].letters[0]) );
			refresh();
			add_dict( &(new_words[i].letters[0]) );
			dict_changed = 1;
		}
		clear_rect( 21, 0, 22, 79 );
		if( i == illword ) {
			illword = 0;
		} else {
			printw( "  Pro meti malgxustan vorton, vi ne gajnas poentojn cxi-vice.\n" );
			printw( "  Vi forprenu viajn literojn de la tabulo.\n" );
			for( j = 0; j < placed; j++ )
				plr_tiles[plr][((*newlet)[j]).tilepos] = ((*newlet)[j]).letter;
		}
	}
	if( illword == 0 ) {
		if( placed == 7 )
			printw( "  %s uzis cxiu sep literojn!", you[plr] );
		printw( "  %s poentoj cxi-vice estas %3d.\n", your[plr], score );
		plr_scores[plr] += score;
		for( i = 0; i < placed; i++ ) {
			x = ((*newlet)[i]).x;
			y = ((*newlet)[i]).y;
			tile = ((*newlet)[i]).letter;
			if( tile == CH_BL ) {
				tile = ((*newlet)[i]).blankchar;
				if( b1x == 0 ) {
					b1x = x;
					b1y = y;
				} else {
					b2x = x;
					b2y = y;
				}
			}
			board[y][x] = tile;
		}
		for( i = 0, shift = 0; i < 7; i++ ) {
			if( plr_tiles[plr][i] == 0 ) shift++;
			else if( shift > 0 ) {
				plr_tiles[plr][i - shift] = plr_tiles[plr][i];
				plr_tiles[plr][i] = 0;
			}
		}
		for( i = 7 - shift; i < 7; i++ ) {
			tile = draw_tile();
			if( tile == 0 ) break;
			plr_tiles[plr][i] = tile;
		}
		move( 22, 0 );
		if( tile == 0 && i == 7 - shift) {
			if( plr != human_player )
				printw( "  Ne plu estas literoj por %s preni.\n", you[plr] );
			else
				printw( "  Ne plu estas literoj por vi preni.\n" );
		} else {
			if( tile == 0 ) {
				printw( "  %s povas preni nur ", you[plr] );
				shift = i - ( 7 - shift );
			} else {
				printw( "  %s prenas ", you[plr]);
			}
			printw( "%d litero%s.\n", shift, ( shift == 1 ? "n" : "jn" ) );
		}
	}
	print_board();
	print_tiles();
	press_return();
}

add_dict( word )
  char *word;
{
	int i, l;
	long p1, p2;

	l = strlen( word );
	for( p1 = wlen[l];
		  p1 < wlen[l + 1] && strcmp( word, &(words[wptr[p1]]) ) > 0;
		  p1++ );
	for( p2 = dict_size - 1; p2 >= wptr[p1]; p2-- ) words[p2 + l + 1] = words[p2];
	for( p2 = wlen[16]; p2 > p1; p2-- ) wptr[p2] = wptr[p2 - 1] + l + 1;
	for( i = l + 1; i < 17; i++ ) wlen[i]++;
	strcpy( &(words[wptr[p1]]), word );
	dict_size += l + 1;
/*	printw( "\n  " );
	for( p2 = p1 - 2; p2 < p1 + 3; p2++ )
		printw( "%s  ", &(words[wptr[p2]]) );
	printw( "%s  %s", &(words[wptr[wlen[8]]]), &(words[wptr[wlen[16] - 1]]) );
	press_return(); */
}
\Rogue\Monster\
else
  echo "will not over write ./score.c"
fi
if `test ! -s ./scrab.h`
then
echo "writing ./scrab.h"
cat > ./scrab.h << '\Rogue\Monster\'
/*
 *
 * scrab.h -- constants and structures
 *
 */

#include <curses.h>
#include <string.h>
#include <sys/time.h>

#define SKILL_LEVELS	5
#define SKILL_EXPERT	( SKILL_LEVELS + 1 )

#define CH_EM			'.'
#define CH_DL			'+'
#define CH_TL			'#'
#define CH_DW			'0'
#define CH_TW			'@'
#define CH_BL			'*'
#define CH_IT			'_'

#define BOARD_UY		2
#define BOARD_LY		16
#define BOARD_LX		34
#define BOARD_RX		48
#define INFO_Y			2
#define INFO_X			0
#define TILE_RACKS_Y	2
#define TILE_RACKS_X	54
#define TILES_LEFT_Y	0
#define TILES_LEFT_X	57
/* #define PRINT_CPU_TILES */

/* #define DICT_FILE		"/home/contrib/lib/scrabbledict" */
#define DICT_FILE		"skrablovortaro"

struct another_word {
	int startx;
	int starty;
	int dir;
	int length;
	int blankloc;
	int score;
	char letters[16];
};

struct plrlet {
	int x;
	int y;
	char letter;
	char blankchar;
	char oldlet;
	int tilepos;
};

typedef struct cm {
	struct cm *next;
	struct plrlet newlet[7];
	int placed;
	int dir;
	int score;
} compmove;

#define CM_SIZE		( sizeof( compmove ) )

typedef struct sc {
	struct sc *next;
	int score;
	int num;
} scoreent;

#define SC_SIZE		( sizeof( scoreent ) )

struct let_distrib {
	int tiles;
	int points;
};
\Rogue\Monster\
else
  echo "will not over write ./scrab.h"
fi
if `test ! -s ./skrablo.6`
then
echo "writing ./skrablo.6"
cat > ./skrablo.6 << '\Rogue\Monster\'
.\" @(#)scrabble.6 1.02 92/09/16 JAC
.TH SCRABBLE 6 "16 September 1992"
.SH NAME
scrabble \- play the Scrabble(TM) board game
.SH SYNOPSIS
.B scrabble
.SH DESCRIPTION
.LP
.B scrabble
is a computer version of the Selchow & Righter board game, Scrabble.
Only one human player plays; the user may select the number of
computer opponents, from one to three.
.SH BASIC SCRABBLE RULES
.LP
The object of the game is to form English words in a
crossword\-like grid.  Words are formed using
.I tiles,
each of which has a letter on it.
The player with the highest score at the
end of the game is the winner.
.LP
Each letter has a
particular score associated with it.  For example, the letter
.B E
is worth one point, while
.B Q
is worth ten points.  There are a fixed number of tiles with
each letter.  For example, there are twelve
.B E
tiles, and only one
.B Q
tile.  There are also two blank tiles, which
may be used as any letter. Once a blank tile is placed on the
board as a certain letter, that letter may not change.
.LP
Each player starts with seven tiles,
which are placed in their
.I rack.
These tiles are drawn from a shuffled pool of
one hundred tiles.
.LP
The first player to
move must play a word that covers the center square;
as well, this player must place two or more of their
tiles.  After the first move,
players take turns placing one or more of their tiles
on the board, so as to form new words in the
standard crossword\-like manner: new words must read
across or down, not diagonally.
.LP
New words may be formed one of three ways:
.TP
1.
By adding a tiles to an already existing word, e.g.,
adding
.B ABLE
to
.B READ.
.TP
2.
By adding tiles that intersect another word, e.g.,
spelling
.B WARY
by placing 
.B W,
.B R,
and
.B Y
around the
.B A
of
.B REAL.
.TP
3.
By spelling a word in one direction and forming
new words in the other direction, e.g., by adding
.B FOX
next to
.B PIG
so that the
.B I
of
.B PIG
is used to spell
.B IF
with the
.B F
from
.B FOX
and, similarly, the
.B G
is used to spell
.B GO.
.LP
If all the new words formed are valid English words,
that player's score is increased by the value of the
tiles in
.I all
new words formed.  The player then draws new tiles from
the pool until the player again has seven tiles in his/her
rack, or until there are no more tiles left to draw.
.LP
If
.I any
of the new
words formed are not valid English words, the player
scores zero for that turn, and must remove the tiles just
placed from the board and replace them in his/her rack.
.LP
Valid English words in Scrabble constitute any word so long
as it is not an abbreviation (LTD, CORP), is not normally
capitalized (MATTHEW, LONDON), does not contain punctuation
(COLD\-HEARTED, CAN'T),
and is not a prefix or suffix (PRE, ATION).
Foreign words that are used frequently in English
are allowed (words such as CIAO and QUO).  Slang
and colloquial words are also allowed.
.LP
Once a tile has been placed on the board, it may not
be moved.
.LP
Certain board squares are special, in that they increase
the value of a letter or a word.  Double and triple letter
squares increase the value of a tile by double and triple,
respectively.  Double and triple word scores increase the
value of a word by double and triple, respectively.  Double
and triple letter squares are counted
.I before
double and triple word squares.  These special squares only
count on the turn in which they are covered; the squares
are no longer special in subsequent turns.
.LP
A player who uses all seven tiles on one turn gets a premium
of fifty points on top of the regular score for that turn.
.LP
Instead of placing tiles, a player may forfeit his/her
turn and draw between zero and seven new tiles.  The player
selects which of his/her tiles to replace, puts them back
in the pool, and then draws the same number of tiles from
the pool again.  A player doing this scores zero for that
turn.
.LP
The game ends when there are no tiles left to draw and
one player has no tiles left to place,
.I or
when no player can make a valid move.  Each player's score
is adjusted by subtracting from it
the value of each tile remaining
in his/her own rack.  As well, if one player uses all his/her
tiles, his/her score is increased by the sum of all unplayed
letters in the other players' racks.  The player with the
highest score wins the game.  In the event of a tie, the
player with the highest score prior to the score adjustment
is the winner.
.SH SCRABBLE SCREEN LAYOUT
.LP
The upper\-left side of the screen lists the special board
symbols used in
.B scrabble.
.TP
\+
Double letter score.
.TP
\#
Triple letter score.
.TP
o
Double word score.
.TP
\@
Triple word score.
.TP
*
Blank tile.  This is the character displayed in a player's
rack when he/she owns a blank tile.  Once the tile is
placed on the board, it is shown in lower\-case as the letter
it represents.
.LP
The lower\-left side of the screen lists the value of each
tile, as well as the total number of tiles of each type.
For example, "A\-1, 9" means that there are a total of nine
tiles with
.B A
on them, and that each tile is worth one point.
.LP
The center of the screen shows the
.B scrabble
board.
.LP
The upper\-right of the screen displays the number of
tiles left in the pool to draw.  As well, it displays
the number of passed turns, if any.
.LP
The central\-right of the screen shows all players'
tile racks.  The computer players' tiles are represented
by dashes.  As well, the computer players' skill levels
are displayed in brackets next to their designations
(e.g., CPU1).  Finally, each player's score is shown here.
.LP
The lower\-right of the screen indicates the location of
any blank tiles that have been placed on the board, as
well as the letter they represent.
.LP
The bottom of the screen is the message and input area.
.SH PLAYING SCRABBLE
.LP
The user must select the number of computer players
to play against.  Then, each player draws a tile.
The player with the lowest tile alphabetically starts
the game.  A blank tile is considered lower alphabetically
than all other letters.
.LP
The user then selects the skill level of each
computer player.  Skill levels go from 1 (easy to beat)
to 5 (hard to beat, but still possible), and skill level
6 ("expert mode") makes the computer player play its
highest\-scoring move every turn.
.LP
When it is the computer's turn to play, it searches the
board for a move.  The cursor shows the square that the
computer is thinking about playing on.  After the search,
the computer chooses its move based on its skill level.
If it could not find a move, it will say so.
.LP
When it is your turn to play, the cursor
starts at the upper\-left corner of the board.  The following
keys may then be used.
.TP
h
Moves the cursor left.  If the cursor is on the left edge
of the board, this key has no effect.
.TP
j
Moves the cursor down.  If the cursor is on the bottom edge
of the board, this key has no effect.
.TP
k
Moves the cursor up.  If the cursor is on the top edge
of the board, this key has no effect.
.TP
l
Moves the cursor right.  If the cursor is on the right edge
of the board, this key has no effect.
.TP
RETURN
Starts placing tiles on the board.  If the cursor is over
a square that is already occupied by a tile, this key has
no effect.  More on this key below.
.TP
SPACE
Rearrange your tiles.  Sometimes it's easier to see what words
you can form if you group your tiles in your rack a certain
way.  This key allows you to regroup your tiles.  Typing the
letter of a tile in your rack moves it to the end of your rack.
Use the asterisk for a blank tile.  Pressing RETURN exits this
mode.
.TP
\\.
Draw new tiles.  If you really hate the tiles in
your rack, or even if you
don't, you can replace none, some, or all of your tiles and
draw (potentially) new ones.
Type this key, followed by the
letters in your rack that you wish to replace.  Pressing dash
or DEL will put your most recent selection back in your rack.
Pressing ESC will cancel this operation, and pressing RETURN
will ask you to confirm your selection.
.TP
.I Note
.I If you cannot move
and wish to pass your turn,
then you must press the "Draw new tiles" key,
and then draw zero new tiles.
.LP
Once you press RETURN to start placing tiles, you can press
either 
.I h
or
.I v
to place your tiles horizontally or vertically,
respectively.
.LP
Then, you simply begin typing.  Each time you type a tile
that is in your rack, the tile is placed on the board at the
cursor's position.  The cursor then moves to the next blank
square in the appropriate direction.  If you type a letter
that is not in your rack, it is ignored
.I except
if you have a blank tile.  In this case, the blank tile is
placed on the board for you.  If you type an asterisk and you
have a blank tile, it is placed on the board as usual.
.LP
While typing, you may press dash or DEL to remove the last
tile placed from the board and put it back in your rack.  Or, you
may press ESC to cancel this particular placement all together.
If you're satisfied with what you've placed, you may press
RETURN.  If you placed any blank tiles by typing asterisk, you
will be asked for the letters that the blank tiles represent.
Press RETURN to confirm your move, or
.I n
to alter it.
.LP
Your words are then checked against the dictionary.  If all
the words are in the dictionary, your score is increased and
new tiles are drawn for you.  If any of your words are not
in the dictionary, you are asked if said words are valid
.B scrabble
words.  You are expected to answer honestly!  If any word is
invalid, your tiles are removed from the board and replaced in
your rack.  If the word is valid, it is added to the dictionary.
So beware!  The computer players can then use the word too.
.LP
.B scrabble
does all the drawing of new tiles automatically.  It also
does all the scoring, including the score adjustments at the
end of the game.  It can even handle multiple\-way ties at the
end of the game, should this unlikely event occur.
.LP
At the end of the game, if any words have been added to
the dictionary,
.B scrabble
will ask you if you want to save the dictionary.  If you
say yes, the old dictionary file is overwritten with the
new one.  Otherwise, the original dictionary remains intact.
(The option of rewriting the dictionary is useful if you
were simply cheating and spelling really long garbage words
for the satisfaction of totally annihilating the computer.)
.LP
One minor point: often throughout the game, you will be
prompted to "Press <RETURN>".  If you press the
.I q
key followed by RETURN, you will exit scrabble.  This can
be safer than pressing an interrupt key to exit, which may
mess up your window.
.SH COMPUTER PLAYERS' ALGORITHM
.LP
For the curious, here is a brief description of how the
computer players decide on their moves.
.LP
If the board is empty, the computer simply searches the
dictionary for any word whose length is between two and
seven that can be formed with its tiles.  It stores all
possibilities, and computes the score for all possible
placements of each word.
.LP
For the remainder of this section, a
.I legal move
is one which adjoins to the existing puzzle.
.LP
The computer players do an exhaustive search of the board,
finding all positions in which a legal move can be made.
.LP
At each square, the computer determines how many of its tiles
it can place and still be a legal move.  This can be anywhere
between one and seven tiles, inclusive.  For example, the
computer might be able to place any number of tiles between
three and seven, and still be making a legal move.  The computer
then performs an exhaustive dictionary search for each of
these numbers of tiles.  In the example, the computer would
perform five exhaustive searches.
.LP
The searching algorithm prunes the search tree in three ways.
.TP
1.
For a given number of tiles to be placed (say three),
all words formed will be of the same length (say four).  Thus,
the computer only need search all four\-letter words.
.TP
2.
Often one or more of the letters in the new word to be formed
will be fixed, because the computer might be adding to
a word that has already been placed on the board.  For example,
if the word
.B WENT
is on the board horizontally, the computer might be trying
to add a word vertically to the
.B N.
Thus, any
word that does not have the fixed letter(s) in the proper
place(s) can be eliminated right away.
.TP
3.
The computer might be forming other words in the opposite
direction to which it is placing tiles.
For example, suppose the computer
is trying to form a word horizontally with three tiles.
Furthermore, suppose that its first tile has to adjoin
to a vertical word such as
.B PIT.
Then, the computer checks
if it can form a valid word of the form
.B PIT_
(where the
underscore represents an unknown tile) before the
exhaustive search.  In this case, the computer would
have to own an
.B A,
.B H,
.B S,
or
.B Y
to form
.B PITA,
.B PITH,
.B PITS,
or
.B PITY.
Otherwise, the search would be abandoned.
.LP
The computer stores all possible moves in a linked list sorted
from highest\-scoring move to lowest\-scoring move.  Once the
search is complete, the computer then selects a move.  In expert
mode (level 6), the computer merely chooses the move at the
head of the list.  On the other levels, the computer picks
a move using a normal p.d.f.  The mean of the distribution is
placed close to the highest\-scoring move on level 5, and
sort of close to the lowest\-scoring move on level 1.  The standard
deviation of the distribution is one\-fifth of the number
of distinct scores that each move might give.  For example,
the computer might be able to make moves that would give it
4, 6, 7, 9, or 10 points.  In this case, the standard deviation
would be one.
.SH FILES
.TP
scrabble
This is the executable file.
.TP
scrabbledict
This is the dictionary file.
.SH DICTIONARY FILES
.LP
If desired, the user may supply his/her own version of
the dictionary file.
The dictionary file must have the following properties:
.TP
1.
It must be sorted from shortest words (two letters)
to longest words (fifteen letters).
.TP
2.
Within each word length, the words must be sorted
alphabetically from A to Z.
.TP
3.
Words
.I must
be all capitals.
.B scrabble
ignores any word that contains
punctuation, as well as any word longer than
fifteen characters.
.SH AUTHOR
.LP
.B scrabble
was written by James A. Cherry, at Carleton University,
Ottawa, Ontario, Canada.  Questions, comments, etc., may
be addressed to jac@doe.carleton.ca.
.SH BUGS
.LP
The computer search algorithm is highly inelegant.  It is
simply brute\-force.
.LP
.B scrabble
is a complete pig for memory; it stores the entire dictionary
in memory for fast searching.  Also, every possible computer
move on a given turn is stored; no moves are erased until the
computer has decided on its move.  Since it is sometimes
possible to make 3,000 or more moves, the move list occupies
a large chunk of memory.
.LP
If you play a garbage word, and tell the computer that it really
is a word, it will believe you.
.LP
The whole concept of challenging another
player's word is non\-existent in
.B scrabble.
This is unfortunate, as it is an important part of the game.
The computer players only spell words that are in the dictionary.
They never try to "pull a fast one" on you.  Likewise, if the
computer plays a word that you're
.I sure
is not a valid
.B scrabble
word, it will not allow you to challenge it.  After all, the
word was in the dictionary, so it
.I must
be valid.  (Yeah, right.)  Perhaps removing the offending
word from the dictionary at the end of the game is the solution.
.LP
In expert mode, the computers are practically impossible to beat.
.LP
There is no way to get the computer to suggest a move for you.
.LP
On any level but expert, the computer players tend to keep their
Q and Z tiles right until the end; this means they lose a lot of
points after the game is over.  Even a bad human player would try
to get rid of these high\-scoring tiles quickly, but the computer's
algorithm does not allow it to.
.LP
Interrupt characters are not caught, and they might mess up your
window to the point that it is no longer usable.
.LP
If something bad happens (like an interrupt character) while
.B scrabble
is re\-writing the dictionary, the dictionary file might be lost.
\Rogue\Monster\
else
  echo "will not over write ./skrablo.6"
fi
if `test ! -s ./skrablovortaro`
then
echo "writing ./skrablovortaro"
cat > ./skrablovortaro << '\Rogue\Monster\'
CIA
EMI
ENE
E\O
IRO
KIU
LIA
LIN
MIN
ONI
OVA
PER
POR
PRI
PRO
SED
SIA
SIN
SUB
SUR
VIA
XIA
BENI
BLUA
CIAN
DAMO
FOJE
FOJO
FUXA
HORO
JARE
JARO
KAPO
KATO
KIAL
KIAM
KIEL
KIES
KIOM
KION
KISA
KIUN
KUZE
KUZO
LEGI
LIAJ
LIAN
LUDO
LUMA
MARO
MEVO
MIRE
MOVA
MOVI
NEPO
NEVO
NIAN
NOMO
NOVA
ONIA
PA[O
QIAL
QIAM
QIES
QIOM
QIUJ
QIUN
RADE
RADO
RANO
REGI
REMI
RETO
REVO
RE[O
RU[A
SAGO
SA[E
SE[O
TAGO
TEME
TIAL
TIAM
TIEL
TIOM
TION
TIUJ
TIUN
TURA
TUTO
TUXI
VAGA
VAGI
VIRO
VOLI
XIAJ
XIAN
ZONO
[ENI
\ORA
\ORO
BARIS
ELIGU
ETI[E
GARDI
HUNDA
HUNDO
KAPTI
KAPTO
KNABO
LANDE
LANDO
LEONO
LERNI
MIELO
MONDA
MONDE
MONDO
MOVAS
NOVAN
PATRO
PENAS
PIEDA
PIEDE
PIEDO
TEMPE
TUXAS
TUXIS
TUXOS
VAGAS
VULPA
VULPO
XTATA
XTATE
XTATO
BENITA
HOMETO
\Rogue\Monster\
else
  echo "will not over write ./skrablovortaro"
fi
if `test ! -s ./smain.c`
then
echo "writing ./smain.c"
cat > ./smain.c << '\Rogue\Monster\'
/*
 *
 * smain.c -- main program
 *
 */

#include "scrab.h"
#include "globals.h"


set_up_window() {
	int xsize, ysize;
	WINDOW *screen;

	screen = initscr();
	refresh();
	if( screen->_maxx < 80 || screen->_maxy < 24 ) {
		endwin();
		fprintf( stderr, "Bezonas ekranon je almenaux 24x80\n" );
		exit( 1 );
	}
	cbreak();
	noecho();
}

exit_window() {
	char c;

	move( 23, 0 );
	printw( "Pusxu klavon por fini... " );
	refresh();
	c = getch();
	endwin();
}

init_board() {
	int i, j;

	for( i = 1; i < 16; i++ )
		for( j = 1; j < 16; j++ )
			board[i][j] = CH_EM;
	board[1][1] = CH_TW;
	board[8][1] = CH_TW;
	board[8][8] = CH_DW;
	for( i = 2; i < 6; i++ ) {
		board[i][i] = CH_DW;
	}
	board[2][6] = CH_TL;
	board[6][2] = CH_TL;
	board[6][6] = CH_TL;
	board[1][4] = CH_DL;
	board[4][1] = CH_DL;
	board[3][7] = CH_DL;
	board[7][3] = CH_DL;
	board[8][4] = CH_DL;
	board[7][7] = CH_DL;
	for( i = 1; i < 9; i++ )
		for( j = 1; j < 8; j++ ) {
			board[16-j][i] = board[i][j];
			board[16-i][16-j] = board[i][j];
			board[j][16-i] = board[i][j];
		}
}

print_info() {
	move( INFO_Y    , INFO_X );
	printw( "Specialaj simboloj:" );
	move( INFO_Y + 1, INFO_X + 2 );
	printw( "%c: Duobla litervaloro", CH_DL );
	move( INFO_Y + 2, INFO_X + 2 );
	printw( "%c: Triobla litervaloro", CH_TL );
	move( INFO_Y + 3, INFO_X + 2 );
	printw( "%c: Duobla vortvaloro", 'o' );
	move( INFO_Y + 4, INFO_X + 2 );
	printw( "%c: Triobla vortvaloro", CH_TW );
	move( INFO_Y + 5, INFO_X + 2 );
	printw( "%c: Senlitero", CH_BL );
	move( INFO_Y + 7, INFO_X );
	printw( "Literaj valoroj kaj nombroj:" );
	move( INFO_Y + 8, INFO_X + 2 );
	printw( "A-1, 8  G-3, 2  K-2, 4  S-1, 6" );
	move( INFO_Y + 9, INFO_X + 2 );
	printw( "B-4, 2  [-3, 2  L-1, 4  X-4, 1" );
	move( INFO_Y +10, INFO_X + 2 );
	printw( "C-4, 1  H-8, 1  M-2, 4  T-1, 4" );
	move( INFO_Y +11, INFO_X + 2 );
	printw( "Q-4, 2  \\10, 1  N-1, 6  U-1, 4" );
	move( INFO_Y +12, INFO_X + 2 );
	printw( "D-2, 3  I-1, 8  O-1, 8  W-8, 1" );
	move( INFO_Y +13, INFO_X + 2 );
	printw( "E-1, 8  J-2, 3  P-2, 3  V-3, 2" );
	move( INFO_Y +14, INFO_X + 2 );
	printw( "F-3, 2  Y10, 1  R-1, 6  Z-5, 1" );
	move( INFO_Y +15, INFO_X + 26);
	printw( "%c-0, 2", CH_BL );
	refresh();
}

init_tiles() {
	int i, j;

	for( i = 0; i < 29; i++ )
		tiles_left[i] = letters[i].tiles;
	for( i = 0; i < 4; i++ )
		for( j = 0; j < 7; j++ )
			plr_tiles[i][j] = 0;
	b1x = 0;
	b2x = 0;
	b1y = 0;
	b2y = 0;
	normal_sum = 0;
	for( i = 0; i < 40; i++	) normal_sum += normal_dist[i];
}

get_num_players() {
	char c;
	int i, j;
	char ft[4], cs[7];

	clear_prompt();
	printw( "  Nombro de komputilaj ludantoj (1-3)? " );
	refresh();
	for( ;; ) {
		c = getch();
		if( c >= '1' && c <= '3' ) break;
	}
	players = c - '0' + 1;
	for( ;; ) {
		init_tiles();
		for( i = 0; i < players; i++ ) ft[i] = draw_tile();
		for( i = 1; i < players; i++ )
			if( ft[0] == ft[i] ) break;
		if( i != players ) continue;
		move( 20, 0 );
		printw( "  Cxiu ludanto prenas ludilon.  Vi: %c", ft[0] );
		for( i = 1; i < players; i++ ) {
			printw( "  Aliulo %d: %c", i + 1, ft[i] );
			if( ft[i] == CH_BL ) ft[i] = 'A' - 1;
		}
		j = players;
		for( i = 1; i < players; i++ )
			if( ft[0] < ft[i] ) j--;
		if( j == 1 ) strcpy( cs, "unue" );
		if( j == 2 ) strcpy( cs, "due" );
		if( j == 3 ) strcpy( cs, "trie" );
		if( j == 4 ) strcpy( cs, "kvare" );
		printw( "\n  Vi ludos %s.", cs );
		human_player = j - 1;
		print_tiles_left( 100 );
		press_return();
		clear_prompt();
		refresh();
		break;
	}

	init_tiles();
	j = '1';
	for( i = 0; i < 4; i++ ) {
		if( i == human_player ) {
			strcpy( &(your[i][0]), "Via" );
			strcpy( &(you[i][0]), "Vi" );
		} else {
			strcpy( &(your[i][0]), "CPU a" );
			strcpy( &(you[i][0]), "CPU " );
			your[i][3] = j;
			you[i][3] = j++;
		}
		plr_skills[i] = 0;
	}

	for( i = 0; i < players; i++ ) {
		print_tiles();
		if( i == human_player ) continue;
		clear_prompt();
		printw( "  Elektu ludkapablon 1-%d por %s, 1 estas komencanto, %d estas sperta, kaj\n", SKILL_EXPERT, you[i], SKILL_LEVELS );
		printw( "  %d estas spertega. -> ", SKILL_EXPERT );
		refresh();
		for( ;; ) {
			c = getch();
			if( c >= '1' && c <= '6' ) break;
		}
		plr_skills[i] = c - '0';
	}

	for( i = 0; i < players; i++ ) {
		plr_scores[i] = 0;
		for( j = 0; j < 7; j++ )
			plr_tiles[i][j] = draw_tile();
	}
	print_tiles();
}

end_game() {
	int i, j;
	int adj[4], wbs, wb[4], was, wa[4];
	long p1;
	FILE *fp;
	char c;

	clear_turn();
	printw( "*** LUDO FINITA\n" );
	print_tiles();
	clear_prompt();
	printw( "  Jen la poentaraj sxangxoj: " );
	wbs = -1;
	for( i = 0; i < players; i++ )
		if( plr_scores[i] > wbs ) wbs = plr_scores[i];
	for( i = 0; i < players; i++ ) {
		if( plr_scores[i] == wbs ) wb[i] = 1;
		else wb[i] = 0;
	}
	for( i = 0; i < players; i++ ) {
		adj[i] = 1;
		for( j = 0; j < 7; j++ ) {
			c = plr_tiles[i][j];
			if( c != 0 ) {
				if( adj[i] == 1 ) adj[i] = 0;
				if( c != CH_BL ) adj[i] -= letters[c - 'A'].points;
			}
		}
	}
	for( j = 0; j < players; j++ )
		if( adj[j] == 1 ) break;
	if( j < players ) {
		adj[j] = 0;
		for( i = 0; i < players; i++ )
			if( i != j ) adj[j] -= adj[i];
	}
	for( i = 0; i < players; i++ ) {
		move( 19 + i, 36 );
		if( i == human_player ) addch( ' ' );
		printw( "%s: %d", you[i], adj[i] );
		plr_scores[i] += adj[i];
	}
	was = -1;
	for( i = 0; i < players; i++ )
		if( plr_scores[i] > was ) was = plr_scores[i];
	for( i = 0; i < players; i++ ) {
		if( plr_scores[i] == was ) wa[i] = 1;
		else wa[i] = 0;
	}
	press_return();
	print_tiles();
	clear_prompt();
	move( 20, 0 );
	was = 0;
	for( i = 0; i < players; i++ ) was += wa[i];
	wbs = 0;
	for( i = 0; i < players; i++ ) wbs += wb[i];
	if( was == 1 || wbs == 1 ) {
		if( was == 1 ) {
			for( i = 0; i < players; i++ )
				if( wa[i] == 1 ) break;
		} else {
			for( i = 0; i < players; i++ )
				if( wb[i] == 1 ) break;
		}
		printw( "  Kaj la gajninto estas:  %s!", you[i] );
	} else {
		printw( "  Estas kungajno inter:  " );
		wbs = 1;
		for( i = 0; i < players; i++ )
			if( wa[i] == 1 ) {
				if( wbs < was - 1 ) printw( ", " );
				else {
					if( was > 2 ) printw( ", kaj " );
					else printw( " kaj " );
				}
				printw( "%s", you[i] );
				wbs++;
			}
		printw( "!" );
	}
	refresh();
	if( dict_changed == 1 ) {
		press_return();
		clear_prompt();
		printw( "  La komputila vortaro sxangxigxis dum la ludo.\n" );
		printw( "  Cxu vi volas memori la novajn vortojn (j/n)? " );
		refresh();
		do {
			c = get_key();
		} while( c != 'J' && c != 'N' );
		if( c == 'J' ) {
			printw( "\n\n  Aldiskigante novan vortaron..." );
			refresh();
			fp = fopen( DICT_FILE, "w+" );
			if( fp == NULL ) {
				printw( "eraro aldiskigante vortaron!\n" );
				exit_window();
				exit( 1 );
			}
			for( p1 = 0; p1 < wlen[16]; p1++ )
				fprintf( fp, "%s\n", &(words[wptr[p1]]) );
			fclose( fp );
		}
	}
}

int main() {
	int plr;
	int i;

	set_up_window();
	clear();
	printw( "*** SKRABLO 1.21-Es (Esperanto) ***\n\n" );

	read_words();
	dict_changed = 0;

	clear();
	printw( "*** SKRABLO 1.21-Es (Esperanto) ***\n\n" );

	init_board();
	seed_random();
	print_board();
	print_info();
	get_num_players();

	game_done = 0;
	abort = 0;
	do {
		for( plr = 0; plr < players; plr++ ) {
			clear_turn();
			printw( "*** %s vico por ludi  ", your[plr] );
			if( plr == human_player ) {
				player_move();
			} else {
				computer_move( plr );
			}
			if( abort != 0 ) break;
			if( game_done == 0 ) clear_rect( 1, 50, 1, 79 );
			else {
				move( 1, 64 );
				printw( "Pasoj:  %d", game_done );
			}
			refresh();
			if( game_done == players ) break;
			for( i = 0; i < 7; i++ )
				if( plr_tiles[plr][i] != 0 ) break;
			if( i == 7 ) {
				game_done = players;
				break;
			}
		}
	} while( game_done < players && abort == 0 );

	if( abort == 0 ) end_game();
	exit_window();
}
\Rogue\Monster\
else
  echo "will not over write ./smain.c"
fi
echo "Finished archive 1 of 2"
exit
-- 
Duncan   <duncan@spd.eee.strathclyde.ac.uk> |  .__ _. _ .__._  _ , .___ _
Thomson     (OR <cnbr50@vaxa.strath.ac.uk>) |  |_ |_ |_||_ |_|/_\|\| | / \
SPD, Dept of EEE, University of Strathclyde |  |__._||  |__| \| || | | \_/
204 George Street, Glasgow G1 1XW, UK       | esperanto - lingvo internacia