#PYTHON PyNeg(Trait,Pass,Depth,alpha,beta)

maxDepth=0
totCoups=0
dir=[1,8,9,10,-1,-8,-9,-10] 

def PyNextMov(Tr,ind,Bo,OrdM):
  import hpprime
  from hpprime import eval as ppleval

  res=0
  res2=[]
  i1=ind
  while (i1<len(OrdM)) and (res==0):
    cas=int(OrdM[i1]-1)  
    if Bo[cas]==0:
      for i3 in range(0,8):
        i2=1
        di=dir[i3]
        res1=[]
        while Bo[cas+i2*di] == (3-Tr):
          res1.append(cas+i2*di)
          i2+=1
        if (i2>1) and (Bo[cas+i2*di]==Tr):
          res=cas
          res2=res2+res1
    i1+=1
  if res==0:
    i1+=1
  return res,res2,i1

def PyMovOK(board,trait,cas1):
  if board[cas1] != 0: 
    return 0
  for i3 in range(0,8):
    i2=1
    di=dir[i3]
    while board[cas1+i2*di] == (3-trait):
      i2+=1  
    if (i2>1) and (board[cas1+i2*di]==trait):
      return 1
  return 0

def PyEval(board,trait):
  import math

# possibilité de jouer un coin  
  pycorners=[10,17,73,80]
  movCorn=0
  for i1 in range(0,4): 
    x=PyMovOK(board,trait,pycorners[i1])
    if x==1:
      movCorn+=1 
    else:
      x=PyMovOK(board,3-trait,pycorners[i1])
      if x==1:
        movCorn+=-1 

# possession d'un coin
  corners=0;
  for i1 in range(0,4): 
    if board[pycorners[i1]]==trait: 
      corners+=1
    else:
      if board[pycorners[i1]]==(3-trait): 
        corners+=-1

# cases X 
  pyxsquares=[20,25,65,70]
  xrisk=0
  for i1 in range(0,4): 
    if board[pycorners[i1]]==0: 
      if board[pyxsquares[i1]]==trait:
        xrisk+=1  
      else:
        if board[pyxsquares[i1]]==(3-trait):
          xrisk+=-1  

# case C
  pycsquares=[11,19,16,26,64,74,71,79] 
  crisk=0
  for i1 in range(0,8): 
    i2=math.floor(i1/2)
    if board[pycorners[i2]]==0: 
      if board[pycsquares[i1]]==trait:  
        crisk+=1
      else:    
        if board[pycsquares[i1]]==(3-trait):  
          crisk+=-1

# Stabilité propagée depuis les coins 

  pyBoardI=[9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,9,9,9,9,9,9,9,9,9,9]

  pyBords=[[[11,12,13,14,15,16],[19,28,37,46,55,64]],[[16,15,14,13,12,11],[26,35,44,53,62,71]],[[74,75,76,77,78,79],[64,55,46,37,28,19]],[[79,78,77,76,75,74],[71,62,53,44,35,26]]]
  VPDA=pyBoardI.copy()
  ok=0
  for i1 in range(0,4): 
    if board[pycorners[i1]]!=0:
      for i2 in range(0,2):
        for i3 in range(0,6):
          if board[pyBords[i1][i2][i3]]==board[pycorners[i1]]:
            VPDA[pyBords[i1][i2][i3]]=board[pycorners[i1]]
            ok=1        
          else:
            break
  pda=0
  if ok==1:
    for i1 in range(10,81): 
      if VPDA[i1]==trait:
        pda+=1
      else:
        if VPDA[i1]==(3-trait):
          pda+=-1 
    
# Mobilité réelle ou
# Mobilité simplifiée : combien de cases vides touchent un pion adverse

  mobil=0
  for y in range (0,8):
    for x in range (0,8):
      i1=(y+1)*9+x+1
      x=PyMovOK(board,trait,i1)
      if x==1:
        mobil+=1 
      x=PyMovOK(board,3-trait,i1)
      if x==1:
        mobil+=-1
 
#      if board[i1]==0:
#        for di in range(0,8):
#          adj=i1+dir[di]
#          if (adj>=10) and (adj<=81) and (board[adj]==(3-trait)):
#            mobil+=1
#            break
#        for di in range(0,8):
#          adj=i1+dir[di]
#          if (adj>=10) and (adj<=81) and (board[adj]==trait):
#            mobil+=-1
#            break

# Stabilité locale et frontière 

  stable=0
  frontier=0
  for y in range (2,8):
    for x in range (2,8):
      i1=y*9+x
      if (board[i1] == 2) or (board[i1] == 1):
        surrounded=0
        emptyAdj=0
        for i2 in range(0,8):
          adj=i1+dir[i2]
          if (adj>=10) and (adj<=80):
            if board[adj]!=0:
              surrounded+=1
            else:
              if board[adj]==0:
                emptyAdj+=1
        if surrounded==8: 
          if board[i1]==trait:
            stable+=1 
          else:
            stable+=-1
        if emptyAdj>0:
          if board[i1]==trait:
            frontier+=1;
          else: 
            frontier+=-1;

  score=(10*corners+2*pda+6*movCorn-5*xrisk-crisk+mobil+stable-frontier)
  return score
 
def PyNega(board,ordre,trait,nbPio,pass1,depth,alpha,beta):
  
  global totCoups
   
  import hpprime
  from hpprime import eval as ppleval

  nbPioB=[0,0]
  maxVal=-999

  if depth==0:
    return PyEval(board,trait)
  if (nbPio[0]+nbPio[1])==64:  
    return (nbPio[trait-1]-nbPio[2-trait])

  i1=0
  res,res2,i1=PyNextMov(trait,i1,board,ordre)
  if res==0:
    pass1+=1
    if pass1<2:
      maxVal=-PyNega(board,ordre,3-trait,nbPio,pass1,depth-1,-beta,-alpha)
      return maxVal
    else:
      return (nbPio[trait-1]-nbPio[2-trait])
  else:
    pass1=0     
   
  while res > 0:
    totCoups+=1
    if (totCoups % 250)==0:
      ppleval('TEXTOUT_P("# "+"%s",235,96,3,RGB(255,255,255),160,RGB(128,128,128))' %totCoups);
    
    boardB=board.copy()
    boardB[res]=trait
    i2=0
    while i2 < len(res2):
      boardB[res2[i2]]=trait
      i2+=1
    nbPioB[trait-1]=nbPio[trait-1]+len(res2)+1
    nbPioB[2-trait]=nbPio[2-trait]-len(res2)
    value=-PyNega(boardB,ordre,3-trait,nbPioB,pass1,depth-1,-beta,-alpha)
    if value > maxVal: 
      maxVal=value
      if depth==maxDepth:
        bestMov=res 
        ppleval('PyReversi.BestMov:=CAS.eval("%s")' %bestMov)
    if maxVal > alpha:
      alpha=maxVal
    if alpha >= beta:
      break
    res,res2,i1=PyNextMov(trait,i1,board,ordre)
  return maxVal;

import sys
import hpprime
from hpprime import eval as ppleval

separator = int(ppleval('HSeparator'))
ppleval('HSeparator := 0')

try:
  board=ppleval('PyReversi.PyBoard')
  ordre=ppleval('PyReversi.PyOrdre')
  nbPio=ppleval('PyReversi.PyNbPio')
  tr=int(sys.argv[0])
  pass1=int(sys.argv[1])
  depth=int(sys.argv[2])
  alpha=-int(sys.argv[3])
  beta=int(sys.argv[4])

  maxDepth=depth
  score=PyNega(board,ordre,tr,nbPio,pass1,depth,alpha,beta)
  ppleval('PyReversi.Sco:=CAS.eval("%s")' %score)
  ppleval('PyReversi.NbCoups:=CAS.eval("%s")' %totCoups)
finally:
  ppleval('HSeparator := ' + repr(separator))

#END

LOCAL PyNegamax(Board,Ordre,Trait,NbPio,Pass,Depth,alpha,beta)
BEGIN
  PyBoard:=Board;
  PyOrdre:=Ordre;
  PyNbPio:=NbPio;
  PyNeg(Trait,Pass,Depth,-alpha,beta);
  BestMov:=BestMov+1;
  RETURN Sco;
END;
