""" Roulette simulator; see http://thewizardofodds.com/ for rules and analysis """from random import *;from simlog import *;from casino import *;from simulator import *;class RouletteTable( GameTable ):	"Roulette Table: Keeps all bets"	def __init__( self ):		GameTable.__init__( self );		self.bets = {			"number 0":			Bet( "number 0", { 0:(35,1) } ),			"number 00":		Bet( "number 00",{ 0:(35,1) } ),			"even":				Bet( "even", { 0:(1,1) } ),			"odd":				Bet( "odd",  { 0:(1,1) } ),			"red":				Bet( "even", { 0:(1,1) } ),			"black":			Bet( "odd",  { 0:(1,1) } ),			"high":				Bet( "high", { 0:(1,1) } ),			"low":				Bet( "low",  { 0:(1,1) } ),			"col1":				Bet( "col1", { 0:(2,1) } ),			"col2":				Bet( "col2", { 0:(2,1) } ),			"col3":				Bet( "col3", { 0:(2,1) } ),			"grp1":				Bet( "grp1", { 0:(2,1) } ),			"grp2":				Bet( "grp2", { 0:(2,1) } ),			"grp3":				Bet( "grp3", { 0:(1,1) } )			};		# single number bets		for n in range( 1, 37 ):			self.bets["number %d"%(n)]= Bet( "number %d"%(n), { 0:(35,1) } );		# adjacent pairs		for n in range( 0, 12 ):			pair1= "pair %d%d" % (n*3+1, n*3+2);			pair2= "pair %d%d" % (n*3+2, n*3+3);			self.bets[pair1]= Bet( pair1, { 0:(17,1) } );			self.bets[pair2]= Bet( pair2, { 0:(17,1) } );		for n in range( 0, 11 ):			pair1= "pair %d%d" % (n*3+1, n*3+4);			pair2= "pair %d%d" % (n*3+2, n*3+5);			pair3= "pair %d%d" % (n*3+3, n*3+6);			self.bets[pair1]= Bet( pair1, { 0:(17,1) } );			self.bets[pair2]= Bet( pair2, { 0:(17,1) } );			self.bets[pair3]= Bet( pair3, { 0:(17,1) } );		# rows of 3		for n in range( 0, 12 ):			three= "three %d%d%d" % ( n*3+1, n*3+2, n*3+3 );			self.bets[three]= Bet( three, { 0:(11,1) } );		# groups of 4		for n in range( 0, 11 ):			quad1= "quad %d%d%d%d" % ( n*3+1, n*3+2, n*3+4, n*3+5 );			quad2= "quad %d%d%d%d" % ( n*3+2, n*3+3, n*3+5, n*3+6 );			self.bets[quad1]= Bet( quad1, { 0:(8,1) } );			self.bets[quad2]= Bet( quad2, { 0:(8,1) } );		# groups of 6		for n in range( 0, 11 ):			hex1= "hex %d%d%d%d%d%d" % ( n*3+1, n*3+2, n*3+3, n*3+4, n*3+5, n*3+6 );			self.bets[hex1]= Bet( hex1, { 0:(5,1) } );class RouletteGame ( CasinoGame ):	"The Roulette Game - bets held by a RouletteTable"	def __init__( self ):		CasinoGame.__init__( self );		self.table= RouletteTable();		self.rolls= [ ["number 00", "green"], [ "number 0", "green"] ];		for n in range(1,37):			if( self.red(n) ): color= "red";			else: color= "black";			if( self.even(n)): even=  "even";			else: even=  "odd";			if( n >= 18 ):     high= "high";			else: high= "low";			group= 1+int( (n-1)/12 );			column= 1+int( (n+2)%3 );			bets= ["number %d"%n, color, even, high, "grp%d"%group, "col%d"%column];			if( column != 3 ): bets.append( "pair %d%d" % (n,n+1) );			if( column != 1 ): bets.append( "pair %d%d" % (n-1,n) );			if( n < 34 ): bets.append( "pair %d%d" % (n,n+3) );			if( n > 3  ): bets.append( "pair %d%d" % (n-3,n) );			row= int( (n-1)/3 );			bets.append( "three %d%d%d" % (row*3+1,row*3+2,row*3+3) );			if( n < 33 ): bets.append( "quad %d%d%d%d" % (n, n+1, n+3, n+4) );			if( n > 1 and n < 34 ): bets.append( "quad %d%d%d%d" % (n-1, n, n+2, n+3) );			if( n > 3 and n < 36 ): bets.append( "quad %d%d%d%d" % (n-3, n-2, n, n+1) );			if( n > 4 ): bets.append( "quad %d%d%d%d" % (n-4, n-3, n-1, n) );			hex= int( (n-1)/6 );			bets.append( "hex %d%d%d%d%d%d" % (hex*6+1,hex*6+2,hex*6+3,hex*6+4,hex*6+5,hex*6+6) );			self.rolls.append( bets );		#print string.join( map( str, self.rolls ), "\n" );	def state( self ):		return self.roll;	def red( self, number ):		return number in [1,3,5,7,9,12,14,16,18,19,21,23,25,27,30,32,34,36];	def black( self, number ):		return number in [2,4,6,8,10,11,13,15,17,20,22,24,26,28,29,31,33,35];	def even( self, number ):		return number > 0 and int(number/2)*2 == number;	def odd( self, number ):		return number > 0 and int(number/2)*2 != number;	def payout( self, number ):		"Basic roulette payout"		number= int(self.roll[0][7:]);		self.log.msg( "game.roll", str(self.state()) );		for b in self.table.bets.keys():			if( b in self.roll ): self.table.win(b,number)			else: self.table.lose( b );	def play( self ):		"play 1 round of roulette"		cmd= self.table.player.startRound( self );		cmd.do( self );		Simlog().instance().msg( "game.start", str(cmd) );		self.roll= choice(self.rolls);		self.payout( self.roll );		self.table.player.endRound( self );class RoulettePlayer ( Player ):	"bet zero"	def __init__( self, limit ):		Player.__init__( self, limit );	def startRound( self, game ):		"place start-of-round bet"		Player.startRound( self, game );		return CommandBet( "zero", 1 );class RoulettePlayerRed ( Player ):	"bet red"	def __init__( self, limit ):		Player.__init__( self, limit );	def startRound( self, game ):		"place start-of-round bet"		Player.startRound( self, game );		return CommandBet( "red", 1 );class RoulettePlayerRedCount ( Player ):	"bet red after n blacks, Martingale"	def __init__( self, limit, wait ):		Player.__init__( self, limit );		self.wait= wait;		self.blackCount= 0;	def startRound( self, game ):		"place start-of-round bet"		Player.startRound( self, game );		if( self.blackCount >= self.wait ):			self.log.msg( "player.count", "count %d, wait %d" % (self.blackCount,self.wait) );			return CommandBet( "red", self.blackCount - self.wait + 1 );		return Command( "none" );	def endRound( self, game ):		"check game state to keep history"		color= None;		for a in game.state():			if( a == "black" ): color= a;		if( color == "black" ): self.blackCount += 1;		else: self.blackCount= 0;	def name( self ):		return self.__doc__ + "(n=%d,limit=%d)" % (self.wait,self.limit);class RoulettePlayerLastCol ( Player ):	"two columns which did NOT win on the last roll"	def __init__( self, limit ):		Player.__init__( self, limit );		self.lastColumn= None;	def startRound( self, game ):		"place start-of-round bets"		bets= CommandSequence();		Player.startRound( self, game );		for b in [ "col1", "col2", "col3" ]:			if( self.lastColumn != b ):				bets.addCommand( CommandBet( b, 1 ) );		return bets;	def endRound( self, game ):		"check game state to keep history"		self.lastColumn= None;		for a in game.state():			if( a[0:3] == "col" ): self.lastColumn= a;class RoulettePlayerWatchCol ( Player ):	"wait for column to lose 3 times"	def __init__( self, limit ):		Player.__init__( self, limit );		self.colCount= { "col1":0, "col2":0, "col3":0 };	def startRound( self, game ):		"place start-of-round bet"		bets= CommandSequence();		Player.startRound( self, game );		# bet on columns NOT winning in the last 3 plays		for b in [ "col1", "col2", "col3" ]:			if( self.colCount[b] >= 3 ): bets.addCommand( CommandBet( b, 1 ) );		return bets;	def endRound( self, game ):		"check game state to keep history"		column= None;		for a in game.state():			if( a[0:3] == "col" ): column= a;		if( column == None ):  self.colCount= { "col1":0, "col2":0, "col3":0 };		else:			for c in self.colCount.keys():				if( column != c ): self.colCount[c] += 1;			self.colCount[column]= 0;class RoulettePlayerFactory ( PlayerFactory ):	def __init__( self ):		PlayerFactory.__init__( self );	def newPlayer( self, name ):		if( name == "simple" ): return RoulettePlayer( 100 );		if( name == "red" ): return RoulettePlayerRed( 100 );		if( name == "red4" ): return RoulettePlayerRedCount( 100, 4 );		if( name == "red7" ): return RoulettePlayerRedCount( 100, 7 );		if( name == "red7sl" ): return RoulettePlayerRedCount( 20, 7 );		if( name == "lastcol" ): return RoulettePlayerLastCol( 100 );		if( name == "watchcol" ): return RoulettePlayerWatchCol( 100 );		else: print "unknown", name;def main():	#(log,n)= ( Simlog().instance().summary(), 100 );	(log,n)= ( Simlog().instance().detail(), 1 );	a= Analyzer();	s= Simulator( RoulettePlayerFactory().playerSet( ["lastcol","watchcol","red7","red7sl"] ), RouletteGame(), a );	s.generate( n, 100 );	a.report();def profile():	import profile;	profile.run( 'main()' );if( __name__ == "__main__" ):	main();