1 #include "engine/declarations.h"
2 
3 #include "declarations_app.h"
4 #include "universe.h"
5 
6 
7 
universe_init(void)8 int universe_init(void) {
9 	(void) universe_set_message("");
10 
11 	if((sp = malloc(sizeof(struct universe))) == NULL) {
12 		LOGWARN(
13 			ERROR_SLIGHT, SUBSYSTEM,
14 			_("Failed to allocate %lu bytes of memory"),
15 			(unsigned long) sizeof(struct universe)
16 		);
17 
18 		return(-1);
19 	}
20 
21 	if(universe_create_random() != 0) {
22 		(void) universe_free();
23 
24 		return(-1);
25 	}
26 
27 	return(0);
28 }
29 
universe_free(void)30 void universe_free(void) {
31 	unsigned long i;
32 
33 	if(sp != NULL) {
34 		for(i = 0; i < sp->galaxies; i++) (void) galaxy_free(sp->ga[i]);
35 
36 		(void) free(sp);
37 
38 		sp = NULL;
39 	}
40 }
41 
universe_run(void)42 void universe_run(void) {
43 	unsigned long a, b, c, d;
44 
45 	struct tm tv;
46 
47 	struct galaxy *ga;
48 	struct star *sa;
49 	struct planet *pa, *ca;
50 
51 	(void) timer_get_date_by_time(&tv, (time_t) round(clock_get_ticks()));
52 #if defined(__sun__)
53 	(void) snprintf(
54 		dt, sizeof(dt),
55 		"%d.%d.%d %.2d:%.2d",
56 		tv.tm_mday, tv.tm_mon + 1, tv.tm_year + 1900,
57 		tv.tm_hour, tv.tm_min);
58 #else
59 	(void) snprintf(
60 		dt, sizeof(dt),
61 		"%d.%d.%d %s %.2d:%.2d",
62 		tv.tm_mday, tv.tm_mon + 1, tv.tm_year + 1900, tv.tm_zone,
63 		tv.tm_hour, tv.tm_min);
64 #endif
65 	for(a = 0; a < sp->galaxies; a++) {
66 		ga = sp->ga[a];
67 
68 		(void) galaxy_run(ga);
69 
70 		for(b = 0; b < ga->stars; b++) {
71 			sa = ga->sa[b];
72 
73 			(void) star_run(sa);
74 
75 			for(c = 0; c < sa->planets; c++) {
76 				pa = sa->pa[c];
77 
78 				(void) planet_run(pa);
79 
80 				for(d = 0; d < pa->satellites; d++) {
81 					ca = pa->ca[d];
82 
83 					(void) planet_run(ca);
84 				}
85 			}
86 		}
87 	}
88 }
89 
universe_set_message(char * s)90 void universe_set_message(char *s) {
91 	(void) snprintf(ms, sizeof(ms), "%s", s);
92 
93 	++mc;
94 }
95 
universe_chk_message(void)96 unsigned int universe_chk_message(void) {
97 	return(mc);
98 }
99 
universe_get_message(void)100 char *universe_get_message(void) {
101 	return(ms);
102 }
103 
universe_get_date(void)104 char *universe_get_date(void) {
105 	return(dt);
106 }
107 
universe_get_galaxy_by_id(unsigned long a)108 struct galaxy *universe_get_galaxy_by_id(unsigned long a) {
109 	if(a > sp->galaxies) {
110 		return(NULL);
111 	}
112 
113 	return(sp->ga[a]);
114 }
115 
universe_get_star_by_id(unsigned long a,unsigned long b)116 struct star *universe_get_star_by_id(unsigned long a, unsigned long b) {
117 	if(a > sp->galaxies || b > sp->ga[a]->stars) {
118 		return(NULL);
119 	}
120 
121 	return(sp->ga[a]->sa[b]);
122 }
123 
universe_get_planet_by_id(unsigned long a,unsigned long b,unsigned long c)124 struct planet *universe_get_planet_by_id(unsigned long a, unsigned long b, unsigned long c) {
125 	if(a > sp->galaxies || b > sp->ga[a]->stars || c > sp->ga[a]->sa[b]->planets || sp->ga[a]->sa[b]->planets == 0) {
126 		return(NULL);
127 	}
128 
129 	return(sp->ga[a]->sa[b]->pa[c]);
130 }
131 
universe_get_satellite_by_id(unsigned long a,unsigned long b,unsigned long c,unsigned long d)132 struct planet *universe_get_satellite_by_id(unsigned long a, unsigned long b, unsigned long c, unsigned long d) {
133 	if(a > sp->galaxies || b > sp->ga[a]->stars || c > sp->ga[a]->sa[b]->planets || d > sp->ga[a]->sa[b]->pa[c]->satellites || sp->ga[a]->sa[b]->pa[c]->satellites == 0) {
134 		return(NULL);
135 	}
136 
137 	return(sp->ga[a]->sa[b]->pa[c]->ca[d]);
138 }
139 
universe_create_random(void)140 static int universe_create_random(void) {
141 	unsigned long a;
142 
143 	sp->id = 0;
144 	sp->galaxies = UNIVERSE_GALAXIES_PER_SPACE;
145 
146 	if((sp->ga = malloc(sizeof(struct galaxy *) * sp->galaxies)) == NULL) {
147 		LOGWARN(
148 			ERROR_SLIGHT, SUBSYSTEM,
149 			_("Failed to allocate %lu bytes of memory"),
150 			(unsigned long (sizeof(struct galaxy *) * sp->galaxies)
151 		);
152 
153 		return(-1);
154 	}
155 
156 	/* Populate universe */
157 	for(a = 0; a < sp->galaxies; a++) {
158 		if(galaxy_create(sp, a) != 0) return(-1);
159 		if(universe_create_random_stars(sp->ga[a]) != 0) return(-1);
160 	}
161 
162 	return(0);
163 }
164 
165 static int universe_create_random_stars(struct galaxy *ga) {
166 	unsigned long b;
167 
168 	if(ga->stars > UNIVERSE_STARS_PER_GALAXY_MAX) {
169 		(void) flush_error();
170 
171 		LOGWARN(
172 			ERROR_NOERROR, SUBSYSTEM,
173 			_("Star count %lu exceeds star limit of %u, limiting star count to %u"),
174 			ga->stars, (unsigned int) UNIVERSE_STARS_PER_GALAXY_MAX, (unsigned int) UNIVERSE_STARS_PER_GALAXY_MAX
175 		);
176 
177 		ga->stars = UNIVERSE_STARS_PER_GALAXY_MAX;
178 	}
179 
180 	if((ga->sa = malloc(sizeof(struct star *) * ga->stars)) == NULL) {
181 		LOGWARN(
182 			ERROR_SLIGHT, SUBSYSTEM,
183 			_("Failed to allocate %lu bytes of memory"),
184 			(unsigned long) (sizeof(struct star *) * ga->stars)
185 		);
186 
187 		return(-1);
188 	}
189 
190 	LOGINFO(
191 		ERROR_NOERROR, SUBSYSTEM,
192 		_("Generating %lu solar systems, this may take a while"),
193 		ga->stars
194 	);
195 
196 	/* First star is always a black hole at the center of the galaxy */
197 	if(star_create_blackhole(ga, 0) != 0) return(-1);
198 
199 	(void) star_create_spot_blackhole(ga, 0);
200 
201 	for(b = 1; b < ga->stars; b++) {
202 		switch(maths_rand(1000)) {
203 			case 1:
204 				if(star_create_blackhole(ga, b) != 0) return(-1);
205 
206 				break;
207 			case 2:
208 			case 3:
209 			case 4:
210 				if(star_create_neutron(ga, b) != 0) return(-1);
211 
212 				break;
213 			default:
214 				if(star_create(ga, b) != 0) return(-1);
215 				if(universe_create_random_planets(ga, b) != 0) return(-1);
216 
217 				break;
218 		}
219 
220 		(void) star_create_spot(ga, b);
221 	}
222 
223 	return(0);
224 }
225 
226 static int universe_create_random_planets(struct galaxy *ga, unsigned long b) {
227 	unsigned long c;
228 
229 	/* Create planets for parent star only if star is lucky enough (50% out of 100) */
230 	if(maths_rand(100) > 50) return(0);
231 
232 	ga->sa[b]->planets = UNIVERSE_PLANETS_PER_STAR_MAX - UNIVERSE_PLANETS_PER_STAR_MIN;
233 	ga->sa[b]->planets = (unsigned long) maths_rand((unsigned int) ga->sa[b]->planets) + UNIVERSE_PLANETS_PER_STAR_MIN;
234 
235 	ga->sa[b]->created = ga->sa[b]->planets;
236 
237 	if((ga->sa[b]->pa = malloc(sizeof(struct planet *) * ga->sa[b]->planets)) == NULL) {
238 		LOGWARN(
239 			ERROR_SLIGHT, SUBSYSTEM,
240 			_("Failed to allocate %lu bytes of memory"),
241 			(unsigned long) (sizeof(struct planet *) * ga->sa[b]->planets)
242 		);
243 
244 		return(-1);
245 	}
246 
247 	/* Parent star is a center of solar system now because it has planets */
248 	if(star_create_solar(ga, b) != 0) return(-1);
249 
250 	for(c = 0; c < ga->sa[b]->planets; c++) {
251 		if(planet_create(ga->sa[b], c) != 0) return(-1);
252 		if(universe_create_random_satellites(ga->sa[b], c) != 0) return(-1);
253 	}
254 
255 	return(0);
256 }
257 
258 static int universe_create_random_satellites(struct star *sa, unsigned long c) {
259 	unsigned long d;
260 
261 	/* Create satellites for parent planet if planet is lucky enough (75% out of 100) */
262 	if(maths_rand(100) > 75) return(0);
263 
264 	sa->pa[c]->satellites = UNIVERSE_COMPS_PER_PLANET_MAX - UNIVERSE_COMPS_PER_PLANET_MIN;
265 	sa->pa[c]->satellites = (unsigned long) maths_rand((unsigned int) sa->pa[c]->satellites) + UNIVERSE_COMPS_PER_PLANET_MIN;
266 
267 	if((sa->pa[c]->ca = malloc(sizeof(struct planet *) * sa->pa[c]->satellites)) == NULL) {
268 		LOGWARN(
269 			ERROR_SLIGHT, SUBSYSTEM,
270 			_("Failed to allocate %lu bytes of memory"),
271 			(unsigned long) (sizeof(struct planet *) * sa->pa[c]->satellites)
272 		);
273 
274 		return(-1);
275 	}
276 
277 	for(d = 0; d < sa->pa[c]->satellites; d++) {
278 		if(planet_satellite_create(sa, c, d) != 0) return(-1);
279 	}
280 
281 	return(0);
282 }
283 
284 static void universe_print_human(void) {
285 	(void) fprintf(stdout, _("$ Universe %lu, with %lu galaxies%c"), sp->id, sp->galaxies, CONFIG_LINE_FEED);
286 	(void) fprintf(stdout, "%c", CONFIG_LINE_FEED);
287 }
288 
289 static void universe_header_print_human(void) {
290 	(void) fprintf(stdout, _("# This is %s version %s human-readable catalog%c"), APPLICATION_NAME, APPLICATION_VERSION, CONFIG_LINE_FEED);
291 	(void) fprintf(stdout, "%c", CONFIG_LINE_FEED);
292 }
293