From 39a7cb300a7af1834d1a2cd46be06acff8b3e841 Mon Sep 17 00:00:00 2001
From: Xuan Trinh <xuan.trinh@student.unimelb.edu.au>
Date: Sat, 27 Mar 2021 20:32:41 +1100
Subject: [PATCH] =?UTF-8?q?Can=20run!!=20=1B[D=1B[D=1B[D=20under=20most=20?=
 =?UTF-8?q?scenario!=20Will=20work=20on=20what=20if=20there=20no=20way=20a?=
 =?UTF-8?q?=20piece=20can=20get=20to=20its=20target.=20XUAN=205:30PM=20=1B?=
 =?UTF-8?q?[D=1B[D=1B[D=1B[D=1B[D=1B[8=1B[B=1B[C=1B[C=1B[C=1B[C=1B[C=2027?=
 =?UTF-8?q?=20Mar=202021?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 Test_case/level_3/12.json                     | 103 ++++++++++++++
 search/__pycache__/main.cpython-38.pyc        | Bin 2823 -> 1976 bytes
 search/__pycache__/search_algo.cpython-38.pyc | Bin 6995 -> 8742 bytes
 search/main.py                                |  42 +-----
 search/search_algo.py                         | 131 +++++++++++++++---
 5 files changed, 218 insertions(+), 58 deletions(-)
 create mode 100644 Test_case/level_3/12.json

diff --git a/Test_case/level_3/12.json b/Test_case/level_3/12.json
new file mode 100644
index 0000000..37334dc
--- /dev/null
+++ b/Test_case/level_3/12.json
@@ -0,0 +1,103 @@
+{
+  "upper": [
+    [
+      "p",
+      0,
+      -3
+    ],
+    [
+      "s",
+      0,
+      0
+    ]
+  ],
+  "lower": [
+    [
+      "r",
+      0,
+      1
+    ],
+    [
+      "p",
+      0,
+      2
+    ]
+  ],
+  "block": [
+    [
+      "",
+      -1,
+      -3
+    ],
+    [
+      "",
+      -1,
+      -2
+    ],
+    [
+      "",
+      -1,
+      -1
+    ],
+    [
+      "",
+      -1,
+      0
+    ],
+    [
+      "",
+      -1,
+      1
+    ],
+    [
+      "",
+      -1,
+      2
+    ],
+    [
+      "",
+      -1,
+      3
+    ],
+    [
+      "",
+      0,
+      3
+    ],
+    [
+      "",
+      1,
+      -4
+    ],
+    [
+      "",
+      1,
+      -3
+    ],
+    [
+      "",
+      1,
+      -2
+    ],
+    [
+      "",
+      1,
+      -1
+    ],
+    [
+      "",
+      1,
+      0
+    ],
+    [
+      "",
+      1,
+      1
+    ],
+    [
+      "",
+      1,
+      2
+    ]
+  ]
+}
\ No newline at end of file
diff --git a/search/__pycache__/main.cpython-38.pyc b/search/__pycache__/main.cpython-38.pyc
index 4796c0c303b7134efd9eeda4d2d15bd9c1c39d38..1ac4f3a1eb06acd9bcb68a9797aeb04de23944bd 100644
GIT binary patch
delta 188
zcmZn{+rh6L%FD~ez`(#@_bV>pqBsM?V-N=!GchnQI503U6dO#`RuE-LVQpcEVo703
zVQ*oGVohNRX3*rASoVo=)#OaZS=>S;!X^AATqOd{%#+!e+!#eB`!XGrjN&dR%FHW?
zPs&d$N{QmiP0UV(uqX2|hcNO@PG(kSWZK-$e1nNGYH|YGVn+SREbMNKY?B+fL?*B1
XlAU~sOPLSkN)`?dMh->}W)4LF`&lY*

delta 1053
zcmdnN-!7&d%FD~ez`(%Jbuli1Q-*=zF^GeVnHd-u92giFirpq^D`+#OFz2v@Fr=`g
zu(mKnv8J%4u(vQov8A%7aLi#$;Y{IbVTs~MVG3r@<er%DiE+{7V8&U@Y$g1Ye=xc+
z3Qe|WIyhO9IfPMUavrlXBje^t%r}@AZ%xi-Tg+%OnV;RQp79o2QEEwPQC>0=k|RKD
z5OxN+qk(~ep@yM^L6Tts<3fg7h8jjVo3Vx=g)y6{$f|}hg(;h<NT-A;n4yL-g*lt4
zsHTKDm?6)ph5;-S0~PgyssQP#DPgV;X2?^hVSs3;VFVji0967q5Nt>ZOE7~bOX6on
z1_mw#5b!T8QYbAbNG(z*$V^R6EmlY@N>vEbQ3y~-%u7)S)=|jGFGrOu(orY?OBO>+
z2v1cg&&<hDs87z%D@!dZQAo-!$xtZChw4mDEKXI(Ni8W!Eh+|UOU_75&Q?fGOwLdM
z$w3XtFU?6&NJ>@6%S=uMX)Y~JRY=ayEl4a%EXglYNGdH+NKVXCFHy)yEK5}=vMaVL
zuq#q1EzZnKSI8{k;!;qkS5Qz00*AkXV|=)$pF(CD#7~Y2<(YZKItorGqE28@u!~%R
z9K%7X^HMWQGE$2`5)fDU=jBu?<mBgPD<qaEq-7QrmnbA>Bo-wmm!uXc<fkbVmlS2@
zrGqS2P_U{8xiuGRrIkWSWkD)PO-TmGKiR2y3YmEd)#^d&I_d%HI_kmdI_gF0I_d@L
zI_kyhwP5?KkW6qQ*#waP6|5jB&<YX+FhA!PDS-S4wxmdofq|h&5k$x^FfeGc7Ab+)
zk_-$CQLNyAi(&<bR1^zHk0w(T8#rY+LTRTWQIL8tA;!SKaEl)-9iN<*pOceWoSC1O
z0ZQpApe(@4!^p$P!N|eL!pOnM#)QdYVJcDsIfC;RdwhIKesX+#5gW*K4v=d^i&GPe
zk~8#j^UG3mQ}asVbMn(OlP71g%dy{L&de(*Qk&eut|r9Cz`(%50WzC|k%NOnfx`p<
Db~_N^

diff --git a/search/__pycache__/search_algo.cpython-38.pyc b/search/__pycache__/search_algo.cpython-38.pyc
index 38e12487fceb0dbd91d980333270203f9d429110..9c6190551c3a2812e7abaca1b7123fa02b9eb34a 100644
GIT binary patch
delta 3970
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

delta 2212
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
VIQT_4csb-bWI04R#5m+Q90083#8v<R

diff --git a/search/main.py b/search/main.py
index 59181f2..d463cb9 100644
--- a/search/main.py
+++ b/search/main.py
@@ -8,14 +8,8 @@ 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 *
 
-# Constant's definition.
-
-
-
-
 
 def main():
     # define global variable
@@ -47,7 +41,8 @@ def main():
         input()
         upperDictPieces = update_state(upperDictPieces, lowerDictPieces, setBlocks, targetDict)
         targetDict = check_if_piece_hit_target(upperDictPieces, lowerDictPieces, targetDict)
-    print(lowerDictPieces)
+
+    print_board(make_board(lowerDictPieces,upperDictPieces,setBlocks))
 
 def parse_input(data):
     """
@@ -101,40 +96,7 @@ def parse_input(data):
         setBlocks.add((block[ROW], block[COLUMN]))
 
 
-def piece_collision(pieceA, pieceB) -> 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
-     Would be nice to use comparator but can't have r>s>p>r using it
-
-     Return A_WIN if pieceA wins, B_WIN if pieceB wins and DRAW if neither win
-     Only look at first character of string
 
-    :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
-    """
-    pieceA = pieceA[TYPE].lower()
-    pieceB = pieceB[TYPE].lower()
-    if pieceA == "r":
-        if pieceB == "s":
-            return A_WIN
-        elif pieceB == "p":
-            return B_WIN
-
-    elif pieceA == "s":
-        if pieceB == "p":
-            return A_WIN
-        elif pieceB == "r":
-            return B_WIN
-
-    elif pieceA == "p":
-        if pieceB == "r":
-            return A_WIN
-        elif pieceB == "s":
-            return B_WIN
-
-    return DRAW
 
 
 
diff --git a/search/search_algo.py b/search/search_algo.py
index 9d9519c..5b9dfef 100644
--- a/search/search_algo.py
+++ b/search/search_algo.py
@@ -1,8 +1,8 @@
-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, swing_to_tile_1, swing_to_tile_2, swing_to_tile_3
+from search.movement_logic import *
 from search.util import print_board
 
-BLOCK = ""
+# BLOCK should be "" but put [X] so we can observe from the print_board statement
+BLOCK = "[X]"
 POSITION_CLOSEST_TO_TARGET = 0
 TYPE = 0
 ROW = 1
@@ -16,9 +16,10 @@ FIRST_CHAR = 0
 upperDictPieces = {}
 lowerDictPieces ={}
 targetDict = {}
-
+targeted_l_piece = set()
 setBlocks = set()
 
+
 def make_board(lowerPieces, upperPieces, setBlocks):
     """
     create a board of the current game -> can do a position look up.
@@ -124,11 +125,13 @@ 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)
+
+    # add all the swing action to queue
     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])))
+    if piece in targetDict.keys():
+        position_list.sort(key=(lambda x: distance_between(x, targetDict[piece])))
 
     return position_list
 
@@ -146,15 +149,71 @@ def update_state(upperPieces, lowerPieces, setBlocks, targetDict):
     # create the board in order to support faster look up
     board = make_board(lowerPieces, upperPieces, setBlocks)
     print_board(board)
-
+    possible_action = {}
     # 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)
-        upperPieces[piece] = position_list[POSITION_CLOSEST_TO_TARGET]
+        possible_action[piece] = make_priority_list_of_action(upperPieces, piece, targetDict, board)
+
+    upperPieces = choose_optimal_combination(possible_action, upperPieces, board, targetDict)
+    return upperPieces
+
+
+def choose_optimal_combination(possible_action, upperPieces, board, targetDict):
+
+    """
+    prioritise action lead a piece directly to its target.
+    else choose a combination that does not cause collision between upper piece
+
+    :param possible_action: all set of possible move sorted base on how close they are to the piece target
+    :param upperPieces: contain all upper piece
+    :param board: all piece
+    :param targetDict: map all piece to its target
+    :return:
+    """
+    finished = set()
+    for piece in possible_action.keys():
+        if piece in possible_action.keys():
+
+            if piece in targetDict.keys() and compare_tile(possible_action[piece][0], targetDict[piece]):
+
+                # perform swap and update board
+                del board[upperPieces[piece]]
+                upperPieces[piece] = targetDict[piece]
+
+                board[targetDict[piece]] = piece
+                # we've finished with this piece.
+                finished.add(piece)
+
+    # each piece is moved once and only once.
+    for piece in possible_action:
+        if piece in finished:
+            continue
+        index = 0
+        moved = False
+        while not moved:
+            # check if the move exist in the board
+            if possible_action[piece][index] not in board.keys():
+                # perform swap and update board
+                del board[upperPieces[piece]]
+                upperPieces[piece] = possible_action[piece][index]
+
+                board[possible_action[piece][index]] = piece
+                moved = True
+            else:
+                # check if no collision happen:
+                if piece_collision(board[possible_action[piece][index]], piece) == DRAW:
+                    # perform swap and update board
+                    del board[upperPieces[piece]]
+                    upperPieces[piece] = possible_action[piece][index]
+
+                    board[possible_action[piece][index]] = piece
+                    moved = True
+            index += 1
 
     return upperPieces
 
 
+
 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
@@ -164,7 +223,7 @@ def check_if_piece_hit_target(upperPieces, lowerPieces, targetDict):
     """
     removed = False
     for piece in upperPieces:
-        if targetDict and compare_tile(upperPieces[piece], targetDict[piece]):
+        if piece in targetDict.keys() and compare_tile(upperPieces[piece], targetDict[piece]):
             for removed_piece in lowerPieces:
                 if compare_tile(lowerPieces[removed_piece],targetDict[piece]):
                    removed = removed_piece
@@ -185,6 +244,42 @@ def check_if_piece_hit_target(upperPieces, lowerPieces, targetDict):
     return targetDict
 
 
+def piece_collision(pieceA, pieceB) -> 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
+     Would be nice to use comparator but can't have r>s>p>r using it
+
+     Return A_WIN if pieceA wins, B_WIN if pieceB wins and DRAW if neither win
+     Only look at first character of string
+
+    :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
+    """
+    pieceA = pieceA[TYPE].lower()[0]
+    pieceB = pieceB[TYPE].lower()[0]
+    if pieceA == "r":
+        if pieceB == "s":
+            return A_WIN
+        elif pieceB == "p":
+            return B_WIN
+
+    elif pieceA == "s":
+        if pieceB == "p":
+            return A_WIN
+        elif pieceB == "r":
+            return B_WIN
+
+    elif pieceA == "p":
+        if pieceB == "r":
+            return A_WIN
+        elif pieceB == "s":
+            return B_WIN
+
+    return DRAW
+
+
 def add_swing_action(upperDict, piece, board):
     """
     check for adjacent tile.
@@ -198,37 +293,37 @@ def add_swing_action(upperDict, piece, board):
     # 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] != "":
+            right_tile in board and board[right_tile] != BLOCK:
         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] != "":
+            left_tile in board and board[left_tile] != BLOCK:
         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] != "":
+            up_left_tile in board and board[up_left_tile] != BLOCK:
         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] != "":
+            up_right_tile in board and board[up_right_tile] != BLOCK:
         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] != "":
+            down_left_tile in board and board[down_left_tile] != BLOCK:
         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] != "":
+            down_right_tile in board and board[down_right_tile] != BLOCK:
         adjacent_list.append(down_right_tile)
 
     # if there are at least one adjacent piece : add the adjacent move from  those tile
@@ -271,9 +366,8 @@ def find_target(piece_key):
     # Start with dummy information
     targetPiece = ""
     targetDist = MAX_DISTANCE
-    print(lowerDictPieces)
     for key in lowerDictPieces:
-        if key[FIRST_CHAR] == target:
+        if key[FIRST_CHAR] == target and key not in targeted_l_piece:
             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.
@@ -287,4 +381,5 @@ def find_target(piece_key):
         return
     else:
         targetDict[piece_key] = lowerDictPieces[targetPiece]
+        targeted_l_piece.add(targetPiece)
 
-- 
GitLab