# board.py - Classes for simulating "The Settlers of Catan"
#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
# 97-02-27 ct7 Original version.
# 97-03-06 ct7 Split Board into multiple classes
#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

import whrandom

from pieces import *

#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

Odds = { 2:1, 3:2, 4:3, 5:4, 6:5, 7:6, 8:5, 9:4, 10:3, 11:2, 12:1 }

#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
# Functions for random (but reproducible) numbers
#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

def Randomize( seed ):

	if seed:
		s1 = 255 & (seed >> 16)
		s2 = 255 & (seed >> 8)
		s3 = 255 & seed
		whrandom.seed( s1, s2, s3 )
		return seed
	else:
		s1,s2,s3 = whrandom._inst._seed
		return (s1 << 16) + (s2 <<8) + s3

#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

Random = whrandom.randint

#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

def Shuffle( array ):

	a = array[:]

	l = len( a )
	for i in range(7):
		for left in range( l ):
			right = Random( 0, l-1 )
			a[left],a[right] = a[right],a[left]

	return a

#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
# Order of hexes and spots around a given hex or spot
#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

CntrClock = [ ( 0,-1),( 1,-1),( 1, 0),( 0, 1),(-1, 1),(-1, 0),( 0,-1) ]
Clockwise = [ ( 0,-1),(-1, 0),(-1, 1),( 0, 1),( 1, 0),( 1,-1),( 0,-1) ]

#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
# The Board class is responsible for placing hexes and spots within a
# two-dimensional representation of a hexagonal tiling.  It uses a 
# seperate layout manager to actually display the internal model, to 
# allow for easily adding graphical displays at a later date.
#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

class Board:

	#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

	def __init__( self, layout, seed=0 ):

		self.layout = layout
		self.seed   = Randomize( seed )

		self.layout.set_board( self )

		self.hexes = {}
		self.roads = {}

		self.lands = []
		self.ports = []
		self.spots = []
		self.water = []

		self.land_list = Shuffle( self.Lands )
		self.port_list = Shuffle( self.Ports )

		self.place_lands()
		self.place_water()
		self.place_land_spots()
		self.place_port_spots()

	#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

	def place_lands( self ):

		l = 0
		o = 0
		for x,y in self.L_Hex:

			land = self.land_list[l]

			if land == Desert:
				h = Hex( self.layout, x, y, land )
			else:
				h = Hex( self.layout, x, y, land, self.Order[o] )

			self.hexes[ (x,y) ] = h
			self.lands.append( h )
			self.layout.add_land( h )

			if land <> Desert: o = o + 1
			l = l + 1

	#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

	def place_water( self ):

		offset = Random( 0, 1 )

		c = 0
		p = 0
		for x,y in self.W_Hex:

			if offset == c % 2:
				h = Hex( self.layout, x, y, self.port_list[p] )
				self.ports.append( h )
				self.layout.add_port( h )
				p = p + 1
			else:
				h = Hex( self.layout, x, y, Water )
				self.water.append( h )
				self.layout.add_water( h )

			self.hexes[ (x,y) ] = h
			c = c + 1

	#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

	def place_land_spots( self ):

		for land in self.lands:
			x,y = land.x, land.y
			for d in range(6):
				dx,dy = Clockwise[d]
				sx,sy = x + dx, y + dy

				self.add_spot( land, sx, sy )

		for spot in self.spots:
			x,y = spot.x, spot.y
			for d in range(6):
				dx,dy = Clockwise[d]
				hx,hy = x + dx, y + dy

				if self.hexes.has_key( (hx,hy) ):
					hex = self.hexes[ (hx,hy) ]
					if hex in self.lands:
						spot.lands.append( hex )
					if hex in self.spots:
						self.add_road( spot, hex )

	#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

	def place_port_spots( self ):

		cx,cy = self.C_Hex

		for port in self.ports:
			px,py = port.x, port.y
			pd = max( (abs(px-cx), abs(py-cy)) )
			for d in range(6):
				dx0,dy0 = Clockwise[d]
				dx1,dy1 = Clockwise[d+1]
				sx0 = min( (px+pd*dx0,px+pd*dx1) )
				sx1 = max( (px+pd*dx0,px+pd*dx1) )
				sy0 = min( (py+pd*dy0,py+pd*dy1) )
				sy1 = max( (py+pd*dy0,py+pd*dy1) )
				if (sx0 <= cx <= sx1) and (sy0 <= cy <= sy1):
					spot = self.hexes[ (px+dx0,py+dy0) ]
					spot.port = port
					spot = self.hexes[ (px+dx1,py+dy1) ]
					spot.port = port
					break

	#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

	def add_spot( self, land, sx, sy ):

		if not self.hexes.has_key( (sx,sy) ):
			s = Spot( self.layout, sx, sy )
			self.hexes[ (sx,sy) ] = s
			self.spots.append( s )
			land.spots.append( s )
			self.layout.add_spot( s )

	#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

	def add_road( self, fm, to ):

		if not self.roads.has_key( (fm,to) ) and \
		   not self.roads.has_key( (to,fm) ):
			r = Road( self.layout, fm, to )
			self.roads[ (fm,to) ] = r
			fm.roads.append( r )
			fm.spots.append( to )
			to.roads.append( r )
			to.spots.append( fm )
			self.layout.add_road( r )

	#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

	def draw( self ):

		self.layout.draw()

#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
