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