[Tutor] GoFish

Russell Bungay rab121@york.ac.uk
Sat, 11 May 2002 17:06:36 +0100


Hello Again,

As promised here is my code.  It is arranged in four modules:

gofish.py:	the main program module
cards.py:	the module defining a pack of cards class
players.py:	the module defining the player classes for humans and AI
players
bmdutils.py:	my general purpose module for useful functions (only the
used code is included)

I believe I have used code that will only work under Python 2.2.  There
is also a very little windows specific code (os.system('cls')).

#
#gofish.py
#

import bmdutils,cards,ConfigParser,os,os.path,players,sys

gofishdir = os.path.dirname(players.__file__)    # Get directory of
module

class GoFish:

    def __init__(self):
        
        self.fishers = {}
        self.deck =[]
        self.out = []
        
        if not os.path.exists(gofishdir + '\\gofishini'):
            self.createini()
	    gofishinifile = open(gofishdir + '\\gofishini', 'rw')
            self.ini = ConfigParser.ConfigParser()
            self.ini.readfp(gofishinifile)
        else:
            gofishinifile = open(gofishdir + '\\gofishini', 'rw')
            self.ini = ConfigParser.ConfigParser()
            self.ini.readfp(gofishinifile)

        bmdutils.bmdmenu([['1.  Start a New game', self.new,
['1','n','N']],['2.  Edit your Preferences', self.pref, ['2','p','P']],
['3.  Quit this program', self.quit, ['3','q','Q']]])

    def new(self):
        
        default = 'Default Options:\n'
        for a in range(self.ini.getint('default','ai')):    # Create
string showing default options
            default = default + self.ini.get('ai', str(a + 1)) + ' (' +
self.ini.get('ai' , 'levels')[a] + ') '
        bmdutils.bmdmenu([['1.  Start with Default options',
self.create, ['1','d','D']],['2.  Start with New options',
self.createopt, ['2','n','N']],[default,None,[]]])  # Third option
prints default options with no possible selection

    def create(self, options=None):

        hum = 0
        if not options:
            options = []
            for opt in range(self.ini.getint('default','ai')):
               
options.append([self.ini.get('ai','levels')[opt],self.ini.get('ai',
str(opt + 1))])
            if self.ini.getint('default', 'human') != 0:
                options.append([0,self.ini.get('default', 'name')])

        for p in range(len(options)):
            if options[p][0] == 0:
                self.fishers[p] = players.Human(options[p][1])
                hum = p
            else:
                level = 'AI' + str(options[p][0])
                self.fishers[p] = eval('players.' + level +
'(options[p][1])')

        newcards = cards.bmdcard()
        hands =
newcards.deal(hands=[[len(self.fishers),self.ini.getint('default','cards')]],
shuffles=self.ini.getint('prefs','shuffles'))

        for k in range(len(self.fishers)):
            for c in hands[k]:
                self.fishers[self.fishers.keys()[k]].receivecard(c)

        hands= hands[-1:]
        self.deck = hands[0]
        os.system('cls')
        self.mainloop(1,hum)
        
    def createopt(self):

        print 'opt'

    def mainloop(self,start,human):

        fish = start
        num = len(self.fishers)

        while len(self.fishers[human].hand) > 0:
                
                if fish not in self.out:
                    fish = self.turn(fish,human)
                elif len(self.out) == len(self.fishers) - 1:
                    print 'cheese'
                else:
                    for f in self.fishers:
                        if f not in self.out:
                            fish = f
                    fish = self.turn(fish,human)
                
                for p in self.fishers:
                    if len(self.fishers[p].hand) == 0 and p not in
self.out:
                        print 'Well done ' + self.fishers[p].name + '
you finished in place number ' + str(len(self.out) + 1)
                        self.out.append(p)
                
        raw_input()
        self.quit()
                        
    def turn(self, fish, human):

        interface = 'You have:  '
        for card in self.fishers[human].hand:
            interface += self.numtocard(card) + '  '
        interface += '\n'
        interface += 'You have declared:  '
        for rank in self.fishers[human].declared:
            interface += str(rank + 1) + '  '
        interface += '\n\n'
        for player in self.fishers:
            if self.fishers[player] != self.fishers[human]:
                interface += self.fishers[player].name + ' has ' +
str(len(self.fishers[player].hand)) + ' cards remaining, and has
declared:  '
                for rank in self.fishers[player].declared:
                    interface += str(rank + 1) + '  '
                interface += '\n'
        interface += '\nThere are ' + str(len(self.deck)) + ' cards in
the deck. \n'

        if fish != human:
            print interface
            #for t in self.fishers:
            #    print self.fishers[t].name, self.fishers[t].hand
            play = 0,fish
            while play[1] == fish or play[1] in self.out:
                play = self.fishers[fish].askcard(len(self.fishers))
            print self.fishers[fish].name + ' has asked ' +
self.fishers[play[1]].name + ' for a ' + str(play[0] + 1)
            
            for p in (play[0]*4, play[0]*4 + 1, play[0]*4 + 2, play[0]*4
+ 3):
                if p in self.fishers[play[1]].hand:
                    print self.fishers[play[1]].name + ' has given ' +
self.fishers[fish].name + ' a ' + str(play[0] + 1)
                    self.fishers[fish].receivecard(p)
                    self.fishers[play[1]].removecard(p)
                    for player in self.fishers:
                        if 'update' in dir(player):
                            player.update()
                    raw_input()
                    os.system('cls')
                    return fish
        
            if len(self.deck) != 0:
                self.fishers[fish].receivecard(self.deck[0])
                self.deck = self.deck[1:]
            print 'GO FISH'
            raw_input()
            os.system('cls')
            return play[1]
        else:
            interface += '\nAsk for a card from:'
            for player in self.fishers:
                interface += '\n'
                if self.fishers[player] != self.fishers[human]:
                    interface += str(player + 1) + '. ' +
self.fishers[player].name + '  '
            interface += '\nDeclare a rank.\n'
            interface += 'Quit the game.\n'
            print interface
            choice = ''
            choices = ['d','D','q','Q']
            for i in range(len(self.fishers) - 1):
                choices.append(str(i + 1))
            while choice not in choices:
                choice = raw_input('Please choose an option: ')
            if choice == 'd' or choice == 'D':
                print declare
            elif choice == 'q' or choice == 'Q':
                if raw_input('Are you sure? y/n') == 'y' or
raw_input('Are you sure? y/n') == 'Y': self.quit()
            else:
                askfor = int(raw_input('Which rank do you wish to ask
for?')) - 1
                for a in (askfor*4, askfor*4 + 1, askfor*4 + 2, askfor*4
+ 3):
                    if a in self.fishers[int(choice) - 1].hand:
                        print self.fishers[int(choice) - 1].name + ' has
given you a ' + str(askfor + 1)
                        self.fishers[fish].receivecard(a)
                        self.fishers[int(choice) - 1].removecard(a)
                        for player in self.fishers:
                            if 'update' in dir(player):
                                player.update()

                        raw_input()
                        os.system('cls')
                        return fish

                if len(self.deck) != 0:
                    self.fishers[fish].receivecard(self.deck[0])
                    self.deck = self.deck[1:]
                print 'GO FISH'
                raw_input()
                os.system('cls')
                return int(choice) - 1
            

    def pref(self):

        print 'pref'

    def quit(self):

        sys.exit()

    def createini(self):

        gofishinifile = open(gofishdir + '\\gofishini', 'w')
        self.ini = ConfigParser.ConfigParser()
        self.ini.add_section('prefs')
        self.ini.set('prefs', 'sort', 0)
        self.ini.set('prefs', 'disp_actions', 1)
        self.ini.set('prefs', 'auto_dec', 0)
        self.ini.set('prefs', 'shuffles', 10)        
        self.ini.add_section('default')
        self.ini.set('default', 'ai', 3)
        self.ini.set('default', 'human', 1)
        self.ini.set('default', 'name', 'Player')
        self.ini.set('default', 'cards', 7)
        self.ini.add_section('ai')
        self.ini.set('ai','levels','11111111')
        names = {1: 'Amy', 2: 'Theresa', 3:'Russell', 4:'Matthew',
5:'Richard', 6:'Susannah', 7:'Julia', 8:'John'}
        for num in names.keys():
            self.ini.set('ai',str(num),names[num])
        self.ini.write(gofishinifile)
        gofishinifile.close()

    def numtocard(self,num):

        if num % 4 == 0: return str(num/4 + 1) + 'S'
        elif (num - 1) % 4 == 0 : return str((num - 1)/4 + 1) + 'H'
        elif (num - 2) % 4 == 0 : return str((num - 2)/4 + 1) + 'D'
        elif (num - 3) % 4 == 0 : return str((num - 3)/4 + 1) + 'C'
    
if __name__ == '__main__':

    newfish = GoFish()

#
#cards.py
#

class bmdcard:

    def __init__(self, size=52, comp=None):

        self.cards = []
        self.deck = []
        for c in range(size):
            self.deck.append(c)
        self.cards = self.deck

    def deal(self, hands=[[4,7]], shuffles=3):

        for s in range(shuffles):
            self.shuffle()
        dealt=[]
        for h in hands:
            for i in range(hands[hands.index(h)][0]):
                dealt.append(self.cards[:hands[hands.index(h)][1]])
                self.cards = self.cards[hands[hands.index(h)][1]:]
            dealt.append(self.cards)
        self.cards=self.deck
        return dealt

    def shuffle(self):
        """Orignal code by Bruce Sass, as provided on Python Tutor
Mailing list"""

        import random

        half = len(self.cards)/2
        part1 = self.cards[:half]
        part2 = self.cards[half:]
        shuffled = []
        mingrp = 1
        maxgrp = 4
        while part1 or part2:
            if part1:
                for i in range(random.randrange(mingrp, 1 + min(maxgrp,
len(part1)))):
                    shuffled.append(part1.pop())
            if part2:
                for i in range(random.randrange(mingrp, 1 + min(maxgrp,
len(part2)))):
                    shuffled.append(part2.pop())

        self.cards = shuffled

#
#players.py
#

import random

class Player:

    def __init__(self,name):

        self.hand = []
        self.count = [0]*13
        self.name = name
        self.declared = []

    def removecard(self,card):

        self.hand.remove(card)
        self.count[card/4] += -1
        
    def receivecard(self,card):

        self.hand.append(card)
        self.count[card/4] += 1
        self.bookcheck()
        
    def declare(self, rank):

        self.declared.append(rank)
        for c in (rank*4,rank*4 + 1,rank*4 + 2,rank*4 + 3):
            self.removecard(c)
        self.count[rank] = 0
        
    def bookcheck(self):

        if max(self.count) == 4:
            self.declare(self.count.index(4))
        
class Human(Player):

    def cheese(self):

        print 'cheese'

class AI1(Player):

    def askcard(self, players):

        return self.count.index(max(self.count)), random.randrange(0,
players)
                    
#
#bmdutils.py - part of
#

def bmdmenu(options, prompt='Please select an option:'):

    choice = ''
    choices = {}
    for o in options:
        print o[0]

        for p in o[2]:
            choices[p] = o[1]

    while choice not in choices.keys():
        choice = raw_input(prompt)

    choices[choice]()

#
#end
#

Thankyou very much,

Russell
--
http://www.bigmaddrongo.com
President of York University Trampoline Club:
http://york.trampolining.net
Chair of The York Glee Singers:
http://www.gleesingers.co.uk