Skip to content

Commit

Permalink
version 1.3.6, fix bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
houluy committed Oct 12, 2020
1 parent b9a7e30 commit 944000d
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 27 deletions.
95 changes: 80 additions & 15 deletions chessboard/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from itertools import product
import logging

import chessboard.logger
from colorline import cprint


Expand Down Expand Up @@ -53,12 +52,14 @@ def __init__(self, board_size=3, ch_off='O', ch_def='X', ch_blank=' ', win=3):#,
self.game_round = 0
self.start_player = 1
self.win = win
self.logger = logging.getLogger(__name__)
if self.board_size > MAX_LOW:
raise ValueError(f'Board size has reached its limit ({MAX_LOW})!')
if self.win > self.board_size:
raise ValueError('Winning number exceeds the board size!')
self.pos_range = range(self.board_size)
self.pos = [[0 for _ in self.pos_range] for _ in self.pos_range]
self.top_row = [self.board_size for _ in self.pos_range]
self.available_actions = list(product(self.pos_range, self.pos_range))
self.move = (-1, -1)
#elif pos:
Expand Down Expand Up @@ -91,6 +92,7 @@ def __init__(self, board_size=3, ch_off='O', ch_def='X', ch_blank=' ', win=3):#,
self.full_angle = [_*math.pi/4 for _ in range(FULL_DIR_NUM)]

self.check_re = re.compile(r'^\s*([1-9]\d*)\s*,\s*([1-9]\d*)\s*$')
self.check_row_re = re.compile(r'^([1-9]\d*)$')

def __str__(self):
return ''.join([''.join([str(x) for x in y]) for y in self.pos])
Expand All @@ -106,7 +108,7 @@ def mround(self):
return self.board_size**2

def info(self):
logging.debug(f"Current Player: {self.player}, last move: {self.move}")
self.logger.info(f"Current Player: {self.player}, last move: {self.move}")

def celebrate(self, duel=False):
if not duel:
Expand All @@ -133,6 +135,20 @@ def process_ipt(self, ipt):
self.validate_pos(pos)
return pos

def process_single_ipt(self, ipt):
"""This function is used to process single input of row, particular for fourinarow game"""
mat = self.check_row_re.match(ipt)
if mat is None:
raise ValueError('Error format of coordinate, must be a tuple of one integer, e.g., 1')
column = int(mat.groups()[0])
if column > self.board_size or column <= 0:
raise ValueError(f'Coordinate {column} exceeds range of chessboard with {self.board_size}')
row = self.get_row_by_column(column)
if row == 0:
raise ValueError(f'There is a chess piece!')
pos = (row - 1, column - 1)
return pos

@property
def state(self):
return [y for x in self.pos for y in x]
Expand All @@ -141,7 +157,7 @@ def str2state(self, pos_str):
return [int(x) for x in pos_str]

def get_column(self, column):
return [_[column] for _ in self.pos]
return [_[column - 1] for _ in self.pos]

def state2board(self, state):
board_size = int(math.sqrt(len(state)))
Expand Down Expand Up @@ -262,7 +278,10 @@ def asc2pos(self, ch):
return ch

def get_player(self):
return 2 - self.game_round % 2
if self.game_round % 2:
return 1
else:
return 2

def another_player(self, player=None):
if not player:
Expand All @@ -282,6 +301,9 @@ def set_pos(self, pos, validate=False):#, check=False):
player = self.get_player()
self.history[self.game_round] = copy.deepcopy(self.pos)
self.pos[x][y] = player
self.logger.debug(f"SET_POS -- Current player: {player}")
if self.top_row[y] > x:
self.top_row[y] = x
self.user_pos_dict[player].append(pos)

def play(self):
Expand Down Expand Up @@ -310,6 +332,7 @@ def clear(self):
self.graph = copy.deepcopy(self.pos)
self.game_round = 0
self.available_actions = list(product(self.pos_range, self.pos_range))
self.top_row = [self.board_size for _ in self.pos_range]

def input(self):
ipt = input("Please input your chess position:")
Expand Down Expand Up @@ -382,31 +405,54 @@ def distance(self, piecex, piecey):
return max(abs(piecex[0] - piecey[0]), abs(piecex[1], piecey[1]))

def check_win_by_step(self, pos, player, line_number=None):
'''Check winners by current step'''
''' Check winners by current step
Eight direction:
🡔|↑|🡕
←|o|→
🡗|↓|🡖
3π/4| π |5π/4
π/2| O |3π/2
π/4| 0 |7π/4
(-1, -1)|(-1, 0)|(-1, 1)
(0, -1)|(0, 0) |(0, 1)
(1, -1)|(1, 0) |(1, 1)
# direction = [Forward (0 ~ π), Backward (π ~ 2π)]
'''
if not line_number:
line_number = self.win
x, y = pos
self.logger.debug(f"Current position: {(x, y)}")
for ang in self.half_angle:
self.win_list = [(x, y)]
angs = [ang, ang + math.pi]
line_num = 1
radius = 1
direction = [1, 1]
while True:
while direction != [0, 0]:
if line_num == line_number:
return True
if direction == [0, 0]:
break
for ind, a in enumerate(angs):
target_x = int(x + radius*(sign(math.cos(a)))) if direction[ind] else -1
target_y = int(y - radius*(sign(math.sin(a)))) if direction[ind] else -1
if target_x < 0 or target_y < 0 or target_x > self.board_size - 1 or target_y > self.board_size - 1:
direction[ind] = 0
elif self.pos[target_x][target_y] == player:
self.win_list.append((target_x, target_y))
line_num += 1
if direction[ind]:
target_x = int(x + radius*(sign(math.cos(a))))
target_y = int(y - radius*(sign(math.sin(a))))
else:
target_x = target_y = -1
if target_x < 0 or target_y < 0 or target_x >= self.board_size or target_y >= self.board_size:
direction[ind] = 0
else:
next_pos = self.pos[target_x][target_y]
self.logger.debug(f"Radius: {radius}, Angle: {a * 57.2957795:.0f}, Position: {(target_x, target_y)}"
f"direction: {direction}, Player: {player} "
f"Next_pos: {next_pos}")
if next_pos == player:
self.win_list.append((target_x, target_y))
line_num += 1
self.logger.debug(f"Win_list: {self.win_list}")
else:
direction[ind] = 0
else:
radius += 1
else:
Expand All @@ -427,6 +473,25 @@ def count_chess(self):
result[j - 1] = result[j - 1] + 1 if j != 0 else result[j - 1]
return result

def get_row_by_column(self, column):
'''Get the available row number of the given column
e.g.:
1 2 3
1| | |X|
2|O| |O|
3|X| |X|
assert get_row_by_column(1) == 1
assert get_row_by_column(2) == 3
assert get_row_by_column(3) == 0
NOTE: 0 is unavailable move
Args:
column: The actual index of column (1, 2, 3 in the e.g.)
Return:
int: The actual index of top index of row (0, 1, 2, 3 in the e.g.)
'''
return self.top_row[column - 1]


class ChessboardExtension(Chessboard):
'''Provide extended methods for Class Chessboard'''
Expand Down
9 changes: 0 additions & 9 deletions chessboard/logger.py

This file was deleted.

2 changes: 1 addition & 1 deletion chessboard/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '1.3.4'
__version__ = '1.3.6'
2 changes: 1 addition & 1 deletion chessboardCLI.egg-info/PKG-INFO
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Metadata-Version: 1.2
Name: chessboardCLI
Version: 1.3.4
Version: 1.3.6
Summary: Chessboard generator in command line
Home-page: https://github.com/houluy/chessboard
Author: Houlu
Expand Down
1 change: 0 additions & 1 deletion chessboardCLI.egg-info/SOURCES.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
README.md
setup.py
chessboard/__init__.py
chessboard/logger.py
chessboard/version.py
chessboardCLI.egg-info/PKG-INFO
chessboardCLI.egg-info/SOURCES.txt
Expand Down
Binary file added dist/chessboardCLI-1.3.6-py3-none-any.whl
Binary file not shown.
Binary file added dist/chessboardCLI-1.3.6.tar.gz
Binary file not shown.
27 changes: 27 additions & 0 deletions tests/test_chessboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,30 @@ def test_state2board(self):
board = [[1, 2, 0, 1], [2, 0, 1, 1], [2, 2, 1, 1], [1, 0, 0, 0]]
self.assertEqual(self.chessboard.state2board(state), board)

def test_play(self):
self.chessboard.clear()
self.chessboard.play()

def test_column(self):
self.chessboard.clear()
self.chessboard.set_pos((1, 1))
columns = self.chessboard.get_column(2)
self.assertEqual(columns, [0, 1, 0])
top_row = self.chessboard.get_row_by_column(2)
self.assertEqual(top_row, 2)
self.chessboard.game_round += 1
self.chessboard.set_pos((0, 1))
columns = self.chessboard.get_column(2)
self.assertEqual(columns, [2, 1, 0])
top_row = self.chessboard.get_row_by_column(2)
self.assertEqual(top_row, 1)

def test_process_ipt(self):
valid_ipt = '1, 2'
pos = self.chessboard.process_ipt(valid_ipt)
self.assertEqual(pos, (0, 1))
valid_column_ipt = '1'
pos = self.chessboard.process_single_ipt(valid_column_ipt)
self.assertEqual(pos, 0)


0 comments on commit 944000d

Please sign in to comment.