545 main.py
@@ -13,19 +13,88 @@
'1': u"\u001b[38;5;26m",
'2': u"\u001b[38;5;202m",
'3': u"\u001b[38;5;14m",
'b_white': u"\u001b[47m"
'b_white': u"\u001b[47m",
'grey': u"\u001b[38;5;244m",
'ocean': u"\u001b[38;5;234m",
'b0': u"\u001b[48;5;1m",
'b1': u"\u001b[48;5;26m",
'b2': u"\u001b[48;5;202m",
'b3': u"\u001b[48;5;14m"
}
DEBUG = True

class Cmd(object):
def __init__(self, name, arg_desc, func=None, isDevCmd=False):
self.name = name
self.argc = len(arg_desc)
self.argv = arg_desc
self.func = func
self.isDevCmd = isDevCmd

def help_text(self):
msg = u"Usage: " + self.name + " "
for a in range(self.argc):
msg += "$" + str(a+1) + " "
msg += u"\t\u001b[38;5;244m"
for a in range(self.argc):
msg += str(a+1) + ": " + self.argv[a] + " "
msg += u"\u001b[0m"
if self.isDevCmd:
msg += " (Note: this is a developer command)"

class Catan(object):
return msg

def wrong_args_text(self):
return u'Command "%s" requires %s arguments. For help, type "help".' % (self.name, str(self.argc))

def do(self, args):
if self.func == None:
return ""
return self.func(*args)

class Die(object):
def __init__(self, initialValue=0):
self.value = 0

def __repr__(self):
return str(self.value)

def roll(self):
self.value = random.randint(1,6)

class Dice(object):
def __init__(self):
self.dice = [ Die(), Die() ]

def get_value(self):
return self.dice[0].value + self.dice[1].value

def roll(self):
self.dice[0].roll()
self.dice[1].roll()

return self.get_value()

def view(self,i):
return self.dice[i]

class Catan(object):
def __init__(self, numHumans, numCPUs):
self.vpGoal = 10

self.dice = Dice()
self.hexes = []
self.nodes = []
self.roads = []
self.conns = []

self.numHumans = numHumans
self.numCPUs = numCPUs
self.players = []

self.generate_board()
self.currentPlayer = None
self.hasLargestArmy = None
self.hasLongestRoad = None
self.isFirstTurn = True

self.h_index = {
'd11': 5,
@@ -227,15 +296,66 @@ def __init__(self):
'v26': 70,
'v30': 71
}
self.hex_dots = { 0:0, 2:1, 3:2, 4:3, 5:4, 6:5, 8:5, 9:4, 10:3, 11:2, 12:1 }

self.cmds = {
'info': Cmd('info', ["coordinate (e.g. E24)"], self.cmd_info),
'clear': Cmd('clear', []),
'help': Cmd('help', ["command (e.g. info)"]),
'abbrev': Cmd('abbrev', [], self.cmd_abbrev),
'n': Cmd('n', ["coordinate (e.g. E24)"], self.cmd_neighbors, True),
'roll': Cmd('roll', [], self.roll),
'reset': Cmd('reset', [], self.reseed, True),
'settle': Cmd('settle', ["coordinate (e.g. E24)"], self.cmd_settle),
'pave': Cmd('pave', ["coordinate (e.g. F26)"], self.cmd_pave),
'setname': Cmd('setname', ["name (8 chars or less)"], self.cmd_setname),
'setcpuname': Cmd('setcpuname', ["id (e.g. '4' for 'CPU 4')","name (8 chars or less)"], self.cmd_setcpuname)
}

self.devCardDeck = []

self.reseed()

def take_first_turn(self):
for p in self.players:
self.currentPlayer = p
p.settle()
for p in self.players[::-1]:
self.currentPlayer = p
p.settle()

self.isFirstTurn = False
self.view('awaiting command')

def roll(self):
diceValue = self.dice.roll()

if diceValue == 7:
return "Robber!!"
else:
for h in self.hexes:
if h.diceValue == diceValue and h.isBlocked == False:
for n in h.get_adj_nodes():
if n.owner != None:
n.owner.resCards[h.resource] += 1

if diceValue in {8,11}:
return "You rolled an %d." % diceValue
return "You rolled a %d." % diceValue

def reseed(self):
self.generate_board()
self.generate_players()
self.take_first_turn()

return "** RESEED **"

def generate_board(self):
self.hexes = []
self.nodes = []
self.roads = []
self.conns = []

self.players = []

diceValues = [2,3,3,4,4,5,5,6,6,8,8,9,9,10,10,11,11,12]
random.shuffle(diceValues)
resources = ['desert', 'wheat', 'wheat', 'wheat', 'wheat', 'sheep', 'sheep', 'sheep', 'sheep', 'brick', 'brick', 'brick', 'wood', 'wood', 'wood', 'wood', 'ore', 'ore', 'ore']
@@ -279,85 +399,152 @@ def generate_board(self):
conn_node.add_conn(self.conns[i])
conn_hex.add_conn(self.conns[i])

# make the Players
for i in range(4):
self.players.append( Player(i) )
def generate_players(self):
self.players = [ Human(i, self) for i in range(self.numHumans) ]
self.players += [ CPU(self.numHumans + i, self) for i in range(self.numCPUs)]
random.shuffle(self.players)

def handle_input(self, in_msg="", msg=None, options={}):
persistentOptions = {'info', 'clear', 'help', 'abbrev', 'setname', 'setcpuname'}

def handle_input(self, args):
args = args.split(' ')
if msg != None:
self.view( in_msg + "\n" + self.printf(msg) )
else:
self.view( in_msg )
args = raw_input('> ').split(' ')
cmd = args[0]

if cmd == 'help':
if len(args) == 1:
msg = u'For help with a specific command, type "help {cmd}".\n\u001b[38;5;244mavailable commands:\u001b[0m help, info'
elif len(args) == 2:
if args[1] == 'help':
msg = u"Usage: help $1\t\u001b[38;5;244m1: command (e.g. info)\u001b[0m"
elif args[1] == 'info':
msg = u"Usage: info $1\t\u001b[38;5;244m1: coordinate (e.g. E24)\u001b[0m"
else:
msg = '%s: Unrecognized command. For a list of commands, type "help".' % args[1]
else:
msg = 'Command "help" requires one or two arguments. For help, type "help".'
if cmd in self.cmds.keys():
cmd = self.cmds[cmd]

if options != {} and cmd.name not in options and cmd.name not in persistentOptions:
msg = u'%s: Could not execute. GRYCurrently available commands:PLY ' % cmd.name
for opt in options:
msg += opt + ", "
msg += "ReS"
for opt in persistentOptions:
msg += opt + ", "

elif cmd == 'info':
if len(args) != 2:
msg = 'Command "info" requires one argument. For help, type "help info".'
else:
msg = self.cmd_info(args[1])
elif cmd == '!n': # hide this command from end users (i.e. not in help menus)
if len(args) != 2:
msg = 'Command "!n" requires one argument.'
else:
msg = self.cmd_neighbors(args[1])
elif cmd == '!reset': # hide this command from end users (i.e. not in help menus)
self.generate_board()
msg = "** regenerated board **"

if cmd.name == 'help':
keys = sorted(self.cmds.keys())
if len(args) == 1:
msg = u'For help with a specific command, type "help {command}".\nGRYCommands:ReS '
for key in keys:
if DEBUG == True or self.cmds[key].isDevCmd == False:
msg += self.cmds[key].name + ", "
else:
if args[1] in keys:
cmd = self.cmds[args[1]]
msg = cmd.help_text()
else:
msg = '%s: Unrecognized command. For a list of commands, type "help".' % args[1]
if options == {}:
return

else:
if len(args) - 1 == cmd.argc:
if DEBUG == True or cmd.isDevCmd == False:
msg = cmd.do(args[1:])
if msg == False:
msg = "Error executing %s. Make sure all arguments are correct." % cmd.name
else:
if options == {} or cmd.name in options:
return
else:
msg = "%s: Could not execute because developer commands are disabled for this session." % cmd.name
else:
msg = cmd.wrong_args_text()

else:
msg = '%s: Unrecognized command. For a list of commands, type "help".' % cmd

return msg
self.handle_input( in_msg, msg, options )

def printf(self, line):
line = line.replace(u"ReS", COLORS['reset'])
line = line.replace(u"GRY", COLORS['grey'])
line = line.replace(u"RED", COLORS['0'])
line = line.replace(u"BLU", COLORS['1'])
line = line.replace(u"YEL", COLORS['wheat'])
line = line.replace(u"LGR", COLORS['sheep'])
line = line.replace(u"ORA", COLORS['brick'])
line = line.replace(u"DGR", COLORS['wood'])
line = line.replace(u"ORE", COLORS['ore'])
line = line.replace(u"OCE", COLORS['ocean'])
line = line.replace(u"PLY", self.currentPlayer.color)

return line

def view(self, msg):
os.system('cls' if os.name == 'nt' else 'clear')

s = u"""\u001b[38;5;244m/================================ [ CaTEXT ] ==================================\\
0 1 2 3 4
01234567890123456789012345678901234567890\u001b[0m\t .___________________. \u001b[38;5;244m
A\u001b[38;5;27m ~~~~~~~~~~~ \u001b[0m%s\u001b[38;5;27m ~~~~~ \u001b[0m%s\u001b[38;5;27m ~~~~~ \u001b[0m%s\u001b[38;5;27m ~~~~~~~~~~~ \u001b[38;5;244mA\u001b[0m |__KEY______________| \u001b[38;5;244m
B\u001b[38;5;27m ~~~~~~~~~ \u001b[0m%s %s\u001b[38;5;27m ~ \u001b[0m%s %s\u001b[38;5;27m ~ \u001b[0m%s %s\u001b[38;5;27m ~~~~~~~~~ \u001b[38;5;244mB\u001b[0m | %s %s | \u001b[38;5;244m
C\u001b[38;5;27m ~~~~~~~ \u001b[0m%s %s %s %s\u001b[38;5;27m ~~~~~~~ \u001b[38;5;244mC\u001b[0m | %s %s | \u001b[38;5;244m
D\u001b[38;5;27m ~~~~~~~ \u001b[0m| %2s | %2s | %2s |\u001b[38;5;27m ~~~~~~~ \u001b[38;5;244mD\u001b[0m | %s %s | \u001b[38;5;244m
E\u001b[38;5;27m ~~~~~~~ \u001b[0m%s %s %s %s\u001b[38;5;27m ~~~~~~~ \u001b[38;5;244mE\u001b[0m |______%s_______| \u001b[38;5;244m
F\u001b[38;5;27m ~~~~~ \u001b[0m%s %s %s %s %s %s %s %s\u001b[38;5;27m ~~~~~ \u001b[38;5;244mF\u001b[0m \u001b[38;5;244m
G\u001b[38;5;27m ~~~ \u001b[0m%s %s %s %s %s\u001b[38;5;27m ~~~ \u001b[38;5;244mG\u001b[0m ._________________________. \u001b[38;5;244m
H\u001b[38;5;27m ~~~ \u001b[0m| %2s | %2s | %2s | %2s |\u001b[38;5;27m ~~~ \u001b[38;5;244mH\u001b[0m |__NAME_____Pts_Cards_DCs_| \u001b[38;5;244m
I\u001b[38;5;27m ~~~ \u001b[0m%s %s %s %s %s\u001b[38;5;27m ~~~ \u001b[38;5;244mI\u001b[0m | %s %s %s %s | \u001b[38;5;244m
J\u001b[38;5;27m ~ \u001b[0m%s %s %s %s %s %s %s %s %s %s\u001b[38;5;27m ~ \u001b[38;5;244mJ\u001b[0m | %s %s %s %s | \u001b[38;5;244m
K\u001b[0m %s %s %s %s %s %s \u001b[38;5;244mK\u001b[0m | %s %s %s %s | \u001b[38;5;244m
L\u001b[0m | %2s | %2s | %2s | %2s | %2s | \u001b[38;5;244mL\u001b[0m | %s %s %s %s | \u001b[38;5;244m
M\u001b[0m %s %s %s %s %s %s \u001b[38;5;244mM\u001b[0m |_________________________| \u001b[38;5;244m
N\u001b[38;5;27m ~ \u001b[0m%s %s %s %s %s %s %s %s %s %s\u001b[38;5;27m ~ \u001b[38;5;244mN
O\u001b[38;5;27m ~~~ \u001b[0m%s %s %s %s %s\u001b[38;5;27m ~~~ \u001b[38;5;244mO
P\u001b[38;5;27m ~~~ \u001b[0m| %2s | %2s | %2s | %2s |\u001b[38;5;27m ~~~ \u001b[38;5;244mP
Q\u001b[38;5;27m ~~~ \u001b[0m%s %s %s %s %s\u001b[38;5;27m ~~~ \u001b[38;5;244mQ
R\u001b[38;5;27m ~~~~~ \u001b[0m%s %s %s %s %s %s %s %s\u001b[38;5;27m ~~~~~ \u001b[38;5;244mR
S\u001b[38;5;27m ~~~~~~~ \u001b[0m%s %s %s %s\u001b[38;5;27m ~~~~~~~ \u001b[38;5;244mS
T\u001b[38;5;27m ~~~~~~~ \u001b[0m| %2s | %2s | %2s |\u001b[38;5;27m ~~~~~~~ \u001b[38;5;244mT
U\u001b[38;5;27m ~~~~~~~ \u001b[0m%s %s %s %s\u001b[38;5;27m ~~~~~~~ \u001b[38;5;244mU
V\u001b[38;5;27m ~~~~~~~~~ \u001b[0m%s %s\u001b[38;5;27m ~ \u001b[0m%s %s\u001b[38;5;27m ~ \u001b[0m%s %s\u001b[38;5;27m ~~~~~~~~~ \u001b[38;5;244mV
W\u001b[38;5;27m ~~~~~~~~~~~ \u001b[0m%s\u001b[38;5;27m ~~~~~ \u001b[0m%s\u001b[38;5;27m ~~~~~ \u001b[0m%s\u001b[38;5;27m ~~~~~~~~~~~ \u001b[38;5;244mW
01234567890123456789012345678901234567890
0 1 2 3 4
\\==============================================================================/\u001b[0m\t
%s"""

print s % ( self.nodes[0], self.nodes[1], self.nodes[2], self.roads[0], self.roads[1], self.roads[2], self.roads[3], self.roads[4], self.roads[5], (COLORS['desert'] + u'desert' + COLORS['reset']), (COLORS['ore'] + 'ore' + COLORS['reset']), self.nodes[3], self.nodes[4], self.nodes[5], self.nodes[6], (COLORS['wheat'] + 'wheat' + COLORS['reset']), (COLORS['wood'] + 'wood' + COLORS['reset']), self.hexes[5], self.hexes[6], self.hexes[7], (COLORS['sheep'] + 'sheep' + COLORS['reset']), (COLORS['brick'] + 'brick' + COLORS['reset']), self.nodes[7], self.nodes[8], self.nodes[9], self.nodes[10], (COLORS['black'] + COLORS['b_white'] + 'robber' + COLORS['reset']), self.roads[6], self.roads[7], self.roads[8], self.roads[9], self.roads[10], self.roads[11], self.roads[12], self.roads[13], self.nodes[11], self.nodes[12], self.nodes[13], self.nodes[14], self.nodes[15], self.hexes[10], self.hexes[11], self.hexes[12], self.hexes[13], self.nodes[16], self.nodes[17], self.nodes[18], self.nodes[19], self.nodes[20], (COLORS['0'] + str(self.players[0]).ljust(8)), str(self.players[0].score).rjust(2), str(len(self.players[0].resCards)).rjust(2), (str(len(self.players[0].devCards)).rjust(2) + COLORS['reset']), self.roads[14], self.roads[15], self.roads[16], self.roads[17], self.roads[18], self.roads[19], self.roads[20], self.roads[21], self.roads[22], self.roads[23], (COLORS['1'] + str(self.players[1]).ljust(8)), str(self.players[1].score).rjust(2), str(len(self.players[1].resCards)).rjust(2), (str(len(self.players[1].devCards)).rjust(2) + COLORS['reset']), self.nodes[21], self.nodes[22], self.nodes[23], self.nodes[24], self.nodes[25], self.nodes[26], (COLORS['2'] + str(self.players[2])).ljust(8), str(self.players[2].score).rjust(2), str(len(self.players[2].resCards)).rjust(2), (str(len(self.players[2].devCards)).rjust(2) + COLORS['reset']), self.hexes[16], self.hexes[17], self.hexes[18], self.hexes[19], self.hexes[20], (COLORS['3'] + str(self.players[3]).ljust(8)), str(self.players[3].score).rjust(2), str(len(self.players[3].resCards)).rjust(2), (str(len(self.players[3].devCards)).rjust(2) + COLORS['reset']), self.nodes[27], self.nodes[28], self.nodes[29], self.nodes[30], self.nodes[31], self.nodes[32], self.roads[24], self.roads[25], self.roads[26], self.roads[27], self.roads[28], self.roads[29], self.roads[30], self.roads[31], self.roads[32], self.roads[33], self.nodes[33], self.nodes[34], self.nodes[35], self.nodes[36], self.nodes[37], self.hexes[23], self.hexes[24], self.hexes[25], self.hexes[26], self.nodes[38], self.nodes[39], self.nodes[40], self.nodes[41], self.nodes[42], self.roads[34], self.roads[35], self.roads[36], self.roads[37], self.roads[38], self.roads[39], self.roads[40], self.roads[41], self.nodes[43], self.nodes[44], self.nodes[45], self.nodes[46], self.hexes[29], self.hexes[30], self.hexes[31], self.nodes[47], self.nodes[48], self.nodes[49], self.nodes[50], self.roads[42], self.roads[43], self.roads[44], self.roads[45], self.roads[46], self.roads[47], self.nodes[51], self.nodes[52], self.nodes[53], msg)

def isGameOver(self):
board = u""

board += self.printf( u"GRY/================================ [ CaTEXT ] ==================================\\\n")
board += self.printf( u" 0 1 2 3 4\n" )
board += self.printf( u" 01234567890123456789012345678901234567890ReS .___________________________.GRY\n" )
board += self.printf( u" AOCE ~~~~~~~~~~~ReS%sOCE~~~~~ReS%sOCE~~~~~ReS%sOCE~~~~~~~~~~~ GRYAReS |__NAME____VPs_Res_DCs_Army_|GRY\n" % (self.nodes[0], self.nodes[1], self.nodes[2]) )
board += self.printf( u" BOCE ~~~~~~~~~ReS%s %sOCE~ReS%s %sOCE~ReS%s %sOCE~~~~~~~~~ GRYBReS |%s|GRY\n" % (self.roads[0], self.roads[1], self.roads[2], self.roads[3], self.roads[4], self.roads[5], self.players[0].print_line()) )
board += self.printf( u" COCE ~~~~~~~ReS%s %s %s %sOCE~~~~~~~ GRYCReS |%s|GRY\n" % (self.nodes[3], self.nodes[4], self.nodes[5], self.nodes[6], self.players[1].print_line()) )
board += self.printf( u" DOCE ~~~~~~~ReS%s %s %s %s %s %s %sOCE~~~~~~~ GRYDReS |%s|GRY\n" % (self.roads[6], self.hexes[5], self.roads[7], self.hexes[6], self.roads[8], self.hexes[7], self.roads[9], self.players[2].print_line()) )
board += self.printf( u" EOCE ~~~~~~~ReS%s %s %s %sOCE~~~~~~~ GRYEReS |%s|GRY\n" % (self.nodes[7], self.nodes[8], self.nodes[9], self.nodes[10], self.players[3].print_line()) )
board += self.printf( u" FOCE ~~~~~ReS%s %s %s %s %s %s %s %sOCE~~~~~ GRYFReS |___________________________|GRY\n" % (self.roads[10], self.roads[11], self.roads[12], self.roads[13], self.roads[14], self.roads[15], self.roads[16], self.roads[17]) )
board += self.printf( u" GOCE ~~~ReS%s %s %s %s %sOCE~~~ GRYGReS ._. ._.GRY\n" % (self.nodes[11], self.nodes[12], self.nodes[13], self.nodes[14], self.nodes[15]) )
board += self.printf( u" HOCE ~~~ReS%s %s %s %s %s %s %s %s %sOCE~~~ GRYHReS Dice: |%s| |%s|GRY\n" % (self.roads[18], self.hexes[10], self.roads[19], self.hexes[11], self.roads[20], self.hexes[12], self.roads[21], self.hexes[13], self.roads[22],self.dice.view(0),self.dice.view(1)) )
board += self.printf( u" IOCE ~~~ReS%s %s %s %s %sOCE~~~ GRYI\n" % (self.nodes[16], self.nodes[17], self.nodes[18], self.nodes[19], self.nodes[20]) )
board += self.printf( u" JOCE ~ReS%s %s %s %s %s %s %s %s %s %sOCE~ GRYJ PLY.___________________________.GRY\n" % (self.roads[23], self.roads[24], self.roads[25], self.roads[26], self.roads[27], self.roads[28], self.roads[29], self.roads[30], self.roads[31], self.roads[32]) )
board += self.printf( u" KReS%s %s %s %s %s %sGRYK PLY|__RESOURCES_________Num____|GRY\n" % (self.nodes[21], self.nodes[22], self.nodes[23], self.nodes[24], self.nodes[25], self.nodes[26]) )
board += self.printf( u" LReS%s %s %s %s %s %s %s %s %s %s %sGRYL PLY|YEL Wheat %s PLY|GRY\n" % (self.roads[33], self.hexes[16], self.roads[34], self.hexes[17], self.roads[35], self.hexes[18], self.roads[36], self.hexes[19], self.roads[37], self.hexes[20], self.roads[38], self.currentPlayer.count('wheat')) )
board += self.printf( u" MReS%s %s %s %s %s %sGRYM PLY|LGR Sheep %s PLY|GRY\n" % (self.nodes[27], self.nodes[28], self.nodes[29], self.nodes[30], self.nodes[31], self.nodes[32], self.currentPlayer.count('sheep')) )
board += self.printf( u" NOCE ~ReS%s %s %s %s %s %s %s %s %s %sOCE~ GRYN PLY|ORA Brick %s PLY|GRY\n" % (self.roads[39], self.roads[40], self.roads[41], self.roads[42], self.roads[43], self.roads[44], self.roads[45], self.roads[46], self.roads[47], self.roads[48], self.currentPlayer.count('brick')) )
board += self.printf( u" OOCE ~~~ReS%s %s %s %s %sOCE~~~ GRYO PLY|DGR Wood %s PLY|GRY\n" % (self.nodes[33], self.nodes[34], self.nodes[35], self.nodes[36], self.nodes[37], self.currentPlayer.count('wood')) )
board += self.printf( u" POCE ~~~ReS%s %s %s %s %s %s %s %s %sOCE~~~ GRYP PLY|ORE Ore %s PLY|GRY\n" % (self.roads[49], self.hexes[23], self.roads[50], self.hexes[24], self.roads[51], self.hexes[25], self.roads[52], self.hexes[26], self.roads[53], self.currentPlayer.count('ore')) )
board += self.printf( u" QOCE ~~~ReS%s %s %s %s %sOCE~~~ GRYQ PLY|___________________________|GRY\n" % (self.nodes[38], self.nodes[39], self.nodes[40], self.nodes[41], self.nodes[42]) )
board += self.printf( u" ROCE ~~~~~ReS%s %s %s %s %s %s %s %sOCE~~~~~ GRYR PLY|__DEV CARDS_____Up__Down___|GRY\n" % (self.roads[54], self.roads[55], self.roads[56], self.roads[57], self.roads[58], self.roads[59], self.roads[60], self.roads[61]) )
board += self.printf( u" SOCE ~~~~~~~ReS%s %s %s %sOCE~~~~~~~ GRYS PLY|YEL VPs %s %s PLY|GRY\n" % (self.nodes[43], self.nodes[44], self.nodes[45], self.nodes[46], self.currentPlayer.count('vp','up'), self.currentPlayer.count('vp','down')) )
board += self.printf( u" TOCE ~~~~~~~ReS%s %s %s %s %s %s %sOCE~~~~~~~ GRYT PLY|RED Knights %s %s PLY|GRY\n" % (self.roads[62], self.hexes[29], self.roads[63], self.hexes[30], self.roads[64], self.hexes[31], self.roads[65], self.currentPlayer.count('knight','up'), self.currentPlayer.count('knight','down')) )
board += self.printf( u" UOCE ~~~~~~~ReS%s %s %s %sOCE~~~~~~~ GRYU PLY|DGR YoPs %s %s PLY|GRY\n" % (self.nodes[47], self.nodes[48], self.nodes[49], self.nodes[50], self.currentPlayer.count('yop','up'), self.currentPlayer.count('yop','down')) )
board += self.printf( u" VOCE ~~~~~~~~~ReS%s %sOCE~ReS%s %sOCE~ReS%s %sOCE~~~~~~~~~ GRYV PLY|DGR Monopolies %s %s PLY|GRY\n" % (self.roads[66], self.roads[67], self.roads[68], self.roads[69], self.roads[70], self.roads[71], self.currentPlayer.count('monopoly','up'), self.currentPlayer.count('monopoly','down')) )
board += self.printf( u" WOCE ~~~~~~~~~~~ReS%sOCE~~~~~ReS%sOCE~~~~~ReS%sOCE~~~~~~~~~~~ GRYW PLY|DGR Road Builders %s %s PLY|GRY\n" % (self.nodes[51], self.nodes[52], self.nodes[53], self.currentPlayer.count('rb','up'), self.currentPlayer.count('rb','down')) )
board += self.printf( u" 01234567890123456789012345678901234567890 PLY|___________________________|GRY\n" % () )
board += self.printf( u" 0 1 2 3 4 \n" % () )
board += self.printf( u"\\==============================================================================/ReS\t\n" )
board += self.printf( u"%s" % msg )

print board

def is_game_over(self):
for player in self.players:
if player.score >= self.vpGoal:
print "%s wins!" % player.name
exit()

def checkLongestRoad(self):
if self.hasLongestRoad != None:
currentHolder = self.hasLongestRoad
currentLongestRoad = currentHolder.longestRoad
else:
currentLongestRoad = 0
for player in self.players:
if player.longestRoad > currentLongestRoad:
currentHolder = player
currentLongestRoad = currentHolder.longestRoad
if currentLongestRoad > 4:
if currentHolder != self.hasLongestRoad:
currentHolder.hasLongestRoad = True
currentHolder.score += 2
if self.hasLongestRoad != None:
self.hasLongestRoad.hasLongestRoad = False
self.hasLongestRoad.score -= 2
self.hasLongestRoad = currentHolder
self.is_game_over()

def get_player_by_id(self, i):
for p in self.players:
if p.num == i:
return p
return False

def lookup(self, coord):
@@ -407,27 +594,137 @@ def cmd_neighbors(self, coord):
s += "}"
return s

def cmd_abbrev(self):
return "List of abbreviations:\nVPs=Victory points, Res=Resource cards, DCs=(Unplayed) development cards,\nArmy=Number of knights (player with largest army has a star *),\nUp=Unplayed development cards, Down=Played development cards"

def cmd_settle(self, coord):
node = self.lookup(coord)
if node == False or type(node) != type(self.nodes[0]):
return False
if node.settle(self.currentPlayer) == False:
return False

def cmd_pave(self, coord):
road = self.lookup(coord)
if road == False or type(road) != type(self.roads[0]):
return False
if road.pave(self.currentPlayer) == False:
return False
return self.currentPlayer.add_road(road)

def cmd_setname(self, name):
self.currentPlayer.name = name[:8]

def cmd_setcpuname(self, i, name):
p = self.get_player_by_id(int(i)-1)
if p != False:
if type(p) == type(CPU(0, self)):
msg = "Successfully changed %s%sReS to %s%sReS" % (p.color, p.name, p.color, name[:8])
p.name = name[:8]
return msg
return False

class Player(object):
def __init__(self, num):
def __init__(self, num, catan):
self.num = num
self.score = 0
self.resCards = []
self.devCards = []
self.resCards = { 'wheat':0, 'sheep':0, 'brick':0, 'wood':0, 'ore':0 } # resource cards
self.devCardsU = { 'vp':0, 'knight':0, 'yop':0, 'monopoly':0, 'rb':0 } # played
self.devCardsP = { 'vp':0, 'knight':0, 'yop':0, 'monopoly':0, 'rb':0 } # unplayed
self.numKnights = 0
self.hasLargestArmy = False
self.color = COLORS[str(num)]
self.bcolor = COLORS['b' + str(num)]
self.name = ''
self.isHuman = False
self.catan = catan
self.settlements = []
self.roads = []
self.longestRoad = 0
self.hasLongestRoad = False

def print_line(self):
return "%s %s %s %s %s %s %s" % (self.color, self.name.ljust(8), self.f(self.score), self.total(self.resCards), self.total(self.devCardsU), self.f(self.numKnights), COLORS['reset'])

def total(self, dic):
acc = 0
for key in dic.keys():
acc += dic[key]
return self.f(acc)

def f(self, num, rjust=2): # format
return str(num).rjust(rjust)

def count(self, res, within='resources'):
if within == 'up':
dic = self.devCardsU
elif within == 'down':
dic = self.devCardsP
else:
dic = self.resCards
return str(dic[res]).rjust(2)

def __repr__(self):
return u"Player %d" % (self.num + 1)
def calc_longest_road(self):
longestRoad = 0
self.longestRoad = longestRoad
self.catan.checkLongestRoad()

def add_settlement(self, node):
self.score += 1
self.settlements.append(node)

def add_road(self, road):
self.roads.append(road)
self.calc_longest_road()

class Human(Player):
def __init__(self, num, catan):
Player.__init__(self, num, catan)
self.isHuman = True
self.name = "Player " + str(self.num + 1)

def settle(self):
self.catan.handle_input( u"PLY%s please choose a settlement (settle $1).ReS" % self.name, None, {'settle'} )
if self.catan.isFirstTurn:
self.catan.handle_input( u"PLY%s please choose a road (pave $1).ReS" % self.name, None, {'pave'})

class CPU(Player):
def __init__(self, num, catan):
Player.__init__(self, num, catan)
self.name = "CPU " + str(self.num + 1)

def settle(self):
bestNode = None
bestTotal = 0
for node in self.catan.nodes:
if node.isSettleable:
thisTotal = 0
for adj_hex in node.get_adj_hexes():
thisTotal += self.catan.hex_dots[adj_hex.diceValue]
if thisTotal > bestTotal:
bestNode = node
bestTotal = thisTotal
bestNode.settle(self)

if self.catan.isFirstTurn:
self.pave(bestNode)

def pave(self, restrict=None):
if self.catan.isFirstTurn:
r = random.choice(self.settlements[-1].roads)
r.pave(self)

class Vertex(object):
def __init__(self, num):
self.num = num
self.roads = set()
self.conns = set()
self.roads = []
self.conns = []

def add_road(self, road):
self.roads.add(road)
self.roads.append(road)

def add_conn(self, conn):
self.conns.add(conn)
self.conns.append(conn)

class Hex(Vertex):
def __init__(self, num, isOcean, diceValue, resource):
@@ -462,23 +759,30 @@ def show_info(self, coord):
s += COLORS['reset'] + " }"
return s

def get_adj_nodes(self):
nodes = []
for c in self.conns:
nodes.append(c.vertices[0])
return nodes

class Node(Vertex):
def __init__(self, num):
Vertex.__init__(self, num)
self.owner = None
self.isCity = False
self.isSettleable = True

def __repr__(self):
s = u""
if self.owner != None:
s += COLORS[str(self.owner)]
s += self.owner.bcolor
if self.isCity:
s += u"0"
s += u" C "
else:
s += u"o"
s += u" s "
s += COLORS['reset']
else:
s += u"."
s += u" . "
return s

def show_info(self, coord):
@@ -492,33 +796,84 @@ def show_info(self, coord):
s += "YES"
else:
s += "NO"
s += COLORS['reset'] + ", is-settleable: " + COLORS['b_white'] + COLORS['black']
if self.isSettleable:
s += "YES"
else:
s += "NO"
s += COLORS['reset'] + " }"
return s

def settle(self, player):
if self.isSettleable:
self.owner = player
self.isSettleable = False
for adj_node in self.get_adj_nodes():
adj_node.isSettleable = False
player.add_settlement(self)
return True

return False

def make_city(self):
self.isCity = True

def get_adj_nodes(self):
nodes = []
for r in self.roads:
if r.vertices[0].num != self.num:
nodes.append(r.vertices[0])
else:
nodes.append(r.vertices[1])
return nodes

def get_adj_hexes(self):
hexes = []
for c in self.conns:
hexes.append(c.vertices[1])
return hexes

class Edge(object):
def __init__(self, num):
self.num = num
self.vertices = set()
self.vertices = []

def set_vertices(self,u,v):
self.vertices = {u,v}
self.vertices = [u,v]

class Road(Edge):
def __init__(self, num):
Edge.__init__(self, num)
self.owner = None

def pave(self, player):
if self.owner == None:
if player.catan.isFirstTurn:
if self in player.settlements[-1].roads: # check if adjacent to most recently placed city
self.owner = player
player.add_road(self)
return True
else:
for r in player.roads:
if self.calc_distance(r) <= 1: # check if adjacent to any other built roads
self.owner = player
player.add_road(self)
return True

return False

def __repr__(self):
s = u""
if self.owner != None:
s += COLORS[str(self.owner)]
if (self.num % 2 and self.num < 24) or ( self.num % 2 == 0 and self.num >= 24):
s += "\\"
s += self.owner.bcolor
if self.num in {0,2,4,10,12,14,16,23,25,27,29,31,40,42,44,46,48,55,57,59,61,67,69,71}:
s += " / "
elif self.num in {1,3,5,11,13,15,17,24,26,28,30,32,39,41,43,45,47,54,56,58,60,66,68,70}:
s += " \\ "
elif self.num in {6,7,8,9,18,19,20,21,22,33,34,35,36,37,38,49,50,51,52,53,62,63,64,65}:
s += " | "
else:
s += "/"
return "?"
s += COLORS['reset']
return s

@@ -539,15 +894,11 @@ def __repr__(self):
return "Connection(%s)" % ("<-->".join(str(e) for e in self.vertices))

def main():
catan = Catan()
catan.view('Welcome to CaTEXT, a text-based Catan game for your terminal! If this is your\nfirst time, try typing "help".')

while catan.isGameOver() != True:

args = raw_input(': ')
msg = catan.handle_input(args)
catan = Catan(1,3)
#catan.view('Welcome to CaTEXT, a text-based Catan game for your terminal! If this is your\nfirst time, try typing "help".')

catan.view(msg)
while catan.is_game_over() != True:
pass

return 0