1 #include "engine/declarations.h"
2 
3 #include "declarations_app.h"
4 #include "elements.h"
5 #include "star.h"
6 
7 
8 
star_create(struct galaxy * ga,unsigned long b)9 int star_create(struct galaxy *ga, unsigned long b) {
10 	struct star *s;
11 
12 	if((ga->sa[b] = malloc(sizeof(struct star))) == NULL) {
13 		LOGWARN(
14 			ERROR_SLIGHT, SUBSYSTEM,
15 			_("Failed to allocate %lu bytes of memory"),
16 			(unsigned long) sizeof(struct star)
17 		);
18 
19 		return(-1);
20 	}
21 
22 	s = ga->sa[b];
23 
24 	s->id = b;
25 	s->pd = ga->id;
26 
27 	s->planets = 0;
28 	s->created = 0;
29 	s->fusion = 0.0;
30 	s->solarsize = 0.0;
31 
32 	(void) star_create_comp(s);
33 	(void) star_create_spec(s);
34 	(void) star_create_draw(s);
35 
36 	if(star_create_name(s) != 0) return(-1);
37 	if(star_create_nick(s) != 0) return(-1);
38 
39 	s->pa = NULL;
40 
41 	s->solar = NULL;
42 	s->solar_t = 0;
43 
44 	return(0);
45 }
46 
star_create_neutron(struct galaxy * ga,unsigned long b)47 int star_create_neutron(struct galaxy *ga, unsigned long b) {
48 	struct star *s;
49 
50 	if((ga->sa[b] = malloc(sizeof(struct star))) == NULL) {
51 		LOGWARN(
52 			ERROR_SLIGHT, SUBSYSTEM,
53 			_("Failed to allocate %lu bytes of memory"),
54 			(unsigned long) sizeof(struct star)
55 		);
56 
57 		return(-1);
58 	}
59 
60 	s = ga->sa[b];
61 
62 	s->id = b;
63 	s->pd = ga->id;
64 
65 	s->planets = 0;
66 	s->created = 0;
67 	s->fusion = 0.0;
68 	s->solarsize = 0.0;
69 
70 	(void) star_create_comp_neutron(s);
71 	(void) star_create_spec_neutron(s);
72 	(void) star_create_draw(s);
73 
74 	if(star_create_name(s) != 0) return(-1);
75 	if(star_create_nick(s) != 0) return(-1);
76 
77 	s->pa = NULL;
78 
79 	s->solar = NULL;
80 	s->solar_t = 0;
81 
82 	return(0);
83 }
84 
star_create_blackhole(struct galaxy * ga,unsigned long b)85 int star_create_blackhole(struct galaxy *ga, unsigned long b) {
86 	struct star *s;
87 
88 	if((ga->sa[b] = malloc(sizeof(struct star))) == NULL) {
89 		LOGWARN(
90 			ERROR_SLIGHT, SUBSYSTEM,
91 			_("Failed to allocate %lu bytes of memory"),
92 			(unsigned long) sizeof(struct star)
93 		);
94 
95 		return(-1);
96 	}
97 
98 	s = ga->sa[b];
99 
100 	s->id = b;
101 	s->pd = ga->id;
102 
103 	s->planets = 0;
104 	s->created = 0;
105 	s->fusion = 0.0;
106 	s->solarsize = 0.0;
107 
108 	(void) star_create_comp_blackhole(s);
109 	(void) star_create_spec_blackhole(s);
110 	(void) star_create_draw(s);
111 
112 	if(star_create_name(s) != 0) return(-1);
113 	if(star_create_nick(s) != 0) return(-1);
114 
115 	s->pa = NULL;
116 
117 	s->solar = NULL;
118 	s->solar_t = 0;
119 
120 	return(0);
121 }
122 
star_create_comp(struct star * sa)123 static void star_create_comp(struct star *sa) {
124 	/* Largest percentage of total mass -order */
125 	struct star_cont sc[] = {
126 		{ STAR_COMP_HELIUM_MIN, STAR_COMP_HELIUM_MAX, &sa->sc.helium },
127 		{ STAR_COMP_OXYGEN_MIN, STAR_COMP_OXYGEN_MAX, &sa->sc.oxygen },
128 		{ STAR_COMP_CARBON_MIN, STAR_COMP_CARBON_MAX, &sa->sc.carbon },
129 		{ STAR_COMP_NITROGEN_MIN, STAR_COMP_NITROGEN_MAX, &sa->sc.nitrogen },
130 		{ STAR_COMP_SILICON_MIN, STAR_COMP_SILICON_MAX, &sa->sc.silicon },
131 		{ STAR_COMP_MAGNESIUM_MIN, STAR_COMP_MAGNESIUM_MAX, &sa->sc.magnesium },
132 		{ STAR_COMP_NEON_MIN, STAR_COMP_NEON_MAX, &sa->sc.neon },
133 		{ STAR_COMP_IRON_MIN, STAR_COMP_IRON_MAX, &sa->sc.iron },
134 		{ STAR_COMP_SULFUR_MIN, STAR_COMP_SULFUR_MAX, &sa->sc.sulfur },
135 
136 		{ 0, 0, NULL }
137 	};
138 
139 	sa->sc.hydrogen = 100.0 - star_create_comp_op(sc);
140 }
141 
star_create_comp_neutron(struct star * sa)142 static void star_create_comp_neutron(struct star *sa) {
143 	/* Content of neutron star is solid iron here, as nobody knows for sure */
144 	sa->sc.carbon = 0.0;
145 	sa->sc.helium = 0.0;
146 	sa->sc.hydrogen = 0.0;
147 	sa->sc.iron = 100.0;
148 	sa->sc.magnesium = 0.0;
149 	sa->sc.neon = 0.0;
150 	sa->sc.nitrogen = 0.0;
151 	sa->sc.oxygen = 0.0;
152 	sa->sc.silicon = 0.0;
153 	sa->sc.sulfur = 0.0;
154 }
155 
star_create_comp_blackhole(struct star * sa)156 static void star_create_comp_blackhole(struct star *sa) {
157 	/* Content of black hole is not known, they say that it does not contain any kind of information */
158 	sa->sc.carbon = 0.0;
159 	sa->sc.helium = 0.0;
160 	sa->sc.hydrogen = 0.0;
161 	sa->sc.iron = 0.0;
162 	sa->sc.magnesium = 0.0;
163 	sa->sc.neon = 0.0;
164 	sa->sc.nitrogen = 0.0;
165 	sa->sc.oxygen = 0.0;
166 	sa->sc.silicon = 0.0;
167 	sa->sc.sulfur = 0.0;
168 }
169 
star_create_comp_op(struct star_cont * s)170 static float star_create_comp_op(struct star_cont *s) {
171 	unsigned int i, t;
172 	float c, d;
173 
174 	c = 0.0;
175 
176 	for(i = 0; ; i++) {
177 		if(s[i].c == NULL) break;
178 
179 		t = s[i].b - s[i].a;
180 		t = maths_rand(t) + s[i].a;
181 
182 		d = (((float) t / 100000.0) / 100.0) * (100.0 - c);
183 
184 		*s[i].c = d;
185 
186 		c += d;
187 	}
188 
189 	return(c);
190 }
191 
star_create_spec(struct star * sa)192 static void star_create_spec(struct star *sa) {
193 	sa->ss.bm = (double) maths_rand(140 - -5);				/* Star mean Bt magnitude (-0.5 - 14.0) */
194 	sa->ss.bm = (sa->ss.bm + -5.0) / 100.0;
195 
196 	sa->ss.vm = (double) maths_rand(140 - -5);				/* Star mean Vt magnitude (-0.5 - 14.0) */
197 	sa->ss.vm = (sa->ss.vm + -5.0) / 100.0;
198 
199 	sa->ss.jm = (double) maths_rand(140 - -14);				/* Star magnitude in Johnson V (-1.44 - 14.0) */
200 	sa->ss.jm = (sa->ss.jm + -14.0) / 100.0;
201 
202 	sa->ss.bv = (double) maths_rand(2400 - -315);				/* Star BtVt index (-0.315 - 2.4) (sa->ss.bm - sa->ss.vm) */
203 	sa->ss.bv = maths_btvt_to_bv((sa->ss.bv + -315.0) / 1000.0);
204 
205 	sa->ss.parallax = (double) maths_rand(7720 - 1);			/* Star trigonometric parallax (0.1 - 772.0) */
206 	sa->ss.parallax = (sa->ss.parallax + 10.0) / 100.0;
207 
208 	sa->ss.magnitude = maths_amag_by_vmag_distance(sa->ss.jm, maths_parsec_by_parallax(sa->ss.parallax));
209 	sa->ss.temperature = maths_bv_to_temperature(sa->ss.bv);
210 	sa->ss.radius = maths_radius_by_amag_temperature(sa->ss.magnitude, sa->ss.temperature) / 1000.0;
211 	sa->ss.luminance = maths_luminance_by_radius_temperature(sa->ss.radius, sa->ss.temperature) * 1000000.0;
212 
213 	sa->ss.mass = (double) (sa->ss.radius / STAR_SUN_RADIUS_KM) * STAR_SUN_MASS_KG;
214 	sa->ss.area = (double) (sa->ss.radius * sa->ss.radius) * CONST_PI_4;
215 	sa->ss.volume = (double) (sa->ss.radius * sa->ss.radius * sa->ss.radius) * CONST_VOLUME_SP;
216 
217 	(void) star_create_spec_spectral(sa, sa->ss.bv);
218 	(void) star_create_spec_type(sa, sa->ss.magnitude, sa->ss.temperature);
219 	(void) star_create_spec_flat(sa);
220 
221 	/* Energy is calculated what core produces (10%), hence 0.1 */
222 	sa->ss.energy = (double) 0.007 * 0.1 * sa->ss.mass * (STAR_SOL * STAR_SOL);
223 
224 	sa->ss.lifetime = sa->ss.energy / sa->ss.luminance;
225 	sa->ss.lifetime *= 1.0 / CONST_SECS_YEAR;				/* Convert seconds to years */
226 	sa->ss.lifetime /= 1000000.0;						/* Convert years to millions */
227 
228 	sa->ss.centripetal = (sa->ss.rotation * sa->ss.rotation) / (sa->ss.radius * 1000.0);
229 
230 	sa->ss.acceleration = (sa->ss.mass * CONST_GRAVITY) / ((sa->ss.radius * 1000.0) * (sa->ss.radius * 1000.0));
231 	sa->ss.acceleration -= sa->ss.centripetal;
232 
233 	sa->ss.velocity = sqrtf((float) (CONST_GRAVITY_2 * (sa->ss.mass / 1000.0)) / sa->ss.radius);
234 	sa->ss.velocity /= 1000.0;						/* Convert to meters */
235 
236 	(void) color_bv_to_rgba(&sa->ss.rgb, sa->ss.bv, sa->ss.vm);
237 }
238 
star_create_spec_spectral(struct star * sa,double b)239 static void star_create_spec_spectral(struct star *sa, double b) {
240 	unsigned int i;
241 	double d;
242 	char *r;
243 
244 	d = 9999.0;
245 	r = "  ";
246 
247 	for(i = 0; ; i++) {
248 		if(star_spectral[i].s == NULL) break;
249 		if(fabs(b - star_spectral[i].c) < d) {
250 			d = fabs(b - star_spectral[i].c);
251 			r = star_spectral[i].s;
252 		}
253 	}
254 
255 	(void) memcpy((void *) sa->spectral, (const void *) r, sizeof(sa->spectral));
256 }
257 
star_create_spec_type(struct star * sa,double a,double k)258 static void star_create_spec_type(struct star *sa, double a, double k) {
259 	/* Generate star class */
260 	if(k > 33000.0) sa->class = STAR_CLASS_O;
261 	else if(k > 10000.0) sa->class = STAR_CLASS_B;
262 	else if(k > 7500.0) sa->class = STAR_CLASS_A;
263 	else if(k > 6000.0) sa->class = STAR_CLASS_F;
264 	else if(k > 5200.0) sa->class = STAR_CLASS_G;
265 	else if(k > 3700.0) sa->class = STAR_CLASS_K;
266 	else if(k > 2400.0) sa->class = STAR_CLASS_M;
267 	else if(k > 1300.0) sa->class = STAR_CLASS_L;
268 	else if(k > 500.0) sa->class = STAR_CLASS_T;
269 	else sa->class = STAR_CLASS_Y;
270 
271 	/* Generate star type */
272 	if(a > 15.0) sa->type = STAR_TYPE_DWARF_BROWN;
273 	else if(a > 10.0) sa->type = STAR_TYPE_DWARF_RED;
274 	else if(a > 5.0) sa->type = STAR_TYPE_DWARF_WHITE;
275 	else if(a > 0.0) sa->type = STAR_TYPE_GIANT_SUB;
276 	else if(a > -5.0) sa->type = STAR_TYPE_GIANT;
277 	else if(a > -10.0) sa->type = STAR_TYPE_GIANT_SUPER;
278 	else sa->type = STAR_TYPE_GIANT_HYPER;
279 }
280 
star_create_spec_flat(struct star * sa)281 static void star_create_spec_flat(struct star *sa) {
282 	unsigned int a, b;
283 	double c, r;
284 
285 	/* Rotation speed has 20% tolerance, hence / 5 */
286 	a = star_flat[sa->class] - (star_flat[sa->class] / 5);
287 	b = star_flat[sa->class] + (star_flat[sa->class] / 5);
288 
289 	a *= 36000;
290 	b *= 36000;
291 
292 	sa->ss.rotation = (double) (maths_rand(b - a) + a) / 1000.0;
293 
294 	r = sa->ss.radius * 1000.0;						/* Convert radius to meters */
295 	c = sa->ss.rotation / r;						/* Star angular velocity */
296 
297 	sa->ss.flattening = 1.25 * (((c * c) * (r * r * r)) / (CONST_GRAVITY * sa->ss.mass));
298 
299 	sa->ss.radius_e = sa->ss.radius * (1.0 + 2.0 * sa->ss.flattening / 3.0);
300 	sa->ss.radius_p = sa->ss.radius * (1.0 - 2.0 * sa->ss.flattening / 3.0);
301 }
302 
star_create_spec_neutron(struct star * sa)303 static void star_create_spec_neutron(struct star *sa) {
304 	double d;
305 
306 	sa->ss.bm = 0.0;
307 	sa->ss.vm = 0.0;
308 	sa->ss.jm = 0.0;
309 	sa->ss.bv = 0.0;
310 
311 	sa->ss.parallax = 0.0;
312 
313 	/* Neutron star mass is from 1 to 5 times of the sun */
314 	d = (double) (maths_rand(4000000) + 1000000);
315 	d /= 1000000.0;
316 
317 	sa->ss.mass = d * STAR_SUN_MASS_KG;
318 
319 	/* Neutron star radius is from 10 to 30 kilometers */
320 	d = (double) (maths_rand(20000000) + 10000000);
321 	d /= 1000000.0;
322 
323 	sa->ss.radius = d;
324 
325 	sa->ss.area = (double) (sa->ss.radius * sa->ss.radius) * CONST_PI_4;
326 	sa->ss.volume = (double) (sa->ss.radius * sa->ss.radius * sa->ss.radius) * CONST_VOLUME_SP;
327 
328 	sa->ss.magnitude = (double) (maths_rand(20000) + 20000);
329 	sa->ss.magnitude /= 1000.0;
330 
331 	sa->ss.temperature = (double) maths_rand(1000000) + 100000.0;
332 	sa->ss.luminance = maths_luminance_by_radius_temperature(sa->ss.radius, sa->ss.temperature) * 1000000.0;
333 
334 	(void) star_create_spec_neutron_type(sa);
335 	(void) star_create_spec_flat(sa);
336 
337 	sa->ss.energy = (double) 0.007 * sa->ss.mass * (STAR_SOL * STAR_SOL);
338 
339 	sa->ss.lifetime = sa->ss.energy / sa->ss.luminance;
340 	sa->ss.lifetime *= 1.0 / CONST_SECS_YEAR;				/* Convert seconds to years */
341 	sa->ss.lifetime /= 1000000.0;						/* Convert years to millions */
342 
343 	sa->ss.centripetal = (sa->ss.rotation * sa->ss.rotation) / (sa->ss.radius * 1000.0);
344 
345 	sa->ss.acceleration = (sa->ss.mass * CONST_GRAVITY) / ((sa->ss.radius * 1000.0) * (sa->ss.radius * 1000.0));
346 	sa->ss.acceleration -= sa->ss.centripetal;
347 
348 	sa->ss.velocity = sqrtf((float) (CONST_GRAVITY_2 * (sa->ss.mass / 1000.0)) / sa->ss.radius);
349 	sa->ss.velocity /= 1000.0;						/* Convert to meters */
350 
351 	sa->ss.rgb.pixel.r = 255;
352 	sa->ss.rgb.pixel.g = 255;
353 	sa->ss.rgb.pixel.b = 255;
354 	sa->ss.rgb.pixel.a = 255;
355 }
356 
star_create_spec_neutron_type(struct star * sa)357 static void star_create_spec_neutron_type(struct star *sa) {
358 	unsigned int k;
359 
360 	k = maths_rand(100);
361 
362 	/* This neutron star is possibly pulsar or magnetar (25% chance out of 100 for each) */
363 	if(k < 25) sa->class = STAR_CLASS_NEUTRON_PULSAR;
364 	else if(k < 50)  sa->class = STAR_CLASS_NEUTRON_MAGNETAR;
365 	else sa->class = STAR_CLASS_NEUTRON_NEUTRON;
366 
367 	sa->type = STAR_TYPE_NEUTRON;
368 }
369 
star_create_spec_blackhole(struct star * sa)370 static void star_create_spec_blackhole(struct star *sa) {
371 	double d;
372 
373 	sa->ss.bm = 0.0;
374 	sa->ss.vm = 0.0;
375 	sa->ss.jm = 0.0;
376 	sa->ss.bv = 0.0;
377 
378 	sa->ss.parallax = 0.0;
379 
380 	d = (double) (maths_rand(1000000) + 1);
381 	d /= (double) (maths_rand(10) + 1);
382 
383 	sa->ss.mass = d * STAR_SUN_MASS_KG;
384 
385 	sa->ss.radius = (double) ((2.0 * CONST_GRAVITY) * sa->ss.mass) / (STAR_SOL * STAR_SOL);
386 	sa->ss.radius /= 1000.0;						/* Convert to kilometers */
387 
388 	sa->ss.radius_e = sa->ss.radius;
389 	sa->ss.radius_p = sa->ss.radius;
390 
391 	sa->ss.area = (double) (sa->ss.radius * sa->ss.radius) * CONST_PI_4;
392 	sa->ss.volume = (double) (sa->ss.radius * sa->ss.radius * sa->ss.radius) * CONST_VOLUME_SP;
393 
394 	sa->ss.acceleration = (float) 1.0 / sa->ss.mass;
395 	sa->ss.acceleration *= STAR_SOL * STAR_SOL * STAR_SOL * STAR_SOL;
396 	sa->ss.acceleration /= 4.0 * CONST_GRAVITY;
397 
398 	sa->ss.velocity = sqrtf((float) (CONST_GRAVITY_2 * (sa->ss.mass / 1000.0)) / sa->ss.radius);
399 	sa->ss.velocity /= 1000.0;						/* Convert to meters */
400 
401 	sa->ss.temperature = (double) 1.0 / sa->ss.mass;
402 	sa->ss.temperature *= CONST_HBAR * (STAR_SOL * STAR_SOL * STAR_SOL);
403 	sa->ss.temperature /= 8.0 * CONST_KBAR * CONST_PI * CONST_GRAVITY;
404 
405 	sa->ss.luminance = (double) 1.0 / (sa->ss.mass * sa->ss.mass);
406 	sa->ss.luminance *= CONST_HBAR * (STAR_SOL * STAR_SOL * STAR_SOL * STAR_SOL * STAR_SOL * STAR_SOL);
407 	sa->ss.luminance /= 15360.0 * CONST_PI * (CONST_GRAVITY * CONST_GRAVITY);
408 
409 	sa->ss.lifetime = (double) (sa->ss.mass * sa->ss.mass * sa->ss.mass);
410 	sa->ss.lifetime *= 5120 * CONST_PI * (CONST_GRAVITY * CONST_GRAVITY);
411 	sa->ss.lifetime /= CONST_HBAR * (STAR_SOL * STAR_SOL * STAR_SOL * STAR_SOL);
412 
413 	sa->ss.magnitude = (double) 1e9;
414 
415 	sa->ss.energy = (double) 0.007 * sa->ss.mass * (STAR_SOL * STAR_SOL);
416 
417 	sa->ss.rotation = 0.0;
418 	sa->ss.flattening = 0.0;
419 
420 	sa->ss.centripetal = 0.0;
421 
422 	(void) star_create_spec_blackhole_type(sa, sa->ss.mass);
423 
424 	sa->ss.rgb.pixel.r = STAR_DRAW_LIGHT_BLACKHOLE_RED;
425 	sa->ss.rgb.pixel.g = STAR_DRAW_LIGHT_BLACKHOLE_GREEN;
426 	sa->ss.rgb.pixel.b = STAR_DRAW_LIGHT_BLACKHOLE_BLUE;
427 	sa->ss.rgb.pixel.a = 255;
428 }
429 
star_create_spec_blackhole_type(struct star * sa,double k)430 static void star_create_spec_blackhole_type(struct star *sa, double k) {
431 	double d;
432 
433 	d = k / STAR_SUN_MASS_KG;
434 
435 	if(d > 100000.0) sa->class = STAR_CLASS_BLACKHOLE_SUPERMASSIVE;
436 	else if(d > 5000.0) sa->class = STAR_CLASS_BLACKHOLE_INTERMEDIATE;
437 	else if(d > 20.0) sa->class = STAR_CLASS_BLACKHOLE_STELLAR;
438 	else sa->class = STAR_CLASS_BLACKHOLE_MICRO;
439 
440 	sa->type = STAR_TYPE_BLACKHOLE;
441 }
442 
star_create_draw(struct star * sa)443 static void star_create_draw(struct star *sa) {
444 	sa->sd.p_w = STAR_DRAW_PREVIEW_WIDTH;
445 	sa->sd.p_h = STAR_DRAW_PREVIEW_HEIGHT;
446 
447 	sa->sd.c = maths_rand(STAR_DRAW_NOISE_SEED);
448 
449 	sa->sd.ca = 0;
450 
451 	sa->sd.p_t = 0;
452 	sa->sd.p_p = NULL;
453 
454 	sa->sd.cc_p = NULL;
455 	sa->sd.cp_p = NULL;
456 
457 	(void) memset((void *) &sa->sd.cp, 0, sizeof(sa->sd.cp));
458 	(void) memset((void *) &sa->sd.cp_f, 0, sizeof(sa->sd.cp_f));
459 
460 	(void) memset((void *) &sa->sd.cc_s, 0, sizeof(sa->sd.cc_s));
461 	(void) memset((void *) &sa->sd.cp_s, 0, sizeof(sa->sd.cp_s));
462 }
463 
star_create_name(struct star * sa)464 static int star_create_name(struct star *sa) {
465 	char n[STAR_NAME_LEN_MAX];
466 
467 	/* Generate star name (PARENT_ID-STAR_ID-CLASS-TYPE) */
468 	(void) snprintf(n, sizeof(n), "%s-%lu-%lu-%u-%u", star_name_p, sa->pd, sa->id, sa->class, sa->type);
469 
470 	sa->name_t = strnlen(n, sizeof(n) - sizeof(char));
471 
472 	if((sa->name = malloc((size_t) sa->name_t + (sizeof(char) * 4))) == NULL) {
473 		LOGWARN(
474 			ERROR_SLIGHT, SUBSYSTEM,
475 			_("Failed to allocate %lu bytes of memory"),
476 			(unsigned long) (sa->name_t + sizeof(char))
477 		);
478 
479 		return(-1);
480 	}
481 
482 	(void) memcpy((void *) sa->name, (const void *) n, sa->name_t);
483 
484 	sa->name[sa->name_t] = 0;
485 	sa->name[sa->name_t + 1] = 0;
486 	sa->name[sa->name_t + 2] = 0;
487 	sa->name[sa->name_t + 3] = 0;
488 
489 	return(0);
490 }
491 
star_create_nick(struct star * sa)492 static int star_create_nick(struct star *sa) {
493 	sa->nick = NULL;
494 	sa->nick_t = 0;
495 
496 	return(0);
497 }
498 
star_create_solar(struct galaxy * ga,unsigned long b)499 int star_create_solar(struct galaxy *ga, unsigned long b) {
500 	char *e, *f;
501 
502 	char n[STAR_NAME_LEN_MAX];
503 
504 	struct star *s;
505 
506 	s = ga->sa[b];
507 
508 	/* Generate solar system name (ID-PARENT_ID-STAR_ID-COUNTER) */
509 	e = star_solar_name_a[maths_rand(STAR_SOLAR_NAME_A)];
510 	f = star_solar_name_a[maths_rand(STAR_SOLAR_NAME_A)];
511 
512 	(void) snprintf(n, sizeof(n), _("%s%s-%lu-%lu-%lu system"), e, f, s->pd, s->id, ga->solars++);
513 
514 	n[0] = (char) toupper((int) n[0]);
515 	n[1] = (char) toupper((int) n[1]);
516 
517 	s->solar_t = strnlen(n, sizeof(n) - sizeof(char));
518 
519 	if((s->solar = malloc((size_t) s->solar_t + (sizeof(char) * 4))) == NULL) {
520 		LOGWARN(
521 			ERROR_SLIGHT, SUBSYSTEM,
522 			_("Failed to allocate %lu bytes of memory"),
523 			(unsigned long) (s->solar_t + sizeof(char))
524 		);
525 
526 		return(-1);
527 	}
528 
529 	(void) memcpy((void *) s->solar, (const void *) n, s->solar_t);
530 
531 	s->solar[s->solar_t] = 0;
532 	s->solar[s->solar_t + 1] = 0;
533 	s->solar[s->solar_t + 2] = 0;
534 	s->solar[s->solar_t + 3] = 0;
535 
536 	return(0);
537 }
538 
star_create_spot(struct galaxy * ga,unsigned long b)539 void star_create_spot(struct galaxy *ga, unsigned long b) {
540 	double i, d, e, g, u, v, x, y, z;
541 
542 	struct star *s;
543 
544 	s = ga->sa[b];
545 
546 	/* Gaussian curve is from 0.0 to 0.4 */
547 	d = -5.0;
548 	e = -(d) / (double) ga->stars;
549 
550 	d += e * (double) b;
551 
552 	g = maths_gaussian_dens(d);
553 
554 	/* Which galaxy arm we are on (z = 2 * pi = whole round) */
555 	z = (CONST_PI * 2.0) / (double) ga->gs.arms;
556 	z *= b % ga->gs.arms;
557 
558 	i = ga->gs.steps * (double) b;
559 
560 	/* Randomness increases a bit towards the galaxy arm tail */
561 	u = maths_gaussian_rand(g, ga->gs.sigma) * ga->gs.dispersion * (i + 1.0);
562 	v = maths_gaussian_rand(g, ga->gs.sigma) * ga->gs.dispersion * (i + 1.0);
563 
564 	x = (sin(i + z) * i) * ga->gs.radius;
565 	y = (sin(i + z + (CONST_PI / 2.0))) * (i + (CONST_PI / 2.0)) * ga->gs.radius;
566 
567 	switch(b % 4) {
568 		case 0:
569 			x -= u;
570 			y += v;
571 
572 			break;
573 		case 1:
574 			x -= u;
575 			y -= v;
576 
577 			break;
578 		case 2:
579 			x += u;
580 			y -= v;
581 
582 			break;
583 		default:
584 			x += u;
585 			y += v;
586 
587 			break;
588 	}
589 
590 	s->sp.x = x * CONST_LY_KM;
591 	s->sp.y = y * CONST_LY_KM;
592 	s->sp.z = 0.0;
593 
594 	/* Update galaxy dimensions */
595 	if(s->sp.x < ga->gd_a.x) ga->gd_a.x = s->sp.x;
596 	if(s->sp.y < ga->gd_a.y) ga->gd_a.y = s->sp.y;
597 	if(s->sp.z < ga->gd_a.z) ga->gd_a.z = s->sp.z;
598 
599 	if(s->sp.x > ga->gd_b.x) ga->gd_b.x = s->sp.x;
600 	if(s->sp.y > ga->gd_b.y) ga->gd_b.y = s->sp.y;
601 	if(s->sp.z > ga->gd_b.z) ga->gd_b.z = s->sp.z;
602 
603 	/* Initial velocity of star makes galaxy to swirl */
604 	d = 1.0 + (maths_rand(10) / 10.0);
605 	e = (double) (1.0 / (maths_rand(10) + 1));
606 
607 	x = (s->sp.x * cos(d) - s->sp.y * sin(d)) / (CONST_LY_KM / 2.0 * e);
608 	y = (s->sp.x * sin(d) + s->sp.y * cos(d)) / (CONST_LY_KM / 2.0 * e);
609 
610 	s->sv.x = x;
611 	s->sv.y = y;
612 	s->sv.z = 0.0;
613 }
614 
star_create_spot_blackhole(struct galaxy * ga,unsigned long b)615 void star_create_spot_blackhole(struct galaxy *ga, unsigned long b) {
616 	struct star *s;
617 
618 	s = ga->sa[b];
619 
620 	/* Black hole sits at the center of the galaxy */
621 	s->sp.x = 0.0;
622 	s->sp.y = 0.0;
623 	s->sp.z = 0.0;
624 
625 	s->sv.x = 0.0;
626 	s->sv.y = 0.0;
627 	s->sv.z = 0.0;
628 }
629 
star_free(struct star * sa)630 void star_free(struct star *sa) {
631 	unsigned long i;
632 
633 	if(sa != NULL) {
634 		(void) star_live_free(sa);
635 		(void) star_preview_free(sa);
636 
637 		if(sa->name != NULL) (void) free(sa->name);
638 		if(sa->nick != NULL) (void) free(sa->nick);
639 		if(sa->solar != NULL) (void) free(sa->solar);
640 
641 		for(i = 0; i < sa->created; i++) (void) planet_free(sa->pa[i]);
642 
643 		(void) free(sa);
644 	}
645 }
646 
star_image(struct star * sa,char * d,int m)647 void star_image(struct star *sa, char *d, int m) {
648 	char *s;
649 
650 	char n[CONFIG_LINE_LENGTH];
651 
652 	size_t t;
653 
654 	t = CONFIG_PATH_LENGTH;
655 
656 	if((s = malloc(t + sizeof(char))) == NULL) {
657 		LOGWARN(
658 			ERROR_SLIGHT, SUBSYSTEM,
659 			_("Failed to allocate %lu bytes of memory"),
660 			(unsigned long) (t + sizeof(char))
661 		);
662 
663 		return;
664 	}
665 
666 	if(sa->nick != NULL) {
667 		(void) snprintf(
668 			s, t,
669 			"%s%cstar_%s_%s.%s",
670 			d, CONFIG_PATH_DELIM, sa->name, sa->nick, (char *) image_get_suffix_by_type(m)
671 		);
672 	}
673 	else {
674 		(void) snprintf(
675 			s, t,
676 			"%s%cstar_%s.%s",
677 			d, CONFIG_PATH_DELIM, sa->name, (char *) image_get_suffix_by_type(m)
678 		);
679 	}
680 
681 	if(star_preview_create(sa, sa->sd.p_w, sa->sd.p_h, 1.5) != 0) {
682 		(void) free(s);
683 
684 		return;
685 	}
686 
687 	(void) image_write_32(sa->sd.p_p, (unsigned int) sa->sd.p_w, (unsigned int) sa->sd.p_h, s, m);
688 
689 	(void) snprintf(
690 		n, sizeof(n),
691 		"Star image saved to %s",
692 		s);
693 
694 	(void) universe_set_message(n);
695 
696 	(void) free(s);
697 }
698 
star_preview(struct star * sa,unsigned int h,int x,int y)699 void star_preview(struct star *sa, unsigned int h, int x, int y) {
700 	if(star_preview_create(sa, sa->sd.p_w, sa->sd.p_h, 1.5) != 0) return;
701 
702 	sa->sd.cp.sx = 0;
703 	sa->sd.cp.sy = 0;
704 	sa->sd.cp.dx = x;
705 	sa->sd.cp.dy = y;
706 	sa->sd.cp.c.width = (unsigned int) sa->sd.p_w;
707 	sa->sd.cp.c.height = (unsigned int) sa->sd.p_h;
708 	sa->sd.cp.s.width = (unsigned int) sa->sd.p_w;
709 	sa->sd.cp.s.height = (unsigned int) sa->sd.p_h;
710 	sa->sd.cp.p = sa->sd.p_p;
711 
712 	(void) gui_draw_copy_alpha(h, &sa->sd.cp);
713 }
714 
star_preview_create(struct star * sa,int w,int h,double u)715 static int star_preview_create(struct star *sa, int w, int h, double u) {
716 	double d;
717 
718 	struct position g;
719 	struct pixel_rgb_8 s;
720 	struct pixel_rgba_8 a;
721 
722 	if(sa->sd.p_p != NULL) return(0);
723 	if(star_preview_create_op(sa, w, h) != 0) return(-1);
724 
725 	/* Calculate percentage difference of equatorial and polar radius */
726 	d = fabs(sa->ss.radius_e - sa->ss.radius_p);
727 	d /= fabs(sa->ss.radius_e + sa->ss.radius_p) / 2.0;
728 	d *= 100.0;
729 
730 	if((sa->sd.ca = draw_sphere_matte_noise_2d_cache(w, h, u, 100.0, 100.0 - d, sa->sd.c, 0.15)) == 0) {
731 		(void) star_preview_free(sa);
732 
733 		return(-1);
734 	}
735 
736 	g.x = STAR_DRAW_LIGHT_X;
737 	g.y = STAR_DRAW_LIGHT_Y;
738 	g.z = STAR_DRAW_LIGHT_Z;
739 
740 	a.pixel.p = sa->ss.rgb.pixel.p;
741 
742 	switch(sa->type) {
743 		case STAR_TYPE_BLACKHOLE:
744 			s.r = STAR_DRAW_LIGHT_BLACKHOLE_RED;
745 			s.g = STAR_DRAW_LIGHT_BLACKHOLE_GREEN;
746 			s.b = STAR_DRAW_LIGHT_BLACKHOLE_BLUE;
747 
748 			break;
749 		case STAR_TYPE_NEUTRON:
750 			s.r = STAR_DRAW_LIGHT_NEUTRON_RED;
751 			s.g = STAR_DRAW_LIGHT_NEUTRON_GREEN;
752 			s.b = STAR_DRAW_LIGHT_NEUTRON_BLUE;
753 
754 			break;
755 		default:
756 			s.r = STAR_DRAW_LIGHT_DEFAULT_RED;
757 			s.g = STAR_DRAW_LIGHT_DEFAULT_GREEN;
758 			s.b = STAR_DRAW_LIGHT_DEFAULT_BLUE;
759 
760 			break;
761 	}
762 
763 	(void) draw_sphere_blur(sa->sd.p_p, &a, &s, &g, 0.5, 2.0, sa->sd.ca);
764 
765 	return(0);
766 }
767 
star_preview_create_op(struct star * sa,int w,int h)768 static int star_preview_create_op(struct star *sa, int w, int h) {
769 	sa->sd.p_t = (w * h) * sizeof(struct pixel_rgba_8);
770 
771 	if((sa->sd.p_p = malloc(sa->sd.p_t)) == NULL) {
772 		LOGWARN(
773 			ERROR_SLIGHT, SUBSYSTEM,
774 			_("Failed to allocate %lu bytes of memory"),
775 			(unsigned long) sa->sd.p_t
776 		);
777 
778 		return(-1);
779 	}
780 
781 	(void) memset((void *) sa->sd.p_p, 0, sa->sd.p_t);
782 
783 	return(0);
784 }
785 
star_preview_free(struct star * sa)786 void star_preview_free(struct star *sa) {
787 	if(sa->sd.p_p != NULL) {
788 		(void) free(sa->sd.p_p);
789 
790 		sa->sd.p_t = 0;
791 		sa->sd.p_p = NULL;
792 	}
793 
794 	if(sa->sd.ca != 0) {
795 		(void) draw_sphere_cache_delete(sa->sd.ca);
796 
797 		sa->sd.ca = 0;
798 	}
799 }
800 
star_run(struct star * sa)801 void star_run(struct star *sa) {
802 	unsigned long i;
803 	double d;
804 
805 	struct planet *p;
806 
807 	/* Calculate position for orbiting planets */
808 	for(i = 0; i < sa->planets; i++) {
809 		p = sa->pa[i];
810 		d = CONST_PI_2 * p->distance;
811 
812 		/* One iteration to position is one second as speed is orbital velocity in km/s */
813 		p->position += p->ps.speed * clock_get_multiplier();
814 
815 		if(p->position > d) p->position -= d;
816 
817 		p->angle = maths_map(p->position, 0.0, d, 0.0, 360.0);
818 	}
819 
820 	/* Simulate nuclear fusion */
821 	(void) star_run_burn(sa);
822 }
823 
star_run_burn(struct star * sa)824 static void star_run_burn(struct star *sa) {
825 	double d, e;
826 
827 	char n[CONFIG_LINE_LENGTH];
828 
829 	if(sa->type == STAR_TYPE_NEUTRON || sa->type == STAR_TYPE_BLACKHOLE) return;
830 
831 	e = clock_get_ticks();
832 
833 	/* Simulate nuclear fusion only once per stretching year */
834 	if(e - sa->fusion < CONST_SECS_YEAR) return;
835 
836 	sa->fusion = e;
837 
838 	/* Once the core is completely helium, star is gone for good */
839 	if(sa->sc.hydrogen > 0.0) {
840 		d = sa->sc.hydrogen / sa->ss.lifetime;
841 
842 		sa->sc.hydrogen -= d;
843 		sa->sc.helium += d;
844 	}
845 
846 	d = 0.000001;
847 
848 	/* If nuclear fusion has ended, convert star to neutron star or black hole */
849 	if((sa->ss.lifetime -= d) < d) {
850 		sa->planets = 0;
851 		sa->solarsize = 0.0;
852 
853 		(void) star_preview_free(sa);
854 
855 		/* Mass is calculated what core weights (10%), hence 0.1 */
856 		if(sa->ss.mass * 0.1 < STAR_SUN_MASS_KG * 3.0) {
857 			(void) snprintf(
858 				n, sizeof(n),
859 				"%s %s collapsed to neutron star%c%c%c%c",
860 				star_type[sa->type], sa->name, 0, 0, 0, 0);
861 
862 			(void) star_create_comp_neutron(sa);
863 			(void) star_create_spec_neutron(sa);
864 		}
865 		else {
866 			(void) snprintf(
867 				n, sizeof(n),
868 				"%s %s collapsed to black hole%c%c%c%c",
869 				star_type[sa->type], sa->name, 0, 0, 0, 0);
870 
871 			(void) star_create_comp_blackhole(sa);
872 			(void) star_create_spec_blackhole(sa);
873 		}
874 
875 		(void) universe_set_message(n);
876 	}
877 }
878 
star_live(unsigned long a,unsigned long b,double u,double v,double s,unsigned int h)879 void star_live(unsigned long a, unsigned long b, double u, double v, double s, unsigned int h) {
880 	unsigned int x, y, w;
881 	unsigned long i;
882 	double e, z;
883 
884 	struct star *sa;
885 	struct planet *p;
886 
887 	struct position o;
888 
889 	if((sa = universe_get_star_by_id(a, b)) == NULL) return;
890 
891 	if(sa->planets == 0) {
892 		(void) star_live_title(sa, h);
893 		(void) star_preview(sa, h,
894 			(window_get_active_width(h) / 2) - (STAR_DRAW_PREVIEW_WIDTH / 2),
895 			(window_get_active_height(h) / 2) - (STAR_DRAW_PREVIEW_HEIGHT / 2));
896 
897 		return;
898 	}
899 
900 	if(star_live_op(sa) != 0) return;
901 
902 	x = window_get_active_width(h);
903 	y = window_get_active_height(h);
904 
905 	w = VALUE_MIN2(x, y) - 1;
906 
907 	x /= 2;
908 	y /= 2;
909 
910 	/* Set zoom factor */
911 	s = maths_clamp(s, 0.0, STAR_LIVE_ZOOM_STEPS - 0.1);
912 	z = sa->solarsize / STAR_LIVE_ZOOM_STEPS;
913 
914 	for(i = 0; i < sa->planets; i++) {
915 		p = sa->pa[i];
916 
917 		(void) coords_angle_distance_to_position(p->angle, p->distance, &o);
918 
919 		/* Apply zooming */
920 		e = sa->solarsize - (z * s);
921 
922 		sa->sd.cp_p[i].x = maths_map(o.x, 0.0, e, 0.0, (double) w) + x + u;
923 		sa->sd.cp_p[i].y = maths_map(o.y, 0.0, e, 0.0, (double) w) + y + v;
924 		sa->sd.cp_p[i].p.pixel.p = p->ps.rgb.pixel.p;
925 
926 		sa->sd.cc_p[i].x = sa->sd.cp_p[i].x;
927 		sa->sd.cc_p[i].y = sa->sd.cp_p[i].y;
928 		sa->sd.cc_p[i].n = 4;
929 		sa->sd.cc_p[i].r = 10;
930 		sa->sd.cc_p[i].f = 0.0;
931 		sa->sd.cc_p[i].d = 360.0;
932 		sa->sd.cc_p[i].p.pixel.p = p->ps.rgb.pixel.p;
933 	}
934 
935 	sa->sd.cc_s.c = (unsigned int) sa->planets;
936 	sa->sd.cc_s.p = sa->sd.cc_p;
937 
938 	sa->sd.cp_s.c = (unsigned int) sa->planets;
939 	sa->sd.cp_s.p = sa->sd.cp_p;
940 
941 	sa->sd.cl_p[0].x1 = x + u;
942 	sa->sd.cl_p[0].y1 = y + v - 10;
943 	sa->sd.cl_p[0].x2 = sa->sd.cl_p[0].x1;
944 	sa->sd.cl_p[0].y2 = sa->sd.cl_p[0].y1 + 20;
945 	sa->sd.cl_p[0].p.pixel.p = sa->ss.rgb.pixel.p;
946 	sa->sd.cl_p[1].x1 = x + u - 10;
947 	sa->sd.cl_p[1].y1 = y + v;
948 	sa->sd.cl_p[1].x2 = sa->sd.cl_p[1].x1 + 20;
949 	sa->sd.cl_p[1].y2 = sa->sd.cl_p[1].y1;
950 	sa->sd.cl_p[1].p.pixel.p = sa->sd.cl_p[0].p.pixel.p;
951 
952 	(void) star_preview(sa, h, 0, window_get_active_height(h) - STAR_DRAW_PREVIEW_HEIGHT);
953 
954 	(void) gui_draw_line_aa(h, &sa->sd.cl_p[0]);
955 	(void) gui_draw_line_aa(h, &sa->sd.cl_p[1]);
956 
957 	(void) gui_draw_circles_aa(h, &sa->sd.cc_s);
958 	(void) gui_draw_subpixels(h, &sa->sd.cp_s);
959 
960 	(void) star_live_title(sa, h);
961 }
962 
star_live_op(struct star * sa)963 static int star_live_op(struct star *sa) {
964 	size_t t;
965 
966 	if(sa->sd.cc_p == NULL) {
967 		t = sizeof(struct circle_2) * sa->planets;
968 
969 		if((sa->sd.cc_p = malloc(t)) == NULL) {
970 			LOGWARN(
971 				ERROR_SLIGHT, SUBSYSTEM,
972 				_("Failed to allocate %lu bytes of memory"),
973 				(unsigned long) t
974 			);
975 
976 			return(-1);
977 		}
978 
979 		(void) memset((void *) sa->sd.cc_p, 0, t);
980 	}
981 
982 	if(sa->sd.cp_p == NULL) {
983 		t = sizeof(struct subpoint_2) * sa->planets;
984 
985 		if((sa->sd.cp_p = malloc(t)) == NULL) {
986 			LOGWARN(
987 				ERROR_SLIGHT, SUBSYSTEM,
988 				_("Failed to allocate %lu bytes of memory"),
989 				(unsigned long) t
990 			);
991 
992 			return(-1);
993 		}
994 
995 		(void) memset((void *) sa->sd.cp_p, 0, t);
996 	}
997 
998 	return(0);
999 }
1000 
star_live_title(struct star * sa,unsigned int h)1001 static void star_live_title(struct star *sa, unsigned int h) {
1002 	char n[CONFIG_LINE_LENGTH];
1003 
1004 	struct pixel_rgb_8 p;
1005 
1006 	if(sa->sd.cp_f[0] == 0) {
1007 		if((sa->sd.cp_f[0] = fonts_open("share/detroit/fonts/NotoSans-Italic.ttf", 18, 0)) == 0) return;
1008 	}
1009 
1010 	(void) memset((void *) n, 0, sizeof(n));
1011 
1012 	if(sa->type == STAR_TYPE_NEUTRON || sa->type == STAR_TYPE_BLACKHOLE) {
1013 		(void) snprintf(
1014 			n, sizeof(n),
1015 			"%s %s, class %s%c%c%c%c",
1016 			star_type[sa->type], sa->name, star_class[sa->class], 0, 0, 0, 0
1017 		);
1018 	}
1019 	else {
1020 		if(sa->spectral[0] != ' ') {
1021 			(void) snprintf(
1022 				n, sizeof(n),
1023 				"%s %s, class %s, spectral class %c%c, %lu planets%c%c%c%c",
1024 				star_type[sa->type], sa->name, star_class[sa->class],
1025 				sa->spectral[0], sa->spectral[1], sa->planets, 0, 0, 0, 0
1026 			);
1027 		}
1028 	}
1029 
1030 	p.r = 255;
1031 	p.g = 215;
1032 	p.b = 105;
1033 
1034 	(void) fonts_render(sa->sd.cp_f[0], "UTF-8", n, str_len(n, STRING_ASCII), &p, 0);
1035 
1036 	sa->sd.cp_t[0].x = 10;
1037 	sa->sd.cp_t[0].y = 10;
1038 
1039 	sa->sd.cp_t[0].f = sa->sd.cp_f[0];
1040 
1041 	(void) gui_draw_text(h, &sa->sd.cp_t[0]);
1042 }
1043 
star_live_free(struct star * sa)1044 void star_live_free(struct star *sa) {
1045 	unsigned long i;
1046 
1047 	for(i = 0; i < sizeof(sa->sd.cp_f) / sizeof(sa->sd.cp_f[0]); i++) {
1048 		(void) fonts_close(sa->sd.cp_f[i]);
1049 	}
1050 
1051 	if(sa->sd.cc_p != NULL) {
1052 		(void) free(sa->sd.cc_p);
1053 
1054 		sa->sd.cc_p = NULL;
1055 	}
1056 
1057 	if(sa->sd.cp_p != NULL) {
1058 		(void) free(sa->sd.cp_p);
1059 
1060 		sa->sd.cp_p = NULL;
1061 	}
1062 }
1063 
star_live_closest(unsigned long a,unsigned long b,double u,double v)1064 unsigned long star_live_closest(unsigned long a, unsigned long b, double u, double v) {
1065 	unsigned long i, r;
1066 	double e, f;
1067 
1068 	struct star *sa;
1069 
1070 	struct position p, q;
1071 
1072 	if((sa = universe_get_star_by_id(a, b)) == NULL) return(0);
1073 
1074 	r = 0;
1075 	f = sa->solarsize * 2.0;
1076 
1077 	q.x = u;
1078 	q.y = v;
1079 
1080 	for(i = 0; i < (unsigned long) sa->sd.cp_s.c; i++) {
1081 		p.x = sa->sd.cp_p[i].x;
1082 		p.y = sa->sd.cp_p[i].y;
1083 
1084 		e = coords_difference_2d(&p, &q);
1085 
1086 		if(e < f) {
1087 			f = e;
1088 			r = i + 1;
1089 		}
1090 	}
1091 
1092 	return(r);
1093 }
1094 
star_get_name(unsigned long a,unsigned long b)1095 char *star_get_name(unsigned long a, unsigned long b) {
1096 	struct star *sa;
1097 
1098 	if((sa = universe_get_star_by_id(a, b)) == NULL) return(NULL);
1099 
1100 	return(sa->name);
1101 }
1102 
star_get_nick(unsigned long a,unsigned long b)1103 char *star_get_nick(unsigned long a, unsigned long b) {
1104 	struct star *sa;
1105 
1106 	if((sa = universe_get_star_by_id(a, b)) == NULL) return(NULL);
1107 
1108 	return(sa->nick);
1109 }
1110 
star_get_ordinary(struct star * sa)1111 int star_get_ordinary(struct star *sa) {
1112 	int r;
1113 
1114 	switch(sa->type) {
1115 		case STAR_TYPE_NEUTRON:
1116 		case STAR_TYPE_BLACKHOLE:
1117 			r = IS_NO;
1118 
1119 			break;
1120 		default:
1121 			r = IS_YES;
1122 
1123 			break;
1124 	}
1125 
1126 	return(r);
1127 }
1128 
star_print_catalog(struct star * sa)1129 int star_print_catalog(struct star *sa) {
1130 	int r;
1131 
1132 	char n;
1133 
1134 	r = catalog_entry_open();
1135 
1136 	r += catalog_entry_item_save((void *) &sa->id, sizeof(sa->id));
1137 	r += catalog_entry_item_save((void *) &sa->pd, sizeof(sa->pd));
1138 
1139 	r += catalog_entry_item_save((void *) &sa->planets, sizeof(sa->planets));
1140 	r += catalog_entry_item_save((void *) &sa->solarsize, sizeof(sa->solarsize));
1141 
1142 	r += catalog_entry_item_save((void *) &sa->class, sizeof(sa->class));
1143 	r += catalog_entry_item_save((void *) &sa->type, sizeof(sa->type));
1144 
1145 	r += catalog_entry_item_save((void *) &sa->spectral, sizeof(sa->spectral));
1146 
1147 	/* Star position and velocity */
1148 	r += catalog_entry_item_save((void *) &sa->sp.x, sizeof(sa->sp.x));
1149 	r += catalog_entry_item_save((void *) &sa->sp.y, sizeof(sa->sp.y));
1150 	r += catalog_entry_item_save((void *) &sa->sp.z, sizeof(sa->sp.z));
1151 
1152 	r += catalog_entry_item_save((void *) &sa->sv.x, sizeof(sa->sv.x));
1153 	r += catalog_entry_item_save((void *) &sa->sv.y, sizeof(sa->sv.y));
1154 	r += catalog_entry_item_save((void *) &sa->sv.z, sizeof(sa->sv.z));
1155 
1156 	/* Star composition */
1157 	r += catalog_entry_item_save((void *) &sa->sc.carbon, sizeof(sa->sc.carbon));
1158 	r += catalog_entry_item_save((void *) &sa->sc.helium, sizeof(sa->sc.helium));
1159 	r += catalog_entry_item_save((void *) &sa->sc.hydrogen, sizeof(sa->sc.hydrogen));
1160 	r += catalog_entry_item_save((void *) &sa->sc.iron, sizeof(sa->sc.iron));
1161 	r += catalog_entry_item_save((void *) &sa->sc.magnesium, sizeof(sa->sc.magnesium));
1162 	r += catalog_entry_item_save((void *) &sa->sc.neon, sizeof(sa->sc.neon));
1163 	r += catalog_entry_item_save((void *) &sa->sc.nitrogen, sizeof(sa->sc.nitrogen));
1164 	r += catalog_entry_item_save((void *) &sa->sc.oxygen, sizeof(sa->sc.oxygen));
1165 	r += catalog_entry_item_save((void *) &sa->sc.silicon, sizeof(sa->sc.silicon));
1166 	r += catalog_entry_item_save((void *) &sa->sc.sulfur, sizeof(sa->sc.sulfur));
1167 
1168 	/* Star specs */
1169 	r += catalog_entry_item_save((void *) &sa->ss.bm, sizeof(sa->ss.bm));
1170 	r += catalog_entry_item_save((void *) &sa->ss.vm, sizeof(sa->ss.vm));
1171 	r += catalog_entry_item_save((void *) &sa->ss.jm, sizeof(sa->ss.jm));
1172 	r += catalog_entry_item_save((void *) &sa->ss.bv, sizeof(sa->ss.bv));
1173 
1174 	r += catalog_entry_item_save((void *) &sa->ss.parallax, sizeof(sa->ss.parallax));
1175 
1176 	r += catalog_entry_item_save((void *) &sa->ss.radius, sizeof(sa->ss.radius));
1177 	r += catalog_entry_item_save((void *) &sa->ss.radius_e, sizeof(sa->ss.radius_e));
1178 	r += catalog_entry_item_save((void *) &sa->ss.radius_p, sizeof(sa->ss.radius_p));
1179 	r += catalog_entry_item_save((void *) &sa->ss.magnitude, sizeof(sa->ss.magnitude));
1180 	r += catalog_entry_item_save((void *) &sa->ss.temperature, sizeof(sa->ss.temperature));
1181 	r += catalog_entry_item_save((void *) &sa->ss.luminance, sizeof(sa->ss.luminance));
1182 
1183 	r += catalog_entry_item_save((void *) &sa->ss.mass, sizeof(sa->ss.mass));
1184 	r += catalog_entry_item_save((void *) &sa->ss.area, sizeof(sa->ss.area));
1185 	r += catalog_entry_item_save((void *) &sa->ss.volume, sizeof(sa->ss.volume));
1186 	r += catalog_entry_item_save((void *) &sa->ss.energy, sizeof(sa->ss.energy));
1187 	r += catalog_entry_item_save((void *) &sa->ss.lifetime, sizeof(sa->ss.lifetime));
1188 
1189 	r += catalog_entry_item_save((void *) &sa->ss.rotation, sizeof(sa->ss.rotation));
1190 	r += catalog_entry_item_save((void *) &sa->ss.flattening, sizeof(sa->ss.flattening));
1191 
1192 	r += catalog_entry_item_save((void *) &sa->ss.centripetal, sizeof(sa->ss.centripetal));
1193 	r += catalog_entry_item_save((void *) &sa->ss.acceleration, sizeof(sa->ss.acceleration));
1194 	r += catalog_entry_item_save((void *) &sa->ss.velocity, sizeof(sa->ss.velocity));
1195 
1196 	r += catalog_entry_item_save((void *) &sa->ss.rgb, sizeof(sa->ss.rgb));
1197 
1198 	/* Star drawing variables */
1199 	r += catalog_entry_item_save((void *) &sa->sd.p_w, sizeof(sa->sd.p_w));
1200 	r += catalog_entry_item_save((void *) &sa->sd.p_h, sizeof(sa->sd.p_h));
1201 
1202 	r += catalog_entry_item_save((void *) &sa->sd.c, sizeof(sa->sd.c));
1203 
1204 	/* Star name */
1205 	n = 0;
1206 
1207 	if(sa->name != NULL) r += catalog_entry_item_save((void *) sa->name, sa->name_t + sizeof(char));
1208 	else r += catalog_entry_item_save((void *) &n, sizeof(n));
1209 
1210 	if(sa->nick != NULL) r += catalog_entry_item_save((void *) sa->nick, sa->nick_t + sizeof(char));
1211 	else r += catalog_entry_item_save((void *) &n, sizeof(n));
1212 
1213 	if(sa->solar != NULL) r += catalog_entry_item_save((void *) sa->solar, sa->solar_t + sizeof(char));
1214 	else r += catalog_entry_item_save((void *) &n, sizeof(n));
1215 
1216 	return(r);
1217 }
1218 
star_render(unsigned int h,unsigned long a,unsigned long b)1219 void star_render(unsigned int h, unsigned long a, unsigned long b) {
1220 	struct star *sa;
1221 
1222 	if((sa = universe_get_star_by_id(a, b)) == NULL) return;
1223 
1224 	(void) star_preview(sa, h, 0, 0);
1225 }
1226 
star_store(unsigned long a,unsigned long b,char * s)1227 void star_store(unsigned long a, unsigned long b, char *s) {
1228 	struct star *sa;
1229 
1230 	if((sa = universe_get_star_by_id(a, b)) == NULL) return;
1231 
1232 	(void) star_image(sa, s, IMAGE_FORMAT_TGA);
1233 }
1234 
star_print(unsigned long a,unsigned long b)1235 void star_print(unsigned long a, unsigned long b) {
1236 	struct star *sa;
1237 
1238 	if((sa = universe_get_star_by_id(a, b)) == NULL) return;
1239 
1240 	(void) star_print_human(sa);
1241 }
1242 
star_print_human(struct star * sa)1243 void star_print_human(struct star *sa) {
1244 	(void) fprintf(stdout, _("* %s %s, class %s"), star_type[sa->type], sa->name, star_class[sa->class]);
1245 
1246 	if(sa->type != STAR_TYPE_NEUTRON && sa->type != STAR_TYPE_BLACKHOLE) {
1247 		if(sa->spectral[0] != ' ') (void) fprintf(stdout, _(", spectral class %c%c"), sa->spectral[0], sa->spectral[1]);
1248 	}
1249 
1250 	if(sa->planets != 0) {
1251 		(void) fprintf(stdout, _(", %s with %lu planets"), sa->solar, sa->planets);
1252 	}
1253 
1254 	(void) fprintf(stdout, "%c%c", CONFIG_LINE_FEED, CONFIG_LINE_FEED);
1255 
1256 	(void) fprintf(stdout, _(" absolute magnitude......... %g%c"), sa->ss.magnitude, CONFIG_LINE_FEED);
1257 	(void) fprintf(stdout, _(" luminance.................. %g watts%c"), sa->ss.luminance, CONFIG_LINE_FEED);
1258 	(void) fprintf(stdout, _(" temperature................ %g kelvin%c"), sa->ss.temperature, CONFIG_LINE_FEED);
1259 	(void) fprintf(stdout, _("                             %g celsius%c"), maths_kelvin_to_celsius(sa->ss.temperature), CONFIG_LINE_FEED);
1260 	(void) fprintf(stdout, _("                             %g fahrenheit%c"), maths_kelvin_to_fahrenheit(sa->ss.temperature), CONFIG_LINE_FEED);
1261 	(void) fprintf(stdout, "%c", CONFIG_LINE_FEED);
1262 
1263 	(void) fprintf(stdout, _(" mean radius................ %g kilometers%c"), sa->ss.radius, CONFIG_LINE_FEED);
1264 	(void) fprintf(stdout, _(" equatorial radius.......... %g kilometers%c"), sa->ss.radius_e, CONFIG_LINE_FEED);
1265 	(void) fprintf(stdout, _(" polar radius............... %g kilometers%c"), sa->ss.radius_p, CONFIG_LINE_FEED);
1266 	(void) fprintf(stdout, _(" rotation velocity.......... %g meters per second%c"), sa->ss.rotation, CONFIG_LINE_FEED);
1267 	(void) fprintf(stdout, _(" flattening................. %g%c"), sa->ss.flattening, CONFIG_LINE_FEED);
1268 	(void) fprintf(stdout, "%c", CONFIG_LINE_FEED);
1269 
1270 	(void) fprintf(stdout, _(" mass....................... %g kilograms%c"), sa->ss.mass, CONFIG_LINE_FEED);
1271 	(void) fprintf(stdout, _(" area....................... %g square kilometers%c"), sa->ss.area, CONFIG_LINE_FEED);
1272 	(void) fprintf(stdout, _(" volume..................... %g cubic kilometers%c"), sa->ss.volume, CONFIG_LINE_FEED);
1273 	(void) fprintf(stdout, "%c", CONFIG_LINE_FEED);
1274 
1275 	(void) fprintf(stdout, _(" energy..................... %g joules%c"), sa->ss.energy, CONFIG_LINE_FEED);
1276 	(void) fprintf(stdout, _(" lifetime................... %g million years%c"), sa->ss.lifetime, CONFIG_LINE_FEED);
1277 	(void) fprintf(stdout, "%c", CONFIG_LINE_FEED);
1278 
1279 	(void) fprintf(stdout, _(" centripetal acceleration... %g meters per second%c"), sa->ss.centripetal, CONFIG_LINE_FEED);
1280 	(void) fprintf(stdout, _(" gravity acceleration....... %g meters per second%c"), sa->ss.acceleration, CONFIG_LINE_FEED);
1281 	(void) fprintf(stdout, _(" escape velocity............ %g kilometers per second%c"), sa->ss.velocity, CONFIG_LINE_FEED);
1282 	(void) fprintf(stdout, "%c", CONFIG_LINE_FEED);
1283 
1284 	if(sa->type != STAR_TYPE_BLACKHOLE) {
1285 		(void) fprintf(stdout, _(" color...................... %d/%d/%d/%d in RGBA (0-255)%c"), sa->ss.rgb.pixel.r, sa->ss.rgb.pixel.g, sa->ss.rgb.pixel.b, sa->ss.rgb.pixel.a, CONFIG_LINE_FEED);
1286 		(void) fprintf(stdout, "%c", CONFIG_LINE_FEED);
1287 	}
1288 
1289 	if(sa->type != STAR_TYPE_NEUTRON && sa->type != STAR_TYPE_BLACKHOLE) {
1290 		(void) fprintf(stdout, _(" chemical composition percentages%c"), CONFIG_LINE_FEED);
1291 		(void) fprintf(stdout, "%c", CONFIG_LINE_FEED);
1292 
1293 		(void) star_print_human_op(sa, _(ELEMENT_CARBON_ELEMENT_NAME), ELEMENT_CARBON_STANDARD_STATE, ELEMENT_CARBON_TEMP_MELTING, ELEMENT_CARBON_TEMP_BOILING, sa->sc.carbon);
1294 		(void) star_print_human_op(sa, _(ELEMENT_HELIUM_ELEMENT_NAME), ELEMENT_HELIUM_STANDARD_STATE, ELEMENT_HELIUM_TEMP_MELTING, ELEMENT_HELIUM_TEMP_BOILING, sa->sc.helium);
1295 		(void) star_print_human_op(sa, _(ELEMENT_HYDROGEN_ELEMENT_NAME), ELEMENT_HYDROGEN_STANDARD_STATE, ELEMENT_HYDROGEN_TEMP_MELTING, ELEMENT_HYDROGEN_TEMP_BOILING, sa->sc.hydrogen);
1296 		(void) star_print_human_op(sa, _(ELEMENT_IRON_ELEMENT_NAME), ELEMENT_IRON_STANDARD_STATE, ELEMENT_IRON_TEMP_MELTING, ELEMENT_IRON_TEMP_BOILING, sa->sc.iron);
1297 		(void) star_print_human_op(sa, _(ELEMENT_MAGNESIUM_ELEMENT_NAME), ELEMENT_MAGNESIUM_STANDARD_STATE, ELEMENT_MAGNESIUM_TEMP_MELTING, ELEMENT_MAGNESIUM_TEMP_BOILING, sa->sc.magnesium);
1298 		(void) star_print_human_op(sa, _(ELEMENT_NEON_ELEMENT_NAME), ELEMENT_NEON_STANDARD_STATE, ELEMENT_NEON_TEMP_MELTING, ELEMENT_NEON_TEMP_BOILING, sa->sc.neon);
1299 		(void) star_print_human_op(sa, _(ELEMENT_NITROGEN_ELEMENT_NAME), ELEMENT_NITROGEN_STANDARD_STATE, ELEMENT_NITROGEN_TEMP_MELTING, ELEMENT_NITROGEN_TEMP_BOILING, sa->sc.nitrogen);
1300 		(void) star_print_human_op(sa, _(ELEMENT_OXYGEN_ELEMENT_NAME), ELEMENT_OXYGEN_STANDARD_STATE, ELEMENT_OXYGEN_TEMP_MELTING, ELEMENT_OXYGEN_TEMP_BOILING, sa->sc.oxygen);
1301 		(void) star_print_human_op(sa, _(ELEMENT_SILICON_ELEMENT_NAME), ELEMENT_SILICON_STANDARD_STATE, ELEMENT_SILICON_TEMP_MELTING, ELEMENT_SILICON_TEMP_BOILING, sa->sc.silicon);
1302 		(void) star_print_human_op(sa, _(ELEMENT_SULFUR_ELEMENT_NAME), ELEMENT_SULFUR_STANDARD_STATE, ELEMENT_SULFUR_TEMP_MELTING, ELEMENT_SULFUR_TEMP_BOILING, sa->sc.sulfur);
1303 
1304 		(void) fprintf(stdout, "%c", CONFIG_LINE_FEED);
1305 	}
1306 }
1307 
star_print_human_op(struct star * a,char * s,int e,float m,float b,float c)1308 static void star_print_human_op(struct star *a, char *s, int e, float m, float b, float c) {
1309 	char *x, *y, *z;
1310 
1311 	size_t i, t;
1312 
1313 	char n[STAR_NAME_LEN_MAX];
1314 
1315 	switch(e) {
1316 		case ELEMENT_STATE_GAS:
1317 			x = _(ELEMENT_STATE_GAS_GAS);
1318 			y = _(ELEMENT_STATE_GAS_LIQUID);
1319 			z = _(ELEMENT_STATE_GAS_ICE);
1320 
1321 			break;
1322 		case ELEMENT_STATE_LIQUID:
1323 			x = _(ELEMENT_STATE_LIQUID_VAPOR);
1324 			y = _(ELEMENT_STATE_LIQUID_LIQUID);
1325 			z = _(ELEMENT_STATE_LIQUID_ICE);
1326 
1327 			break;
1328 		case ELEMENT_STATE_SOLID:
1329 			x = _(ELEMENT_STATE_SOLID_VAPOR);
1330 			y = _(ELEMENT_STATE_SOLID_MOLTEN);
1331 			z = _(ELEMENT_STATE_SOLID_SOLID);
1332 
1333 			break;
1334 		default:
1335 			x = "";
1336 			y = "";
1337 			z = "";
1338 
1339 			break;
1340 	}
1341 
1342 	if(a->ss.temperature >= b) {
1343 		(void) snprintf(n, sizeof(n), "%s, %s", s, x);
1344 	}
1345 	else if(a->ss.temperature >= m) {
1346 		(void) snprintf(n, sizeof(n), "%s, %s", s, y);
1347 	}
1348 	else {
1349 		(void) snprintf(n, sizeof(n), "%s, %s", s, z);
1350 	}
1351 
1352 	(void) fprintf(stdout, "  %s", n);
1353 
1354 	t = str_len(n, STRING_ASCII);
1355 
1356 	if(t < 26) {
1357 		for(i = 0; i < 26 - t; i++) (void) fprintf(stdout, ".");
1358 	}
1359 
1360 	(void) fprintf(stdout, " %f%c", c, CONFIG_LINE_FEED);
1361 }
1362