Документ взят из кэша поисковой машины. Адрес оригинального документа : http://kodomo.cmm.msu.su/trac/snake/browser/engine.py?format=txt
Дата изменения: Tue Dec 28 16:47:32 2010
Дата индексирования: Tue Oct 2 10:45:59 2012
Кодировка:
import random as rnd
import Tkinter as tk
import snake

directions = [(0,1), (1,0), (0,-1), (-1,0)]

class Dict(dict):
"""Create a dictionary."""
pass

class Cell(object):
"""Cells.

Atributes:
- 'x' - absciss of the cell in field
- 'y' - ordinate of the cell in field
- 'canvas' - Widget the cell belongs to
- 'snake' - snake the cell belongs to, possible values:
snake
None
'my' \
'enemy' / for patterns only

- 'type' - type of the cell, possible values:
'empty'
'wall'
'body'
'head'
'tail'
'any' } for patterns only
'void' } for cells out of the field
"""
def __init__(self, x, y, canvas = None):
"""Initialyze the cell with default parameters:
type = 'empty'
snake = None"""
self.x = x
self.y = y
self.canvas = canvas
self.snake = None
self.type = 'empty'
return

def redraw(self, offset, c_size):
"""Draw a cell based on it content"""
x0=offset[0] + self.x*c_size
y0=offset[1] + self.y*c_size
x1=offset[0] + (self.x+1)*c_size
y1=offset[1] + (self.y+1)*c_size
x2=offset[0] + (self.x+1/2.0)*c_size
if self.type == 'wall':
self.canvas.create_rectangle(x0, y0, x1, y1, fill="grey")
pass
elif self.type == 'empty':
self.canvas.create_rectangle(x0, y0, x1, y1, fill="black")
pass
elif self.type == 'body':
self.canvas.create_rectangle(x0, y0, x1, y1, fill=self.snake.color)
pass
elif self.type == 'head':
self.canvas.create_oval(x0, y0, x1, y1, fill=self.snake.color)
pass
elif self.type == 'tail':
self.canvas.create_polygon(x0, y0, x1, y0, x2, y1, fill=self.snake.color)
pass
return

def __eq__(self, pattern):
"""Check the equaliation of the cell to the pattern cell."""
if pattern.type == 'any':
return True
if pattern.type != self.type:
return False
if pattern.snake_type == 'my' and pattern.snake != self.snake:
return False
elif pattern.snake_type == 'enemy' and pattern.snake == self.snake:
return False
return True

def __ne__(self, pattern):
"""Check the discrepancy of the cell to the pattern cell."""
return not self == pattern

def clear(self):
"""Change the cell parameters back to default."""
self.snake = None
self.type = 'empty'
return


class Engine(object):
"""Engine

Atributes:

- 'field' - game field:
'field.w' - width of the field count in cells
'field.h' - hight of the field count in cells
- 'canvas' - Widget game field is showing on
- 'snakes' - list of snakes loaded
- 'psnakes' - list of snakes loaded in previous match, if other snakes are not loaded
- 'start_snake_length' - starting length of the snake"""

def __init__(self, canvas):
"""Initialyze the engine:
start_snake_length = 10"""
self.canvas = canvas
self.snakes = [None, None, None, None]
self.psnakes = [None, None, None, None]
self.init_field()
self.start_snake_length = 10
return

def init_field (self):
"""Initialyze the field:
width = 31
hieght = 31
perimeter is made by walls"""
self.field = Dict()
self.field.w = 31
self.field.h = 31
f_w = self.field.w
f_h = self.field.h
for x in range(f_w):
for y in range(f_h):
self.field[x, y] = Cell(x, y, self.canvas)
for y in range(f_h):
self.field[0, y].type = 'wall'
self.field[f_w-1, y].type = 'wall'
for x in range(1,f_w-1):
self.field[x, 0].type = 'wall'
self.field[x, f_h-1].type = 'wall'
self.refill()
self.redraw()
return

def step(self):
"""Do the step of the game."""
for i, snake in enumerate(self.snakes):
if snake != None:
if len(snake.cells) <= 1:
if len(snake.cells) == 0:
self.snakes[i] = None
continue
self.legal_moves(snake)
self.move_snake(snake)
self.refill()
self.redraw()
return

def move_snake(self, snake):
"""Check of movement direction based on the snake rule list and actual
enviroment."""
head = snake.cells[0]
for rule in snake.rules:
for direction in snake.legal_dir:
rule.rotate(direction)
if rule.applies(self.field, head.x, head.y) == True:
self.move_do(snake, direction)
return
if snake.legal_dir != []:
self.move_do(snake, snake.legal_dir[0])
pass
return

def move_do(self, snake, applied_dir):
"""Do the move of the snake."""
head = snake.cells[0]
dir_cell = self.field[head.x + applied_dir[0], head.y + applied_dir[1]]
if dir_cell.type == 'empty':
snake.cells.insert(0,dir_cell)
del snake.cells[-1]
pass
elif (dir_cell.type == 'tail' and dir_cell.snake != snake):
snake.cells.insert(0,dir_cell)
del dir_cell.snake.cells[-1]
pass

def create_snake(self, snake_number, old_snake = None):
"""Create the snake:
position choice is based on number or placement of 'Load' button
snakes are placed with tails turned to the wall.
color is chosen accorting to fen shui tradition"""
cells_id = []
f_h = self.field.h
f_w = self.field.w
for y in range(self.start_snake_length):
cells_id.insert(0,((f_w-1)/2, y+1))
for rot_num in range(snake_number):
for i, cell in enumerate(cells_id):
cells_id[i] = (min(f_h, f_w)-1-cell[1],cell[0])
cells = []
for cell in cells_id:
cells.append(self.field[cell])
color_dic = {
0:'blue',
1:'green',
2:'yellow',
3:'red',}
if old_snake == None:
self.snakes[snake_number] = snake.Snake(cells, color_dic[snake_number])
else:
old_snake.cells = cells
return self.snakes[snake_number]

def refill(self):
"""Refill the field cells types and snakes according to the actual
position"""
f_w = self.field.w
f_h = self.field.h
for x in range(1,f_w-1):
for y in range(1,f_h-1):
self.field[x, y].type = 'empty'
self.field[x, y].snake = None
pass
for snake in self.snakes:
if snake == None:
pass
else:
snake.fill()
pass
return

def redraw(self):
"""Clear the field Widget and redraw cells images on it"""
self.canvas.delete("all")
_, offset, c = self.field_geometry_calc()
for cell_coord in self.field:
self.field[cell_coord].redraw(offset, c)
return

def field_geometry_calc (self):
"""Calculate grafical parameters of the field.
Return:
field_geometry - (width, hight) of the field
offset - (x, y) of the left top corner of the field
c - cell size"""
w = self.canvas.winfo_width()
h = self.canvas.winfo_height()
cw = w/float(self.field.w)
ch = h/float(self.field.h)
c = min(cw, ch)
field_geometry = (self.field.w*c,self.field.h*c)
offset = ((w - field_geometry[0])/2.0, (h - field_geometry[1])/2.0)
return field_geometry, offset, c

def legal_moves(self, snake):
"""Check for snake legal move directions according to the game rules.
Return:
list of legal moves"""
snake.legal_dir = []
head = snake.cells[0]
for direction in directions:
dir_cell = self.field[head.x + direction[0], head.y + direction[1]]
if (dir_cell.type == 'empty' or (dir_cell.type == 'tail' and dir_cell.snake != snake)):
snake.legal_dir.append(direction)
rnd.shuffle(snake.legal_dir)
return snake.legal_dir