Compare commits

..

No commits in common. "test" and "master" have entirely different histories.
test ... master

6 changed files with 5 additions and 357 deletions

11
TODO
View File

@ -1,11 +0,0 @@
TODO
----
- make an interface for picking moves
- make an interface, period
- back-propagate values up the tree
BUGS
----
- test framework makes mistake

125
board2.py
View File

@ -1,125 +0,0 @@
#!/usr/bin/env python
import copy
from pos import TwoDPos
class BoardTools:
def __init__(self):
pass
def winning(self, b):
for i in range(3):
if b[i][0] == b[i][1] == b[i][2]:
if b[i][0] != Board.unplayed:
return b[i][0]
if b[0][i] == b[1][i] == b[2][i]:
if b[0][i] != Board.unplayed:
return b[0][i]
if b[0][0] == b[1][1] == b[2][2]:
if b[0][0] != Board.unplayed:
return b[0][0]
if b[2][0] == b[1][1] == b[0][2]:
if b[2][0] != Board.unplayed:
return b[2][0]
spaces = 0
for i in range(3):
for j in range(3):
if b[i][j] != Board.unplayed:
spaces += 1
if spaces == 9:
return Board.tie
return Board.unplayed
class Board:
unplayed = 0
cross = 1
nought = 2
tie = 3
def __init__(self):
self.board = [
[
[
[Board.unplayed for i in range(3)]
for j in range(3)
]
for k in range(3)
]
for l in range(3)
]
self.moves = []
self.turn = Board.cross
def copy(self):
new = Board()
new.board = copy.deepcopy(self.board)
new.moves = copy.deepcopy(self.moves)
new.turn = copy.deepcopy(self.turn)
return new
def set(self, a, b, c, d, val):
self.board[a][b][c][d] = val
def get(self, a, b, c, d):
return self.board[a][b][c][d]
def alternate(self):
if self.turn == Board.cross:
self.turn = Board.nought
else:
self.turn = Board.cross
def subWin(self, x, y):
return BoardTools.winning(None, self.board[x][y])
def metaboard(self):
return [[BoardTools.winning(None, self.board[x][y]) for x in range(3)] for y in range(3)]
def win(self):
return BoardTools.winning(self.metaboard())
def append(self, move):
self.moves.append(move)
self.set(*move.local(), self.turn)
self.alternate()
def reachableEmpty(self):
metaboard = self.metaboard()
buf = []
for i in range(3):
for j in range(3):
if metaboard[j][i] == Board.unplayed:
for k in range(3):
for l in range(3):
if self.board[i][j][k][l] == Board.unplayed:
buf.append(TwoDPos(TwoDPos.l, (i, j, k, l)))
return buf
def possible(self):
# check if board is in final state
isFinal = BoardTools.winning(self, self.metaboard())
if isFinal in [Board.tie, Board.cross, Board.nought]:
return []
try:
move = self.moves[-1]
except IndexError:
buf = []
for i in range(3):
for j in range(3):
for k in range(3):
for l in range(3):
buf.append(TwoDPos(TwoDPos.l, (i, j, k, l)))
return buf
local = move.local()
if self.subWin(local[2], local[3]) in [Board.tie, Board.nought, Board.cross]:
return self.reachableEmpty()
buf = []
for i in range(3):
for j in range(3):
if self.board[local[2]][local[3]][i][j] == Board.unplayed:
buf.append(TwoDPos(TwoDPos.l, (local[2], local[3], i, j)))
return buf

138
cli.py
View File

@ -1,138 +0,0 @@
#!/usr/bin/env python
from board2 import Board
from board2 import BoardTools
from pos import TwoDPos
from pos import TwoDUtils
from node import Node
class StateError(BaseException):
pass
piecemaps = {
0: '.',
1: 'x',
2: 'o',
}
mappings = TwoDUtils.reverse
def tree_of_node(node, count=5):
if count == 1:
score = 0
for i in range(9):
for j in range(9):
p = TwoDPos(TwoDPos.g, (i + 1, j + 1))
a, b, c, d = p.local()
if node.inner.board[a][b][c][d] == Board.cross:
score += 1
elif node.inner.board[a][b][c][d] == Board.nought:
score -= 1
return score
parent = node
print("considering board with moveset " + str(parent.inner.moves))
possible = parent.inner.possible()
if len(possible) != 0:
print("permuting!")
for i in possible:
copy = parent.inner.copy()
copy.append(i)
childnode = Node()
childnode.inner = copy
parent.children.append(childnode)
for i in parent.children:
tree_of_node(i, count - 1)
else:
print("calculated score")
rawscore = BoardTools.winning(None, parent.inner.metaboard())
if rawscore == Board.cross:
score = -1
elif rawscore == Board.nought:
score = 1
elif rawscore == Board.tie:
score = 0
else:
score = None
raise StateError("aaaa")
print("score" + str(score))
return score
def render(board):
print("123 456 789")
moves = board.possible()
moves = [i.glob() for i in moves]
for i in range(9):
buf = []
for j in range(9):
ri = mappings[i]
string = ''.join([ri, str(j + 1)])
pos = TwoDPos(TwoDPos.g, string)
item = board.get(*pos.local())
if string in moves:
buf.append('?')
else:
buf.append(piecemaps[item])
if j in [2, 5]:
buf.append(" | ")
if j == 8:
buf.append(" " + ri)
print(''.join(buf))
if i in [2, 5]:
print("----+-----+----")
print("to play: " + str(board.turn))
def help_text():
print("m - make a move")
print("p - see coordinates of legal moves")
print("t - see whose turn it is")
print("r - render the board to the screen")
print("q - quit program")
print("h - show help (this list)")
def move(board, move):
move = TwoDPos(TwoDPos.g, move)
print(move)
board.append(move)
def possibilities(board):
print(board.possible())
def turn(board):
print("to play: " + str(board.turn))
def main():
b = Board()
print("type h for help")
while True:
# try:
cmd = input("> ")
spl = cmd.split(' ')
if spl[0] == "m":
move(b, spl[1])
elif spl[0] == "p":
possibilities(b)
elif spl[0] == "t":
turn(b)
elif spl[0] == "r":
render(b)
elif spl[0] == "h":
help_text()
elif spl[0] == "z":
# create node from current board
node = Node()
node.inner = b
tree_of_node(node)
elif spl[0] == "q":
break;
# except:
# print("error occured")
return
if __name__ == "__main__":
main()

17
node.py
View File

@ -1,17 +0,0 @@
# node implementation
class Node:
def __init__(self):
self.children = []
self.score = None
self.inner = None
def calculate(self):
if self.children == []:
return self.score
total = 0
items = 0
for i in self.children:
score = i.calculate()
if score != None:
items += 1
total += score

20
pos.py
View File

@ -21,26 +21,16 @@ class TwoDPos:
l = 1
def __init__(self, mode, param):
if mode == TwoDPos.g:
try:
self.pos = (
TwoDUtils.mappings[param[0]],
int(param[1]) - 1,
)
except KeyError:
self.pos = (
int(param[0]) - 1,
int(param[1]) - 1,
)
self.pos = (
TwoDUtils.mappings[param[0]],
int(param[1]) - 1,
)
elif mode == TwoDPos.l:
self.pos = (
param[0] * 3 + param[2],
param[1] * 3 + param[3],
param[1] * 3 + param[3] + 1,
)
def __repr__(self):
return ' '.join([self.glob(), str(self.local())])
def glob(self):
ret = []
ret.append(TwoDUtils.reverse[self.pos[0]])

51
test.py
View File

@ -1,51 +0,0 @@
#!/usr/bin/env python3
from board2 import Board
from pos import TwoDPos
b = Board()
print(b.possible())
print("moving to d4")
b.append(TwoDPos(TwoDPos.g, "d4"))
print(b.possible())
print("moving to b2")
b.append(TwoDPos(TwoDPos.g, "b2"))
print(b.possible())
print("moving to d5")
b.append(TwoDPos(TwoDPos.g, "d5"))
print(b.possible())
print("moving to b5")
b.append(TwoDPos(TwoDPos.g, "b5"))
print(b.possible())
print("moving to d6")
b.append(TwoDPos(TwoDPos.g, "d6"))
print(b.possible())
print("moving to b8")
b.append(TwoDPos(TwoDPos.g, "b8"))
print(b.possible())
print("there should be a square captured in the middle")
print("moving to a7")
b.append(TwoDPos(TwoDPos.g, "a7"))
print(b.possible())
print("moving to c3")
b.append(TwoDPos(TwoDPos.g, "c3"))
print(b.possible())
print("moving to g7")
b.append(TwoDPos(TwoDPos.g, "g7"))
print(b.possible())
print("moving to b3")
b.append(TwoDPos(TwoDPos.g, "b3"))
print(b.possible())
print("moving to d7")
b.append(TwoDPos(TwoDPos.g, "d7"))
print(b.possible())
print("moving to a3")
b.append(TwoDPos(TwoDPos.g, "a3"))
print(b.possible())
print("moving to c9")
b.append(TwoDPos(TwoDPos.g, "c9"))
print(b.possible())
print("moving to g9")
b.append(TwoDPos(TwoDPos.g, "g9"))
print(b.possible())