diff --git a/Test_case/level_1/8.json b/Test_case/level_1/8.json new file mode 100644 index 0000000000000000000000000000000000000000..c99b1f6e7a00519cc4a90b9886631363516b06ff --- /dev/null +++ b/Test_case/level_1/8.json @@ -0,0 +1,22 @@ +{ + "upper": [ + [ + "r", + 4, + -4 + ] + ], + "lower": [ + [ + "s", + 0, + -2 + ], + [ + "s", + 0, + 4 + ] + ], + "block": [] +} \ No newline at end of file diff --git a/search/__pycache__/main.cpython-38.pyc b/search/__pycache__/main.cpython-38.pyc index 39cf0f0c5ea04dbc9c928500fcf177d8a05a2557..4796c0c303b7134efd9eeda4d2d15bd9c1c39d38 100644 Binary files a/search/__pycache__/main.cpython-38.pyc and b/search/__pycache__/main.cpython-38.pyc differ diff --git a/search/__pycache__/search_algo.cpython-38.pyc b/search/__pycache__/search_algo.cpython-38.pyc index a78ee17d6e28f7e9f68cc5ee5a115a10aa34ce4f..38e12487fceb0dbd91d980333270203f9d429110 100644 Binary files a/search/__pycache__/search_algo.cpython-38.pyc and b/search/__pycache__/search_algo.cpython-38.pyc differ diff --git a/search/main.py b/search/main.py index 5f9abbd3848ed45715689cb07dae1f81b7031f76..59181f27d05a476318acab91f34e824174141309 100644 --- a/search/main.py +++ b/search/main.py @@ -9,32 +9,17 @@ This script contains the entry point to the program (the code in import sys import json from search.movement_logic import * -from search.search_algo import check_if_piece_hit_target, make_board, update_state -from search.util import print_board +from search.search_algo import * # Constant's definition. -TYPE = 0 -ROW = 1 -COLUMN = 2 -A_WIN = 1 -B_WIN = 2 -DRAW = 0 -MAX_DISTANCE = 99 -FIRST_CHAR = 0 -upperDictPieces = {} -lowerDictPieces ={} -targetDict = {} - -setBlocks = set() def main(): # define global variable global upperDictPieces, lowerDictPieces, targetDict, setBlocks - print("a") try: with open(sys.argv[1]) as file: data = json.load(file) @@ -59,10 +44,10 @@ def main(): find_target(piece) # keep moving until all the piece met its target while targetDict: + input() upperDictPieces = update_state(upperDictPieces, lowerDictPieces, setBlocks, targetDict) - targetDict = check_if_piece_hit_target(upperDictPieces, targetDict) - print(upperDictPieces) - + targetDict = check_if_piece_hit_target(upperDictPieces, lowerDictPieces, targetDict) + print(lowerDictPieces) def parse_input(data): """ @@ -152,43 +137,7 @@ def piece_collision(pieceA, pieceB) -> int: return DRAW -def find_target(piece_key): - """ - This function changes the value of the key given in the - target dictionary to the closest enemy piece it can beat - XUAN: by separated the upper to lower piece, we dont need to search for the whole dictionary every time we compare. - :param piece_key: key of the piece to find a target for. We should only work with upper player's pieces - :return: null - """ - global targetDict - # Set the target - if piece_key[TYPE] == "R": - target = "s" - elif piece_key[TYPE] == "S": - target = "p" - else: - target = "r" - - # Now we check which target is closest - # Start with dummy information - targetPiece = "" - targetDist = MAX_DISTANCE - for key in lowerDictPieces: - if key[FIRST_CHAR] == target: - distance = distance_between(lowerDictPieces[key], lowerDictPieces[key]) - # if the distance between this key and the query key is less than the least distance. - # as well as the key is not targeted by any other key. - if distance < targetDist: - targetPiece = key - targetDist = distance - - # Now add target to dictionary - # case where no key that match criteria. - if targetDist == MAX_DISTANCE: - targetDict[piece_key] = () - else: - targetDict[piece_key] = lowerDictPieces[targetPiece] # Situation 1: If you plan the route ahead without knowing any other piece route, diff --git a/search/search_algo.py b/search/search_algo.py index f55d69a3409706c9b357825c076e7c9c263e6447..9d9519c79c39d7cc2532d05e4612a2bc3d86d4fe 100644 --- a/search/search_algo.py +++ b/search/search_algo.py @@ -1,10 +1,23 @@ from search.movement_logic import slide_right, slide_left, slide_up_left, slide_up_right, slide_down_left, \ - slide_down_right, compare_tile, distance_between + slide_down_right, compare_tile, distance_between, swing_to_tile_1, swing_to_tile_2, swing_to_tile_3 from search.util import print_board BLOCK = "" POSITION_CLOSEST_TO_TARGET = 0 +TYPE = 0 +ROW = 1 +COLUMN = 2 +A_WIN = 1 +B_WIN = 2 +DRAW = 0 +MAX_DISTANCE = 99 +FIRST_CHAR = 0 +upperDictPieces = {} +lowerDictPieces ={} +targetDict = {} + +setBlocks = set() def make_board(lowerPieces, upperPieces, setBlocks): """ @@ -32,9 +45,9 @@ def get_stronger_piece(piece_type): :param piece_type: the type of the piece that we are interested :return: the type of the piece that stronger than the input piece """ - if piece_type == 'R': + if piece_type[0] == 'R': return 'p' - if piece_type == 'S': + if piece_type[0] == 'S': return 'r' return 's' @@ -91,7 +104,7 @@ def add_if_valid(position_list, piece, new_position, piece_position, board): return position_list # check if the new position is occupied by piece that stronger - elif board[new_position] == get_stronger_piece(piece): + elif board[new_position][0] == get_stronger_piece(piece): return position_list # add the new position and return @@ -111,7 +124,9 @@ def make_priority_list_of_action(upperDict, piece, targetDict, board): """ # add all the adjacent move to queue position_list = add_slide_action(upperDict, piece, board) + position_list.extend(add_swing_action(upperDict, piece, board)) + #print(position_list) # sort the list base on the how close it is to target position_list.sort(key=(lambda x: distance_between(x, targetDict[piece]))) @@ -134,21 +149,142 @@ def update_state(upperPieces, lowerPieces, setBlocks, targetDict): # right now, i assume there only 1 piece, there will be more code combine all the queue. for piece in upperPieces: - position_list = make_priority_list_of_action(upperPieces,piece, targetDict, board) + position_list = make_priority_list_of_action(upperPieces, piece, targetDict, board) upperPieces[piece] = position_list[POSITION_CLOSEST_TO_TARGET] return upperPieces -def check_if_piece_hit_target(upperPiece, targetDict): +def check_if_piece_hit_target(upperPieces, lowerPieces, targetDict): """ remove the target from the target dictionary if the upper piece is at its target location :param upperPiece: contain all upper piece :param targetDict: map upper piece to its lower target :return: the updated target dictionary """ - for piece in upperPiece: - if targetDict and compare_tile(upperPiece[piece], targetDict[piece]): + removed = False + for piece in upperPieces: + if targetDict and compare_tile(upperPieces[piece], targetDict[piece]): + for removed_piece in lowerPieces: + if compare_tile(lowerPieces[removed_piece],targetDict[piece]): + removed = removed_piece del targetDict[piece] + del lowerPieces[removed] + removed = True + # once the piece hit it target, it is free to find a new target. + # if there are more lower piece then which already targeted {some lower piece is not target} + # we can check if the available pieces can target those + if removed and len(lowerPieces) > len(targetDict): + for piece in upperPieces: + # when a piece is remove then there will + if piece in targetDict: + continue + + find_target(piece) + + return targetDict + + +def add_swing_action(upperDict, piece, board): + """ + check for adjacent tile. + if there are any adjacent tile to this add swing action from those tile + :param upperDict: contain all the upper piece + :param piece: which we want to move + :param board: dictionary contain all piece in the game + :return: list of all action added + """ + adjacent_list = [] + # check the right tile + right_tile = slide_right(upperDict[piece]) + if not compare_tile(right_tile, upperDict[piece]) and\ + right_tile in board and board[right_tile] != "": + adjacent_list.append(right_tile) + + # check the left tile + left_tile = slide_left(upperDict[piece]) + if not compare_tile(left_tile, upperDict[piece]) and\ + left_tile in board and board[left_tile] != "": + adjacent_list.append(left_tile) + + # check the up_left + up_left_tile = slide_up_left(upperDict[piece]) + if not compare_tile(up_left_tile, upperDict[piece]) and\ + up_left_tile in board and board[up_left_tile] != "": + adjacent_list.append(up_left_tile) + + # check the up_right + up_right_tile = slide_up_right(upperDict[piece]) + if not compare_tile(up_right_tile, upperDict[piece]) and\ + up_right_tile in board and board[up_right_tile] != "": + adjacent_list.append(up_right_tile) + + # check the down_left + down_left_tile = slide_down_left(upperDict[piece]) + if not compare_tile(down_left_tile, upperDict[piece]) and\ + down_left_tile in board and board[down_left_tile] != "": + adjacent_list.append(down_left_tile) + + # check the down_right + down_right_tile = slide_down_right(upperDict[piece]) + if not compare_tile(down_right_tile, upperDict[piece]) and\ + down_right_tile in board and board[down_right_tile] != "": + adjacent_list.append(down_right_tile) + + # if there are at least one adjacent piece : add the adjacent move from those tile + position_list = [] + for adjacent_piece in adjacent_list: + # add the swing action to tile 1 (look at swing_action section in movement_logic modulo) + position_list = add_if_valid(position_list, piece, swing_to_tile_1(upperDict[piece], adjacent_piece), + upperDict[piece], board) + + # add the swing action to tile 2 + position_list = add_if_valid(position_list, piece, swing_to_tile_2(upperDict[piece], adjacent_piece), + upperDict[piece], board) + + # add the swing action to tile 3 + position_list = add_if_valid(position_list, piece, swing_to_tile_3(upperDict[piece], adjacent_piece), + upperDict[piece], board) + + return position_list + + +def find_target(piece_key): + """ + This function changes the value of the key given in the + target dictionary to the closest enemy piece it can beat + XUAN: by separated the upper to lower piece, we dont need to search for the whole dictionary every time we compare. + + :param piece_key: key of the piece to find a target for. We should only work with upper player's pieces + :return: null + """ + global targetDict + # Set the target + if piece_key[TYPE] == "R": + target = "s" + elif piece_key[TYPE] == "S": + target = "p" + else: + target = "r" + + # Now we check which target is closest + # Start with dummy information + targetPiece = "" + targetDist = MAX_DISTANCE + print(lowerDictPieces) + for key in lowerDictPieces: + if key[FIRST_CHAR] == target: + distance = distance_between(upperDictPieces[piece_key], lowerDictPieces[key]) + # if the distance between this key and the query key is less than the least distance. + # as well as the key is not targeted by any other key. + if distance < targetDist: + targetPiece = key + targetDist = distance + + # Now add target to dictionary + # case where no key that match criteria. + if targetDist == MAX_DISTANCE: + return + else: + targetDict[piece_key] = lowerDictPieces[targetPiece] - return targetDict \ No newline at end of file