Mercurial > molko
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 |