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