X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fg_tetris.qc;h=d194c94314279ecb9412f342c322fb359780d317;hb=a86fa5a48ac75276db3da34fd3721678517c62fa;hp=5c65847eadf9d062ab2c8e58ae47df842f4a1a9e;hpb=0e7ed909bffb4ff21f0c68d163edfc17487e380a;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/g_tetris.qc b/qcsrc/server/g_tetris.qc index 5c65847ea..d194c9431 100644 --- a/qcsrc/server/g_tetris.qc +++ b/qcsrc/server/g_tetris.qc @@ -26,8 +26,11 @@ float tet_vs_current_timeout; var float tet_high_score = 0; -float TET_LINES = 20; +vector TET_START_PIECE_POS = '5 1 0'; +float TET_LINES = 22; +float TET_DISPLAY_LINES = 20; float TET_WIDTH = 10; +string TET_EMPTY_LINE = "0000000000"; // must match TET_WIDTH //character values float TET_BORDER = 139; float TET_BLOCK = 133; @@ -46,17 +49,14 @@ string TET_PADDING_RIGHT = "\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0 float PIECES = 7; -.float line1, line2, line3, line4, line5, line6, line7, -line8, line9, line10, line11, line12, line13, line14, line15, -line16, line17, line18, line19, line20; - +float tet_line_buf; float SVC_CENTERPRINTa = 26; float Tetris_Level() { return ((floor((self.tet_lines / 10)) + 1)); -}; +} void tetsnd(string snd) { @@ -70,173 +70,81 @@ Library Functions ********************************* */ -void SetLine(float ln, float vl) +void SetLine(float ln, string vl) { - if (ln == 1) - self.line1 = vl; - else if (ln == 2) - self.line2 = vl; - else if (ln == 3) - self.line3 = vl; - else if (ln == 4) - self.line4 = vl; - else if (ln == 5) - self.line5 = vl; - else if (ln == 6) - self.line6 = vl; - else if (ln == 7) - self.line7 = vl; - else if (ln == 8) - self.line8 = vl; - else if (ln == 9) - self.line9 = vl; - else if (ln == 10) - self.line10 = vl; - else if (ln == 11) - self.line11 = vl; - else if (ln == 12) - self.line12 = vl; - else if (ln == 13) - self.line13 = vl; - else if (ln == 14) - self.line14 = vl; - else if (ln == 15) - self.line15 = vl; - else if (ln == 16) - self.line16 = vl; - else if (ln == 17) - self.line17 = vl; - else if (ln == 18) - self.line18 = vl; - else if (ln == 19) - self.line19 = vl; - else if (ln == 20) - self.line20 = vl; -}; - -float GetLine(float ln) + if(ln < 1 || ln > TET_LINES) + error("WTF"); + bufstr_set(tet_line_buf, ln + TET_LINES * num_for_edict(self), vl); +} + +string GetLine(float ln) { - if (ln == 1) - return self.line1; - else if (ln == 2) - return self.line2; - else if (ln == 3) - return self.line3; - else if (ln == 4) - return self.line4; - else if (ln == 5) - return self.line5; - else if (ln == 6) - return self.line6; - else if (ln == 7) - return self.line7; - else if (ln == 8) - return self.line8; - else if (ln == 9) - return self.line9; - else if (ln == 10) - return self.line10; - else if (ln == 11) - return self.line11; - else if (ln == 12) - return self.line12; - else if (ln == 13) - return self.line13; - else if (ln == 14) - return self.line14; - else if (ln == 15) - return self.line15; - else if (ln == 16) - return self.line16; - else if (ln == 17) - return self.line17; - else if (ln == 18) - return self.line18; - else if (ln == 19) - return self.line19; - else if (ln == 20) - return self.line20; - else - return 0; -}; - -float GetXBlock(float x, float dat) -{ - if (x == 1) - return dat & 3; - else if (x == 2) - return (dat & 12) / 4; - else if (x == 3) - return (dat & 48) / 16; - else if (x == 4) - return (dat & 192) / 64; - else if (x == 5) - return (dat & 768) / 256; - else if (x == 6) - return (dat & 3072) / 1024; - else if (x == 7) - return (dat & 12288) / 4096; - else if (x == 8) - return (dat & 49152) / 16384; - else if (x == 9) - return (dat & 196608) / 65536; - else if (x == 10) - return (dat & 786432) / 262144; - else - return 0; -}; - -float SetXBlock(float x, float dat, float new) -{ - if (x == 1) - return (dat - (dat & 3)) | new; - else if (x == 2) - return (dat - (dat & 12)) | (new*4); - else if (x == 3) - return (dat - (dat & 48)) | (new*16); - else if (x == 4) - return (dat - (dat & 192)) | (new*64); - else if (x == 5) - return (dat - (dat & 768)) | (new*256); - else if (x == 6) - return (dat - (dat & 3072)) | (new*1024); - else if (x == 7) - return (dat - (dat & 12288)) | (new*4096); - else if (x == 8) - return (dat - (dat & 49152)) | (new*16384); - else if (x == 9) - return (dat - (dat & 196608)) | (new*65536); - else if (x == 10) - return (dat - (dat & 786432)) | (new*262144); - else - return dat; -}; + if(ln < 1 || ln > TET_LINES) + error("WTF"); + if(ln < 1 || ln > TET_LINES) + return TET_EMPTY_LINE; + return bufstr_get(tet_line_buf, ln + TET_LINES * num_for_edict(self)); +} + +float GetXBlock(float x, string dat) +{ + if(x < 1 || x > TET_WIDTH) + error("WTF"); + return stof(substring(dat, x-1, 1)); +} + +string SetXBlock(float x, string dat, float new) +{ + return strcat( + substring(dat, 0, x-1), + ftos(new), + substring(dat, x, -1) + ); +} float GetSquare(float x, float y) { return GetXBlock(x, GetLine(y)); -}; +} void SetSquare(float x, float y, float val) { - float dat; - + string dat; dat = GetLine(y); - dat = SetXBlock(x, dat, val & 3); + dat = SetXBlock(x, dat, val); SetLine(y, dat); -}; +} +float PieceColor(float pc) +{ + if (pc == 1) + return 3; // O + else if (pc == 2) + return 4; // J + else if (pc == 3) + return 7; // L // we don't have orange, let's use white instead! + else if (pc == 4) + return 5; // I + else if (pc == 5) + return 1; // Z + else if (pc == 6) + return 2; // S + else if (pc == 7) + return 6; // T + else + return 0; +} vector PieceShape(float pc) { if (pc == 1) - return '5 5 0'; // O + return '20 20 0'; // O else if (pc == 2) return '1 21 0'; // J else if (pc == 3) - return '21 1 0'; // L + return '16 21 0'; // L else if (pc == 4) - return '85 0 0'; // I + return '0 85 0'; // I else if (pc == 5) return '5 20 0'; // Z else if (pc == 6) @@ -246,17 +154,35 @@ vector PieceShape(float pc) else return '0 0 0'; } - +vector PieceSize(float pc) +{ + if (pc == 1) + return '2 2 0'; // O + else if (pc == 2) + return '3 2 0'; // J + else if (pc == 3) + return '3 2 0'; // L + else if (pc == 4) + return '4 1 0'; // I + else if (pc == 5) + return '3 2 0'; // Z + else if (pc == 6) + return '3 2 0'; // S + else if (pc == 7) + return '3 2 0'; // T + else + return '0 0 0'; +} vector PieceCenter(float pc) { if(pc == 1) - return '1.5 1.5 0'; // O + return '2.5 1.5 0'; // O else if (pc == 2) return '2 2 0'; // J else if (pc == 3) - return '2 1 0'; // L + return '2 2 0'; // L else if (pc == 4) - return '2.5 1.5 0'; // I + return '2.5 2.5 0'; // I else if (pc == 5) return '2 2 0'; // Z else if (pc == 6) @@ -271,12 +197,10 @@ vector PieceCenter(float pc) float PieceMetric(float x, float y, float rot, float pc) { float t; - vector piece_dat; - float wid; + vector ce; // return bits of a piece - wid = piece_dat_z + 1; - piece_dat = PieceCenter(pc); + ce = PieceCenter(pc); if (rot == 1) // 90 degrees { // x+cx, y+cy -> -y+cx, x+cy @@ -284,13 +208,13 @@ float PieceMetric(float x, float y, float rot, float pc) // x = X-cx // y = Y-cy t = y; - y = x - piece_dat_x + piece_dat_y; - x = -t + piece_dat_x + piece_dat_y; + y = x - ce_x + ce_y; + x = -t + ce_x + ce_y; } else if (rot == 2)//180 { - x = 2 * piece_dat_x - x; - y = 2 * piece_dat_y - y; + x = 2 * ce_x - x; + y = 2 * ce_y - y; } else if (rot == 3) // 270 { @@ -299,19 +223,104 @@ float PieceMetric(float x, float y, float rot, float pc) // x = X-cx // y = Y-cy t = y; - y = -x + piece_dat_y + piece_dat_x; - x = t - piece_dat_y + piece_dat_x; + y = -x + ce_y + ce_x; + x = t - ce_y + ce_x; } if (x < 1 || y < 1 || x > 4 || y > 2) return 0; - piece_dat = PieceShape(pc); + ce = PieceShape(pc); if (y == 1) - return GetXBlock(x, piece_dat_x); // first row + return !!(ce_x & pow(4, x-1)); // first row else if (y == 2) - return GetXBlock(x, piece_dat_y); // second row + return !!(ce_y & pow(4, x-1)); // second row else return 0; // illegal parms -}; +} +vector tet_piecemins; +vector tet_piecemaxs; +void PieceMinsMaxs(float rot, float pc) +{ + vector sz, ce; + float t; + vector v; + + sz = PieceSize(pc); + ce = PieceCenter(pc); + // 1 = 2..2 + // 2 = 2..3 + // 3 = 1..3 + // 4 = 1..4 + tet_piecemins_x = floor(3.0 - sz_x * 0.5); + tet_piecemaxs_x = floor(2.0 + sz_x * 0.5); + if(sz_y == 1) + { + // special case for "I" + tet_piecemins_y = tet_piecemaxs_y = 2; + } + else + { + tet_piecemins_y = 1; + tet_piecemaxs_y = sz_y; + } + //print(sprintf("ce%v sz%v mi%v ma%v\n", ce, sz, tet_piecemins, tet_piecemaxs)); + if (rot == 1) // 90 degrees + { + t = tet_piecemins_y; + tet_piecemins_y = -tet_piecemins_x + ce_y + ce_x; + tet_piecemins_x = t - ce_y + ce_x; + t = tet_piecemaxs_y; + tet_piecemaxs_y = -tet_piecemaxs_x + ce_y + ce_x; + tet_piecemaxs_x = t - ce_y + ce_x; + // swap mins_y, maxs_y + t = tet_piecemins_y; + tet_piecemins_y = tet_piecemaxs_y; + tet_piecemaxs_y = t; + // TODO OPTIMIZE + } + else if (rot == 2)//180 + { + v = tet_piecemins; + tet_piecemins = 2 * ce - tet_piecemaxs; + tet_piecemaxs = 2 * ce - v; + } + else if (rot == 3) // 270 + { + t = tet_piecemins_y; + tet_piecemins_y = tet_piecemins_x - ce_x + ce_y; + tet_piecemins_x = -t + ce_x + ce_y; + t = tet_piecemaxs_y; + tet_piecemaxs_y = tet_piecemaxs_x - ce_x + ce_y; + tet_piecemaxs_x = -t + ce_x + ce_y; + // swap mins_x, maxs_x + t = tet_piecemins_x; + tet_piecemins_x = tet_piecemaxs_x; + tet_piecemaxs_x = t; + // TODO OPTIMIZE + } +#ifdef VERIFY + print(vtos(tet_piecemins), "-"); + print(vtos(tet_piecemaxs), "\n"); + if(tet_piecemins_x > tet_piecemaxs_x) + error("inconsistent mins/maxs"); + if(tet_piecemins_y > tet_piecemaxs_y) + error("inconsistent mins/maxs"); + float i, j; + vector realmins, realmaxs; + realmins = '4 4 0'; + realmaxs = '1 1 0'; + for(i = 1; i <= 4; ++i) + for(j = 1; j <= 4; ++j) + if(PieceMetric(i, j, rot, pc)) + { + realmins_x = min(realmins_x, i); + realmins_y = min(realmins_y, j); + realmaxs_x = max(realmaxs_x, i); + realmaxs_y = max(realmaxs_y, j); + } + if(realmins != tet_piecemins || realmaxs != tet_piecemaxs) + error(sprintf("incorrect mins/maxs: %v %v in %d rot %d mins %v maxs %v\n", realmins, realmaxs, rot, pc, tet_piecemins, tet_piecemaxs)); +#endif +} /* ********************************* @@ -334,7 +343,7 @@ void WriteTetrisString(string s) float pnum(float num, float dig) { - local float f, i; + float f, i; if (num < 0) { WriteChar(MSG_ONE, 173); @@ -352,7 +361,7 @@ float pnum(float num, float dig) } WriteChar(MSG_ONE, 176 + num); return dig; -}; +} void DrawLine(float ln) { @@ -361,11 +370,11 @@ void DrawLine(float ln) for (x = 1; x <= TET_WIDTH; x = x + 1) { - d = GetSquare(x, ln); + d = GetSquare(x, ln + TET_LINES - TET_DISPLAY_LINES); if (d) { WriteChar(MSG_ONE, '^'); - WriteChar(MSG_ONE, d * d - 2 * d + 50); // 1, 2, 5 + WriteChar(MSG_ONE, d + '0'); WriteChar(MSG_ONE, TET_BLOCK); } else @@ -380,7 +389,7 @@ void DrawPiece(float pc, float ln) { float x, d, piece_ln, pcolor; vector piece_dat; - pcolor = mod(pc, 3) + 1; + pcolor = PieceColor(pc); WriteChar(MSG_ONE, TET_SPACE); // pad to 6 piece_dat = PieceShape(pc); @@ -390,11 +399,10 @@ void DrawPiece(float pc, float ln) piece_ln = piece_dat_y; for (x = 1; x <= 4; x = x + 1) { - d = GetXBlock(x, piece_ln) * pcolor; - if (d) + if (piece_ln & pow(4, x-1)) { WriteChar(MSG_ONE, '^'); - WriteChar(MSG_ONE, d * d - 2 * d + 50); // 1, 2, 5 + WriteChar(MSG_ONE, pcolor + '0'); WriteChar(MSG_ONE, TET_BLOCK); } else @@ -408,13 +416,18 @@ void Draw_Tetris() entity head; msg_entity = self; WriteChar(MSG_ONE, SVC_CENTERPRINTa); + if(autocvar_g_bastet) + { + WriteTetrisString("NEVER GONNA GIVE YOU"); + WriteChar(MSG_ONE, 10); + } // decoration for (i = 1; i <= (TET_WIDTH + 2); i = i + 1) WriteChar(MSG_ONE, TET_BORDER); WriteTetrisString(" "); WriteUnterminatedString(MSG_ONE, TET_PADDING_RIGHT); WriteChar(MSG_ONE, 10); - for (i = 1; i <= TET_LINES; i = i + 1) + for (i = 1; i <= TET_DISPLAY_LINES; i = i + 1) { if(self.tetris_on == 2) WriteTetrisString(" GAME OVER "); @@ -423,7 +436,7 @@ void Draw_Tetris() else DrawLine(i); if (i == 1) - WriteTetrisString(" NEXT "); + WriteTetrisString(autocvar_g_bastet ? " THAT " : " NEXT "); else if (i == 3) DrawPiece(self.next_piece, 1); else if (i == 4) @@ -501,13 +514,16 @@ void ResetTetris() { float i; + if(!tet_line_buf) + tet_line_buf = buf_create(); + for (i=1; i<=TET_LINES; i = i + 1) - SetLine(i, 0); + SetLine(i, TET_EMPTY_LINE); self.piece_pos = '0 0 0'; self.piece_type = 0; self.next_piece = self.tet_lines = self.tet_score = 0; self.tet_piece_bucket = 0; -}; +} void Tet_GameExit() { @@ -516,8 +532,229 @@ void Tet_GameExit() self.tet_vs_id = 0; ResetTetris(); self.movetype = MOVETYPE_WALK; -}; +} +void PrintField() +{ + string l; + float r, c; + for(r = 1; r <= TET_LINES; ++r) + { + l = GetLine(r); + print(">"); + for(c = 1; c <= TET_WIDTH; ++c) + { + print(ftos(GetXBlock(c, l))); + } + print("\n"); + } +} + +float BastetEvaluate() +{ + float height; + string l; + float lines; + float score, score_save; + string occupied, occupied_save; + float occupied_count, occupied_count_save; + float i, j, line; + + score = 0; + + // adds a bonus for each free dot above the occupied blocks profile + occupied = TET_EMPTY_LINE; + occupied_count = TET_WIDTH; + height = 0; + lines = 0; + for(i = 1; i <= TET_LINES; ++i) + { + l = GetLine(i); + if(l == TET_EMPTY_LINE) + { + height = i; + continue; + } + line = 1; + occupied_save = occupied; + occupied_count_save = occupied_count; + score_save = score; + for(j = 1; j <= TET_WIDTH; ++j) + { + if(GetXBlock(j, l)) + { + if(!GetXBlock(j, occupied)) + { + occupied = SetXBlock(j, occupied, 1); + --occupied_count; + } + } + else + line = 0; + score += 10000 * occupied_count; + } + if(line) + { + occupied = occupied_save; + occupied_count = occupied_count_save; + score = score_save + 100000000 + 10000 * TET_WIDTH + 1000; + ++lines; + } + } + + score += 1000 * height; + + return score; +} + +float CheckMetrics(float piece, float orgx, float orgy, float rot); +void ClearPiece(float piece, float orgx, float orgy, float rot); +void CementPiece(float piece, float orgx, float orgy, float rot); +float bastet_profile_evaluate_time; +float bastet_profile_checkmetrics_time; +float BastetSearch(float buf, float pc, float x, float y, float rot, float move_bias) +// returns best score, or -1 if position is impossible +{ + string r; + float b; + float s, sm; + float t1, t2; + + if(move_bias < 0) + return 0; // DO NOT WANT + + if(x < 1 || x > TET_WIDTH || y < 1 || y > TET_LINES) + return -1; // impossible + if(rot < 0) rot = 3; + if(rot > 3) rot = 0; + + // did we already try? + b = x + (TET_WIDTH+2) * (y + (TET_LINES+2) * rot); + r = bufstr_get(buf, b); + if(r != "") // already tried + return stof(r); + + bufstr_set(buf, b, "0"); // in case we READ that, not that bad - we already got that value in another branch then anyway + + + + t1 = gettime(GETTIME_HIRES); + if(CheckMetrics(pc, x, y, rot)) + { + t2 = gettime(GETTIME_HIRES); + bastet_profile_checkmetrics_time += (t2 - t1); + // try all moves + sm = 1; + s = BastetSearch(buf, pc, x-1, y, rot, move_bias - 1); if(s > sm) sm = s; + s = BastetSearch(buf, pc, x+1, y, rot, move_bias - 1); if(s > sm) sm = s; + s = BastetSearch(buf, pc, x, y, rot+1, move_bias - 1); if(s > sm) sm = s; + s = BastetSearch(buf, pc, x, y, rot-1, move_bias - 1); if(s > sm) sm = s; + + s = BastetSearch(buf, pc, x, y+1, rot, move_bias + 2); if(s > sm) sm = s; + if(s < 0) + { + //print(sprintf("MAY CEMENT AT: %d %d %d\n", x, y, rot)); + // moving down did not work - that means we can fixate the block here + t1 = gettime(GETTIME_HIRES); + + CementPiece(pc, x, y, rot); + s = BastetEvaluate(); + ClearPiece(pc, x, y, rot); + + t2 = gettime(GETTIME_HIRES); + bastet_profile_evaluate_time += (t2 - t1); + + if(s > sm) sm = s; + } + } + else + { + t2 = gettime(GETTIME_HIRES); + bastet_profile_checkmetrics_time += (t2 - t1); + sm = -1; // impassible + } + + bufstr_set(buf, b, ftos(sm)); + + return sm; +} + +float bastet_piece[7]; +float bastet_score[7]; +float bastet_piecetime[7]; +float BastetPiece() +{ + float b; + + bastet_profile_evaluate_time = 0; + bastet_profile_checkmetrics_time = 0; + var float t1 = gettime(GETTIME_HIRES); + + 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); + 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); + 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); + 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); + 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); + 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); + 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); + + var float t2 = gettime(GETTIME_HIRES); + dprint(sprintf("Time taken: %.6f seconds (of this, ev = %.2f%%, cm = %.2f%%)\n", t2 - t1, 100 * bastet_profile_evaluate_time / (t2 - t1), 100 * bastet_profile_checkmetrics_time / (t2 - t1))); + + // sort + float i, j, k, p, s; + +/* + for(i = 0; i < 7; ++i) + { + print(sprintf("piece %s value = %d\n", substring("OJLIZST", bastet_piece[i]-1, 1), bastet_score[i])); + } +*/ + + for(i = 0; i < 7; ++i) + { + k = i; + p = bastet_piece[k]; + s = bastet_score[k]; + for(j = i + 1; j < 7; ++j) + { + if(bastet_score[j] < s) + { + k = j; + s = bastet_score[k]; + p = bastet_piece[k]; + } + } + if(k != i) + { + bastet_score[k] = bastet_score[i]; + bastet_piece[k] = bastet_piece[i]; + bastet_score[i] = s; + bastet_piece[i] = p; + } + } + + b = random(); + if(b < 0.8) + j = 0; + else if(b < 0.92) + j = 1; + else if(b < 0.98) + j = 2; + else + j = 3; + j = bastet_piece[j]; + + for(i = 0; i < 7; ++i) + { + if(i == j-1) + bastet_piecetime[i] = 0.2 * bastet_piecetime[i]; + else + bastet_piecetime[i] = 1.8 * bastet_piecetime[i] + 1000; + } + + return j; +} /* @@ -534,6 +771,7 @@ float RandomPiece() float p, q; float b; float seen; + if(self.tet_piece_bucket > 1) { p = mod(self.tet_piece_bucket, 7); @@ -562,50 +800,50 @@ float RandomPiece() self.tet_piece_bucket = b; return p + 1; } -}; +} void TetAddScore(float n) { self.tet_score = self.tet_score + n * Tetris_Level(); if (self.tet_score > tet_high_score) tet_high_score = self.tet_score; -}; +} float CheckMetrics(float piece, float orgx, float orgy, float rot) /*FIXDECL*/ { // check to see if the piece, if moved to the locations will overlap float x, y; + string l; // why did I start counting from 1, damnit orgx = orgx - 1; orgy = orgy - 1; - for (y = 0; y < 5; y = y + 1) + PieceMinsMaxs(rot, piece); + if (tet_piecemins_x+orgx<1 || tet_piecemaxs_x+orgx > TET_WIDTH || tet_piecemins_y+orgy<1 || tet_piecemaxs_y+orgy> TET_LINES) + return FALSE; // ouside the level + for (y = tet_piecemins_y; y <= tet_piecemaxs_y; y = y + 1) { - for (x = 0; x < 5; x = x + 1) - { + l = GetLine(y + orgy); + if(l != TET_EMPTY_LINE) + for (x = tet_piecemins_x; x <= tet_piecemaxs_x; x = x + 1) if (PieceMetric(x, y, rot, piece)) - { - if (GetSquare(x + orgx, y + orgy)) + if (GetXBlock(x + orgx, l)) return FALSE; // uhoh, gonna hit something. - if (x+orgx<1 || x+orgx > TET_WIDTH || y+orgy<1 || y+orgy> TET_LINES) - return FALSE; // ouside the level - } - } } return TRUE; } void ClearPiece(float piece, float orgx, float orgy, float rot) /*FIXDECL*/ { - float x, y; // why did I start counting from 1, damnit orgx = orgx - 1; orgy = orgy - 1; - for (y = 0; y < 5; y = y + 1) + PieceMinsMaxs(rot, piece); + for (y = tet_piecemins_y; y <= tet_piecemaxs_y; y = y + 1) { - for (x = 0; x < 5; x = x + 1) + for (x = tet_piecemins_x; x <= tet_piecemaxs_x; x = x + 1) { if (PieceMetric(x, y, rot, piece)) { @@ -622,11 +860,12 @@ void CementPiece(float piece, float orgx, float orgy, float rot) /*FIXDECL*/ orgx = orgx - 1; orgy = orgy - 1; - pcolor = mod(piece, 3) + 1; + pcolor = PieceColor(piece); - for (y = 0; y < 5; y = y + 1) + PieceMinsMaxs(rot, piece); + for (y = tet_piecemins_y; y <= tet_piecemaxs_y; y = y + 1) { - for (x = 0; x < 5; x = x + 1) + for (x = tet_piecemins_x; x <= tet_piecemaxs_x; x = x + 1) { if (PieceMetric(x, y, rot, piece)) { @@ -650,18 +889,24 @@ void AddLines(float n) void CompletedLines() { - float y, cleared, ln, added, pos, i; + float y, cleared, added, pos, i; + string ln; cleared = 0; y = TET_LINES; - while(y >= 1) + for(;;) { ln = GetLine(y); - if (((ln & LINE_LOW) | ((ln & LINE_HIGH)/2)) == LINE_LOW) + if(strstrofs(ln, "0", 0) < 0) cleared = cleared + 1; else y = y - 1; - ln = GetLine(y - cleared); + if(y < 1) + break; + if(y - cleared < 1) + ln = TET_EMPTY_LINE; + else + ln = GetLine(y - cleared); SetLine(y, ln); } @@ -685,17 +930,17 @@ void CompletedLines() for(y = max(1, TET_LINES - added + 1); y <= TET_LINES; ++y) { pos = floor(random() * TET_WIDTH); - ln = 0; + ln = TET_EMPTY_LINE; for(i = 1; i <= TET_WIDTH; ++i) if(i != pos) - ln = SetXBlock(i, ln, floor(random() * 3 + 1)); + ln = SetXBlock(i, ln, floor(random() * 7 + 1)); SetLine(y, ln); } } self.tet_highest_line = 0; for(y = 1; y <= TET_LINES; ++y) - if(GetLine(y) != 0) + if(GetLine(y) != TET_EMPTY_LINE) { self.tet_highest_line = TET_LINES + 1 - y; break; @@ -709,7 +954,7 @@ void CompletedLines() tetsnd("tetline"); else tetsnd("tetland"); -}; +} void HandleGame(float keyss) { @@ -725,12 +970,21 @@ void HandleGame(float keyss) if (self.piece_type == 0) { - self.piece_pos = '5 1 0'; // that's about middle top, we count from 1 ARGH - if (self.next_piece) - self.piece_type = self.next_piece; + self.piece_pos = TET_START_PIECE_POS; // that's about middle top, we count from 1 ARGH + + if(autocvar_g_bastet) + { + self.piece_type = BastetPiece(); + self.next_piece = bastet_piece[6]; + } else - self.piece_type = RandomPiece(); - self.next_piece = RandomPiece(); + { + if (self.next_piece) + self.piece_type = self.next_piece; + else + self.piece_type = RandomPiece(); + self.next_piece = RandomPiece(); + } keyss = 0; // no movement first frame self.tet_autodown = time + 0.2; brand_new = 1; @@ -833,7 +1087,7 @@ void HandleGame(float keyss) return; } CementPiece(self.piece_type, self.piece_pos_x, self.piece_pos_y, self.piece_pos_z); -}; +} /* ********************************* @@ -873,7 +1127,7 @@ void TetrisImpulse() Tet_GameExit(); self.impulse = 0; } -}; +} float TetrisPreFrame() @@ -890,24 +1144,24 @@ float TetrisPreFrame() else self.tet_drawtime = time + 0.5; return 1; -}; +} float frik_anglemoda(float v) { return v - floor(v/360) * 360; -}; +} float angcompa(float y1, float y2) { y1 = frik_anglemoda(y1); y2 = frik_anglemoda(y2); - local float answer; + float answer; answer = y1 - y2; if (answer > 180) answer = answer - 360; else if (answer < -180) answer = answer + 360; return answer; -}; +} .float tetkey_down, tetkey_rotright, tetkey_left, tetkey_right, tetkey_rotleft, tetkey_drop; @@ -986,6 +1240,10 @@ float TetrisPostFrame() } return 1; -}; +} + +#else + +FTEQCC_YOU_SUCK_THIS_IS_NOT_UNREFERENCED(autocvar_g_bastet); #endif