Документ взят из кэша поисковой машины. Адрес оригинального документа : http://kodomo.fbb.msu.ru/hg/snake/annotate/008be193a0a3/engine.py
Дата изменения: Unknown
Дата индексирования: Fri Feb 28 22:54:00 2014
Кодировка:
snake: engine.py annotate

snake

annotate engine.py @ 173:008be193a0a3

fixed not correct work of UI.restart() if whole game was made by steps
author Alex Martynov
date Fri, 24 Dec 2010 00:50:06 +0300
parents af59540d48a9
children d73d8cecc812
rev   line source
martiran@12 1 import random as rnd
martiran@15 2 import Tkinter as tk
Alex@66 3 import snake
martiran@12 4
martiran@6 5 directions = [(0,1), (1,0), (0,-1), (-1,0)]
martiran@1 6
martiran@111 7 class Dict(dict):
martiran@142 8 """Create a dictionary."""
martiran@111 9 pass
martiran@111 10
martiran@5 11 class Cell(object):
martiran@142 12 """Cells.
martiran@142 13
martiran@142 14 Atributes:
martiran@142 15 - 'x' - absciss of the cell in field
martiran@142 16 - 'y' - ordinate of the cell in field
martiran@142 17 - 'canvas' - Widget the cell belongs to
martiran@142 18 - 'snake' - snake the cell belongs to, possible values:
martiran@142 19 snake
martiran@142 20 None
martiran@142 21 'my' \
martiran@142 22 'enemy' / for patterns only
martiran@142 23
martiran@142 24 - 'type' - type of the cell, possible values:
martiran@142 25 'empty'
martiran@142 26 'wall'
martiran@142 27 'body'
martiran@142 28 'head'
martiran@142 29 'tail'
martiran@142 30 'any' } for patterns only
martiran@142 31 'void' } for cells out of the field
martiran@142 32 """
martiran@15 33 def __init__(self, x, y, canvas = None):
martiran@142 34 """Initialyze the cell with default parameters:
martiran@142 35 type = 'empty'
martiran@142 36 snake = None"""
martiran@1 37 self.x = x
martiran@1 38 self.y = y
martiran@1 39 self.canvas = canvas
martiran@1 40 self.snake = None
martiran@28 41 self.type = 'empty'
martiran@1 42 return
martiran@142 43
martiran@113 44 def redraw(self, offset, c_size):
martiran@142 45 """Draw a cell based on it content"""
martiran@113 46 x0=offset[0] + self.x*c_size
martiran@113 47 y0=offset[1] + self.y*c_size
martiran@113 48 x1=offset[0] + (self.x+1)*c_size
martiran@113 49 y1=offset[1] + (self.y+1)*c_size
martiran@113 50 x2=offset[0] + (self.x+1/2.0)*c_size
martiran@15 51 if self.type == 'wall':
Alex@101 52 self.canvas.create_rectangle(x0, y0, x1, y1, fill="grey")
martiran@15 53 pass
martiran@15 54 elif self.type == 'empty':
Alex@101 55 self.canvas.create_rectangle(x0, y0, x1, y1, fill="black")
martiran@15 56 pass
martiran@15 57 elif self.type == 'body':
Alex@101 58 self.canvas.create_rectangle(x0, y0, x1, y1, fill=self.snake.color)
martiran@15 59 pass
martiran@15 60 elif self.type == 'head':
Alex@101 61 self.canvas.create_oval(x0, y0, x1, y1, fill=self.snake.color)
martiran@15 62 pass
martiran@15 63 elif self.type == 'tail':
Alex@101 64 self.canvas.create_polygon(x0, y0, x1, y0, x2, y1, fill=self.snake.color)
martiran@15 65 pass
martiran@15 66 return
martiran@142 67
martiran@6 68 def __eq__(self, pattern):
martiran@142 69 """Check the equaliation of the cell to the pattern cell."""
martiran@52 70 if pattern.type == 'any':
martiran@6 71 return True
martiran@52 72 if pattern.type != self.type:
martiran@6 73 return False
martiran@52 74 if pattern.snake_type == 'my' and pattern.snake != self.snake:
martiran@52 75 return False
martiran@52 76 elif pattern.snake_type == 'enemy' and pattern.snake == self.snake:
martiran@52 77 return False
martiran@52 78 return True
martiran@126 79
martiran@126 80 def __ne__(self, pattern):
martiran@142 81 """Check the discrepancy of the cell to the pattern cell."""
martiran@126 82 return not self == pattern
martiran@126 83
martiran@6 84 def clear(self):
martiran@142 85 """Change the cell parameters back to default."""
martiran@1 86 self.snake = None
martiran@1 87 self.type = 'empty'
martiran@1 88 return
martiran@1 89
martiran@2 90
martiran@5 91 class Engine(object):
martiran@142 92 """Engine
martiran@142 93
martiran@142 94 Atributes:
martiran@142 95
martiran@142 96 - 'field' - game field:
martiran@142 97 'field.w' - width of the field count in cells
martiran@142 98 'field.h' - hight of the field count in cells
martiran@142 99 - 'canvas' - Widget game field is showing on
martiran@142 100 - 'snakes' - list of snakes loaded
Alex@155 101 - 'psnakes' - list of snakes loaded in previous match, if other snakes are not loaded
martiran@142 102 - 'start_snake_length' - starting length of the snake"""
martiran@142 103
martiran@6 104 def __init__(self, canvas):
martiran@142 105 """Initialyze the engine:
martiran@142 106 start_snake_length = 10"""
martiran@1 107 self.canvas = canvas
martiran@12 108 self.snakes = [None, None, None, None]
Alex@155 109 self.psnakes = [None, None, None, None]
martiran@9 110 self.init_field()
martiran@111 111 self.start_snake_length = 10
martiran@9 112 return
martiran@142 113
martiran@9 114 def init_field (self):
martiran@142 115 """Initialyze the field:
martiran@142 116 width = 31
martiran@142 117 hieght = 31
martiran@142 118 perimeter is made by walls"""
martiran@111 119 self.field = Dict()
martiran@117 120 self.field.w = 31
martiran@117 121 self.field.h = 31
martiran@113 122 f_w = self.field.w
martiran@113 123 f_h = self.field.h
martiran@113 124 for x in range(f_w):
martiran@113 125 for y in range(f_h):
martiran@9 126 self.field[x, y] = Cell(x, y, self.canvas)
martiran@113 127 for y in range(f_h):
martiran@9 128 self.field[0, y].type = 'wall'
martiran@113 129 self.field[f_w-1, y].type = 'wall'
martiran@113 130 for x in range(1,f_w-1):
martiran@9 131 self.field[x, 0].type = 'wall'
martiran@113 132 self.field[x, f_h-1].type = 'wall'
Alex@103 133 self.refill()
Alex@93 134 self.redraw()
martiran@1 135 return
martiran@142 136
martiran@6 137 def step(self):
martiran@142 138 """Do the step of the game."""
Alex@62 139 for i, snake in enumerate(self.snakes):
Alex@103 140 if snake != None:
Alex@170 141 if len(snake.cells) <= 1:
Alex@170 142 if len(snake.cells) == 0:
Alex@170 143 self.snakes[i] = None
Alex@103 144 continue
Alex@66 145 self.legal_moves(snake)
martiran@12 146 self.move_snake(snake)
martiran@12 147 self.refill()
martiran@9 148 self.redraw()
martiran@9 149 return
martiran@142 150
martiran@9 151 def move_snake(self, snake):
martiran@142 152 """Check of movement direction based on the snake rule list and actual
martiran@142 153 enviroment."""
martiran@105 154 head = snake.cells[0]
martiran@12 155 for rule in snake.rules:
martiran@105 156 for direction in snake.legal_dir:
martiran@105 157 rule.rotate(direction)
martiran@105 158 if rule.applies(self.field, head.x, head.y) == True:
martiran@105 159 self.move_do(snake, direction)
martiran@105 160 return
martiran@105 161 if snake.legal_dir != []:
Alex@99 162 self.move_do(snake, snake.legal_dir[0])
martiran@12 163 pass
martiran@14 164 return
martiran@142 165
Alex@94 166 def move_do(self, snake, applied_dir):
martiran@142 167 """Do the move of the snake."""
martiran@107 168 head = snake.cells[0]
martiran@107 169 dir_cell = self.field[head.x + applied_dir[0], head.y + applied_dir[1]]
Alex@90 170 if dir_cell.type == 'empty':
Alex@90 171 snake.cells.insert(0,dir_cell)
Alex@90 172 del snake.cells[-1]
Alex@90 173 pass
Alex@90 174 elif (dir_cell.type == 'tail' and dir_cell.snake != snake):
Alex@90 175 snake.cells.insert(0,dir_cell)
Alex@90 176 del dir_cell.snake.cells[-1]
Alex@90 177 pass
Alex@90 178
Alex@156 179 def create_snake(self, snake_number, old_snake = None):
martiran@142 180 """Create the snake:
martiran@142 181 position choice is based on number or placement of 'Load' button
martiran@146 182 snakes are placed with tails turned to the wall.
martiran@142 183 color is chosen accorting to fen shui tradition"""
martiran@46 184 cells_id = []
martiran@113 185 f_h = self.field.h
martiran@113 186 f_w = self.field.w
martiran@111 187 for y in range(self.start_snake_length):
martiran@146 188 cells_id.insert(0,((f_w-1)/2, y+1))
Alex@160 189 for rot_num in range(snake_number):
Alex@62 190 for i, cell in enumerate(cells_id):
martiran@122 191 cells_id[i] = (min(f_h, f_w)-1-cell[1],cell[0])
martiran@46 192 cells = []
martiran@46 193 for cell in cells_id:
Alex@60 194 cells.append(self.field[cell])
martiran@46 195 color_dic = {
Alex@160 196 0:'blue',
Alex@160 197 1:'green',
Alex@160 198 2:'yellow',
Alex@160 199 3:'red',}
Alex@156 200 if old_snake == None:
Alex@160 201 self.snakes[snake_number] = snake.Snake(cells, color_dic[snake_number])
Alex@156 202 else:
Alex@156 203 old_snake.cells = cells
Alex@160 204 return self.snakes[snake_number]
martiran@142 205
martiran@6 206 def refill(self):
martiran@142 207 """Refill the field cells types and snakes according to the actual
martiran@142 208 position"""
martiran@113 209 f_w = self.field.w
martiran@113 210 f_h = self.field.h
martiran@113 211 for x in range(1,f_w-1):
martiran@113 212 for y in range(1,f_h-1):
martiran@12 213 self.field[x, y].type = 'empty'
martiran@31 214 self.field[x, y].snake = None
martiran@12 215 pass
martiran@12 216 for snake in self.snakes:
martiran@12 217 if snake == None:
martiran@12 218 pass
martiran@12 219 else:
martiran@31 220 snake.fill()
martiran@12 221 pass
martiran@14 222 return
martiran@142 223
martiran@9 224 def redraw(self):
martiran@142 225 """Clear the field Widget and redraw cells images on it"""
martiran@117 226 self.canvas.delete("all")
martiran@113 227 w = self.canvas.winfo_width()
martiran@113 228 h = self.canvas.winfo_height()
martiran@113 229 cw = w/float(self.field.w)
martiran@113 230 ch = h/float(self.field.h)
martiran@113 231 c = min(cw, ch)
martiran@113 232 field_geometry = (self.field.w*c,self.field.h*c)
martiran@113 233 offset = ((w - field_geometry[0])/2.0, (h - field_geometry[1])/2.0)
martiran@32 234 for cell_coord in self.field:
martiran@113 235 self.field[cell_coord].redraw(offset, c)
martiran@15 236 return
martiran@142 237
martiran@6 238 def legal_moves(self, snake):
martiran@142 239 """Check for snake legal move directions according to the game rules."""
martiran@6 240 snake.legal_dir = []
martiran@108 241 head = snake.cells[0]
martiran@6 242 for direction in directions:
martiran@108 243 dir_cell = self.field[head.x + direction[0], head.y + direction[1]]
martiran@12 244 if (dir_cell.type == 'empty' or (dir_cell.type == 'tail' and dir_cell.snake != snake)):
martiran@6 245 snake.legal_dir.append(direction)
Alex@90 246 rnd.shuffle(snake.legal_dir)
martiran@6 247 return
martiran@6 248