1#include "ap_req.h" 2#include "bm.h" 3 4const char * const ap_requirement_names[] = { 5#define X(i, n) [CONCAT(REQUIREMENT_, n)] = STRINGIFY(n), 6REQUIREMENT_LIST 7#undef X 8 NULL, 9}; 10 11static struct ap_reqmask current_reqmask = {0}; 12 13static void reqmask_set(struct ap_reqmask * mask, enum ap_requirement req) { 14 assert(req < _REQUIREMENT_MAX); 15 BM_SET(mask->bits, req); 16} 17 18static bool reqmask_match(const struct ap_reqmask * src) { 19 if (BM_ISEMPTY(src->bits)) return false; 20 return BM_ISMATCH(src->bits, current_reqmask.bits); 21} 22 23static void reqmask_print(const struct ap_reqmask * mask, char **buf_p) { 24 char * buf = *buf_p; 25 if (BM_ISEMPTY(mask->bits)) { 26 buf += sprintf(buf, "None"); 27 } else { 28 bool first = true; 29 for (int i = 0; i < _REQUIREMENT_MAX; i++) { 30 if (BM_ISSET(mask->bits, i)) { 31 if (first) { 32 first = false; 33 } else { 34 *buf++ = '&'; 35 } 36 buf += sprintf(buf, "%s", ap_requirement_names[i]); 37 } 38 } 39 } 40 *buf_p = buf; 41} 42 43void ap_req_update() { 44 memset(¤t_reqmask, 0, sizeof(current_reqmask)); 45#define X(i, n) \ 46 if (i != 0 && ap_ram.inventory_base[i] != 0) { \ 47 reqmask_set(¤t_reqmask, CONCAT(REQUIREMENT_, n)); \ 48 } 49 REQUIREMENT_LIST 50#undef X 51 if (*ap_ram.inventory_sword > 1) { 52 reqmask_set(¤t_reqmask, REQUIREMENT_MASTER_SWORD); 53 } 54 if (*ap_ram.dungeon_current_keys> 0) { 55 // XXX how to handle this across dungeons 56 reqmask_set(¤t_reqmask, REQUIREMENT_KEY); 57 } 58 if (*ap_ram.sram_pendants & 0x01) { 59 reqmask_set(¤t_reqmask, REQUIREMENT_GREEN_PENDANT); 60 } 61 if ((*ap_ram.sram_pendants & 0x07) == 0x07) { 62 reqmask_set(¤t_reqmask, REQUIREMENT_ALL_PENDANTS); 63 } 64 if ((*ap_ram.sram_crystals & 0x05) == 0x05) { 65 reqmask_set(¤t_reqmask, REQUIREMENT_FIVESIX_CRYSTALS); 66 } 67 if ((*ap_ram.sram_crystals & 0x7F) == 0x7F) { 68 reqmask_set(¤t_reqmask, REQUIREMENT_ALL_CRYSTALS); 69 } 70 if (*ap_ram.inventory_gloves >= 1) { 71 reqmask_set(¤t_reqmask, REQUIREMENT_GLOVES_1); 72 } 73 if (*ap_ram.inventory_gloves >= 2) { 74 reqmask_set(¤t_reqmask, REQUIREMENT_GLOVES_2); 75 } 76} 77 78void ap_req_init(struct ap_req * req) { 79 memset(req, 0x00, sizeof(*req)); 80} 81 82void ap_req_require(struct ap_req * req, size_t slot, uint16_t requirement) { 83 assert(slot < AP_REQ_SLOTS); 84 assert(requirement < (uint16_t) _REQUIREMENT_MAX); 85 reqmask_set(&req->alternative_requirements[slot], requirement); 86} 87 88bool ap_req_is_satisfied(const struct ap_req * req) { 89 bool all_zero = true; 90 for (size_t i = 0; i < AP_REQ_SLOTS; i++) { 91 if (reqmask_match(&req->alternative_requirements[i])) { 92 return true; 93 } 94 if (!BM_ISEMPTY(req->alternative_requirements[i].bits)) { 95 all_zero = false; 96 } 97 } 98 return all_zero; 99} 100 101const char * ap_req_print(const struct ap_req * req) { 102 static char sbuf[4096]; 103 char *buf = sbuf; 104 if (req == NULL) { 105 reqmask_print(¤t_reqmask, &buf); 106 return sbuf; 107 } 108 109 *buf++ = '['; 110 bool first = true; 111 for (size_t i = 0; i < AP_REQ_SLOTS; i++) { 112 if (BM_ISEMPTY(req->alternative_requirements[i].bits)) { 113 continue; 114 } 115 if (first) { 116 first = false; 117 } else { 118 buf += sprintf(buf, " | "); 119 } 120 reqmask_print(&req->alternative_requirements[i], &buf); 121 } 122 if (first) { 123 buf += sprintf(buf, "Any"); 124 } 125 *buf++ = ']'; 126 *buf++ = '\0'; 127 return sbuf; 128}