/element.c
C | 159 lines | 113 code | 30 blank | 16 comment | 18 complexity | fba9105d37f05e24e10126b4a431181b MD5 | raw file
1#include <stdlib.h>
2#include <stdio.h>
3#include <string.h>
4#include <assert.h>
5#include "element.h"
6
7
8/* ==================== Static Data ==================== */
9
10BuiltinElement builtin_elements[] = {
11 {"Aquasoothius", 1, ATTR_CONSTANT}, /* #1286 */
12 {"Falsium", 0, ATTR_CONSTANT}, /* #721 */
13 {"Periphius", 3.14159265, ATTR_CONSTANT}, /* #953 */
14 {"Aquaphidium", 1.61803399, ATTR_CONSTANT}, /* #1144 */
15 {"Eulerius", 2.71828182, ATTR_CONSTANT}, /* #846 */
16 {"Quantifius", 0, ATTR_PRODUCT}, /* #1065 */
17 {"Inquirium", 0, ATTR_PRODUCT}, /* #963 */
18 {"Elucidium", 0, ATTR_PRODUCT}, /* #929 */
19 {"Scribius", 0, ATTR_PRODUCT} /* #836 */
20};
21
22
23
24/* ==================== External Data ==================== */
25
26/* Allocate and return a new Element after initializing it.
27 * If it breaks naming conventions, NULL is returned instead.
28 */
29Element *element_create(const char *name) {
30 Element *element;
31 element = malloc(sizeof(Element));
32 if (!element_init(element, name)) {
33 free(element);
34 return NULL;
35 }
36 return element;
37}
38
39
40/* Initialize a given Element - naming it and computing its other properties.
41 * If it breaks naming conventions, 0 is returned; 1 otherwise.
42 */
43int element_init(Element *element, const char *name) {
44 unsigned int i;
45 assert(element);
46 assert(name && name[0] != '\0');
47
48 /* Copy name and compute substance number */
49 element->value = 0;
50 element->subnum = 0;
51 for (i = 0; i < NAME_MAX; i++) {
52 element->name[i] = name[i];
53 element->subnum += name[i];
54 }
55 element->name[i] = '\0';
56
57 /* Determine if dry/wet, if the name is valid, and aqueous */
58 i = strlen(element->name);
59 if (strcmp(element->name + i - 3, "ius") == 0)
60 element->dry = 1;
61 else if (strcmp(element->name + i - 3, "ium") == 0)
62 element->dry = 0;
63 else
64 return 0;
65 element->aqueous = strncmp(element->name, "Aqua", 4) == 0;
66 element->initialized = 0;
67 element->attributes = 0;
68 return 1;
69}
70
71
72void element_destroy(Element *element) {
73 assert(element);
74 free(element);
75}
76
77
78void element_set_value(Element *element, double value) {
79 assert(element);
80 element->value = value;
81 if (!element->initialized)
82 element->initialized = 1;
83}
84
85
86
87Reagents *reagents_create() {
88 Reagents *reagents;
89 reagents = malloc(sizeof(Reagents));
90 reagents_clear(reagents);
91 reagents_set_solvent(reagents, ALKAHEST, 0);
92 return reagents;
93}
94
95
96void reagents_destroy(Reagents *reagents) {
97 assert(reagents);
98 free(reagents->elements);
99 free(reagents->amounts);
100 free(reagents);
101}
102
103
104void reagents_add_element(Reagents *reagents, Element *element,
105 uint32_t amount) {
106 assert(reagents);
107 assert(reagents->count < MAX_REAGENTS);
108 reagents->elements[reagents->count] = element;
109 reagents->amounts[reagents->count] = amount;
110 reagents->count++;
111}
112
113
114void reagents_clear(Reagents *reagents) {
115 reagents->count = 0;
116 memset(reagents->elements, 0, sizeof(Element *) * MAX_REAGENTS);
117 memset(reagents->amounts, 0, sizeof(uint32_t) * MAX_REAGENTS);
118}
119
120
121void reagents_set_solvent(Reagents *reagents, Solvent solvent,
122 uint32_t amount) {
123 assert(reagents);
124 reagents->solvent = solvent;
125 reagents->solvent_amount = amount;
126}
127
128
129/* Return the amount of solvent that is needed to perform a reaction, given the
130 * list of elements, their respective amounts, and the desired solvent type.
131 */
132uint32_t reagents_needed_solvent(Reagents *reagents) {
133 unsigned int i, base, amount;
134 assert(reagents);
135 base = 1;
136 if (reagents->solvent == WATER)
137 base++;
138 for (i = 0, amount = 0; i < reagents->count; i++) {
139 if (reagents->elements[i]->dry)
140 amount += base * reagents->amounts[i];
141 else
142 amount += (base + 1) * reagents->amounts[i];
143 }
144 return amount;
145}
146
147
148/* Return 1 if the all elements in the list are aqeuous.
149 * If any are not, 0 is returned.
150 */
151int reagents_are_soluble(Reagents *reagents) {
152 unsigned int i;
153 assert(reagents);
154 for (i = 0; i < reagents->count; i++) {
155 if (reagents->elements[i]->aqueous == 0)
156 return 0;
157 }
158 return 1;
159}