Exemplo n.º 1
0
    def drop(self):
        """ Drop card from hand. (Required API by Agent)
        This API will implement the algorithm to deside the dropped card. It will be called during game when necessary.
        Agent is responsible for removing dropped card from hand when make decision.
        The implemented dropping card algorithm as below:
        1. 只有獨張的風牌或中發白
        2. 沒有機會形成 Triplet 或 Sequence 的萬/筒/條 (只有單張)
        3. 頭尾的先丟. (Ex. 1萬/9萬/1筒/9筒/1條/9條)
        4. 下家有丟過的先丟.
        5. 最後都沒有滿足, 任意丟一張 萬/筒/條.
        * Return
          Dropped card which being removed from hand.
        """
        card = ''
        # 1. 只有獨張的風牌或中發白就丟.
        if (not card) and len(self.word_list) == 1:
            card = self.word_list.pop()
            self.card_count -= 1
            return card
        else:
            for c in set(self.word_list):
                if self.word_list.count(c) == 1:
                    self.word_list.remove(c)
                    self.card_count -= 1
                    return c

        if (not card) and len(self.wind_list) == 1:
            card = self.wind_list.pop()
            self.card_count -= 1
            return card
        else:
            for c in set(self.wind_list):
                if self.wind_list.count(c) == 1:
                    self.wind_list.remove(c)
                    self.card_count -= 1
                    return c
        # 2. 沒有機會形成 Triplet 或 Sequence 的萬/筒/條 (只有單張)
        # 3. 頭尾的先丟. (Ex. 1萬/9萬/1筒/9筒/1條/9條)
        if (not card) and len(self.tube_list) > 0:
            for c in set(self.tube_list):
                #number = int(card[:1])
                if self.tube_list.count(c) > 1:
                    continue
                elif GameBoard.PrevCard(
                        c) in self.tube_list or GameBoard.NextCard(
                            c) in self.tube_list:
                    continue
                else:
                    self.tube_list.remove(c)
                    self.card_count -= 1
                    return c
            if (not card) and '1筒' in self.tube_list:
                card = '1筒'
                self.tube_list.remove(card)
                self.card_count -= 1
                return card
            elif (not card) and '9筒' in self.tube_list:
                card = '9筒'
                self.tube_list.remove(card)
                self.card_count -= 1
                return card

        if (not card) and len(self.wang_list) > 0:
            for c in set(self.wang_list):
                if self.wang_list.count(c) > 1:
                    continue
                elif GameBoard.PrevCard(
                        c) in self.wang_list or GameBoard.NextCard(
                            c) in self.wang_list:
                    continue
                else:
                    self.wang_list.remove(c)
                    self.card_count -= 1
                    return c
            if (not card) and '1萬' in self.wang_list:
                card = '1萬'
                self.wang_list.remove(card)
                self.card_count -= 1
                return card
            elif (not card) and '9萬' in self.wang_list:
                card = '9萬'
                self.wang_list.remove(card)
                self.card_count -= 1
                return card

        if (not card) and len(self.bamb_list) > 0:
            for c in set(self.bamb_list):
                if self.bamb_list.count(c) > 1:
                    continue
                elif GameBoard.PrevCard(
                        c) in self.bamb_list or GameBoard.NextCard(
                            c) in self.bamb_list:
                    continue
                else:
                    self.bamb_list.remove(c)
                    self.card_count -= 1
                    return c
            if (not card) and '1條' in self.bamb_list:
                card = '1條'
                self.bamb_list.remove(card)
                self.card_count -= 1
                return card
            elif (not card) and '9條' in self.bamb_list:
                card = '9條'
                self.bamb_list.remove(card)
                self.card_count -= 1
                return card

        # 4. 下家有丟過的先丟
        rightAgt = self.gb.rightOpponent(self)
        if rightAgt.name in self.gb.drop_record and len(
                self.gb.drop_record[rightAgt.name]) > 0:
            dc = self.gb.drop_record[rightAgt.name][-1]
            ct = GameBoard.CardType(dc)
            if ct == 1 and dc in self.wang_list:
                self.wang_list.remove(dc)
                self.card_count -= 1
                return dc
            elif ct == 2 and dc in self.tube_list:
                self.tube_list.remove(dc)
                self.card_count -= 1
                return dc
            elif ct == 3 and dc in self.bamb_list:
                self.bamb_list.remove(dc)
                self.card_count -= 1
                return dc
            elif ct == 4 and dc in self.word_list:
                self.word_list.remove(dc)
                self.card_count -= 1
                return dc
            elif ct == 5 and dc in self.wind_list:
                self.wind_list.remove(dc)
                self.card_count -= 1
                return dc

        # 5. 任意丟一張 萬/筒/條
        if (not card) and len(self.tube_list) > 0:
            card = self.tube_list.pop()
            self.card_count -= 1
            return card
        if (not card) and len(self.wang_list) > 0:
            card = self.wang_list.pop()
            self.card_count -= 1
            return card
        if (not card) and len(self.bamb_list) > 0:
            card = self.bamb_list.pop()
            self.card_count -= 1
            return card
Exemplo n.º 2
0
    def pong_or_eat(self, action_flag, ctype, card):
        if (ctype == 1): c_list = self.wang_list
        elif (ctype == 2): c_list = self.tube_list
        elif (ctype == 3): c_list = self.bamb_list
        elif (ctype == 4): c_list = self.word_list
        else: c_list = self.wind_list
        temp_cards = []
        if (action_flag == 1):
            temp_cards.append([card, card])
        else:  # for eat, we have to find all possible eaten cards
            n = GameBoard.NextCard(card)
            p = GameBoard.PrevCard(card)
            if (int(card[0]) == 1):
                n = GameBoard.NextCard(card)
                nn = GameBoard.NextCard(n)
                temp_cards.append([n, nn])
            elif (int(card[0]) == 2):
                p = GameBoard.PrevCard(card)
                n = GameBoard.NextCard(card)
                nn = GameBoard.NextCard(n)
                if ((p in c_list) and (n in c_list)): temp_cards.append([p, n])
                if ((n in c_list) and (nn in c_list)):
                    temp_cards.append([n, nn])
            elif (int(card[0]) == 8):
                p = GameBoard.PrevCard(card)
                n = GameBoard.NextCard(card)
                pp = GameBoard.PrevCard(p)
                if ((p in c_list) and (n in c_list)): temp_cards.append([p, n])
                if ((p in c_list) and (pp in c_list)):
                    temp_cards.append([pp, p])
            elif (int(card[0]) == 9):
                p = GameBoard.PrevCard(card)
                pp = GameBoard.PrevCard(p)
                if ((p in c_list) and (pp in c_list)):
                    temp_cards.append([pp, p])
            else:
                n = GameBoard.NextCard(card)
                nn = GameBoard.NextCard(n)
                p = GameBoard.PrevCard(card)
                pp = GameBoard.PrevCard(p)
                if ((p in c_list) and (n in c_list)): temp_cards.append([p, n])
                if ((pp in c_list) and (p in c_list)):
                    temp_cards.append([pp, p])
                if ((n in c_list) and (nn in c_list)):
                    temp_cards.append([n, nn])
        mini = 99
        useful = 0
        score = 0
        result = None
        for one in temp_cards:
            for c in one:
                self.pong_list.append(c)
                c_list.remove(c)
            self.pong_list.append(card)
            m, u, s = self.count_steps()
            for c in one:
                self.pong_list.remove(c)
                c_list.append(c)
            self.pong_list.remove(card)
            c_list.sort()
            if (m > mini): continue
            if (m == mini) and (u < useful): continue
            if (m == mini) and (u == useful) and (s <= score): continue
            result = one
            mini = m
            useful = u
            score = s
        """
		noe we know, which cards to eat is better
		check: should we eat/pong or not
		return None: do not eat/pong
		"""
        if (mini > self.current_best_state[0]):
            #			print "current_best_state: {0}".format(self.current_best_state)
            #			print "mini: {0}, useful: {1}, score: {2}".format(mini, useful, score)
            return None
        if (mini == self.current_best_state[0]) and (
                useful < self.current_best_state[1]):
            #			print "current_best_state: {0}".format(self.current_best_state)
            #			print "mini: {0}, useful: {1}, score: {2}".format(mini, useful, score)
            return None
        for c in result:
            c_list.remove(c)
            self.pong_list.append(c)
            self.card_count -= 1
        self.pong_list.append(card)
        self.pong_list.sort()
        return self.drop()
Exemplo n.º 3
0
    def find_all_combination(self, ctype, cards, comb_str, combination):
        if len(cards) == 0:
            combination.append(comb_str)
            return combination
        card = cards[0]
        ctype = GameBoard.CardType(card)
        if (ctype == 1) or (ctype == 2) or (ctype == 3):
            count = cards.count(card)
            if count == 3:
                copy = list(cards)
                copy.remove(card)
                copy.remove(card)
                copy.remove(card)
                new = "{0} {0} {0}\t".format(card)
                self.find_all_combination(ctype, copy, comb_str + new,
                                          combination)
            if count == 2:
                copy = list(cards)
                copy.remove(card)
                copy.remove(card)
                new = "{0} {0}\t".format(card)
                self.find_all_combination(ctype, copy, comb_str + new,
                                          combination)
            n = GameBoard.NextCard(card)
            if n != None: nn = GameBoard.NextCard(n)
            else: nn = ""
            if (n in cards) and (nn in cards):
                copy = list(cards)
                copy.remove(card)
                copy.remove(n)
                copy.remove(nn)
                new = "{0} {1} {2}\t".format(card, n, nn)
                self.find_all_combination(ctype, copy, comb_str + new,
                                          combination)
            if n in cards:
                copy = list(cards)
                copy.remove(card)
                copy.remove(n)
                new = "{0} {1}\t".format(card, n)
                self.find_all_combination(ctype, copy, comb_str + new,
                                          combination)
            if nn in cards:
                copy = list(cards)
                copy.remove(card)
                copy.remove(nn)
                new = "{0} {1}\t".format(card, nn)
                self.find_all_combination(ctype, copy, comb_str + new,
                                          combination)
            cards.remove(card)
            new = "{0}\t".format(card)
            self.find_all_combination(ctype, cards, comb_str + new,
                                      combination)

        if (ctype == 4) or (ctype == 5):
            count = cards.count(card)
            if count == 3:
                copy = list(cards)
                copy.remove(card)
                copy.remove(card)
                copy.remove(card)
                new = "{0} {0} {0}\t".format(card)
                self.find_all_combination(ctype, copy, comb_str + new,
                                          combination)
            if count == 2:
                copy = list(cards)
                copy.remove(card)
                copy.remove(card)
                new = "{0} {0}\t".format(card)
                self.find_all_combination(ctype, copy, comb_str + new,
                                          combination)
            cards.remove(card)
            new = "{0}\t".format(card)
            self.find_all_combination(ctype, cards, comb_str + new,
                                      combination)

        return combination
Exemplo n.º 4
0
    def way_to_prewin(self, one):
        """
		kind = [triple, pair, neighbor, single]
		useful: how many cards can we get one more triple
		score: a metric to evaluate how good
			triple = 3, pair/consecutive neighbor = 2, non-consecutive = 1, single = 0
		"""
        kind = [0, 0, 0, 0]
        useful = []
        score = 0
        for part in one.split("\t"):
            #print "part: {0}".format(part)
            tmp = part.split()
            length = len(tmp)
            if (length == 3):  # triple
                kind[0] += 1
                score += 3
            elif (length == 1):  # single
                kind[3] += 1
            elif (tmp[0] == tmp[1]):  # pair
                kind[1] += 1
                useful.append("{0}".format(tmp[0]))
                score += 2
            else:
                kind[2] += 1
                n = GameBoard.NextCard(tmp[0])
                p = GameBoard.PrevCard(tmp[0])
                nn = GameBoard.NextCard(tmp[1])
                if (n == tmp[1]):  # consecutive neighbor
                    score += 2
                    if (p != None): useful.append(p)
                    if (nn != None): useful.append(nn)
                else:
                    useful.append(n)
                    score += 1

        #print "kind: {0}".format(kind)
        """ how many cards can we probably get """
        useful_amount = 0
        for card in set(useful):
            ctype = GameBoard.CardType(card)
            if (ctype == 1): a = self.wang_list.count(card)
            elif (ctype == 2): a = self.tube_list.count(card)
            elif (ctype == 3): a = self.bamb_list.count(card)
            elif (ctype == 4): a = self.word_list.count(card)
            else: a = self.wind_list.count(card)
            b = self.gb.drop_list.count(card)
            useful_amount += (4 - a - b)
        """
		1. enumerate, because goal state not too much
		2. counting pong_list so that we can focus on 16 cards
		3. check prewin first	
		"""
        goals = [[4, 1, 1, 0], [5, 0, 0, 1], [4, 2, 0, 0]]
        gpattern = [["***", "***", "***", "***", "##", "$$"],
                    ["***", "***", "***", "***", "***", "/"],
                    ["***", "***", "***", "***", "##", "##"]]
        result = [0, 0, 0]
        size = len(self.pong_list) / 3
        if ((size + kind[0]) > 4): return [0, useful_amount, score]
        for i in range(size):
            gpattern[0].remove("***")
            gpattern[1].remove("***")
            gpattern[2].remove("***")
        for number in range(3):
            k0 = kind[0]
            k1 = kind[1]
            k2 = kind[2]
            k3 = kind[3]
            p1 = gpattern[number]
            for i in range(k0):
                p1.remove("***")
            for i in range(min(k1, goals[number][1])):
                k1 -= 1
                p1.remove("##")
            for i in range(min(k2, goals[number][2])):
                k2 -= 1
                p1.remove("$$")
            #print "p1: {0}, size: {1}".format(p1, (k1+k2)*2+k3)
            step = 0
            two = k1 + k2
            for i in range(len(p1)):
                length = len(p1[i])
                if (length == 3):
                    if two:
                        two -= 1
                        step += 1
                    else:
                        step += 2
                elif (length == 2):
                    step += 1
            result[number] = step
        #print "steps to goal: {0}, useful: {1}".format(result, len(useful))

        return [min(result), useful_amount, score]
Exemplo n.º 5
0
    def drop(self):
        card = ''
        # 1.
        if len(self.word_list) == 1:
            card = self.word_list.pop()
            return card
        else:
            for c in set(self.word_list):
                if self.word_list.count(c) == 1:
                    self.word_list.remove(c)
                    self.card_count -= 1
                    return c
        if len(self.wind_list) == 1:
            card = self.wind_list.pop()
            return card
        else:
            for c in set(self.wind_list):
                if self.wind_list.count(c) == 1:
                    self.wind_list.remove(c)
                    self.card_count -= 1
                    return c
        # 2
        if (not card) and len(self.tube_list) > 0:
            for c in set(self.tube_list):
                #number = int(card[:1])
                if self.tube_list.count(c) > 1:
                    continue
                elif GameBoard.PrevCard(
                        c) in self.tube_list or GameBoard.NextCard(
                            c) in self.tube_list:
                    continue
                else:
                    self.tube_list.remove(c)
                    return c
            if (not card) and '1筒' in self.tube_list:
                card = '1筒'
                self.tube_list.remove('1筒')
                return card
            elif (not card) and '9筒' in self.tube_list:
                card = '9筒'
                self.tube_list.remove('9筒')
                self.card_count -= 1
                return card

        if (not card) and len(self.wang_list) > 0:
            for c in set(self.wang_list):
                if self.wang_list.count(c) > 1:
                    continue
                elif GameBoard.PrevCard(
                        c) in self.wang_list or GameBoard.NextCard(
                            c) in self.wang_list:
                    continue
                else:
                    self.wang_list.remove(c)
                    self.card_count -= 1
                    return c
            if (not card) and '1萬' in self.wang_list:
                card = '1萬'
                self.wang_list.remove('1萬')
                return card
            elif (not card) and '9萬' in self.wang_list:
                card = '9萬'
                self.wang_list.remove('9萬')
                return card

        if (not card) and len(self.bamb_list) > 0:
            for c in set(self.bamb_list):
                if self.bamb_list.count(c) > 1:
                    continue
                elif GameBoard.PrevCard(
                        c) in self.bamb_list or GameBoard.NextCard(
                            c) in self.bamb_list:
                    continue
                else:
                    self.bamb_list.remove(c)
                    self.card_count -= 1
                    return c
            if (not card) and '1條' in self.bamb_list:
                card = '1條'
                self.bamb_list.remove(card)
                self.card_count -= 1
                return card
            elif (not card) and '9條' in self.bamb_list:
                card = '9條'
                self.bamb_list.remove(card)
                self.card_count -= 1
                return card

        # 任意丟一張 萬/筒/條
        if (not card) and len(self.tube_list) > 0:
            card = self.tube_list.pop()
        if (not card) and len(self.wang_list) > 0:
            card = self.wang_list.pop()
        if (not card) and len(self.bamb_list) > 0:
            card = self.bamb_list.pop()
        self.card_count -= 1
        return card