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
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
def claimness(hand, discard): result = IntDict() if AllPairHonors.shouldTry(hand): result[Message.Pung] = -999 result[Message.Kong] = -999 result[Message.Chow] = -999 return result
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
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))
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
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
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()
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
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()
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
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
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
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
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()