Files @ f9ab2070bd69
Branch filter:

Location: OneEye/src/go/core.py - annotation

Laman
Engine: more tests and fixes
3798475f45c1
3798475f45c1
077600f0c5f8
07f3fda1cbd7
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
07f3fda1cbd7
077600f0c5f8
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
4e67f9e9f027
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
07f3fda1cbd7
07f3fda1cbd7
3798475f45c1
0cb3fbe06b5d
07f3fda1cbd7
07f3fda1cbd7
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
077600f0c5f8
3798475f45c1
3798475f45c1
077600f0c5f8
0cb3fbe06b5d
f9ab2070bd69
07f3fda1cbd7
07f3fda1cbd7
f9ab2070bd69
f9ab2070bd69
f9ab2070bd69
f9ab2070bd69
f9ab2070bd69
f9ab2070bd69
077600f0c5f8
07f3fda1cbd7
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
4e67f9e9f027
3798475f45c1
0cb3fbe06b5d
0cb3fbe06b5d
0cb3fbe06b5d
0cb3fbe06b5d
0cb3fbe06b5d
077600f0c5f8
077600f0c5f8
077600f0c5f8
07f3fda1cbd7
07f3fda1cbd7
07f3fda1cbd7
3798475f45c1
07f3fda1cbd7
a98de30efa51
07f3fda1cbd7
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
3798475f45c1
import logging as log

from util import EMPTY,BLACK,WHITE, colorNames,hashBoard
from .helperboard import HelperBoard
from .gamerecord import GameRecord


class Go:
	## Initializes self.board to a list[r][c]=EMPTY.
	def __init__(self,boardSize=19):
		self.boardSize=boardSize
		self.board=[[EMPTY]*boardSize for x in range(boardSize)]
		self.toMove=BLACK
		self._helper=HelperBoard(self.board)
		self._hashes=[]
		self._record=GameRecord()

	## Executes a move.
	#
	#  Doesn't check for kos. Suicide not allowed.
	#
	#  @param color BLACK or WHITE
	#  @return True on success, False on failure (illegal move)
	def doMove(self,color,row,col):
		if color!=self.toMove: log.warning("move by %s out of order",colorNames[color])
		if self.board[row][col]!=EMPTY: return False

		self.board[row][col]=color

		# capture neighbors
		for r,c in ((-1,0),(1,0),(0,-1),(0,1)):
			self._helper.clear()
			if not self._helper.floodFill(-color,row+r,col+c,EMPTY): self._remove()

		# check for suicide and prevent it
		self._helper.clear()
		if not self._helper.floodFill(color,row,col,EMPTY):
			self.board[row][col]=EMPTY
			return False
		self._record.move(color,row,col)
		self.toMove=-1*color
		self._hashes.append(self.hash())
		return True

	def undoMove(self,r,c,captures):
		assert self.board[r][c]==-1*self.toMove, "{0}!={1}".format(self.board[r][c],-1*self.toMove)

		if len(captures)>0:
			self._helper.clear()
			for (ri,ci) in captures:
				self._helper.floodFill(EMPTY,ri,ci)
			self._fill(self.toMove)

		self.board[r][c]=EMPTY
		self.toMove*=-1
		self._hashes.pop()

	def transitionMove(self,board):
		res=transitionMove(self.board,board)
		if not res: return res
		(r,c,color)=res
		return self.doMove(color,r,c)

	def load(self,board):
		for (r,row) in enumerate(board):
			for (c,x) in enumerate(row):
				self.board[r][c]=x

	def hash(self):
		return hashBoard(self.board)

	## Removes stones at coordinates marked with True in self.helper.
	def _remove(self):
		self._fill(EMPTY)

	def _fill(self,filling):
		for (r,c) in self._helper.getContinuousArea():
			self.board[r][c]=filling


def isLegalPosition(board):
	boardSize=len(board)
	temp=[[None]*boardSize for x in range(boardSize)]

	for r in range(boardSize):
		for c in range(boardSize):
			if board[r][c]==EMPTY: continue
			if temp[r][c]: continue
			if not dfs([(r,c)],board,temp): return False
	return True


def transitionMove(state1,state2):
	moves=[]
	for (r,(row1,row2)) in enumerate(zip(state1,state2)):
		for (c,(item1,item2)) in enumerate(zip(row1,row2)):
			if item1==EMPTY and item2!=EMPTY:
				moves.append((r,c,item2))

	if len(moves)==0:
		log.info("no new stone")
		return None
	elif len(moves)==1:
		log.info("new stone: %s",moves[0])
		return moves[0]
	else:
		log.warning("too many new stones: %s",moves)
		return False


def dfs(stack,board,mask):
	boardSize=len(board)
	(r,c)=stack[0]
	color=board[r][c]

	while len(stack)>0:
		(r,c)=stack.pop()
		if board[r][c]==EMPTY: return True
		elif board[r][c]!=color: continue
		elif mask[r][c]: return True
		mask[r][c]=True
		for (x,y) in ((0,-1),(-1,0),(0,1),(1,0)):
			if 0<=r+y<boardSize and 0<=c+x<boardSize:
				stack.append((r+y,c+x))
	return False