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