Skip to content
Snippets Groups Projects
Select Git revision
  • 3f6c359e75230c2cb65e9d30e53ce56d31e412e0
  • master default protected
2 results

test.o

Blame
  • main.py NaN GiB
    """
    COMP30024 Artificial Intelligence, Semester 1, 2021
    Project Part A: Searching
    
    This script contains the entry point to the program (the code in
    `__main__.py` calls `main()`). Your solution starts here!
    """
    
    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
    
    # 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)
        except IndexError:
            print("usage: python3 -m search path/to/input.json", file=sys.stderr)
            sys.exit(1)
    
        parse_input(data)
        # So basically it is heavily implied to treat the game as a state-based search problem.
        # We are also told in question 3 of the design report to discuss the time and space
        # requirements, and the connection with the branching factor and search tree depth.
        # In question 2 we are told to comment on any heuristics we use.
        # Considering all of the above, I propose that we use the heuristic of "tiles to closest target"
        # This is greedy, but it's a lot faster than trying to path optimally.
        # And for search algorithm choice let's try starting with depth-first search, depth limit 1, 2 or 3
        # Not sure which is best at the moment, looking ahead is good but looking too far ahead costs too much time
        # We'll use a dictionary to track current targets
        # ALGORITHM GOES HERE
    
        # Add starting targets
        for piece in upperDictPieces:
            find_target(piece)
        # keep moving until all the piece met its target
        while targetDict:
            upperDictPieces = update_state(upperDictPieces, lowerDictPieces, setBlocks, targetDict)
            targetDict = check_if_piece_hit_target(upperDictPieces, targetDict)
            print(upperDictPieces)
    
    
    def parse_input(data):
        """
         data is a dictionary with keys "upper", "lower" and "block"
         pieces in dictionary, blocks in set, we can use if position in setblocks
    
        parse data into either dictPieces or setBlocks
        :param data: Dictionary obtain after read from JSON file using JSON module.
        :return: NULL
        """
        # We can put the code to read the file NOT in the try/except statement because
        # if the file couldn't be read the process would end anyway
    
        global upperDictPieces, lowerDictPieces, setBlocks
        initialPiecesUpper = data["upper"]
        initialPiecesLower = data["lower"]
        initialBlocks = data["block"]
    
        keyWrite = ""
    
        # Parse the Upper's player token
        nump, numr, nums = 0, 0, 0
        for piece in initialPiecesUpper:
            if piece[TYPE] == "p":
                nump = nump + 1
                keyWrite = "P" + str(nump)
            elif piece[TYPE] == "r":
                numr = numr + 1
                keyWrite = "R" + str(numr)
            else:
                nums = nums + 1
                keyWrite = "S" + str(nums)
            upperDictPieces[keyWrite] = (piece[ROW], piece[COLUMN])
    
        # parse the Lower player's token
        nump, numr, nums = 0, 0, 0
        for piece in initialPiecesLower:
            if piece[TYPE] == "p":
                nump = nump + 1
                keyWrite = "p" + str(nump)
            elif piece[TYPE] == "r":
                numr = numr + 1
                keyWrite = "r" + str(numr)
            else:
                nums = nums + 1
                keyWrite = "s" + str(nums)
            lowerDictPieces[keyWrite] = (piece[ROW], piece[COLUMN])
    
        # parse the block object
        for block in initialBlocks:
            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
    
    
    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,
        # there will be a crash at tile N as both R and S try to take a straight line
        #              .-'-._.-'-._.-'-._.-'-._.-'-.
        #             |     |     |     |     |     |
        #           .-'-._.-'-._.-'-._.-'-._.-'-._.-'-.
        #          |     |  p  |     |     |  s  |     |
        #        .-'-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'-.
        #       |     |     |     |     |     |     |     |
        #     .-'-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'-.
        #    |     |     |     |     |     |     |     |     |
        #  .-'-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'-.
        # |     |     |     |     |  N  |     |     |     |     |
        # '-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'
        #    |     |     |     |     |     |     |     |     |
        #    '-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'
        #       |     |     |     |     |     |     |     |
        #       '-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'
        #          |     |  R  |     |     |  S |     |
        #          '-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'
        #             |      |     |     |     |     |
        #             '-._.-'-._.-'-._.-'-._.-'-._.-'
    
        # Situation 2 (B are blocks)
        # I'm not sure if they will throw something this tricky at us
        # but this should be solvable
        #              .-'-._.-'-._.-'-._.-'-._.-'-.
        #             |     |     |     |     |     |
        #           .-'-._.-'-._.-'-._.-'-._.-'-._.-'-.
        #          |     |     |     |     |     |     |
        #        .-'-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'-.
        #       |     |     |     |     |     |     |     |
        #     .-'-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'-.
        #    |  B  |  B  |  B  |  B  |  B  |  B  |  B  |     |
        #  .-'-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'-.
        # |  B  |  P  |     |     |  S  |  r  |  p  |  B  |     |
        # '-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'
        #    |  B  |  B  |  B  |  B  |  B  |  B  |  B  |     |
        #    '-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'
        #       |     |     |     |     |     |     |     |
        #       '-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'
        #          |     |     |     |     |     |     |
        #          '-._.-'-._.-'-._.-'-._.-'-._.-'-._.-'
        #             |     |     |     |     |     |
        #             '-._.-'-._.-'-._.-'-._.-'-._.-'