From cbf9bb898558b5295244c62d857f91b9d848aae3 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 29 Sep 2014 20:38:01 +0200 Subject: [PATCH] fix qsort in wormhole code. pointers are hard. --- src/modules/wormhole.c | 245 +++++++++++++++++++++-------------------- 1 file changed, 123 insertions(+), 122 deletions(-) diff --git a/src/modules/wormhole.c b/src/modules/wormhole.c index 30184db43..abb2a7fde 100644 --- a/src/modules/wormhole.c +++ b/src/modules/wormhole.c @@ -8,7 +8,7 @@ This program may not be used, modified or distributed without prior permission by the authors of Eressea. -*/ + */ #include #include @@ -40,186 +40,187 @@ static bool good_region(const region * r) { - return (!fval(r, RF_CHAOTIC) && r->age > 30 && rplane(r) == NULL - && r->units != NULL && r->land != NULL); + return (!fval(r, RF_CHAOTIC) && r->age > 30 && rplane(r) == NULL + && r->units != NULL && r->land != NULL); } static int cmp_age(const void *v1, const void *v2) { - const region *r1 = (const region *)v1; - const region *r2 = (const region *)v2; - if (r1->age < r2->age) - return -1; - if (r1->age > r2->age) - return 1; - return 0; + const region **r1 = (const region **)v1; + const region **r2 = (const region **)v2; + if ((*r1)->age < (*r2)->age) + return -1; + if ((*r1)->age > (*r2)->age) + return 1; + return 0; } typedef struct wormhole_data { - building *entry; - region *exit; + building *entry; + region *exit; } wormhole_data; static void wormhole_init(struct attrib *a) { - a->data.v = calloc(1, sizeof(wormhole_data)); + a->data.v = calloc(1, sizeof(wormhole_data)); } static void wormhole_done(struct attrib *a) { - free(a->data.v); + free(a->data.v); } static int wormhole_age(struct attrib *a) { - wormhole_data *data = (wormhole_data *) a->data.v; - int maxtransport = data->entry->size; - region *r = data->entry->region; - unit *u = r->units; + wormhole_data *data = (wormhole_data *)a->data.v; + int maxtransport = data->entry->size; + region *r = data->entry->region; + unit *u = r->units; - for (; u != NULL && maxtransport != 0; u = u->next) { - if (u->building == data->entry) { - message *m = NULL; - if (u->number > maxtransport || has_limited_skills(u)) { - m = msg_message("wormhole_requirements", "unit region", u, u->region); - } else if (data->exit != NULL) { - move_unit(u, data->exit, NULL); - maxtransport -= u->number; - m = msg_message("wormhole_exit", "unit region", u, data->exit); - add_message(&data->exit->msgs, m); - } - if (m != NULL) { - add_message(&u->faction->msgs, m); - msg_release(m); - } + for (; u != NULL && maxtransport != 0; u = u->next) { + if (u->building == data->entry) { + message *m = NULL; + if (u->number > maxtransport || has_limited_skills(u)) { + m = msg_message("wormhole_requirements", "unit region", u, u->region); + } + else if (data->exit != NULL) { + move_unit(u, data->exit, NULL); + maxtransport -= u->number; + m = msg_message("wormhole_exit", "unit region", u, data->exit); + add_message(&data->exit->msgs, m); + } + if (m != NULL) { + add_message(&u->faction->msgs, m); + msg_release(m); + } + } } - } - remove_building(&r->buildings, data->entry); - ADDMSG(&r->msgs, msg_message("wormhole_dissolve", "region", r)); + remove_building(&r->buildings, data->entry); + ADDMSG(&r->msgs, msg_message("wormhole_dissolve", "region", r)); - /* age returns 0 if the attribute needs to be removed, !=0 otherwise */ - return AT_AGE_KEEP; + /* age returns 0 if the attribute needs to be removed, !=0 otherwise */ + return AT_AGE_KEEP; } static void wormhole_write(const struct attrib *a, const void *owner, struct storage *store) { - wormhole_data *data = (wormhole_data *) a->data.v; - write_building_reference(data->entry, store); - write_region_reference(data->exit, store); + wormhole_data *data = (wormhole_data *)a->data.v; + write_building_reference(data->entry, store); + write_region_reference(data->exit, store); } /** conversion code, turn 573, 2008-05-23 */ static int resolve_exit(variant id, void *address) { - building *b = findbuilding(id.i); - region **rp = address; - if (b) { - *rp = b->region; - return 0; - } - *rp = NULL; - return -1; + building *b = findbuilding(id.i); + region **rp = address; + if (b) { + *rp = b->region; + return 0; + } + *rp = NULL; + return -1; } static int wormhole_read(struct attrib *a, void *owner, struct storage *store) { - wormhole_data *data = (wormhole_data *) a->data.v; - resolve_fun resolver = (global.data_version < UIDHASH_VERSION) - ? resolve_exit : resolve_region_id; - read_fun reader = (global.data_version < UIDHASH_VERSION) - ? read_building_reference : read_region_reference; + wormhole_data *data = (wormhole_data *)a->data.v; + resolve_fun resolver = (global.data_version < UIDHASH_VERSION) + ? resolve_exit : resolve_region_id; + read_fun reader = (global.data_version < UIDHASH_VERSION) + ? read_building_reference : read_region_reference; - int rb = - read_reference(&data->entry, store, read_building_reference, - resolve_building); - int rr = read_reference(&data->exit, store, reader, resolver); - if (rb == 0 && rr == 0) { - if (!data->exit || !data->entry) { - return AT_READ_FAIL; + int rb = + read_reference(&data->entry, store, read_building_reference, + resolve_building); + int rr = read_reference(&data->exit, store, reader, resolver); + if (rb == 0 && rr == 0) { + if (!data->exit || !data->entry) { + return AT_READ_FAIL; + } } - } - return AT_READ_OK; + return AT_READ_OK; } static attrib_type at_wormhole = { - "wormhole", - wormhole_init, - wormhole_done, - wormhole_age, - wormhole_write, - wormhole_read, - ATF_UNIQUE + "wormhole", + wormhole_init, + wormhole_done, + wormhole_age, + wormhole_write, + wormhole_read, + ATF_UNIQUE }; static void make_wormhole(const building_type * bt_wormhole, region * r1, region * r2) { - building *b1 = new_building(bt_wormhole, r1, default_locale); - building *b2 = new_building(bt_wormhole, r2, default_locale); - attrib *a1 = a_add(&b1->attribs, a_new(&at_wormhole)); - attrib *a2 = a_add(&b2->attribs, a_new(&at_wormhole)); - wormhole_data *d1 = (wormhole_data *) a1->data.v; - wormhole_data *d2 = (wormhole_data *) a2->data.v; - d1->entry = b1; - d2->entry = b2; - d1->exit = b2->region; - d2->exit = b1->region; - b1->size = bt_wormhole->maxsize; - b2->size = bt_wormhole->maxsize; - ADDMSG(&r1->msgs, msg_message("wormhole_appear", "region", r1)); - ADDMSG(&r2->msgs, msg_message("wormhole_appear", "region", r2)); + building *b1 = new_building(bt_wormhole, r1, default_locale); + building *b2 = new_building(bt_wormhole, r2, default_locale); + attrib *a1 = a_add(&b1->attribs, a_new(&at_wormhole)); + attrib *a2 = a_add(&b2->attribs, a_new(&at_wormhole)); + wormhole_data *d1 = (wormhole_data *)a1->data.v; + wormhole_data *d2 = (wormhole_data *)a2->data.v; + d1->entry = b1; + d2->entry = b2; + d1->exit = b2->region; + d2->exit = b1->region; + b1->size = bt_wormhole->maxsize; + b2->size = bt_wormhole->maxsize; + ADDMSG(&r1->msgs, msg_message("wormhole_appear", "region", r1)); + ADDMSG(&r2->msgs, msg_message("wormhole_appear", "region", r2)); } void create_wormholes(void) { #define WORMHOLE_CHANCE 10000 - const building_type *bt_wormhole = bt_find("wormhole"); - quicklist *ql, *rlist = 0; - region *r = regions; - int qi, i = 0, count = 0; - region **match; + const building_type *bt_wormhole = bt_find("wormhole"); + quicklist *ql, *rlist = 0; + region *r = regions; + int qi, i = 0, count = 0; + region **match; - if (bt_wormhole == NULL) - return; - /* - * select a list of regions. we'll sort them by age later. - */ - while (r != NULL) { - int next = rng_int() % (2 * WORMHOLE_CHANCE); - while (r != NULL && (next != 0 || !good_region(r))) { - if (good_region(r)) { - --next; - } - r = r->next; + if (bt_wormhole == NULL) + return; + /* + * select a list of regions. we'll sort them by age later. + */ + while (r != NULL) { + int next = rng_int() % (2 * WORMHOLE_CHANCE); + while (r != NULL && (next != 0 || !good_region(r))) { + if (good_region(r)) { + --next; + } + r = r->next; + } + if (r == NULL) + break; + ql_push(&rlist, r); + ++count; + r = r->next; } - if (r == NULL) - break; - ql_push(&rlist, r); - ++count; - r = r->next; - } - if (count < 2) - return; + if (count < 2) + return; - match = (region **) malloc(sizeof(region *) * count); - - for (ql = rlist,qi = 0; i != count; ql_advance(&ql, &qi, 1)) { - match[i++] = (region *)ql_get(ql, qi); - } - qsort(match, count, sizeof(region *), cmp_age); - ql_free(rlist); + match = (region **)malloc(sizeof(region *) * count); - count /= 2; - for (i = 0; i != count; ++i) { - make_wormhole(bt_wormhole, match[i], match[i + count]); - } - free(match); + for (ql = rlist, qi = 0; i != count; ql_advance(&ql, &qi, 1)) { + match[i++] = (region *)ql_get(ql, qi); + } + qsort(match, count, sizeof(region *), cmp_age); + ql_free(rlist); + + count /= 2; + for (i = 0; i != count; ++i) { + make_wormhole(bt_wormhole, match[i], match[i + count]); + } + free(match); } void register_wormholes(void) { - at_register(&at_wormhole); + at_register(&at_wormhole); }