diff --git a/board_detector.py b/board_detector.py
index d63851826ff39d724aff67371d2dec994faae9a7..c5f1b46d57b4124bfa2529dee906b4334af00838 100644
--- a/board_detector.py
+++ b/board_detector.py
@@ -230,6 +230,11 @@ def find_board(img):
     corners = [tuple(corner) for corner in corners] # convert to tuples
     corners_sorted = sort_square_grid_coords(corners, unpacked=True)
 
+    return corners_sorted, intersection
+
+def warp_board(img, corners_sorted, intersection):
+    height, width, _ = img.shape
+
     tl, tr, bl, br = corners_sorted
     src = np.float32([list(tl), list(tr), list(bl), list(br)])
     dest = np.float32([[0,0], [width, 0], [0, height], [width, height]])
@@ -327,15 +332,23 @@ def find_pieces(warped_img, sorted_warped_points, reader, img_idx):
     gray_after = cv2.cvtColor(bgr_after, cv2.COLOR_BGR2GRAY)
 
     diff_mask_contours = np.zeros_like(gray_after)
+    drawn_warped_img = deepcopy(warped_img)
     if compare_prev_warped:
         # img_path = os.path.join('game_images', 'warped' + str(img_idx - 1) + '.jpg')
         # prev_warped_img = cv2.imread(img_path)
-        diff = cv2.absdiff(bgr_after, prev_bgr_after)
-        diff_mask = cv2.cvtColor(diff, cv2.COLOR_BGR2GRAY)
+        # diff = cv2.absdiff(bgr_after, prev_bgr_after)
+        # diff_mask = cv2.cvtColor(diff, cv2.COLOR_BGR2GRAY)
+
+        gray_after_mask = np.zeros_like(gray_after)
+        prev_gray_after_mask = np.zeros_like(prev_gray_after)
+        gray_after_mask[gray_after != 0] = 255
+        prev_gray_after_mask[prev_gray_after != 0] = 255
+        # prev_gray_after[prev_gray_after != 0] = 255
+        diff_mask = cv2.absdiff(gray_after_mask, prev_gray_after_mask)
         # display_img([diff_mask])
-        diff_thresh = 70
-        diff_mask[diff_mask > diff_thresh] = 255
-        diff_mask[diff_mask <= diff_thresh] = 0
+        # diff_thresh = 60
+        # diff_mask[diff_mask > diff_thresh] = 255
+        # diff_mask[diff_mask <= diff_thresh] = 0
 
         diff_contours, hierarchy = cv2.findContours(diff_mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
         diff_contours_sorted = sorted(diff_contours, reverse=True, key=cv2.contourArea)
@@ -343,7 +356,7 @@ def find_pieces(warped_img, sorted_warped_points, reader, img_idx):
         cv2.drawContours(diff_mask_contours, diff_contours_sorted, -1, (255), thickness=cv2.FILLED)
 
         if show_cv:
-            display_img([bgr_after, prev_bgr_after])
+            display_img([prev_bgr_after, bgr_after])
             display_img([diff_mask, diff_mask_contours])
 
     # if compare_prev_warped:
@@ -354,6 +367,8 @@ def find_pieces(warped_img, sorted_warped_points, reader, img_idx):
     # define color thresholds to use to classify colors later on
     hue_thresh_dict = {'red': (170,190), 'orange':(8,18), 'yellow': (18,44), 'green': (50,70), 'purple': (120,140), 
                        'teal': (80,105), 'pink': (140,170)} # CHANGE
+    
+    letter_dict = {0: 'A', 1: 'B', 2: 'C', 3: 'D', 4: 'E', 5: 'F', 6: 'G', 7: 'H'}
 
     if (show_cv):
         warped_img_pil = cv2_to_pil(warped_img)
@@ -366,7 +381,7 @@ def find_pieces(warped_img, sorted_warped_points, reader, img_idx):
     
     # cur_bounding_box_array = np.empty((8,8), dtype=object)
     # cur_bounding_box_array.fill([])
-    pixel_thresh = 40
+    pixel_thresh = 150 # was 40
     color_grid = []
     # loop through each square of chess board
     for i in range(0,8):
@@ -380,6 +395,12 @@ def find_pieces(warped_img, sorted_warped_points, reader, img_idx):
             bl = sorted_warped_points[i+1][j]
             br = sorted_warped_points[i+1][j+1]
 
+            # straight edges around square
+            x_min = min(tl[0], bl[0])
+            x_max = max(tr[0], br[0])
+            y_min = min(tl[1], tr[1])
+            y_max = max(bl[1], br[1])
+
             # create mask of the square
             height, width, _ = warped_img.shape
             rect_mask = np.zeros((height, width), dtype=np.uint8)
@@ -433,7 +454,7 @@ def find_pieces(warped_img, sorted_warped_points, reader, img_idx):
                         cur_bounding_box = cv2.boundingRect(largest_contour)
                         # cur_bounding_box_array[j][i] = cur_bounding_box
                         
-                    hue = 0
+                    hue_sum = 0
                     if compare_prev_warped:
                         # display_img([filled_contour_mask])
                         # filled_contour_mask = cv2.bitwise_and(filled_contour_mask, filled_contour_mask, mask=diff_mask)
@@ -441,19 +462,35 @@ def find_pieces(warped_img, sorted_warped_points, reader, img_idx):
                         diff_contour_mask = cv2.bitwise_or(filled_contour_mask, prev_filled_contour_mask, mask=diff_mask_contours)
                         # diff_contour_mask = cv2.bitwise_and(diff_contour_mask, diff_contour_mask, mask=rect_mask)
 
-                        num_pixels = 1
-                        num_diff_pixels = 0
-                        for x in range(min(tl[0],bl[0]), max(tr[0],br[0])):
-                            for y in range(min(tl[1],tr[1]), max(bl[1],br[1])):
-                                if diff_contour_mask[y, x, 0] > 0:
-                                    num_diff_pixels += 1
-                                if filled_contour_mask[y, x, 0] > 0 and hsv_after[y, x, 0] != 0:
-                                    num_pixels += 1
-                                    hue += hsv_after[y, x, 0]
-                        avg_hue = hue / num_pixels
+                        # num_pixels = 1
+                        # num_diff_pixels = 0
+                        # for x in range(min(tl[0],bl[0]), max(tr[0],br[0])):
+                        #     for y in range(min(tl[1],tr[1]), max(bl[1],br[1])):
+                        #         if diff_contour_mask[y, x, 0] > 0:
+                        #             num_diff_pixels += 1
+                        #             if filled_contour_mask[y, x, 0] > 0 and hsv_after[y, x, 0] != 0:
+                        #                 num_pixels += 1
+                        #                 hue += hsv_after[y, x, 0]
+                        # avg_hue = hue / num_pixels
+
+                        # diff calculation
+                        diff_rect = diff_contour_mask[y_min:y_max, x_min:x_max, 0]
+                        num_diff_pixels = np.count_nonzero(diff_rect)
                         
                         if num_diff_pixels > pixel_thresh:
                             do_ocr = True
+
+                            cv2.drawContours(drawn_warped_img, diff_contours_sorted, -1, (0,0,255), thickness=cv2.FILLED)
+
+                            # get avg hue
+                            filled_rect = filled_contour_mask[y_min:y_max, x_min:x_max, 0]
+                            hsv_rect = hsv_after[y_min:y_max, x_min:x_max, 0]
+                            both_nonzero_mask = (filled_rect > 0) & (hsv_rect != 0)
+                            num_pixels = np.count_nonzero(both_nonzero_mask)
+                            hue_sum = np.sum(hsv_rect[both_nonzero_mask])
+
+                            avg_hue = hue_sum / num_pixels if num_pixels != 0 else 0
+
                             # only save the contour if it has enough pixels, otherwise erase it
                             if largest_contour is not None and num_pixels < pixel_thresh:
                                 cv2.drawContours(filled_contour_mask, [largest_contour], -1, (0, 0, 0), thickness=cv2.FILLED)
@@ -462,13 +499,22 @@ def find_pieces(warped_img, sorted_warped_points, reader, img_idx):
                             avg_hue = 0
                     else:
                         # loop through all pixels in square and find average hue
-                        num_pixels = 1
-                        for x in range(min(tl[0],bl[0]), max(tr[0],br[0])):
-                            for y in range(min(tl[1],tr[1]), max(bl[1],br[1])):
-                                if filled_contour_mask[y, x, 0] > 0 and hsv_after[y, x, 0] != 0:
-                                    num_pixels += 1
-                                    hue += hsv_after[y, x, 0]
-                        avg_hue = hue / num_pixels
+                        # num_pixels = 1
+                        # for x in range(min(tl[0],bl[0]), max(tr[0],br[0])):
+                        #     for y in range(min(tl[1],tr[1]), max(bl[1],br[1])):
+                        #         if filled_contour_mask[y, x, 0] > 0 and hsv_after[y, x, 0] != 0:
+                        #             num_pixels += 1
+                        #             hue += hsv_after[y, x, 0]
+                        # avg_hue = hue / num_pixels
+
+                        # get avg hue
+                        filled_rect = filled_contour_mask[y_min:y_max, x_min:x_max, 0]
+                        hsv_rect = hsv_after[y_min:y_max, x_min:x_max, 0]
+                        both_nonzero_mask = (filled_rect > 0) & (hsv_rect != 0)
+                        num_pixels = np.count_nonzero(both_nonzero_mask)
+                        hue_sum = np.sum(hsv_rect[both_nonzero_mask])
+
+                        avg_hue = hue_sum / num_pixels if num_pixels != 0 else 0
 
                         # only save the contour if it has enough pixels, otherwise erase it
                         if largest_contour is not None and num_pixels < pixel_thresh:
@@ -494,19 +540,21 @@ def find_pieces(warped_img, sorted_warped_points, reader, img_idx):
                     image=img_to_read,
                     allowlist="PKQRBN", # only want these letters
                     rotation_info=[180], # either rightside up or upside down
-                    text_threshold=0.7,
-                    low_text = 0.7,
+                    text_threshold=0.45,
+                    low_text = 0.1,
                     min_size = 5
                 )
 
                 # get letter if found
                 if len(result) != 0:
                     bound_box, letter, confidence = result[0]
-                    if show_cv:
-                        print(letter, confidence)
                 else:
-                    letter = "X"
+                    letter = "X - remove letter"
+                    confidence = ""
                 if show_cv:
+
+                    coord = letter_dict[j] + str(8 - i)
+                    print(letter, confidence, coord)
                     display_img([img_to_read])
 
                 for color, (lower, upper) in hue_thresh_dict.items(): # for each color threshold
@@ -526,30 +574,33 @@ def find_pieces(warped_img, sorted_warped_points, reader, img_idx):
             else:
                 color_grid[i].append([None, avg_hue, num_pixels, None])
 
-    if show_cv:
+    if show_cv and False:
         warped_img_draw = pil_to_cv2(warped_img_draw._image)
 
         bgr_after_intersections = bgr_after.copy()
         for points in sorted_warped_points:
                 for point in points:
                     cv2.circle(bgr_after_intersections, point, 1, (255, 255, 255), -1)
-        display_img([warped_img_draw, bgr_after_intersections, filled_contour_mask])
+        # display_img([warped_img_draw, bgr_after_intersections, filled_contour_mask])
+        display_img([bgr_after_intersections, filled_contour_mask])
 
     # if compare_prev_warped:
     #     display_img([diff_contour_mask])
 
     # print color_grid. only print when the color is found a lot in the square (> pixel_thresh times)
-    # if show_cv:
+    if show_cv:
         # print("|avg_hue, num_pixels, letter|")
-    # for row in color_grid:
-    #     print("||", end="")
-    #     for color, avg_hue, num_pixels, letter in row:
-    #         if num_pixels > pixel_thresh:
-    #             print(f"{color},   {letter}\t|", end="")
-    #             # print(f"{color},   {letter}\t|", end="")
-    #         else:
-    #             print("\t\t|", end="")
-    #     print("|")
+        for row in color_grid:
+            print("||", end="")
+            for color, avg_hue, num_pixels, letter in row:
+                if letter is not None and letter[0] == "X":
+                    print(f"{int(num_pixels)},   {letter}\t|", end="")
+                elif num_pixels > pixel_thresh:
+                    # print(f"{int(avg_hue)}, {color}, {letter}\t|", end="") # THE GOOD ONE
+                    print(f"{int(num_pixels)},   {letter}\t|", end="")
+                else:
+                    print("\t\t|", end="")
+            print("|")
 
     prev_warped_img = deepcopy(warped_img)
     prev_hsv_img = deepcopy(hsv_img)
@@ -565,7 +616,7 @@ def find_pieces(warped_img, sorted_warped_points, reader, img_idx):
     prev_largest_contour = deepcopy(largest_contour)
     # prev_bounding_box_array = cur_bounding_box_array.copy()
 
-    return color_grid
+    return color_grid, drawn_warped_img
 
 def sort_square_grid_coords(coordinates, unpacked):
     # this function assumes there are a perfect square amount of coordinates
diff --git a/game.py b/game.py
index 30e72ccf1b5c8b5bfa160628cee93cc70b51a963..0b406a84fa93aa61bac27a493c459f91b72ff0dc 100644
--- a/game.py
+++ b/game.py
@@ -2,6 +2,7 @@ import argparse
 import chess
 import chess.pgn
 from board_detector import find_board
+from board_detector import warp_board
 from board_detector import find_pieces
 from board_detector import init_global
 from board_detector import display_img
@@ -11,6 +12,7 @@ import cv2
 import os
 import time
 import easyocr
+import sys
 
 # was having issues installing picamera2 on my PC
 # if the raspi runs this code (with picamera2 installed), skip_camera will be false
@@ -21,15 +23,17 @@ try:
 except ImportError:
     skip_camera = True
 
-example_fens = {"gunnar_enpass": "r1bq1r2/pp2n1p1/4N2k/3pPp1P/1b1n2Q1/2N5/PP3PP1/R1B1K2R b KQ - 0 14"}
+example_fens = {"gunnar_enpass": "r1bq1r2/pp2n1p1/4N2k/3pPp1P/1b1n2Q1/2N5/PP3PP1/R1B1K2R b KQ - 0 14",
+                "piece_test_castling1-": "r3k3/1b1p1p2/p3pK2/5qp1/2P5/P3P3/1P2B3/R1R1Q3 w q - 4 30"} # prins 
 
 class ChessGame:
-    def __init__(self, difficulty, color_scheme, show_cv, show_cam, loop, img_idx = 1, test_img = None, save_img_as = None):
+    def __init__(self, difficulty, color_scheme, show_cv, show_board, show_cam, loop, img_idx = 1, test_img = None, save_img_as = None):
         self.board = chess.Board()
         self.prev_board = chess.Board()
         self.difficulty = difficulty
         self.color_scheme = color_scheme
         self.show_cv = show_cv
+        self.show_board = show_board
         self.show_cam = show_cam
         self.test_img = test_img
         self.loop = loop
@@ -49,6 +53,11 @@ class ChessGame:
 
         self.img_size = 512
 
+        # store warping info
+        self.corners_sorted = None
+        self.intersection = None
+        self.drawn_warped_img = None
+
         if not skip_camera:
             self.picam2 = Picamera2()
         else:
@@ -91,17 +100,26 @@ class ChessGame:
             self.board = chess.Board()
             # self.img_idx += 1
 
+        if self.show_board and self.drawn_warped_img is not None:
+            display_img([self.drawn_warped_img])
+
         while(1): # game loop
 
             # if self.board.turn == chess.WHITE:
             self.player_turn()
 
+            if self.show_board and self.drawn_warped_img is not None:
+                display_img([self.drawn_warped_img])
+
             if self.check_game_over():
                 break
 
             # if self.board.turn == chess.BLACK:
             self.ai_turn()
 
+            if self.show_board and self.drawn_warped_img is not None:
+                display_img([self.drawn_warped_img])
+
             if self.check_game_over():
                 break
 
@@ -149,6 +167,11 @@ class ChessGame:
             if (self.test_img):
                 img_txt = self.test_img + str(self.img_idx) + '.jpg'
                 img_path = os.path.join('ocr_test_images', img_txt)
+                if not os.path.exists(img_path):
+                    print("\n-------------------")
+                    print("Out of test images.")
+                    print("-------------------\n")
+                    sys.exit()
                 orig_img = cv2.imread(img_path)
                 self.img_idx += 1
             else:
@@ -175,15 +198,20 @@ class ChessGame:
 
             if (not self.loop):
                 break
+
+        if self.img_idx == 2:
+            self.corners_sorted, self.intersection = find_board(img)
         
         # warp the image based on the lines of the board
-        warped_img, sorted_warped_points = find_board(img)
+        # if self.img_idx == 1:
+        warped_img, sorted_warped_points = warp_board(img, self.corners_sorted, self.intersection)
 
         if (warped_img is None):
+            print("warped_img is None")
             return
         
         # get the pieces based on color thresholding and easyocr
-        color_grid = find_pieces(warped_img, sorted_warped_points, self.reader, self.img_idx - 1)
+        color_grid, self.drawn_warped_img = find_pieces(warped_img, sorted_warped_points, self.reader, self.img_idx - 1)
 
         # convert color_grid to board, which we can get fen string from
         if self.color_scheme == 'p/y':
@@ -201,6 +229,7 @@ class ChessGame:
             print(self.board)
             print(self.board.fen())
 
+
     def check_game_over(self):
         if self.board.is_checkmate():
             print("\n----------------------")
@@ -246,7 +275,7 @@ class ChessGame:
             for j, (color, _, _, letter) in enumerate(row):
                 piece_type = None
                 if letter is not None:
-                    print("letter:", letter)
+                    # print("letter:", letter)
                     letter = letter[0]
                     if letter == "P":
                         piece_type = chess.PAWN
@@ -260,7 +289,7 @@ class ChessGame:
                         piece_type = chess.QUEEN
                     elif letter == "K":
                         piece_type = chess.KING
-                    elif letter == "X":
+                    elif letter == "X": # 'X - remove letter'
                         temp_board.remove_piece_at(chess.square(j, 7 - i))
                         continue
 
@@ -284,20 +313,18 @@ class ChessGame:
             board_copy = self.prev_board.copy()
             board_copy.push(move)
 
-            # print(move)
-            # print(temp_board)
-            # print(temp_board.board_fen())
-            # print(board_copy)
-            # print(board_copy.board_fen())
             if (temp_board.board_fen() == board_copy.board_fen()):
                 found_move = True
+                print("Found move!", move)
                 self.board = board_copy.copy()
                 break
         
-        if found_move:
-            print("Found move!")
-        else:
+        if not found_move:
             print("Did NOT find move.")
+            if self.img_idx != 2:
+                print("Detected Board: ")
+                print(board_copy)
+                print("\n")
 
         # print("PREVIOUS BOARD:")
         # print(self.prev_board)
@@ -314,6 +341,7 @@ if __name__ == "__main__":
     parser.add_argument("--color_scheme", choices=["r/t", "p/y"], 
                         default="p/y", help="Red and teal or pink and yellow for chess piece colors")
     parser.add_argument("--show_cv", action="store_true", help="Show opencv images as processing occurs during game")
+    parser.add_argument("--show_board", action="store_true", help="Show only the board (will show warped version)")
     parser.add_argument("--show_cam", action="store_true", help="Show persistent camera view")
     parser.add_argument("--loop", action="store_true", help="Loop before cv (for taking test images)")
     parser.add_argument("--img_idx", help="Where to start indexing images (for naming them; default is 1 if not specified)")
@@ -321,5 +349,5 @@ if __name__ == "__main__":
     parser.add_argument("--save_img_as", help="If specified, will save image as given name in game_images")
     args = parser.parse_args()
 
-    game = ChessGame(args.difficulty, args.color_scheme, args.show_cv, args.show_cam, args.loop, args.img_idx, args.test_img, args.save_img_as)
+    game = ChessGame(args.difficulty, args.color_scheme, args.show_cv, args.show_board, args.show_cam, args.loop, args.img_idx, args.test_img, args.save_img_as)
     game.start_game()
\ No newline at end of file