This is an excellent overall implementation that's easy to use with incredibly fast results. The gaddag data structure is well implemented and very quickly finds all intersecting word options. However, the design of calculateHighestScorePlacement is incomplete. In only looks down and to the right of existing empty space to find anchor for legal moves. In scrabble, it is legal to hook words to tiles on the left or from above and these legal moves are missed in the design. As a result, calculateHighestScorePlacement doesn't always find the highest scoring option.
Below is a good example. The following board was used to call gaddagcommandline with standard Scrabble game board setup with Triple Word squares in corners and middle of each edge. The text file I provided for board as input was without header (i.e. started with 01|).
1 2 3 4 5 6 7 8 9.0.1.2.3.4.5
01| H G I N S|
02| E P O |
03| M I R I E S T |
04| V E X I O E |
05| S U C C O R Y P |
06| A A |
07| T D |
08| I N A N E R S |
09| D |
10| |
11| |
12| |
13| |
14| |
15| |
The response for Rack=HIKEYUE is CHUNKY @7,6 for 24 points.
However, words like YEH@15,6 or SH/HIKE@15,8 are far better plays at twice the points (they are word options adjacent to the ending of NOTEPADS). Because these words are found by looking to on hooking on a tile to the left of an empty cell, they are never found in the search.
The implementation did return NOTEPADS for the previous move so generally works well when best available words are down and to the right of an empty tile.
Here is the output that was returned for above example:
19:43:07.007 [main] DEBUG com.wordswithcheats.board.Board - TOTAL: 26
19:43:07.007 [main] INFO com.wordswithcheats.board.Board - 45 tiles placed
19:43:07.009 [main] DEBUG c.w.board.format.SimpleBoardFormat - Line number prefix: #
19:43:07.009 [main] DEBUG c.w.board.format.SimpleBoardFormat - Line number suffix: :
19:43:07.009 [main] DEBUG c.w.board.format.SimpleBoardFormat - * * H G I N S
19:43:07.009 [main] DEBUG c.w.board.format.SimpleBoardFormat - * * E P O
19:43:07.009 [main] DEBUG c.w.board.format.SimpleBoardFormat - * * M I R I E S T
19:43:07.009 [main] DEBUG c.w.board.format.SimpleBoardFormat - * V E X I O * E *
19:43:07.009 [main] DEBUG c.w.board.format.SimpleBoardFormat - S U C C O R Y P
19:43:07.009 [main] DEBUG c.w.board.format.SimpleBoardFormat - * * H A A
19:43:07.009 [main] DEBUG c.w.board.format.SimpleBoardFormat - * U * T * D
19:43:07.009 [main] DEBUG c.w.board.format.SimpleBoardFormat - * * I N A N E R * S *
19:43:07.009 [main] DEBUG c.w.board.format.SimpleBoardFormat - * K * D *
19:43:07.009 [main] DEBUG c.w.board.format.SimpleBoardFormat - * * Y * *
19:43:07.009 [main] DEBUG c.w.board.format.SimpleBoardFormat - * *
19:43:07.009 [main] DEBUG c.w.board.format.SimpleBoardFormat - * * * * *
19:43:07.009 [main] DEBUG c.w.board.format.SimpleBoardFormat - * * * *
19:43:07.009 [main] DEBUG c.w.board.format.SimpleBoardFormat - * * * *
19:43:07.009 [main] DEBUG c.w.board.format.SimpleBoardFormat - * * * * *
-
-
V E X I O * E *
S U C C O R Y P
-
"CHUNKY" was played for 26 points.
An additional example of incomplete search would be words from above that come down and end on an existing tile. For example, if the first word is "TENT" and the next player rack includes ZEN,
..Z
TENT
..N
will be found but following option is never evaluated because only down and to the right is scanned:
.....Z
.....E
TENT
I've started to debug and I am working to improve design in calculateHighestScorePlacement for a more complete search.