#!/usr/bin/python
# -*- coding: latin1 -*-

### snake.py -- a snake game 
#   Copyright (C) 2004 Grégoire Dooms
# 
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
# 
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
# 
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
###

# First two players version
__version__ = "1.2"

class Serpent:
	def __init__(self,canvas,pos=((10,10),(11,10),(12,10)),dir=(-1,0),color='black'):
		self.pos=list(pos)
		self.dir=dir
		self.canvas=canvas
		self.can_ids=[]
		self.color=color
		for i,j in self.pos:
			self.can_ids.append(self._create_block(i,j,color))

	def _create_block(self,i,j,color):
		return self.canvas.create_rectangle(i*10+1, j*10+1, (i+1)*10+1, (j+1)*10+1, width=1, fill=color)

	def _move_block(self,block,i,j):
		self.canvas.coords(block,i*10+1, j*10+1, (i+1)*10+1, (j+1)*10+1)

	def setdirection(self,dir):
		arriere = (-self.dir[0], -self.dir[1])
		if dir != arriere:
			self.dir= dir

	def walk(self,steps=1,must_grow=False):
		for i in range(steps):
			queue = self.pos[-1]
			queue_id = self.can_ids[-1]
			self.pos[1:] = self.pos[:-1]
			self.can_ids[1:] = self.can_ids[:-1]
			self.pos[0] = (self.pos[0][0]+self.dir[0], self.pos[1][1]+self.dir[1]) 
			self.can_ids[0] = queue_id
			i,j = self.pos[0]
			self._move_block(queue_id, i, j)
			if must_grow:
				i,j = queue 
				self.pos.append(queue)
				self.can_ids.append(self._create_block(i,j,self.color))
	def position(self):
		return self.pos



from Tkinter import *
import random,sys


numplayers=1

if len(sys.argv) >1:
	numplayers=min(int(sys.argv[1]),2)


timeleft=30.0

	
#Init fenetre
fen = Tk()
tkscore=Label(fen,text="Game Loading...")
tkscore.pack()
timecan = Canvas(fen,height=20,width=401)
timebar = timecan.create_rectangle(0, 0, 0, 20, width=1, fill='green')
timecan.pack()
can = Canvas(fen,height=401,width=401)
can.pack()

#Init callbacks, move buffers, snakes
move_dir={'droite':(1,0),'gauche':(-1,0),'haut':(0,-1),'bas':(0,1)}
playermovescallbacks=[]
playersnakes=[]
playermoves=[]
playerscores=[]

def set_playermove_callback(player,move):
	playermovescallbacks[player][move] = lambda e:playermoves[player].append(move_dir[move])
def get_playermove_callback(player,move):
	return playermovescallbacks[player][move]

colors=['black','grey']
initpos=[((15,10),(14,10),(13,10)),((10,10),(11,10),(12,10))]
initdir=[(1,0),(-1,0)]

for i in range(numplayers):
	playermoves.append([])
	callbacks={}
	playermovescallbacks.append(callbacks)
	for m in move_dir:
		set_playermove_callback(i,m)
	#init Serpents
	playersnakes.append(Serpent(can,initpos[i],initdir[i],colors[i]))
	playerscores.append(0)

fen.bind("<Left>",get_playermove_callback(0,'gauche'))
fen.bind("<Up>",get_playermove_callback(0,'haut'))
fen.bind("<Right>",get_playermove_callback(0,'droite'))
fen.bind("<Down>",get_playermove_callback(0,'bas'))
if numplayers>1:
	fen.bind("<q>",get_playermove_callback(1,'gauche'))
	fen.bind("<z>",get_playermove_callback(1,'haut'))
	fen.bind("<d>",get_playermove_callback(1,'droite'))
	fen.bind("<s>",get_playermove_callback(1,'bas'))
def changer_dir():
	for player,moves in enumerate(playermoves):
		if len(moves)>0:
			n_dir = moves[0]
			del moves[0]
		else:
			continue
		playersnakes[player].setdirection(n_dir)

#Init Bonus
def create_block(i,j,color):
	return can.create_rectangle(i*10+1, j*10+1, (i+1)*10+1, (j+1)*10+1, width=1, fill=color)

def move_block(block,i,j):
	can.coords(block,i*10+1, j*10+1, (i+1)*10+1, (j+1)*10+1)

bonus={}
for k in range(10):
	i = random.randrange(40)
	j = random.randrange(40)
	bonus[i,j] = create_block(i,j,'red')
	
def deplacer():
	changer_dir()

	for player,serpent in enumerate(playersnakes):
		serp=serpent.position()
		#traitement des collisions
		i,j = serp[0]
		# dans les murs
		if i<0 or j<0 or i>39 or j>39:
			quitter()
		#sur lui même
		if serp[0] in serp[1:]:
			quitter()
		
		#traitement des bonus
		grow_snake=False
		if serp[0] in bonus:
			item = bonus[serp[0]]
			i,j = (random.randrange(40),random.randrange(40))
			bonus[i,j] = item
			del bonus[serp[0]]
			move_block(item, i, j)
			#Alongement du serpent	
			grow_snake=True
			# Calcul du score
			playerscores[player]+=1

			#Calcul du temps restant
			global timeleft
			timeleft+=2
		#Animation de la queue
		serpent.walk(must_grow=grow_snake)
	#Traitement des collisions entre serpents
	for player,s in enumerate(playersnakes):
		for s2 in playersnakes:
			if not (s is s2):
				if s.position()[0] in s2.position():
					quitter("Player %d lost"%player)
		
	# Traitement du temps restant et de la vitesse
	delay = int(300 / (max(playerscores)/10.0+1))
	timeleft-=delay/1000.0
	if timeleft<0:
		quitter()
	#Animation du score
	tkscore.configure(text=("Score: %d, "*numplayers+"Time left: %.2f")%(tuple(playerscores)+(timeleft,)))
	#Animation du temsp restant
	if timeleft < 2:
		color = 'red'
	elif timeleft < 5:
		color = 'yellow'
	else:
		color = 'green'
	timecan.coords(timebar, 0, 0, int(10*timeleft), 20)
	timecan.itemconfig(timebar, fill=color)
	
	fen.after(delay,deplacer)

def quitter(event=None):
	print "\n".join(['Joueur %d, votre score est de %d'%(player,score) for (player,score) in enumerate(playerscores)])
	if type(event)==type(""):
		print event
	fen.quit()

fen.bind("<Escape>",quitter)
deplacer()
fen.mainloop()

		
