pythonリバーシ...pyreversi

課題のc++オセロAIが弱すぎて萎える。得点ボード+確定石の近似で評価して終盤は完全読みをしてはいるんだが・・・flashのオセロに負けた・・・

そのせいで一気に萎えた。で、気分転換にpythonリバーシのプログラム書いた。AIは無し。基本的なルールだけの実装。バーッと書いたのでReversi::display_game_overが若干不安。

#!/usr/bin/env python
import re
WHITE = -1
BLANK = 0
BLACK = 1

class Board: # represent reversi board
    def __init__(self):
        self.board = [[0] * 8 for x in range(8)]
        self.board[3][3] = WHITE
        self.board[4][4] = WHITE
        self.board[3][4] = BLACK
        self.board[4][3] = BLACK
        self.turns = 0 # turn counter
        self.current = BLACK # current player
	self.stones = [2, 60, 2] # white, blank, black

    def get_stone(self, x, y):
	return self.board[x][y]
    def get_current(self):
	return self.current
    def get_turn(self):
	return self.turns
    def count_stone(self, st):
	return self.stones[1 + st]
    def pass_turn(self):
	self.current *= -1
    
    def validate_range(self, x, y): # validate input range
        if x < 0 or x > 7 or y < 0 or y > 7:
            return False
        return True

    def validate_input(self, x, y): # validate input
        if not self.validate_range(x, y):
            return False
	if not self.board[x][y] == BLANK:
	    return False
        elif not self.can_reverse(x, y):
            return False
        return True

    def can_reverse(self, x, y):
        storex, storey = x, y
        for dx in [-1, 0, 1]:
            for dy in [-1, 0, 1]:
		if not self.validate_range(x + dx, y + dy):
		    continue
                if self.board[x + dx][y + dy] == -self.current:
		    if self.can_reverse_one_dir(x + dx, y + dy, dx, dy):
			return True
	return False
    
    def can_reverse_one_dir(self, x, y, dx, dy):
	while self.validate_range(x, y):
	    if self.board[x][y] == BLANK:
		return False
	    elif self.board[x][y] == -self.current:
		x += dx
		y += dy
		continue
	    elif self.board[x][y] == self.current:
		return True
        return False

    def reverse_one_dir(self, x, y, dx, dy):
	while self.board[x][y] != self.current:
	    if self.board[x][y] == -self.current:
		self.board[x][y] *= -1 # reverse
		self.stones[1 + self.current] += 1
		self.stones[1 + -self.current] -= 1
	    x += dx
	    y += dy
	
    def put_stone(self, x, y):
	self.board[x][y] = self.current
	self.stones[1 + BLANK] -= 1
	self.stones[1 + self.current] += 1

	for dx in [-1, 0, 1]:
	    for dy in [-1, 0, 1]:
		if self.can_reverse_one_dir(x + dx, y + dy, dx, dy):
		    self.reverse_one_dir(x + dx, y + dy, dx, dy)

	self.turns += 1 # incremnt turn
	self.current *= -1 # change turn


class Reversi:
    def __init__(self):
	self.board = Board()
	self.pass_flag = False
	self.mark = ["W", "-", "B"] # each represents white, blank, black

    def display_board(self):
	table = [[0] * 8 for x in range(8)]
	for i in range(8):
	    for j in range(8):
		if self.board.validate_input(i, j):
		    table[i][j] = "*"
		else:
		    table[i][j] = self.mark[1 + self.board.get_stone(i ,j)]
	print "x\\y",
	for i in range(8):
	    print "%d" % i,
	print "" # newline
	print "  ",
	print "--"*8
	for i in range(8):
	    print i,"|",
	    for j in range(8):
		print "%c" % table[i][j],
	    print "" # newline

    def isover(self):
	for i in range(8):
	    for j in range(8):
		if self.board.validate_input(i, j):
		    self.pass_flag = False
		    return False
	if not self.pass_flag:
	    self.pass_flag = True
	    return False
	if self.pass_flag:
	    return True # game is over
	
    def display_game_over(self):
	print "game is now over"
	black = self.board.count_stone(BLACK)
	white = self.board.count_stone(WHITE)
	table = self.mark[1+BLACK]*black + self.mark[1+WHITE]*white
	if len(table) < 64:
	    table += "-" * (64 - len(table))

	print "B:",black,",W:",white
	for i in range(8):
	    for j in range(8):
		print table[i*8 + j],
	    print "" # newline
	if black > white:
	    print "winner black"
	elif black < white:
	    print "winner white"
	else:
	    print "draw"
	
	
    def play(self):
	while not self.isover():
	    self.display_board()
	    if self.pass_flag:
		print "*PASS* ", self.mark[1 + self.board.get_current()]
		self.board.pass_turn()
		continue
	    print "TURN",self.mark[1 + self.board.get_current()],
	    print ":",self.board.get_turn()+1

	    # user input
	    while True:
		point = raw_input("(x, y)>")
		if point == "":
		    continue
		if not re.match(r"\s*?\d \d\s*?", point):
		    print "validater reject."
		    continue
		point = map(eval, point.split())
		if self.board.validate_input(*point):
		    break
		print "validater reject."
		
	    self.board.put_stone(*point)
	self.display_game_over()
	    

def main():
    r = Reversi()
    r.play()
    
if __name__ == '__main__':
    main()