#Colin Frazer
#Cary Academy INT-3
#ACSL Contest #4

import random

enemyLocations = [] #Enemy marker locations
playerMarkers = {
    "one":0,
    "two":0,
    "three":0
}
occupiedSpaces = [] #Which spaces are occupied
rolls = [] #Dice rolls
grid = [] #Game grid

#Read input
def readNumbers():
    #Bring relevant global variables into scope
    global rolls
    global enemyLocations
    global playerMarkers

    #Read input and split it into numbers, and convert each number to an integer
    inp = input("Input numbers: ")
    splitput = inp.split(" ")
    inputs = []
    for inpu in splitput:
        inputs.append(int(inpu))

    #Set enemy marker locations
    enemyLocations.append(inputs[0])
    enemyLocations.append(inputs[1])
    enemyLocations.append(inputs[2])

    #Set player marker locations
    playerMarkers["one"] = inputs[3]
    playerMarkers["two"] = inputs[4]
    playerMarkers["three"] = inputs[5]

    #Read die rolls
    for i in range(inputs[6]):
        rolls.append(inputs[7+i])

#Generate Panolli game grid
def generateGrid():
    #Bring relevant global variables into scope
    global grid

    #Generate 2D Panolli grid
    grid.append([0 , 0, 0, 0, 1,52, 0, 0, 0, 0])
    grid.append([0 , 0, 0, 0, 2,51, 0, 0, 0, 0])
    grid.append([7 , 6, 5, 4, 3,50,49,48,47,46])
    grid.append([8 , 9,10,11,12,41,42,43,44,45])
    grid.append([17,16,15,14,13,40,39,38,37,36])
    grid.append([18,19,20,21,22,31,32,33,34,35])
    grid.append([0 , 0, 0, 0,23,30, 0, 0, 0, 0])
    grid.append([0 , 0, 0, 0,24,29, 0, 0, 0, 0])
    grid.append([0 , 0, 0, 0,25,28, 0, 0, 0, 0])
    grid.append([0 , 0, 0, 0,26,27, 0, 0, 0, 0])

def updateOccupiedSpaces():
    #Bring relevant global variables into scope
    global enemyLocations
    global playerMarkers
    global occupiedSpaces

    occupiedSpaces.clear() #Clear list

    #Rebuild list with new occupied spaces
    occupiedSpaces.append(enemyLocations[0])
    occupiedSpaces.append(enemyLocations[1])
    occupiedSpaces.append(enemyLocations[2])
    occupiedSpaces.append(playerMarkers["one"])
    occupiedSpaces.append(playerMarkers["two"])
    occupiedSpaces.append(playerMarkers["three"])


def playGame():
    #Bring relevant global variables into scope
    global rolls
    global grid
    global occupiedSpaces
    global playerMarkers

    rollss = rolls
    gridd = grid
    occupiedSpacess = occupiedSpaces
    playerMarkerss = playerMarkers

    #Step through rolls
    for i, roll in enumerate(rolls):
        updateOccupiedSpaces()
        marker = getLowestMarker() #Get key for lowest number
        newSpace = playerMarkers[marker]+roll #Generate space to move to

        #Don't move if space is occupied
        if newSpace in occupiedSpaces:
            continue

        #Don't move if going off the board
        if newSpace > 52:
            continue

        #Remove piece from game if end is reached
        if newSpace==52:
            setMarker(marker, random.randint(55, 100)) #Setting the space to some high value off the board effectively removes it from the game
            continue

        #Initiate prime triggered skipping sequence if prime
        if (isPrime(newSpace)):
            newSpace=primeSkipping(newSpace)
            setMarker(marker, newSpace)
            continue

        #Initiate perfect square triggered skipping sequence if perfect square
        if (isPerfectSquare(newSpace)):
            newSpace=squareSkipping(newSpace)
            setMarker(marker, newSpace)
            continue

        if (cornerMove(playerMarkers[marker], newSpace)):
            newSpace=cornerSkipping(playerMarkers[marker], roll)
            setMarker(marker, newSpace)
            continue

        setMarker(marker, newSpace)
        updateOccupiedSpaces()

#Set marker to a value
def setMarker(marker, value):
    #Bring relevant global variables into scope
    global playerMarkers

    playerMarkers[marker] = value

#Prime number triggered skipping sequence
def primeSkipping(start):
    #Bring relevant global variables into scope
    global occupiedSpaces

    #Check if any blockages occur
    for i in range(7):
        if start+i in occupiedSpaces:
            return start+i-1 #Return partial movement if obstructed
    
    #Return full movement if unobstructed
    return start+6

#Perfect square triggered skipping sequence
def squareSkipping(start):
    #Bring relevant global variables into scope
    global occupiedSpaces

    #Check if any blockages occur
    for i in range(7):
        if start-i in occupiedSpaces:
            return start-i+1 #Return partial movement if obstructed
    
    #Return full movement if unobstructed
    return start-6

#Corner triggered skipping sequence
def cornerSkipping(start, roll):
    #Bring relevant global variables into scope
    global occupiedSpaces

    #Create variable to hold new location
    newLoc = start
    
    #Determine suitable location
    for i in range(start, start+roll+1):
        if i%roll == 0 and i not in occupiedSpaces:
            newLoc = i
    return newLoc

#Return true if horizontal and vertical difference, return false if not
def hDiff(start, end):
    #Bring relevant global variables into scope
    global grid

    #X values for start and end points
    startX = 0
    endX = 0

    #Find X values for start and end
    for i in range(10):
        for j in range(10):

            if grid[i][j] == start:
                startX = j

            elif grid[i][j] == end:
                endX = j

    #Return true if horitzontal movement occurred, false if otherwise
    if startX != endX:
        return True
    else:
        return False

def vDiff(start, end):
    #Bring relevant global variables into scope
    global grid

    #Y values for start and end points
    startY = 0
    endY = 0

    #Find Y values for start and end
    for i in range(10):
        for j in range(10):

            if grid[i][j] == start:
                startY = i

            elif grid[i][j] == end:
                endY = i

    #Return true if vertical movement occurred, false if otherwise
    if startY != endY:
        return True
    else:
        return False

def cornerMove(start, end):
    for i in range(start, end):
        if hDiff(i, i+1):
            for j in range(i, end):
                if vDiff(j, j+1):
                    return True
            return False
        else:
            return False

#Return false if composite number, return true otherwise
def isPrime(num):
    #Return false if number can be evenly divided by anything greater than 1 and less than itself
    for i in range(2, num):
        if num % i == 0:
            return False

    #Return true otherwise
    return True

#Returns true if perfect square, returns false otherwise
def isPerfectSquare(num):
    #Return true if number has an integer square root
    for i in range(2, num):
        if i**2 == num:
            return True
    
    #Return false otherwise
    return False

#Return key for lowest player marker
def getLowestMarker():
    #Bring relevant global variables into scope
    global playerMarkers

    #Find minimum value
    minimum = playerMarkers["one"]
    if (playerMarkers["two"] < minimum):
        minimum = playerMarkers["two"]
    if (playerMarkers["three"] < minimum):
        minimum = playerMarkers["three"]

    #Find and return which key correponds to the minimum value    
    for key in (["one", "two", "three"]):
        if playerMarkers[key] == minimum:
            return key

def printOutput():
    #Bring relevant global variables into scope
    global playerMarkers

    finout = [] #Setup list for printing
    
    #Add the values to the final list, ensuring none is greater than 52
    for key in (["one", "two", "three"]):
        if playerMarkers[key] <= 52:
            finout.append(playerMarkers[key])
            
    
    #Make sure at least one piece is on the board, and print output in numerical order
    for num in finout:
        if num < 52:
            finout.sort()
            print("Output:", str(finout))
            return
    
    #Print GAME OVER if all pieces are off the board
    print("GAME OVER")

for i in range(5):
    enemyLocations = [] #Enemy marker locations
    playerMarkers = {
        "one":0,
        "two":0,
        "three":0
    }
    occupiedSpaces = [] #Which spaces are occupied
    rolls = [] #Dice rolls
    grid = [] #Game grid
    readNumbers()
    generateGrid()
    updateOccupiedSpaces()
    playGame()
    printOutput()

'''
Sample inputs:

4 14 24 1 8 12 6 6 3 5 1 5 6
14 28 31 10 20 24 7 6 6 5 5 6 2 4
5 30 33 3 20 24 8 6 6 6 5 6 3 4 6
4 11 15 2 8 20 5 5 2 5 1 6
45 50 48 42 46 40 6 3 2 6 5 4 1

Sample outputs:
13 15 18
26 29 30
20 23 24
14 16 20
44 46 47
'''