Spaces:
Sleeping
Sleeping
| import re | |
| # Define patterns using regular expressions | |
| patterns = { | |
| 'five': re.compile('11111'), | |
| 'block_five': re.compile('211111|111112'), | |
| 'four': re.compile('011110'), | |
| 'block_four': re.compile('10111|11011|11101|211110|211101|211011|210111|011112|101112|110112|111012'), | |
| 'three': re.compile('011100|011010|010110|001110'), | |
| 'block_three': re.compile('211100|211010|210110|001112|010112|011012'), | |
| 'two': re.compile('001100|011000|000110|010100|001010'), | |
| } | |
| # Define shapes with associated scores | |
| shapes = { | |
| 'FIVE': 5, | |
| 'BLOCK_FIVE': 50, | |
| 'FOUR': 4, | |
| 'FOUR_FOUR': 44, # Double four | |
| 'FOUR_THREE': 43, # Four with an open three | |
| 'THREE_THREE': 33, # Double three | |
| 'BLOCK_FOUR': 40, | |
| 'THREE': 3, | |
| 'BLOCK_THREE': 30, | |
| 'TWO_TWO': 22, # Double two | |
| 'TWO': 2, | |
| 'NONE': 0 | |
| } | |
| # Initialize a performance record | |
| performance = { | |
| 'five': 0, | |
| 'block_five': 0, | |
| 'four': 0, | |
| 'block_four': 0, | |
| 'three': 0, | |
| 'block_three': 0, | |
| 'two': 0, | |
| 'none': 0, | |
| 'total': 0 | |
| } | |
| # Function to detect shapes on the board | |
| def get_shape(board, x, y, offset_x, offset_y, role): | |
| """ | |
| Detect shape at a given board position. | |
| :param board: The game board. | |
| :param x: X-coordinate. | |
| :param y: Y-coordinate. | |
| :param offset_x: X-direction offset for scanning. | |
| :param offset_y: Y-direction offset for scanning. | |
| :param role: Current player's role. | |
| :return: A tuple of shape, self count, opponent count, and empty count. | |
| """ | |
| opponent = -role | |
| empty_count = 0 | |
| self_count = 1 | |
| opponent_count = 0 | |
| shape = shapes['NONE'] | |
| # Skip empty nodes | |
| if ( | |
| board[x + offset_x + 1][y + offset_y + 1] == 0 | |
| and board[x - offset_x + 1][y - offset_y + 1] == 0 | |
| and board[x + 2 * offset_x + 1][y + 2 * offset_y + 1] == 0 | |
| and board[x - 2 * offset_x + 1][y - 2 * offset_y + 1] == 0 | |
| ): | |
| return [0, self_count, opponent_count, empty_count] | |
| # Check for 'two' pattern | |
| for i in range(-3, 4): | |
| if i == 0: | |
| continue | |
| nx, ny = x + i * offset_x, y + i * offset_y | |
| current_role = board.get((nx, ny)) | |
| if current_role is None: | |
| continue | |
| if current_role == 2: | |
| opponent_count += 1 | |
| elif current_role == role: | |
| self_count += 1 | |
| elif current_role == 0: | |
| empty_count += 1 | |
| if self_count == 2: | |
| if opponent_count == 0: | |
| return shapes['TWO'], self_count, opponent_count, empty_count | |
| else: | |
| return shapes['NONE'], self_count, opponent_count, empty_count | |
| # Reset counts and prepare string for pattern matching | |
| empty_count, self_count, opponent_count = 0, 1, 0 | |
| result_string = '1' | |
| # Build result string for pattern matching | |
| for i in range(1, 6): | |
| nx = x + i * offset_x + 1 | |
| ny = y + i * offset_y + 1 | |
| currentRole = board[nx][ny] | |
| if currentRole == 2: | |
| result_string += '2' | |
| elif currentRole == 0: | |
| result_string += '0' | |
| else: | |
| result_string += '1' if currentRole == role else '2' | |
| if currentRole == 2 or currentRole == opponent: | |
| opponent_count += 1 | |
| break | |
| if currentRole == 0: | |
| empty_count += 1 | |
| if currentRole == role: | |
| self_count += 1 | |
| for i in range(1, 6): | |
| nx = x - i * offset_x + 1 | |
| ny = y - i * offset_y + 1 | |
| currentRole = board[nx][ny] | |
| if currentRole == 2: | |
| result_string = '2' + result_string | |
| elif currentRole == 0: | |
| result_string = '0' + result_string | |
| else: | |
| result_string = '1' if currentRole == role else '2' + result_string | |
| if currentRole == 2 or currentRole == opponent: | |
| opponent_count += 1 | |
| break | |
| if currentRole == 0: | |
| empty_count += 1 | |
| if currentRole == role: | |
| self_count += 1 | |
| # Check patterns and update performance | |
| for pattern_key, shape_key in [('five', 'FIVE'), ('four', 'FOUR'), ('block_four', 'BLOCK_FOUR'), | |
| ('three', 'THREE'), ('block_three', 'BLOCK_THREE'), ('two', 'TWO')]: | |
| if patterns[pattern_key].search(result_string): | |
| shape = shapes[shape_key] | |
| performance[pattern_key] += 1 | |
| performance['total'] += 1 | |
| break | |
| ## 尽量减少多余字符串生成 | |
| if self_count <= 1 or len(result_string) < 5: | |
| return shape, self_count, opponent_count, empty_count | |
| return shape, self_count, opponent_count, empty_count | |
| def count_shape(board, x, y, offset_x, offset_y, role): | |
| opponent = - role | |
| inner_empty_count = 0 # Number of empty positions inside the player's stones | |
| temp_empty_count = 0 | |
| self_count = 0 # Number of the player's stones in the shape | |
| total_length = 0 | |
| side_empty_count = 0 # Number of empty positions on the side of the shape | |
| no_empty_self_count = 0 | |
| one_empty_self_count = 0 | |
| # Right direction | |
| for i in range(1, 6): | |
| nx = x + i * offset_x + 1 | |
| ny = y + i * offset_y + 1 | |
| current_role = board[nx][ny] | |
| if current_role == 2 or current_role == opponent: | |
| break | |
| if current_role == role: | |
| self_count += 1 | |
| side_empty_count = 0 | |
| if temp_empty_count: | |
| inner_empty_count += temp_empty_count | |
| temp_empty_count = 0 | |
| if inner_empty_count == 0: | |
| no_empty_self_count += 1 | |
| one_empty_self_count += 1 | |
| elif inner_empty_count == 1: | |
| one_empty_self_count += 1 | |
| total_length += 1 | |
| if current_role == 0: | |
| temp_empty_count += 1 | |
| side_empty_count += 1 | |
| if side_empty_count >= 2: | |
| break | |
| if not inner_empty_count: | |
| one_empty_self_count = 0 | |
| return { | |
| 'self_count': self_count, | |
| 'total_length': total_length, | |
| 'no_empty_self_count': no_empty_self_count, | |
| 'one_empty_self_count': one_empty_self_count, | |
| 'inner_empty_count': inner_empty_count, | |
| 'side_empty_count': side_empty_count | |
| } | |
| # Fast shape detection function | |
| def get_shape_fast(board, x, y, offsetX, offsetY, role): | |
| if ( | |
| board[x + offsetX + 1][y + offsetY + 1] == 0 | |
| and board[x - offsetX + 1][y - offsetY + 1] == 0 | |
| and board[x + 2 * offsetX + 1][y + 2 * offsetY + 1] == 0 | |
| and board[x - 2 * offsetX + 1][y - 2 * offsetY + 1] == 0 | |
| ): | |
| return [shapes['NONE'], 1] | |
| selfCount = 1 | |
| totalLength = 1 | |
| shape = shapes['NONE'] | |
| leftEmpty = 0 | |
| rightEmpty = 0 | |
| noEmptySelfCount = 1 | |
| OneEmptySelfCount = 1 | |
| left = count_shape(board, x, y, -offsetX, -offsetY, role) | |
| right = count_shape(board, x, y, offsetX, offsetY, role) | |
| selfCount = left['self_count'] + right['self_count'] + 1 | |
| totalLength = left['total_length'] + right['total_length'] + 1 | |
| noEmptySelfCount = left['no_empty_self_count'] + right['no_empty_self_count'] + 1 | |
| OneEmptySelfCount = max( | |
| left['one_empty_self_count'] + right['no_empty_self_count'], | |
| left['no_empty_self_count'] + right['one_empty_self_count'], | |
| ) + 1 | |
| rightEmpty = right['side_empty_count'] | |
| leftEmpty = left['side_empty_count'] | |
| if totalLength < 5: | |
| return [shape, selfCount] | |
| if noEmptySelfCount >= 5: | |
| if rightEmpty > 0 and leftEmpty > 0: | |
| return [shapes['FIVE'], selfCount] | |
| else: | |
| return [shapes['BLOCK_FIVE'], selfCount] | |
| if noEmptySelfCount == 4: | |
| if ( | |
| (rightEmpty >= 1 or right['one_empty_self_count'] > right['no_empty_self_count']) | |
| and (leftEmpty >= 1 or left['one_empty_self_count'] > left['no_empty_self_count']) | |
| ): | |
| return [shapes['FOUR'], selfCount] | |
| elif not (rightEmpty == 0 and leftEmpty == 0): | |
| return [shapes['BLOCK_FOUR'], selfCount] | |
| if OneEmptySelfCount == 4: | |
| return [shapes['BLOCK_FOUR'], selfCount] | |
| if noEmptySelfCount == 3: | |
| if (rightEmpty >= 2 and leftEmpty >= 1) or (rightEmpty >= 1 and leftEmpty >= 2): | |
| return [shapes['THREE'], selfCount] | |
| else: | |
| return [shapes['BLOCK_THREE'], selfCount] | |
| if OneEmptySelfCount == 3: | |
| if rightEmpty >= 1 and leftEmpty >= 1: | |
| return [shapes['THREE'], selfCount] | |
| else: | |
| return [shapes['BLOCK_THREE'], selfCount] | |
| if (noEmptySelfCount == 2 or OneEmptySelfCount == 2) and totalLength > 5: | |
| shape = shapes['TWO'] | |
| return [shape, selfCount] | |
| # Helper functions to check for specific shapes | |
| def is_five(shape): | |
| # Checked | |
| return shape in [shapes['FIVE'], shapes['BLOCK_FIVE']] | |
| def is_four(shape): | |
| # Checked | |
| return shape in [shapes['FOUR'], shapes['BLOCK_FOUR']] | |
| # Function to get all shapes at a specific point | |
| def get_all_shapes_of_point(shape_cache, x, y, role = None): | |
| # Checked | |
| roles = [role] if role else [1, -1] | |
| result = [] | |
| for r in roles: | |
| for d in range(4): | |
| shape = shape_cache[r][d][x][y] | |
| if shape > 0: | |
| result.append(shape) | |
| return result | |
| if __name__ == "__main__": | |
| pass |