]> icculus.org git repositories - divverent/nexuiz.git/blob - TeamNexuiz/game/gamec/g_tetris.c
bumps for morphed's teleporter model
[divverent/nexuiz.git] / TeamNexuiz / game / gamec / g_tetris.c
1 /*\r
2 \r
3 Installation:\r
4 \r
5 in weapons.qc add TetrisImpulses(); to ImpulseCommands\r
6 \r
7 in progs.src add tetris.qc after subs.qc\r
8 in client.qc add if (TetrisPreFrame()) return; to  PlayerPreThink\r
9 in client.qc add if (TetrisPostFrame()) return; to PlayerPostThink\r
10 \r
11 */\r
12 \r
13 .vector tet_org;\r
14 \r
15 .float tetris_on, tet_time, tet_autodown;\r
16 .vector piece_pos;\r
17 .float piece_type, next_piece, tet_score, tet_lines;\r
18 \r
19 var float tet_high_score = 0;\r
20 \r
21 float TET_LINES = 20;\r
22 float TET_WIDTH = 10;\r
23 //character values\r
24 float TET_BORDER = 132;\r
25 float TET_BLOCKS = 132; // +1 = first color, +2, +3;\r
26 float TET_SPACE = 32; // blankness\r
27 \r
28 \r
29 \r
30 float TETKEY_UP = 1;\r
31 float TETKEY_DOWN = 2;\r
32 float TETKEY_LEFT = 4;\r
33 float TETKEY_RIGHT = 8;\r
34 float TETKEY_ROTLEFT = 16;\r
35 float TETKEY_ROTRIGHT = 32;\r
36 \r
37 float PIECES = 7;\r
38 \r
39 .float line1, line2, line3, line4, line5, line6, line7,\r
40 line8, line9, line10, line11, line12, line13, line14, line15,\r
41 line16, line17, line18, line19, line20;\r
42 \r
43 \r
44 float   SVC_CENTERPRINTa                = 26;\r
45 \r
46 \r
47 /*\r
48 *********************************\r
49 \r
50 Library Functions\r
51 \r
52 *********************************\r
53 */\r
54 void (float ln, float vl) SetLine =\r
55 {\r
56         if (ln == 1)\r
57                 self.line1 = vl;\r
58         else if (ln == 2)\r
59                 self.line2 = vl;\r
60         else if (ln == 3)\r
61                 self.line3 = vl;\r
62         else if (ln == 4)\r
63                 self.line4 = vl;\r
64         else if (ln == 5)\r
65                 self.line5 = vl;\r
66         else if (ln == 6)\r
67                 self.line6 = vl;\r
68         else if (ln == 7)\r
69                 self.line7 = vl;\r
70         else if (ln == 8)\r
71                 self.line8 = vl;\r
72         else if (ln == 9)\r
73                 self.line9 = vl;\r
74         else if (ln == 10)\r
75                 self.line10 = vl;\r
76         else if (ln == 11)\r
77                 self.line11 = vl;\r
78         else if (ln == 12)\r
79                 self.line12 = vl;\r
80         else if (ln == 13)\r
81                 self.line13 = vl;\r
82         else if (ln == 14)\r
83                 self.line14 = vl;\r
84         else if (ln == 15)\r
85                 self.line15 = vl;\r
86         else if (ln == 16)\r
87                 self.line16 = vl;\r
88         else if (ln == 17)\r
89                 self.line17 = vl;\r
90         else if (ln == 18)\r
91                 self.line18 = vl;\r
92         else if (ln == 19)\r
93                 self.line19 = vl;\r
94         else if (ln == 20)\r
95                 self.line20 = vl;\r
96 };\r
97 \r
98 float (float ln) GetLine =\r
99 {\r
100         if (ln == 1)\r
101                 return self.line1;\r
102         else if (ln == 2)\r
103                 return self.line2;\r
104         else if (ln == 3)\r
105                 return self.line3;\r
106         else if (ln == 4)\r
107                 return self.line4;\r
108         else if (ln == 5)\r
109                 return self.line5;\r
110         else if (ln == 6)\r
111                 return self.line6;\r
112         else if (ln == 7)\r
113                 return self.line7;\r
114         else if (ln == 8)\r
115                 return self.line8;\r
116         else if (ln == 9)\r
117                 return self.line9;\r
118         else if (ln == 10)\r
119                 return self.line10;\r
120         else if (ln == 11)\r
121                 return self.line11;\r
122         else if (ln == 12)\r
123                 return self.line12;\r
124         else if (ln == 13)\r
125                 return self.line13;\r
126         else if (ln == 14)\r
127                 return self.line14;\r
128         else if (ln == 15)\r
129                 return self.line15;\r
130         else if (ln == 16)\r
131                 return self.line16;\r
132         else if (ln == 17)\r
133                 return self.line17;\r
134         else if (ln == 18)\r
135                 return self.line18;\r
136         else if (ln == 19)\r
137                 return self.line19;\r
138         else if (ln == 20)\r
139                 return self.line20;\r
140         else\r
141                 return 0;\r
142 };\r
143 \r
144 float(float x, float dat) GetXBlock =\r
145 {\r
146         if (x == 1)\r
147                 return dat & 3;\r
148         else if (x == 2)\r
149                 return (dat & 12) / 4;\r
150         else if (x == 3)\r
151                 return (dat & 48) / 16;\r
152         else if (x == 4)\r
153                 return (dat & 192) / 64;\r
154         else if (x == 5)\r
155                 return (dat & 768) / 256;\r
156         else if (x == 6)\r
157                 return (dat & 3072) / 1024;\r
158         else if (x == 7)\r
159                 return (dat & 12288) / 4096;\r
160         else if (x == 8)\r
161                 return (dat & 49152) / 16384;\r
162         else if (x == 9)\r
163                 return (dat & 196608) / 65536;\r
164         else if (x == 10)\r
165                 return (dat & 786432) / 262144;\r
166         else\r
167                 return 0;\r
168 };\r
169 \r
170 float(float x, float dat, float new) SetXBlock =\r
171 {\r
172         if (x == 1)\r
173                 return (dat - (dat & 3)) | new;\r
174         else if (x == 2)\r
175                 return (dat - (dat & 12)) | (new*4);\r
176         else if (x == 3)\r
177                 return (dat - (dat & 48)) | (new*16);\r
178         else if (x == 4)\r
179                 return (dat - (dat & 192)) | (new*64);\r
180         else if (x == 5)\r
181                 return (dat - (dat & 768)) | (new*256);\r
182         else if (x == 6)\r
183                 return (dat - (dat & 3072)) | (new*1024);\r
184         else if (x == 7)\r
185                 return (dat - (dat & 12288)) | (new*4096);\r
186         else if (x == 8)\r
187                 return (dat - (dat & 49152)) | (new*16384);\r
188         else if (x == 9)\r
189                 return (dat - (dat & 196608)) | (new*65536);\r
190         else if (x == 10)\r
191                 return (dat - (dat & 786432)) | (new*262144);\r
192         else\r
193                 return dat;\r
194 };\r
195 \r
196 \r
197 float(float x, float y) GetSquare =\r
198 {\r
199         return GetXBlock(x,  GetLine(y));\r
200 };\r
201 \r
202 void (float x, float y, float val) SetSquare =\r
203 {\r
204         float dat;\r
205 \r
206         dat = GetLine(y);\r
207         dat  = SetXBlock(x, dat, val & 3);\r
208         SetLine(y, dat);\r
209 };\r
210 \r
211 \r
212 \r
213 vector(float pc) PieceShape =\r
214 {\r
215 \r
216 /*\r
217 1 =\r
218  ##\r
219  ##\r
220 */\r
221         if (pc == 1)\r
222                 return '20 20 0'; // 1 * 4 + 1 * 16\r
223 /*\r
224 2 =\r
225 \r
226 ####\r
227 */\r
228         else if (pc == 2)\r
229                 return '85 0 0';\r
230 \r
231 /*\r
232 3 =\r
233 \r
234 ###\r
235 #\r
236 */\r
237         else if (pc == 3)\r
238                 return '21 1 0';\r
239 /*\r
240 4 =\r
241 \r
242 #\r
243 ###\r
244 */\r
245         else if (pc == 4)\r
246                 return '1 21 0';\r
247 /*\r
248 5 =\r
249 ##\r
250  ##\r
251 */\r
252         else if (pc == 5)\r
253                 return '5 20 0';\r
254 \r
255 /*\r
256 6 =\r
257  ##\r
258 ##\r
259 */\r
260         else if (pc == 6)\r
261                 return '20 5 0';\r
262 \r
263 /*\r
264 7 =\r
265  #\r
266 ###\r
267 */\r
268         else if (pc == 7)\r
269                 return '4 21 0';\r
270 \r
271 \r
272         else\r
273                 return '0 0 0';\r
274 \r
275 }\r
276 \r
277 // do x 1..4 and y 1..4 in case of rotation\r
278 float(float x, float y, float rot, float pc) PieceMetric =\r
279 {\r
280         float t;\r
281         vector piece_dat;\r
282 \r
283         // return bits of a piece\r
284         if (rot == 1) // 90 degrees\r
285         {\r
286                 t = y;\r
287                 y = x;\r
288                 x = 5 - t;\r
289         }\r
290         else if (rot == 2)//180\r
291         {\r
292                 x = 5 - x;\r
293                 y = 3 - y;\r
294         }\r
295         else if (rot == 3) // 270\r
296         {\r
297                 t = y;\r
298                 y = 5 - x;\r
299                 x = t;\r
300         }\r
301         if (x < 1 || y < 1 || x > 4 || y > 2)\r
302                 return 0;\r
303         piece_dat = PieceShape(pc);\r
304         if (y == 1)\r
305                 return GetXBlock(x, piece_dat_x); // first row\r
306         else if (y == 2)\r
307                 return GetXBlock(x, piece_dat_y); // second row\r
308         else if (y == 3)\r
309                 return GetXBlock(x, piece_dat_z); // third row (doesn't exist)\r
310         else\r
311                 return 0; // illegal parms\r
312 };\r
313 /*\r
314 *********************************\r
315 \r
316 Draw\r
317 \r
318 *********************************\r
319 */\r
320 \r
321 \r
322 /* some prydon gate functions to make life easier....\r
323 \r
324 somewhat modified because we don't need all the fanciness Prydon Gate is capable of\r
325 \r
326 */\r
327 \r
328 void(float c1, float c2, float c3, float c4, float c5, float c6) p6 =\r
329 {\r
330         WriteChar(MSG_ONE, c1);\r
331         WriteChar(MSG_ONE, c2);\r
332         WriteChar(MSG_ONE, c3);\r
333         WriteChar(MSG_ONE, c4);\r
334         WriteChar(MSG_ONE, c5);\r
335         WriteChar(MSG_ONE, c6);\r
336 };\r
337 \r
338 float(float num, float dig) pnum =\r
339 {\r
340         local float f, i;\r
341         if (num < 0)\r
342         {\r
343                 WriteChar(MSG_ONE, 45);\r
344                 num = 0 - num;\r
345         }\r
346         f = floor(num / 10);\r
347         num = num - (f * 10);\r
348         if (f)\r
349                 dig = pnum(f, dig+1);\r
350         else\r
351         {\r
352                 // pad to 6\r
353                 for (i = 0; i < (5 - dig); i = i + 1)\r
354                         WriteChar(MSG_ONE, TET_SPACE);\r
355         }\r
356         WriteChar(MSG_ONE, 48 + num);\r
357         return dig;\r
358 };\r
359 \r
360 void (float ln) DrawLine =\r
361 {\r
362         float x, d;\r
363         WriteChar(MSG_ONE, TET_BORDER);\r
364 \r
365         for (x = 1; x <= TET_WIDTH; x = x + 1)\r
366         {\r
367                 d = GetSquare(x, ln);\r
368                 if (d)\r
369                         WriteChar(MSG_ONE, TET_BLOCKS + d);\r
370                 else\r
371                         WriteChar(MSG_ONE, TET_SPACE);\r
372         }\r
373         WriteChar(MSG_ONE, TET_BORDER);\r
374 }\r
375 \r
376 void (float pc, float ln) DrawPiece =\r
377 {\r
378         float x, d, piece_ln, color;\r
379         vector piece_dat;\r
380         color = pc & 3;\r
381         if (color == 0) // 4\r
382                 color = 1;\r
383         WriteChar(MSG_ONE, TET_SPACE); // pad to 6\r
384 \r
385         piece_dat = PieceShape(pc);\r
386         if (ln == 1)\r
387                 piece_ln = piece_dat_x;\r
388         else\r
389                 piece_ln = piece_dat_y;\r
390         for (x = 1; x <= 4; x = x + 1)\r
391         {\r
392                 d = GetXBlock(x, piece_ln) * color;\r
393                 if (d)\r
394                         WriteChar(MSG_ONE, TET_BLOCKS + d);\r
395                 else\r
396                         WriteChar(MSG_ONE, TET_SPACE);\r
397         }\r
398         WriteChar(MSG_ONE, TET_SPACE);  // pad to 6\r
399 }\r
400 void() Draw_Tetris =\r
401 {\r
402         float i;\r
403         msg_entity = self;\r
404         WriteChar(MSG_ONE, SVC_CENTERPRINTa);\r
405         // decoration\r
406         for (i = 1; i <= (TET_WIDTH + 2); i = i + 1)\r
407                 WriteChar(MSG_ONE, TET_BORDER);\r
408         p6(' ', ' ', ' ', ' ', ' ', ' ');\r
409         WriteChar(MSG_ONE, 10);\r
410         for (i = 1; i <= TET_LINES; i = i + 1)\r
411         {\r
412                 DrawLine(i);\r
413                 if (i == 1)\r
414                         p6(' ', 'N', 'E', 'X', 'T', ' ');\r
415                 else if (i == 3)\r
416                         DrawPiece(self.next_piece, 1);\r
417                 else if (i == 4)\r
418                         DrawPiece(self.next_piece, 2);\r
419                 else if (i == 6)\r
420                         p6(' ', 'L', 'I', 'N', 'E', 'S');\r
421                 else if (i == 7)\r
422                         pnum(self.tet_lines, 0);\r
423                 else if (i == 9)\r
424                         p6(' ', 'S', 'C', 'O', 'R', 'E');\r
425                 else if (i == 10)\r
426                         pnum(self.tet_score, 0);\r
427                 else if (i == 12)\r
428                         p6(' ', 'H', 'I', 'G', 'H', ' ');\r
429                 else if (i == 13)\r
430                         p6(' ', 'S', 'C', 'O', 'R', 'E');\r
431                 else if (i == 14)\r
432                         pnum(tet_high_score, 0);\r
433                 else if (i == 16)\r
434                         p6(' ', 'L', 'E', 'V', 'E', 'L');\r
435                 else if (i == 17)\r
436                         pnum(floor(self.tet_lines / 20)+ 1, 0);\r
437                 else\r
438                         p6(' ', ' ', ' ', ' ', ' ', ' ');\r
439                 WriteChar(MSG_ONE, 10);\r
440         }\r
441         // decoration\r
442 \r
443         for (i = 1; i <= (TET_WIDTH + 2); i = i + 1)\r
444                 WriteChar(MSG_ONE, TET_BORDER);\r
445         p6(' ', ' ', ' ', ' ', ' ', ' ');\r
446         WriteChar(MSG_ONE, 10);\r
447         WriteChar(MSG_ONE, 0);\r
448 }\r
449 /*\r
450 *********************************\r
451 \r
452 Game Functions\r
453 \r
454 *********************************\r
455 */\r
456 \r
457 // reset the game\r
458 void() ResetTetris =\r
459 {\r
460         float i;\r
461 \r
462         for (i=1; i<=TET_LINES; i = i + 1)\r
463                 SetLine(i, 0);\r
464         self.piece_pos = '0 0 0';\r
465         self.piece_type = 0;\r
466         self.next_piece = self.tet_lines = self.tet_score = 0;\r
467 \r
468 };\r
469 \r
470 void () Tet_GameOver =\r
471 {\r
472         centerprint(self, "Game Over");\r
473         self.tetris_on = 0;\r
474         ResetTetris();\r
475         self.movetype = MOVETYPE_WALK;\r
476 };\r
477 \r
478 \r
479 \r
480 /*\r
481 *********************************\r
482 \r
483 Game Mechanics\r
484 \r
485 *********************************\r
486 */\r
487 float() RandomPiece =\r
488 {\r
489         return floor(random() * PIECES) + 1;\r
490 };\r
491 \r
492 void(float n) TetAddScore =\r
493 {\r
494         self.tet_score = self.tet_score + n;\r
495         if (self.tet_score > tet_high_score)\r
496                 tet_high_score = self.tet_score;\r
497 };\r
498 float CheckMetrics(float piece, float orgx, float orgy, float rot) =\r
499 {\r
500         // check to see if the piece, if moved to the locations will overlap\r
501 \r
502         float x, y;\r
503         // why did I start counting from 1, damnit\r
504         orgx = orgx - 1;\r
505         orgy = orgy - 1;\r
506 \r
507         for (y = 1; y < 5; y = y + 1)\r
508         {\r
509                 for (x = 1; x < 5; x = x + 1)\r
510                 {\r
511                         if (PieceMetric(x, y, rot, piece))\r
512                         {\r
513                                 if (GetSquare(x + orgx, y + orgy))\r
514                                         return FALSE; // uhoh, gonna hit something.\r
515                                 if (x+orgx<1 || x+orgx > TET_WIDTH || y+orgy<1 || y+orgy> TET_LINES)\r
516                                         return FALSE; // ouside the level\r
517                         }\r
518                 }\r
519         }\r
520         return TRUE;\r
521 }\r
522 \r
523 void ClearPiece(float piece, float orgx, float orgy, float rot) =\r
524 {\r
525 \r
526         float x, y;\r
527         // why did I start counting from 1, damnit\r
528         orgx = orgx - 1;\r
529         orgy = orgy - 1;\r
530 \r
531         for (y = 1; y < 5; y = y + 1)\r
532         {\r
533                 for (x = 1; x < 5; x = x + 1)\r
534                 {\r
535                         if (PieceMetric(x, y, rot, piece))\r
536                         {\r
537                                 SetSquare(x + orgx, y + orgy, 0);\r
538                         }\r
539                 }\r
540         }\r
541 }\r
542 void CementPiece(float piece, float orgx, float orgy, float rot) =\r
543 {\r
544         float color;\r
545         float x, y;\r
546         // why did I start counting from 1, damnit\r
547         orgx = orgx - 1;\r
548         orgy = orgy - 1;\r
549 \r
550         color = piece & 3;\r
551         if (color == 0) // 4\r
552                 color = 1;\r
553 \r
554         for (y = 1; y < 5; y = y + 1)\r
555         {\r
556                 for (x = 1; x < 5; x = x + 1)\r
557                 {\r
558                         if (PieceMetric(x, y, rot, piece))\r
559                         {\r
560                                 SetSquare(x + orgx, y + orgy, color);\r
561                         }\r
562                 }\r
563         }\r
564 }\r
565 \r
566 float LINE_LOW = 349525;\r
567 float LINE_HIGH = 699050; // above number times 2\r
568 \r
569 void() CompletedLines =\r
570 {\r
571         float y, cleared, ln;\r
572 \r
573         cleared = 0;\r
574         y = TET_LINES;\r
575         while(y >= 1)\r
576         {\r
577                 ln = GetLine(y);\r
578                 if (((ln & LINE_LOW) | ((ln & LINE_HIGH)/2)) == LINE_LOW)\r
579                         cleared = cleared + 1;\r
580                 else\r
581                         y = y - 1;\r
582                 ln = GetLine(y - cleared);\r
583                 SetLine(y, ln);\r
584         }\r
585         self.tet_lines = self.tet_lines + cleared;\r
586         TetAddScore(cleared * cleared * 10);\r
587 };\r
588 \r
589 void(float keyss) HandleGame =\r
590 {\r
591 \r
592         // first off, we need to see if we need a new piece\r
593         vector check_pos;\r
594         float brand_new;\r
595         brand_new = 0;\r
596         if (self.tet_time > time)\r
597                 return;\r
598         self.tet_time = time + 0.1;\r
599 \r
600 \r
601         if (self.piece_type == 0)\r
602         {\r
603                 self.piece_pos = '5 1 0'; // that's about middle top, we count from 1 ARGH\r
604                 if (self.next_piece)\r
605                         self.piece_type = self.next_piece;\r
606                 else\r
607                         self.piece_type = RandomPiece();\r
608                 self.next_piece =  RandomPiece();\r
609                 keyss = 0; // no movement first frame\r
610                 self.tet_autodown = time + 0.2;\r
611                 brand_new = 1;\r
612         }\r
613         else\r
614                 ClearPiece(self.piece_type, self.piece_pos_x, self.piece_pos_y, self.piece_pos_z);\r
615 \r
616         // next we need to check the piece metrics against what's on the level\r
617         // based on the key order\r
618 \r
619         check_pos = self.piece_pos;\r
620 \r
621         if (keyss & TETKEY_RIGHT)\r
622                 check_pos_x = check_pos_x + 1;\r
623         else if (keyss & TETKEY_LEFT)\r
624                 check_pos_x = check_pos_x - 1;\r
625         else if (keyss & TETKEY_ROTRIGHT)\r
626                 check_pos_z = check_pos_z + 1;\r
627         else if (keyss & TETKEY_ROTLEFT)\r
628                 check_pos_z = check_pos_z - 1;\r
629         // bounds check\r
630         if (check_pos_z > 3)\r
631                 check_pos_z = 0;\r
632         else if (check_pos_z < 0)\r
633                 check_pos_z = 3;\r
634 \r
635         // reality check\r
636         if (CheckMetrics(self.piece_type, check_pos_x, check_pos_y, check_pos_z))\r
637                 self.piece_pos = check_pos;\r
638         else if (brand_new)\r
639                 Tet_GameOver();\r
640         check_pos = self.piece_pos;\r
641         if (keyss & TETKEY_DOWN)\r
642                 check_pos_y = check_pos_y + 1;\r
643         else if (self.tet_autodown < time)\r
644         {\r
645                 check_pos_y = check_pos_y + 1;\r
646                 self.tet_autodown = time + 1 / (floor(self.tet_lines / 20) + 1);\r
647         }\r
648         if (CheckMetrics(self.piece_type, check_pos_x, check_pos_y, check_pos_z))\r
649                 self.piece_pos = check_pos;\r
650         else\r
651         {\r
652                 CementPiece(self.piece_type, self.piece_pos_x, self.piece_pos_y, self.piece_pos_z);\r
653                 TetAddScore(1);\r
654                 CompletedLines();\r
655                 self.piece_type = 0;\r
656                 return;\r
657         }\r
658         CementPiece(self.piece_type, self.piece_pos_x, self.piece_pos_y, self.piece_pos_z);\r
659 };\r
660 \r
661 /*\r
662 *********************************\r
663 \r
664 Important Linking Into Quake stuff\r
665 \r
666 *********************************\r
667 */\r
668 \r
669 \r
670 void() TetrisImpulses =\r
671 {\r
672         if (self.impulse == 200)\r
673         {\r
674                 self.tetris_on = 1;\r
675                 ResetTetris();\r
676                 self.tet_org = self.origin;\r
677                 self.movetype = MOVETYPE_NOCLIP;\r
678                 stuffcmd(self, "cl_bob 0\ncl_rollangle 0\n");\r
679         }\r
680 };\r
681 \r
682 \r
683 float() TetrisPreFrame =\r
684 {\r
685         if (!self.tetris_on)\r
686                 return 0;\r
687 \r
688         self.tet_org = self.origin;\r
689         if (self.tet_time > time)\r
690                 return 1;\r
691         Draw_Tetris();\r
692         return 1;\r
693 \r
694 };\r
695 float(float v) frik_anglemoda =\r
696 {\r
697         return v - floor(v/360) * 360;\r
698 };\r
699 float (float y1, float y2) angcompa =\r
700 {\r
701         y1 = frik_anglemoda(y1);\r
702         y2 = frik_anglemoda(y2);\r
703 \r
704         local float answer;\r
705         answer = y1 - y2;\r
706         if (answer > 180)\r
707                 answer = answer - 360;\r
708         else if (answer < -180)\r
709                 answer = answer + 360;\r
710         return answer;\r
711 };\r
712 \r
713 \r
714 float() TetrisPostFrame =\r
715 {\r
716         vector mov;\r
717         float keysa, norm;\r
718 \r
719         keysa = 0;\r
720 \r
721         if (!self.tetris_on)\r
722                 return 0;\r
723         if (self.origin != self.tet_org)\r
724         {\r
725                 mov = vectoangles(self.origin - self.tet_org);\r
726                 self.origin = self.tet_org;\r
727 \r
728                 norm = angcompa(self.v_angle_y, mov_y);\r
729 \r
730                 if (norm > -80 && norm < 80)\r
731                         keysa = keysa | TETKEY_UP;\r
732                 if (norm > 10 && norm < 170)\r
733                         keysa = keysa | TETKEY_RIGHT;\r
734                 if (norm > 100  || norm < -260)\r
735                         keysa = keysa | TETKEY_DOWN;\r
736                 if (norm > -170 && norm < -10)\r
737                         keysa = keysa | TETKEY_LEFT;\r
738         }\r
739         if (self.button0)\r
740                 keysa = keysa | TETKEY_ROTRIGHT;\r
741         if (self.button2)\r
742                 keysa = keysa | TETKEY_ROTLEFT;\r
743         HandleGame(keysa);\r
744         return 1;\r
745 };\r
746 \r