forked from github/server
fix qsort in wormhole code. pointers are hard.
This commit is contained in:
parent
3e829e2880
commit
cbf9bb8985
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
This program may not be used, modified or distributed
|
This program may not be used, modified or distributed
|
||||||
without prior permission by the authors of Eressea.
|
without prior permission by the authors of Eressea.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
#include <kernel/config.h>
|
#include <kernel/config.h>
|
||||||
|
@ -40,186 +40,187 @@
|
||||||
|
|
||||||
static bool good_region(const region * r)
|
static bool good_region(const region * r)
|
||||||
{
|
{
|
||||||
return (!fval(r, RF_CHAOTIC) && r->age > 30 && rplane(r) == NULL
|
return (!fval(r, RF_CHAOTIC) && r->age > 30 && rplane(r) == NULL
|
||||||
&& r->units != NULL && r->land != NULL);
|
&& r->units != NULL && r->land != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cmp_age(const void *v1, const void *v2)
|
static int cmp_age(const void *v1, const void *v2)
|
||||||
{
|
{
|
||||||
const region *r1 = (const region *)v1;
|
const region **r1 = (const region **)v1;
|
||||||
const region *r2 = (const region *)v2;
|
const region **r2 = (const region **)v2;
|
||||||
if (r1->age < r2->age)
|
if ((*r1)->age < (*r2)->age)
|
||||||
return -1;
|
return -1;
|
||||||
if (r1->age > r2->age)
|
if ((*r1)->age > (*r2)->age)
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct wormhole_data {
|
typedef struct wormhole_data {
|
||||||
building *entry;
|
building *entry;
|
||||||
region *exit;
|
region *exit;
|
||||||
} wormhole_data;
|
} wormhole_data;
|
||||||
|
|
||||||
static void wormhole_init(struct attrib *a)
|
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)
|
static void wormhole_done(struct attrib *a)
|
||||||
{
|
{
|
||||||
free(a->data.v);
|
free(a->data.v);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wormhole_age(struct attrib *a)
|
static int wormhole_age(struct attrib *a)
|
||||||
{
|
{
|
||||||
wormhole_data *data = (wormhole_data *) a->data.v;
|
wormhole_data *data = (wormhole_data *)a->data.v;
|
||||||
int maxtransport = data->entry->size;
|
int maxtransport = data->entry->size;
|
||||||
region *r = data->entry->region;
|
region *r = data->entry->region;
|
||||||
unit *u = r->units;
|
unit *u = r->units;
|
||||||
|
|
||||||
for (; u != NULL && maxtransport != 0; u = u->next) {
|
for (; u != NULL && maxtransport != 0; u = u->next) {
|
||||||
if (u->building == data->entry) {
|
if (u->building == data->entry) {
|
||||||
message *m = NULL;
|
message *m = NULL;
|
||||||
if (u->number > maxtransport || has_limited_skills(u)) {
|
if (u->number > maxtransport || has_limited_skills(u)) {
|
||||||
m = msg_message("wormhole_requirements", "unit region", u, u->region);
|
m = msg_message("wormhole_requirements", "unit region", u, u->region);
|
||||||
} else if (data->exit != NULL) {
|
}
|
||||||
move_unit(u, data->exit, NULL);
|
else if (data->exit != NULL) {
|
||||||
maxtransport -= u->number;
|
move_unit(u, data->exit, NULL);
|
||||||
m = msg_message("wormhole_exit", "unit region", u, data->exit);
|
maxtransport -= u->number;
|
||||||
add_message(&data->exit->msgs, m);
|
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);
|
if (m != NULL) {
|
||||||
msg_release(m);
|
add_message(&u->faction->msgs, m);
|
||||||
}
|
msg_release(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
remove_building(&r->buildings, data->entry);
|
remove_building(&r->buildings, data->entry);
|
||||||
ADDMSG(&r->msgs, msg_message("wormhole_dissolve", "region", r));
|
ADDMSG(&r->msgs, msg_message("wormhole_dissolve", "region", r));
|
||||||
|
|
||||||
/* age returns 0 if the attribute needs to be removed, !=0 otherwise */
|
/* age returns 0 if the attribute needs to be removed, !=0 otherwise */
|
||||||
return AT_AGE_KEEP;
|
return AT_AGE_KEEP;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
wormhole_write(const struct attrib *a, const void *owner, struct storage *store)
|
wormhole_write(const struct attrib *a, const void *owner, struct storage *store)
|
||||||
{
|
{
|
||||||
wormhole_data *data = (wormhole_data *) a->data.v;
|
wormhole_data *data = (wormhole_data *)a->data.v;
|
||||||
write_building_reference(data->entry, store);
|
write_building_reference(data->entry, store);
|
||||||
write_region_reference(data->exit, store);
|
write_region_reference(data->exit, store);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** conversion code, turn 573, 2008-05-23 */
|
/** conversion code, turn 573, 2008-05-23 */
|
||||||
static int resolve_exit(variant id, void *address)
|
static int resolve_exit(variant id, void *address)
|
||||||
{
|
{
|
||||||
building *b = findbuilding(id.i);
|
building *b = findbuilding(id.i);
|
||||||
region **rp = address;
|
region **rp = address;
|
||||||
if (b) {
|
if (b) {
|
||||||
*rp = b->region;
|
*rp = b->region;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*rp = NULL;
|
*rp = NULL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wormhole_read(struct attrib *a, void *owner, struct storage *store)
|
static int wormhole_read(struct attrib *a, void *owner, struct storage *store)
|
||||||
{
|
{
|
||||||
wormhole_data *data = (wormhole_data *) a->data.v;
|
wormhole_data *data = (wormhole_data *)a->data.v;
|
||||||
resolve_fun resolver = (global.data_version < UIDHASH_VERSION)
|
resolve_fun resolver = (global.data_version < UIDHASH_VERSION)
|
||||||
? resolve_exit : resolve_region_id;
|
? resolve_exit : resolve_region_id;
|
||||||
read_fun reader = (global.data_version < UIDHASH_VERSION)
|
read_fun reader = (global.data_version < UIDHASH_VERSION)
|
||||||
? read_building_reference : read_region_reference;
|
? read_building_reference : read_region_reference;
|
||||||
|
|
||||||
int rb =
|
int rb =
|
||||||
read_reference(&data->entry, store, read_building_reference,
|
read_reference(&data->entry, store, read_building_reference,
|
||||||
resolve_building);
|
resolve_building);
|
||||||
int rr = read_reference(&data->exit, store, reader, resolver);
|
int rr = read_reference(&data->exit, store, reader, resolver);
|
||||||
if (rb == 0 && rr == 0) {
|
if (rb == 0 && rr == 0) {
|
||||||
if (!data->exit || !data->entry) {
|
if (!data->exit || !data->entry) {
|
||||||
return AT_READ_FAIL;
|
return AT_READ_FAIL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
return AT_READ_OK;
|
||||||
return AT_READ_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static attrib_type at_wormhole = {
|
static attrib_type at_wormhole = {
|
||||||
"wormhole",
|
"wormhole",
|
||||||
wormhole_init,
|
wormhole_init,
|
||||||
wormhole_done,
|
wormhole_done,
|
||||||
wormhole_age,
|
wormhole_age,
|
||||||
wormhole_write,
|
wormhole_write,
|
||||||
wormhole_read,
|
wormhole_read,
|
||||||
ATF_UNIQUE
|
ATF_UNIQUE
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
make_wormhole(const building_type * bt_wormhole, region * r1, region * r2)
|
make_wormhole(const building_type * bt_wormhole, region * r1, region * r2)
|
||||||
{
|
{
|
||||||
building *b1 = new_building(bt_wormhole, r1, default_locale);
|
building *b1 = new_building(bt_wormhole, r1, default_locale);
|
||||||
building *b2 = new_building(bt_wormhole, r2, default_locale);
|
building *b2 = new_building(bt_wormhole, r2, default_locale);
|
||||||
attrib *a1 = a_add(&b1->attribs, a_new(&at_wormhole));
|
attrib *a1 = a_add(&b1->attribs, a_new(&at_wormhole));
|
||||||
attrib *a2 = a_add(&b2->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 *d1 = (wormhole_data *)a1->data.v;
|
||||||
wormhole_data *d2 = (wormhole_data *) a2->data.v;
|
wormhole_data *d2 = (wormhole_data *)a2->data.v;
|
||||||
d1->entry = b1;
|
d1->entry = b1;
|
||||||
d2->entry = b2;
|
d2->entry = b2;
|
||||||
d1->exit = b2->region;
|
d1->exit = b2->region;
|
||||||
d2->exit = b1->region;
|
d2->exit = b1->region;
|
||||||
b1->size = bt_wormhole->maxsize;
|
b1->size = bt_wormhole->maxsize;
|
||||||
b2->size = bt_wormhole->maxsize;
|
b2->size = bt_wormhole->maxsize;
|
||||||
ADDMSG(&r1->msgs, msg_message("wormhole_appear", "region", r1));
|
ADDMSG(&r1->msgs, msg_message("wormhole_appear", "region", r1));
|
||||||
ADDMSG(&r2->msgs, msg_message("wormhole_appear", "region", r2));
|
ADDMSG(&r2->msgs, msg_message("wormhole_appear", "region", r2));
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_wormholes(void)
|
void create_wormholes(void)
|
||||||
{
|
{
|
||||||
#define WORMHOLE_CHANCE 10000
|
#define WORMHOLE_CHANCE 10000
|
||||||
const building_type *bt_wormhole = bt_find("wormhole");
|
const building_type *bt_wormhole = bt_find("wormhole");
|
||||||
quicklist *ql, *rlist = 0;
|
quicklist *ql, *rlist = 0;
|
||||||
region *r = regions;
|
region *r = regions;
|
||||||
int qi, i = 0, count = 0;
|
int qi, i = 0, count = 0;
|
||||||
region **match;
|
region **match;
|
||||||
|
|
||||||
if (bt_wormhole == NULL)
|
if (bt_wormhole == NULL)
|
||||||
return;
|
return;
|
||||||
/*
|
/*
|
||||||
* select a list of regions. we'll sort them by age later.
|
* select a list of regions. we'll sort them by age later.
|
||||||
*/
|
*/
|
||||||
while (r != NULL) {
|
while (r != NULL) {
|
||||||
int next = rng_int() % (2 * WORMHOLE_CHANCE);
|
int next = rng_int() % (2 * WORMHOLE_CHANCE);
|
||||||
while (r != NULL && (next != 0 || !good_region(r))) {
|
while (r != NULL && (next != 0 || !good_region(r))) {
|
||||||
if (good_region(r)) {
|
if (good_region(r)) {
|
||||||
--next;
|
--next;
|
||||||
}
|
}
|
||||||
r = 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)
|
if (count < 2)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
match = (region **) malloc(sizeof(region *) * count);
|
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);
|
|
||||||
|
|
||||||
count /= 2;
|
for (ql = rlist, qi = 0; i != count; ql_advance(&ql, &qi, 1)) {
|
||||||
for (i = 0; i != count; ++i) {
|
match[i++] = (region *)ql_get(ql, qi);
|
||||||
make_wormhole(bt_wormhole, match[i], match[i + count]);
|
}
|
||||||
}
|
qsort(match, count, sizeof(region *), cmp_age);
|
||||||
free(match);
|
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)
|
void register_wormholes(void)
|
||||||
{
|
{
|
||||||
at_register(&at_wormhole);
|
at_register(&at_wormhole);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue