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@103
|
141 if len(snake.cells) == 0: |
Alex@103
|
142 self.snakes[i] = None |
Alex@103
|
143 continue |
Alex@66
|
144 self.legal_moves(snake) |
martiran@12
|
145 self.move_snake(snake) |
martiran@12
|
146 self.refill() |
martiran@9
|
147 self.redraw() |
martiran@9
|
148 return |
martiran@142
|
149 |
martiran@9
|
150 def move_snake(self, snake): |
martiran@142
|
151 """Check of movement direction based on the snake rule list and actual |
martiran@142
|
152 enviroment.""" |
martiran@105
|
153 head = snake.cells[0] |
martiran@12
|
154 for rule in snake.rules: |
martiran@105
|
155 for direction in snake.legal_dir: |
martiran@105
|
156 rule.rotate(direction) |
martiran@105
|
157 if rule.applies(self.field, head.x, head.y) == True: |
martiran@105
|
158 self.move_do(snake, direction) |
martiran@105
|
159 return |
martiran@105
|
160 if snake.legal_dir != []: |
Alex@99
|
161 self.move_do(snake, snake.legal_dir[0]) |
martiran@12
|
162 pass |
martiran@14
|
163 return |
martiran@142
|
164 |
Alex@94
|
165 def move_do(self, snake, applied_dir): |
martiran@142
|
166 """Do the move of the snake.""" |
martiran@107
|
167 head = snake.cells[0] |
martiran@107
|
168 dir_cell = self.field[head.x + applied_dir[0], head.y + applied_dir[1]] |
Alex@90
|
169 if dir_cell.type == 'empty': |
Alex@90
|
170 snake.cells.insert(0,dir_cell) |
Alex@90
|
171 del snake.cells[-1] |
Alex@90
|
172 pass |
Alex@90
|
173 elif (dir_cell.type == 'tail' and dir_cell.snake != snake): |
Alex@90
|
174 snake.cells.insert(0,dir_cell) |
Alex@90
|
175 del dir_cell.snake.cells[-1] |
Alex@90
|
176 pass |
Alex@90
|
177 |
martiran@6
|
178 def create_snake(self, snake_number): |
martiran@142
|
179 """Create the snake: |
martiran@142
|
180 position choice is based on number or placement of 'Load' button |
martiran@146
|
181 snakes are placed with tails turned to the wall. |
martiran@142
|
182 color is chosen accorting to fen shui tradition""" |
martiran@46
|
183 cells_id = [] |
martiran@113
|
184 f_h = self.field.h |
martiran@113
|
185 f_w = self.field.w |
martiran@111
|
186 for y in range(self.start_snake_length): |
martiran@146
|
187 cells_id.insert(0,((f_w-1)/2, y+1)) |
martiran@46
|
188 for rot_num in range(snake_number - 1): |
Alex@62
|
189 for i, cell in enumerate(cells_id): |
martiran@122
|
190 cells_id[i] = (min(f_h, f_w)-1-cell[1],cell[0]) |
martiran@46
|
191 cells = [] |
martiran@46
|
192 for cell in cells_id: |
Alex@60
|
193 cells.append(self.field[cell]) |
martiran@46
|
194 color_dic = { |
martiran@46
|
195 1:'blue', |
martiran@46
|
196 2:'green', |
martiran@46
|
197 3:'yellow', |
martiran@46
|
198 4:'red',} |
martiran@46
|
199 self.snakes[snake_number-1] = snake.Snake(cells, color_dic[snake_number]) |
Alex@155
|
200 self.psnakes[snake_number-1] = self.snakes[snake_number-1] |
Alex@77
|
201 return self.snakes[snake_number-1] |
martiran@142
|
202 |
martiran@6
|
203 def refill(self): |
martiran@142
|
204 """Refill the field cells types and snakes according to the actual |
martiran@142
|
205 position""" |
martiran@113
|
206 f_w = self.field.w |
martiran@113
|
207 f_h = self.field.h |
martiran@113
|
208 for x in range(1,f_w-1): |
martiran@113
|
209 for y in range(1,f_h-1): |
martiran@12
|
210 self.field[x, y].type = 'empty' |
martiran@31
|
211 self.field[x, y].snake = None |
martiran@12
|
212 pass |
martiran@12
|
213 for snake in self.snakes: |
martiran@12
|
214 if snake == None: |
martiran@12
|
215 pass |
martiran@12
|
216 else: |
martiran@31
|
217 snake.fill() |
martiran@12
|
218 pass |
martiran@14
|
219 return |
martiran@142
|
220 |
martiran@9
|
221 def redraw(self): |
martiran@142
|
222 """Clear the field Widget and redraw cells images on it""" |
martiran@117
|
223 self.canvas.delete("all") |
martiran@113
|
224 w = self.canvas.winfo_width() |
martiran@113
|
225 h = self.canvas.winfo_height() |
martiran@113
|
226 cw = w/float(self.field.w) |
martiran@113
|
227 ch = h/float(self.field.h) |
martiran@113
|
228 c = min(cw, ch) |
martiran@113
|
229 field_geometry = (self.field.w*c,self.field.h*c) |
martiran@113
|
230 offset = ((w - field_geometry[0])/2.0, (h - field_geometry[1])/2.0) |
martiran@32
|
231 for cell_coord in self.field: |
martiran@113
|
232 self.field[cell_coord].redraw(offset, c) |
martiran@15
|
233 return |
martiran@142
|
234 |
martiran@6
|
235 def legal_moves(self, snake): |
martiran@142
|
236 """Check for snake legal move directions according to the game rules.""" |
martiran@6
|
237 snake.legal_dir = [] |
martiran@108
|
238 head = snake.cells[0] |
martiran@6
|
239 for direction in directions: |
martiran@108
|
240 dir_cell = self.field[head.x + direction[0], head.y + direction[1]] |
martiran@12
|
241 if (dir_cell.type == 'empty' or (dir_cell.type == 'tail' and dir_cell.snake != snake)): |
martiran@6
|
242 snake.legal_dir.append(direction) |
Alex@90
|
243 rnd.shuffle(snake.legal_dir) |
martiran@6
|
244 return |
martiran@6
|
245
|