diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index b7648c37bfb036c35a935ec778a8b0b35f9004d9..e3d4f144d63cc8bc216b848d0ae1864314ef4c03 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -13,6 +13,7 @@ <option name="ignoredIdentifiers"> <list> <option value="tuple.*" /> + <option value="dict.__getitem__" /> </list> </option> </inspection_tool> diff --git a/search/movement_logic.py b/search/movement_logic.py index 2abd2c718969a7a49aac41b8108cc407d1a5b12b..4f3dd18da49b414ac0ed9648e481d95ebc11c3f5 100644 --- a/search/movement_logic.py +++ b/search/movement_logic.py @@ -19,85 +19,97 @@ Slide action logic: # '-._.-'-._.-' # """ -row = 0 -column = 1 +ROW = 0 +COLUMN = 1 # 1 -def slide_left(coordinate): +def slide_left(coordinate: tuple[int, int]) -> tuple[int, int]: if coordinate: - new_pos = (coordinate[row], coordinate[column] - 1) + new_pos = (coordinate[ROW], coordinate[COLUMN] - 1) if not check_within_board(new_pos): return coordinate else: print("Empty coordinate") + return + return new_pos # 2 -def slide_right(coordinate): +def slide_right(coordinate: tuple[int, int]) -> tuple[int, int]: if coordinate: - new_pos = (coordinate[row], coordinate[column] + 1) + new_pos = (coordinate[ROW], coordinate[COLUMN] + 1) if not check_within_board(new_pos): return coordinate else: print("Empty coordinate") + return + return new_pos # 3 -def slide_up_left(coordinate): +def slide_up_left(coordinate: tuple[int, int]) -> tuple[int, int]: new_pos = () if coordinate: - new_pos = (coordinate[row] + 1, coordinate[column] - 1) + new_pos = (coordinate[ROW] + 1, coordinate[COLUMN] - 1) if not check_within_board(new_pos): return coordinate else: print("Empty coordinate") + return + return new_pos # 4 -def slide_up_right(coordinate): +def slide_up_right(coordinate: tuple[int, int]) -> tuple[int, int]: if coordinate: - new_pos = (coordinate[row] + 1, coordinate[column]) + new_pos = (coordinate[ROW] + 1, coordinate[COLUMN]) if not check_within_board(new_pos): return coordinate else: print("Empty coordinate") + return + return new_pos # 5 -def slide_down_left(coordinate): +def slide_down_left(coordinate: tuple[int, int]) -> tuple[int, int]: if coordinate: - new_pos = (coordinate[row] - 1, coordinate[column]) + new_pos = (coordinate[ROW] - 1, coordinate[COLUMN]) if not check_within_board(new_pos): return coordinate else: print("Empty coordinate") + return + return new_pos # 6 -def slide_down_right(coordinate): +def slide_down_right(coordinate: tuple[int, int]) -> tuple[int, int]: if coordinate: - new_pos = (coordinate[row] - 1, coordinate[column] + 1) + new_pos = (coordinate[ROW] - 1, coordinate[COLUMN] + 1) if not check_within_board(new_pos): return coordinate else: print("Empty coordinate") + return + return new_pos @@ -110,7 +122,7 @@ DOWN_LEFT = 5 DOWN_RIGHT = 6 OUT_OF_BOARD = 0 """ -:argument token - the selected game object that is presented by its position on board { (row, column)} +:argument piece - the selected game object that is presented by its position on board { (row, column)} x - the adjacent game object :return new position after the action is complete if the new position is out of the board return the token's position instead @@ -124,182 +136,184 @@ Swing action logic: RIGHT .-'-. UP_RIGHT .-'-._.-'-. | 1 | | 1 | 2 | .-'-._.-'-._.-'-. '-._.-'-._.-'-. - |token| [x] | 2 | | [x] | 3 | + |piece| [x] | 2 | | [x] | 3 | '-._.-'-._.-'-._.-' .-'-._.-'-._.-' - | 3 | |token| + | 3 | |piece| '-._.-' '-._.-' OWN_RIGHT .-'-. UP_LEFT .-'-._.-'-. - |token| | 2 | 3 | + |piece| | 2 | 3 | '-._.-'-._.-'-. .-'-._.-'-._.-' | [x] | 1 | | 1 | [x] | .-'-._.-'-._.-' '-._.-'-._.-'-. - | 3 | 2 | |token| - '-._.-'-._.-' '-._.-' + | 3 | 2 | |piece| + '-._.-'-._.-' '-._.-' DOWN_LEFT .-'-. LEFT .-'-. - |token| | 3 | + |piece| | 3 | .-'-._.-'-._.-' .-'-._.-'-._.-'-. - | 3 | [x] | | 2 | [x] |token| + | 3 | [x] | | 2 | [x] |piece| '-._.-'-._.-'-. '-._.-'-._.-'-._.-' | 2 | 1 | | 1 | '-._.-'-._.-' '-._.-' """ -def swing_to_tile_1(token, x): - position = get_relative_position(token, x) - +def swing_to_tile_1(piece: tuple[int, int], x: tuple[int, int]) -> tuple[int, int]: + position = get_relative_position(piece, x) + new_position = () if position == LEFT: - new_postion = slide_down_left(slide_left(token)) + new_position = slide_down_left(slide_left(piece)) if position == RIGHT: - new_postion = slide_up_right(slide_right(token)) + new_position = slide_up_right(slide_right(piece)) if position == UP_RIGHT: - new_postion = slide_up_left(slide_up_right(token)) + new_position = slide_up_left(slide_up_right(piece)) if position == UP_LEFT: - new_postion = slide_left(slide_up_left(token)) + new_position = slide_left(slide_up_left(piece)) if position == DOWN_LEFT: - new_postion = slide_down_right(slide_down_left(token)) + new_position = slide_down_right(slide_down_left(piece)) if position == DOWN_RIGHT: - new_postion = slide_right(slide_down_right(token)) + new_position = slide_right(slide_down_right(piece)) # if the position of the token after the action complete is out of board, return the token position in # stead - if compare_tile(new_postion, x): - return token + if compare_tile(new_position, x): + return piece - return new_postion + return new_position -def swing_to_tile_2(token, x): - position = get_relative_position(token, x) +def swing_to_tile_2(piece: tuple[int, int], x: tuple[int, int]) -> tuple[int, int]: + position = get_relative_position(piece, x) + new_position = () if position == LEFT: - new_postion = slide_left(slide_left(token)) + new_position = slide_left(slide_left(piece)) if position == RIGHT: - new_postion = slide_right(slide_right(token)) + new_position = slide_right(slide_right(piece)) if position == UP_RIGHT: - new_postion = slide_up_right(slide_up_right(token)) + new_position = slide_up_right(slide_up_right(piece)) if position == UP_LEFT: - new_postion = slide_up_left(slide_up_left(token)) + new_position = slide_up_left(slide_up_left(piece)) if position == DOWN_LEFT: - new_postion = slide_down_left(slide_down_left(token)) + new_position = slide_down_left(slide_down_left(piece)) if position == DOWN_RIGHT: - new_postion = slide_down_right(slide_down_right(token)) + new_position = slide_down_right(slide_down_right(piece)) # if the position of the token after the action complete is out of board, return the token position in # stead - if compare_tile(new_postion, x): - return token + if compare_tile(new_position, x): + return piece - return new_postion + return new_position -def swing_to_tile_3(token, x): - position = get_relative_position(token, x) +def swing_to_tile_3(piece: tuple[int, int], x: tuple[int, int]) -> tuple[int, int]: + position = get_relative_position(piece, x) + new_position = () if position == LEFT: - new_postion = slide_up_left(slide_left(token)) + new_position = slide_up_left(slide_left(piece)) if position == RIGHT: - new_postion = slide_down_right(slide_right(token)) + new_position = slide_down_right(slide_right(piece)) if position == UP_RIGHT: - new_postion = slide_right(slide_up_right(token)) + new_position = slide_right(slide_up_right(piece)) if position == UP_LEFT: - new_postion = slide_up_right(slide_up_left(token)) + new_position = slide_up_right(slide_up_left(piece)) if position == DOWN_LEFT: - new_postion = slide_left(slide_down_left(token)) + new_position = slide_left(slide_down_left(piece)) if position == DOWN_RIGHT: - new_postion = slide_down_left(slide_down_right(token)) + new_position = slide_down_left(slide_down_right(piece)) # if the position of the token after the action complete is out of board, return the token position in # stead - if compare_tile(new_postion, x): - return token + if compare_tile(new_position, x): + return piece - return new_postion + return new_position -def get_relative_position(token, x): +def get_relative_position(piece: tuple[int, int], x: tuple[int, int]) -> tuple[int, int]: """ - :argument token - the selected game object that is presented by its position on board { (row, column)} - x - the adjacent game object + :param x: the adjacent game object + :argument piece: the selected game object that is presented by its position on board { (row, column)} :return the position of x relative to token -> using the slide direction as the position definition. e.g left,right, up_left, up_right,..etc """ # check if x is to the left of tile - if compare_tile(slide_left(token), x): + if compare_tile(slide_left(piece), x): return LEFT # check if x is to the right of tile - if compare_tile(slide_right(token), x): + if compare_tile(slide_right(piece), x): return RIGHT # check if x is to the up_left of the tile - if compare_tile(slide_up_left(token), x): + if compare_tile(slide_up_left(piece), x): return UP_LEFT # check if x is to the up_right of the tile - if compare_tile(slide_up_right(token), x): + if compare_tile(slide_up_right(piece), x): return UP_RIGHT # check if x is to the down_left of the tile - if compare_tile(slide_down_left(token), x): + if compare_tile(slide_down_left(piece), x): return DOWN_LEFT # check if x is to the down_right of the tile - if compare_tile(slide_down_right(token), x): + if compare_tile(slide_down_right(piece), x): return DOWN_RIGHT -def compare_tile(tile1, tile2): +def compare_tile(tile1: tuple[int, int], tile2: tuple[int, int]) -> bool: """ - :argument tile1 - compose of (row, column) - tile2 - compose of (row, column) + :param tile2: compose of (row, column) + :param tile1: compose of (row, column) :return true if both of the row and column are matches between 2 tiles """ - return tile1[row] == tile2[row] \ - and tile1[column] == tile2[column] + return tile1[ROW] == tile2[ROW] \ + and tile1[COLUMN] == tile2[COLUMN] -def check_within_board(tile): +def check_within_board(tile: tuple[int, int]) -> bool: """ ensure that the tile is exist within the board :param tile: coordinate of the tile :return: true if the tile exist within the board, else false """ - if tile[row] < -4 or tile[row] > 4: + if tile[ROW] < -4 or tile[ROW] > 4: return False - if tile[column] < -4 or tile[column] > 4: + if tile[COLUMN] < -4 or tile[COLUMN] > 4: return False - if tile[column] in [-4, -3, -2, -1] and tile[row] < -4 - tile[column]: + if tile[COLUMN] in [-4, -3, -2, -1] and tile[ROW] < -4 - tile[COLUMN]: return False - if tile[column] in [4, 3, 2, 1] and tile[row] > 4 - tile[column]: + if tile[COLUMN] in [4, 3, 2, 1] and tile[ROW] > 4 - tile[COLUMN]: return False return True -def distance_between(Upper_token, Lower_token): +def distance_between(piece: tuple[int, int], target: tuple[int, int]) -> bool: """ - :argument Upper_token - compose of (row, column) - :argument Lower_token - compose of (row, column) + :argument piece - compose of (row, column) + :argument target - compose of (row, column) :return the number of step from upper's token to lower's token Taken from https://www.redblobgames.com/grids/hexagons/ @@ -307,7 +321,7 @@ def distance_between(Upper_token, Lower_token): -> """ - dx = abs(Upper_token[1] - Lower_token[1]) - dy = abs(Upper_token[0] - Lower_token[0]) + dx = abs(piece[1] - target[1]) + dy = abs(piece[0] - target[0]) result = dx + max(0, (dy - dx) / 2) return result diff --git a/search/search_algorithm.py b/search/search_algorithm.py index 666985893bd303aa583db1b51dfecbab13006cdf..9bfa2de6c3b462f3240a46203391983e75efd69b 100644 --- a/search/search_algorithm.py +++ b/search/search_algorithm.py @@ -29,9 +29,9 @@ HIGHEST_RANK = 0 # Global variable: # All the dictionary is made into global variable since all method is interact with them -upperPiecesDict = {} -lowerPiecesDict = {} -setBlocks = set() +upperPiecesDict: dict[str, tuple] = {} +lowerPiecesDict: dict[str, tuple] = {} +setBlocks: set[tuple, ...] = set() targetsDict = {} # keep track all the lower player's piece <- to ensure no two Upper piece can target only one distinguish lower piece @@ -41,10 +41,12 @@ targetedPiece = set() # this help rank the action. positionHistory = {} -board = {} +board: dict[tuple:str] = {} ''' METHOD ''' + + def get_weaker_piece(piece: str) -> str: """ get the weaker piece type in low case @@ -87,8 +89,6 @@ def make_board(): board[block] = BLOCK - - def check_valid_action(piece: str, new_position: tuple) -> bool: """ check if the action is resolved successfully. @@ -110,7 +110,7 @@ def check_valid_action(piece: str, new_position: tuple) -> bool: if new_position in board.keys(): if board[new_position] == BLOCK: return False - if piece_collision(board[new_position], piece) != DRAW: + if result_of_collision(board[new_position], piece) != DRAW: return False return True @@ -149,7 +149,7 @@ def rank(position: tuple, piece: str) -> int: return baseRank + reduceFactor -def piece_collision(pieceA: str, pieceB: str) -> int: +def result_of_collision(pieceA: str, pieceB: str) -> int: """ Our upper pieces are R, P and S, lower pieces are r, p and s We will convert both to lower case letters and check each case @@ -157,7 +157,7 @@ def piece_collision(pieceA: str, pieceB: str) -> int: :param pieceA: type of the token in {'R','P','S','r','p','s'} :param pieceB: type of the token in {'R','P','S','r','p','s'} - :return: A_WIN, B_WIN or DRAW + :return: A_WIN, B_WIN or DRAW """ pieceA = pieceA[TYPE].lower() pieceB = pieceB[TYPE].lower() @@ -312,7 +312,7 @@ def perform_optimal_combination(move_list: dict): break if move_list[piece][index] in board.keys() and\ - piece_collision(board[move_list[piece][index]], piece) != DRAW: + result_of_collision(board[move_list[piece][index]], piece) != DRAW: index += 1 continue diff --git a/search/test.py b/search/test.py deleted file mode 100644 index 374b8ce5f34e531230b0d08821dae092721dd52b..0000000000000000000000000000000000000000 --- a/search/test.py +++ /dev/null @@ -1,8 +0,0 @@ -from search.movement_logic import distance_between - -print(distance_between((2, -2), (4, 0))) -print(distance_between((2, -1), (4, 0))) -print(distance_between((1, 0), (4, 0))) -print(distance_between((0, 0), (4, 0))) -print(distance_between((0, -1), (4, 0))) -print(distance_between((1, -2), (4, 0))) \ No newline at end of file