Lesson learned while building a bot to play Go in Kotlin. Performance optimizations, kotlin idioms, MCTS algoritm and why Go is so difficult for computer to master.
1. Go, Kotlin Go!
Go is an abstract strategy board game for
two players, in which the aim is to surround
more territory than the opponent.
The game was invented in ancient China more
than 2,500 years ago and is believed to be
the oldest board game continuously played
today.
The game reached Japan in the 7th century CE
—where it is called go ( 碁 ) or igo ( 囲碁 ).
The modern version of the game as we know it
today was formalized in Japan in the 15th
century.
4. Rules
At the beginning of the game, the
board is empty.
One player takes the black
stones, the other player the
white ones.
The player with the black stones
makes the first move.
A move is made by placing a stone
on an interesection.
A player can play on any
unoccupied intersection he wants
to.
A stone does not move after being
played, unless it is captured and
taken off the board.
The previous board position
cannot be recreated.
5. Eyes and false eyes
There is no special rule for life and death of
groups, they just emerge from capture rule.
How cool is that?
Diagrams from https://senseis.xmp.net/
6. Computer Go
Nice client
https://sabaki.yichuanshen.de/
Strongest Open Source Go program
http://pachi.or.cz/
DeepLearning Open Source
https://github.com/gcp/leela-zero
Strongest commercial Go program
https://www.remi-coulom.fr/CrazyStone/
Old generation Open Source
https://www.gnu.org/software/gnugo/
7. Deep Learning and the Game of Go opens
up the world of deep learning and AI by
teaching you to build your own Go-
playing machine. You'll explore key deep
learning ideas like neural networks and
reinforcement learning and maybe even
step up your Go game a notch or two. AI
experts and Go enthusiasts Max Pumperla
and Kevin Ferguson take you every step
of the way as you build your Go bot and
train it from eternal loser to hardened
Go player.
https://github.com/uberto/kakomu
I think that this Python code
would look better in Kotlin...
8. KAKOMU ( 囲む )
https://github.com/uberto/kakomu
In Japanese it means “to surround” and the
ideogram is the same that in the game of Go
First commit 2nd Jan 2018
42 classes and about 700 loc (excluding tests)
It’s able to play at a intermediate level on a
9x9 board
Next big feature will be DeepLearning support
9. Lessons Learned
●
Don’t fear the ?
●
Avoid !! at any cost
●
Immutability is nice but…
●
Algebraic Data Types to
avoid if
●
Premature Optimization
is...
●
Kotlin is awesome!
10. How to capture?
Stone: each position on the board can be empty|white|black
String: a set of stones which are in contact
Liberties: the empty positions touched by a string
Group: a group of strings that “work together”. Computer
don’t care about it.
Look at code Board.placeStone()
11.
12. How to decide who won?
A B C D E F G H J
9 . x x x o . o . o 9
8 x x x o o o o o . 8
7 . x x x o o . o o 7
6 x x x o o o o . o 6
5 . x x x x x o o o 5
4 x x x x x o o o . 4
3 x . x . x x o o o 3
2 x x . x x x x x o 2
1 x . x x . x o o o 1
A B C D E F G H J
Final score black: 45 white: 36
13. Minimax
Minimax algorithm with
alternate moves. A minimax
algorithm is a recursive
algorithm for choosing the
next move in an n-player
game, usually a two-player
game. A value is associated
with each position or state
of the game.
14. AlphaBeta pruning
The benefit of alpha–beta
pruning lies in the fact that
branches of the search tree can
be eliminated. This way, the
search time can be limited to
the 'more promising' subtree,
and a deeper search can be
performed in the same time.
The optimization reduces the
effective depth to slightly more
than half that of simple minimax
if the nodes are evaluated in an
optimal or near optimal order
(best choice for side on move
ordered first at each node).
15. Monte Carlo Tree Search
The focus of Monte Carlo tree search is on the analysis of the most
promising moves, expanding the search tree based on random sampling
of the search space. The application of Monte Carlo tree search in
games is based on many playouts. In each playout, the game is played
out to the very end by selecting moves at random. The final game
result of each playout is then used to weight the nodes in the game
tree so that better nodes are more likely to be chosen in future
playouts.
16. Performance
Timings for a complete rollout from start single thread
on my laptop i7 2Ghz (in millisec on 9x9 and 19x19)
10 160 validmove without deepcopy
6 65 immutable goStrings
3.5 38 neighbors map
1.5 31 faster isAnEye
1.3 27 simpleKo
1.25 25 selectMove returning State
0.7 12 remove System.nanotime
0.5 4.5 RandomBot evaluating single move
0.33 2.4 single swap instead of shuffle
0.27 2.1 array instead of map for winCount