AI Gaming
Lexico is based on the classic family game where you take turns to place tiles on a board to create words. The more words you create, the more points you will get!


The aim of the game is to have more points than your opponent at the end of the game. You score points by placing tiles from your hand onto empty spaces on the board when it's your turn.
Each new line of words (top to bottom and left to right) created on your turn must spell out a word, and you get points for all of the words you create. Each letter has a points value and for each word created you get the sum of the points of the letters in that word.
The tiles you place must line up in a single row or column, and must be connected along that row or column (although tiles already on the board can connect them). At least one of the tiles you place must be adjacent to a tile already on the board.
Once you've played your tiles onto the board, you will receive new tiles from the bag of tiles so that you always have 7 tiles in hand (if there are enough tiles in the bag). If you play all 7 tiles from your hand in one turn, you get an additional 50 points added to your score.
Instead of playing tiles on your turn, you can choose to pass instead. You won't score any points, but you can exchange tiles with random ones from the bag. However, you cannot exchange on the first go or when there are fewer than 7 tiles in the bag.
The game ends when there are no more tiles left in the bag and either you or your opponent runs out of tiles, or when both players pass and exchange no tiles. The scores are then compared to decide who is the winner.

The First Turn

On the first turn your word must cover up the centre square of the board and it must be at least three letters long.

Blank tiles

Blank tiles can take the form of any letter, but don't give you any points. You play them in the same way as any other tile, but must indicate what letter it represents. It will be that letter for the rest of the game, but with a points value of 0.
Blank tiles are only included in the Multipliers version of the game.


In the Multipliers version of the game, there are four types of multipliers:
  • Double Letter - This doubles the points value of the tile placed on top of it.
  • Double Word - This doubles the points value of the word or words created on top of it.
  • Triple Letter - This triples the points value of the tile placed on top of it.
  • Triple Word - This triples the points value of the word or words created on top of it.
Each Multiplier is nullified the turn after it has been used - on your turn you can create multiple words on a multiplier to get even more bonus points but after you have used it, it will not provide any bonus points.


In Lexico there are a finite number of possible moves that you can make on your turn. A perfect bot with a basic strategy would be one that compares each of these possible moves to find the one that gives you the highest number of points that turn.
However, this may be extremely difficult to do before time runs out on your turn. Because of this, optimizing your bot would mean efficiently finding as many moves as possible before the timer runs out.

Basic strategy

Finding possible moves can be broken down into two jobs: finding positions for words and finding the words themselves. For the first job, having been given a board, we want to find all the spaces adjacent to the current tiles on the board and the directions that words can go using that space.
There are many ways to do this, such as randomly choosing a coordinate and checking to see whether it is empty and adjacent to a square. Another way is to compare the previous board to the current one, so you can keep a constantly updating list of possible tile positions. Try to find as efficient a method as possible!
The second job involves using the tiles in hand and the letters available on the board to find words in the dictionary provided. However, checking if each word can be placed on the board takes a long time- there are over 150,000 words! Instead, try to reduce the number of words checked by altering the size of the dictionary- for example by the first letter.
It's also extremely important that you don't go over the ResponseDeadline. If you go over the time limit you automatically lose. Therefore, it's a good idea to check throughout the calculate_move() function whether you're getting close to the deadline. If you are, make sure you give your best move so far.


There are lots of tactics within Lexico to optimise your win rate. You'd assume that passing your go or exchanging tiles is never a good option, but it can improve your odds of playing all seven tiles in one move, or getting one of the multipliers.
Keeping certain types of letters is also important, as you don't want to end up with a hand of all vowels or all consonants. Another good keep is the letter 'S', as this can be put on the end of words already on the board but also on your (perpendicular) word, scoring a large number of points.
Keeping Blank tiles is also very important, as these can lead to a 7 tile play, and an extra 50 points!

Advanced strategies

As the game goes on, there are more possible places for words and more tiles to interact with, so finding the optimal play often takes longer. A useful thing to do is to use the spare time you have on your first few turns to help you out on the later ones.
This can be saving the board state in persistent_data so searching for spaces takes less time later on, or sorting the dictionary in different ways to help you find the best words quickly.


In the Multipliers version of the game, getting the biggest words on the triple or double words spaces is likely to win you the game, especially when combined with triple or double letter spaces. However, you also want to consider not letting your opponent use those tiles- try to avoid putting useful letters near those multipliers.

Programmer's Reference


An example of the gamestate JSON
'Board': [
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', 'E', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
['D', ' ', ' ', 'G', 'I', 'N', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
['I', ' ', ' ', 'D', ' ', 'I', ' ', ' ', 'O', 'D', 'I', 'O', 'U', 'S', ' '],
['R', 'A', 'V', 'E', ' ', 'A', ' ', 'M', ' ', 'E', ' ', ' ', ' ', ' ', ' '],
['A', ' ', ' ', ' ', ' ', 'T', 'W', 'I', 'N', 'E', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', 'L', 'I', 'M', 'B', ' ', 'H', ' ', 'R', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', 'O', ' ', ' ', 'O', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', 'O', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', 'F', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
'IsMover': True,
'MyScore': 19,
"Opponent'sScore": 54,
'ResponseDeadline': 1544012659463,
'MoveTime': 5000,
'Dictionary': '',
'TileScores': {
'A': 1,
'B': 3,
'C': 3,
'D': 2,
'E': 1,
'F': 4,
'G': 2,
'H': 4,
'I': 1,
'J': 8,
'K': 5,
'L': 1,
'M': 3,
'N': 1,
'O': 1,
'P': 3,
'Q': 10,
'R': 1,
'S': 1,
'T': 1,
'U': 1,
'V': 4,
'W': 4,
'X': 8,
'Y': 4,
'Z': 10
'BlanksList': [],
'NumberOfTilesInBag': 47,
'DoubleWordList': [],
'DoubleLetterList': [],
'TripleWordList': [],
'TripleLetterList': [],
'FirstGo': False,
'MyHand': ['T', 'N', 'F', 'S', 'L', 'P', 'I'],
'GameStatus': 'RUNNING',
'GameId': 2398845,
'OpponentId': 'housebot-practise'
A description of each field in the gamestate
A list of rows, where each row is a list of strings. This represents the state of the board
A Boolean value indicating whether it is your turn to move. It will always be true when in the calculate_move() function
The epoch time, in milliseconds, that a successful move has to be sent and received by to prevent you from timing out
Your current hand of tiles. These are the tiles you can play on the board, or exchange with tiles in the bag
The number of tiles left in the bag
The time you get to make a move, in milliseconds
The link to the dictionary used in the game
A list of the positions of blank tiles that have been played on the board
A list of the positions of double word spaces on the board.
A list of the positions of double letter spaces on the board
A list of the positions of triple word spaces on the board
A list of the positions of triple letter spaces on the board
A Boolean value indicating whether it is the first turn of the game
A dictionary of points you get when you place a letter to create a word
Your current score in this game, which increases whenever you place tiles to create a word. The player with the largest score at the end wins
Your opponent's current score in this game, which increased whenever they place tiles to create a word. The player with the largest score at the end wins
A string that will have value "RUNNING" if the game is in progress or a reason the game has ended otherwise
An integer representing the unique game id for the current game
A string containing the name of your opponent

Understanding the board

The strings on the board contain either " " if the position is blank or a capital letter, for example "A", if a tile has been placed there.
The indices of the board are as follows:
board[y][x] denotes the position or square (x+1,y+1) on the board, or the intersection of the y-th row with the x-th column. For example, the middle of the board (in the 15x15 version) is board[7][7], and the bottom right-hand corner is board[0][14].

Making a Valid Move

The value you have to return from the calculate_move() function is a list. The first entry in that list is a list of the tiles in your hand you are either playing or exchanging, e.g. ["A","B","C"].
The second entry in that list is a list of the corresponding positions (which are lists of length 2) of each of those tiles, e.g. [[6,7],[7,7],[8,7]]. The first value in each coordinate is the x-value, and the second is the y-value.
If you choose to pass your turn rather than play tiles, this second entry must be ["Pass"]. If you are playing the Multipliers Game Style with Blank Tiles, the value of these blanks must be added to a third entry of the output, e.g. ["X"].
Here are three examples of valid moves:
[["C", "A", "R"], [[6,7], [7,7], [8,7]]]
[["C", "A", "R"], ["Pass"]]
[["C", "A", "Blank"], [[6,7], [7,7], [8,7]],["R"]]
Copy link
The First Turn
Blank tiles
Basic strategy
Advanced strategies
Programmer's Reference
Understanding the board
Making a Valid Move