#!/usr/bin/env python3
# 4x4 Othello
# on 2024.12.10 by maechan
#
BLACK = 1
WHITE = 0
dx = [1,0,-1,0,1,1,-1,-1]
dy = [0,1,0,-1,1,-1,-1,1]

def move(ce, d):
  x = ce // 4 + dx[d]
  y = ce % 4 + dy[d]
  if (x < 0 or x >= 4 or y < 0 or y >=4):
    return -1
  else:
    return x * 4 + y

def iscolor(bl,wh,co,ce):
  if (ce == -1):
    return False
  elif (co == BLACK):
    return ((bl >> int(ce)) & 1)
  else:
    return ((wh >> int(ce)) & 1)

def put(bl,wh,co,ce):
  if (((bl | wh) >> int(ce) ) & 1):
    return 0
  result = 0
  for d in range(8):
    rev = 0
    ce2 = move(ce,d)
    while (iscolor(bl,wh,1-co,ce2)):
      rev |= 1 << int(ce2)
      ce2 = move(ce2,d)
    if (iscolor(bl,wh,co,ce2)):
      result |= rev
  return result

def calc(bl,wh,co):
  nbl = 0
  nwh = 0
  nem = 0
  for ce in range(16):
    if ((bl >> int(ce)) & 1):
      nbl += 1
    elif ((wh >> int(ce)) & 1):
      nwh += 1
    else:
      nem += 1
  if (nbl > nwh):
    nbl += nem
  elif (nbl < nwh):
    nwh += nem
  if (co == BLACK):
    return nbl - nwh
  else:
    return nwh - nbl

import numpy as np

def rec(alpha,beta,bl,wh,co):
  mine = np.array([])
  opp = np.array([])
  for ce in range(16):
    if (put(bl,wh,co,ce)):
      mine = np.append(mine,ce)
      # print("mine",mine)
    if (put(bl,wh,1-co,ce)):
      opp = np.append(opp,ce)
      # print("opp ",opp)
  if (len(mine) == 0 and len(opp) == 0):
    return calc(bl,wh,co)
  if (len(mine) == 0):
    return -rec(-beta,-alpha,bl,wh,1-co)
  for ce in mine:
    rev = put(bl,wh,co,ce)
    bl2 = bl ^ rev
    wh2 = wh ^ rev
    if (co == BLACK):
      bl2 |= 1 << int(ce)
    else:
      wh2 |= 1 << int(ce)
    score = -rec(-beta,-alpha,bl2,wh2,1-co)
    alpha = alpha if alpha > score else score
    if (alpha >= beta):
      print ("Beta cut => B:",format(bl,"016b")," W:",format(wh,"016b"))
      return alpha
  return alpha

if __name__ == "__main__":
  bl = (1<<6)|(1<<9)
  wh = (1<<5)|(1<<10)

  score = rec(-16,16,bl,wh,BLACK)
  # print (score," B:",bin(gbl)," W:",bin(gwh))
  print (score)
  
