PageRenderTime 25ms CodeModel.GetById 12ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/element.c

https://bitbucket.org/shadwick/alchemy
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}