From 4c86839a5fcc14594094aea52a5d5856c5e11e4a Mon Sep 17 00:00:00 2001
From: wrongu <rlange@ur.rochester.edu>
Date: Wed, 10 Feb 2016 12:28:25 -0500
Subject: [PATCH] fresh start: project skeleton

---
 .gitignore                                         |   3 +
 .gitmodules                                        |   3 +
 AlphaGo/__init__.py                                |   0
 AlphaGo/ai.py                                      |   0
 AlphaGo/go.py                                      |  83 +++++++
 AlphaGo/mcts.py                                    |   5 +
 AlphaGo/models/__init__.py                         |   0
 AlphaGo/models/policy.py                           |   0
 AlphaGo/models/value.py                            |   0
 AlphaGo/training/gen_value_positions.py            |   0
 AlphaGo/training/train_rl.py                       |   0
 AlphaGo/training/train_supervised.py               |   0
 AlphaGo/training/train_value.py                    |   0
 CONTRIBUTING.md                                    |  27 ++
 LICENSE                                            |  21 ++
 README.md                                          |   3 +
 data/expert_play/friday_tournament.sgf             | 109 ++++++++
 data/expert_play/monday_tournament.sgf             | 275 +++++++++++++++++++++
 data/expert_play/thursday_tournament.sgf           |  84 +++++++
 data/expert_play/tuesday_tournament.sgf            |  93 +++++++
 data/expert_play/wednesday_tournament.sgf          |  85 +++++++
 data/self_play/s_a_z_tuples_here_format_TBD        |   0
 .../h5_files_here_by_hyperparamer_UID              |   0
 interface/client/simple_client_here_possibly_Wgo   |   0
 interface/opponents/pachi/pachi.py                 |   0
 interface/server/simple_server_here                |   0
 requirements.txt                                   |   7 +
 tests/__init__.py                                  |   0
 tests/test_gamestate.py                            |  73 ++++++
 29 files changed, 871 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 .gitmodules
 create mode 100644 AlphaGo/__init__.py
 create mode 100644 AlphaGo/ai.py
 create mode 100644 AlphaGo/go.py
 create mode 100644 AlphaGo/mcts.py
 create mode 100644 AlphaGo/models/__init__.py
 create mode 100644 AlphaGo/models/policy.py
 create mode 100644 AlphaGo/models/value.py
 create mode 100644 AlphaGo/training/gen_value_positions.py
 create mode 100644 AlphaGo/training/train_rl.py
 create mode 100644 AlphaGo/training/train_supervised.py
 create mode 100644 AlphaGo/training/train_value.py
 create mode 100644 CONTRIBUTING.md
 create mode 100644 LICENSE
 create mode 100644 README.md
 create mode 100644 data/expert_play/friday_tournament.sgf
 create mode 100644 data/expert_play/monday_tournament.sgf
 create mode 100644 data/expert_play/thursday_tournament.sgf
 create mode 100644 data/expert_play/tuesday_tournament.sgf
 create mode 100644 data/expert_play/wednesday_tournament.sgf
 create mode 100644 data/self_play/s_a_z_tuples_here_format_TBD
 create mode 100644 data/trained_models/h5_files_here_by_hyperparamer_UID
 create mode 100644 interface/client/simple_client_here_possibly_Wgo
 create mode 100644 interface/opponents/pachi/pachi.py
 create mode 100644 interface/server/simple_server_here
 create mode 100644 requirements.txt
 create mode 100644 tests/__init__.py
 create mode 100644 tests/test_gamestate.py

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2b359c3
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+*.pyc
+*.npy
+*.h5
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..11fba82
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "interface/opponents/pachi/pachi"]
+	path = interface/opponents/pachi/pachi
+	url = https://github.com/pasky/pachi
diff --git a/AlphaGo/__init__.py b/AlphaGo/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/AlphaGo/ai.py b/AlphaGo/ai.py
new file mode 100644
index 0000000..e69de29
diff --git a/AlphaGo/go.py b/AlphaGo/go.py
new file mode 100644
index 0000000..6a6deff
--- /dev/null
+++ b/AlphaGo/go.py
@@ -0,0 +1,83 @@
+import numpy as np
+
+WHITE = -1
+BLACK = +1
+EMPTY = 0
+
+class GameState(object):
+	"""State of a game of Go and some basic functions to interact with it
+	"""
+
+	def __init__(self, size=19):
+		self.board = np.zeros((size, size))
+		self.board.fill(EMPTY)
+		self.size = size
+		self.turns_played = 0
+		self.current_player = BLACK
+		
+	def copy(self):
+		"""get a copy of this Game state
+		"""
+		other = GameState(self.size)
+		other.board = self.board.copy()
+		other.turns_played = self.turns_played
+		other.current_player = self.current_player
+		return other
+
+	def is_legal(self, action):
+		"""determine if the given action (x,y tuple) is a legal move
+		"""
+		(x,y) = action
+		empty = self.board[x][y] == EMPTY
+		on_board = x >= 0 and y >= 0 and x < self.size and y < self.size
+		suicide = False # todo
+		ko = False # todo
+		return empty and on_board and (not suicide) and (not ko)
+
+	def do_move(self, action):
+		"""Play current_player's color at (x,y)
+
+		If it is a legal move, current_player switches to the other player
+		If not, an IllegalMove exception is raised
+		"""
+		(x,y) = action
+		if self.is_legal((x,y)):
+			self.board[x][y] = self.current_player
+			self.current_player = -self.current_player
+			self.turns_played += 1
+		else:
+			raise IllegalMove(str((x,y)))
+
+	def symmetries(self):
+		"""returns a list of 8 GameState objects:
+		all reflections and rotations of the current board
+
+		does not check for duplicates
+		"""
+		copies = [self.copy() for i in range(8)]
+		# copies[0] is the original.
+		# rotate CCW 90
+		copies[1].board = np.rot90(self.board,1)
+		# rotate 180
+		copies[2].board = np.rot90(self.board,2)
+		# rotate CCW 270
+		copies[3].board = np.rot90(self.board,3)
+		# mirror left-right
+		copies[4].board = np.fliplr(self.board)
+		# mirror up-down
+		copies[5].board = np.flipud(self.board)
+		# mirror \ diagonal
+		copies[6].board = np.transpose(self.board)
+		# mirror / diagonal (equivalently: rotate 90 CCW then flip LR)
+		copies[7].board = np.fliplr(copies[1].board)
+		return copies
+
+	def from_sgf(self, sgf_string):
+		raise NotImplementedError()
+
+	def to_sgf(self, sgf_string):
+		raise NotImplementedError()
+
+
+class IllegalMove(Exception):
+	pass
\ No newline at end of file
diff --git a/AlphaGo/mcts.py b/AlphaGo/mcts.py
new file mode 100644
index 0000000..27f16d1
--- /dev/null
+++ b/AlphaGo/mcts.py
@@ -0,0 +1,5 @@
+class MCTS(object):
+	pass
+
+class ParallelMCTS(MCTS):
+	pass
\ No newline at end of file
diff --git a/AlphaGo/models/__init__.py b/AlphaGo/models/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/AlphaGo/models/policy.py b/AlphaGo/models/policy.py
new file mode 100644
index 0000000..e69de29
diff --git a/AlphaGo/models/value.py b/AlphaGo/models/value.py
new file mode 100644
index 0000000..e69de29
diff --git a/AlphaGo/training/gen_value_positions.py b/AlphaGo/training/gen_value_positions.py
new file mode 100644
index 0000000..e69de29
diff --git a/AlphaGo/training/train_rl.py b/AlphaGo/training/train_rl.py
new file mode 100644
index 0000000..e69de29
diff --git a/AlphaGo/training/train_supervised.py b/AlphaGo/training/train_supervised.py
new file mode 100644
index 0000000..e69de29
diff --git a/AlphaGo/training/train_value.py b/AlphaGo/training/train_value.py
new file mode 100644
index 0000000..e69de29
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..e0aa684
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,27 @@
+## Git guide for this project
+
+Get familiar with git's collaboration model - there are 
+[plenty](http://rogerdudler.github.io/git-guide/) 
+[of](https://guides.github.com/introduction/flow/) 
+[resources](https://www.atlassian.com/git/tutorials/syncing) 
+for this!
+
+Fork this repository, and push all your changes to your copy. Make sure your branch is up to date with the central repository before making a pull request. [Git-scm](https://git-scm.com/book/en/v2/Distributed-Git-Distributed-Workflows#Integration-Manager-Workflow) describes this model well.
+
+Follow these guidelines in particular:
+
+1. keep `upstream/master` functional
+1. write useful commit messages
+1. `commit --amend` or `rebase` to avoid publishing a series of "oops" commits (better done on your own branch, not `master`) ([read this](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History))
+1. ..but don't modify published history
+1. prefer `rebase master` to `merge master`, again for the sake of keeping histories clean. Don't do this if you're not totally comfortable with how `rebase` works.
+1. track issues via GitHub's tools
+
+## Coding guide
+
+We are using Python 2.7. I recommend using `virtualenv` to set up an environment; [requirements.txt](requirements.txt) contains the necessary python modules. Beyond that, follow these guidelines:
+
+1. remember that ["code is read more often than it is written"](https://www.python.org/dev/peps/pep-0008)
+1. avoid premature optimization. instead, be pedantic and clear with code and we will make targeted optimizations later using a profiler
+1. write [tests](https://docs.python.org/2/library/unittest.html). These are scripts that essentially try to break your own code and make sure your classes and functions can handle what is thrown at them
+1. [document](http://epydoc.sourceforge.net/docstrings.html) every class and function, comment liberally
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..5232026
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 University of Rochester
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..020a87f
--- /dev/null
+++ b/README.md
@@ -0,0 +1,3 @@
+# AlphaGoReplication
+
+A replication of DeepMind's 2016 Nature publication, "Mastering the game of Go with deep neural networks and tree search," details of which can be found [on their website](http://deepmind.com/alpha-go.html).
diff --git a/data/expert_play/friday_tournament.sgf b/data/expert_play/friday_tournament.sgf
new file mode 100644
index 0000000..95c8c04
--- /dev/null
+++ b/data/expert_play/friday_tournament.sgf
@@ -0,0 +1,109 @@
+(;PB[Fan Hui]PW[AlphaGo]KM[7.5]HA[0]SZ[19]TM[3600]OT[1 moves / 30 sec]RU[Chinese]RE[W+R]
+;B[dp]
+;W[pp];B[cd]
+;W[pd];B[nc]
+;W[qf];B[ic]
+;W[cj];B[ci]
+;W[di];B[ch]
+;W[dj];B[dh]
+;W[cn];B[ei]
+;W[fq];B[eo]
+;W[cq];B[cl]
+;W[dl];B[cp]
+;W[dq];B[dm]
+;W[cm];B[el]
+;W[dk];B[bl]
+;W[bk];B[dn]
+;W[bm];B[gp]
+;W[gq];B[hp]
+;W[iq];B[pb]
+;W[qc];B[ld]
+;W[ec];B[dc]
+;W[db];B[ed]
+;W[cc];B[dd]
+;W[bb];B[eb]
+;W[fc];B[fb]
+;W[bd];B[da]
+;W[cb];B[be]
+;W[ac];B[ek]
+;W[bi];B[bh]
+;W[fd];B[gb]
+;W[id];B[jd]
+;W[hc];B[hb]
+;W[jc];B[ib]
+;W[md];B[je]
+;W[mc];B[me]
+;W[nd];B[lb]
+;W[lc];B[kc]
+;W[le];B[ai]
+;W[bo];B[lf]
+;W[kd];B[jb]
+;W[ej];B[fj]
+;W[fi];B[bj]
+;W[eh];B[ak]
+;W[gj];B[fk]
+;W[ef];B[fe]
+;W[gk];B[ck]
+;W[ei];B[fm]
+;W[hh];B[ji]
+;W[bp];B[ij]
+;W[ff];B[ge]
+;W[hl];B[jl]
+;W[im];B[jo]
+;W[jm];B[km]
+;W[kn];B[jn]
+;W[kl];B[lm]
+;W[jk];B[ll]
+;W[kk];B[ik]
+;W[il];B[lk]
+;W[kj];B[mi]
+;W[kh];B[jh]
+;W[lj];B[mj]
+;W[lh];B[ke]
+;W[mg];B[lo]
+;W[qm];B[ne]
+;W[oe];B[ld]
+;W[fp];B[hn]
+;W[fo];B[gn]
+;W[og];B[mb]
+;W[od];B[qq]
+;W[qp];B[pq]
+;W[oq];B[or]
+;W[nr];B[rp]
+;W[ro];B[op]
+;W[nq];B[rr]
+;W[sp];B[sq]
+;W[rq];B[gl]
+;W[hk];B[rp]
+;W[pr];B[qr]
+;W[rq];B[nh]
+;W[ng];B[rp]
+;W[mn];B[ln]
+;W[rq];B[gi]
+;W[hi];B[rp]
+;W[ce];B[so]
+;W[ee];B[oo]
+;W[pj];B[lr]
+;W[pn];B[rn]
+;W[on];B[mo]
+;W[nk];B[mk]
+;W[jr];B[qk]
+;W[pk];B[qj]
+;W[qi];B[rl]
+;W[ri];B[kr]
+;W[kq];B[lq]
+;W[kp];B[lp]
+;W[rm];B[sm]
+;W[ql];B[po]
+;W[rk];B[qb]
+;W[rb];B[ra]
+;W[rc];B[oc]
+;W[hq];B[gc]
+;W[de];B[hf]
+;W[gh];B[bf]
+;W[ig];B[jg]
+;W[if];B[ie]
+;W[ep];B[do]
+;W[fn];B[ip]
+;W[jq];B[ko]
+;W[no])
diff --git a/data/expert_play/monday_tournament.sgf b/data/expert_play/monday_tournament.sgf
new file mode 100644
index 0000000..a69ff74
--- /dev/null
+++ b/data/expert_play/monday_tournament.sgf
@@ -0,0 +1,275 @@
+(;GM[1]FF[4]CA[UTF-8]AP[CGoban:3]ST[2]
+RU[Chinese]SZ[19]KM[7.50]TM[3600]
+PW[AlphaGo]PB[Fan Hui]BR[2p]DT[2015-10-05]RE[W+2.50]
+;B[pd]
+;W[dd]
+;B[pp]
+;W[dq]
+;B[co]
+;W[dl]
+;B[dn]
+;W[fp]
+;B[bq]
+;W[jq]
+;B[cf]
+;W[ch]
+;B[fd]
+;W[df]
+;B[dg]
+;W[cg]
+;B[dc]
+;W[ce]
+;B[cc]
+;W[hc]
+;B[fb]
+;W[nc]
+;B[qf]
+;W[pb]
+;B[bf]
+;W[be]
+;B[ef]
+;W[de]
+;B[qc]
+;W[kc]
+;B[qn]
+;W[cm]
+;B[cr]
+;W[mq]
+;B[oq]
+;W[qm]
+;B[pm]
+;W[ql]
+;B[rn]
+;W[pl]
+;B[om]
+;W[qi]
+;B[hq]
+;W[hp]
+;B[gq]
+;W[gp]
+;B[iq]
+;W[ip]
+;B[jr]
+;W[kq]
+;B[er]
+;W[rg]
+;B[qg]
+;W[rf]
+;B[re]
+;W[qh]
+;B[kr]
+;W[ln]
+;B[sf]
+;W[rh]
+;B[qb]
+;W[fe]
+;B[el]
+;W[ek]
+;B[fk]
+;W[ej]
+;B[fl]
+;W[dm]
+;B[fj]
+;W[il]
+;B[fi]
+;W[ei]
+;B[fh]
+;W[gd]
+;B[dh]
+;W[ci]
+;B[di]
+;W[cj]
+;B[fn]
+;W[em]
+;B[hn]
+;W[in]
+;B[en]
+;W[oo]
+;B[np]
+;W[nn]
+;B[po]
+;W[hm]
+;B[fm]
+;W[nl]
+;B[og]
+;W[nr]
+;B[or]
+;W[nh]
+;B[oj]
+;W[ol]
+;B[oh]
+;W[ni]
+;B[oi]
+;W[ng]
+;B[nf]
+;W[mf]
+;B[ne]
+;W[me]
+;B[gc]
+;W[hb]
+;B[bd]
+;W[ed]
+;B[fc]
+;W[ff]
+;B[ae]
+;W[bg]
+;B[af]
+;W[eh]
+;B[fg]
+;W[eg]
+;B[ge]
+;W[hd]
+;B[gf]
+;W[ee]
+;B[if]
+;W[fa]
+;B[ga]
+;W[gb]
+;B[ea]
+;W[ec]
+;B[eb]
+;W[nd]
+;B[je]
+;W[pe]
+;B[oe]
+;W[od]
+;B[of]
+;W[pc]
+;B[qd]
+;W[jh]
+;B[kd]
+;W[lc]
+;B[nj]
+;W[hh]
+;B[hg]
+;W[mj]
+;B[mk]
+;W[lj]
+;B[nk]
+;W[lk]
+;B[pa]
+;W[rm]
+;B[mp]
+;W[lp]
+;B[lr]
+;W[lq]
+;B[bn]
+;W[qq]
+;B[rp]
+;W[rq]
+;B[qp]
+;W[ag]
+;B[ad]
+;W[cp]
+;B[bp]
+;W[oa]
+;B[qa]
+;W[dr]
+;B[ds]
+;W[ob]
+;B[ml]
+;W[nm]
+;B[pn]
+;W[hj]
+;B[kg]
+;W[jg]
+;B[kf]
+;W[kh]
+;B[bl]
+;W[bm]
+;B[am]
+;W[bk]
+;B[jc]
+;W[jb]
+;B[lm]
+;W[km]
+;B[mn]
+;W[mo]
+;B[mm]
+;W[no]
+;B[kl]
+;W[jm]
+;B[ll]
+;W[lg]
+;B[jk]
+;W[cl]
+;B[qj]
+;W[rj]
+;B[gm]
+;W[ho]
+;B[al]
+;W[ak]
+;B[an]
+;W[ic]
+;B[mr]
+;W[nq]
+;B[ns]
+;W[op]
+;B[pq]
+;W[jd]
+;B[pj]
+;W[sg]
+;B[ii]
+;W[se]
+;B[sd]
+;W[ih]
+;B[ji]
+;W[hi]
+;B[ie]
+;W[ld]
+;B[ke]
+;W[he]
+;B[gg]
+;W[eq]
+;B[fq]
+;W[ep]
+;B[cq]
+;W[gn]
+;B[ki]
+;W[li]
+;B[ik]
+;W[sn]
+;B[so]
+;W[sm]
+;B[dp]
+;W[eo]
+;B[id]
+;W[jc]
+;B[do]
+;W[fo]
+;B[hk]
+;W[hl]
+;B[cb]
+;W[ph]
+;B[pg]
+;W[qk]
+;B[ha]
+;W[ia]
+;B[fa]
+;W[ca]
+;B[ba]
+;W[dj]
+;B[cd]
+;W[sf]
+;B[gl]
+;W[gj]
+;B[gk]
+;W[ij]
+;B[kk]
+;W[lh]
+;B[ig]
+;W[lf]
+;B[le]
+;W[gh]
+;B[kj]
+;W[jf]
+;B[hf]
+;W[jl]
+;B[jj]
+;W[gi]
+;B[pi]
+;W[cn]
+;B[pk]
+;W[ok]
+;B[on]
+;W[bb]C[Since all valuable points have been played, the game was finished manually after White's atari at B18. White wins by 2.5.])
diff --git a/data/expert_play/thursday_tournament.sgf b/data/expert_play/thursday_tournament.sgf
new file mode 100644
index 0000000..f8bffa2
--- /dev/null
+++ b/data/expert_play/thursday_tournament.sgf
@@ -0,0 +1,84 @@
+(;PB[AlphaGo]PW[Fan Hui]KM[7.5]HA[0]SZ[19]TM[3600]OT[1 moves / 30 sec]RU[Chinese]RE[B+R]
+;B[dp];W[pp]
+;B[dd];W[pc]
+;B[pe];W[qe]
+;B[qf];W[qd]
+;B[pg];W[nc]
+;B[qk];W[qm]
+;B[ok];W[oq]
+;B[dj];W[fq]
+;B[dn];W[fc]
+;B[df];W[ip]
+;B[ec];W[fd]
+;B[id];W[he]
+;B[ie];W[hg]
+;B[hf];W[gf]
+;B[if];W[gg]
+;B[jh];W[dh]
+;B[eg];W[ih]
+;B[ji];W[eh]
+;B[fh];W[fi]
+;B[fg];W[ej]
+;B[gi];W[gj]
+;B[hj];W[dk]
+;B[gk];W[fj]
+;B[hi];W[ib]
+;B[cj];W[cg]
+;B[ck];W[be]
+;B[cc];W[bc]
+;B[bb];W[cd]
+;B[ac];W[bd]
+;B[db];W[de]
+;B[ee];W[cf]
+;B[ed];W[jc]
+;B[hc];W[gb]
+;B[hb];W[ha]
+;B[fb];W[gc]
+;B[dl];W[bi]
+;B[ci];W[bh]
+;B[qo];W[pl]
+;B[pk];W[qp]
+;B[fa];W[ga]
+;B[lc];W[lb]
+;B[kb];W[kc]
+;B[mb];W[ld]
+;B[mc];W[md]
+;B[nb];W[ke]
+;B[oc];W[od]
+;B[nd];W[ne]
+;B[pb];W[nc]
+;B[ob];W[pd]
+;B[kq];W[jq]
+;B[kp];W[dr]
+;B[hq];W[ir]
+;B[gq];W[fp]
+;B[fr];W[er]
+;B[ho];W[gr]
+;B[hr];W[fs]
+;B[go];W[cq]
+;B[rp];W[rq]
+;B[ig];W[qb]
+;B[rb];W[qa]
+;B[rc];W[qc]
+;B[la];W[on]
+;B[rf];W[sb]
+;B[mg];W[of]
+;B[og];W[mf]
+;B[nm];W[lg]
+;B[mh];W[lo]
+;B[ko];W[ln]
+;B[kn];W[lm]
+;B[km];W[ll]
+;B[om];W[pn]
+;B[mp];W[mq]
+;B[np];W[nn]
+;B[nq];W[kr]
+;B[mr];W[hs]
+;B[or];W[pr]
+;B[op];W[pq]
+;B[po];W[oo]
+;B[ro];W[sq]
+;B[qr];W[ps]
+;B[rr];W[sr]
+;B[rm];W[rl]
+;B[ql])
diff --git a/data/expert_play/tuesday_tournament.sgf b/data/expert_play/tuesday_tournament.sgf
new file mode 100644
index 0000000..77e368a
--- /dev/null
+++ b/data/expert_play/tuesday_tournament.sgf
@@ -0,0 +1,93 @@
+(;PB[AlphaGo]PW[Fan Hui]KM[6.5]HA[0]SZ[19]TM[3600]OT[1 moves / 30 sec]RU[Chinese]RE[B+R]
+;B[dp];W[pp]
+;B[dd];W[pc]
+;B[pe];W[qe]
+;B[pd];W[qd]
+;B[oc];W[qf]
+;B[pf];W[pg]
+;B[qc];W[pb]
+;B[rc];W[qb]
+;B[qg];W[qh]
+;B[rb];W[ob]
+;B[rg];W[rf]
+;B[rh];W[rd]
+;B[nc];W[ph]
+;B[qi];W[pi]
+;B[qj];W[nb]
+;B[se];W[sd]
+;B[ne];W[pj]
+;B[ql];W[pk]
+;B[rm];W[sg]
+;B[ri];W[mf]
+;B[lc];W[kd]
+;B[kc];W[jd]
+;B[ic];W[id]
+;B[hc];W[jc]
+;B[jb];W[kb]
+;B[lb];W[ib]
+;B[ka];W[gd]
+;B[hd];W[he]
+;B[ge];W[fd]
+;B[hf];W[ie]
+;B[hb];W[de]
+;B[fe];W[ed]
+;B[ee];W[dc]
+;B[cd];W[cc]
+;B[be];W[df]
+;B[bc];W[gf]
+;B[ff];W[gg]
+;B[fg];W[fh]
+;B[gh];W[hg]
+;B[eh];W[fi]
+;B[eg];W[bb]
+;B[ec];W[ei]
+;B[fc];W[di]
+;B[nq];W[qn]
+;B[pl];W[ol]
+;B[om];W[nl]
+;B[pn];W[rn]
+;B[nm];W[ml]
+;B[qo];W[po]
+;B[ro];W[on]
+;B[pm];W[rp]
+;B[sn];W[qp]
+;B[qm];W[mp]
+;B[lq];W[mq]
+;B[mr];W[np]
+;B[or];W[oq]
+;B[nr];W[pr]
+;B[jq];W[io]
+;B[hp];W[ho]
+;B[gp];W[fn]
+;B[dn];W[dq]
+;B[cq];W[ep]
+;B[eo];W[cp]
+;B[do];W[cr]
+;B[bq];W[br]
+;B[eq];W[dr]
+;B[bp];W[er]
+;B[gr];W[ar]
+;B[le];W[jg]
+;B[el];W[fl]
+;B[fk];W[ek]
+;B[dk];W[ej]
+;B[lf];W[lh]
+;B[lm];W[mm]
+;B[ko];W[kn]
+;B[ln];W[km]
+;B[ll];W[lp]
+;B[kp];W[lo]
+;B[jn];W[kl]
+;B[mn];W[nn]
+;B[lk];W[im]
+;B[nj];W[ok]
+;B[kk];W[il]
+;B[mh];W[mi]
+;B[li];W[ki]
+;B[ni];W[lj]
+;B[mk];W[of]
+;B[nh];W[nf]
+;B[oe];W[og]
+;B[lg];W[mg]
+;B[kh];W[li]
+;B[me])
diff --git a/data/expert_play/wednesday_tournament.sgf b/data/expert_play/wednesday_tournament.sgf
new file mode 100644
index 0000000..3670457
--- /dev/null
+++ b/data/expert_play/wednesday_tournament.sgf
@@ -0,0 +1,85 @@
+(;PB[Fan Hui]PW[AlphaGo]KM[7.5]HA[0]SZ[19]TM[3600]OT[1 moves / 30 sec]RU[Chinese]RE[W+R]
+;B[dp]
+;W[pp];B[cd]
+;W[pd];B[nc]
+;W[qf];B[ic]
+;W[cj];B[ci]
+;W[di];B[ch]
+;W[dj];B[dh]
+;W[cn];B[ei]
+;W[fq];B[eo]
+;W[cq];B[cl]
+;W[dl];B[ck]
+;W[bj];B[dk]
+;W[ej];B[dm]
+;W[fi];B[eh]
+;W[fl];B[el]
+;W[fm];B[dn]
+;W[dq];B[fk]
+;W[fj];B[gk]
+;W[fh];B[fg]
+;W[gg];B[gf]
+;W[hg];B[ff]
+;W[hf];B[he]
+;W[ie];B[id]
+;W[je];B[kd]
+;W[cc];B[bc]
+;W[ke];B[ld]
+;W[df];B[cf]
+;W[cg];B[de]
+;W[bf];B[ce]
+;W[bh];B[dg]
+;W[bb];B[be]
+;W[ac];B[bd]
+;W[ek];B[hj]
+;W[hl];B[hi]
+;W[jj];B[ji]
+;W[ki];B[jk]
+;W[kj];B[gl]
+;W[gm];B[hm]
+;W[go];B[il]
+;W[hn];B[im]
+;W[bn];B[fp]
+;W[gp];B[cp]
+;W[bp];B[bq]
+;W[br];B[bo]
+;W[aq];B[co]
+;W[ao];B[em]
+;W[hh];B[ll]
+;W[fo];B[eq]
+;W[ep];B[np]
+;W[do];B[pn]
+;W[qq];B[nn]
+;W[qi];B[qc]
+;W[pc];B[pb]
+;W[qd];B[rb]
+;W[rc];B[qb]
+;W[ql];B[pl]
+;W[pk];B[oq]
+;W[qn];B[qo]
+;W[rn];B[po]
+;W[ro];B[jq]
+;W[ii];B[qp]
+;W[rp];B[qr]
+;W[jp];B[kp]
+;W[iq];B[jo]
+;W[ip];B[kr]
+;W[jr];B[kq]
+;W[pq];B[pr]
+;W[rr];B[op]
+;W[rq];B[ok]
+;W[pm];B[ol]
+;W[om];B[pj]
+;W[qk];B[pi]
+;W[qh];B[ph]
+;W[nm];B[pg]
+;W[qg];B[mm]
+;W[ml];B[on]
+;W[nl];B[lk]
+;W[oj];B[nk]
+;W[mk];B[nj]
+;W[mj];B[ni]
+;W[mi];B[nh]
+;W[nf];B[mf]
+;W[mg];B[of]
+;W[ne])
diff --git a/data/self_play/s_a_z_tuples_here_format_TBD b/data/self_play/s_a_z_tuples_here_format_TBD
new file mode 100644
index 0000000..e69de29
diff --git a/data/trained_models/h5_files_here_by_hyperparamer_UID b/data/trained_models/h5_files_here_by_hyperparamer_UID
new file mode 100644
index 0000000..e69de29
diff --git a/interface/client/simple_client_here_possibly_Wgo b/interface/client/simple_client_here_possibly_Wgo
new file mode 100644
index 0000000..e69de29
diff --git a/interface/opponents/pachi/pachi.py b/interface/opponents/pachi/pachi.py
new file mode 100644
index 0000000..e69de29
diff --git a/interface/server/simple_server_here b/interface/server/simple_server_here
new file mode 100644
index 0000000..e69de29
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..a4eb6bb
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,7 @@
+Keras==0.3.1
+numpy==1.10.4
+PyYAML==3.11
+scipy==0.17.0
+six==1.10.0
+Theano==0.7.0
+wheel==0.29.0
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/test_gamestate.py b/tests/test_gamestate.py
new file mode 100644
index 0000000..42894fb
--- /dev/null
+++ b/tests/test_gamestate.py
@@ -0,0 +1,73 @@
+from AlphaGo.Game import GameState
+import numpy as np
+import unittest
+
+class TestSymmetries(unittest.TestCase):
+
+	def setUp(self):
+		self.s = GameState()
+		self.s.do_move((4,5))
+		self.s.do_move((5,5))
+		self.s.do_move((5,6))
+
+		self.syms = self.s.symmetries()
+
+	def test_num_syms(self):
+		# make sure we got exactly 8 back
+		self.assertEqual(len(self.syms), 8)
+
+	def test_copy_fields(self):
+		# make sure each copy has the correct non-board fields
+		for copy in self.syms:
+			self.assertEqual(self.s.size, copy.size)
+			self.assertEqual(self.s.turns_played, copy.turns_played)
+			self.assertEqual(self.s.current_player, copy.current_player)
+
+	def test_sym_boards(self):
+		# construct by hand the 8 boards we expect to see
+		expectations = [GameState() for i in range(8)]
+
+		descriptions = ["noop", "rot90", "rot180", "rot270", "mirror LR", "mirror UD", "mirror \\", "mirror /"]
+
+		# copy of self.s
+		expectations[0].do_move((4,5))
+		expectations[0].do_move((5,5))
+		expectations[0].do_move((5,6))
+
+		# rotate 90 CCW
+		expectations[1].do_move((13,4))
+		expectations[1].do_move((13,5))
+		expectations[1].do_move((12,5))
+
+		# rotate 180
+		expectations[2].do_move((14,13))
+		expectations[2].do_move((13,13))
+		expectations[2].do_move((13,12))
+
+		# rotate CCW 270
+		expectations[3].do_move((5,14))
+		expectations[3].do_move((5,13))
+		expectations[3].do_move((6,13))
+
+		# mirror left-right
+		expectations[4].do_move((4,13))
+		expectations[4].do_move((5,13))
+		expectations[4].do_move((5,12))
+
+		# mirror up-down
+		expectations[5].do_move((14,5))
+		expectations[5].do_move((13,5))
+		expectations[5].do_move((13,6))
+
+		# mirror \ diagonal
+		expectations[6].do_move((5,4))
+		expectations[6].do_move((5,5))
+		expectations[6].do_move((6,5))
+
+		# mirror / diagonal (equivalently: rotate 90 CCW then flip LR)
+		expectations[7].do_move((13,14))
+		expectations[7].do_move((13,13))
+		expectations[7].do_move((12,13))
+
+		for i in range(8):
+			self.assertTrue(np.array_equal(expectations[i].board, self.syms[i].board), descriptions[i])
\ No newline at end of file
