import numpy as np
import time
import random
recent = []
recent1 = []
cloud = []
a = 1
b = 78
c = 23
fg_colors = {
	"black": "\033[90m",
	"red": "\033[91m",
	"green": "\033[92m",
	"yellow": "\033[93m",
	"blue": "\033[94m",
	"magenta": "\033[95m",
	"cyan": "\033[96m",
	"white": "\033[97m"
}

bg_colors = {
	"black": "\033[100m",
	"red": "\033[101m",
	"green": "\033[102m",
	"yellow": "\033[103m",
	"blue": "\033[104m",
	"magenta": "\033[105m",
	"cyan": "\033[106m",
	"white": "\033[107m"
}

def colour(text, fg="white", bold=False, bg=None):
	prefix = ""
	if bold:
		prefix += "\033[1m"
	prefix += fg_colors.get(fg.lower(), "\033[97m")
	if bg:
		prefix += bg_colors.get(bg.lower(), "")
	return f"{prefix}{text}\033[0m"

nums = np.zeros((3,3))
board = np.full((3,3),'#')
board_original = board.copy()
col = np.full((3,3),'orange')
bg = np.full((3,3),'cyan')
output_board = board
num1 = 0
num2 = 0
coname = """    						
						███	 ███	 ████	 ███	 ███	 ███	 ████ (MarStar)
						█ 	█  █	█   █	█   	  █	█  █	█   █
						███	█████	████ 	  █	  █	█████	████
						█ 	█  █	█  █	   █	  █	█  █	█  █
						█ 	█  █	█   █	███	  █	█  █	█   █
					
						  		  		 			        		by Marcy
															  	--------
"""
output_zero = """						    								
		TTTTTTTTTTTTTTTTTT  IIIIII       CCCCCC   
		       TTT	      II        C
		       TTT	      II       C
		       TTT	      II      C
		       TTT	      II      C
		       TTT	      II       C
		       TTT            II        C
		       TTT          IIIIII       CCCCCC
		"""
output_one = """
		TTTTTTTTTTTTTTTTTT   A	    	 CCCCCC
		       TTT	    A A         C
		       TTT	   A   A       C
		       TTT        A     A     C
                       TTT	 AAAAAAAAA    C
                       TTT	A         A    C
                       TTT     A           A    C
                       TTT    A             A    CCCCCC
		"""
output_two = """
		TTTTTTTTTTTTTTTTT  OOOOO     EEEEEEEE
		       TTT	  O	O    E
		       TTT	 O	 O   E
                       TTT	O	  O  E
		       TTT	O	  O  EEEEEEE
    	               TTT       O	 O   E
		       TTT	  O	O    E
		       TTT	   OOOOO     EEEEEEEE
		"""
print(colour(coname,'green',bold = True,bg = None))
time.sleep(1)
print(colour(output_zero,'magenta',bold = True,bg = None))
print(colour(output_one,'cyan',bold = True,bg = None))
print(colour(output_two,'green',bold = True,bg = None))
time.sleep(1)
print(colour('+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++','red',bold = True,bg = 'cyan'))
print(colour("Enjoy the classic Tic-Tac-Toe game!No need for Wi-Fi!Let's get fun!Available for single-player mode and two-player mode!Anytime,anywhere,enjoy the fun of Tic-Tac-Toe!FULL OF FUN.",'yellow',bold = True,bg = None))
time.sleep(1)
print(colour('--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------','red',bold = True,bg = None))
print(colour('Developer:           Marcy            ','green',bold = True,bg = 'magenta'))
txt = """How to find position:
		  y y y y y

 
		  0    1   2
	x	0['#','#','#']
	x
	x	1['#','#','#']
	x
	x	2['#','#','#']
		
	You can use find the position this way,and the form is (x,y),WARNING:x is the first,then y!The number of x and y is the position above,have fun :)
	
How to use functions:
	marstar.clear() : For clear all the character on the board.
	marstar.guide() : For check the guide of this game.
	marstar.x(x,y) : Use it follow the rule in the <How to find position> part,put your position inside,then 'X' will be on that position on board.
	marstar.o(x,y) : Use it follow the rule in the <How to find position> part,put your position inside,then 'O' will be on that position on board.
	marstar.ai() : DO NOT PUT ANYTHING INSIDE,this function is the AI player function,it will fill the board using 'A' and race with you.
	How easy this game is!
Game rules:
	1.If your piece fill a line(every line is okay,but first it have to be a line),then you win!
		['#','#','X']
		['#','X','#']
		['X','#','#']
	See?In this case playerX won!
	2.Your first placed piece will disapear everytime when there are three same piece on board!So that allowed you to play forever!
	Okay,that is all,HAVE FUN :)
	

	Developer: Marcy"""
time.sleep(1)
print(colour('--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------','magenta',bold = True,bg = None))
print(colour(txt,'cyan',bold = True,bg = None))	
time.sleep(1)
print(colour('--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------','green',bold = True,bg = None))
print(colour('Email address:        huazii@gmail.com  ,any advice for this game can be send to this address! -Marcy','magenta',bold = True,bg = 'cyan'))
time.sleep(1)

print(colour('--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------','yellow',bold = True,bg = None))
print(colour('Enjoy the fun of this Tic-Tac-Toe game!','magenta',bold = True,bg = 'cyan'))
time.sleep(1)
print(colour('--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------','cyan',bold = True,bg = None))
print(colour('Developer:           Marcy            ','green',bold = True,bg = 'magenta'))
time.sleep(1)
print(colour("Why don't you start by type 'marstar.ai()'?",'white',bold = True,bg = None))

def col():
	global board
	cols = ['magenta','green','yellow','cyan','white','red','blue']
	pos = random.randrange(7)
	outputs = colour(board,cols[pos],bold = True,bg = None)
	return outputs
		
def guide():
	print(colour(txt,'cyan',bold = True,bg = None))
	
def is_line():
	if board[0][0] == board[1][0] == board[2][0] != '#':
		if board[0][0] == 'X':
			return a
		elif board[0][0] == 'O':
			return b
		else:
			return c
	elif board[0][1] == board[1][1] == board[2][1] != '#':
		if board[0][1] == 'X':
			return a
		elif board[0][1] == 'O':
			return b
		else:
			return c
	elif board[0][2] == board[1][2] == board[2][2] != '#':
		if board[0][2] == 'X':
			return a
		elif board[0][2] == 'O':
			return b
		else:
			return c
	elif board[0][0] == board[0][1] == board[0][2] != '#':
		if board[0][0] == 'X':
			return a
		elif board[0][0] == 'O':
			return b
		else:
			return c
	elif board[1][0] == board[1][1] == board[1][2] != '#':
		if board[1][0] == 'X':
			return a
		elif board[1][0] == 'O':
			return b
		else:
			return c
	elif board[2][0] == board[2][1] == board[2][2] != '#':
		if board[2][0] == 'X':
			return a
		elif board[2][0] == 'O':
			return b
		else:
			return c
	elif board[0][0] == board[1][1] == board[2][2] != '#':
		if board[0][0] == 'X':
			return a
		elif board[0][0] == 'O':
			return b
		else:
			return c
	elif board[2][0] == board[1][1] == board[0][2] != '#':
		if board[2][0] == 'X':
			return a
		elif board[2][0] == 'O':
			return b
		else:
			return c
	else:
		return a + b


def x(x, y):
	global board_original
	global output_board
	global recent
	global recent1
	global char_colour
	global num1
	global num2
	global nums
	global board
	board_original = board.copy()
	output_board = board.copy()

	recent.append((x,y))
	if len(recent) > 3:
		old = recent.pop(0)
		board[old] = '#'

	
	if board[x][y] == '#':
		board[x][y] = 'X'
		nums[x][y] = 1
		board_original = board.copy()
		print(col())
	elif board[x][y] == 'A':
		print(col())
		print('Sorry,board(',x,',',y,'is taken by playerAI')
	elif board[x][y] == 'O':
		print(col())
		print('Sorry,board(',x,',',y,'is taken by playerO')
	else:
		print(col())
		print('Sorry,board(',x,',',y,'is taken by yourself')
	result = is_line()
	if result == a:
		print(colour('@PlayerX won!','magenta',bold = True,bg = 'green'))
		board = np.full((3,3),'#')
		nums = np.zeros((3,3))
		recent = []
		recent1 = []
		cloud = []
	elif result == b:
		print(colour('@PlayerO won!','yellow',bold = True,bg = 'blue'))
		board = np.full((3,3),'#')
		nums = np.zeros((3,3))
		recent = []
		recent1 = []
		cloud = []
	elif not any('#' in row for row in board):
		print('DRAW,game over :<')
		board = np.full((3,3),'#')
		nums = np.zeros((3,3))
		recent = []
		recent1 = []
		cloud = []


def o(x, y):
	global board_original
	global recent
	global recent1
	global num1
	global num2
	global nums
	global board
	global char_colour
	baord_orignal = board.copy()
	recent1.append((x,y))

	if len(recent1) > 3:
		old=recent1.pop(0)
		board[old]='#'

	if board[x][y] == '#':
		board[x][y] = 'O'
		nums[x][y] = 127
		board_original = board.copy()
		print(col())
	elif board[x][y] == 'X':
		print(col())
		print('Sorry,board(',x,',',y,'is taken by playerX')
	elif board[x][y] == 'A':
		print(col())
		print('Sorry,board(',x,',',y,'is taken by playerAI')
	else:
		print(col())
		print('Sorry,board(',x,',',y,'is taken by yourself') 
	result = is_line()
	if result == a:
		print(colour('@PlayerX won!','magenta',bold = True,bg = 'green'))
		board = np.full((3,3),'#')
		nums = np.zeros((3,3))
		recent1 = []
		recent = []
		cloud = []
	elif result == b:
		print(colour('@PlayerO won!','yellow',bold = True,bg = 'blue'))
		board = np.full((3,3),'#')
		nums = np.zeros((3,3))
		recent1 = []
		recent = []
		cloud = []
	elif not any('#' in row for row in board):
		print('DRAW,game over :<')
		board = np.full((3,3),'#')
		nums = np.zeros((3,3))
		recent1 = []
		recent = []
		cloud = []


def clear():
	global recent
	global cloud
	global recent1
	global board
	global nums
	recent = []
	cloud = []
	recent1 = []
	board = np.full((3,3),'#')
	nums = np.zeros((3,3))
	print(colour('Board reset.Data reset.','magenta',bold = True,bg = 'cyan'))

def ai():
	global recent
	global char_colour
	global cloud
	global board_original
	global board,nums
	rows, cols = board.shape
	found = False
	if 'X' not in board and 'A' not in board and 'O' not in board:
		board[1][1] = 'A'
		cloud.append((1,1))
		print(col())
		found = True	
	else:
		for i in range(rows):
			countX = 0
			countO = 0
			empty_j = None
			for j in range(cols):
				if board[i][j] == 'X':
					countX += 1
				elif board[i][j] == 'O':
					countO += 1
				elif board[i][j] == '#':
					empty_j = j
	
			if empty_j is not None:
				if countX == 2 or countO == 2:
					pos = (i, empty_j)
					board[pos] = 'A'
					cloud.append(pos)
					if len(cloud) > 3:
						old = cloud.pop(0)
						board[old] = '#'
					print(col())
					found = True
					break
		if not found:
			for j in range(cols):
				countX = 0
				countO = 0
				empty_i = None
				for i in range(rows):
					if board[i][j] == 'X':
						countX += 1
					elif board[i][j] == 'O':
						countO += 1
					elif board[i][j] == '#':
						empty_i = i
	
				if empty_i is not None:
					if countX == 2 or countO == 2:
						pos = (empty_i, j)
						board[pos] = 'A'
						cloud.append(pos)
						if len(cloud) > 3:
							old = cloud.pop(0)
							board[old] = '#'
							print(col())
						found = True
						break
		if not found:
			countX = 0
			countO = 0
			empty_k = None
			for k in range(3):
				if board[k][k] == 'X':
					countX += 1
				elif board[k][k] == 'O':
					countO += 1
				else:
					empty_k = k
			if empty_k is not None and (countX == 2 or countO == 2):
				pos = (empty_k, empty_k)
				board[pos] = 'A'
				cloud.append(pos)
				if len(cloud) > 3:
					old = cloud.pop(0)
					board[old] = '#'
				print(col())
				found = True
		if not found:
			countX = 0
			countO = 0
			empty_k = None
			for k in range(3):
				i = k
				j = 2 - k
				if board[i][j] == 'X':
					countX += 1
				elif board[i][j] == 'O':
					countO += 1
				else:
					empty_k = (i,j)
			if empty_k is not None and (countX == 2 or countO == 2):
				pos = empty_k
				board[pos] = 'A'
				cloud.append(pos)
				if len(cloud) > 3:
					old = cloud.pop(0)
					board[old] = '#'
				print(col())
				found = True
		if not found:
			for i in range(rows):
				countA = 0
				empty_j = None
				for j in range(cols):
					if board[i][j] == 'A':
						countA += 1
					elif board[i][j] == '#':
						empty_j = j
				if empty_j is not None and countA == 2:
					pos = (i, empty_j)
					board[pos] = 'A'
					cloud.append(pos)
					if len(cloud) > 3:
						old = cloud.pop(0)
						board[old] = '#'
					print(col())
					found = True
					break
		if not found:
			for j in range(cols):
				countA = 0
				empty_i = None
				for i in range(rows):
					if board[i][j] == 'A':
						countA += 1
					elif board[i][j] == '#':
						empty_i = i
				if empty_i is not None and countA == 2:
					pos = (empty_i, j)
					board[pos] = 'A'
					cloud.append(pos)
					if len(cloud) > 3:
						old = cloud.pop(0)
						board[old] = '#'
					print(col())
					found = True
					break
		if not found:
			countA = 0
			empty_k = None
			for k in range(3):
				if board[k][k] == 'A':
					countA += 1
				elif board[k][k] == '#':
					empty_k = k
			if empty_k is not None and countA == 2:
				pos = (empty_k, empty_k)
				board[pos] = 'A'
				cloud.append(pos)
				if len(cloud) > 3:
					old = cloud.pop(0)
					board[old] = '#'
				print(col())
				found = True
		if not found:
			countA = 0
			empty_k = None
			for k in range(3):
				i = k
				j = 2 - k
				if board[i][j] == 'A':
					countA += 1
				elif board[i][j] == '#':
					empty_k = (i,j)
			if empty_k is not None and countA == 2:
				pos = empty_k
				board[pos] = 'A'
				cloud.append(pos)
				if len(cloud) > 3:
					old = cloud.pop(0)
					board[old] = '#'
				print(col())
				found = True
		if not found:
			positions = list(zip(*np.where(board == '#')))
			if positions:
				pos = random.choice(positions)
				board[pos] = 'A'
				cloud.append(pos)
				if len(cloud) > 3:
					old = cloud.pop(0)
					board[old] = '#'
				print(col())
	result = is_line()
	if result == c:
		print(colour('@PlayerAI won!','blue',bold = True,bg = 'yellow'))
		print(colour('From @PlayerAI:"HOORAY!I won!I like playing with you!Hope next time we can play together again =) =) :)!"','magenta',bold = True,bg = 'cyan'))
		board = np.full((3,3),'#')
		nums = np.zeros((3,3))
		cloud = []
		recent = []
		recent1 = []
		
	else:
		string = ['Your turn :)','Your turn =)','I am done,your turn :>','Your turn!','I think i am going to win =)!Your turn!','YOUR TURN :)','Your turn :) :)']
		rand_num = random.randrange(len(string))
		colours = ['green','magenta','yellow','red','blue','cyan','white']
		c_pos = random.randrange(7)					
		print(colour(string[rand_num],colours[c_pos],bold = True,bg = None))			
		

