home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / games / volume14 / scrbble2 / part18 < prev    next >
Encoding:
Internet Message Format  |  1993-01-26  |  42.3 KB

  1. Path: uunet!zephyr.ens.tek.com!master!saab!billr
  2. From: billr@saab.CNA.TEK.COM (Bill Randle)
  3. Newsgroups: comp.sources.games
  4. Subject: v14i110:  scrabble2 - another version of the crossword-puzzle board game, Part18/18
  5. Message-ID: <3628@master.CNA.TEK.COM>
  6. Date: 22 Sep 92 18:57:15 GMT
  7. Sender: news@master.CNA.TEK.COM
  8. Lines: 1535
  9. Approved: billr@saab.CNA.TEK.COM
  10.  
  11. Submitted-by: jac@doe.carleton.ca (James A. Cherry)
  12. Posting-number: Volume 14, Issue 110
  13. Archive-name: scrabble2/Part18
  14. Environment: curses
  15.  
  16.  
  17.  
  18. #! /bin/sh
  19. # This is a shell archive.  Remove anything before this line, then unpack
  20. # it by saving it into a file and typing "sh file".  To overwrite existing
  21. # files, type "sh file -c".  You can also feed this as standard input via
  22. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  23. # will see the following message at the end:
  24. #        "End of archive 18 (of 18)."
  25. # Contents:  pmove.c score.c scrabble.6 smain.c
  26. # Wrapped by billr@saab on Tue Sep 22 11:47:52 1992
  27. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  28. if test -f 'pmove.c' -a "${1}" != "-c" ; then 
  29.   echo shar: Will not clobber existing file \"'pmove.c'\"
  30. else
  31. echo shar: Extracting \"'pmove.c'\" \(8730 characters\)
  32. sed "s/^X//" >'pmove.c' <<'END_OF_FILE'
  33. X/*
  34. X *
  35. X * pmove.c -- player move routines
  36. X *
  37. X */
  38. X
  39. X#include "scrab.h"
  40. X#include "globals.h"
  41. X
  42. X
  43. Xplayer_move() {
  44. X    char c;
  45. X    int xpos, ypos, done;
  46. X
  47. X    xpos = BOARD_LX;
  48. X    ypos = BOARD_UY;
  49. X    for( ;; ) {
  50. X        clear_prompt();
  51. X        printw( "  Use the 'hjkl' keys to move the cursor.\n" );
  52. X        printw( "  Press <RETURN> on an empty square to start placing tiles on the board.\n" );
  53. X        printw( "  Press <SPACE> to rearrange your tiles.\n" );
  54. X        printw( "  Press '.' to use your turn to draw new tiles.\n" );
  55. X        refresh();
  56. X        done = 0;
  57. X        do {
  58. X            move( ypos, xpos );
  59. X            refresh();
  60. X            c = get_key();
  61. X            switch( c ) {
  62. X              case 'H':
  63. X                if( xpos > BOARD_LX ) xpos--;
  64. X                break;
  65. X              case 'L':
  66. X                if( xpos < BOARD_RX ) xpos++;
  67. X                break;
  68. X              case 'J':
  69. X                if( ypos < BOARD_LY ) ypos++;
  70. X                break;
  71. X              case 'K':
  72. X                if( ypos > BOARD_UY ) ypos--;
  73. X                break;
  74. X              case '\n':
  75. X                if( board[ypos - BOARD_UY + 1][xpos - BOARD_LX + 1] < 'A' )
  76. X                    done = place_tiles( xpos, ypos );
  77. X                break;
  78. X              case ' ':
  79. X                done = rearrange_tiles();
  80. X                break;
  81. X              case '.':
  82. X                done = draw_new_tiles();
  83. X                break;
  84. X            }
  85. X        } while( done == 0 );
  86. X        if( done == 1 ) break;
  87. X    }
  88. X    if( c == '.' ) game_done++;
  89. X    else game_done = 0;
  90. X}
  91. X
  92. Xint place_tiles( xpos, ypos )
  93. X  int xpos, ypos;
  94. X{
  95. X    char c;
  96. X    int xinc, yinc;
  97. X    int i, j, t1, t2, ct1, ct2, tile;
  98. X    struct plrlet newlet[7];
  99. X    int placed;
  100. X    int err, xt, yt;
  101. X
  102. X    clear_prompt();
  103. X    printw( "  Which direction would you like to place your tiles:" );
  104. X    printw( " horizontally or\n  vertically (h/v)? " );
  105. X    refresh();
  106. X    c = get_key();
  107. X    if( c != 'H' && c != 'V' ) return( -1 );
  108. X    if( c == 'H' ) {
  109. X        xinc = 1;
  110. X        yinc = 0;
  111. X    } else {
  112. X        xinc = 0;
  113. X        yinc = 1;
  114. X    }
  115. X    show_instructions();
  116. X    placed = 0;
  117. X    for( ;; ) {
  118. X        move( ypos, xpos );
  119. X        refresh();
  120. X        c = get_key();
  121. X        if( c == '-' || c == 127 || c == 8 ) {
  122. X            if( placed == 0 ) break;
  123. X            --placed;
  124. X            do {
  125. X                xpos -= xinc;
  126. X                ypos -= yinc;
  127. X            } while( board[ypos - BOARD_UY + 1][xpos - BOARD_LX + 1] >= 'A' );
  128. X            move( ypos, xpos );
  129. X            addch( newlet[placed].oldlet );
  130. X            plr_tiles[human_player][newlet[placed].tilepos]
  131. X              = newlet[placed].letter;
  132. X            print_tiles();
  133. X        } else if( c == 27 ) {
  134. X            while( placed-- > 0 ) {
  135. X                do {
  136. X                    xpos -= xinc;
  137. X                    ypos -= yinc;
  138. X                } while( board[ypos - BOARD_UY + 1][xpos - BOARD_LX + 1] >= 'A' );
  139. X                move( ypos, xpos );
  140. X                addch( newlet[placed].oldlet );
  141. X                plr_tiles[human_player][newlet[placed].tilepos]
  142. X                  = newlet[placed].letter;
  143. X            }
  144. X            print_tiles();
  145. X            break;
  146. X        } else if( c == '\n' ) {
  147. X            if( placed == 0 ) break;
  148. X            clear_prompt();
  149. X            err = 0;
  150. X            if( board[8][8] == CH_DW ) {
  151. X                if( placed < 2 ) {
  152. X                    printw( "  On the first move, you must place at least two tiles!\n" );
  153. X                    err = 1;
  154. X                } else {
  155. X                    for( i = 0; i < placed; i++ )
  156. X                        if( newlet[i].x != 8 || newlet[i].y != 8 ) err++;
  157. X                    if( err == placed )
  158. X                        printw( "  On the first move, you must place a tile on the centre square!\n" ); 
  159. X                    else err = 0;
  160. X                }
  161. X            } else {
  162. X                for( i = 0; i < placed; i++ ) {
  163. X                    xt = newlet[i].x;
  164. X                    yt = newlet[i].y;
  165. X                    if( board[yt][xt - 1] >= 'A' || board[yt][xt + 1] >= 'A'
  166. X                      || board[yt - 1][xt] >= 'A' || board[yt + 1][xt] >= 'A' )
  167. X                        break;
  168. X                }
  169. X                if( i == placed ) {
  170. X                    printw( "  You must add to part of the existing puzzle!\n" );
  171. X                    err = 1;
  172. X                }
  173. X            }
  174. X            if( err == 0 ) {
  175. X                clear_prompt();
  176. X                for( tile = 0, t1 = -1, t2 = -1, i = 0; i < placed; i++ )
  177. X                    if( newlet[i].letter == CH_BL ) {
  178. X                        tile++;
  179. X                        if( t1 == -1 ) {
  180. X                            t1 = i;
  181. X                            ct1 = newlet[i].blankchar;
  182. X                        } else if( t2 == -1 ) {
  183. X                            t2 = i;
  184. X                            ct2 = newlet[i].blankchar;
  185. X                        }
  186. X                    }
  187. X                for( i = 0, xt = 2; i < tile; i++ ) {
  188. X                    if( i == 0 ) j = t1;
  189. X                    else if( i == 1 ) j = t2;
  190. X                    if( newlet[j].blankchar == CH_BL ) {
  191. X                        clear_rect( 20, 0, 20, 79 );
  192. X                        printw( "  What letter do you want the " );
  193. X                        if( tile == 2 && i == 0 ) printw( "first " );
  194. X                        else if( tile == 2 ) printw( "second " );
  195. X                        printw( "blank tile to be? " );
  196. X                        refresh();
  197. X                        do {
  198. X                            c = get_key();
  199. X                        } while( c < 'A' || c > 'Z' );
  200. X                        newlet[j].blankchar = c;
  201. X                    }
  202. X                    move( 22, xt );
  203. X                    if( tile == 2 && i == 0 ) printw( "First b" );
  204. X                    else if( tile == 2 ) printw( "Second b" );
  205. X                    else printw( "B" );
  206. X                    printw( "lank tile is a" );
  207. X                    if( index( "AEFHILMNORSX", newlet[j].blankchar ) != 0 ) {
  208. X                        printw( "n" );
  209. X                        xt++;
  210. X                    }
  211. X                    printw( " %c.", newlet[j].blankchar );
  212. X                    xt += 26;
  213. X                }
  214. X                clear_rect( 20, 0, 20, 79 );
  215. X                printw( "  Type <RETURN> to end your turn.  Otherwise, type 'n'. -> " );
  216. X                refresh();
  217. X                do {
  218. X                    c = getch();
  219. X                } while( c != '\n' && c != 'N' && c != 'n' );
  220. X                if( c == '\n' ) break;
  221. X                if( t1 != -1 ) newlet[t1].blankchar = ct1;
  222. X                if( t2 != -1 ) newlet[t2].blankchar = ct2;
  223. X            } else press_return();
  224. X            show_instructions();
  225. X        } else {
  226. X            if( xpos > BOARD_RX || ypos > BOARD_LY ) continue;
  227. X            tile = -1;
  228. X            for( i = 0; i < 7; i++ ) {
  229. X                if( c == plr_tiles[human_player][i] ) tile = i;
  230. X                else if( plr_tiles[human_player][i] == CH_BL && tile == -1 )
  231. X                    tile = i;
  232. X            }
  233. X            if( tile == -1 ) continue;
  234. X            if( plr_tiles[human_player][tile] == CH_BL )
  235. X                newlet[placed].blankchar = c;
  236. X            newlet[placed].letter = plr_tiles[human_player][tile];
  237. X            plr_tiles[human_player][tile] = 0;
  238. X            newlet[placed].x = xpos - BOARD_LX + 1;
  239. X            newlet[placed].y = ypos - BOARD_UY + 1;
  240. X            newlet[placed].oldlet =
  241. X              board[ypos - BOARD_UY + 1][xpos - BOARD_LX + 1];
  242. X            if( newlet[placed].oldlet == CH_DW ) newlet[placed].oldlet = 'o';
  243. X            newlet[placed].tilepos = tile;
  244. X            addch( newlet[placed].letter );
  245. X            do {
  246. X                xpos += xinc;
  247. X                ypos += yinc;
  248. X            } while( board[ypos - BOARD_UY + 1][xpos - BOARD_LX + 1] >= 'A'
  249. X              && xpos <= BOARD_RX && ypos <= BOARD_LY );
  250. X            print_tiles();
  251. X            placed++;
  252. X        }
  253. X    }
  254. X    if( placed <= 0 ) return( -1 );
  255. X    err = find_new_words( &newlet[0], placed, xinc, yinc );
  256. X    display_words( human_player, &newlet[0], err, placed );
  257. X    return( 1 );
  258. X}
  259. X
  260. Xshow_instructions() {
  261. X    clear_prompt();
  262. X    printw( "  Type the letter to be placed in each square, and '%c' for a blank tile.\n", CH_BL );
  263. X    printw( "  If you type a letter which you do not have, and you have a blank tile, then\n" );
  264. X    printw( "  it will be placed for you automatically.\n" );
  265. X    printw( "  Press '-' to backspace, <ESC> to cancel, and <RETURN> when done.\n" );
  266. X    refresh();
  267. X}
  268. X
  269. Xint rearrange_tiles() {
  270. X    char c;
  271. X    int i, j;
  272. X
  273. X    clear_prompt();
  274. X    printw( "  Each letter you type will be moved to the end of your rack.\n" );
  275. X    printw( "  Type '%c' for a blank tile, and <RETURN> when you are done.\n",
  276. X          CH_BL );
  277. X    refresh();
  278. X    print_tiles();
  279. X    do {
  280. X        c = get_key();
  281. X        for( i = 0; i < 7; i++ ) {
  282. X            if( c == plr_tiles[human_player][i] ) {
  283. X                for( j = i; j < 6; j++ )
  284. X                    plr_tiles[human_player][j] = plr_tiles[human_player][j + 1];
  285. X                plr_tiles[human_player][6] = c;
  286. X                print_tiles();
  287. X                break;
  288. X            }
  289. X        }
  290. X    } while( c != '\n' );
  291. X    return( -1 );
  292. X}
  293. X
  294. Xdisp_instr() {
  295. X    clear_rect( 19, 0, 20, 79 );
  296. X    printw( "  Type the tiles that you wish to discard, using '%c' for a blank tile.\n", CH_BL );
  297. X    printw( "  Press '-' to backspace, <ESC> to cancel, and <RETURN> when done.\n" );
  298. X    refresh();
  299. X}
  300. X
  301. Xint draw_new_tiles() {
  302. X    char c, tile[7];
  303. X    int i, j, plr;
  304. X    int used[7];
  305. X
  306. X    clear_prompt();
  307. X    disp_instr();
  308. X    plr = human_player;
  309. X    j = 0;
  310. X    for( i = 0; i < 7; i++ ) {
  311. X        used[i] = 0;
  312. X        tile[i] = plr_tiles[plr][i];
  313. X    }
  314. X    for( ;; ) {
  315. X        clear_rect( 22, 0, 22, 79 );
  316. X        printw( "  Tiles to discard:" );
  317. X        for( i = 0; i < 7; i++ )
  318. X            if( used[i] != 0 ) printw( " %c", tile[i] );
  319. X        print_tiles();
  320. X        c = get_key();
  321. X        if( c == '\n' ) {
  322. X            if( j != 0 ) {
  323. X                clear_rect( 19, 0, 20, 79 );
  324. X                printw( "  Type <RETURN> to confirm your selection.  Otherwise, type 'n'. -> " );
  325. X            } else {
  326. X                clear_rect( 19, 0, 20, 79 );
  327. X                printw( "  Type <RETURN> to pass your turn.  Otherwise, type 'n'. -> " );
  328. X            }
  329. X            refresh();
  330. X            do {
  331. X                c = getch();
  332. X            } while( c != '\n' && c != 'N' && c != 'n' );
  333. X            if( c == '\n' ) break;
  334. X            disp_instr();
  335. X        } else if( c == '-' || c == 127 || c == 8 ) {
  336. X            if( j > 0 ) {
  337. X                for( i = 0; i < 7; i++ )
  338. X                    if( used[i] == j ) {
  339. X                        used[i] = 0;
  340. X                        plr_tiles[plr][i] = tile[i];
  341. X                        j--;
  342. X                        break;
  343. X                    }
  344. X            } else {
  345. X                j = -1;
  346. X                break;
  347. X            }
  348. X        } else if( c == 27 ) {
  349. X            for( i = 0; i < 7; i++ )
  350. X                if( used[i] != 0 ) plr_tiles[plr][i] = tile[i];
  351. X            print_tiles();
  352. X            j = -1;
  353. X            break;
  354. X        } else {
  355. X            for( i = 0; i < 7; i++ ) {
  356. X                if( c == plr_tiles[plr][i] ) {
  357. X                    j++;
  358. X                    used[i] = j;
  359. X                    plr_tiles[plr][i] = 0;
  360. X                    break;
  361. X                }
  362. X            }
  363. X        }
  364. X    }
  365. X    if( j == -1 ) return( -1 );
  366. X    for( i = 0; i < 7; i++ )
  367. X        if( used[i] != 0 ) {
  368. X            c = tile[i] - 'A';
  369. X            if( tile[i] == CH_BL ) c = 26;
  370. X            tiles_left[c]++;
  371. X        }
  372. X    for( i = 0; i < 7; i++ )
  373. X        if( used[i] != 0 ) plr_tiles[plr][i] = draw_tile();
  374. X    print_tiles();
  375. X    return( 1 );
  376. X}
  377. END_OF_FILE
  378. if test 8730 -ne `wc -c <'pmove.c'`; then
  379.     echo shar: \"'pmove.c'\" unpacked with wrong size!
  380. fi
  381. # end of 'pmove.c'
  382. fi
  383. if test -f 'score.c' -a "${1}" != "-c" ; then 
  384.   echo shar: Will not clobber existing file \"'score.c'\"
  385. else
  386. echo shar: Extracting \"'score.c'\" \(6224 characters\)
  387. sed "s/^X//" >'score.c' <<'END_OF_FILE'
  388. X/*
  389. X *
  390. X * score.c -- find score for a turn
  391. X *
  392. X */
  393. X
  394. X#include "scrab.h"
  395. X#include "globals.h"
  396. X
  397. X
  398. Xint find_new_words( newlet, placed, xinc, yinc )
  399. X  struct plrlet (*newlet)[];
  400. X  int placed, xinc, yinc;
  401. X{
  402. X    struct plrlet *currlet;
  403. X    int i, w, j;
  404. X    int dx, dy;
  405. X    int x, y;
  406. X    int score, mult, tsc, cptr, blloc;
  407. X    char c, ch;
  408. X
  409. X    w = 0;
  410. X    dx = 1 - xinc;
  411. X    dy = 1 - yinc;
  412. X    for( i = 0; i <= placed; i++ ) {
  413. X        if( i < placed ) {
  414. X            currlet = &((*newlet)[i]);
  415. X            x = currlet->x;
  416. X            y = currlet->y;
  417. X        } else {
  418. X            x = ((*newlet)[0]).x;
  419. X            y = ((*newlet)[0]).y;
  420. X            dx = xinc;
  421. X            dy = yinc;
  422. X        }
  423. X        if( ( y - dy > 0 && x - dx > 0 && board[y - dy][x - dx] >= 'A' )
  424. X          || ( y + dy < 16 && x + dx < 16 && board[y + dy][x + dx] >= 'A' )
  425. X          || i == placed ) {
  426. X            while( board[y - dy][x - dx] >= 'A' && x - dx > 0 && y - dy > 0 ) {
  427. X                x -= dx;
  428. X                y -= dy;
  429. X            }
  430. X            new_words[w].startx = x;
  431. X            new_words[w].starty = y;
  432. X            new_words[w].dir = dy;
  433. X            score = 0;
  434. X            mult = 1;
  435. X            cptr = 0;
  436. X            blloc = -1;
  437. X            for( ;; ) {
  438. X                c = board[y][x];
  439. X                if( c >= 'A' ) {
  440. X                    if( ( x != b1x || y != b1y ) && ( x != b2x || y != b2y ) )
  441. X                        score += letters[c - 'A'].points;
  442. X                    new_words[w].letters[cptr++] = c;
  443. X                } else {
  444. X                    for( j = 0; j < placed; j++ )
  445. X                        if( x == ((*newlet)[j]).x && y == ((*newlet)[j]).y )
  446. X                            break;
  447. X                    if( j == placed ) break;
  448. X                    if( blloc == -1 ) blloc = cptr;
  449. X                    else blloc = -2;
  450. X                    ch = ((*newlet)[j]).letter;
  451. X                    if( ch == CH_BL ) {
  452. X                        tsc = 0;
  453. X                        new_words[w].letters[cptr++] = ((*newlet)[j]).blankchar;
  454. X                    } else {
  455. X                        tsc = letters[ch - 'A'].points;
  456. X                        new_words[w].letters[cptr++] = ch;
  457. X                    }
  458. X                    if( c == CH_DL ) tsc *= 2;
  459. X                    else if( c == CH_TL ) tsc *= 3;
  460. X                    else if( c == CH_DW ) mult *= 2;
  461. X                    else if( c == CH_TW ) mult *= 3;
  462. X                    score += tsc;
  463. X                }
  464. X                x += dx;
  465. X                y += dy;
  466. X                if( x > 15 || y > 15 ) break;
  467. X            }
  468. X            score *= mult;
  469. X            if( placed == 7 && i == placed ) score += 50;
  470. X            new_words[w].length = cptr;
  471. X            new_words[w].letters[cptr] = '\0';
  472. X            new_words[w].blankloc = blloc;
  473. X            new_words[w].score = score;
  474. X            if( i != placed || cptr != 1 ) w++;
  475. X        }
  476. X    }
  477. X    return( w );
  478. X}
  479. X
  480. Xlong bin_search( word )
  481. X  char *word;
  482. X{
  483. X    long f, l, m;
  484. X    int found;
  485. X
  486. X    f = wlen[strlen( word )];
  487. X    l = wlen[strlen( word ) + 1] - 1;
  488. X    found = 0;
  489. X    do {
  490. X        m = ( f + l ) / 2;
  491. X        if( strcmp( word, &(words[wptr[m]]) ) > 0 )
  492. X            f = m + 1;
  493. X        else if( strcmp( word, &(words[wptr[m]]) ) < 0 )
  494. X            l = m - 1;
  495. X        else {
  496. X            found = 1;
  497. X            f = m;
  498. X            l = m;
  499. X        }
  500. X    } while( f < l );
  501. X    if( strcmp( word, &(words[wptr[f]]) ) == 0 
  502. X        || strcmp( word, &(words[wptr[l]]) ) == 0 ) found = 1;
  503. X    return( found );
  504. X}
  505. X
  506. Xdisplay_words( plr, newlet, nwords, placed )
  507. X  int plr, nwords, placed;
  508. X  struct plrlet (*newlet)[];
  509. X{
  510. X    int i, j, xloc, score;
  511. X    char c, tile, *word;
  512. X    int x, y;
  513. X    int illword, ind[8];
  514. X    int shift;
  515. X
  516. X    clear_turn();
  517. X    clear_prompt();
  518. X    move( 18, 0 );
  519. X    printw( "  %s made the following words:\n", you[plr] );
  520. X    refresh();
  521. X    score = 0;
  522. X    illword = 0;
  523. X    printw( "    " );
  524. X    xloc = 4;
  525. X    for( i = 0; i < nwords; i++ ) {
  526. X        word = &(new_words[i].letters[0]);
  527. X        if( strlen( word ) + xloc + 2 > 79 ) {
  528. X            printw( "\n    " );
  529. X            xloc = 4;
  530. X        }
  531. X        printw( "%s  ", word );
  532. X        score += new_words[i].score;
  533. X        if( bin_search( word ) == 0 ) {
  534. X            ind[illword++] = i;
  535. X        }
  536. X    }
  537. X    move( 21, 0 );
  538. X    if( illword != 0 ) {
  539. X        if( plr != human_player ) {
  540. X            printw( "*** Fatal error in display_words()\n" );
  541. X            exit_window();
  542. X            exit( 1 );
  543. X        }
  544. X        for( i = 0; i < illword; i++ ) {
  545. X            clear_rect( 21, 0, 22, 79 );
  546. X            printw( "  %s is not in the computer's dictionary.\n",
  547. X              &(new_words[i].letters[0]) );
  548. X            printw( "  Is it a valid Scrabble word (y/n)? " );
  549. X            refresh();
  550. X            do {
  551. X                c = get_key();
  552. X            } while( c != 'Y' && c != 'N' );
  553. X            if( c == 'N' ) break;
  554. X            clear_rect( 21, 0, 22, 79 );
  555. X            printw( "  Inserting %s into the dictionary...",
  556. X              &(new_words[i].letters[0]) );
  557. X            refresh();
  558. X            add_dict( &(new_words[i].letters[0]) );
  559. X            dict_changed = 1;
  560. X        }
  561. X        clear_rect( 21, 0, 22, 79 );
  562. X        if( i == illword ) {
  563. X            illword = 0;
  564. X        } else {
  565. X            printw( "  For placing an invalid word, you score zero this round.\n" );
  566. X            printw( "  You remove your tiles from the board.\n" );
  567. X            for( j = 0; j < placed; j++ )
  568. X                plr_tiles[plr][((*newlet)[j]).tilepos] = ((*newlet)[j]).letter;
  569. X        }
  570. X    }
  571. X    if( illword == 0 ) {
  572. X        if( placed == 7 )
  573. X            printw( "  %s used all seven tiles!", you[plr] );
  574. X        printw( "  %s score this round is %3d.\n", your[plr], score );
  575. X        plr_scores[plr] += score;
  576. X        for( i = 0; i < placed; i++ ) {
  577. X            x = ((*newlet)[i]).x;
  578. X            y = ((*newlet)[i]).y;
  579. X            tile = ((*newlet)[i]).letter;
  580. X            if( tile == CH_BL ) {
  581. X                tile = ((*newlet)[i]).blankchar;
  582. X                if( b1x == 0 ) {
  583. X                    b1x = x;
  584. X                    b1y = y;
  585. X                } else {
  586. X                    b2x = x;
  587. X                    b2y = y;
  588. X                }
  589. X            }
  590. X            board[y][x] = tile;
  591. X        }
  592. X        for( i = 0, shift = 0; i < 7; i++ ) {
  593. X            if( plr_tiles[plr][i] == 0 ) shift++;
  594. X            else if( shift > 0 ) {
  595. X                plr_tiles[plr][i - shift] = plr_tiles[plr][i];
  596. X                plr_tiles[plr][i] = 0;
  597. X            }
  598. X        }
  599. X        for( i = 7 - shift; i < 7; i++ ) {
  600. X            tile = draw_tile();
  601. X            if( tile == 0 ) break;
  602. X            plr_tiles[plr][i] = tile;
  603. X        }
  604. X        move( 22, 0 );
  605. X        if( tile == 0 && i == 7 - shift) {
  606. X            if( plr != human_player )
  607. X                printw( "  There are no tiles left for %s to draw.\n", you[plr] );
  608. X            else
  609. X                printw( "  There are no tiles left for you to draw.\n" );
  610. X        } else {
  611. X            if( tile == 0 ) {
  612. X                printw( "  %s can only draw ", you[plr] );
  613. X                shift = i - ( 7 - shift );
  614. X            } else {
  615. X                printw( "  %s dra%s ", you[plr],
  616. X                  ( ( plr == human_player ) ? "w" : "ws" ) );
  617. X            }
  618. X            printw( "%d til%s.\n", shift, ( shift == 1 ? "e" : "es" ) );
  619. X        }
  620. X    }
  621. X    print_board();
  622. X    print_tiles();
  623. X    press_return();
  624. X}
  625. X
  626. Xadd_dict( word )
  627. X  char *word;
  628. X{
  629. X    int i, l;
  630. X    long p1, p2;
  631. X
  632. X    l = strlen( word );
  633. X    for( p1 = wlen[l];
  634. X          p1 < wlen[l + 1] && strcmp( word, &(words[wptr[p1]]) ) > 0;
  635. X          p1++ );
  636. X    for( p2 = dict_size - 1; p2 >= wptr[p1]; p2-- ) words[p2 + l + 1] = words[p2];
  637. X    for( p2 = wlen[16]; p2 > p1; p2-- ) wptr[p2] = wptr[p2 - 1] + l + 1;
  638. X    for( i = l + 1; i < 17; i++ ) wlen[i]++;
  639. X    strcpy( &(words[wptr[p1]]), word );
  640. X    dict_size += l + 1;
  641. X/*    printw( "\n  " );
  642. X    for( p2 = p1 - 2; p2 < p1 + 3; p2++ )
  643. X        printw( "%s  ", &(words[wptr[p2]]) );
  644. X    printw( "%s  %s", &(words[wptr[wlen[8]]]), &(words[wptr[wlen[16] - 1]]) );
  645. X    press_return(); */
  646. X}
  647. END_OF_FILE
  648. if test 6224 -ne `wc -c <'score.c'`; then
  649.     echo shar: \"'score.c'\" unpacked with wrong size!
  650. fi
  651. # end of 'score.c'
  652. fi
  653. if test -f 'scrabble.6' -a "${1}" != "-c" ; then 
  654.   echo shar: Will not clobber existing file \"'scrabble.6'\"
  655. else
  656. echo shar: Extracting \"'scrabble.6'\" \(16325 characters\)
  657. sed "s/^X//" >'scrabble.6' <<'END_OF_FILE'
  658. X.\" @(#)scrabble.6 1.02 92/09/16 JAC
  659. X.TH SCRABBLE 6 "16 September 1992"
  660. X.SH NAME
  661. Xscrabble \- play the Scrabble(TM) board game
  662. X.SH SYNOPSIS
  663. X.B scrabble
  664. X.SH DESCRIPTION
  665. X.LP
  666. X.B scrabble
  667. Xis a computer version of the Selchow & Righter board game, Scrabble.
  668. XOnly one human player plays; the user may select the number of
  669. Xcomputer opponents, from one to three.
  670. X.SH BASIC SCRABBLE RULES
  671. X.LP
  672. XThe object of the game is to form English words in a
  673. Xcrossword\-like grid.  Words are formed using
  674. X.I tiles,
  675. Xeach of which has a letter on it.
  676. XThe player with the highest score at the
  677. Xend of the game is the winner.
  678. X.LP
  679. XEach letter has a
  680. Xparticular score associated with it.  For example, the letter
  681. X.B E
  682. Xis worth one point, while
  683. X.B Q
  684. Xis worth ten points.  There are a fixed number of tiles with
  685. Xeach letter.  For example, there are twelve
  686. X.B E
  687. Xtiles, and only one
  688. X.B Q
  689. Xtile.  There are also two blank tiles, which
  690. Xmay be used as any letter. Once a blank tile is placed on the
  691. Xboard as a certain letter, that letter may not change.
  692. X.LP
  693. XEach player starts with seven tiles,
  694. Xwhich are placed in their
  695. X.I rack.
  696. XThese tiles are drawn from a shuffled pool of
  697. Xone hundred tiles.
  698. X.LP
  699. XThe first player to
  700. Xmove must play a word that covers the center square;
  701. Xas well, this player must place two or more of their
  702. Xtiles.  After the first move,
  703. Xplayers take turns placing one or more of their tiles
  704. Xon the board, so as to form new words in the
  705. Xstandard crossword\-like manner: new words must read
  706. Xacross or down, not diagonally.
  707. X.LP
  708. XNew words may be formed one of three ways:
  709. X.TP
  710. X1.
  711. XBy adding a tiles to an already existing word, e.g.,
  712. Xadding
  713. X.B ABLE
  714. Xto
  715. X.B READ.
  716. X.TP
  717. X2.
  718. XBy adding tiles that intersect another word, e.g.,
  719. Xspelling
  720. X.B WARY
  721. Xby placing 
  722. X.B W,
  723. X.B R,
  724. Xand
  725. X.B Y
  726. Xaround the
  727. X.B A
  728. Xof
  729. X.B REAL.
  730. X.TP
  731. X3.
  732. XBy spelling a word in one direction and forming
  733. Xnew words in the other direction, e.g., by adding
  734. X.B FOX
  735. Xnext to
  736. X.B PIG
  737. Xso that the
  738. X.B I
  739. Xof
  740. X.B PIG
  741. Xis used to spell
  742. X.B IF
  743. Xwith the
  744. X.B F
  745. Xfrom
  746. X.B FOX
  747. Xand, similarly, the
  748. X.B G
  749. Xis used to spell
  750. X.B GO.
  751. X.LP
  752. XIf all the new words formed are valid English words,
  753. Xthat player's score is increased by the value of the
  754. Xtiles in
  755. X.I all
  756. Xnew words formed.  The player then draws new tiles from
  757. Xthe pool until the player again has seven tiles in his/her
  758. Xrack, or until there are no more tiles left to draw.
  759. X.LP
  760. XIf
  761. X.I any
  762. Xof the new
  763. Xwords formed are not valid English words, the player
  764. Xscores zero for that turn, and must remove the tiles just
  765. Xplaced from the board and replace them in his/her rack.
  766. X.LP
  767. XValid English words in Scrabble constitute any word so long
  768. Xas it is not an abbreviation (LTD, CORP), is not normally
  769. Xcapitalized (MATTHEW, LONDON), does not contain punctuation
  770. X(COLD\-HEARTED, CAN'T),
  771. Xand is not a prefix or suffix (PRE, ATION).
  772. XForeign words that are used frequently in English
  773. Xare allowed (words such as CIAO and QUO).  Slang
  774. Xand colloquial words are also allowed.
  775. X.LP
  776. XOnce a tile has been placed on the board, it may not
  777. Xbe moved.
  778. X.LP
  779. XCertain board squares are special, in that they increase
  780. Xthe value of a letter or a word.  Double and triple letter
  781. Xsquares increase the value of a tile by double and triple,
  782. Xrespectively.  Double and triple word scores increase the
  783. Xvalue of a word by double and triple, respectively.  Double
  784. Xand triple letter squares are counted
  785. X.I before
  786. Xdouble and triple word squares.  These special squares only
  787. Xcount on the turn in which they are covered; the squares
  788. Xare no longer special in subsequent turns.
  789. X.LP
  790. XA player who uses all seven tiles on one turn gets a premium
  791. Xof fifty points on top of the regular score for that turn.
  792. X.LP
  793. XInstead of placing tiles, a player may forfeit his/her
  794. Xturn and draw between zero and seven new tiles.  The player
  795. Xselects which of his/her tiles to replace, puts them back
  796. Xin the pool, and then draws the same number of tiles from
  797. Xthe pool again.  A player doing this scores zero for that
  798. Xturn.
  799. X.LP
  800. XThe game ends when there are no tiles left to draw and
  801. Xone player has no tiles left to place,
  802. X.I or
  803. Xwhen no player can make a valid move.  Each player's score
  804. Xis adjusted by subtracting from it
  805. Xthe value of each tile remaining
  806. Xin his/her own rack.  As well, if one player uses all his/her
  807. Xtiles, his/her score is increased by the sum of all unplayed
  808. Xletters in the other players' racks.  The player with the
  809. Xhighest score wins the game.  In the event of a tie, the
  810. Xplayer with the highest score prior to the score adjustment
  811. Xis the winner.
  812. X.SH SCRABBLE SCREEN LAYOUT
  813. X.LP
  814. XThe upper\-left side of the screen lists the special board
  815. Xsymbols used in
  816. X.B scrabble.
  817. X.TP
  818. X\+
  819. XDouble letter score.
  820. X.TP
  821. X\#
  822. XTriple letter score.
  823. X.TP
  824. Xo
  825. XDouble word score.
  826. X.TP
  827. X\@
  828. XTriple word score.
  829. X.TP
  830. X*
  831. XBlank tile.  This is the character displayed in a player's
  832. Xrack when he/she owns a blank tile.  Once the tile is
  833. Xplaced on the board, it is shown in lower\-case as the letter
  834. Xit represents.
  835. X.LP
  836. XThe lower\-left side of the screen lists the value of each
  837. Xtile, as well as the total number of tiles of each type.
  838. XFor example, "A\-1, 9" means that there are a total of nine
  839. Xtiles with
  840. X.B A
  841. Xon them, and that each tile is worth one point.
  842. X.LP
  843. XThe center of the screen shows the
  844. X.B scrabble
  845. Xboard.
  846. X.LP
  847. XThe upper\-right of the screen displays the number of
  848. Xtiles left in the pool to draw.  As well, it displays
  849. Xthe number of passed turns, if any.
  850. X.LP
  851. XThe central\-right of the screen shows all players'
  852. Xtile racks.  The computer players' tiles are represented
  853. Xby dashes.  As well, the computer players' skill levels
  854. Xare displayed in brackets next to their designations
  855. X(e.g., CPU1).  Finally, each player's score is shown here.
  856. X.LP
  857. XThe lower\-right of the screen indicates the location of
  858. Xany blank tiles that have been placed on the board, as
  859. Xwell as the letter they represent.
  860. X.LP
  861. XThe bottom of the screen is the message and input area.
  862. X.SH PLAYING SCRABBLE
  863. X.LP
  864. XThe user must select the number of computer players
  865. Xto play against.  Then, each player draws a tile.
  866. XThe player with the lowest tile alphabetically starts
  867. Xthe game.  A blank tile is considered lower alphabetically
  868. Xthan all other letters.
  869. X.LP
  870. XThe user then selects the skill level of each
  871. Xcomputer player.  Skill levels go from 1 (easy to beat)
  872. Xto 5 (hard to beat, but still possible), and skill level
  873. X6 ("expert mode") makes the computer player play its
  874. Xhighest\-scoring move every turn.
  875. X.LP
  876. XWhen it is the computer's turn to play, it searches the
  877. Xboard for a move.  The cursor shows the square that the
  878. Xcomputer is thinking about playing on.  After the search,
  879. Xthe computer chooses its move based on its skill level.
  880. XIf it could not find a move, it will say so.
  881. X.LP
  882. XWhen it is your turn to play, the cursor
  883. Xstarts at the upper\-left corner of the board.  The following
  884. Xkeys may then be used.
  885. X.TP
  886. Xh
  887. XMoves the cursor left.  If the cursor is on the left edge
  888. Xof the board, this key has no effect.
  889. X.TP
  890. Xj
  891. XMoves the cursor down.  If the cursor is on the bottom edge
  892. Xof the board, this key has no effect.
  893. X.TP
  894. Xk
  895. XMoves the cursor up.  If the cursor is on the top edge
  896. Xof the board, this key has no effect.
  897. X.TP
  898. Xl
  899. XMoves the cursor right.  If the cursor is on the right edge
  900. Xof the board, this key has no effect.
  901. X.TP
  902. XRETURN
  903. XStarts placing tiles on the board.  If the cursor is over
  904. Xa square that is already occupied by a tile, this key has
  905. Xno effect.  More on this key below.
  906. X.TP
  907. XSPACE
  908. XRearrange your tiles.  Sometimes it's easier to see what words
  909. Xyou can form if you group your tiles in your rack a certain
  910. Xway.  This key allows you to regroup your tiles.  Typing the
  911. Xletter of a tile in your rack moves it to the end of your rack.
  912. XUse the asterisk for a blank tile.  Pressing RETURN exits this
  913. Xmode.
  914. X.TP
  915. X\\.
  916. XDraw new tiles.  If you really hate the tiles in
  917. Xyour rack, or even if you
  918. Xdon't, you can replace none, some, or all of your tiles and
  919. Xdraw (potentially) new ones.
  920. XType this key, followed by the
  921. Xletters in your rack that you wish to replace.  Pressing dash
  922. Xor DEL will put your most recent selection back in your rack.
  923. XPressing ESC will cancel this operation, and pressing RETURN
  924. Xwill ask you to confirm your selection.
  925. X.TP
  926. X.I Note
  927. X.I If you cannot move
  928. Xand wish to pass your turn,
  929. Xthen you must press the "Draw new tiles" key,
  930. Xand then draw zero new tiles.
  931. X.LP
  932. XOnce you press RETURN to start placing tiles, you can press
  933. Xeither 
  934. X.I h
  935. Xor
  936. X.I v
  937. Xto place your tiles horizontally or vertically,
  938. Xrespectively.
  939. X.LP
  940. XThen, you simply begin typing.  Each time you type a tile
  941. Xthat is in your rack, the tile is placed on the board at the
  942. Xcursor's position.  The cursor then moves to the next blank
  943. Xsquare in the appropriate direction.  If you type a letter
  944. Xthat is not in your rack, it is ignored
  945. X.I except
  946. Xif you have a blank tile.  In this case, the blank tile is
  947. Xplaced on the board for you.  If you type an asterisk and you
  948. Xhave a blank tile, it is placed on the board as usual.
  949. X.LP
  950. XWhile typing, you may press dash or DEL to remove the last
  951. Xtile placed from the board and put it back in your rack.  Or, you
  952. Xmay press ESC to cancel this particular placement all together.
  953. XIf you're satisfied with what you've placed, you may press
  954. XRETURN.  If you placed any blank tiles by typing asterisk, you
  955. Xwill be asked for the letters that the blank tiles represent.
  956. XPress RETURN to confirm your move, or
  957. X.I n
  958. Xto alter it.
  959. X.LP
  960. XYour words are then checked against the dictionary.  If all
  961. Xthe words are in the dictionary, your score is increased and
  962. Xnew tiles are drawn for you.  If any of your words are not
  963. Xin the dictionary, you are asked if said words are valid
  964. X.B scrabble
  965. Xwords.  You are expected to answer honestly!  If any word is
  966. Xinvalid, your tiles are removed from the board and replaced in
  967. Xyour rack.  If the word is valid, it is added to the dictionary.
  968. XSo beware!  The computer players can then use the word too.
  969. X.LP
  970. X.B scrabble
  971. Xdoes all the drawing of new tiles automatically.  It also
  972. Xdoes all the scoring, including the score adjustments at the
  973. Xend of the game.  It can even handle multiple\-way ties at the
  974. Xend of the game, should this unlikely event occur.
  975. X.LP
  976. XAt the end of the game, if any words have been added to
  977. Xthe dictionary,
  978. X.B scrabble
  979. Xwill ask you if you want to save the dictionary.  If you
  980. Xsay yes, the old dictionary file is overwritten with the
  981. Xnew one.  Otherwise, the original dictionary remains intact.
  982. X(The option of rewriting the dictionary is useful if you
  983. Xwere simply cheating and spelling really long garbage words
  984. Xfor the satisfaction of totally annihilating the computer.)
  985. X.LP
  986. XOne minor point: often throughout the game, you will be
  987. Xprompted to "Press <RETURN>".  If you press the
  988. X.I q
  989. Xkey followed by RETURN, you will exit scrabble.  This can
  990. Xbe safer than pressing an interrupt key to exit, which may
  991. Xmess up your window.
  992. X.SH COMPUTER PLAYERS' ALGORITHM
  993. X.LP
  994. XFor the curious, here is a brief description of how the
  995. Xcomputer players decide on their moves.
  996. X.LP
  997. XIf the board is empty, the computer simply searches the
  998. Xdictionary for any word whose length is between two and
  999. Xseven that can be formed with its tiles.  It stores all
  1000. Xpossibilities, and computes the score for all possible
  1001. Xplacements of each word.
  1002. X.LP
  1003. XFor the remainder of this section, a
  1004. X.I legal move
  1005. Xis one which adjoins to the existing puzzle.
  1006. X.LP
  1007. XThe computer players do an exhaustive search of the board,
  1008. Xfinding all positions in which a legal move can be made.
  1009. X.LP
  1010. XAt each square, the computer determines how many of its tiles
  1011. Xit can place and still be a legal move.  This can be anywhere
  1012. Xbetween one and seven tiles, inclusive.  For example, the
  1013. Xcomputer might be able to place any number of tiles between
  1014. Xthree and seven, and still be making a legal move.  The computer
  1015. Xthen performs an exhaustive dictionary search for each of
  1016. Xthese numbers of tiles.  In the example, the computer would
  1017. Xperform five exhaustive searches.
  1018. X.LP
  1019. XThe searching algorithm prunes the search tree in three ways.
  1020. X.TP
  1021. X1.
  1022. XFor a given number of tiles to be placed (say three),
  1023. Xall words formed will be of the same length (say four).  Thus,
  1024. Xthe computer only need search all four\-letter words.
  1025. X.TP
  1026. X2.
  1027. XOften one or more of the letters in the new word to be formed
  1028. Xwill be fixed, because the computer might be adding to
  1029. Xa word that has already been placed on the board.  For example,
  1030. Xif the word
  1031. X.B WENT
  1032. Xis on the board horizontally, the computer might be trying
  1033. Xto add a word vertically to the
  1034. X.B N.
  1035. XThus, any
  1036. Xword that does not have the fixed letter(s) in the proper
  1037. Xplace(s) can be eliminated right away.
  1038. X.TP
  1039. X3.
  1040. XThe computer might be forming other words in the opposite
  1041. Xdirection to which it is placing tiles.
  1042. XFor example, suppose the computer
  1043. Xis trying to form a word horizontally with three tiles.
  1044. XFurthermore, suppose that its first tile has to adjoin
  1045. Xto a vertical word such as
  1046. X.B PIT.
  1047. XThen, the computer checks
  1048. Xif it can form a valid word of the form
  1049. X.B PIT_
  1050. X(where the
  1051. Xunderscore represents an unknown tile) before the
  1052. Xexhaustive search.  In this case, the computer would
  1053. Xhave to own an
  1054. X.B A,
  1055. X.B H,
  1056. X.B S,
  1057. Xor
  1058. X.B Y
  1059. Xto form
  1060. X.B PITA,
  1061. X.B PITH,
  1062. X.B PITS,
  1063. Xor
  1064. X.B PITY.
  1065. XOtherwise, the search would be abandoned.
  1066. X.LP
  1067. XThe computer stores all possible moves in a linked list sorted
  1068. Xfrom highest\-scoring move to lowest\-scoring move.  Once the
  1069. Xsearch is complete, the computer then selects a move.  In expert
  1070. Xmode (level 6), the computer merely chooses the move at the
  1071. Xhead of the list.  On the other levels, the computer picks
  1072. Xa move using a normal p.d.f.  The mean of the distribution is
  1073. Xplaced close to the highest\-scoring move on level 5, and
  1074. Xsort of close to the lowest\-scoring move on level 1.  The standard
  1075. Xdeviation of the distribution is one\-fifth of the number
  1076. Xof distinct scores that each move might give.  For example,
  1077. Xthe computer might be able to make moves that would give it
  1078. X4, 6, 7, 9, or 10 points.  In this case, the standard deviation
  1079. Xwould be one.
  1080. X.SH FILES
  1081. X.TP
  1082. Xscrabble
  1083. XThis is the executable file.
  1084. X.TP
  1085. Xscrabbledict
  1086. XThis is the dictionary file.
  1087. X.SH DICTIONARY FILES
  1088. X.LP
  1089. XIf desired, the user may supply his/her own version of
  1090. Xthe dictionary file.
  1091. XThe dictionary file must have the following properties:
  1092. X.TP
  1093. X1.
  1094. XIt must be sorted from shortest words (two letters)
  1095. Xto longest words (fifteen letters).
  1096. X.TP
  1097. X2.
  1098. XWithin each word length, the words must be sorted
  1099. Xalphabetically from A to Z.
  1100. X.TP
  1101. X3.
  1102. XWords
  1103. X.I must
  1104. Xbe all capitals.
  1105. X.B scrabble
  1106. Xignores any word that contains
  1107. Xpunctuation, as well as any word longer than
  1108. Xfifteen characters.
  1109. X.SH AUTHOR
  1110. X.LP
  1111. X.B scrabble
  1112. Xwas written by James A. Cherry, at Carleton University,
  1113. XOttawa, Ontario, Canada.  Questions, comments, etc., may
  1114. Xbe addressed to jac@doe.carleton.ca.
  1115. X.SH BUGS
  1116. X.LP
  1117. XThe computer search algorithm is highly inelegant.  It is
  1118. Xsimply brute\-force.
  1119. X.LP
  1120. X.B scrabble
  1121. Xis a complete pig for memory; it stores the entire dictionary
  1122. Xin memory for fast searching.  Also, every possible computer
  1123. Xmove on a given turn is stored; no moves are erased until the
  1124. Xcomputer has decided on its move.  Since it is sometimes
  1125. Xpossible to make 3,000 or more moves, the move list occupies
  1126. Xa large chunk of memory.
  1127. X.LP
  1128. XIf you play a garbage word, and tell the computer that it really
  1129. Xis a word, it will believe you.
  1130. X.LP
  1131. XThe whole concept of challenging another
  1132. Xplayer's word is non\-existent in
  1133. X.B scrabble.
  1134. XThis is unfortunate, as it is an important part of the game.
  1135. XThe computer players only spell words that are in the dictionary.
  1136. XThey never try to "pull a fast one" on you.  Likewise, if the
  1137. Xcomputer plays a word that you're
  1138. X.I sure
  1139. Xis not a valid
  1140. X.B scrabble
  1141. Xword, it will not allow you to challenge it.  After all, the
  1142. Xword was in the dictionary, so it
  1143. X.I must
  1144. Xbe valid.  (Yeah, right.)  Perhaps removing the offending
  1145. Xword from the dictionary at the end of the game is the solution.
  1146. X.LP
  1147. XIn expert mode, the computers are practically impossible to beat.
  1148. X.LP
  1149. XThere is no way to get the computer to suggest a move for you.
  1150. X.LP
  1151. XOn any level but expert, the computer players tend to keep their
  1152. XQ and Z tiles right until the end; this means they lose a lot of
  1153. Xpoints after the game is over.  Even a bad human player would try
  1154. Xto get rid of these high\-scoring tiles quickly, but the computer's
  1155. Xalgorithm does not allow it to.
  1156. X.LP
  1157. XInterrupt characters are not caught, and they might mess up your
  1158. Xwindow to the point that it is no longer usable.
  1159. X.LP
  1160. XIf something bad happens (like an interrupt character) while
  1161. X.B scrabble
  1162. Xis re\-writing the dictionary, the dictionary file might be lost.
  1163. END_OF_FILE
  1164. if test 16325 -ne `wc -c <'scrabble.6'`; then
  1165.     echo shar: \"'scrabble.6'\" unpacked with wrong size!
  1166. fi
  1167. # end of 'scrabble.6'
  1168. fi
  1169. if test -f 'smain.c' -a "${1}" != "-c" ; then 
  1170.   echo shar: Will not clobber existing file \"'smain.c'\"
  1171. else
  1172. echo shar: Extracting \"'smain.c'\" \(7661 characters\)
  1173. sed "s/^X//" >'smain.c' <<'END_OF_FILE'
  1174. X/*
  1175. X *
  1176. X * smain.c -- main program
  1177. X *
  1178. X */
  1179. X
  1180. X#include "scrab.h"
  1181. X#include "globals.h"
  1182. X
  1183. X
  1184. Xset_up_window() {
  1185. X    int xsize, ysize;
  1186. X    WINDOW *screen;
  1187. X
  1188. X    screen = initscr();
  1189. X    refresh();
  1190. X    if( screen->_maxx < 80 || screen->_maxy < 24 ) {
  1191. X        endwin();
  1192. X        fprintf( stderr, "Need at least a 24x80 screen\n" );
  1193. X        exit( 1 );
  1194. X    }
  1195. X    cbreak();
  1196. X    noecho();
  1197. X}
  1198. X
  1199. Xexit_window() {
  1200. X    char c;
  1201. X
  1202. X    move( 23, 0 );
  1203. X    printw( "Press any key to end? " );
  1204. X    refresh();
  1205. X    c = getch();
  1206. X    endwin();
  1207. X}
  1208. X
  1209. Xinit_board() {
  1210. X    int i, j;
  1211. X
  1212. X    for( i = 1; i < 16; i++ )
  1213. X        for( j = 1; j < 16; j++ )
  1214. X            board[i][j] = CH_EM;
  1215. X    board[1][1] = CH_TW;
  1216. X    board[8][1] = CH_TW;
  1217. X    board[8][8] = CH_DW;
  1218. X    for( i = 2; i < 6; i++ ) {
  1219. X        board[i][i] = CH_DW;
  1220. X    }
  1221. X    board[2][6] = CH_TL;
  1222. X    board[6][2] = CH_TL;
  1223. X    board[6][6] = CH_TL;
  1224. X    board[1][4] = CH_DL;
  1225. X    board[4][1] = CH_DL;
  1226. X    board[3][7] = CH_DL;
  1227. X    board[7][3] = CH_DL;
  1228. X    board[8][4] = CH_DL;
  1229. X    board[7][7] = CH_DL;
  1230. X    for( i = 1; i < 9; i++ )
  1231. X        for( j = 1; j < 8; j++ ) {
  1232. X            board[16-j][i] = board[i][j];
  1233. X            board[16-i][16-j] = board[i][j];
  1234. X            board[j][16-i] = board[i][j];
  1235. X        }
  1236. X}
  1237. X
  1238. Xprint_info() {
  1239. X    move( INFO_Y    , INFO_X );
  1240. X    printw( "Special symbols:" );
  1241. X    move( INFO_Y + 1, INFO_X + 2 );
  1242. X    printw( "%c: Double letter score", CH_DL );
  1243. X    move( INFO_Y + 2, INFO_X + 2 );
  1244. X    printw( "%c: Triple letter score", CH_TL );
  1245. X    move( INFO_Y + 3, INFO_X + 2 );
  1246. X    printw( "%c: Double word score", 'o' );
  1247. X    move( INFO_Y + 4, INFO_X + 2 );
  1248. X    printw( "%c: Triple word score", CH_TW );
  1249. X    move( INFO_Y + 5, INFO_X + 2 );
  1250. X    printw( "%c: Blank tile", CH_BL );
  1251. X    move( INFO_Y + 7, INFO_X );
  1252. X    printw( "Tile values & distributions:" );
  1253. X    move( INFO_Y + 8, INFO_X + 2 );
  1254. X    printw( "A-1, 9  H-4, 2  O-1, 8  V-4, 2" );
  1255. X    move( INFO_Y + 9, INFO_X + 2 );
  1256. X    printw( "B-3, 2  I-1, 9  P-3, 2  W-4, 2" );
  1257. X    move( INFO_Y +10, INFO_X + 2 );
  1258. X    printw( "C-3, 2  J-8, 1  Q10, 1  X-8, 1" );
  1259. X    move( INFO_Y +11, INFO_X + 2 );
  1260. X    printw( "D-2, 4  K-5, 1  R-1, 6  Y-4, 2" );
  1261. X    move( INFO_Y +12, INFO_X + 2 );
  1262. X    printw( "E-1,12  L-1, 4  S-1, 4  Z10, 1" );
  1263. X    move( INFO_Y +13, INFO_X + 2 );
  1264. X    printw( "F-4, 2  M-3, 2  T-1, 6  %c-0, 2", CH_BL );
  1265. X    move( INFO_Y +14, INFO_X + 2 );
  1266. X    printw( "G-2, 3  N-1, 6  U-1, 4" );
  1267. X    refresh();
  1268. X}
  1269. X
  1270. Xinit_tiles() {
  1271. X    int i, j;
  1272. X
  1273. X    for( i = 0; i < 27; i++ )
  1274. X        tiles_left[i] = letters[i].tiles;
  1275. X    for( i = 0; i < 4; i++ )
  1276. X        for( j = 0; j < 7; j++ )
  1277. X            plr_tiles[i][j] = 0;
  1278. X    b1x = 0;
  1279. X    b2x = 0;
  1280. X    b1y = 0;
  1281. X    b2y = 0;
  1282. X    normal_sum = 0;
  1283. X    for( i = 0; i < 40; i++    ) normal_sum += normal_dist[i];
  1284. X}
  1285. X
  1286. Xget_num_players() {
  1287. X    char c;
  1288. X    int i, j;
  1289. X    char ft[4], cs[7];
  1290. X
  1291. X    clear_prompt();
  1292. X    printw( "  Number of computer players (1-3)? " );
  1293. X    refresh();
  1294. X    for( ;; ) {
  1295. X        c = getch();
  1296. X        if( c >= '1' && c <= '3' ) break;
  1297. X    }
  1298. X    players = c - '0' + 1;
  1299. X    for( ;; ) {
  1300. X        init_tiles();
  1301. X        for( i = 0; i < players; i++ ) ft[i] = draw_tile();
  1302. X        for( i = 1; i < players; i++ )
  1303. X            if( ft[0] == ft[i] ) break;
  1304. X        if( i != players ) continue;
  1305. X        move( 20, 0 );
  1306. X        printw( "  All players draw a tile.  You: %c", ft[0] );
  1307. X        for( i = 1; i < players; i++ ) {
  1308. X            printw( "  Player %d: %c", i + 1, ft[i] );
  1309. X            if( ft[i] == CH_BL ) ft[i] = 'A' - 1;
  1310. X        }
  1311. X        j = players;
  1312. X        for( i = 1; i < players; i++ )
  1313. X            if( ft[0] < ft[i] ) j--;
  1314. X        if( j == 1 ) strcpy( cs, "first" );
  1315. X        if( j == 2 ) strcpy( cs, "second" );
  1316. X        if( j == 3 ) strcpy( cs, "third" );
  1317. X        if( j == 4 ) strcpy( cs, "fourth" );
  1318. X        printw( "\n  You will play %s.", cs );
  1319. X        human_player = j - 1;
  1320. X        print_tiles_left( 100 );
  1321. X        press_return();
  1322. X        clear_prompt();
  1323. X        refresh();
  1324. X        break;
  1325. X    }
  1326. X
  1327. X    init_tiles();
  1328. X    j = '1';
  1329. X    for( i = 0; i < 4; i++ ) {
  1330. X        if( i == human_player ) {
  1331. X            strcpy( &(your[i][0]), "Your" );
  1332. X            strcpy( &(you[i][0]), "You" );
  1333. X        } else {
  1334. X            strcpy( &(your[i][0]), "CPU 's" );
  1335. X            strcpy( &(you[i][0]), "CPU " );
  1336. X            your[i][3] = j;
  1337. X            you[i][3] = j++;
  1338. X        }
  1339. X        plr_skills[i] = 0;
  1340. X    }
  1341. X
  1342. X    for( i = 0; i < players; i++ ) {
  1343. X        print_tiles();
  1344. X        if( i == human_player ) continue;
  1345. X        clear_prompt();
  1346. X        printw( "  Select skill level 1-%d for %s, where 1 is beginner, %d is advanced, and\n", SKILL_EXPERT, you[i], SKILL_LEVELS );
  1347. X        printw( "  %d is expert. -> ", SKILL_EXPERT );
  1348. X        refresh();
  1349. X        for( ;; ) {
  1350. X            c = getch();
  1351. X            if( c >= '1' && c <= '6' ) break;
  1352. X        }
  1353. X        plr_skills[i] = c - '0';
  1354. X    }
  1355. X
  1356. X    for( i = 0; i < players; i++ ) {
  1357. X        plr_scores[i] = 0;
  1358. X        for( j = 0; j < 7; j++ )
  1359. X            plr_tiles[i][j] = draw_tile();
  1360. X    }
  1361. X    print_tiles();
  1362. X}
  1363. X
  1364. Xend_game() {
  1365. X    int i, j;
  1366. X    int adj[4], wbs, wb[4], was, wa[4];
  1367. X    long p1;
  1368. X    FILE *fp;
  1369. X    char c;
  1370. X
  1371. X    clear_turn();
  1372. X    printw( "*** GAME OVER\n" );
  1373. X    print_tiles();
  1374. X    clear_prompt();
  1375. X    printw( "  Here are the score adjustments: " );
  1376. X    wbs = -1;
  1377. X    for( i = 0; i < players; i++ )
  1378. X        if( plr_scores[i] > wbs ) wbs = plr_scores[i];
  1379. X    for( i = 0; i < players; i++ ) {
  1380. X        if( plr_scores[i] == wbs ) wb[i] = 1;
  1381. X        else wb[i] = 0;
  1382. X    }
  1383. X    for( i = 0; i < players; i++ ) {
  1384. X        adj[i] = 1;
  1385. X        for( j = 0; j < 7; j++ ) {
  1386. X            c = plr_tiles[i][j];
  1387. X            if( c != 0 ) {
  1388. X                if( adj[i] == 1 ) adj[i] = 0;
  1389. X                if( c != CH_BL ) adj[i] -= letters[c - 'A'].points;
  1390. X            }
  1391. X        }
  1392. X    }
  1393. X    for( j = 0; j < players; j++ )
  1394. X        if( adj[j] == 1 ) break;
  1395. X    if( j < players ) {
  1396. X        adj[j] = 0;
  1397. X        for( i = 0; i < players; i++ )
  1398. X            if( i != j ) adj[j] -= adj[i];
  1399. X    }
  1400. X    for( i = 0; i < players; i++ ) {
  1401. X        move( 19 + i, 36 );
  1402. X        if( i == human_player ) addch( ' ' );
  1403. X        printw( "%s: %d", you[i], adj[i] );
  1404. X        plr_scores[i] += adj[i];
  1405. X    }
  1406. X    was = -1;
  1407. X    for( i = 0; i < players; i++ )
  1408. X        if( plr_scores[i] > was ) was = plr_scores[i];
  1409. X    for( i = 0; i < players; i++ ) {
  1410. X        if( plr_scores[i] == was ) wa[i] = 1;
  1411. X        else wa[i] = 0;
  1412. X    }
  1413. X    press_return();
  1414. X    print_tiles();
  1415. X    clear_prompt();
  1416. X    move( 20, 0 );
  1417. X    was = 0;
  1418. X    for( i = 0; i < players; i++ ) was += wa[i];
  1419. X    wbs = 0;
  1420. X    for( i = 0; i < players; i++ ) wbs += wb[i];
  1421. X    if( was == 1 || wbs == 1 ) {
  1422. X        if( was == 1 ) {
  1423. X            for( i = 0; i < players; i++ )
  1424. X                if( wa[i] == 1 ) break;
  1425. X        } else {
  1426. X            for( i = 0; i < players; i++ )
  1427. X                if( wb[i] == 1 ) break;
  1428. X        }
  1429. X        printw( "  And the winner is:  %s!", you[i] );
  1430. X    } else {
  1431. X        printw( "  It was a tie between:  " );
  1432. X        wbs = 1;
  1433. X        for( i = 0; i < players; i++ )
  1434. X            if( wa[i] == 1 ) {
  1435. X                if( wbs < was - 1 ) printw( ", " );
  1436. X                else {
  1437. X                    if( was > 2 ) printw( ", and " );
  1438. X                    else printw( " and " );
  1439. X                }
  1440. X                printw( "%s", you[i] );
  1441. X                wbs++;
  1442. X            }
  1443. X        printw( "!" );
  1444. X    }
  1445. X    refresh();
  1446. X    if( dict_changed == 1 ) {
  1447. X        press_return();
  1448. X        clear_prompt();
  1449. X        printw( "  The computer's dictionary was modified this game.\n" );
  1450. X        printw( "  Would you like to save the new dictionary (y/n)? " );
  1451. X        refresh();
  1452. X        do {
  1453. X            c = get_key();
  1454. X        } while( c != 'Y' && c != 'N' );
  1455. X        if( c == 'Y' ) {
  1456. X            printw( "\n\n  Writing new dictionary..." );
  1457. X            refresh();
  1458. X            fp = fopen( DICT_FILE, "w+" );
  1459. X            if( fp == NULL ) {
  1460. X                printw( "error writing new dictionary!\n" );
  1461. X                exit_window();
  1462. X                exit( 1 );
  1463. X            }
  1464. X            for( p1 = 0; p1 < wlen[16]; p1++ )
  1465. X                fprintf( fp, "%s\n", &(words[wptr[p1]]) );
  1466. X            fclose( fp );
  1467. X        }
  1468. X    }
  1469. X}
  1470. X
  1471. Xint main() {
  1472. X    int plr;
  1473. X    int i;
  1474. X
  1475. X    set_up_window();
  1476. X    clear();
  1477. X    printw( "*** SCRABBLE 1.21 ***\n\n" );
  1478. X
  1479. X    read_words();
  1480. X    dict_changed = 0;
  1481. X
  1482. X    clear();
  1483. X    printw( "*** SCRABBLE 1.21 ***\n\n" );
  1484. X
  1485. X    init_board();
  1486. X    seed_random();
  1487. X    print_board();
  1488. X    print_info();
  1489. X    get_num_players();
  1490. X
  1491. X    game_done = 0;
  1492. X    abort = 0;
  1493. X    do {
  1494. X        for( plr = 0; plr < players; plr++ ) {
  1495. X            clear_turn();
  1496. X            printw( "*** %s turn to play  ", your[plr] );
  1497. X            if( plr == human_player ) {
  1498. X                player_move();
  1499. X            } else {
  1500. X                computer_move( plr );
  1501. X            }
  1502. X            if( abort != 0 ) break;
  1503. X            if( game_done == 0 ) clear_rect( 1, 50, 1, 79 );
  1504. X            else {
  1505. X                move( 1, 64 );
  1506. X                printw( "Passed turns:  %d", game_done );
  1507. X            }
  1508. X            refresh();
  1509. X            if( game_done == players ) break;
  1510. X            for( i = 0; i < 7; i++ )
  1511. X                if( plr_tiles[plr][i] != 0 ) break;
  1512. X            if( i == 7 ) {
  1513. X                game_done = players;
  1514. X                break;
  1515. X            }
  1516. X        }
  1517. X    } while( game_done < players && abort == 0 );
  1518. X
  1519. X    if( abort == 0 ) end_game();
  1520. X    exit_window();
  1521. X}
  1522. END_OF_FILE
  1523. if test 7661 -ne `wc -c <'smain.c'`; then
  1524.     echo shar: \"'smain.c'\" unpacked with wrong size!
  1525. fi
  1526. # end of 'smain.c'
  1527. fi
  1528. echo shar: End of archive 18 \(of 18\).
  1529. cp /dev/null ark18isdone
  1530. MISSING=""
  1531. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ; do
  1532.     if test ! -f ark${I}isdone ; then
  1533.     MISSING="${MISSING} ${I}"
  1534.     fi
  1535. done
  1536. if test "${MISSING}" = "" ; then
  1537.     echo You have unpacked all 18 archives.
  1538.     echo "now type ./blddict.sh to build dictionary file"
  1539.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1540. else
  1541.     echo You still need to unpack the following archives:
  1542.     echo "        " ${MISSING}
  1543. fi
  1544. ##  End of shell archive.
  1545. exit 0
  1546.