Exemple #1
0
    def __init__(self, game, name):
        """
        Initialize a player for a give game.

        @type game: L{Game} or None.
        @param game: The game this player is part of. May be None.
        """
        if game:
            self._game = weakref.ref(game)
        else:
            self._game = None
        self.__balance = 0
        self.__payment = 0
        self.wonCount = 0
        self.__name = ''
        Players.createIfUnknown(name)
        self.name = name
        self.wind = East
        self.intelligence = AIDefault(self)
        self.visibleTiles = IntDict(game.visibleTiles) if game else IntDict()
        self.handCache = {}
        self.cacheHits = 0
        self.cacheMisses = 0
        self.__lastSource = TileSource.East14th
        self.clearHand()
        self.handBoard = None
Exemple #2
0
 def __init__(self, game):
     if game:
         self._game = weakref.ref(game)
     else:
         self._game = None
     self.__balance = 0
     self.__payment = 0
     self.wonCount = 0
     self.name = ''
     self.wind = WINDS[0]
     self.visibleTiles = IntDict(game.visibleTiles) if game else IntDict()
     self.clearHand()
     self.__lastSource = '1' # no source: blessing from heaven or earth
     self.voice = None
     self.handBoard = None
Exemple #3
0
 def claimness(hand, discard):
     result = IntDict()
     if AllPairHonors.shouldTry(hand):
         result[Message.Pung] = -999
         result[Message.Kong] = -999
         result[Message.Chow] = -999
     return result
Exemple #4
0
 def claimness(cls, hand, discard):
     result = IntDict()
     if cls.shouldTry(hand):
         result[Message.Pung] = -999
         result[Message.Kong] = -999
         result[Message.Chow] = -999
     return result
Exemple #5
0
 def cleanPlayerTable(self):
     """remove now unneeded columns host, password and make names unique"""
     playerCounts = IntDict()
     names = {}
     keep = {}
     for nameId, name in Query('select id,name from player').records:
         playerCounts[name] += 1
         names[int(nameId)] = name
     for name, counter in defaultdict.items(playerCounts):
         nameIds = [x[0] for x in names.items() if x[1] == name]
         keepId = nameIds[0]
         keep[keepId] = name
         if counter > 1:
             for nameId in nameIds[1:]:
                 Query(
                     'update score set player=%d where player=%d' %
                     (keepId, nameId))
                 Query(
                     'update game set p0=%d where p0=%d' %
                     (keepId, nameId))
                 Query(
                     'update game set p1=%d where p1=%d' %
                     (keepId, nameId))
                 Query(
                     'update game set p2=%d where p2=%d' %
                     (keepId, nameId))
                 Query(
                     'update game set p3=%d where p3=%d' %
                     (keepId, nameId))
                 Query('delete from player where id=%d' % nameId)
     Query('drop table player')
     self.createTable('player')
     for nameId, name in keep.items():
         Query('insert into player(id,name) values(?,?)', (nameId, name))
Exemple #6
0
 def __init__(self):
     self.occurrence = IntDict()  # key: db, s3 etc. value: occurrence
     self.winds = {Tile(Tile.wind, x) for x in Tile.winds}
     self.wINDS = {x.concealed for x in self.winds}
     self.dragons = {Tile(Tile.dragon, x) for x in Tile.dragons}
     self.dRAGONS = {x.concealed for x in self.dragons}
     self.honors = self.winds | self.dragons
     self.hONORS = self.wINDS | self.dRAGONS
     self.terminals = {
         Tile(x, y)
         for x in Tile.colors for y in Tile.terminals
     }
     self.tERMINALS = {x.concealed for x in self.terminals}
     self.majors = self.honors | self.terminals
     self.mAJORS = self.hONORS | self.tERMINALS
     self.greenHandTiles = {Tile(Tile.bamboo, x)
                            for x in '23468'
                            } | {Tile(Tile.dragon, Tile.green)}
     self.minors = {Tile(x, y) for x in Tile.colors for y in Tile.minors}
     for tile in self.majors:
         self.occurrence[tile] = 4
     for tile in self.minors:
         self.occurrence[tile] = 4
     for bonus in Tile.boni:
         for _ in Tile.winds:
             self.occurrence[Tile(bonus, _)] = 1
Exemple #7
0
 def claimness(self, hand, dummyDiscard):
     result = IntDict()
     if self.shouldTry(hand):
         result[Message.Pung] = -999
         result[Message.Kong] = -999
         result[Message.Chow] = -999
     return result
Exemple #8
0
 def __init__(self, game, hand):
     list.__init__(self)
     self.game = game
     self.hand = hand
     self.hiddenTiles = list(x.lower() for x in hand.tileNamesInHand)
     self.groupCounts = IntDict(
     )  # counts for tile groups (sbcdw), exposed and concealed
     for tile in self.hiddenTiles:
         self.groupCounts[tile[0]] += 1
     self.declaredGroupCounts = IntDict()
     for tile in sum((x.pairs.lower() for x in hand.declaredMelds), []):
         self.groupCounts[tile[0]] += 1
         self.declaredGroupCounts[tile[0]] += 1
     self.extend(
         list(
             TileAI(self, x)
             for x in sorted(set(self.hiddenTiles), key=elementKey)))
     self.link()
Exemple #9
0
 def claimness(cls, hand, discard):
     result = IntDict()
     if cls.shouldTry(hand):
         doublesCount = hand.doublesEstimate(discard)
         # TODO: compute scoring for resulting hand. If it is high anyway,
         # prefer pung over trying 13 orphans
         if doublesCount < 2 or cls.shouldTry(hand, 1):
             result[Message.Pung] = -999
             result[Message.Kong] = -999
             result[Message.Chow] = -999
     return result
Exemple #10
0
 def __init__(self, player, hand):
     list.__init__(self)
     self._player = weakref.ref(player)
     self._hand = weakref.ref(hand)
     if Debug.robotAI:
         player.game.debug('DiscardCandidates for hand %s are %s' %
                           (hand, hand.tilesInHand))
     self.hiddenTiles = list(x.exposed for x in hand.tilesInHand)
     self.groupCounts = IntDict()
     # counts for tile groups (sbcdw), exposed
     # and concealed
     for tile in self.hiddenTiles:
         self.groupCounts[tile.group] += 1
     self.declaredGroupCounts = IntDict()
     for tile in sum((x for x in hand.declaredMelds), []):
         self.groupCounts[tile.lowerGroup] += 1
         self.declaredGroupCounts[tile.lowerGroup] += 1
     self.extend(
         list(TileAI(self, x) for x in sorted(set(self.hiddenTiles))))
     self.link()
Exemple #11
0
 def claimness(hand, discard):
     result = IntDict()
     player = hand.player
     if player.originalCall and player.mayWin:
         if player.originalCallingHand.chancesToWin():
             # winning with OriginalCall is still possible
             result[Message.Pung] = -999
             result[Message.Kong] = -999
             result[Message.Chow] = -999
         else:
             player.mayWin = False  # bad luck
     return result
Exemple #12
0
 def claimness(hand, discard):
     result = IntDict()
     if ThirteenOrphans.shouldTry(hand):
         doublesCount = hand.doublesEstimate()
         if hand.tileNames.count(discard) == 2:
             # TODO: compute scoring for resulting hand. If it is high anyway,
             # prefer pung over trying 13 orphans
             for rule in hand.ruleset.doublingMeldRules:
                 if rule.appliesToMeld(hand, Meld(discard.lower() * 3)):
                     doublesCount += 1
         if doublesCount < 2 or ThirteenOrphans.shouldTry(hand,
                                                          maxMissing=1):
             result[Message.Pung] = -999
             result[Message.Kong] = -999
             result[Message.Chow] = -999
     return result
Exemple #13
0
 def selectAnswer(self, answers):
     """this is where the robot AI should go.
     Returns answer and one parameter"""
     # pylint: disable=R0912
     # disable warning about too many branches
     answer = parameter = None
     tryAnswers = (x for x in [
         Message.MahJongg, Message.OriginalCall, Message.Kong, Message.Pung,
         Message.Chow, Message.Discard
     ] if x in answers)
     hand = self.client.game.myself.hand
     claimness = IntDict()
     discard = self.client.game.lastDiscard
     if discard:
         for func in self.client.game.ruleset.filterFunctions('claimness'):
             claimness += func.claimness(hand, discard.element)
     for tryAnswer in tryAnswers:
         parameter = self.client.sayable[tryAnswer]
         if not parameter:
             continue
         if claimness[tryAnswer] < 0:
             if Debug.robotAI:
                 hand.debug('claimness %d inhibits %s %s' %
                            (claimness[tryAnswer], tryAnswer, parameter))
             continue
         if tryAnswer in [Message.Discard, Message.OriginalCall]:
             parameter = self.selectDiscard(hand)
         elif tryAnswer in [Message.Pung, Message.Chow, Message.Kong
                            ] and self.respectOriginalCall():
             continue
         elif tryAnswer == Message.Pung and self.client.maybeDangerous(
                 tryAnswer):
             continue
         elif tryAnswer == Message.Chow:
             parameter = self.selectChow(parameter)
         elif tryAnswer == Message.Kong:
             parameter = self.selectKong(parameter)
         if parameter:
             answer = tryAnswer
             break
     if not answer:
         answer = answers[0]  # for now always return default answer
     return answer, parameter
Exemple #14
0
 def selectAnswer(self, answers):
     """this is where the robot AI should go.
     Returns answer and one parameter"""
     # pylint: disable=too-many-branches
     # disable warning about too many branches
     answer = parameter = None
     tryAnswers = (x for x in [
         Message.MahJongg, Message.OriginalCall, Message.Kong, Message.Pung,
         Message.Chow, Message.Discard
     ] if x in answers)
     hand = self.player.hand
     claimness = IntDict()
     discard = self.player.game.lastDiscard
     if discard:
         for rule in self.player.game.ruleset.filterRules('claimness'):
             claimness += rule.claimness(hand, discard)
             if Debug.robotAI:
                 hand.debug('%s: claimness in selectAnswer:%s' %
                            (rule.name, claimness))
     for tryAnswer in tryAnswers:
         parameter = self.player.sayable[tryAnswer]
         if not parameter:
             continue
         if claimness[tryAnswer] < 0:
             continue
         if tryAnswer in [Message.Discard, Message.OriginalCall]:
             parameter = self.selectDiscard(hand)
         elif tryAnswer == Message.Pung and self.player.maybeDangerous(
                 tryAnswer):
             continue
         elif tryAnswer == Message.Chow:
             parameter = self.selectChow(parameter)
         elif tryAnswer == Message.Kong:
             parameter = self.selectKong(parameter)
         if parameter:
             answer = tryAnswer
             break
     if not answer:
         answer = answers[0]  # for now always return default answer
     return answer, parameter
Exemple #15
0
    def __init__(self,
                 names,
                 ruleset,
                 gameid=None,
                 wantedGame=None,
                 client=None):
        """a new game instance. May be shown on a field, comes from database
        if gameid is set.

        Game.lastDiscard is the tile last discarded by any player. It is
        reset to None when a player gets a tile from the living end of the
        wall or after he claimed a discard.
        """
        # pylint: disable=too-many-statements
        assert self.__class__ != Game, 'Do not directly instantiate Game'
        for wind, name in names:
            assert isinstance(wind, Wind), 'Game.__init__ expects Wind objects'
            assert isinstance(
                name,
                str), 'Game.__init__: name must be string and not {}'.format(
                    type(name))
        self.players = Players()
        # if we fail later on in init, at least we can still close the program
        self.myself = None
        # the player using this client instance for talking to the server
        self.__shouldSave = False
        self._client = None
        self.client = client
        self.rotated = 0
        self.notRotated = 0  # counts hands since last rotation
        self.ruleset = None
        self.roundsFinished = 0
        self._currentHandId = None
        self._prevHandId = None
        self.wantedGame = wantedGame
        self.moves = []
        self.gameid = gameid
        self.playOpen = False
        self.autoPlay = False
        self.handctr = 0
        self.roundHandCount = 0
        self.handDiscardCount = 0
        self.divideAt = None
        self.__lastDiscard = None  # always uppercase
        self.visibleTiles = IntDict()
        self.discardedTiles = IntDict(self.visibleTiles)
        # tile names are always lowercase
        self.dangerousTiles = list()
        self.csvTags = []
        self.randomGenerator = CountingRandom(self)
        self._setHandSeed()
        self.activePlayer = None
        self.__winner = None
        self._setGameId()
        self.__useRuleset(ruleset)
        # shift rules taken from the OEMC 2005 rules
        # 2nd round: S and W shift, E and N shift
        self.shiftRules = 'SWEN,SE,WE'
        self.wall = self.wallClass(self)
        self.assignPlayers(names)
        if self.belongsToGameServer():
            self.__shufflePlayers()
        self._scanGameOption()
        for player in self.players:
            player.clearHand()