Exemplo n.º 1
0
 def declaredMahJongg(self, concealed, withDiscard, lastTile, lastMeld):
     """player declared mah jongg. Determine last meld, show concealed tiles grouped to melds"""
     assert not isinstance(lastTile, Tile)
     lastMeld = Meld(lastMeld) # do not change the original!
     self.game.winner = self
     if withDiscard:
         self.lastTile = withDiscard
         self.lastMeld = lastMeld
         assert withDiscard == self.game.lastDiscard.element, 'withDiscard: %s lastDiscard: %s' % (
             withDiscard, self.game.lastDiscard.element)
         self.addConcealedTiles(self.game.lastDiscard)
         melds = [Meld(x) for x in concealed.split()]
         if self.lastSource != 'k':   # robbed the kong
             self.lastSource = 'd'
         # the last claimed meld is exposed
         assert lastMeld in melds, '%s: concealed=%s melds=%s lastMeld=%s lastTile=%s withDiscard=%s' % (
                 self.__concealedTileNames, concealed,
                 meldsContent(melds), ''.join(lastMeld.pairs), lastTile, withDiscard)
         melds.remove(lastMeld)
         self.lastTile = self.lastTile.lower()
         lastMeld.pairs.toLower()
         self._exposedMelds.append(lastMeld)
         for tileName in lastMeld.pairs:
             self.visibleTiles[tileName] += 1
     else:
         melds = [Meld(x) for x in concealed.split()]
         self.lastTile = lastTile
         self.lastMeld = lastMeld
     self._concealedMelds = melds
     self.__concealedTileNames = []
     self.__hand = None
     self.syncHandBoard()
Exemplo n.º 2
0
 def receive(self, tile=None, meld=None):
     """receive a tile or meld and return the meld this tile becomes part of"""
     if tile:
         if tile.isBonus():
             if tile.board == self:
                 return
             meld = Meld(tile)
         else:
             meld = self.__chooseDestinationMeld(tile, meld) # from selector board.
             # if the source is a Handboard, we got a Meld, not a Tile
             if not meld:
                 # user pressed ESCAPE
                 return None
         assert not tile.element.istitle() or meld.pairs[0] != 'Xy', tile
     senderBoard = meld[0].board
     senderBoard.removing(meld=meld)
     if senderBoard == self:
         self.player.moveMeld(meld)
         self.sync()
     else:
         self.player.addMeld(meld)
         self.sync(adding=meld.tiles)
         senderBoard.remove(meld=meld)
     meld.tiles = sorted(meld.tiles, key=lambda x: x.xoffset)
     if any(x.focusable for x in meld.tiles):
         for idx, tile in enumerate(meld.tiles):
             tile.focusable = idx == 0
     return meld
Exemplo n.º 3
0
 def newTilePositions(self):
     """returns list(TileAttr) for all tiles except bonus tiles.
     The tiles are not associated to any board."""
     result = list()
     isScoringGame = self.player.game.isScoringGame()
     newUpperMelds = list(self.player.exposedMelds)
     if isScoringGame:
         newLowerMelds = list(self.player.concealedMelds)
     else:
         if self.player.concealedMelds:
             newLowerMelds = sorted(self.player.concealedMelds, key=meldKey)
         else:
             tileStr = 'R' + ''.join(self.player.concealedTileNames)
             handStr = ' '.join([tileStr, self.player.mjString()])
             content = Hand.cached(self.player, handStr)
             newLowerMelds = list(Meld(x) for x in content.sortedMeldsContent.split())
             if newLowerMelds:
                 if self.rearrangeMelds:
                     if newLowerMelds[0].pairs[0] == 'Xy':
                         newLowerMelds = sorted(newLowerMelds, key=len, reverse=True)
                 else:
                     # generate one meld with all sorted tiles
                     newLowerMelds = [Meld(sorted(sum((x.pairs for x in newLowerMelds), []), key=elementKey))]
     for yPos, melds in ((0, newUpperMelds), (self.lowerY, newLowerMelds)):
         meldDistance = self.concealedMeldDistance if yPos else self.exposedMeldDistance
         meldX = 0
         for meld in melds:
             for idx in range(len(meld)):
                 result.append(TileAttr(self, meld, idx, meldX, yPos))
                 meldX += 1
             meldX += meldDistance
     return sorted(result, key=lambda x: x.yoffset * 100 + x.xoffset)
Exemplo n.º 4
0
 def computeLastMeld(self):
     """compile hand info into a string as needed by the scoring engine"""
     if self.scoringDialog:
         cbLastMeld = self.scoringDialog.cbLastMeld
         idx = cbLastMeld.currentIndex()
         if idx >= 0:
             return Meld(str(cbLastMeld.itemData(idx).toString()))
     return Meld()
Exemplo n.º 5
0
    def __parseString(self, inString):
        """parse the string passed to Hand()"""
        # pylint: disable=too-many-branches
        tileStrings = []
        for part in inString.split():
            partId = part[0]
            if partId == 'm':
                if len(part) > 1:
                    try:
                        self.__lastSource = TileSource.byChar[part[1]]
                    except KeyError:
                        raise Exception('{} has unknown lastTile {}'.format(inString, part[1]))
                    if len(part) > 2:
                        self.__announcements = set(part[2])
            elif partId == 'L':
                if len(part[1:]) > 8:
                    raise Exception(
                        'last tile cannot complete a kang:' + inString)
                if len(part) > 3:
                    self.__lastMeld = Meld(part[3:])
                self.__lastTile = Tile(part[1:3])
            else:
                if part != 'R':
                    tileStrings.append(part)
        self.bonusMelds, tileStrings = self.__separateBonusMelds(tileStrings)
        tileString = ' '.join(tileStrings)
        self.tiles = TileList(tileString.replace(' ', '').replace('R', ''))
        self.tiles.sort()
        for part in tileStrings[:]:
            if part[:1] != 'R':
                self.melds.append(Meld(part))
                tileStrings.remove(part)

        self.values = tuple(x.value for x in self.tiles)
        self.suits = set(x.lowerGroup for x in self.tiles)
        self.declaredMelds = MeldList(x for x in self.melds if x.isDeclared)
        declaredTiles = list(sum((x for x in self.declaredMelds), []))
        self.tilesInHand = TileList(x for x in self.tiles
                                    if x not in declaredTiles)
        self.lenOffset = (len(self.tiles) - 13
                          - sum(x.isKong for x in self.melds))

        assert len(tileStrings) < 2, tileStrings
        self.__rest = TileList()
        if len(tileStrings):
            self.__rest.extend(TileList(tileStrings[0][1:]))

        last = self.__lastTile
        if last and not last.isBonus:
            assert last in self.tiles, \
                'lastTile %s is not in hand %s' % (last, str(self))
            if self.__lastSource is TileSource.RobbedKong:
                assert self.tiles.count(last.exposed) + \
                    self.tiles.count(last.concealed) == 1, (
                        'Robbing kong: I cannot have '
                        'lastTile %s more than once in %s' % (
                            last, ' '.join(self.tiles)))
Exemplo n.º 6
0
 def computeLastMeld(self):
     """compile hand info into a string as needed by the scoring engine"""
     if self.scoringDialog:
         # is None while ScoringGame is created
         cbLastMeld = self.scoringDialog.cbLastMeld
         idx = cbLastMeld.currentIndex()
         if idx >= 0:
             return Meld(cbLastMeld.itemData(idx))
     return Meld()
Exemplo n.º 7
0
 def rearrange(dummyHand, pairs):
     result = []
     for tileName in pairs[:]:
         if pairs.count(tileName) >= 2:
             result.append(Meld([tileName, tileName]))
             pairs.remove(tileName)
             pairs.remove(tileName)
         elif pairs.count(tileName) == 1:
             result.append(Meld([tileName]))
             pairs.remove(tileName)
     return result, pairs
Exemplo n.º 8
0
 def claimTile(self, player, claim, meldTiles, nextMessage):
     """a player claims a tile for pung, kong or chow.
     meldTiles contains the claimed tile, concealed"""
     if not self.running:
         return
     lastDiscard = self.game.lastDiscard
     # if we rob a tile, self.game.lastDiscard has already been set to the
     # robbed tile
     hasTiles = Meld(meldTiles[:])
     discardingPlayer = self.game.activePlayer
     hasTiles = hasTiles.without(lastDiscard)
     meld = Meld(meldTiles)
     if len(meld) != 4 and not (meld.isPair or meld.isPungKong
                                or meld.isChow):
         msg = i18nE('%1 wrongly said %2 for meld %3')
         self.abort(msg, player.name, claim.name, str(meld))
         return
     if not player.hasConcealedTiles(hasTiles):
         msg = i18nE(
             '%1 wrongly said %2: claims to have concealed tiles %3 but only has %4'
         )
         self.abort(msg, player.name, claim.name, ' '.join(hasTiles),
                    ''.join(player.concealedTiles))
         return
     # update our internal state before we listen to the clients again
     self.game.discardedTiles[lastDiscard.exposed] -= 1
     self.game.activePlayer = player
     if lastDiscard:
         player.lastTile = lastDiscard.exposed
         player.lastSource = TileSource.LivingWallDiscard
     player.exposeMeld(hasTiles, lastDiscard)
     self.game.lastDiscard = None
     block = DeferredBlock(self)
     if (nextMessage != Message.Kong
             and self.game.dangerousFor(discardingPlayer, lastDiscard)
             and discardingPlayer.playedDangerous):
         player.usedDangerousFrom = discardingPlayer
         if Debug.dangerousGame:
             logDebug('%s claims dangerous tile %s discarded by %s' %
                      (player, lastDiscard, discardingPlayer))
         block.tellAll(player,
                       Message.UsedDangerousFrom,
                       source=discardingPlayer.name)
     block.tellAll(player, nextMessage, meld=meld)
     if claim == Message.Kong:
         block.callback(self.pickKongReplacement)
     else:
         block.callback(self.moved)
Exemplo n.º 9
0
 def clientAction(self, client, move):
     """mirror the action locally"""
     prevMove = client.game.lastMoves(only=[Message.DeclaredKong]).next()
     prevKong = Meld(prevMove.source)
     prevMove.player.robTile(prevKong.pairs[0].capitalize())
     move.player.lastSource = 'k'
     client.game.addCsvTag('robbedKong', forAllPlayers=True)
Exemplo n.º 10
0
 def splitRegex(self, rest):
     """split rest into melds as good as possible"""
     rest = ''.join(rest)
     melds = []
     for rule in self.ruleset.splitRules:
         splits = rule.apply(rest)
         while len(splits) > 1:
             for split in splits[:-1]:
                 melds.append(Meld(split))
             rest = splits[-1]
             splits = rule.apply(rest)
         if len(splits) == 0:
             break
     if len(splits) == 1:
         assert Meld(splits[0]).isValid()  # or the splitRules are wrong
     return melds
Exemplo n.º 11
0
 def toolTip(self, button, dummyTile):
     """decorate the action button which will send this message"""
     maySay = button.client.sayable[self]
     if not maySay:
         return '', False, ''
     myself = button.client.game.myself
     txt = []
     warn = False
     if myself.originalCall and myself.mayWin:
         warn = True
         txt.append(m18n('saying %1 violates Original Call',
             self.i18nName))
     dangerousMelds = button.client.maybeDangerous(self)
     if dangerousMelds:
         lastDiscardName = Meld.tileName(button.client.game.lastDiscard.element)
         warn = True
         if Debug.dangerousGame and len(dangerousMelds) != len(maySay):
             button.client.game.debug('only some claimable melds are dangerous: %s' % dangerousMelds)
         if len(dangerousMelds) == 1:
             txt.append(m18n(
                'claiming %1 is dangerous because you will have to discard a dangerous tile',
                lastDiscardName))
         else:
             for meld in dangerousMelds:
                 txt.append(m18n(
                'claiming %1 for %2 is dangerous because you will have to discard a dangerous tile',
                lastDiscardName, str(meld)))
     if not txt:
         txt = [m18n('You may say %1', self.i18nName)]
     return '<br><br>'.join(txt), warn, ''
Exemplo n.º 12
0
 def toolTip(self, button, dummyTile):
     """decorate the action button which will send this message"""
     maySay = button.client.sayable[self]
     if not maySay:
         return '', False, ''
     myself = button.client.game.myself
     txt = []
     warn = False
     if myself.originalCall and myself.mayWin:
         warn = True
         txt.append(m18n('saying Kong for %1 violates Original Call',
             Meld.tileName(maySay[0])))
     if not txt:
         txt = [m18n('You may say Kong for %1',
             Meld.tileName(maySay[0][0]))]
     return '<br><br>'.join(txt), warn, ''
Exemplo n.º 13
0
 def __setLastTile(self):
     """sets lastTile, lastSource, announcements"""
     self.__announcements = ''
     self.__lastTile = None
     self.__lastSource = None
     parts = self.mjStr.split()
     for part in parts:
         if part[0] == 'L':
             part = part[1:]
             if len(part) > 2:
                 self.__lastMeld = Meld(part[2:])
             self.__lastTile = part[:2]
         elif part[0] == 'M':
             if len(part) > 3:
                 self.__lastSource = part[3]
                 if len(part) > 4:
                     self.__announcements = part[4:]
     if self.__lastTile:
         assert self.__lastTile in self.tileNames, 'lastTile %s is not in tiles %s, mjStr=%s' % (
             self.__lastTile, ' '.join(self.tileNames), self.mjStr)
         if self.__lastSource == 'k':
             assert self.tileNames.count(self.__lastTile.lower()) + \
                 self.tileNames.count(self.__lastTile.capitalize()) == 1, \
                 'Robbing kong: I cannot have lastTile %s more than once in %s' % (
                 self.__lastTile, ' '.join(self.tileNames))
Exemplo n.º 14
0
 def __init__(self, player, command, kwargs):
     if isinstance(command, Message):
         self.message = command
     else:
         self.message = Message.defined[command]
     self.table = None
     self.notifying = False
     self._player = weakref.ref(player) if player else None
     self.token = kwargs['token']
     self.kwargs = kwargs.copy()
     del self.kwargs['token']
     self.score = None
     self.lastMeld = None
     for key, value in kwargs.items():
         assert not isinstance(value, bytes), 'value is bytes:{}'.format(
             repr(value))
         if value is None:
             self.__setattr__(key, None)
         else:
             if key.lower().endswith('tile'):
                 self.__setattr__(key, Tile(value))
             elif key.lower().endswith('tiles'):
                 self.__setattr__(key, TileList(value))
             elif key.lower().endswith('meld'):
                 self.__setattr__(key, Meld(value))
             elif key.lower().endswith('melds'):
                 self.__setattr__(key, MeldList(value))
             elif key == 'playerNames':
                 if Internal.isServer:
                     self.__setattr__(key, value)
                 else:
                     self.__setattr__(key, self.__convertWinds(value))
             else:
                 self.__setattr__(key, value)
Exemplo n.º 15
0
 def computeLastMelds(cls, hand):
     """returns all possible last melds"""
     if not hand.lastTile:
         return []
     couples, rest = cls.findCouples(hand)
     assert not rest, '%s: couples=%s rest=%s' % (hand.string, couples,
                                                  rest)
     return [Meld(x) for x in couples if hand.lastTile in x]
Exemplo n.º 16
0
 def computeLastMelds(self, hand):
     """returns all possible last melds"""
     if not hand.lastTile:
         return
     triples, rest = self.findTriples(hand)
     assert len(rest) == 2
     triples.append(rest)  # just a list of tuples
     return [Meld(x) for x in triples if hand.lastTile in x]
Exemplo n.º 17
0
 def rearrange(self, hand, pairs):
     melds = []
     for triple in self.findTriples(hand)[0]:
         melds.append(Meld(triple))
         pairs.remove(triple[0])
         pairs.remove(triple[1])
         pairs.remove(triple[2])
     while len(pairs) >= 2:
         for value in set(x[1] for x in pairs):
             suits = set(x[0] for x in pairs if x[1] == value)
             if len(suits) < 2:
                 return melds, pairs
             pair = (suits.pop() + value, suits.pop() + value)
             melds.append(Meld(sorted(pair, key=elementKey)))
             pairs.remove(pair[0])
             pairs.remove(pair[1])
     return melds, pairs
Exemplo n.º 18
0
 def rearrange(dummyHand, pairs):
     melds = []
     for pair in set(pairs) & elements.mAJORS:
         while pairs.count(pair) >= 2:
             melds.append(Meld(pair * 2))
             pairs.remove(pair)
             pairs.remove(pair)
     return melds, pairs
Exemplo n.º 19
0
 def computeLastMelds(cls, hand):
     """returns all possible last melds"""
     if not hand.lastTile:
         return
     triples, rest = cls.findTriples(hand)
     assert len(rest) == 2
     triples = list(triples)
     triples.append(rest)
     return [Meld(x) for x in triples if hand.lastTile in x]
Exemplo n.º 20
0
 def __separateBonusMelds(tileString):
     """keep them separate. One meld per bonus tile. Others depend on that."""
     result = []
     if 'f' in tileString or 'y' in tileString:
         for pair in Pairs(tileString.replace(' ', '').replace('R', '')):
             if pair[0] in 'fy':
                 result.append(Meld(pair))
                 tileString = tileString.replace(pair, '', 1)
     return result, tileString
Exemplo n.º 21
0
 def toolTip(self, button, tile):
     """decorate the action button which will send this message"""
     game = button.client.game
     myself = game.myself
     txt = []
     warn = False
     if myself.violatesOriginalCall(tile):
         txt.append(m18n('discarding %1 violates Original Call',
             Meld.tileName(tile.element)))
         warn = True
     if game.dangerousFor(myself, tile):
         txt.append(m18n('discarding %1 is Dangerous Game',
             Meld.tileName(tile.element)))
         warn = True
     if not txt:
         txt = [m18n('discard the least useful tile')]
     txt = '<br><br>'.join(txt)
     return txt, warn, txt
Exemplo n.º 22
0
 def rearrange(self, hand, pairs):
     melds = []
     for couple in self.findCouples(hand)[0]:
         if couple[0].islower():
             # this is the mj pair, lower after claiming
             continue
         melds.append(Meld(couple))
         pairs.remove(couple[0])
         pairs.remove(couple[1])
     return melds, pairs
Exemplo n.º 23
0
 def __computeDragonWindMelds(tileString):
     """returns lists with melds containing all (even single)
     dragons respective winds"""
     dragonMelds = []
     windMelds = []
     for split in tileString.split():
         if split[0] == 'R':
             pairs = Pairs(split[1:])
             for lst, tiles in ((windMelds, elements.wINDS),
                                (dragonMelds, elements.dRAGONS)):
                 for tile in tiles:
                     count = pairs.count(tile)
                     if count:
                         lst.append(Meld([tile] * count))
         elif split[0] in 'dD':
             dragonMelds.append(Meld(split))
         elif split[0] in 'wW':
             windMelds.append(Meld(split))
     return dragonMelds, windMelds
Exemplo n.º 24
0
 def __computeLenOffset(self, tileString):
     """lenOffset is <0 for short hand, 0 for correct calling hand, >0 for long hand.
     Of course ignoring bonus tiles.
     if there are no kongs, 13 tiles will return 0"""
     result = len(self.tileNames) - 13
     for split in tileString.split():
         if split[0] != 'R':
             if Meld(split).isKong():
                 result -= 1
     return result
Exemplo n.º 25
0
 def rearrange(cls, hand, rest):
     melds = []
     for couple in cls.findCouples(hand, rest)[0]:
         if couple[0].islower():
             # this is the mj pair, lower after claiming
             continue
         melds.append(Meld(couple))
         rest.remove(couple[0])
         rest.remove(couple[1])
     yield tuple(melds), tuple(rest)
Exemplo n.º 26
0
 def exposeMeld(self, meldTiles, calledTile=None):
     """exposes a meld with meldTiles: removes them from concealedTileNames,
     adds the meld to exposedMelds and returns it
     calledTile: we got the last tile for the meld from discarded, otherwise
     from the wall"""
     game = self.game
     game.activePlayer = self
     allMeldTiles = meldTiles[:]
     if calledTile:
         allMeldTiles.append(calledTile.element if isinstance(calledTile, Tile) else calledTile)
     if len(allMeldTiles) == 4 and allMeldTiles[0].islower():
         tile0 = allMeldTiles[0].lower()
         # we are adding a 4th tile to an exposed pung
         self._exposedMelds = [meld for meld in self._exposedMelds if meld.pairs != [tile0] * 3]
         meld = Meld(tile0 * 4)
         self.__concealedTileNames.remove(allMeldTiles[3])
         self.visibleTiles[tile0] += 1
     else:
         allMeldTiles = sorted(allMeldTiles) # needed for Chow
         meld = Meld(allMeldTiles)
         for meldTile in meldTiles:
             self.__concealedTileNames.remove(meldTile)
         for meldTile in allMeldTiles:
             self.visibleTiles[meldTile.lower()] += 1
         meld.expose(bool(calledTile))
     self._exposedMelds.append(meld)
     self.__hand = None
     game.computeDangerous(self)
     adding = [calledTile] if calledTile else None
     self.syncHandBoard(adding=adding)
     return meld
Exemplo n.º 27
0
 def speak(what):
     """this is what the user of this module will call."""
     if not Sound.enabled:
         return
     game = Internal.field.game
     reactor = Internal.reactor
     if game and not game.autoPlay and Sound.playProcesses:
         # in normal play, wait a moment between two speaks. Otherwise
         # sometimes too many simultaneous speaks make them ununderstandable
         lastSpeakStart = max(x.startTime for x in Sound.playProcesses)
         if datetime.datetime.now() - lastSpeakStart < datetime.timedelta(seconds=0.3):
             reactor.callLater(1, Sound.speak, what)
             return
     if os.path.exists(what):
         if Sound.findOgg():
             if os.name == 'nt':
                 name, ext = os.path.splitext(what)
                 assert ext == '.ogg'
                 wavName = name + '.wav'
                 if not os.path.exists(wavName):
                     args = [r'c:\vorbis\oggdec', '--quiet', what]
                     process = subprocess.Popen(args)
                     os.waitpid(process.pid, 0)
                 winsound.PlaySound(wavName, winsound.SND_FILENAME)
             else:
                 args = ['ogg123', '-q', what]
                 if Debug.sound:
                     game.debug(' '.join(args))
                 process = subprocess.Popen(args)
                 process.startTime = datetime.datetime.now()
                 process.name = what
                 Sound.playProcesses.append(process)
                 reactor.callLater(3, Sound.cleanProcesses)
                 reactor.callLater(6, Sound.cleanProcesses)
     elif False:
         text = os.path.basename(what)
         text = os.path.splitext(text)[0]
         # If this ever works, we need to translate all texts
         # we need package jovie and mbrola voices
         # KSpeech setLanguage de
         # KSpeech.showManagerDialog lets me define voices but
         # how do I use them? it is always the same voice,
         # setDefaultTalker "namefrommanager" does not change anything
         # although defaultTalker returns what we just set even if no talker
         # with that name exists
         # getTalkerCodes returns nothing
         # this all feels immature
         if len(text) == 2 and text[0] in 'sdbcw':
             text = Meld.tileName(text)
         args = ['qdbus', 'org.kde.jovie',
             '/KSpeech', 'say', text, '1']
         subprocess.Popen(args)
Exemplo n.º 28
0
 def speak(what):
     """this is what the user of this module will call."""
     if not Sound.enabled:
         return
     game = Internal.field.game
     reactor = Internal.reactor
     if game and not game.autoPlay and Sound.playProcesses:
         # in normal play, wait a moment between two speaks. Otherwise
         # sometimes too many simultaneous speaks make them ununderstandable
         lastSpeakStart = max(x.startTime for x in Sound.playProcesses)
         if datetime.datetime.now() - lastSpeakStart < datetime.timedelta(
                 seconds=0.3):
             reactor.callLater(1, Sound.speak, what)
             return
     if os.path.exists(what):
         if Sound.findOgg():
             if os.name == 'nt':
                 name, ext = os.path.splitext(what)
                 assert ext == '.ogg'
                 wavName = name + '.wav'
                 if not os.path.exists(wavName):
                     args = [r'c:\vorbis\oggdec', '--quiet', what]
                     process = subprocess.Popen(args)
                     os.waitpid(process.pid, 0)
                 winsound.PlaySound(wavName, winsound.SND_FILENAME)
             else:
                 args = ['ogg123', '-q', what]
                 if Debug.sound:
                     game.debug(' '.join(args))
                 process = subprocess.Popen(args)
                 process.startTime = datetime.datetime.now()
                 process.name = what
                 Sound.playProcesses.append(process)
                 reactor.callLater(3, Sound.cleanProcesses)
                 reactor.callLater(6, Sound.cleanProcesses)
     elif False:
         text = os.path.basename(what)
         text = os.path.splitext(text)[0]
         # If this ever works, we need to translate all texts
         # we need package jovie and mbrola voices
         # KSpeech setLanguage de
         # KSpeech.showManagerDialog lets me define voices but
         # how do I use them? it is always the same voice,
         # setDefaultTalker "namefrommanager" does not change anything
         # although defaultTalker returns what we just set even if no talker
         # with that name exists
         # getTalkerCodes returns nothing
         # this all feels immature
         if len(text) == 2 and text[0] in 'sdbcw':
             text = Meld.tileName(text)
         args = ['qdbus', 'org.kde.jovie', '/KSpeech', 'say', text, '1']
         subprocess.Popen(args)
Exemplo n.º 29
0
def getMonth(month):
    folder = os.path.expanduser(
        '~/Documents/MJLogPython/log/{}/'.format(month))

    if not os.path.exists(folder):
        os.mkdir(folder)

    if month > '200801':
        ykmlist = os.path.expanduser(
            '~/Documents/MJLogPython/ykmjs/New/{}.txt'.format(month))
    else:
        #ykmlist = os.path.expanduser('~/Documents/MJLogPython/ykmjs/New/{}.txt'.format(month))
        raise ValueError("{} yakuman list is in an old format".format(month))
    if not os.path.isfile(ykmlist):
        raise ValueError("{} yakuman list was not prepared.".format(month))

    CharHaiDisp = [
        "<1m>", "<2m>", "<3m>", "<4m>", "<5m>", "<6m>", "<7m>", "<8m>", "<9m>",
        "<1p>", "<2p>", "<3p>", "<4p>", "<5p>", "<6p>", "<7p>", "<8p>", "<9p>",
        "<1s>", "<2s>", "<3s>", "<4s>", "<5s>", "<6s>", "<7s>", "<8s>", "<9s>",
        "<東>", "<南>", "<西>", "<北>", "<白>", "<發>", "<中>"
    ]
    #cnt, cnt1 = 0, 0
    with open(ykmlist, 'rb') as file_:
        next(file_)
        next(file_)
        #                        ' time ','  name  ','[table,[   hand   ],[chiiponkon],last]' ,[yakuman(s)],'link info'
        ykmline = re.finditer(
            r'\'.{11}\',\'[^\']+\',\'\[\d+,\[([\d,]+)\],\[([\d,]*)\],\d+\]\',\[([\d,]*)\],\'([^\']+)\'',
            next(file_).decode('utf-8'))
        for ykm in ykmline:
            #cnt += 1
            hand, furu, ykmstr, info = ykm.groups()
            # print(ykm.groups())
            try:
                ykmtypes = {int(_) for _ in ykmstr.split(',')}
            except:
                # 数え役満
                s = ''.join(CharHaiDisp[int(tile) >> 2]
                            for tile in hand.split(','))
                if len(furu) > 0:
                    s += ', ' + ', '.join(
                        Meld(_).getInfo() for _ in furu.split(','))
                print(info)
                print(s)
            #if (37 in ykmtypes) or (38 in ykmtypes): # 天和,地和
            #    #cnt1 += 1
            #    a = PaifuParseTool(info)
            #    a.printHaiPai()

    #print(cnt, cnt1)
    return None
Exemplo n.º 30
0
 def toolTip(self, button, tile):
     """decorate the action button which will send this message"""
     myself = button.client.game.myself
     isCalling = bool((myself.hand - tile.element).callingHands())
     if not isCalling:
         txt = m18n('discarding %1 and declaring Original Call makes this hand unwinnable',
             Meld.tileName(tile.element))
         return txt, True, txt
     else:
         return (m18n(
             'Discard a tile, declaring Original Call meaning you need only one '
             'tile to complete the hand and will not alter the hand in any way (except bonus tiles)'),
             False, '')
Exemplo n.º 31
0
 def claimMahJongg(self, msg):
     """a player claims mah jongg. Check this and
     if correct, tell all. Otherwise abort game, kajongg client is faulty"""
     if not self.running:
         return
     player = msg.player
     concealedMelds = MeldList(msg.args[0])
     withDiscard = Tile(msg.args[1]) if msg.args[1] else None
     lastMeld = Meld(msg.args[2])
     if self.game.ruleset.mustDeclareCallingHand:
         assert player.isCalling, '%s %s %s says MJ but never claimed: concmelds:%s withdiscard:%s lastmeld:%s' % (
             self.game.handId, player.hand, player, concealedMelds,
             withDiscard, lastMeld)
     discardingPlayer = self.game.activePlayer
     lastMove = next(self.game.lastMoves(withoutNotifications=True))
     robbedTheKong = lastMove.message == Message.DeclaredKong
     if robbedTheKong:
         player.robsTile()
         withDiscard = lastMove.meld[0].concealed
         lastMove.player.robTileFrom(withDiscard)
     msgArgs = player.showConcealedMelds(concealedMelds, withDiscard)
     if msgArgs:
         self.abort(*msgArgs)
         return
     player.declaredMahJongg(concealedMelds, withDiscard, player.lastTile,
                             lastMeld)
     if not player.hand.won:
         msg = i18nE('%1 claiming MahJongg: This is not a winning hand: %2')
         self.abort(msg, player.name, player.hand.string)
         return
     block = DeferredBlock(self)
     if robbedTheKong:
         block.tellAll(player, Message.RobbedTheKong, tile=withDiscard)
     if (player.lastSource is TileSource.LivingWallDiscard
             and self.game.dangerousFor(discardingPlayer, player.lastTile)
             and discardingPlayer.playedDangerous):
         player.usedDangerousFrom = discardingPlayer
         if Debug.dangerousGame:
             logDebug('%s wins with dangerous tile %s from %s' %
                      (player, self.game.lastDiscard, discardingPlayer))
         block.tellAll(player,
                       Message.UsedDangerousFrom,
                       source=discardingPlayer.name)
     block.tellAll(player,
                   Message.MahJongg,
                   melds=concealedMelds,
                   lastTile=player.lastTile,
                   lastMeld=lastMeld,
                   withDiscardTile=withDiscard)
     block.callback(self.endHand)
Exemplo n.º 32
0
 def __separateMelds(self, tileString):
     """build a meld list from the hand string"""
     # no matter how the tiles are grouped make a single
     # meld for every bonus tile
     # we need to remove spaces from the hand string first
     # for building only pairs with length 2
     splits = tileString.split()
     rest = ''
     for split in splits:
         if split[0] == 'R':
             rest = split[1:]
         else:
             meld = Meld(split)
             self.melds.append(meld)
             self.declaredMelds.append(meld)
     if rest:
         rest = sorted([rest[x:x+2] for x in range(0, len(rest), 2)])
         self.__split(rest)
     self.melds = sorted(self.melds, key=meldKey)
     for meld in self.melds:
         if not meld.isValid():
             raise Exception('%s has an invalid meld: %s' % (self.string, meld.joined))
     self.__categorizeMelds()