NAME

Games::Literati - For word games like Literati (or Scrabble, or Words With Friends), find the best-scoring solution(s) for a board and hand of tiles.

SYNOPSIS

use Games::Literati qw/literati scrabble wordswithfriends/;
literati();
scrabble();
wordswithfriends();

DESCRIPTION

Games::Literati helps you find out all solutions for a given board and tiles. It can be used to play Scrabble, Literati, Words with Friends, or (by overriding or extending the package) other similar games.

To use this module to play the games, a minimal program such as the following can be used:

use Games::Literati qw/literati/;
literati();

Enter the data prompted then the best 10 solutions will be displayed.

Board Input

The game will prompt you for each row of the board, one row at a time

row 0:
row 1:
...
row 14:

And will expect you to enter the requested row's data. It expects one character for each column on the board. Thus, on a standard 15x15 board, it will expect each row to contain 15 characters. The `.' character represents an empty square. Individual letters (in lower case) represent tiles that have already been laid on the board. (Don't worry about indicating wild tiles just yet; that will come momentarily.) An example input row could be:

.......s.header

After requesting the last row, the Games::Literati will display the board as it received it, and ask you

Is the above correct?

At this point, it is expecting you to type either `yes' or `no'. If you answer `yes', the game will progress. If you answer `no', it will start over asking for row 0:. If you answer with anything else, it will ask you again if everything is correct.

Once you have entered `yes', Games::Literati will ask you for the coordinates of the any wild tiles already on the board

wild tiles are at:[Row1,Col1 Row2,Col2 ...]

Row# and Col# are 0-referenced, so the upper left of the board is 0,0, and the lowe right of the standard board is 14,14. Multiple wild tiles are space-separated. If there have not been any wild tiled played yet, just hit ENTER, giving it an empty input. If you have wilds, with one at one-tile diagonally from the upper right and the second two tiles diagonally from the lower-left, you would enter

1,13 12,2

If your coordinates resolve to an empty tile (.) or a tile that's not on the board, you will be notified:

Invalid wild tile positions, please re-enter.
wild tiles are at:[Row1,Col1 Row2,Col2 ...]

Finally, after receiving a valid input for the wilds, Games::Literati will ask you for what tiles are in your hand.

Enter tiles:

You should enter anywhere from 1 to 7 tiles (for a standard game). Letter tiles should be in lower case; wild tiles are indicated by a question mark `?'.

?omment

It is recommended to pre-write everything into a file. and run the program via command-line. See the "SAMPLE TURNS", below.

SAMPLE TURNS

These samples will use input file t, to help ensure the correct input format.

As described above, the first 15 lines represent board situation, followed with "yes", followed by wild tile positions, if none, place a empty line here, then followed by tiles (can be less than 7), use ? to represent wild tiles. Please make sure the last line in your file ends with a full NEWLINE character on your system (it's safest to add a blank line after the list of tiles).

Make sure to put `./wordlist' in the working directory when running the program, or to set $WordFile to the path to your dictionary.

First Turn

Create game file named t, like this:

...............
...............
...............
...............
...............
...............
...............
...............
...............
...............
...............
...............
...............
...............
...............
yes

?omment
<file end with a CR>

Run the game from the command line:

$perl -e'use Games::Literati qw(literati); literati()' < t

The output will be (depending on word list)

[...]
using 7 tiles:
(47)    row 7 become: 'comment' starting at column 1 (BINGO!!!!)
(47)    row 7 become: 'memento' starting at column 1 (BINGO!!!!)
(47)    row 7 become: 'metonym' starting at column 1 (BINGO!!!!)
(47)    row 7 become: 'momenta' starting at column 1 (BINGO!!!!)
(47)    row 7 become: 'momento' starting at column 1 (BINGO!!!!)
[...]
Possible Ten Best Solution 1: row 7 become: 'metonym' starting at column 5 (BINGO!!!!) using 7 tile(s), score 47
Possible Ten Best Solution 2: row 7 become: 'moments' starting at column 6 (BINGO!!!!) using 7 tile(s), score 47
Possible Ten Best Solution 3: row 7 become: 'momenta' starting at column 6 (BINGO!!!!) using 7 tile(s), score 47
Possible Ten Best Solution 4: column 7 become: 'omentum' starting at row 7 (BINGO!!!!) using 7 tile(s), score 47
Possible Ten Best Solution 5: column 7 become: 'memento' starting at row 7 (BINGO!!!!) using 7 tile(s), score 47
Possible Ten Best Solution 6: column 7 become: 'memento' starting at row 1 (BINGO!!!!) using 7 tile(s), score 47
Possible Ten Best Solution 7: row 7 become: 'comment' starting at column 3 (BINGO!!!!) using 7 tile(s), score 47
Possible Ten Best Solution 8: row 7 become: 'omentum' starting at column 7 (BINGO!!!!) using 7 tile(s), score 47
Possible Ten Best Solution 9: row 7 become: 'omentum' starting at column 1 (BINGO!!!!) using 7 tile(s), score 47
Possible Ten Best Solution 10: column 7 become: 'memento' starting at row 5 (BINGO!!!!) using 7 tile(s), score 47

If you run the same board with the Scrabble engine:

$ perl -e'use Games::Literati qw(scrabble);scrabble()' < t

You will get

[...]
(76)    row 7 become: 'comment' starting at column 1 (BINGO!!!!)
(76)    row 7 become: 'memento' starting at column 1 (BINGO!!!!)
(72)    row 7 become: 'metonym' starting at column 1 (BINGO!!!!)
[...]
Possible Ten Best Solution 1: column 7 become: 'memento' starting at row 1 (BINGO!!!!) using 7 tile(s), score 76
Possible Ten Best Solution 2: column 7 become: 'momento' starting at row 1 (BINGO!!!!) using 7 tile(s), score 76
Possible Ten Best Solution 3: row 7 become: 'metonym' starting at column 5 (BINGO!!!!) using 7 tile(s), score 76
Possible Ten Best Solution 4: row 7 become: 'momenta' starting at column 1 (BINGO!!!!) using 7 tile(s), score 76
[...]

Intermediate Turn

For most turns, you input file the t containing a partially populated game, such as:

...............
...............
...............
.......c.......
......ai.......
.......s.header
.......t....r..
...jurors..soup
.......o....p.h
.upsilon.f..pea
.......speering
.........s..n.e
.........t..g..
.........e.....
........broils.
yes
7,8 10,14 7,14
eurmsss
<file end with a CR>

Run the game from the command line:

perl -e'use Games::Literati qw(literati); literati()' < t

The output will be (depending on word list)

[....]
using 7 tiles:
using 6 tiles:
(9)     row 3 become: 'cussers' starting at column 8
(9)     row 12 become: 'russets' starting at column 4
using 5 tiles:
(8)     row 3 become: 'cruses' starting at column 8
(8)     row 3 become: 'curses' starting at column 8

[...]
Possible Ten Best Solution 1: column 3 become: 'susses' starting at row 10  using 5 tile(s), score 24
Possible Ten Best Solution 2: column 3 become: 'serums' starting at row 10  using 5 tile(s), score 24
[...]

If you run the same board with the Scrabble engine:

perl -e'use Games::Literati qw(scrabble); scrabble()' < t

You will get

[...]
Possible Ten Best Solution 1: row 14 become: 'embroils' starting at column 6  using 2 tile(s), score 36
Possible Ten Best Solution 2: row 6 become: 'stems' starting at column 6  using 4 tile(s), score 23
Possible Ten Best Solution 3: column 2 become: 'spumes' starting at row 8  using 5 tile(s), score 22
[...]

Good luck!:)

PUBLIC FUNCTIONS

literati([min[, max]])
scrabble([min[, max]])
wordswithfriends([min[, max]])

These functions execute each of the games. As shown in the "SYNOPSIS" and "SAMPLE TURNS", each turn generally requires just one call to the specific game function. There are two optional arguments:

min

The minimum number of tiles to play, which defaults to 1. If you want to only allow your computer player (ie, the Games::Literati module) to play 3 or more tiles, you would set min=3.

If you specify 0 or negative, the magic of perl will occur, and it will internally use the default of min=1.

max

The maximum number of tiles to play, which defaults to 7. If you want to restrict your computer player to play 5 or fewer tiles, you would set max=5.

If you want to specify max, you must also specify a min.

If you specify max less than min, Games::Literati will not play any tiles.

Thus, specifying literati(3,5) will restrict the computer Literati player to using 3, 4, or 5 tiles on this turn.

find(\%args) or find($args)

Finds possible valid words, based on the hashref provided. Generally, this is not needed, but it will give you access to a function similar to the internal function used by the game functions to find words, but providing extra hints to the user.

\%args or $args

A reference to a hash containing the keys letters, re, and internal.

$args->{etters}

This is the list of letters available to play.

$args->{re}

This is a string which will be evaluated into a perl regular expression that is evaluated to determine. Note: this requres the full regex syntax, so use '/c.t/' to indicate you are looking for valid letters to put between a `c' and a `t'.

$args->{internal}

(Boolean) If set to a true value, find() will be quiet (not print to standard output) and will return an array-reference of possible solutions. If false, find() will print suggested words to STDOUT.

PUBLIC VARIABLES

These variables are exportable, so can be fully qualified as %Games::Literati::valid, or if included in the export list when you use the module, you can reference them directly, as

use Games::Literati qw/literati $WordFile/;
$WordFile = '/usr/share/dict/words';
$WordFile

The $WordFile points to a text document, which lists one valid word per line.

The variable defaults to './wordfile'. (in version 0.01, that was the only value, and there was no variable.)

You may change the default wordfile by setting this variable to the path to find the list.

$Games::Literati::WordFile = '/usr/dict/words';

Sources for $WordFile

  • Your OS may include a builtin dictionary (such as /usr/dict/words or /usr/share/dict/words). Beware: these often have numbers or punctuation (periods, hyphens), which may interfere with proper functioning

  • ENABLE (Enhanced North American Benchmark Lexicon): a public-domain list with more than 173,000 words, available at a variety of locations, including in an old google code repository as "enable1.txt" The ENABLE dictionary is used by a variety of online tools, and is the primary source for the official Words With Friends dictionary.

  • Anthony Tan has delved into the Words With Friends app, and has compared their internal list to the original ENABLE list at http://www.greenworm.net/notes/2011/05/02/words-friends-wordlist

If you want to use one of the lists from a website, you will need to download the list to a file, and set $WordFile to the path to your downloaded list.

%valid

For each word that Games::Literati parses from the $WordList file, it will set $valid{word} to 1.

CUSTOMIZATION

You can override the private internal functions to get your own functionality. This might be useful if you would like to make a sub-package (maybe that use a GUI interface), or if you'd like to build a script on your webserver that will host a game where you can play against Games::Literati.

These brief notes are intended as hints for how to get started.

For a sub-package, Games::Literati::MyGooeyInterface, you could inherit from Games::Literati, and define your own package-specific input() and output() functions, which you could then ask if you could add to the Games::Literati distribution.

For a standalone application, mywebapp.pl, you could just use Games::Literati and override the default functions, such as defining your own sub Games::Literati::display function.

sub display()

This subroutine displays the current state of the board.

By default, it outputs the board to STDOUT as a 15x15 grid:

...............
...............
...............
...............
...............
...............
...............
...............
...............
...............
...............
...............
...............
...............
...............

Override the subroutine to change the style of output

sub Games::Literati::display { # overrides default behavior
    my $f = shift;

    print "\nBoard:\n";
    for my $row (0..14) {
        print sprintf "%02d ", $row if $f;
        for my $col (0..14) {
            # use _ instead of .
            my $c = $Games::Literati::onboard[$row][$col] || '_';
            $c =~ s/\./_/g;
            print $c;
        }
        print "\n";
    }
    print "\n";
}
input()

Ask for the current board data: existing tile positions, wild-tile positions, and the tiles in your hand, and initiate the search for valid words using the existing board and your hand.

Overriding sub Games::Literati::input (similarly to display, above) will allow a change in input method, such as via CGI. Look at the source code for the default input(), so you know what globals need to be set, and what to return.

BUGS AND FEATURE REQUESTS

Please report any bugs or feature requests emailing bug-Games-Literati AT rt.cpan.org or thru the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Games-Literati.

AUTHOR

Chicheng Zhang <chichengzhang AT hotmail.com> wrote the original code.

Peter C. Jones <petercj AT cpan.org> has added various feature and made bug fixes.

LICENSE AND COPYRIGHT

Copyright (c) 2003, Chicheng Zhang. Copyright (C) 2016 by Peter C. Jones

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.