Imported Debian patch 0.52-2
[pkg/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         int s,w,h;
40
41         for(s = 0 ; s < MAX_SCREENS ; s++)
42                 for(h = 0 ; h < MAX_BOARD_HEIGHT ; h++)
43                         for(w = 0 ; w < MAX_BOARD_WIDTH ; w++) {
44                                 board[s][h][w] = 0;
45                                 oldBoard[s][h][w] = 0;
46                                 changed[s][h] = 0;
47                                 falling[s][w] = 0;
48                                 oldFalling[s][w] = 0;
49                         }
50                                 
51
52         boardHeight[scr] = MAX_BOARD_HEIGHT;
53         boardVisible[scr] = 20;
54         boardWidth[scr] = 10;
55         InitScreen(scr);
56 }
57
58 ExtFunc void CleanupBoard(int scr)
59 {
60         CleanupScreen(scr);
61 }
62
63 ExtFunc BlockType GetBlock(int scr, int y, int x)
64 {
65         if (y < 0 || x < 0 || x >= boardWidth[scr])
66                 return BT_wall;
67         else if (y >= boardHeight[scr])
68                 return BT_none;
69         else
70                 return abs(board[scr][y][x]);
71 }
72
73 ExtFunc void SetBlock(int scr, int y, int x, BlockType type)
74 {
75         if (y >= 0 && y < boardHeight[scr] && x >= 0 && x < boardWidth[scr]) {
76                 if (y < boardVisible[scr])
77                         falling[scr][x] += (type < 0) - (board[scr][y][x] < 0);
78                 board[scr][y][x] = type;
79                 changed[scr][y] |= 1 << x;
80         }
81 }
82
83 ExtFunc int RefreshBoard(int scr)
84 {
85         int y, x, any = 0;
86         unsigned int c;
87         BlockType b;
88
89         for (y = boardVisible[scr] - 1; y >= 0; --y)
90                 if ((c = changed[scr][y])) {
91                         if (robotEnable) {
92                                 RobotCmd(0, "RowUpdate %d %d", scr, y);
93                                 for (x = 0; x < boardWidth[scr]; ++x) {
94                                         b = board[scr][y][x];
95                                         if (fairRobot)
96                                                 b = abs(b);
97                                         RobotCmd(0, " %d", b);
98                                 }
99                                 RobotCmd(0, "\n");
100                         }
101                         changed[scr][y] = 0;
102                         any = 1;
103                         for (x = 0; c; (c >>= 1), (++x))
104                                 if ((c & 1) && B_OLD(board[scr][y][x])!=oldBoard[scr][y][x]) {
105                                         PlotBlock(scr, y, x, B_OLD(board[scr][y][x]));
106                                         oldBoard[scr][y][x] = B_OLD(board[scr][y][x]);
107                                 }
108                 }
109         if (robotEnable)
110                 RobotTimeStamp();
111         for (x = 0; x < boardWidth[scr]; ++x)
112                 if (oldFalling[scr][x] != !!falling[scr][x]) {
113                         oldFalling[scr][x] = !!falling[scr][x];
114                         PlotUnderline(scr, x, oldFalling[scr][x]);
115                         any = 1;
116                 }
117         return any;
118 }
119
120 ExtFunc int PlotFunc(int scr, int y, int x, BlockType type, void *data)
121 {
122         SetBlock(scr, y, x, type);
123         return 0;
124 }
125
126 ExtFunc int EraseFunc(int scr, int y, int x, BlockType type, void *data)
127 {
128         SetBlock(scr, y, x, BT_none);
129         return 0;
130 }
131
132 ExtFunc int CollisionFunc(int scr, int y, int x, BlockType type, void *data)
133 {
134         return GetBlock(scr, y, x) != BT_none;
135 }
136
137 ExtFunc int VisibleFunc(int scr, int y, int x, BlockType type, void *data)
138 {
139         return (y >= 0 && y < boardVisible[scr] && x >= 0 && x < boardWidth[scr]);
140 }
141
142 ExtFunc void PlotShape(Shape *shape, int scr, int y, int x, int falling)
143 {
144         ShapeIterate(shape, scr, y, x, falling, PlotFunc, NULL);
145 }
146
147 ExtFunc void EraseShape(Shape *shape, int scr, int y, int x)
148 {
149         ShapeIterate(shape, scr, y, x, 0, EraseFunc, NULL);
150 }
151
152 ExtFunc int ShapeFits(Shape *shape, int scr, int y, int x)
153 {
154         return !ShapeIterate(shape, scr, y, x, 0, CollisionFunc, NULL);
155 }
156
157 ExtFunc int ShapeVisible(Shape *shape, int scr, int y, int x)
158 {
159         return ShapeIterate(shape, scr, y, x, 0, VisibleFunc, NULL);
160 }
161
162 ExtFunc int MovePiece(int scr, int deltaY, int deltaX)
163 {
164         int result;
165
166         EraseShape(curShape[scr], scr, curY[scr], curX[scr]);
167         result = ShapeFits(curShape[scr], scr, curY[scr] + deltaY,
168                                 curX[scr] + deltaX);
169         if (result) {
170                 curY[scr] += deltaY;
171                 curX[scr] += deltaX;
172         }
173         PlotShape(curShape[scr], scr, curY[scr], curX[scr], 1);
174         return result;
175 }
176
177 ExtFunc int RotatePiece(int scr)
178 {
179         int result;
180
181         EraseShape(curShape[scr], scr, curY[scr], curX[scr]);
182         result = ShapeFits(curShape[scr]->rotateTo, scr, curY[scr], curX[scr]);
183         if (result)
184                 curShape[scr] = curShape[scr]->rotateTo;
185         PlotShape(curShape[scr], scr, curY[scr], curX[scr], 1);
186         return result;
187 }
188
189 ExtFunc int DropPiece(int scr)
190 {
191         int count = 0;
192
193         EraseShape(curShape[scr], scr, curY[scr], curX[scr]);
194         while (ShapeFits(curShape[scr], scr, curY[scr] - 1, curX[scr])) {
195                 --curY[scr];
196                 ++count;
197         }
198         PlotShape(curShape[scr], scr, curY[scr], curX[scr], 1);
199         return count;
200 }
201
202 ExtFunc int LineIsFull(int scr, int y)
203 {
204         int x;
205
206         for (x = 0; x < boardWidth[scr]; ++x)
207                 if (GetBlock(scr, y, x) == BT_none)
208                         return 0;
209         return 1;
210 }
211
212 ExtFunc void CopyLine(int scr, int from, int to)
213 {
214         int x;
215
216         if (from != to)
217                 for (x = 0; x < boardWidth[scr]; ++x)
218                         SetBlock(scr, to, x, GetBlock(scr, from, x));
219 }
220
221 ExtFunc int ClearFullLines(int scr)
222 {
223         int from, to;
224
225         from = to = 0;
226         while (to < boardHeight[scr]) {
227                 while (LineIsFull(scr, from))
228                         ++from;
229                 CopyLine(scr, from++, to++);
230         }
231         return from - to;
232 }
233
234 ExtFunc void FreezePiece(int scr)
235 {
236         int y, x;
237         BlockType type;
238
239         for (y = 0; y < boardHeight[scr]; ++y)
240                 for (x = 0; x < boardWidth[scr]; ++x)
241                         if ((type = board[scr][y][x]) < 0)
242                                 SetBlock(scr, y, x, -type);
243 }
244
245 ExtFunc void InsertJunk(int scr, int count, int column)
246 {
247         int y, x;
248
249         for (y = boardHeight[scr] - count - 1; y >= 0; --y)
250                 CopyLine(scr, y, y + count);
251         for (y = 0; y < count; ++y)
252                 for (x = 0; x < boardWidth[scr]; ++x)
253                         SetBlock(scr, y, x, (x == column) ? BT_none : BT_white);
254         curY[scr] += count;
255 }
256
257 /*
258  * vi: ts=4 ai
259  * vim: noai si
260  */