In [144]:
import sys
import os
import json
import chess
from time import sleep, time
from datetime import datetime, timedelta
from random import random, choice
from IPython.display import clear_output

# Bots
import random_bot
#import final_bot
import basic_bot_1_1

dev = True

### Functions

def print_time(to_print, 
               t=0, 
               clear=True):
    if clear: clear_output()
    print to_print, '\n'
    sys.stdout.flush()
    sleep(t)
    pass

def get_config(board, me):
    cmap = {
        ( 'WIN', 'WHITE'):  'W_win',
        ('DRAW', 'WHITE'): 'W_draw',
        ('LOSE', 'WHITE'): 'W_lose',
        ( 'WIN', 'BLACK'):  'B_win',
        ('DRAW', 'BLACK'): 'B_draw',
        ('LOSE', 'BLACK'): 'B_lose'}

    result = None
    if board.is_checkmate():
        if not board.turn == me:
            result = 'WIN'
        else:
            result = 'LOSE'
    else:
        result = 'DRAW'

    return cmap[(result,turn_color[me])]

def get_status(board):
    result = ""
    if board.is_game_over():
        if board.is_checkmate(): result = 'Checkmate! ' + turn_color[not board.turn] + ' wins'
        if board.is_stalemate(): result = 'Stalemate! DRAW'
        if board.is_insufficient_material(): result = 'Insufficient material. DRAW', 
        if board.is_seventyfive_moves(): result = 'Seventyfive moves without capture or pawn move. DRAW'
        if board.is_fivefold_repetition(): result = 'Fivefold repetition. DRAW'
    else:
        result = turn_color[board.turn], 'to move'
    return result

### Parameters

turn_color = {
    True:'WHITE',
    False:'BLACK',
    None: None
}

def new_state():
    state = {
        'played_since': '',
        'game_desc':    '',
        'fen':          '',
        'turn_desc':    '',
        'W_win':         0,
        'W_draw':        0,
        'W_lose':        0,
        'B_win':         0,
        'B_draw':        0,
        'B_lose' :       0
    }
    return state

def init_state():
    state = None
    if os.path.exists('../html/state'):
        with open('../html/state', 'r') as f:
            state = json.loads(f.read())
    if not state:
        state = new_state()
    return state

def write_state(state):
    with open('../html/state', 'w') as f:
        f.write(json.dumps(state, indent=4))
    pass

state = init_state()

# The Arena
me_bot = basic_bot_1_1
he_bot = random_bot
players = [chess.WHITE, chess.BLACK]
min_turn_time = 0.1

# In[ ]:
if not state['played_since']:
    state['played_since'] = (datetime.fromtimestamp(time())+timedelta(hours=1)).strftime('%Y-%m-%d %H:%M:%S')

In [233]:
while True:
    
    board = chess.Board() # Set up the board
    me    = choice(players)  # My color
    turn  = 0

    cpu_time = {chess.WHITE: 0, chess.BLACK: 0}

    state['game_desc'] = 'Bot plays ' + turn_color[me] + ', ' + turn_color[not me] + ' is random\n'
        
    while not board.is_game_over():
        
        t0 = time()
        turn+=1

        state['fen'] = board.fen()
        
        tt = time()
        if board.turn == me:
            state['turn_desc'] = str(1+turn/2) + ' - My move, ' + turn_color[board.turn]
            move = me_bot.move(board) # My move!
        else:
            state['turn_desc'] = str(1+turn/2) + ' - His move, ' + turn_color[board.turn]
            move = he_bot.move(board) # My opponent's move
        ct = time() - tt
        cpu_time[board.turn] += ct

        board.push(move) # Make the move
        
        if dev: 
            print_time(board)
            print state
            sys.stdout.flush()

        t1 = time()
        if t1-t0 < min_turn_time:
            sleep(min_turn_time - (t1-t0))

        write_state(state)
    
    state['fen'] = board.fen()
    state['game_desc'] = get_status(board)

    result = None
    if board.is_checkmate(): 
        result = turn_color[not board.turn]

    state[get_config(board, me)] += 1

    write_state(state)

    log_entry = {
        'move_stack': ','.join([str(move) for move in board.move_stack]),
        'winner': turn_color[not board.turn] if board.is_checkmate() else None,
        'WHITE': {
            'bot': me_bot.name() if me == chess.WHITE else he_bot.name(),
            'cpu_time': cpu_time[chess.WHITE]
            },
        'BLACK': {
            'bot': me_bot.name() if me == chess.BLACK else he_bot.name(),
            'cpu_time': cpu_time[chess.BLACK]
            },
        }
    
    #with open('log_entry') as f:
    #    f.write(json.dumps(log_entry, separators=(',', ': ')))
    #    write_command = 's3cmd put log_entry %i s3://larsbk/%s/%s/%s/%i' % (i,
    #                                                                        log_entry[winner],
    #                                                                        log_entry[not loser],
    #                                                                        color,i)
    #
    #
    #write_command = 's3cmd put'
    #    
    sleep(8)


r n b q k b n r
p p p p p p p p
. . . . . . . .
. . . . . . . .
P . . . . . . .
. . . . . . . .
. P P P P P P P
R N B Q K B N R 

{u'B_draw': 0, u'fen': 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1', u'W_win': 4, u'played_since': u'2015-12-19 22:33:51', u'turn_desc': '1 - His move, WHITE', u'B_lose': 0, u'W_lose': 0, u'B_win': 3, u'W_draw': 0, u'game_desc': 'Bot plays BLACK, WHITE is random\n'}
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-233-458b1c150cd3> in <module>()
     19         if board.turn == me:
     20             state['turn_desc'] = str(1+turn/2) + ' - My move, ' + turn_color[board.turn]
---> 21             move = move(board) # My move!
     22         else:
     23             state['turn_desc'] = str(1+turn/2) + ' - His move, ' + turn_color[board.turn]

TypeError: 'Move' object is not callable

In [175]:
value_piece = {
    chess.PAWN:   1.0,
    chess.KNIGHT: 2.9,
    chess.BISHOP: 3.1,
    chess.ROOK:   5.0,
    chess.QUEEN:  9.0,
    chess.KING:   0.0
}

f = 1/6.
w = [[1,1,1,1,1,1,1,1],
     [1,2,2,2,2,2,2,1],
     [1,2,3,3,3,3,2,1],
     [1,2,3,5,5,3,2,1],
     [1,2,3,5,5,3,2,1],
     [1,2,3,3,3,3,2,1],
     [1,2,2,2,2,2,2,1],
     [1,1,1,1,1,1,1,1]]

square_importance = {}
for i,r in enumerate(w):
    for j,c in enumerate(r):
        square_importance[chess.square(i,j)] = f*((c-1)/(5.-1))

In [165]:
def eval_board(board):
    
    if board.is_game_over():
        if board.is_checkmate(): 
            result = -1 * (int(board.turn) - int(not board.turn)) * float('inf')
        else:
            result = 0
    else:
        result = eval_player(board, chess.WHITE) - eval_player(board, chess.BLACK)
        
    return result

def eval_player(board, player):
    
    score_material = 0
    score_presence = 0
    score_position = 0
    
    for piece_type in xrange(1,7):
        for square in board.pieces(piece_type, player):
            
            score_material += value_piece[piece_type]
            score_presence += square_importance[square]
        
        for square in board.pieces(piece_type, not player):
            
            attackers = sorted([value_piece[board.piece_type_at(s)] for s in board.attackers(board.turn, square)])
            defenders = sorted([value_piece[board.piece_type_at(s)] for s in board.attackers(not board.turn, square)])
            
            defendant = value_piece[piece_type]
            gain = 0
            while attackers:
                gain += defendant
                if defenders:
                    gain -= attackers.pop(0)
                    defendand = defenders.pop(0)
                else: 
                    break
                    
            score_position += max(0, (player==board.turn) * gain)

    return score_material + score_presence + score_position

In [232]:
def move(board, show=False):
    tree = build_tree(board)
    result = parse_tree(tree)
    return result[0].pop(0)

def board_push(board, move):
    new_board = board.copy()
    new_board.push(move)
    return new_board

def build_tree(root_board, halfmove_depth=1, limit_halfmove_depth=2):

    if halfmove_depth == limit_halfmove_depth:
        return {root_board.fen(): [(move, board_push(root_board, move).fen()) for move in root_board.legal_moves]}
    else:
        return {root_board.fen(): [(move, build_tree(board_push(root_board, move),
                                                     halfmove_depth=halfmove_depth+1,
                                                     limit_halfmove_depth=limit_halfmove_depth)) for move in root_board.legal_moves]}
    pass

def parse_tree(tree):
    ans = _parse_tree(tree)
    return (ans[1:][::-1],ans[0])

def _parse_tree(tree):

    root_board = chess.Board(tree.keys().pop())
    sign = int(root_board.turn) - int(not root_board.turn)

    if tree.values().pop():
        movelist = tree.values().pop()
        if type(movelist.pop()[1])==str:
            return list(max([(sign*eval_board(chess.Board(fen)),move) for (move,fen) in movelist]))
        else:
            ans = max([(-1*t[0],t[1:]) for t in [_parse_tree(subtree)+[move] for (move, subtree) in movelist]])
            return [ans[0]]+ans[1]
    else:
        return list((-sign * float('inf'), move))
    pass

In [228]:
board = chess.Board()
root_board = board
moves = [move for move in board.legal_moves]

In [229]:
tree = build_tree(board)

In [230]:
#tree.values()

In [231]:
parse_tree(tree)


Out[231]:
([Move.from_uci('e2e4'), Move.from_uci('e7e5')], 0.0)

In [178]:
board


Out[178]:
Board('rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1')

In [176]:
value_piece


Out[176]:
{1: 1.0, 2: 2.9, 3: 3.1, 4: 5.0, 5: 9.0, 6: 0.0}

In [121]:
a = {1: []}
if a.values().pop(): print "ja"

In [126]:
print chess.Board(tree.keys().pop())


r n b q k b n r
p p p p p p p p
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
P P P P P P P P
R N B Q K B N R

In [ ]: