Esempio n. 1
0
def applyCard(iP1, card, curse, Spots):
    iP2 = np.array([])  ##initialize list of generated positions
    ##cannot apply a card if both pawns are already at the end
    if 101 in iP1[:, 0]:
        #print("No need to apply cards... you already won!")  ##for debugging
        iP2 = iP1
    else:
        if 0 < card < 10:
            ##make sure you only apply cards which haven't already been used
            for i in range(iP1.shape[0]):
                if str(iP1[i,
                           2])[card] == '1':  ##then card has already been used
                    continue
                ##otherwise, apply the card and mark in the encoder that the card has been used
                iP2 = np.append(iP2, iP1[i, :] - (card, 0, -10**(11 - card)))
                ## Can only subtract or divide when cursed
                if not curse:
                    iP2 = np.append(
                        iP2, iP1[i, :] + (card, 0, 10**(11 - card))
                    )  ##so card corresponds to digit number card
                ##again, do not apply a card to a pawn already at 101
                if iP1[i, 1] != 101:
                    iP2 = np.append(iP2,
                                    iP1[i, :] - (0, card, -10**(11 - card)))
                    ## Can only subtract or divide when cursed
                    if not curse:
                        iP2 = np.append(iP2,
                                        iP1[i, :] + (0, card, 10**(11 - card)))
        elif 9 < card < 12:  ##these cards bump a pawn back to start (the player could do this to themself)
            for i in range(iP1.shape[0]):
                iP2 = np.append(iP2,
                                np.array([
                                    0, iP1[i, 1],
                                    100000000000 + 10**(11 - card)
                                ]))  ##move lower pawn
                if iP1[i, 1] != 101:  ##can't move higher pawn if it is at 101
                    iP2 = np.append(iP2,
                                    np.array([
                                        0, iP1[i, 0],
                                        100000000000 + 10**(11 - card)
                                    ]))  ##move higher pawn
        num = np.int(iP2.shape[0] / 3)  ##count number of positions in the list
        iP2 = iP2.reshape((num, 3))  ##reshape to a list of triples
        iP2 = cleanPositions(
            iP2, Spots)  ##sort, remove unallowable positions and duplicates
    return iP2
Esempio n. 2
0
def simpleMove(roll, pos):
    #partialFlag = 0  ##a flag keeping track of whether it is possible to win on a partial turn
    ##initialize the array of positions with the current position
    iP1 = np.array(pos).reshape((1,2))
    
    ##create all possible orderings for applying dice
    ##e.g. with no cards, we can either apply die1 then die2, or die2, then die1
    if roll[0] == roll[1]:   ##rolled doubles so get 4 copies
        scheme = np.array([str(roll[0]),str(roll[0]),str(roll[0]),str(roll[0])]).reshape((1,4))
    else:
        scheme = np.array([str(roll[0]),str(roll[1]),str(roll[1]),str(roll[0])]).reshape((2,2))

    finalPos = np.array([])  #initialize the array of all complete moves
    for order in scheme:
        intermediatePos2 = iP1.copy()
        for item in order:
            posList = np.array([])
            for i in range(intermediatePos2.shape[0]):
                pos = intermediatePos2[i,:].reshape((1,iP1.shape[1]))
                posList = np.append(posList, applyDie(pos, int(item)))
            intermediatePos2 = posList.reshape((posList.shape[0]//2, 2))
            #if 101 in intermediatePos2[:,0]: ##you can win on a partial turn
            #    partialFlag = 1
        finalPos = np.append(finalPos,intermediatePos2)
    k = np.int(finalPos.shape[0]/2)  ##count number of possible positions (pairs)
    finalPos = finalPos.reshape((k,2))  ##reshape array to (k,2)
    finalPos = cleanPositions(finalPos) #sort, delete repeats and unallowable positions
    ##take care of *self* bumping (i.e. if pos[0]==pos[1] then one pawn goes back to start)
    delRow = np.array([])  ##initialize list of rows to delete
    for i in range(finalPos.shape[0]):
        if finalPos[i,0]==finalPos[i,1] and finalPos[i,0]!=101 and finalPos[i,0]!=0:
            ##delete the option if bumping creates a duplicate
            if [0, finalPos[i,1]] in finalPos.tolist():
                delRow = np.append(delRow, i)
            else:
                finalPos[i,0]=0
    ##REMOVE DUPLICATES##
    finalPos = np.delete(finalPos, delRow.astype('i8'), axis=0)
    return finalPos.astype('int')
Esempio n. 3
0
def applyDie(iP1, die, curse=False, Spots=np.arange(102)):
    if die == 0:  ##A roll of zero corresponds to the value 10
        die = 10
    ##add a way to deal with the possibility of cards and no cards simultaneously
    c = iP1.shape[1]  ##2 if no cards, 3 if allowing cards
    adder1 = (die, 0, 0)
    adder2 = (0, die, 0)
    mult1 = (die, 1, 1)
    mult2 = (1, die, 1)

    iP2 = np.array([])  ##initialize new array of possible positions
    if 101 in iP1[:, 0]:  ##do not allow movement away from position 101
        #print("You already won... No need to keep rolling.")  ##for debugging only
        iP2 = iP1
    else:
        ##when cursed, you can only subtract or divide
        iP2 = np.append(iP2, iP1 - adder1[:c])
        iP2 = np.append(iP2, iP1 / mult1[:c])
        ##if not cursed, you can also add or multiply
        if curse == False:
            iP2 = np.append(iP2, iP1 + adder1[:c])
            iP2 = np.append(iP2, iP1 * mult1[:c])
        ##do not allow movement away from position 101 in the second position either
        if iP1[0, 1] != 101:
            ##when cursed, you can only subtract or divide
            iP2 = np.append(iP2, iP1 - adder2[:c])
            iP2 = np.append(iP2, iP1 / mult2[:c])
            ##if not cursed, you can also add or multiply
            if curse == False:
                iP2 = np.append(iP2, iP1 + adder2[:c])
                iP2 = np.append(iP2, iP1 * mult2[:c])
        ##count the number of new positions (represented as c-tuples)
        num = np.int(iP2.shape[0] / c)
        ##reshape to a list of c-tuples
        iP2 = iP2.reshape((num, c))
        #sort, eliminate duplicates and unallowable positions
        iP2 = cleanPositions(iP2)
    return iP2
Esempio n. 4
0
def moveMapper(roll, curr_pos, availCards, curse, Spots):
    ##initialize the array of positions with the current position
    iP1 = np.array(curr_pos)  ##intermediate Position 1
    '''
    add the encoding of the cards which have been used.
    Note that in this encoding, digit i (1-11) corresponds to a one-hot for card i being used
    Thus, if card 4 has been used, we will add 10^(11-4)
    '''
    iP1 = np.append(iP1, 100000000000)

    ##create all possible orderings for applying cards and dice
    ##first generate a scheme of all possible orders in which to apply dice and/or cards
    ##e.g. with no cards, we can either apply die1 then die2, or die2, then die1
    if roll[0] == roll[1]:  ##rolled doubles so get 4 copies
        scheme = np.array(
            [str(roll[0]),
             str(roll[0]),
             str(roll[0]),
             str(roll[0])])
    else:
        scheme = np.array([str(roll[0]), str(roll[1])])
    ##Add all available action cards to the scheme generator
    for card in availCards:
        if 0 < card < 12:
            scheme = np.append(scheme, 'c' + str(card))
    scheme = set(
        permutations(scheme))  ##create all permutations of the scheme list
    ##it only makes logical sense to move yourself home at the beginning of your turn, otherwise you waste dice
    ##thus, we'll remove any permutations which have card 10 or 11 played later in the turn
    if 10 in availCards or 11 in availCards:
        keepset = []
        for x in scheme:
            if x[0] == 'c10' or x[0] == 'c11':
                keepset.append(x)
        if 10 in availCards and 11 in availCards:
            scheme = []
            for x in keepset:
                if x[1] == 'c10' or x[1] == 'c11':
                    scheme.append(x)
        else:
            scheme = keepset
    finalPos = np.array([])  #initialize the array of all complete moves
    partialFlag = 0  ##a boolean of whether player can win on a partial turn
    for order in scheme:
        impossible = False  ##flag used to eliminate impossible branches
        iP2 = iP1.copy().reshape(
            1, 3)  ##A list of possible intermediate locations
        for item in order:
            #print(iP2.shape)
            if item[0] == 'c':  ##if the first character is c, apply card
                ##ALSO Keep track of positions without using the card!
                iP2 = np.append(iP2,
                                applyCard(iP2, int(item[1:]), curse, Spots),
                                axis=0)
            else:
                iP2 = applyDie(iP2, int(item), curse, Spots)
                ##it is possible (although unlikely) to have no allowable moves
                ##if so, it should ignore these options
                if iP2.shape[0] == 0:
                    impossible = True
                    break
            if 101 in iP2[:, 0]:  ##you can win on a partial turn
                iP2 = iP2[np.where(iP2[:, 0] == 101)]
                partialFlag = 1
                break

        if not impossible:
            if len(finalPos) == 0:
                finalPos = iP2.copy()
            else:
                finalPos = np.append(finalPos, iP2, axis=0)
        else:
            continue
        if partialFlag == 1:
            break
    num = finalPos.shape[0]  ##count number of possible positions (triples)

    ##it is possible to have no options (say b/c of curses), if so, stay put
    if num == 0:
        finalPos = iP1.copy().reshape(-1, 3)  ##stay put
    else:
        #sort, delete repeats and unallowable positions
        finalPos = cleanPositions(finalPos, Spots)

        ##take care of *self* bumping (if pos[0]==pos[1] then one pawn goes back to start)
        delRow = np.array([])  ##initialize list of rows to delete
        for idx, pos in enumerate(finalPos):
            if pos[0] == pos[1] and pos[0] != 101:
                if pos[1] != 0 and [0, pos[1], pos[2]] in finalPos.tolist():
                    delRow = np.append(delRow, idx)
                else:
                    pos[0] = 0
        ##REMOVE DUPLICATES##
        finalPos = np.delete(finalPos, delRow.astype('i8'), axis=0)

    finalPos.view('i8,i8,i8').sort(order=['f0', 'f1'], axis=0)
    return finalPos.astype('i8')