initial interface requests
[netris.git] / board.c
1 /*
2  * Netris -- A free networked version of T*tris
3  * Copyright (C) 1994-1996,1999  Mark H. Weaver <mhw@netris.org>
4  * 
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  *
19  * $Id: board.c,v 1.15 1999/05/16 06:56:24 mhw Exp $
20  */
21
22 #include "netris.h"
23 #include <stdlib.h>
24
25 #ifdef DEBUG_FALLING
26 # define B_OLD
27 #else
28 # define B_OLD abs
29 #endif
30
31 static BlockType board[MAX_SCREENS][MAX_BOARD_HEIGHT][MAX_BOARD_WIDTH];
32 static BlockType oldBoard[MAX_SCREENS][MAX_BOARD_HEIGHT][MAX_BOARD_WIDTH];
33 static unsigned int changed[MAX_SCREENS][MAX_BOARD_HEIGHT];
34 static int falling[MAX_SCREENS][MAX_BOARD_WIDTH];
35 static int oldFalling[MAX_SCREENS][MAX_BOARD_WIDTH];
36
37 ExtFunc void InitBoard(int scr)
38 {
39         boardHeight[scr] = MAX_BOARD_HEIGHT;
40         boardVisible[scr] = 20;
41         boardWidth[scr] = 10;
42         InitScreen(scr);
43 }
44
45 ExtFunc void CleanupBoard(int scr)
46 {
47         CleanupScreen(scr);
48 }
49
50 ExtFunc BlockType GetBlock(int scr, int y, int x)
51 {
52         if (y < 0 || x < 0 || x >= boardWidth[scr])
53                 return BT_wall;
54         else if (y >= boardHeight[scr])
55                 return BT_none;
56         else
57                 return abs(board[scr][y][x]);
58 }
59
60 ExtFunc void SetBlock(int scr, int y, int x, BlockType type)
61 {
62         if (y >= 0 && y < boardHeight[scr] && x >= 0 && x < boardWidth[scr]) {
63                 if (y < boardVisible[scr])
64                         falling[scr][x] += (type < 0) - (board[scr][y][x] < 0);
65                 board[scr][y][x] = type;
66                 changed[scr][y] |= 1 << x;
67         }
68 }
69
70 ExtFunc int RefreshBoard(int scr)
71 {
72         int y, x, any = 0;
73         unsigned int c;
74         BlockType b;
75
76         for (y = boardVisible[scr] - 1; y >= 0; --y)
77                 if ((c = changed[scr][y])) {
78                         if (robotEnable) {
79                                 RobotCmd(0, "RowUpdate %d %d", scr, y);
80                                 for (x = 0; x < boardWidth[scr]; ++x) {
81                                         b = board[scr][y][x];
82                                         if (fairRobot)
83                                                 b = abs(b);
84                                         RobotCmd(0, " %d", b);
85                                 }
86                                 RobotCmd(0, "\n");
87                         }
88                         changed[scr][y] = 0;
89                         any = 1;
90                         for (x = 0; c; (c >>= 1), (++x))
91                                 if ((c & 1) && B_OLD(board[scr][y][x])!=oldBoard[scr][y][x]) {
92                                         PlotBlock(scr, y, x, B_OLD(board[scr][y][x]));
93                                         oldBoard[scr][y][x] = B_OLD(board[scr][y][x]);
94                                 }
95                 }
96         if (robotEnable)
97                 RobotTimeStamp();
98         for (x = 0; x < boardWidth[scr]; ++x)
99                 if (oldFalling[scr][x] != !!falling[scr][x]) {
100                         oldFalling[scr][x] = !!falling[scr][x];
101                         PlotUnderline(scr, x, oldFalling[scr][x]);
102                         any = 1;
103                 }
104         return any;
105 }
106
107 ExtFunc int GlanceFunc(int scr, int y, int x, BlockType type, void *data)
108 {
109         PlotBlock1(scr, y, x, type);
110         return 0;
111 }
112
113 ExtFunc int PlotFunc(int scr, int y, int x, BlockType type, void *data)
114 {
115         SetBlock(scr, y, x, type);
116         return 0;
117 }
118
119 ExtFunc int EraseFunc(int scr, int y, int x, BlockType type, void *data)
120 {
121         SetBlock(scr, y, x, BT_none);
122         return 0;
123 }
124
125 ExtFunc int CollisionFunc(int scr, int y, int x, BlockType type, void *data)
126 {
127         return GetBlock(scr, y, x) != BT_none;
128 }
129
130 ExtFunc int VisibleFunc(int scr, int y, int x, BlockType type, void *data)
131 {
132         return (y >= 0 && y < boardVisible[scr] && x >= 0 && x < boardWidth[scr]);
133 }
134
135 ExtFunc void PlotShape(Shape *shape, int scr, int y, int x, int falling)
136 {
137         ShapeIterate(shape, scr, y, x, falling, PlotFunc, NULL);
138 }
139
140 ExtFunc void EraseShape(Shape *shape, int scr, int y, int x)
141 {
142         ShapeIterate(shape, scr, y, x, 0, EraseFunc, NULL);
143 }
144
145 ExtFunc int ShapeFits(Shape *shape, int scr, int y, int x)
146 {
147         return !ShapeIterate(shape, scr, y, x, 0, CollisionFunc, NULL);
148 }
149
150 ExtFunc int ShapeVisible(Shape *shape, int scr, int y, int x)
151 {
152         return ShapeIterate(shape, scr, y, x, 0, VisibleFunc, NULL);
153 }
154
155 ExtFunc int MovePiece(int scr, int deltaY, int deltaX)
156 {
157         int result;
158
159         EraseShape(curShape[scr], scr, curY[scr], curX[scr]);
160         result = ShapeFits(curShape[scr], scr, curY[scr] + deltaY,
161                                 curX[scr] + deltaX);
162         if (result) {
163                 curY[scr] += deltaY;
164                 curX[scr] += deltaX;
165         }
166         PlotShape(curShape[scr], scr, curY[scr], curX[scr], 1);
167         return result;
168 }
169
170 ExtFunc int RotatePiece(int scr, int dir)
171 {
172         int result;
173
174         EraseShape(curShape[scr], scr, curY[scr], curX[scr]);
175         result = ShapeFits(dir ? curShape[scr]->rotateTo : curShape[scr]->rotateFrom,
176                 scr, curY[scr], curX[scr]);
177         if (result)
178                 curShape[scr] = dir ? curShape[scr]->rotateTo : curShape[scr]->rotateFrom;
179         PlotShape(curShape[scr], scr, curY[scr], curX[scr], 1);
180         return result;
181 }
182
183 ExtFunc int DropPiece(int scr)
184 {
185         int count = 0;
186
187         EraseShape(curShape[scr], scr, curY[scr], curX[scr]);
188         while (ShapeFits(curShape[scr], scr, curY[scr] - 1, curX[scr])) {
189                 --curY[scr];
190                 ++count;
191         }
192         PlotShape(curShape[scr], scr, curY[scr], curX[scr], 1);
193         return count;
194 }
195
196 ExtFunc int LineIsFull(int scr, int y)
197 {
198         int x;
199
200         for (x = 0; x < boardWidth[scr]; ++x)
201                 if (GetBlock(scr, y, x) == BT_none)
202                         return 0;
203         return 1;
204 }
205
206 ExtFunc void CopyLine(int scr, int from, int to)
207 {
208         int x;
209
210         if (from != to)
211                 for (x = 0; x < boardWidth[scr]; ++x)
212                         SetBlock(scr, to, x, GetBlock(scr, from, x));
213 }
214
215 ExtFunc int ClearFullLines(int scr)
216 {
217         int from, to;
218
219         from = to = 0;
220         while (to < boardHeight[scr]) {
221                 while (LineIsFull(scr, from))
222                         ++from;
223                 CopyLine(scr, from++, to++);
224         }
225         return from - to;
226 }
227
228 ExtFunc void FreezePiece(int scr)
229 {
230         int y, x;
231         BlockType type;
232
233         for (y = 0; y < boardHeight[scr]; ++y)
234                 for (x = 0; x < boardWidth[scr]; ++x)
235                         if ((type = board[scr][y][x]) < 0)
236                                 SetBlock(scr, y, x, -type);
237 }
238
239 ExtFunc void InsertJunk(int scr, int count, int column)
240 {
241         int y, x;
242
243         for (y = boardHeight[scr] - count - 1; y >= 0; --y)
244                 CopyLine(scr, y, y + count);
245         for (y = 0; y < count; ++y)
246                 for (x = 0; x < boardWidth[scr]; ++x)
247                         SetBlock(scr, y, x, (x == column) ? BT_none : BT_white);
248         curY[scr] += count;
249 }
250
251 /*
252  * vi: ts=4 ai
253  * vim: noai si
254  */