initial interface requests
[netris.git] / shapes.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: shapes.c,v 1.16 1999/05/16 06:56:31 mhw Exp $
20  */
21
22 #include "netris.h"
23 #include <stdlib.h>
24
25 #define ShapeName(name, dir) \
26         shape_ ## name ## _ ## dir
27
28 #define PreDecl(name, dir) \
29         static Shape ShapeName(name, dir)
30
31 #define StdShape(name, cmdName, mirror, type, realDir, dir, nextDir, prevDir) \
32         static Shape ShapeName(name, dir) = { \
33                 &ShapeName(name, nextDir), &ShapeName(name, prevDir), \
34                 0, 0, mirror, D_ ## realDir, type, cmds_ ## cmdName \
35         }
36
37 #define FourWayDecl(name, cmdName, mirror, type) \
38         PreDecl(name, down); \
39         PreDecl(name, up); \
40         StdShape(name, cmdName, mirror, type, left, left, up, down); \
41         PreDecl(name, right); \
42         StdShape(name, cmdName, mirror, type, up, up, right, left); \
43         StdShape(name, cmdName, mirror, type, right, right, down, up); \
44         StdShape(name, cmdName, mirror, type, down, down, left, right)
45
46 #define TwoWayDecl(name, cmdName, mirror, type) \
47         PreDecl(name, vert); \
48         StdShape(name, cmdName, mirror, type, right, horiz, vert, vert); \
49         StdShape(name, cmdName, mirror, type, down, vert, horiz, horiz)
50
51 static Cmd cmds_long[] = { C_back, C_plot, C_forw, C_plot, C_forw, C_plot,
52         C_forw, C_plot, C_end };
53 TwoWayDecl(long, long, 0, BT_blue);
54
55 static Cmd cmds_square[] = { C_plot, C_forw, C_left, C_plot, C_forw, C_left,
56         C_plot, C_forw, C_left, C_plot, C_end };
57 static Shape shape_square = { &shape_square, &shape_square, 0, 0, D_up, 0,
58         BT_magenta, cmds_square };
59
60 static Cmd cmds_l[] = { C_right, C_back, C_plot, C_forw, C_plot, C_forw,
61         C_plot, C_left, C_forw, C_plot, C_end };
62 FourWayDecl(l, l, 0, BT_cyan); 
63 FourWayDecl(l1, l, 1, BT_yellow);
64
65 static Cmd cmds_t[] = { C_plot, C_forw, C_plot, C_back, C_right, C_forw,
66         C_plot, C_back, C_back, C_plot, C_end };
67 FourWayDecl(t, t, 0, BT_white);
68
69 static Cmd cmds_s[] = { C_back, C_plot, C_forw, C_plot, C_left, C_forw,
70         C_plot, C_right, C_forw, C_plot, C_end };
71 TwoWayDecl(s, s, 0, BT_green);
72 TwoWayDecl(s1, s, 1, BT_red);
73
74 ShapeOption stdOptions[] = {
75         {1, &shape_long_horiz},
76         {1, &shape_square},
77         {1, &shape_l_down},
78         {1, &shape_l1_down},
79         {1, &shape_t_down},
80         {1, &shape_s_horiz},
81         {1, &shape_s1_horiz},
82         {0, NULL}};
83
84 Shape *netMapping[] = {
85         &shape_long_horiz,
86         &shape_long_vert,
87         &shape_square,
88         &shape_l_down,
89         &shape_l_right,
90         &shape_l_up,
91         &shape_l_left,
92         &shape_l1_down,
93         &shape_l1_right,
94         &shape_l1_up,
95         &shape_l1_left,
96         &shape_t_down,
97         &shape_t_right,
98         &shape_t_up,
99         &shape_t_left,
100         &shape_s_horiz,
101         &shape_s_vert,
102         &shape_s1_horiz,
103         &shape_s1_vert,
104         NULL};
105
106 ExtFunc void MoveInDir(Dir dir, int dist, int *y, int *x)
107 {
108         switch (dir) {
109                 case D_down:    *y -= dist; break;
110                 case D_right:   *x += dist; break;
111                 case D_up:              *y += dist; break;
112                 case D_left:    *x -= dist; break;
113                 default:
114                         assert(0);
115         }
116 }
117
118 ExtFunc Dir RotateDir(Dir dir, int delta)
119 {
120         return 3 & (dir + delta);
121 }
122
123 ExtFunc int ShapeIterate(Shape *s, int scr, int y, int x, int falling,
124 ExtFunc                         ShapeDrawFunc func, void *data)
125 {
126         int i, mirror, result;
127         Dir dir;
128         BlockType type;
129
130         y += s->initY;
131         x += s->initX;
132         dir = s->initDir;
133         type = falling ? -s->type : s->type;
134         mirror = s->mirrored ? -1 : 1;
135         for (i = 0; s->cmds[i] != C_end; ++i)
136                 switch (s->cmds[i]) {
137                         case C_forw:
138                                 MoveInDir(dir, 1, &y, &x);
139                                 break;
140                         case C_back:
141                                 MoveInDir(dir, -1, &y, &x);
142                                 break;
143                         case C_left:
144                                 dir = RotateDir(dir, mirror);
145                                 break;
146                         case C_right:
147                                 dir = RotateDir(dir, -mirror);
148                                 break;
149                         case C_plot:
150                                 if ((result = func(scr, y, x, type, data)))
151                                         return result;
152                                 break;
153                         default:
154                                 assert(0);
155                 }
156         return 0;
157 }
158
159 ExtFunc Shape *ChooseOption(ShapeOption *options)
160 {
161         int i;
162         float total = 0, val;
163
164         for (i = 0; options[i].shape; ++i)
165                 total += options[i].weight;
166         val = Random(0, 32767) / 32768.0 * total;
167         for (i = 0; options[i].shape; ++i) {
168                 val -= options[i].weight;
169                 if (val < 0)
170                         return options[i].shape;
171         }
172         return options[0].shape;
173 }
174
175 ExtFunc short ShapeToNetNum(Shape *shape)
176 {
177         int num;
178
179         for (num = 0; netMapping[num]; ++num)
180                 if (netMapping[num] == shape)
181                         return num;
182         assert(0);
183         return 0;
184 }
185
186 ExtFunc Shape *NetNumToShape(short num)
187 {
188         assert(num >= 0 && num < sizeof(netMapping) / sizeof(netMapping[0]) - 1);
189         return netMapping[num];
190 }
191
192 /*
193  * vi: ts=4 ai
194  * vim: noai si
195  */