11 float autocvar_g_bastet;
14 float tet_vs_current_id;
15 float tet_vs_current_timeout;
16 .float tet_vs_id, tet_vs_addlines;
17 .float tet_highest_line;
18 .float tetris_on, tet_gameovertime, tet_drawtime, tet_autodown;
20 .float piece_type, next_piece, tet_score, tet_lines;
21 .float tet_piece_bucket;
26 // 3 = waiting for VS players
28 var float tet_high_score = 0;
30 vector TET_START_PIECE_POS = '5 1 0';
34 float TET_BORDER = 139;
35 float TET_BLOCK = 133;
36 float TET_SPACE = 160; // blankness
41 float TETKEY_DOWN = 2;
42 float TETKEY_LEFT = 4;
43 float TETKEY_RIGHT = 8;
44 float TETKEY_ROTLEFT = 16;
45 float TETKEY_ROTRIGHT = 32;
46 float TETKEY_DROP = 64;
47 string TET_PADDING_RIGHT = "\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0"; // get away from crosshair
51 .float line1, line2, line3, line4, line5, line6, line7,
52 line8, line9, line10, line11, line12, line13, line14, line15,
53 line16, line17, line18, line19, line20;
56 float SVC_CENTERPRINTa = 26;
60 return ((floor((self.tet_lines / 10)) + 1));
63 void tetsnd(string snd)
65 play2(self, strcat("sounds/tetris/", snd));
69 *********************************
73 *********************************
75 void SetLine(float ln, float vl)
119 float GetLine(float ln)
165 float GetXBlock(float x, float dat)
170 return (dat & 12) / 4;
172 return (dat & 48) / 16;
174 return (dat & 192) / 64;
176 return (dat & 768) / 256;
178 return (dat & 3072) / 1024;
180 return (dat & 12288) / 4096;
182 return (dat & 49152) / 16384;
184 return (dat & 196608) / 65536;
186 return (dat & 786432) / 262144;
191 float SetXBlock(float x, float dat, float new)
194 return (dat - (dat & 3)) | new;
196 return (dat - (dat & 12)) | (new*4);
198 return (dat - (dat & 48)) | (new*16);
200 return (dat - (dat & 192)) | (new*64);
202 return (dat - (dat & 768)) | (new*256);
204 return (dat - (dat & 3072)) | (new*1024);
206 return (dat - (dat & 12288)) | (new*4096);
208 return (dat - (dat & 49152)) | (new*16384);
210 return (dat - (dat & 196608)) | (new*65536);
212 return (dat - (dat & 786432)) | (new*262144);
218 float GetSquare(float x, float y)
220 return GetXBlock(x, GetLine(y));
223 void SetSquare(float x, float y, float val)
228 dat = SetXBlock(x, dat, val & 3);
232 vector PieceShape(float pc)
237 return '1 21 0'; // J
239 return '21 1 0'; // L
241 return '85 0 0'; // I
243 return '5 20 0'; // Z
245 return '20 5 0'; // S
247 return '4 21 0'; // T
252 vector PieceCenter(float pc)
255 return '1.5 1.5 0'; // O
261 return '2.5 1.5 0'; // I
272 // do x 1..4 and y 1..4 in case of rotation
273 float PieceMetric(float x, float y, float rot, float pc)
279 // return bits of a piece
280 wid = piece_dat_z + 1;
281 piece_dat = PieceCenter(pc);
282 if (rot == 1) // 90 degrees
284 // x+cx, y+cy -> -y+cx, x+cy
285 // X, Y -> -Y+cy+cx, X-cx+cy
289 y = x - piece_dat_x + piece_dat_y;
290 x = -t + piece_dat_x + piece_dat_y;
292 else if (rot == 2)//180
294 x = 2 * piece_dat_x - x;
295 y = 2 * piece_dat_y - y;
297 else if (rot == 3) // 270
299 // x+cx, y+cy -> y+cx, -x+cy
300 // X, Y -> Y-cy+cx, -X+cx+cy
304 y = -x + piece_dat_y + piece_dat_x;
305 x = t - piece_dat_y + piece_dat_x;
307 if (x < 1 || y < 1 || x > 4 || y > 2)
309 piece_dat = PieceShape(pc);
311 return GetXBlock(x, piece_dat_x); // first row
313 return GetXBlock(x, piece_dat_y); // second row
315 return 0; // illegal parms
318 *********************************
322 *********************************
326 /* some prydon gate functions to make life easier....
328 somewhat modified because we don't need all the fanciness Prydon Gate is capable of
332 void WriteTetrisString(string s)
334 WriteUnterminatedString(MSG_ONE, strconv(0, 2, 2, s));
337 float pnum(float num, float dig)
342 WriteChar(MSG_ONE, 173);
346 num = num - (f * 10);
348 dig = pnum(f, dig+1);
352 for (i = 0; i < (5 - dig); i = i + 1)
353 WriteChar(MSG_ONE, TET_SPACE);
355 WriteChar(MSG_ONE, 176 + num);
359 void DrawLine(float ln)
362 WriteChar(MSG_ONE, TET_BORDER);
364 for (x = 1; x <= TET_WIDTH; x = x + 1)
366 d = GetSquare(x, ln);
369 WriteChar(MSG_ONE, '^');
370 WriteChar(MSG_ONE, d * d - 2 * d + 50); // 1, 2, 5
371 WriteChar(MSG_ONE, TET_BLOCK);
374 WriteChar(MSG_ONE, TET_SPACE);
376 WriteChar(MSG_ONE, '^');
377 WriteChar(MSG_ONE, '7');
378 WriteChar(MSG_ONE, TET_BORDER);
381 void DrawPiece(float pc, float ln)
383 float x, d, piece_ln, pcolor;
385 pcolor = mod(pc, 3) + 1;
386 WriteChar(MSG_ONE, TET_SPACE); // pad to 6
388 piece_dat = PieceShape(pc);
390 piece_ln = piece_dat_x;
392 piece_ln = piece_dat_y;
393 for (x = 1; x <= 4; x = x + 1)
395 d = GetXBlock(x, piece_ln) * pcolor;
398 WriteChar(MSG_ONE, '^');
399 WriteChar(MSG_ONE, d * d - 2 * d + 50); // 1, 2, 5
400 WriteChar(MSG_ONE, TET_BLOCK);
403 WriteChar(MSG_ONE, TET_SPACE);
405 WriteChar(MSG_ONE, TET_SPACE); // pad to 6
412 WriteChar(MSG_ONE, SVC_CENTERPRINTa);
413 if(autocvar_g_bastet)
415 WriteTetrisString("NEVER GONNA GIVE YOU");
416 WriteChar(MSG_ONE, 10);
419 for (i = 1; i <= (TET_WIDTH + 2); i = i + 1)
420 WriteChar(MSG_ONE, TET_BORDER);
421 WriteTetrisString(" ");
422 WriteUnterminatedString(MSG_ONE, TET_PADDING_RIGHT);
423 WriteChar(MSG_ONE, 10);
424 for (i = 1; i <= TET_LINES; i = i + 1)
426 if(self.tetris_on == 2)
427 WriteTetrisString(" GAME OVER ");
428 else if(self.tetris_on == 3)
429 WriteTetrisString("PLEASE WAIT");
433 WriteTetrisString(autocvar_g_bastet ? " THAT " : " NEXT ");
435 DrawPiece(self.next_piece, 1);
437 DrawPiece(self.next_piece, 2);
439 WriteTetrisString(" LINES");
441 pnum(self.tet_lines, 0);
443 WriteTetrisString(" SCORE");
445 pnum(self.tet_score, 0);
447 WriteTetrisString(" HIGH ");
449 WriteTetrisString(" SCORE");
451 pnum(tet_high_score, 0);
453 WriteTetrisString(" LEVEL");
455 pnum(Tetris_Level(), 0);
457 WriteTetrisString(" ");
458 WriteUnterminatedString(MSG_ONE, TET_PADDING_RIGHT);
459 WriteChar(MSG_ONE, 10);
463 for (i = 1; i <= (TET_WIDTH + 2); i = i + 1)
464 WriteChar(MSG_ONE, TET_BORDER);
465 WriteTetrisString(" ");
466 WriteUnterminatedString(MSG_ONE, TET_PADDING_RIGHT);
467 WriteChar(MSG_ONE, 10);
472 WriteChar(MSG_ONE, 10);
473 WriteChar(MSG_ONE, 10);
474 if(self.tetris_on == 3)
476 WriteUnterminatedString(MSG_ONE, strcat("WAITING FOR OTHERS (", ftos(ceil(tet_vs_current_timeout - time)), " SEC)\n"));
479 WriteChar(MSG_ONE, 10);
480 FOR_EACH_REALCLIENT(head) if(head.tetris_on) if(head.tet_vs_id == self.tet_vs_id)
483 WriteUnterminatedString(MSG_ONE, ">");
485 WriteUnterminatedString(MSG_ONE, " ");
486 if(head.tetris_on == 2)
487 WriteUnterminatedString(MSG_ONE, " X_X");
489 pnum(head.tet_highest_line, 0);
490 WriteUnterminatedString(MSG_ONE, " ");
491 WriteUnterminatedString(MSG_ONE, head.netname);
492 WriteChar(MSG_ONE, 10);
496 WriteChar(MSG_ONE, 0);
499 *********************************
503 *********************************
511 for (i=1; i<=TET_LINES; i = i + 1)
513 self.piece_pos = '0 0 0';
515 self.next_piece = self.tet_lines = self.tet_score = 0;
516 self.tet_piece_bucket = 0;
521 centerprint(self, " ");
525 self.movetype = MOVETYPE_WALK;
532 for(r = 1; r <= TET_LINES; ++r)
536 for(c = 1; c <= TET_WIDTH; ++c)
538 print(ftos(GetXBlock(c, l)));
544 float BastetEvaluate()
549 float occupied_count;
551 float score_save, occupied_save, occupied_count_save;
556 // adds a bonus for each free dot above the occupied blocks profile
557 occupied_count = TET_WIDTH;
560 for(i = 1; i <= TET_LINES; ++i)
569 occupied_save = occupied;
570 occupied_count_save = occupied_count;
572 for(j = 1; j <= TET_WIDTH; ++j)
576 if(!GetXBlock(j, occupied))
578 occupied = SetXBlock(j, occupied, 1);
584 score += 10000 * occupied_count;
588 occupied = occupied_save;
589 occupied_count = occupied_count_save;
590 score = score_save + 100000000 + 10000 * TET_WIDTH + 1000;
595 score += 1000 * height;
600 float CheckMetrics(float piece, float orgx, float orgy, float rot);
601 void ClearPiece(float piece, float orgx, float orgy, float rot);
602 void CementPiece(float piece, float orgx, float orgy, float rot);
603 float bastet_profile_evaluate_time;
604 float BastetSearch(float buf, float pc, float x, float y, float rot, float move_bias)
605 // returns best score, or -1 if position is impossible
612 return 0; // DO NOT WANT
614 if(x < 1 || x > TET_WIDTH || y < 1 || y > TET_LINES)
615 return -1; // impossible
619 // did we already try?
620 b = x + (TET_WIDTH+2) * (y + (TET_LINES+2) * rot);
621 r = bufstr_get(buf, b);
622 if(r != "") // already tried
625 bufstr_set(buf, b, "0"); // in case we READ that, not that bad - we already got that value in another branch then anyway
627 #define ALWAYS_CHECK_METRICS
628 #ifdef ALWAYS_CHECK_METRICS
629 if(CheckMetrics(pc, x, y, rot))
634 s = BastetSearch(buf, pc, x-1, y, rot, move_bias - 1); if(s > sm) sm = s;
635 s = BastetSearch(buf, pc, x+1, y, rot, move_bias - 1); if(s > sm) sm = s;
636 s = BastetSearch(buf, pc, x, y, rot+1, move_bias - 1); if(s > sm) sm = s;
637 s = BastetSearch(buf, pc, x, y, rot-1, move_bias - 1); if(s > sm) sm = s;
639 #ifndef ALWAYS_CHECK_METRICS
640 if(CheckMetrics(pc, x, y+1, rot))
643 s = BastetSearch(buf, pc, x, y+1, rot, move_bias + 2); if(s > sm) sm = s;
644 #ifndef ALWAYS_CHECK_METRICS
652 //print(sprintf("MAY CEMENT AT: %d %d %d\n", x, y, rot));
653 // moving down did not work - that means we can fixate the block here
654 var float t1 = gettime(GETTIME_HIRES);
656 CementPiece(pc, x, y, rot);
657 s = BastetEvaluate();
658 ClearPiece(pc, x, y, rot);
660 var float t2 = gettime(GETTIME_HIRES);
661 bastet_profile_evaluate_time += (t2 - t1);
666 #ifdef ALWAYS_CHECK_METRICS
668 sm = -1; // impassible
671 bufstr_set(buf, b, ftos(sm));
676 float bastet_piece[7];
677 float bastet_score[7];
678 float bastet_piecetime[7];
683 bastet_profile_evaluate_time = 0;
684 var float t1 = gettime(GETTIME_HIRES);
686 b = buf_create(); bastet_piece[0] = 1; bastet_score[0] = BastetSearch(b, 1, TET_START_PIECE_POS_x, 1+TET_START_PIECE_POS_y, TET_START_PIECE_POS_y, TET_WIDTH) + 100 * random() + bastet_piecetime[0]; buf_del(b);
687 b = buf_create(); bastet_piece[1] = 2; bastet_score[1] = BastetSearch(b, 2, TET_START_PIECE_POS_x, 1+TET_START_PIECE_POS_y, TET_START_PIECE_POS_y, TET_WIDTH) + 100 * random() + bastet_piecetime[1]; buf_del(b);
688 b = buf_create(); bastet_piece[2] = 3; bastet_score[2] = BastetSearch(b, 3, TET_START_PIECE_POS_x, 1+TET_START_PIECE_POS_y, TET_START_PIECE_POS_y, TET_WIDTH) + 100 * random() + bastet_piecetime[2]; buf_del(b);
689 b = buf_create(); bastet_piece[3] = 4; bastet_score[3] = BastetSearch(b, 4, TET_START_PIECE_POS_x, 1+TET_START_PIECE_POS_y, TET_START_PIECE_POS_y, TET_WIDTH) + 100 * random() + bastet_piecetime[3]; buf_del(b);
690 b = buf_create(); bastet_piece[4] = 5; bastet_score[4] = BastetSearch(b, 5, TET_START_PIECE_POS_x, 1+TET_START_PIECE_POS_y, TET_START_PIECE_POS_y, TET_WIDTH) + 100 * random() + bastet_piecetime[4]; buf_del(b);
691 b = buf_create(); bastet_piece[5] = 6; bastet_score[5] = BastetSearch(b, 6, TET_START_PIECE_POS_x, 1+TET_START_PIECE_POS_y, TET_START_PIECE_POS_y, TET_WIDTH) + 100 * random() + bastet_piecetime[5]; buf_del(b);
692 b = buf_create(); bastet_piece[6] = 7; bastet_score[6] = BastetSearch(b, 7, TET_START_PIECE_POS_x, 1+TET_START_PIECE_POS_y, TET_START_PIECE_POS_y, TET_WIDTH) + 100 * random() + bastet_piecetime[6]; buf_del(b);
694 var float t2 = gettime(GETTIME_HIRES);
695 dprint(sprintf("Time taken: %.6f seconds (of this, ev = %.2f%%)\n", t2 - t1, 100 * bastet_profile_evaluate_time / (t2 - t1)));
701 for(i = 0; i < 7; ++i)
703 print(sprintf("piece %s value = %d\n", substring("OJLIZST", bastet_piece[i]-1, 1), bastet_score[i]));
707 for(i = 0; i < 7; ++i)
712 for(j = i + 1; j < 7; ++j)
714 if(bastet_score[j] < s)
723 bastet_score[k] = bastet_score[i];
724 bastet_piece[k] = bastet_piece[i];
741 for(i = 0; i < 7; ++i)
744 bastet_piecetime[i] = 0.2 * bastet_piecetime[i];
746 bastet_piecetime[i] = 1.8 * bastet_piecetime[i] + 1000;
754 *********************************
758 *********************************
760 .float tet_piece_bucket;
768 if(self.tet_piece_bucket > 1)
770 p = mod(self.tet_piece_bucket, 7);
771 self.tet_piece_bucket = floor(self.tet_piece_bucket / 7);
776 p = floor(random() * 7);
779 for(i = 6; i > 0; --i)
781 q = floor(random() * i);
782 for(j = 0; j <= q; ++j)
793 self.tet_piece_bucket = b;
798 void TetAddScore(float n)
800 self.tet_score = self.tet_score + n * Tetris_Level();
801 if (self.tet_score > tet_high_score)
802 tet_high_score = self.tet_score;
804 float CheckMetrics(float piece, float orgx, float orgy, float rot) /*FIXDECL*/
806 // check to see if the piece, if moved to the locations will overlap
809 // why did I start counting from 1, damnit
813 for (y = 0; y < 5; y = y + 1)
815 for (x = 0; x < 5; x = x + 1)
817 if (PieceMetric(x, y, rot, piece))
819 if (GetSquare(x + orgx, y + orgy))
820 return FALSE; // uhoh, gonna hit something.
821 if (x+orgx<1 || x+orgx > TET_WIDTH || y+orgy<1 || y+orgy> TET_LINES)
822 return FALSE; // ouside the level
829 void ClearPiece(float piece, float orgx, float orgy, float rot) /*FIXDECL*/
833 // why did I start counting from 1, damnit
837 for (y = 0; y < 5; y = y + 1)
839 for (x = 0; x < 5; x = x + 1)
841 if (PieceMetric(x, y, rot, piece))
843 SetSquare(x + orgx, y + orgy, 0);
848 void CementPiece(float piece, float orgx, float orgy, float rot) /*FIXDECL*/
852 // why did I start counting from 1, damnit
856 pcolor = mod(piece, 3) + 1;
858 for (y = 0; y < 5; y = y + 1)
860 for (x = 0; x < 5; x = x + 1)
862 if (PieceMetric(x, y, rot, piece))
864 SetSquare(x + orgx, y + orgy, pcolor);
870 float LINE_LOW = 349525;
871 float LINE_HIGH = 699050; // above number times 2
873 void AddLines(float n)
878 FOR_EACH_REALCLIENT(head) if(head != self) if(head.tetris_on) if(head.tet_vs_id == self.tet_vs_id)
879 head.tet_vs_addlines += n;
882 void CompletedLines()
884 float y, cleared, ln, added, pos, i;
891 if (((ln & LINE_LOW) | ((ln & LINE_HIGH)/2)) == LINE_LOW)
892 cleared = cleared + 1;
895 ln = GetLine(y - cleared);
901 else if(cleared >= 1)
902 AddLines(cleared - 1);
904 self.tet_lines = self.tet_lines + cleared;
905 TetAddScore(cleared * cleared * 10);
907 added = self.tet_vs_addlines;
908 self.tet_vs_addlines = 0;
912 for(y = 1; y <= TET_LINES - added; ++y)
914 SetLine(y, GetLine(y + added));
916 for(y = max(1, TET_LINES - added + 1); y <= TET_LINES; ++y)
918 pos = floor(random() * TET_WIDTH);
920 for(i = 1; i <= TET_WIDTH; ++i)
922 ln = SetXBlock(i, ln, floor(random() * 3 + 1));
927 self.tet_highest_line = 0;
928 for(y = 1; y <= TET_LINES; ++y)
931 self.tet_highest_line = TET_LINES + 1 - y;
937 else if(cleared >= 4)
945 void HandleGame(float keyss)
948 // first off, we need to see if we need a new piece
957 if (self.piece_type == 0)
959 self.piece_pos = TET_START_PIECE_POS; // that's about middle top, we count from 1 ARGH
961 if(autocvar_g_bastet)
963 self.piece_type = BastetPiece();
964 self.next_piece = bastet_piece[6];
969 self.piece_type = self.next_piece;
971 self.piece_type = RandomPiece();
972 self.next_piece = RandomPiece();
974 keyss = 0; // no movement first frame
975 self.tet_autodown = time + 0.2;
979 ClearPiece(self.piece_type, self.piece_pos_x, self.piece_pos_y, self.piece_pos_z);
981 // next we need to check the piece metrics against what's on the level
982 // based on the key order
984 old_pos = check_pos = self.piece_pos;
988 if (keyss & TETKEY_RIGHT)
990 check_pos_x = check_pos_x + 1;
993 else if (keyss & TETKEY_LEFT)
995 check_pos_x = check_pos_x - 1;
998 else if (keyss & TETKEY_ROTRIGHT)
1000 check_pos_z = check_pos_z + 1;
1001 piece_data = PieceShape(self.piece_type);
1005 else if (keyss & TETKEY_ROTLEFT)
1007 check_pos_z = check_pos_z - 1;
1008 piece_data = PieceShape(self.piece_type);
1013 if (check_pos_z > 3)
1015 else if (check_pos_z < 0)
1019 if (CheckMetrics(self.piece_type, check_pos_x, check_pos_y, check_pos_z))
1020 self.piece_pos = check_pos;
1024 self.tet_gameovertime = time + 5;
1029 for(i = 1; i <= nudge; ++i)
1031 if(CheckMetrics(self.piece_type, check_pos_x + i, check_pos_y, check_pos_z))
1032 self.piece_pos = check_pos + '1 0 0' * i;
1033 else if(CheckMetrics(self.piece_type, check_pos_x - i, check_pos_y, check_pos_z))
1034 self.piece_pos = check_pos - '1 0 0' * i;
1040 check_pos = self.piece_pos;
1041 if(keyss & TETKEY_DROP)
1043 // drop to bottom, but do NOT cement it yet
1044 // this allows sliding it
1046 while(CheckMetrics(self.piece_type, check_pos_x, check_pos_y + 1, check_pos_z))
1048 self.tet_autodown = time + 2 / (1 + Tetris_Level());
1050 else if (keyss & TETKEY_DOWN)
1052 check_pos_y = check_pos_y + 1;
1053 self.tet_autodown = time + 2 / (1 + Tetris_Level());
1055 else if (self.tet_autodown < time)
1057 check_pos_y = check_pos_y + 1;
1058 self.tet_autodown = time + 2 / (1 + Tetris_Level());
1060 if (CheckMetrics(self.piece_type, check_pos_x, check_pos_y, check_pos_z))
1062 if(old_pos != check_pos)
1063 self.tet_drawtime = 0;
1064 self.piece_pos = check_pos;
1068 CementPiece(self.piece_type, self.piece_pos_x, self.piece_pos_y, self.piece_pos_z);
1071 self.piece_type = 0;
1072 self.tet_drawtime = 0;
1075 CementPiece(self.piece_type, self.piece_pos_x, self.piece_pos_y, self.piece_pos_z);
1079 *********************************
1081 Important Linking Into Quake stuff
1083 *********************************
1087 void TetrisImpulse()
1089 if(self.tetris_on == 0 || self.tetris_on == 2) // from "off" or "game over"
1093 if(time < tet_vs_current_timeout)
1096 self.tet_vs_id = tet_vs_current_id;
1100 // start new VS game
1101 ++tet_vs_current_id;
1102 tet_vs_current_timeout = time + 15;
1103 self.tet_vs_id = tet_vs_current_id;
1104 bprint("^1TET^7R^1IS: ", self.netname, "^1 started a new game. Do ^7impulse 100^1 to join.\n");
1106 self.tet_highest_line = 0;
1108 self.tet_org = self.origin;
1109 self.movetype = MOVETYPE_NOCLIP;
1111 else if(self.tetris_on == 1) // from "on"
1119 float TetrisPreFrame()
1121 if (!self.tetris_on)
1124 self.tet_org = self.origin;
1125 if (self.tet_drawtime > time)
1128 if(self.tetris_on == 3)
1129 self.tet_drawtime = ceil(time - tet_vs_current_timeout + 0.1) + tet_vs_current_timeout;
1131 self.tet_drawtime = time + 0.5;
1134 float frik_anglemoda(float v)
1136 return v - floor(v/360) * 360;
1138 float angcompa(float y1, float y2)
1140 y1 = frik_anglemoda(y1);
1141 y2 = frik_anglemoda(y2);
1146 answer = answer - 360;
1147 else if (answer < -180)
1148 answer = answer + 360;
1152 .float tetkey_down, tetkey_rotright, tetkey_left, tetkey_right, tetkey_rotleft, tetkey_drop;
1154 float TetrisKeyRepeat(.float fld, float f)
1158 if(self.fld == 0) // initial key press
1160 self.fld = time + 0.3;
1163 else if(time > self.fld)
1165 self.fld = time + 0.1;
1170 // repeating too fast
1181 float TetrisPostFrame()
1187 if (!self.tetris_on)
1190 if(self.tetris_on == 2 && time > self.tet_gameovertime)
1196 if(self.tetris_on == 3 && time > tet_vs_current_timeout)
1198 self.tetris_on = 1; // start VS game
1199 self.tet_drawtime = 0;
1202 setorigin(self, self.tet_org);
1203 self.movetype = MOVETYPE_NONE;
1205 if(self.tetris_on == 1)
1207 if(TetrisKeyRepeat(tetkey_down, self.movement_x < 0))
1208 keysa |= TETKEY_DOWN;
1210 if(TetrisKeyRepeat(tetkey_rotright, self.movement_x > 0))
1211 keysa |= TETKEY_ROTRIGHT;
1213 if(TetrisKeyRepeat(tetkey_left, self.movement_y < 0))
1214 keysa |= TETKEY_LEFT;
1216 if(TetrisKeyRepeat(tetkey_right, self.movement_y > 0))
1217 keysa |= TETKEY_RIGHT;
1219 if(TetrisKeyRepeat(tetkey_rotleft, self.BUTTON_CROUCH))
1220 keysa |= TETKEY_ROTLEFT;
1222 if(TetrisKeyRepeat(tetkey_drop, self.BUTTON_JUMP))
1223 keysa |= TETKEY_DROP;