comparison src/core/inventory.c @ 110:d3bc14c1e243

inventory: add sorting algorithms
author David Demelier <markand@malikania.fr>
date Thu, 02 Apr 2020 18:22:27 +0200
parents ebbf35d90088
children
comparison
equal deleted inserted replaced
109:22014be67057 110:d3bc14c1e243
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */ 17 */
18 18
19 #include <assert.h> 19 #include <assert.h>
20 #include <stddef.h> 20 #include <stddef.h>
21 #include <stdlib.h>
21 #include <string.h> 22 #include <string.h>
22 23
23 #include "inventory.h" 24 #include "inventory.h"
24 #include "item.h" 25 #include "item.h"
26
27 #define INVENTORY_TOTAL (INVENTORY_ROWS_MAX * INVENTORY_COLS_MAX)
25 28
26 static bool 29 static bool
27 can_be_used(struct inventory_slot *slot, const struct item *item) 30 can_be_used(struct inventory_slot *slot, const struct item *item)
28 { 31 {
29 assert(item); 32 assert(item);
96 } 99 }
97 100
98 return amount; 101 return amount;
99 } 102 }
100 103
104 static bool
105 merge(struct inventory_slot *slot, struct inventory_slot *other)
106 {
107 assert(slot);
108 assert(slot->item);
109 assert(other);
110
111 /* Not compatible, return false to let the sorting continue. */
112 if (slot->item != other->item)
113 return false;
114
115 while (slot->amount < slot->item->stackable && other->amount) {
116 slot->amount++;
117 other->amount--;
118 }
119
120 /* No more amount in the other slot, empty it. */
121 if (other->amount == 0U)
122 memset(other, 0, sizeof (*other));
123
124 return slot->amount >= slot->item->stackable;
125 }
126
127 static void
128 sort(struct inventory *iv, struct inventory_slot *slot, int r, int c)
129 {
130 assert(slot);
131 assert(slot->item);
132
133 /* Merge until the end of thiw row. */
134 for (c = c + 1; c < INVENTORY_COLS_MAX; ++c)
135 if (merge(slot, &iv->items[r][c]))
136 return;
137
138 /* Merge the next rows. */
139 for (r = r + 1; r < INVENTORY_ROWS_MAX; ++r)
140 for (c = 0; c < INVENTORY_COLS_MAX; ++c)
141 if (merge(slot, &iv->items[r][c]))
142 return;
143 }
144
101 unsigned int 145 unsigned int
102 inventory_push(struct inventory *iv, struct item *item, unsigned int amount) 146 inventory_push(struct inventory *iv, struct item *item, unsigned int amount)
103 { 147 {
104 assert(iv); 148 assert(iv);
105 assert(item); 149 assert(item);
115 } 159 }
116 160
117 return amount; 161 return amount;
118 } 162 }
119 163
164 static int
165 compare_slot(const void *v1, const void *v2)
166 {
167 const struct inventory_slot *slot1 = v1;
168 const struct inventory_slot *slot2 = v2;
169 int cmp;
170
171 /* Two null slots compare equal. */
172 if (!slot1->item && !slot2->item)
173 return 0;
174
175 /* Null left should be moved after. */
176 if (!slot1->item)
177 return 1;
178
179 /* Null right slots should be moved after. */
180 if (!slot2->item)
181 return -1;
182
183 /* If they are identical, use amount to sort. */
184 if ((cmp = strcmp(slot1->item->name, slot2->item->name)) == 0)
185 return (long long int)slot2->amount - (long long int)slot1->amount;
186
187 return cmp;
188 }
189
190 void
191 inventory_sort(struct inventory *iv)
192 {
193 assert(iv);
194
195 for (int r = 0; r < INVENTORY_ROWS_MAX; ++r)
196 for (int c = 0; c < INVENTORY_COLS_MAX; ++c)
197 if (iv->items[r][c].item)
198 sort(iv, &iv->items[r][c], r, c);
199
200 /* Sort by names AND by amount. */
201 qsort(iv->items, INVENTORY_TOTAL, sizeof (struct inventory_slot), compare_slot);
202 }
203
120 void 204 void
121 inventory_clear(struct inventory *iv) 205 inventory_clear(struct inventory *iv)
122 { 206 {
123 assert(iv); 207 assert(iv);
124 208