File size: 5,142 Bytes
c4367ba 93ed0ca 293933e edf941b c0fee0a edf941b 293933e c4367ba cc9d79f c4367ba 93ed0ca cc9d79f c0fee0a c4367ba cc9d79f c0fee0a 93ed0ca c0fee0a c4367ba c0fee0a 93ed0ca c0fee0a c4c68cc c0fee0a 23f367b 293933e c0fee0a 293933e 23f367b c0fee0a c4c68cc 293933e 23f367b 293933e c4367ba c0fee0a 23f367b c0fee0a 23f367b 293933e 23f367b c0fee0a 293933e 23f367b c4c68cc 293933e 6ad4064 c4367ba c4c68cc 606d9f2 c4c68cc 9b082e6 293933e 606d9f2 293933e 606d9f2 293933e 606d9f2 293933e c0fee0a 606d9f2 293933e 606d9f2 b8ed266 293933e 606d9f2 c0fee0a 293933e 34d6098 b8ed266 c0fee0a 9b082e6 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
import gradio as gr
from PIL import Image, ImageDraw, ImageFont
import random, time, os
DIRECTIONS = [(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)]
history_log = []
# Attempt to load larger font
try:
FONT_L = ImageFont.truetype("DejaVuSans-Bold.ttf", 28)
FONT_S = ImageFont.truetype("DejaVuSans-Bold.ttf", 16)
except:
FONT_L = ImageFont.load_default()
FONT_S = ImageFont.load_default()
def initialize_board():
b = [[0]*8 for _ in range(8)]
b[3][3], b[4][4] = 1, 1
b[3][4], b[4][3] = -1, -1
return b
def get_flips(board, r, c, p):
if board[r][c] != 0: return []
flips=[]
for dr,dc in DIRECTIONS:
rr,cc=r+dr,c+dc; buf=[]
while 0<=rr<8 and 0<=cc<8 and board[rr][cc]==-p:
buf.append((rr,cc)); rr+=dr; cc+=dc
if buf and 0<=rr<8 and 0<=cc<8 and board[rr][cc]==p:
flips+=buf
return flips
def apply_move(board, r, c, p):
f=get_flips(board,r,c,p)
if not f: return False
board[r][c]=p
for rr,cc in f: board[rr][cc]=p
return True
def choose_move(board, player):
valid=[(r,c) for r in range(8) for c in range(8) if get_flips(board,r,c,player)]
return random.choice(valid) if valid else None
def count_score(board):
b=sum(cell==-1 for row in board for cell in row)
w=sum(cell==1 for row in board for cell in row)
return b,w
def is_game_over(board):
return not any(get_flips(board,r,c,p) for p in (-1,1) for r in range(8) for c in range(8))
def board_to_image(board, state):
board_state, player, last_user, last_ai, history = state
size, cell = 400, 400//8
img=Image.new('RGB',(size,size+cell*4),'darkgreen')
draw=ImageDraw.Draw(img)
b,w=count_score(board_state)
draw.rectangle([0,0,size,cell],fill='navy')
draw.text((10,2),f"BLACK: {b}",font=FONT_L,fill='white')
draw.text((size-180,2),f"WHITE: {w}",font=FONT_L,fill='white')
if is_game_over(board_state):
winner = "Draw" if b==w else ("BLACK WINS" if b>w else "WHITE WINS")
draw.rectangle([0,cell,size,cell*2],fill='darkred')
draw.text((size//2-110,cell+2),winner,font=FONT_L,fill='yellow')
draw.text((size//2-90,cell+30),"Click 'New Game' to restart",font=FONT_S,fill='white')
for r in range(8):
for c in range(8):
x0,y0=c*cell,cell*2+r*cell; x1,y1=x0+cell,y0+cell
draw.rectangle([x0,y0,x1,y1],outline='black')
if board_state[r][c]==0 and get_flips(board_state,r,c,player):
draw.ellipse([x0+cell*0.4,y0+cell*0.4,x0+cell*0.6,y0+cell*0.6],fill='yellow')
if board_state[r][c]==1: draw.ellipse([x0+4,y0+4,x1-4,y1-4],fill='white')
if board_state[r][c]==-1: draw.ellipse([x0+4,y0+4,x1-4,y1-4],fill='black')
for mark,clr in ((last_user,'red'),(last_ai,'blue')):
if mark:
mr,mc=mark; x0,y0=mc*cell,cell*2+mr*cell; x1,y1=x0+cell,y0+cell
draw.rectangle([x0,y0,x1,y1],outline=clr,width=4)
y=cell*2+8*cell+10
for res in history[-5:]:
draw.text((10,y),res,font=FONT_S,fill='white'); y+=cell//2
return img
def click_handler(evt, state):
if state is None:
state = (initialize_board(), -1, None, None, [])
board, player, lu, la, history = state
# Handle evt.index callable vs attribute
if callable(evt.index):
x, y = evt.index()
else:
x, y = evt.index
cell = 400 // 8
c, r = int(x // cell), int((y - cell * 2) // cell)
if 0 <= r < 8 and 0 <= c < 8 and not is_game_over(board):
if apply_move(board, r, c, player):
lu, player = (r, c), -player
yield board_to_image(board, (board, player, lu, la, history)), (board, player, lu, la, history)
if is_game_over(board):
winner = "Draw" if count_score(board)[0] == count_score(board)[1] else ("Black" if count_score(board)[0] > count_score(board)[1] else "White")
history.append(f"Game {len(history)+1}: {winner}")
history_log.append(f"Game {len(history_log)+1}: {winner}")
yield board_to_image(board, (board, player, lu, la, history)), (board, player, lu, la, history)
return
thinking_img = board_to_image(board, (board, player, lu, la, history))
draw = ImageDraw.Draw(thinking_img)
draw.text((150, 400 - 25), "AI Thinking...", font=FONT_S, fill='cyan')
yield thinking_img, (board, player, lu, la, history)
time.sleep(1.5)
ai_mv = choose_move(board, player)
if ai_mv:
apply_move(board, ai_mv[0], ai_mv[1], player)
la, player = ai_mv, -player
yield board_to_image(board, (board, player, lu, la, history)), (board, player, lu, la, history)
def reset_handler():
new_board = initialize_board()
return new_board, -1, None, None, history_log.copy()
with gr.Blocks() as demo:
state=gr.State((initialize_board(),-1,None,None,[]))
img=gr.Image(value=board_to_image(initialize_board(),(initialize_board(),-1,None,None,[])),interactive=True)
new_btn=gr.Button("New Game")
img.select(click_handler,inputs=[state],outputs=[img,state])
new_btn.click(fn=reset_handler,outputs=[state,img])
demo.launch()
|