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