💾 Archived View for gemini.rmf-dev.com › repo › Vaati › Tetris › files › a1476d178e22cfd7459ee6bd03e… captured on 2023-12-28 at 15:48:28. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-09-08)

-=-=-=-=-=-=-

Go Back

0 /* See LICENSE file for copyright and license details. */

1 #include "config.h"

2 #include "backend.h"

3 #include <stdlib.h>

4 #include <string.h>

5 #include <time.h>

6 #include <math.h>

7 #include <unistd.h>

8

9 typedef struct Rect {

10 _uint x;

11 _uint y;

12 _uint w;

13 _uint h;

14 } Rect;

15

16 /* Drawing score */

17 uint8 number[10][7] = {

18 {1, 1, 1, 0, 1, 1, 1},

19 {0, 0, 1, 0, 0, 1, 0},

20 {1, 0, 1, 1, 1, 0, 1},

21 {1, 0, 1, 1, 0, 1, 1},

22 {0, 1, 1, 1, 0, 1, 0},

23 {1, 1, 0, 1, 0, 1, 1},

24 {1, 1, 0, 1, 1, 1, 1},

25 {1, 0, 1, 0, 0, 1, 0},

26 {1, 1, 1, 1, 1, 1, 1},

27 {1, 1, 1, 1, 0, 1, 1}

28 };

29

30 Rect offset[8] = {

31 {0, 0, WIDTHX, THICK},

32 {0, 0, THICK, WIDTHY},

33 {WIDTHX - THICK, 0, THICK, WIDTHY},

34 {0, WIDTHY, WIDTHX, THICK},

35 {0, WIDTHY, THICK, WIDTHY},

36 {WIDTHX - THICK, WIDTHY, THICK, WIDTHY},

37 {0, WIDTHY * 2, WIDTHX, THICK},

38 };

39

40 void drawDigit(_uint x, _uint y, _uint n) {

41 uint8 i = 0;

42 Rect r;

43 if (n >= 10) return;

44 for (; i < 7; i++) {

45 if (!number[n][i]) continue;

46 r = offset[i];

47 r.x += x;

48 r.y += y;

49 backend_fill(r.x, r.y, r.w, r.h, TEXT);

50 }

51 }

52

53 void drawNumber(_uint x, _uint y, _ulong n) {

54 _uint j = 0;

55 _uint i = n;

56 if (n == 0) {

57 drawDigit(x, y, 0);

58 return;

59 }

60 for(; i > 0; i /= 10)

61 j++;

62 i = n;

63 for(; i > 0; i /= 10) {

64 j--;

65 drawDigit(x + j * (WIDTHX + THICK * 2), y, i % 10);

66 }

67 }

68

69 /* Game logic */

70 _uint pieceX = SIZEX / 2;

71 _uint pieceY = 0;

72 uint8 pieceId = 0;

73 uint8 rotation = 0;

74

75 uint8 piecesLen[7][2] = {

76 {4, 0},

77 {3, 3},

78 {3, 3},

79 {2, 2},

80 {3, 3},

81 {3, 3},

82 {3, 3}

83 };

84

85 uint8 pieces[7][2][4] = {

86 {

87 { 1, 1, 1, 1 },

88 },

89 {

90 { 1, 0, 0 },

91 { 1, 1, 1 }

92 },

93 {

94 { 0, 0, 1 },

95 { 1, 1, 1 }

96 },

97 {

98 { 1, 1 },

99 { 1, 1 }

100 },

101 {

102 { 0, 1, 1 },

103 { 1, 1, 0 }

104 },

105 {

106 { 0, 1, 0 },

107 { 1, 1, 1 }

108 },

109 {

110 { 1, 1, 0 },

111 { 0, 1, 1 }

112 }

113 };

114

115 uint8 board[SIZEY * SIZEX];

116

117 _uint blocks[6][2];

118 uint8 getBlocks(_uint x, _uint y, uint8 c, uint8 r) {

119 _uint h = c == 0?1:2;

120 uint8 len = 0;

121 uint8 i = 0;

122 uint8 j = 0;

123 for (; i < h; j++) {

124 if (j >= piecesLen[c][i]) {

125 j = -1;

126 i++;

127 continue;

128 }

129 if (pieces[c][i][j] == 0) continue;

130 switch (r) {

131 case 0:

132 blocks[len][0] = x + i;

133 blocks[len][1] = y + j;

134 break;

135 case 1:

136 blocks[len][0] = x + j;

137 blocks[len][1] = y + i;

138 break;

139 case 2:

140 blocks[len][0] = x + h - i - 1;

141 blocks[len][1] = y + j;

142 break;

143 case 3:

144 blocks[len][0] = x + j;

145 blocks[len][1] = y + h - i - 1;

146 break;

147 }

148 len++;

149 }

150 return len;

151 }

152

153 void setPiece() {

154 uint8 len = getBlocks(pieceX, pieceY, pieceId, rotation);

155 uint8 i = 0;

156 for (; i < len; i++)

157 board[blocks[i][0] + blocks[i][1] * SIZEX] = pieceId + 1;

158 }

159

160 uint8 rotate() {

161 uint8 len = getBlocks(pieceX, pieceY, pieceId, (rotation+1)%4);

162 uint8 i = 0;

163 for (; i < len; i++)

164 if (blocks[i][1] >= SIZEY ||

165 blocks[i][0] >= SIZEX ||

166 board[SIZEX * blocks[i][1] + blocks[i][0]])

167 return 0;

168 rotation = (rotation + 1) % 4;

169 return 1;

170 }

171

172 int movePiece(_uint x, _uint y, uint8 m) {

173 uint8 len = getBlocks(x, y, pieceId, rotation);

174 uint8 i = 0;

175 for (; i < len; i++) {

176 if (blocks[i][1] >= SIZEY ||

177 blocks[i][0] >= SIZEX ||

178 board[SIZEX * (blocks[i][1]) + (blocks[i][0])])

179 return 0;

180 }

181 if (!m) return 1;

182 pieceX = x;

183 pieceY = y;

184 return 1;

185 }

186

187 void dropLine(_uint y) {

188 for (; y > 0; y--) {

189 _uint j = 0;

190 for (; j < SIZEX; j++)

191 board[y * SIZEX + j] = board[(y - 1) * SIZEX + j];

192 }

193 }

194

195 _uint checkLines() {

196 _uint l = 0;

197 _uint i = 0;

198 for (; i < SIZEY; i++) {

199 uint8 full = 1;

200 _uint j = 0;

201 for (; j < SIZEX; j++) {

202 if (board[i * SIZEX + j]) continue;

203 full = 0;

204 break;

205 }

206 if (!full) continue;

207 dropLine(i);

208 l++;

209 }

210 return l;

211 }

212

213 /* Rendering */

214 Rect rect;

215

216 #define RATIO rect.w / SIZEX

217 void drawBlock(int x, int y, int id) {

218 backend_fill(rect.x + x * RATIO, rect.y + y * RATIO,

219 RATIO, RATIO, id);

220 backend_draw(rect.x + x * RATIO, rect.y + y * RATIO,

221 RATIO, RATIO, id + 7);

222 }

223

224 void drawPiece() {

225 uint8 len = getBlocks(pieceX, pieceY, pieceId, rotation);

226 uint8 i = 0;

227 for (; i < len; i++)

228 drawBlock(blocks[i][0], blocks[i][1], pieceId);

229 }

230

231

232 int main() {

233 uint8 input = 0;

234 uint8 pressed = 0;

235 _uint tick = 0;

236 _ulong score = 0;

237

238 srand(time(0));

239 pieceId = rand() % 7;

240 memset(board, 0, SIZEY * SIZEX);

241

242 if (backend_init()) return -1;

243

244 while (1) {

245 _uint i = 0;

246 _uint width = backend_width - backend_width % SIZEX;

247 _uint height = backend_height - backend_height % SIZEY;

248 input = backend_input();

249 if (input & QUIT) break;

250 if (input & ROTATE) rotate();

251 if (input & LEFT) movePiece(pieceX - 1, pieceY, 1);

252 if (input & RIGHT) movePiece(pieceX + 1, pieceY, 1);

253 if (input & DOWN) {

254 while (movePiece(pieceX, pieceY + 1, 1))

255 pressed = 1;

256 if (!pressed)

257 tick = TICK * FPS / 1000 / 2;

258 }

259

260 tick++;

261 if (tick * 1000 / FPS >= TICK) {

262 _uint l;

263 tick = 0;

264 if (movePiece(pieceX, pieceY + 1, 1)) continue;

265 /* Piece on the ground */

266 setPiece();

267 score += 5;

268 l = checkLines();

269 score += l * l * 15;

270 pieceX = SIZEX / 2 - 1;

271 pieceY = 0;

272 pieceId = rand() % 7;

273 pressed = 0;

274 if (movePiece(pieceX, pieceY, 0)) continue;

275 /* Game over */

276 score = 0;

277 memset(board, 0, SIZEX * SIZEY);

278 }

279

280 if (backend_height * SIZEX / SIZEY - backend_width < 0) {

281 rect.x = (width - height * SIZEX / SIZEY) / 2;

282 rect.y = (backend_height - height) / 2;

283 rect.w = height * SIZEX / SIZEY;

284 rect.h = height * SIZEY / SIZEX / 2;

285 } else {

286 rect.x = (backend_width - width) / 2;

287 rect.y = (height - width * SIZEY / SIZEX) / 2;

288 rect.w = width * SIZEY / SIZEX / 2;

289 rect.h = width * SIZEY / SIZEX;

290 }

291

292 backend_fill(rect.x, rect.y, rect.w, rect.h + 1, BACKGROUND);

293

294 drawPiece();

295

296 for (; i < SIZEX * SIZEY; i++) {

297 if (!board[i]) continue;

298 drawBlock(i % SIZEX, i / SIZEX, board[i] - 1);

299 }

300

301 drawNumber((rect.x - WIDTHX * 15) > 0?i:THICK * 2,

302 rect.y + THICK * 4, score);

303

304 backend_refresh();

305 }

306

307 backend_clean();

308

309 return 0;

310 }

311