1 /*
2  * This file is part of 'Garden of coloured lights'.
3  *
4  * 'Garden of coloured lights' is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * 'Garden of coloured lights' is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with 'Garden of coloured lights'.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 /*
19 
20    This file contains some maths and utility functions. The only ones used at present are:
21 
22    xpart/ypart - call them with angle x and distance d; they'll give you the x component and y component
23    of a line in the angle x and the distance d
24 
25    angle_to_radians - I use a 1024-degree circle in a format called 'angle'. It lets me use lookup tables
26    radians_to_angle   without interpolation for simple trig, and minimises slow floating-point operations.
27    angle_to_radians takes 'angle' values and turns them into radians; radians_to_angle etc.
28 
29    grand(n) - random number from 1 to n
30 
31 
32  */
33 
34 
35 #include "config.h"
36 
37 #include "allegro.h"
38 
39 #include <math.h>
40 
41 int turn_towards_angle (int angle, int tangle, int turning);
42 int delta_turn_towards_angle (int angle, int tangle, int turning);
43 
44 float lcos (int angle);
45 float lsin (int angle);
46 float angle_to_radians (int angle);
47 
48 // I have no idea why, but the first few elements of cos_table always get corrupted
49 //  unless I put a big fat decoy array just above. A similar thing happens to the
50 //  palette arrays; allegro seems to have a problem with global arrays like these.
51 float decoy_table[ANGLE_1];	// not used
52 float cos_table[ANGLE_1];
53 float sin_table[ANGLE_1];
54 
55 int xpart (int angle, int length);
56 
init_trig(void)57 void init_trig (void)
58 {
59 	int i;
60 
61 	for (i = 0; i < ANGLE_1; i++)
62 	{
63 		cos_table[i] = cos (angle_to_radians (i));	// * ANGLE_1;
64 		sin_table[i] = sin (angle_to_radians (i));	// * ANGLE_1;
65 	}
66 
67 
68 }
69 
xpart(int angle,int length)70 int xpart (int angle, int length)
71 {
72 	return (cos_table[angle & 1023] * length);
73 }
74 
ypart(int angle,int length)75 int ypart (int angle, int length)
76 {
77 	return (sin_table[angle & 1023] * length);
78 }
79 
lcos(int angle)80 float lcos (int angle)
81 {
82 	return cos_table[angle & 1023];
83 
84 }
85 
lsin(int angle)86 float lsin (int angle)
87 {
88 	return sin_table[angle & 1023];
89 
90 }
91 
92 
angle_to_radians(int angle)93 float angle_to_radians (int angle)
94 {
95 	return ((float) angle * PI * 2) / ANGLE_1;
96 }
97 
radians_to_angle(float angle)98 int radians_to_angle (float angle)
99 {
100 	if (angle < 0)
101 		angle += PI * 2;
102 	return (int) ((angle * ANGLE_1) / (PI * 2));
103 }
104 
angle_to_fixed(int angle)105 fixed angle_to_fixed (int angle)
106 {
107 	return itofix (angle / ANGLE_TO_FIXED);
108 }
109 
grand(int number)110 int grand (int number)
111 {
112 	if (number == 0)
113 		return 0;
114 	return ((rand () + (rand () << 16)) & 0x7fffffff) % number;
115 }
116 
117 // returns the new angle
turn_towards_angle(int angle,int tangle,int turning)118 int turn_towards_angle (int angle, int tangle, int turning)
119 {
120 
121 	if ((angle < tangle && tangle > angle + ANGLE_2)
122 	        || (angle > tangle && tangle > angle - ANGLE_2))
123 	{
124 		angle -= turning;
125 		if (angle < 0)
126 			angle += ANGLE_1;
127 	}
128 	else
129 	{
130 		angle += turning;
131 		if (angle > ANGLE_1)
132 			angle -= ANGLE_1;
133 	}
134 
135 	return angle;
136 
137 }
138 
139 
turn_towards_xy(int x1,int y1,int x2,int y2,int angle,int turning)140 int turn_towards_xy (int x1, int y1, int x2, int y2, int angle, int turning)
141 {
142 
143 	int tangle = radians_to_angle (atan2 ((y2 - y1), (x2 - x1))) & 1023;
144 	/*   if (tangle < 0)
145 	    tangle += ANGLE_1;
146 	   if (tangle > ANGLE_1)
147 	    tangle -= ANGLE_1;*/
148 
149 	return turn_towards_angle (angle, tangle, turning);
150 
151 }
152 
153 // delta version just returns the change needed
delta_turn_towards_angle(int angle,int tangle,int turning)154 int delta_turn_towards_angle (int angle, int tangle, int turning)
155 {
156 
157 // if ((angle < tangle && tangle > angle + ANGLE_2)
158 	if ((angle < tangle && tangle > angle + ANGLE_2)
159 	        || (angle > tangle && tangle > angle - ANGLE_2))
160 	{
161 		return turning * -1;
162 	}
163 
164 	return turning;
165 
166 }
167 
odd_even(int v)168 int odd_even (int v)
169 {
170 	if ((v | 1) == 1)
171 		return 1;
172 
173 	return -1;
174 
175 }
176 
delta_turn_towards_xy(int x1,int y1,int x2,int y2,int angle,int turning)177 int delta_turn_towards_xy (int x1, int y1, int x2, int y2, int angle,
178                            int turning)
179 {
180 
181 	int tangle = radians_to_angle (atan2 ((y2 - y1), (x2 - x1)));
182 	if (tangle < 0)
183 		tangle += ANGLE_1;
184 	if (tangle > ANGLE_1)
185 		tangle -= ANGLE_1;
186 
187 	return delta_turn_towards_angle (angle, tangle, turning);
188 
189 }
190 
191 
192 
193 // speed must be at least 4, and a factor of 1024
pulsate(int speed,int amount,int county)194 int pulsate (int speed, int amount, int county)
195 {
196 	return xpart ((county * speed) & 1023, amount);
197 }
198 
error_message_out(const char * errm)199 void error_message_out (const char *errm)
200 {
201 	set_gfx_mode (GFX_TEXT, 0, 0, 0, 0);
202 	allegro_message ("%s", errm);
203 	exit (1);
204 }
205 
206 
angle_difference(int a1,int a2)207 int angle_difference (int a1, int a2)
208 {
209 	int d1, d2;
210 
211 	d1 = (a1 - a2 + ANGLE_1) % ANGLE_1;
212 	d2 = (a2 - a1 + ANGLE_1) % ANGLE_1;
213 
214 	if (d1 < d2)
215 		return abs (d1);
216 
217 	return abs (d2);
218 }
219 
220 
pos_or_neg(int a)221 int pos_or_neg (int a)
222 {
223 	if (grand (2) == 0)
224 		return a;
225 
226 	return a * -1;
227 
228 }
229