示例#1
0
    def test_reformat_hand_xyy_yx6(self):
        # test an invalid hand to check error handling
        print "\nTest #9 reformat_hand_xyy_yx6 ~ invalid 3"

        # disable stdout to avoid screen clutter
        f = open(os.devnull, 'w')
        sys.stdout = f

        result = helpers.reformat_hand_xyy_yx("3_non_existent", 3)

        f.close()
        # re-enable stdout
        sys.stdout = sys.__stdout__

        self.assertEqual(None, result)
        print "Passed!"
示例#2
0
    def test_reformat_hand_xyy_yx5(self):
        # test an invalid hand to check error handling
        print "\nTest #8 reformat_hand_xyy_yx5 ~ invalid 5 #2"

        # disable stdout to avoid screen clutter
        f = open(os.devnull, 'w')
        sys.stdout = f

        result = helpers.reformat_hand_xyy_yx("c05c07d07d08s13", 100)

        f.close()
        # re-enable stdout
        sys.stdout = sys.__stdout__

        self.assertEqual(None, result)
        print "Passed!"
示例#3
0
 def test_reformat_hand_xyy_yx3(self):
     # test a valid 3 card hand
     print "\nTest #6 reformat_hand_xyy_yx3 ~ valid 3"
     result = helpers.reformat_hand_xyy_yx("c03d03s03", 3)
     self.assertEqual("3C3D3S", result)
     print "Passed!"
示例#4
0
 def test_reformat_hand_xyy_yx2(self):
     # test another valid hand to format
     print "\nTest #5 reformat_hand_xyy_yx2 ~ valid 5 #2 "
     result = helpers.reformat_hand_xyy_yx("s07c10d01c05c08", 5)
     self.assertEqual("5C7S8CTCAD", result)
     print "Passed!"
示例#5
0
 def test_reformat_hand_xyy_yx1(self):
     # test a valid hand to format
     print "\nTest #4 reformat_hand_xyy_yx1 ~ valid 5 #1 "
     result = helpers.reformat_hand_xyy_yx("c09c10c11c12c13", 5)
     self.assertEqual("9CTCJCQCKC", result)
     print "Passed!"
示例#6
0
def place_5(game_state, cards, sim_timer, test_deck=None):
    ''' takes game_state, first 5 cards and allocated simulated time in ms as inputs.
    Aggregates scores for simulations of each permutation of the first possible placements 
    and returns an optimal placement as a list with index i = card i+1's allocated row
    e.g. return [1,1,2,2,3] = card 1 in row 1, card 2 in row 1, card 3 in row 2, card 4 in row 2, card 5 in row 3'''

    # if a test deck is passed assign it to global
    if test_deck != None:
        global deck
        deck = test_deck

    try:
        cdic = {cards[0]:1, cards[1]:2, cards[2]:3, cards[3]:4, cards[4]:5} # keep a permanent record of which card was which index

    except Exception:
        print "Invalid cards passed to place_5:", cards
        raise Exception

    print "\n####\nPlace_5:", cards, "\nSimulation Timer:", sim_timer, "ms.\n"

    cstring = ""
    for i in range(0,5):
        cstring += cards[i][0] + cards[i][1] + cards[i][2]
    print cstring

    cstring = helpers.reformat_hand_xyy_yx(cstring, 5)

    cformatted = []
    for i in xrange(0,10,2):
        tstr = cstring[i] + cstring[i+1]
        cformatted.append(tstr)

    # ctemp = 13 elements: 5 cards + 8 '' blanks (13 containers on a player's OFC board)
    ctemp = cards[:]
    for i in range(0,8):
        ctemp.append(None)
        
    pbot = set(itertools.combinations(ctemp,5)) # produce set of combinations for a 5 card row
    pbot = list(pbot)

    pmid = pbot[:] # combinations middle same as bottom

    ptop = set(itertools.combinations(ctemp,3)) # produce set of combinations for a 3 card row
    ptop = list(ptop)

    rowlists = [pbot, pmid, ptop]

    x = set(itertools.product(*rowlists)) # product of all possible row combinations

    # histogram maps frequency of each rank - used to prune states to reduce complexity when there are pairs, trips etc.
    # e.g. if we have pair of Aces removes states where these aces are not placed together
    # as it is very unlikely this would be an optimal placement
    hist = produce_histogram(cformatted)
    if hist == None:
        raise ValueError("Invalid values passed to produce_histogram")
    print "Histogram:", hist, "\n"

    highestfreq = 1 # look for quads or trips or a pair
    thatrank = None
    for item in hist:
        if item[1] > highestfreq:
            highestfreq = item[1]
            thatrank = item[0]

    nexthighestfreq = 1 
    secondrank = None
    if highestfreq < 4: # look for 2nd pair
        for item in hist:
            if item[1] > nexthighestfreq and item[0] is not thatrank:
                nexthighestfreq = item[1]
                secondrank = item[0]
    
    # look for straights and higher, return immediately if found
    cards1 = helpers.reformat_hand_xyy_yx("".join(cards), 5)
    hand_score = hands.score_5(cards1)
    if hand_score[0] >= 5:
        print "Found", hands.classify_5(cards1), ", choosing this in bottom row!"
        return [1,1,1,1,1]

    print "Highest Freq:",highestfreq,"Rank:",thatrank,"... Next Highest Freq:",nexthighestfreq,"Rank:",secondrank
    
    final = []
    # post-processing removes duplicates and validates state has all cards placed 
    for rows in x:
        duplicate = False
        c_count = 0
        for pos in rows[0]:
            if pos is not None:
                c_count += 1
                if pos in rows[1] or pos in rows[2]:
                    duplicate = True
                    break

        if not duplicate:
            for pos in rows[1]:
                if pos is not None:
                    c_count += 1
                    if pos in rows[2]:
                        duplicate = True
                        break
            for pos in rows[2]:
                if pos is not None:
                    c_count += 1
            if c_count == 5 and not duplicate:
                final.append(rows)

    final2 = []

    # 2nd round of post-processing if there are pairs, trips or quads - remove states that don't place these optimally
    if thatrank is not None:
        for state in final:
            counts = [0,0,0]
            for i in range(0,3):
                for x in state[i]:
                    if x is not None:
                        x = int(x[1] + x[2])
                        if x == 1:
                            x = 14
                        if x == thatrank:
                            counts[i] += 1

            if counts[0] < highestfreq and counts[1] < highestfreq and counts[2] < highestfreq: # not all placed together
                # remove this non-optimal state
                pass
            else:
                final2.append(state) # append this state which has all instances of thatrank paired together
    else:
        final2 = final
        
    final3 = []
    
    # 3rd round for any second pair
    if secondrank is not None:
         for state in final2:
            counts = [0,0,0]
            for i in range(0,3):
                for x in state[i]:
                    if x is not None:
                        x = int(x[1] + x[2])
                        if x == 1:
                            x = 14
                        if x == secondrank:
                            counts[i] += 1

            if counts[0] < nexthighestfreq and counts[1] < nexthighestfreq and counts[2] < nexthighestfreq: # not all placed together
                # remove this non-optimal state
                pass
            else:
                final3.append(state) # append this state which has all instances of thatrank paired together
    else:
        final3 = final2

    final4 = []    
        
    # 4th round - if there are still lots of states to consider, prune some sub-optimal placements e.g. all cards placed in middle 
    if len(final3) > 20:
        for state in final3:
            # remove states with an empty or full bottom row
            count = 0
            for item in state[0]:
                if item is not None:
                    count += 1
            if count > 0 and count < 5:
                count = 0
                for item in state[2]:
                    if item is not None:
                        count += 1
                # prune states which have dumped 3 cards top
                if count < 3:
                    final4.append(state)
    else:
        final4 = final3  
        
    final = final4
    final2 = None #wipe
    final3 = None #wipe
    final4 = None #wipe
                 
    s_count = 0
    for state in final:
        s_count += 1
        #print str(s_count) + ":", state
        
    print "Total states:", s_count
    
    current_milli_time = lambda: int(round(time.time() * 1000))
    
    # produce every possible initial game state dictionary for AI placements 
    state_id = 1
    states_scores = []
    random.shuffle(final)
    for state in final:
        gs_copy = copy.deepcopy(game_state)
        for item in state[0]: # bottom
            if item is not None:
                gs_copy = simulate_append_card(gs_copy, 1, item, False)
        for item in state[1]: # middle
            if item is not None:
                gs_copy = simulate_append_card(gs_copy, 2, item, False)
        for item in state[2]: # top
            if item is not None:
                gs_copy = simulate_append_card(gs_copy, 3, item, False)
        
        stime = current_milli_time()
        
        s_ev = 0
        iterations = 0
        while ( (current_milli_time() - stime) < (sim_timer / s_count) ): # each state gets an equal % of iteration time
            s_ev += simulateGame(gs_copy, None, None, False) # simulates random placements of rest of cards on game board and returns EV
            iterations += 1
        
        states_scores.append([state_id, s_ev, iterations])
        
        state_id += 1

    print "\nSTATE SCORES:", states_scores, "\n\n"   
        
    # find the state selection with the highest EV
    highest_ev = 0
    best_state_score = [0,0,0]
    count = 0
    for result in states_scores:
        print "State:", final[count], "-> Total score", result[1], "from", result[2], "iterations = EV:", "{0:.2f}".format(float(result[1])/float(result[2]))
        if float(result[1])/float(result[2]) > highest_ev: # total ev / iterations -> equal weighting between all states , find best score
            best_state_score = result
            highest_ev = result[1]
        count += 1
    
    print "\nBest state score:", best_state_score
    
    best_state_id = best_state_score[0]
    best_state = final[best_state_id -1]
        
    print "~best state got:", best_state    
    
    ftw = open("states_ev.txt", "w")
    s = ""
    for line in states_scores:
        s = "ID: " + str(line[0]) + ", EV: " + str(line[1]) + " from " + str(line[2]) + " iterations. "
        s += str(final[line[0]-1]) + "\n"
        ftw.write(s)
    ftw.close()
    
    brow = best_state[0]
    mrow = best_state[1]
    trow = best_state[2]
    
    r_placements = [0,0,0,0,0]
    
    for item in brow:
        if item is not None:
            t = cdic[item]
            r_placements[t -1] = 1 # bottom
    for item in mrow:
        if item is not None:
            t = cdic[item]
            r_placements[t -1] = 2 # middle
    for item in trow:
        if item is not None:
            t = cdic[item]
            r_placements[t -1] = 3 # top
    
    a = "\nPlacements: "
    for i in range(0,5):
        a += cards[i] + " -> Row " + str(r_placements[i])
        if i is not 4:
            a += ", "
        else:
            a += "."
    print a
    return r_placements