@@ -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}".\n GRYCommands: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:\n VPs=Victory points, Res=Resource cards, DCs=(Unplayed) development cards,\n Army=Number of knights (player with largest army has a star *),\n Up=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\n first 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