Exemplo n.º 1
0
class DummyContract:
    def __init__(self, server, talon):
        self._name = "DummyContract"
        self._server = server
        self._talon = talon
        self._pileMenus = []
        self.DistributeTalon()

    ## written for TeamContract, then copied here
    def DistributeTalon(self):
        cards = list(self._talon.values())
        shuffle(cards)
        Npile = self.Npiles()
        ## create a pile menu to choose which cards to pick up
        self._talonMenu = Menu()
        self._talonMenu.Deactivate()
        for i in range(Npile):
            tag = 'pile{}'.format(i)
            desc = ''  ## description of cards in pile
            ## create a menu for each pile of cards
            menu = Menu(info=True)
            ## distribute cards to the piles
            ## build the description for the pile menu
            for card in cards[i * self._num:(i + 1) * self._num]:
                menu.AddEntry(card.ShortName(),
                              card.LongName())  ## entry for each card
                desc = desc + ('/' if (len(desc) > 0) else '') + '{}'.format(
                    card.LongName())
            self._talonMenu.AddEntry(tag, desc)  ## entry for picking piles
            self._pileMenus.append(menu)

    def Npiles(self):
        return 1

    def ValidPlay(self, hand, play, lead):
        return True

    def CardValue(self, card):
        return 0

    def TrickWinner(self, trick, leadPlayer):
        return list(trick.keys())[0]

    def GetMenu(self, name, tag):
        if tag == 'talon':
            return self._talonMenu
        elif tag[:4] == 'pile':
            return self._pileMenus[0]

    def ProcessMenuEntry(self, name, tag, req):
        if tag == 'talon' and req[:4] == 'pile':
            n = int(req[-1])
            self._server._gameControl._bidders['active'].DeactivateMenu(
                'talon')
            self._server.BroadcastMessage("{} picked {}".format(name, req))
        raise ValueError("ProcessMenuEntry")

    def SetKing(self, king):
        raise ValueError("{} not a valid contract for calling a king".format(
            self._name))
Exemplo n.º 2
0
 def BuildDefaultMenu(self):
   self._menus = {} ## keep multiple menus
   self._menus['default'] = Menu()
   self._menus['default'].AddEntry( 'quit', "Exit the program")
   self._menus['default'].AddEntry( 'master', "Request master action", True)
   self._menus['default'].AddEntry( 'exception', "Throw intentional exception", not( _debug))
   self._menus['default'].AddEntry( '', "Ready", True)
   self._menus['default'].AddEntry( 'end', "End the game", True)
   self._menus['default'].AddEntry( '2p', "Start two player game", True) ## debugging purposes
   self._menus['messages'] = Menu( info=True)
Exemplo n.º 3
0
 def DistributeTalon(self):
     cards = list(self._talon.values())
     shuffle(cards)
     Npile = self.Npiles()
     ## create a pile menu to choose which cards to pick up
     self._talonMenu = Menu()
     self._talonMenu.Deactivate()
     for i in range(Npile):
         tag = 'pile{}'.format(i)
         desc = ''  ## description of cards in pile
         ## create a menu for each pile of cards
         menu = Menu(info=True)
         ## distribute cards to the piles
         ## build the description for the pile menu
         for card in cards[i * self._num:(i + 1) * self._num]:
             menu.AddEntry(card.ShortName(),
                           card.LongName())  ## entry for each card
             desc = desc + ('/' if (len(desc) > 0) else '') + '{}'.format(
                 card.LongName())
         self._talonMenu.AddEntry(tag, desc)  ## entry for picking piles
         self._pileMenus.append(menu)
Exemplo n.º 4
0
 def InitializeMenus(self):
     self._bidMenu = Menu()
     self._bidMenu.AddEntry('pass', 'No bid')
     self._bidMenu.AddEntry('K', 'Klop')
     self._bidMenu.AddEntry('3', 'Three w/ partner')
     self._bidMenu.AddEntry('2', 'Two   w/ partner')
     self._bidMenu.AddEntry('1', 'One   w/ partner')
     self._bidMenu.AddEntry('S3', 'Solo Three')
     self._bidMenu.AddEntry('S2', 'Solo Two')
     self._bidMenu.AddEntry('S1', 'Solo One')
     self._bidMenu.AddEntry('B', 'Beggar')
     self._bidMenu.AddEntry('S0', 'Solo Without')
     self._bidMenu.AddEntry('OB', 'Open Beggar')
     self._bidMenu.AddEntry('CV', 'Color Valat Without')
     self._bidMenu.AddEntry('V', 'Valat Without')
     self._bidMenu.Deactivate()
     self._kingMenu = Menu()
     self._kingMenu.AddEntry('diamond', 'King of Diamonds')
     self._kingMenu.AddEntry('spade', 'King of Spades')
     self._kingMenu.AddEntry('heart', 'King of Hearts')
     self._kingMenu.AddEntry('club', 'King of Clubs')
     self._kingMenu.Deactivate()
     self._announcementMenu = Menu()
     self._announcementMenu.AddEntry('pass', 'No announcement')
     self._announcementMenu.AddEntry('kontra', 'Kontra game (x2)')
     self._announcementMenu.AddEntry('rekontra', 'Rekontra game (x4)')
     self._announcementMenu.AddEntry('subkontra', 'Subkontra game (x8)')
     self._announcementMenu.AddEntry('mordkontra', 'Mordkontra game (x16)')
     self._announcementMenu.AddEntry('trula',
                                     'End game in possession of trula')
     self._announcementMenu.AddEntry('kings',
                                     'End game in possession of all kings')
     self._announcementMenu.AddEntry('king_ult',
                                     'Win called king on last trick')
     self._announcementMenu.AddEntry('pagat_ult',
                                     'Win last trick with pagat')
     self._announcementMenu.AddEntry('valat', 'Win all tricks')
     self._announcementMenu.Deactivate()
Exemplo n.º 5
0
class TeamContract:
    def __init__(self, server, num, talon):
        self._name = "TeamContract"
        self._server = server
        self._num = num
        self._king = None
        self._talon = talon
        self._talonMenu = None
        self._pileMenus = []
        self.DistributeTalon()

    def DistributeTalon(self):
        cards = list(self._talon.values())
        shuffle(cards)
        Npile = len(cards) // self._num
        ## create a pile menu to choose which cards to pick up
        self._talonMenu = Menu()
        self._talonMenu.Deactivate()
        for i in range(Npile):
            tag = 'pile{}'.format(i)
            desc = ''  ## description of cards in pile
            ## create a menu for each pile of cards
            menu = Menu(info=True)
            #menu.Deactivate() ## menus broadcast right before display
            ## distribute cards to the piles
            ## build the description for the pile menu
            for card in cards[i * self._num:(i + 1) * self._num]:
                menu.AddEntry(card.ShortName(),
                              card.LongName())  ## entry for each card
                desc = desc + ('/' if (len(desc) > 0) else '') + '{}'.format(
                    card.LongName())
            self._talonMenu.AddEntry(tag, desc)  ## entry for picking piles
            self._pileMenus.append(menu)

    def Npiles(self):
        return len(self._pileMenus)

    def ValidPlay(self, hand, play, lead):
        return True

    def CardValue(self, card):
        return 0

    def TrickWinner(self, trick, leadPlayer):
        return list(trick.keys())[0]

    def GetMenu(self, name, tag):
        if tag == 'talon':
            return self._talonMenu
        elif tag[:4] == 'pile':
            n = int(tag[-1])
            return self._pileMenus[n]

    def ProcessMenuEntry(self, name, tag, req):
        if tag == 'talon' and req[:4] == 'pile':
            n = int(req[-1])
            self._server.BidderHook('leading').DeactivateMenu('talon')
            self._server.BroadcastMessage("{} picked {}".format(name, req))
            for shortName, longName in self._pileMenus[n].items():
                card = self._talon[shortName]
                self._server.BroadcastMessage("{} picked up {}".format(
                    name, longName))
                self._server.PlayerHook(name).AddToHand(card, fromTalon=True)
            ## refresh the menu
            self._server.PlayerHook(name).HandToMenu()
            self._server.ClientHook(name).PrintMessage(
                "YOUR TURN: choose {} cards to lay down".format(self._num))
        elif tag == 'discard':
            Ndiscard = self._server.PlayerHook(name).DiscardFromHand(req)
            if Ndiscard == self._num:
                ## go to announcements
                self._server.PlayerHook(name).HandToInfo()
                self._server._gameControl._bidding.MakeAnnouncements()
            else:
                self._server.ClientHook(name).PrintMessage(
                    "YOUR TURN: choose {} cards to lay down".format(self._num -
                                                                    Ndiscard))

    def SetKing(self, king):
        self._king = king
Exemplo n.º 6
0
class Bidding:
    def __init__(self, server):
        self._server = server
        self._contracts = {
            'K': 0,
            '3': 10,
            '2': 20,
            '1': 30,
            'S3': 40,
            'S2': 50,
            'S1': 60,
            'B': 70,
            'S0': 80,
            'OB': 90,
            'CV': 125,
            'V': 250
        }
        self._announcements = {
            'kontra': None,
            'rekontra': None,
            'subkontra': None,
            'mordkontra': None,
            'trula': None,
            'kings': None,
            'king_ult': None,
            'pagat_ult': None,
            'valat': None
        }
        self._playerNames = []
        self._bidders = {}  ## key is bidder condition, value is name of bidder
        self.Cleanup()
        self.InitializeMenus()

    def Cleanup(self):
        self._talon = {}  ## dictionary to hold talon cards temporarily
        self._leadingBid = None

    def InitializeMenus(self):
        self._bidMenu = Menu()
        self._bidMenu.AddEntry('pass', 'No bid')
        self._bidMenu.AddEntry('K', 'Klop')
        self._bidMenu.AddEntry('3', 'Three w/ partner')
        self._bidMenu.AddEntry('2', 'Two   w/ partner')
        self._bidMenu.AddEntry('1', 'One   w/ partner')
        self._bidMenu.AddEntry('S3', 'Solo Three')
        self._bidMenu.AddEntry('S2', 'Solo Two')
        self._bidMenu.AddEntry('S1', 'Solo One')
        self._bidMenu.AddEntry('B', 'Beggar')
        self._bidMenu.AddEntry('S0', 'Solo Without')
        self._bidMenu.AddEntry('OB', 'Open Beggar')
        self._bidMenu.AddEntry('CV', 'Color Valat Without')
        self._bidMenu.AddEntry('V', 'Valat Without')
        self._bidMenu.Deactivate()
        self._kingMenu = Menu()
        self._kingMenu.AddEntry('diamond', 'King of Diamonds')
        self._kingMenu.AddEntry('spade', 'King of Spades')
        self._kingMenu.AddEntry('heart', 'King of Hearts')
        self._kingMenu.AddEntry('club', 'King of Clubs')
        self._kingMenu.Deactivate()
        self._announcementMenu = Menu()
        self._announcementMenu.AddEntry('pass', 'No announcement')
        self._announcementMenu.AddEntry('kontra', 'Kontra game (x2)')
        self._announcementMenu.AddEntry('rekontra', 'Rekontra game (x4)')
        self._announcementMenu.AddEntry('subkontra', 'Subkontra game (x8)')
        self._announcementMenu.AddEntry('mordkontra', 'Mordkontra game (x16)')
        self._announcementMenu.AddEntry('trula',
                                        'End game in possession of trula')
        self._announcementMenu.AddEntry('kings',
                                        'End game in possession of all kings')
        self._announcementMenu.AddEntry('king_ult',
                                        'Win called king on last trick')
        self._announcementMenu.AddEntry('pagat_ult',
                                        'Win last trick with pagat')
        self._announcementMenu.AddEntry('valat', 'Win all tricks')
        self._announcementMenu.Deactivate()

    def MenuMask(self, name, tag):
        if tag == 'bidding':
            # Make 3 and Klop available only to final bidder after three passes
            mask = set(['K', '3'])
            if self._leadingBid is None:
                if self._bidders['last'] == name:
                    mask.discard('3')
                    mask.discard('K')
            # Mask off any bids lower than current bid
            else:
                val = 10
                for ct, v in self._contracts.items():
                    if ct == self._leadingBid:
                        val = v
                #TODO: Update to allow for precendence
                out = dict(
                    (c, v) for c, v in self._contracts.items() if v <= val)
                for c in out:
                    mask.add(c)
            return mask
        elif tag == 'announcement':
            mask = set(self._announcementMenu.keys())
            mask.discard('pass')
            if self._announcements['valat'] is None:
                mask.discard('valat')
                mask.discard('kontra')
                if not (self._announcements['kontra'] is None):
                    mask.add('kontra')
                    mask.discard('rekontra')
                if not (self._announcements['rekontra'] is None):
                    mask.add('rekontra')
                    mask.discard('subkontra')
                if not (self._announcements['subkontra'] is None):
                    mask.add('subkontra')
                    mask.discard('mordkontra')
                if not (self._announcements['mordkontra'] is None):
                    mask.add('mordkontra')
                if self._announcements['trula'] is None:
                    mask.discard('trula')
                if self._announcements['kings'] is None:
                    mask.discard('kings')
                if self._announcements['king_ult'] is None:
                    mask.discard('king_ult')
                if self._announcements['pagat_ult'] is None:
                    mask.discard('pagat_ult')
            return mask
        return set([])

    def GetMenu(self, name, tag):
        if tag == 'bidding':
            return self._bidMenu
        if tag == 'kings':
            return self._kingMenu
        if tag == 'announcement':
            return self._announcementMenu

    def StartBidding(self):
        self._bidders['passed'] = []
        self._bidders['active'] = self._bidders['first']
        i = self._playerNames.index(self._bidders['first'])
        Nplayer = len(self._playerNames)
        self._bidders['last'] = self._playerNames[(Nplayer + i - 1) % Nplayer]
        self._bidders['leading'] = None
        self._leadingBid = None
        ## distribute bidding menu
        self._server.BroadcastMenu('bidding')
        self.BidderHook('active').ActivateMenu('bidding')

    def EndBidding(self):
        self.BidderHook('active').DeactivateMenu('bidding')
        self._server.BroadcastMessage('{0} is Declarer with Bid {1}.'.format(
            self._bidders['leading'], self._leadingBid))
        self._server._gameControl.SetContract(self._leadingBid, self._talon)
        self.DeclareKing()

    ## return a hook to the client
    def BidderHook(self, tag):
        return self._server._clientHooks[self._bidders[tag]]

    ## get the name of the bidder
    def Bidder(self, tag):
        return self._bidders[tag]

    def DeclareKing(self):
        kingcontracts = ["3", "2", "1"]
        if self._leadingBid in kingcontracts:
            self._server.BroadcastMenu('kings')
            self._bidders['active'] = self._bidders['leading']
            self.BidderHook('active').ActivateMenu('kings')
        else:
            ## skip to talon
            self.HandleTalon()

    def HandleTalon(self):
        taloncontracts = ["3", "2", "1", "S3", "S2", "S1"]
        if self._leadingBid in taloncontracts:
            self._server.BroadcastMenu('talon')
            for i in range(self._server._gameControl._contract.Npiles()):
                self._server.BroadcastMenu('pile{}'.format(i))
            self._bidders['active'] = self._bidders['leading']
            self.BidderHook('active').ActivateMenu('talon')
        else:
            ## skip to announcements
            self.MakeAnnouncements()

    def DeactivatePileMenus(self):
        taloncontracts = ["3", "2", "1", "S3", "S2", "S1"]
        if self._leadingBid in taloncontracts:
            for name in self._playerNames:
                for i in range(self._server._gameControl._contract.Npiles()):
                    self._server.ClientHook(name).DeactivateMenu(
                        'pile{}'.format(i))

    def MakeAnnouncements(self):
        self._server.BroadcastMessage("starting announcements")
        self._bidders['passed'] = []
        self._bidders['active'] = self._bidders['first']
        i = self._playerNames.index(self._bidders['first'])
        ## distribute bidding menu
        self._server.BroadcastMenu('announcement')
        self.BidderHook('active').ActivateMenu('announcement')

    def EndAnnouncements(self):
        for name in self._playerNames:
            self._server.ClientHook(name).DeactivateMenu('announcement')
        self._server.BroadcastMessage('ending announcements')
        self._server._gameControl.StartTricks()

    def ContractValue(self):
        return self._contracts[self._leadingBid]

    ## handle message forwarding to appropriate class object
    def ProcessMenuEntry(self, name, tag, req):
        if name == self._bidders['active'] and tag == 'bidding':
            if req != 'pass':
                self._leadingBid = req
                self._bidders['leading'] = name
                ## in this case, the incoming bid was the final bid
                if len(self._bidders['passed']) == len(self._playerNames) - 1:
                    self.EndBidding()
                    return  ## don't allow a NextActivePlayer call
            ## if the bid was 'pass'
            else:
                self._bidders['passed'].append(name)
                if len(self._bidders['passed']) == len(self._playerNames) - 1:
                    self._server.BroadcastMessage('Final Bid')
                elif len(self._bidders['passed']) == len(self._playerNames):
                    self.EndBidding()
            self.NextActivePlayer('bidding')
        elif name == self._bidders['active'] and tag == 'kings':
            self._server._gameControl._contract.SetKing(req)
            self.BidderHook('active').DeactivateMenu('kings')
            self.HandleTalon()
        elif name == self._bidders['active'] and tag == 'talon':
            self._server._gameControl._contract.ProcessMenuEntry(
                name, tag, req)
        elif tag == 'announcement':
            if req != 'pass':
                ## TODO: change so more than one announcement can be made by same person at once
                ## need to have at least two rounds of passing to complete announcement process
                self._announcements[req] = name
            ## if the bid was 'pass'
            else:
                self._bidders['passed'].append(name)
                if len(self._bidders['passed']) == len(self._playerNames):
                    self.EndAnnouncements()
                    return
            self.NextActivePlayer('announcement')

    def NextActivePlayer(self, tag):
        i = self._playerNames.index(self._bidders['active'])
        Nplayer = len(self._playerNames)
        self.BidderHook('active').DeactivateMenu(tag)
        for k in range(1, Nplayer + 1):
            if (self._playerNames[(Nplayer + i - k) % Nplayer]
                    not in self._bidders['passed']):
                self._bidders['active'] = self._playerNames[(Nplayer + i - k) %
                                                            Nplayer]
                self.BidderHook('active').ActivateMenu(tag)
                return

    def NextFirstPlayer(self):
        Nplayer = len(self._playerNames)
        i = (self._playerNames.index(self._bidders['first']) + 1) % Nplayer
        self._bidders['first'] = self._playerNames[i]
        self._server.BroadcastMessage('{} to lead next round'.format(
            self._bidders['first']))

    def SetPlayers(self, playerNames):
        self._playerNames = playerNames
        if self._bidders.get('first', None) is None:
            self._bidders['first'] = self._playerNames[0]

    def ActiveBidder(self):
        return self._bidders['active']

    ## add cards to talon when dealing
    ## just save here for now; will be handled by contract later
    def AddToTalon(self, card):
        self._talon[card.ShortName()] = card
Exemplo n.º 7
0
class Player:
    def __init__(self, name, server):
        self._name = name
        self._server = server
        self._score = 0
        self.Cleanup()

    def SetScore(self, score):
        self._score = score

    def GetScore(self):
        return self._score

    def Cleanup(self):
        self._handMenu = Menu(info=True)
        self._hand = {}  ## Card class objects, keys are Card.ShortName()
        self._tricks = {}  ## Card class objects won in tricks
        self._talonCards = []  ## track cards that came from talon

    ## add Card objects to hand when dealing or handling talon
    def AddToHand(self, card, fromTalon=False):
        self._handMenu.AddEntry(card.ShortName(), card.LongName())
        self._hand[card.ShortName()] = card
        if fromTalon:  ## keep track of which cards come from talon
            self._talonCards.append(card.ShortName())

    ## lay down cards after taking from talon
    def DiscardFromHand(self, req):
        card = self._hand[req]
        self._handMenu.MaskEntry(card.ShortName())
        self._tricks[req] = card
        self._server.ClientHook(self._name).PrintMessage(
            "you laid down {}".format(card.LongName()))
        self._server.BroadcastMessage("{} laid down a card".format(self._name))
        return len(
            self._tricks.keys())  ## used to determine change to announcements

    def MenuMask(self, tag):
        if tag == 'hand':
            return self._handMenu._mask

    def GetMenu(self, tag):
        if tag == 'hand':
            return self._handMenu

    ## convert the hand from info-only to menu
    def HandToMenu(self):
        self._handMenu.SetToMenu()
        self._server.BuildMenu(self._name, 'hand')

    ## convert the hand from menu to info-only
    def HandToInfo(self):
        self._handMenu.SetToInfo()
        self._server.BuildMenu(self._name, 'hand')

    ## add cards to hand when dealing or handling talon
    def TakeTrick(self, trick):
        for card in trick.values():
            self._tricks[card.ShortName()] = card

    def CardsInHand(self):
        return len(self._handMenu.keys())

    def ScoreTricks(self, contract):
        cardValueSum = 0
        for card in self._tricks.values():
            cardValueSum += contract.CardValue(card)
        return cardValueSum
Exemplo n.º 8
0
 def Cleanup(self):
     self._handMenu = Menu(info=True)
     self._hand = {}  ## Card class objects, keys are Card.ShortName()
     self._tricks = {}  ## Card class objects won in tricks
     self._talonCards = []  ## track cards that came from talon