#!/usr/bin/python
# -*- coding: utf-8 -*-

""" A minimalistic tic-tac-toe game functionality
Main purpose is to support the testing of Atalk
Tic-tac-toe is the official test game for Atalk. """

import random

def draw_who_starts(set=[], max=2):
    """ Return random element from set.
    if set is empty, return random number <2
    if neither set, nor max is specified, return random number 0 or 1. """
    if len(set)<1:
        return random.choice(range(max))
    else:
        return random.choice(set)

def _start_board():
    return "........." # 3x3 empty cells

def show_board(board):
    print
    print "  789  "+board[6:9]
    print "  456  "+board[3:6]
    print "  123  "+board[0:3]
    print 

def _valid_board(board):
    if (type(board) is str):
        if len(board) == 9:
            if set(board) <= set(".OX"):
                if ((board.count("O")<=3) & (board.count("X")<=3)):
                    return True
    return False

def draw(player, board="", strategy="", mov=0):
    
    def swap(s, i, j):
        lst = list(s);
        lst[i], lst[j] = lst[j], lst[i]
        return ''.join(lst)
     
    if board == "":
        board = _start_board()
    if strategy=="":
        strategy="Rolf"
    if _valid_board(board):
        
        if strategy=="Rolf": # Random from legal fields "Rolf"
            lst_my_tokens = list(t[0] for t in enumerate(board) if t[1]==player)
            lst_no_tokens = list(t[0] for t in enumerate(board) if t[1]==".")
            if len(lst_my_tokens)<3: # Add new token
                l = list(board)
                l[random.choice(lst_no_tokens)] = player
                rolf_board =  "".join(l)
            else: # move existing token
                    mv_from = random.choice(lst_my_tokens)
                    mv_to = random.choice(lst_no_tokens)
                    rolf_board = swap(board, mv_from, mv_to)
            return rolf_board
        
        elif strategy=="Manual": # Make a manual move
            manu_board = board # fall back value if move don't validate
            print " ttt - board before {}".format(board)
            print " ttt - manual player {} says {}".format(player, mov)
            posf = (mov / 10)-1 # move from posf, seen as numerical keypad.
            post = (mov % 10)-1 # move to post. And humans count from 1, computers count from 0
            print " ttt - move: {} -> {}".format(posf,post)
            lst_my_tokens = list(t[0] for t in enumerate(board) if t[1]==player)
            if len(lst_my_tokens)<3: # Add new token
                print " ttt - I have <3 tokens, put token on {}".format(post)
                if board[post] == ".":
                    l = list(board)
                    l[post] = player
                    manu_board =  "".join(l)
                else:
                    print "Error - post {} not vacant...".format(post)
            else:
                print " ttt - move token {} -> {}".format(posf,post)
                if board[posf] == player:
                    if board[post] == ".":
                        manu_board = swap(board, posf, post)
                    else:
                        print "Error - post {} not empty...".format(post)
                else:
                    print "Error - posf {} not your token...".format(posf)
            print " ttt - board after {}".format(manu_board)
            return manu_board
        
        else:
            print " ttt Unknown strategy:", strategy
            return board
    else:
        return board

def is_game_over(board):
    win = winner(board)
    if (win == "X") | (win == "O"):
        return True
    else:
        return False

def winner(board):
    if _valid_board(board):
        for strip in [(0,1,2),(3,4,5),(6,7,8),(0,3,6),(1,4,7),(2,5,8),(0,4,8),(2,4,6)]:
            set_strip = set([board[strip[0]],board[strip[1]],board[strip[2]]])
            if set_strip == set("X"):
                return "X"
            if set_strip == set("O"):
                return "O"
        return "."

if __name__ == "__main__":    
    print "\n   *** This module can't be run - it should be called from another program ***"