コード例 #1
0
def simulateGame(game_state, row, card, bAppend, op_deck=None):
    ''' takes in game state and chosen row to place given card in if bAppend == True
    else if bAppend is false skip appending any specific card.
    randomly simulates rest of game and returns score '''
	
    gs_copy = copy.deepcopy(game_state) # deepcopy copies all elements including nested ones 
    if bAppend == True:
        gs_copy = simulate_append_card(gs_copy, row, card, True)    # append card to appropriate position in game state     
    prune_deck_of_cards(gs_copy)        
    
    #print gs_copy

    if op_deck is None:
        global deck     # get available cards for placement
        tdeck = deck[:]
        random.shuffle(tdeck)
    else:
        # use a specific passed deck (e.g. for consistent unit testing)
        tdeck = op_deck[:]
    
    # populate empty slots in game board with random cards
    for i in range(1,14):
        if gs_copy['properties2']['cards']['items']['position'+str(i)] == None:
            gs_copy['properties2']['cards']['items']['position'+str(i)] = tdeck.pop(0)
                    
        if gs_copy['properties1']['cards']['items']['position'+str(i)] == None:
            gs_copy['properties1']['cards']['items']['position'+str(i)] = tdeck.pop(0)
    

    current_milli_time = lambda: int(round(time.time() * 1000))
    stime2 = current_milli_time()
    
    scores = helpers.scoring_helper(gs_copy) # score game board 
    
    
    global loop_elapsed
    loop_elapsed += (current_milli_time() - stime2)
    
    p2score = (helpers.scores_arr_to_int(scores)) * -1 # function returns p1's score. Get the inverse of this for AI's EV
    
    global counthands
    counthands += 1
    
    if scores[3][1] == False or scores[3][0] == False: # only printing valid results (fouled simulated hands from both players omitted)

        if p2score > 0:
            global scoringhands
            scoringhands += 1
        elif p2score == 0:
            global zeroscorehands
            zeroscorehands += 1
        else:
            global losinghands
            losinghands += 1
    
    else:
        global nullscoringhands
        nullscoringhands += 1
        
    return p2score
コード例 #2
0
    def test_scores_arr_to_int5(self):
        # test validation in scores_arr_to_int
        print "\nTest #14 scores_arr_to_int - validation #3"

        test_scores = [[1, 0, 0], [1, 0, 0], [1, 0, "uh oh!"], [False, False]]
        result = helpers.scores_arr_to_int(test_scores)

        self.assertEqual(None, result)
        print "Passed!"
コード例 #3
0
    def test_scores_arr_to_int4(self):
        # test validation in scores_arr_to_int
        print "\nTest #13 scores_arr_to_int - validation #2"

        test_scores = ["invalid list length"]
        result = helpers.scores_arr_to_int(test_scores)

        self.assertEqual(None, result)
        print "Passed!"
コード例 #4
0
    def test_scores_arr_to_int3(self):
        # test validation in scores_arr_to_int
        print "\nTest #12 scores_arr_to_int - validation #1"

        test_scores = "invalid type1"
        result = helpers.scores_arr_to_int(test_scores)

        self.assertEqual(None, result)
        print "Passed!"
コード例 #5
0
    def test_scores_arr_to_int6(self):
        # test validation in scores_arr_to_int
        print "\nTest #15 scores_arr_to_int - validation #4"

        test_scores = [[1, 0, 0], [1, 0, 0], [1, 0, 0],
                       [False, "look im not a boolean!"]]
        result = helpers.scores_arr_to_int(test_scores)

        self.assertEqual(None, result)
        print "Passed!"
コード例 #6
0
    def test_scores_arr_to_int2(self):
        # test that function correctly converts scores array to int (p1's score)
        print "\nTest #11 scores_arr_to_int #2"

        test_scores = [[2, 0, 5], [2, 0, 3], [2, 0, 6], [False, False]]
        result = helpers.scores_arr_to_int(test_scores)

        self.assertEqual(type(1), type(result))
        self.assertEqual(-20, result)

        print "Passed!"
コード例 #7
0
    def test_scores_arr_to_int1(self):
        # test that function correctly converts scores array to int (p1's score)
        print "\nTest #10 scores_arr_to_int #1"

        test_scores = [[1, 3, 0], [1, 0, 0], [2, 0, 0], [False, False]]
        result = helpers.scores_arr_to_int(test_scores)

        self.assertEqual(type(1), type(result))
        self.assertEqual(4, result)

        print "Passed!"
コード例 #8
0
ファイル: game_logic.py プロジェクト: slavugan/OFCP-AI
def handle_game_logic(game_state, game_id):
    '''
    Take in game state from frontend and game id as inputs - use game id to get record from database
    Compare game state passed to game state from db - validate legitimacy
    Based off who went first and cards placed so far determine next action e.g. deal cards, AI, score board
    Update game state changes and store in database, call AI helper functions to determine optimal play
    Return appropriate response to server e.g. updated game state, cards to be placed, scores array
    '''

    current_milli_time = lambda: int(round(time.time() * 1000))

    # retrieve database for this game
    games = db_backend.get_database_collection()
    state = games.find_one({'_id': ObjectId(game_id)})

    # find if player acted first this round and how many cards have been placed in order to work out current game position
    count = 0
    playerFirst = state["playerFirst"]
    for i in range(0, 13):
        for j in range(0, 2):
            if game_state['properties' +
                          str(j + 1)]['cards']['items']['position' +
                                                        str(i +
                                                            1)] is not None:
                count += 1

    print "\nCurrent game state:\n", game_state, "\nCards placed:", count

    if playerFirst:

        # Special case for player's first turn
        if count == 0:
            cdeck = deck.Deck()  # creates deck
            cards = cdeck.deal_n(5)
            state['deck'] = {}  # initialise deck dic within game state
            state['deck']['cards'] = cdeck.cards
            state['deck']['current-position'] = cdeck.current_position

            state['first5cards'] = cards

            # update game state in database
            update = games.update({'_id': ObjectId(game_id)}, {'$set': state})

            return json.dumps(cards)

        # Special case for AI's first turn
        elif count == 5:

            # remove first 5 cards entry from db now that these have been placed on the board
            del state['first5cards']

            # recreate deck from deck info in database
            cdeck = deck.Deck(state['deck']['cards'],
                              state['deck']['current-position'])

            # validate game state
            state = validate_and_update_state(cdeck, count, game_state, state)
            if state == 0:
                return 0  # raise cherrypy 500 error

            # calculate AI's first 5 card placements
            cards = cdeck.deal_n(5)
            OFCP_AI.loop_elapsed = 0

            stime = current_milli_time()

            iterations_timer = 4000  # Sets time in ms to spend simulating games.
            # As iterations increases diverges to optimal solution
            cardPlacementsAI = OFCP_AI.chooseMove(game_state, cards,
                                                  iterations_timer)

            print "\nTime taken calculating 5 placements:", current_milli_time(
            ) - stime, "ms"
            print "Total time spent scoring hands: ", OFCP_AI.loop_elapsed, "ms"

            state = zip_placements_cards(cardPlacementsAI, cards, state)
            if state == 1:
                # Error with AI placement
                return 1

            # deal player's next card
            card = cdeck.deal_one()

            # update game state with deck info
            state['deck']['cards'] = cdeck.cards
            state['deck']['current-position'] = cdeck.current_position

            # records game state in database + remove first5cards key
            state['cardtoplace'] = card
            update = games.update({'_id': ObjectId(game_id)}, {
                '$set': state,
                '$unset': {
                    'first5cards': 1
                }
            })

            del state['deck']  # don't return deck info to frontend
            del state['_id']
            # state.pop('_id', None)

            return json.dumps(state)

        # general case for every other round after initial 5 placements by player and AI
        elif count < 26:

            cdeck = deck.Deck(state['deck']['cards'],
                              state['deck']['current-position'])

            # validate game state
            state = validate_and_update_state(cdeck, count, game_state, state)
            if state == 0:
                return 0  # raise cherrypy 500 error

            # AI's next move
            card = str(cdeck.deal_one())
            OFCP_AI.loop_elapsed = 0

            stime = current_milli_time()
            iterations_timer = 3000
            AI_placement = OFCP_AI.chooseMove(game_state, card,
                                              iterations_timer)

            print "\nTime taken calculating 1 placement:", current_milli_time(
            ) - stime, "ms"
            print "Total time spent scoring hands: ", OFCP_AI.loop_elapsed, "ms"

            state = zip_placements_cards([AI_placement], [card], state)
            if state == 1:
                # Error with AI placement
                return 1

            # deal player's next card
            card = cdeck.deal_one()

            # update game state with deck info
            state['deck']['cards'] = cdeck.cards
            state['deck']['current-position'] = cdeck.current_position

            # records game state in database
            state['cardtoplace'] = card
            update = games.update({'_id': ObjectId(game_id)}, {'$set': state})

            # print "\nStored game state in database:", state

            del state['deck']  # don't return deck info to frontend
            del state['_id']

            # print "\nReturning state to player:", state

            return json.dumps(state)

        else:
            # game over - validate and score game board

            cdeck = deck.Deck(state['deck']['cards'],
                              state['deck']['current-position'])

            # validate game state
            state = validate_and_update_state(cdeck, count, game_state, state)
            if state == 0:
                return 0  # raise cherrypy 500 error

            # update game state with deck info
            state['deck']['cards'] = cdeck.cards
            state['deck']['current-position'] = cdeck.current_position

            # score game board
            scores_array = helpers.scoring_helper(game_state)

            # store p1's score in database
            state['score'] += helpers.scores_arr_to_int(scores_array)
            print "\nState score recorded as:", state['score'], "!\n"
            scores_array.append([state['score']])
            print "scores_array was", scores_array

            # records game state in database
            del state['cardtoplace']
            update = games.update({'_id': ObjectId(game_id)}, {'$set': state})

            OFCP_AI.reset()  # reset AI variables/ states

            # scores_array format [ [winnerid, winners_bottom_royalty, losers_bottom_royalty],
            #    [winnerid, winners_middle_royalty, losers_middle_royalty] ,
            #    [winnerid, winners_top_royalty, losers_top_royalty] ],
            #    [p1foulbool, p2foulbool],
            #    [p1_existing_score]

            print '\n   Scores -->', scores_array, '\n'

            return json.dumps(scores_array)

    else:
        if count == 0:
            # AI acts first, but return player's first 5 cards first while AI calculates
            if 'first5cards' not in state:
                cdeck = deck.Deck()  # creates deck
                cards_5_player = cdeck.deal_n(5)  # player's first 5 cards
                state['deck'] = {}  # initialise deck dic within game state
                state['deck']['cards'] = cdeck.cards
                state['deck']['current-position'] = cdeck.current_position

                # validate game state
                state = validate_and_update_state(cdeck, count, game_state,
                                                  state)
                if state == 0:
                    return 0  # raise cherrypy 500 error

                state['first5cards'] = cards_5_player

                # update game state in database
                update = games.update({'_id': ObjectId(game_id)},
                                      {'$set': state})

                return json.dumps(cards_5_player)

            else:
                cdeck = deck.Deck(state['deck']['cards'],
                                  state['deck']['current-position'])
                cards_5_AI = cdeck.deal_n(5)

                # validate game state
                state = validate_and_update_state(cdeck, count, game_state,
                                                  state)
                if state == 0:
                    return 0  # raise cherrypy 500 error

                # calculate AI's first 5 card placements
                OFCP_AI.loop_elapsed = 0

                stime = current_milli_time()

                iterations_timer = 4000  # Sets time in ms to spend simulating games.
                # As iterations increases diverges to optimal solution
                cardPlacementsAI = OFCP_AI.chooseMove(game_state, cards_5_AI,
                                                      iterations_timer)

                print "\nTime taken calculating 5 placements:", current_milli_time(
                ) - stime, "ms"
                print "Total time spent scoring hands: ", OFCP_AI.loop_elapsed, "ms"

                state = zip_placements_cards(cardPlacementsAI, cards_5_AI,
                                             state)
                if state == 1:
                    # Error with AI placement
                    return 1

                # update game state with deck info
                state['deck']['cards'] = cdeck.cards
                state['deck']['current-position'] = cdeck.current_position

                # records game state in database + remove first5cards key
                update = games.update({'_id': ObjectId(game_id)},
                                      {'$set': state})

                del state['deck']  # don't return deck info to frontend
                del state['_id']
                # state.pop('_id', None)

                return json.dumps(state)

        # general case for every other round after initial 5 placements by player and AI
        elif count < 26:

            cdeck = deck.Deck(state['deck']['cards'],
                              state['deck']['current-position'])

            # validate game state
            state = validate_and_update_state(cdeck, count, game_state, state)
            if state == 0:
                return 0  # raise cherrypy 500 error

            # AI's next move
            card = str(cdeck.deal_one())
            OFCP_AI.loop_elapsed = 0

            stime = current_milli_time()
            iterations_timer = 3000
            AI_placement = OFCP_AI.chooseMove(game_state, card,
                                              iterations_timer)

            print "\nTime taken calculating 1 placement:", current_milli_time(
            ) - stime, "ms"
            print "Total time spent scoring hands: ", OFCP_AI.loop_elapsed, "ms"

            state = zip_placements_cards([AI_placement], [card], state)
            if state == 1:
                # Error with AI placement
                return 1

            # deal player's next card
            card = cdeck.deal_one()

            # update game state with deck info
            state['deck']['cards'] = cdeck.cards
            state['deck']['current-position'] = cdeck.current_position

            # records game state in database
            state['cardtoplace'] = card
            update = games.update({'_id': ObjectId(game_id)}, {'$set': state})

            # print "\nStored game state in database:", state

            del state['deck']  # don't return deck info to frontend
            del state['_id']

            # print "\nReturning state to player:", state

            return json.dumps(state)

        else:
            # game over - validate and score game board

            cdeck = deck.Deck(state['deck']['cards'],
                              state['deck']['current-position'])

            # validate game state
            state = validate_and_update_state(cdeck, count, game_state, state)
            if state == 0:
                return 0  # raise cherrypy 500 error

            # update game state with deck info
            state['deck']['cards'] = cdeck.cards
            state['deck']['current-position'] = cdeck.current_position

            # score game board
            scores_array = helpers.scoring_helper(game_state)

            # store p1's score in database
            state['score'] += helpers.scores_arr_to_int(scores_array)
            print "\nState score recorded as:", state['score'], "!\n"
            scores_array.append([state['score']])
            print "scores_array was", scores_array

            # records game state in database
            del state['cardtoplace']
            update = games.update({'_id': ObjectId(game_id)}, {'$set': state})

            OFCP_AI.reset()  # reset AI variables/ states

            #    scores_array format [ [winnerid, winners_bottom_royalty, losers_bottom_royalty],
            #    [winnerid, winners_middle_royalty, losers_middle_royalty] ,
            #    [winnerid, winners_top_royalty, losers_top_royalty] ],
            #    [p1foulbool, p2foulbool],
            #    [p1_existing_score]

            print '\n   Scores -->', scores_array, '\n'

            return json.dumps(scores_array)