From 138a4c10a0f04d0514d2ccdcac686a8ee7057cda Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 16 Aug 2014 13:46:34 +0200 Subject: [PATCH] properly create missing monster faction when spawning dragons. remove cached monster faction (static). Conflicts: src/kernel/faction.c --- src/kernel/faction.c | 709 ++++++++++++++++++++++--------------------- src/kernel/faction.h | 1 + src/monsters.c | 2 +- 3 files changed, 363 insertions(+), 349 deletions(-) diff --git a/src/kernel/faction.c b/src/kernel/faction.c index 9e61df9e3..f0cfc46bd 100755 --- a/src/kernel/faction.c +++ b/src/kernel/faction.c @@ -1,7 +1,7 @@ /* Copyright (c) 1998-2010, Enno Rehling - Katja Zedel +Katja Zedel Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -68,526 +68,539 @@ faction *factions; */ void free_faction(faction * f) { - if (f->msgs) - free_messagelist(f->msgs); - while (f->battles) { - struct bmsg *bm = f->battles; - f->battles = bm->next; - if (bm->msgs) - free_messagelist(bm->msgs); - free(bm); - } + if (f->msgs) + free_messagelist(f->msgs); + while (f->battles) { + struct bmsg *bm = f->battles; + f->battles = bm->next; + if (bm->msgs) + free_messagelist(bm->msgs); + free(bm); + } - while (f->groups) { - group *g = f->groups; - f->groups = g->next; - free_group(g); - } - freelist(f->allies); + while (f->groups) { + group *g = f->groups; + f->groups = g->next; + free_group(g); + } + freelist(f->allies); - free(f->email); - free(f->banner); - free(f->passw); - free(f->name); + free(f->email); + free(f->banner); + free(f->passw); + free(f->name); - while (f->attribs) { - a_remove(&f->attribs, f->attribs); - } + while (f->attribs) { + a_remove(&f->attribs, f->attribs); + } - i_freeall(&f->items); + i_freeall(&f->items); - freelist(f->ursprung); + freelist(f->ursprung); } void set_show_item(faction * f, const struct item_type *itype) { - attrib *a = a_add(&f->attribs, a_new(&at_showitem)); - a->data.v = (void *)itype; + attrib *a = a_add(&f->attribs, a_new(&at_showitem)); + a->data.v = (void *)itype; } -faction *get_monsters(void) -{ - static faction *monsters; - static int gamecookie = -1; - - if (gamecookie != global.cookie) { - monsters = NULL; - gamecookie = global.cookie; - } - - if (!monsters) { +faction *get_monsters(void) { faction *f; + for (f = factions; f; f = f->next) { - if ((f->flags & FFL_NPC) && !(f->flags & FFL_DEFENDER)) { - return monsters = f; - } + if ((f->flags & FFL_NPC) && !(f->flags & FFL_DEFENDER)) { + return f; + } } - if (!monsters) { - /* shit! */ - monsters = findfaction(666); + return 0; +} + +faction *get_or_create_monsters(void) +{ + faction *f = get_monsters(); + + if (!f) { + /* shit! */ + f = findfaction(666); } - if (monsters) { - fset(monsters, FFL_NPC | FFL_NOIDLEOUT); + if (!f) { + const race *rc = rc_find("dragon"); + + f = addfaction("noreply@eressea.de", NULL, rc, NULL, 0); + renumber_faction(f, 666); + faction_setname(f, "Monster"); + f->options = 0; } - } - return monsters; + if (f) { + fset(f, FFL_NPC | FFL_NOIDLEOUT); + } + return f; } const unit *random_unit_in_faction(const faction * f) { - unit *u; - int c = 0, u_nr; + unit *u; + int c = 0, u_nr; - for (u = f->units; u; u = u->next) - c++; + for (u = f->units; u; u = u->next) + c++; - u_nr = rng_int() % c; - c = 0; + u_nr = rng_int() % c; + c = 0; - for (u = f->units; u; u = u->next) - if (u_nr == c) - return u; + for (u = f->units; u; u = u->next) + if (u_nr == c) + return u; - /* Hier sollte er nie ankommen */ - return NULL; + /* Hier sollte er nie ankommen */ + return NULL; } const char *factionname(const faction * f) { - typedef char name[OBJECTIDSIZE + 1]; - static name idbuf[8]; - static int nextbuf = 0; + typedef char name[OBJECTIDSIZE + 1]; + static name idbuf[8]; + static int nextbuf = 0; - char *ibuf = idbuf[(++nextbuf) % 8]; + char *ibuf = idbuf[(++nextbuf) % 8]; - if (f && f->name) { - slprintf(ibuf, sizeof(name), "%s (%s)", f->name, itoa36(f->no)); - } else { - strcpy(ibuf, "Unbekannte Partei (?)"); - } - return ibuf; + if (f && f->name) { + slprintf(ibuf, sizeof(name), "%s (%s)", f->name, itoa36(f->no)); + } + else { + strcpy(ibuf, "Unbekannte Partei (?)"); + } + return ibuf; } int resolve_faction(variant id, void *address) { - int result = 0; - faction *f = NULL; - if (id.i != 0) { - f = findfaction(id.i); - if (f == NULL) { - result = -1; + int result = 0; + faction *f = NULL; + if (id.i != 0) { + f = findfaction(id.i); + if (f == NULL) { + result = -1; + } } - } - *(faction **) address = f; - return result; + *(faction **)address = f; + return result; } #define MAX_FACTION_ID (36*36*36*36) static int unused_faction_id(void) { - int id = rng_int() % MAX_FACTION_ID; + int id = rng_int() % MAX_FACTION_ID; - while (!faction_id_is_unused(id)) { - id++; - if (id == MAX_FACTION_ID) - id = 0; - } + while (!faction_id_is_unused(id)) { + id++; + if (id == MAX_FACTION_ID) + id = 0; + } - return id; + return id; } faction *addfaction(const char *email, const char *password, - const struct race * frace, const struct locale * loc, int subscription) + const struct race * frace, const struct locale * loc, int subscription) { - faction *f = calloc(sizeof(faction), 1); - char buf[128]; + faction *f = calloc(sizeof(faction), 1); + char buf[128]; - assert(frace); + assert(frace); + + if (set_email(&f->email, email) != 0) { + log_error("Invalid email address for faction %s: %s\n", itoa36(f->no), email); + } - if (set_email(&f->email, email) != 0) { - log_error("Invalid email address for faction %s: %s\n", itoa36(f->no), email); - } + faction_setpassword(f, password); - faction_setpassword(f, password); + f->alliance_joindate = turn; + f->lastorders = turn; + f->alive = 1; + f->age = 0; + f->race = frace; + f->magiegebiet = 0; + f->locale = loc; + f->subscription = subscription; - f->alliance_joindate = turn; - f->lastorders = turn; - f->alive = 1; - f->age = 0; - f->race = frace; - f->magiegebiet = 0; - f->locale = loc; - f->subscription = subscription; + f->options = + want(O_REPORT) | want(O_ZUGVORLAGE) | want(O_COMPUTER) | want(O_COMPRESS) | + want(O_ADRESSEN) | want(O_STATISTICS); - f->options = - want(O_REPORT) | want(O_ZUGVORLAGE) | want(O_COMPUTER) | want(O_COMPRESS) | - want(O_ADRESSEN) | want(O_STATISTICS); + f->no = unused_faction_id(); + if (rule_region_owners()) { + alliance *al = makealliance(f->no, NULL); + setalliance(f, al); + } + addlist(&factions, f); + fhash(f); - f->no = unused_faction_id(); - if (rule_region_owners()) { - alliance *al = makealliance(f->no, NULL); - setalliance(f, al); - } - addlist(&factions, f); - fhash(f); + slprintf(buf, sizeof(buf), "%s %s", LOC(loc, "factiondefault"), factionid(f)); + f->name = _strdup(buf); - slprintf(buf, sizeof(buf), "%s %s", LOC(loc, "factiondefault"), factionid(f)); - f->name = _strdup(buf); + if (!f->race) { + log_warning("creating a faction that has no race", factionid(f)); + } - return f; + return f; } unit *addplayer(region * r, faction * f) { - unit *u; - char buffer[32]; + unit *u; + char buffer[32]; - assert(f->units == NULL); - set_ursprung(f, 0, r->x, r->y); - u = createunit(r, f, 1, f->race); - equip_items(&u->faction->items, get_equipment("new_faction")); - equip_unit(u, get_equipment("first_unit")); - sprintf(buffer, "first_%s", u_race(u)->_name[0]); - equip_unit(u, get_equipment(buffer)); - u->hp = unit_max_hp(u) * u->number; - fset(u, UFL_ISNEW); - if (f->race == get_race(RC_DAEMON)) { - race_t urc; - race *rc; - do { - urc = (race_t) (rng_int() % MAXRACES); - rc = get_race(urc); - } while (rc == NULL || urc == RC_DAEMON || !playerrace(rc)); - u->irace = rc; - } + assert(f->units == NULL); + set_ursprung(f, 0, r->x, r->y); + u = createunit(r, f, 1, f->race); + equip_items(&u->faction->items, get_equipment("new_faction")); + equip_unit(u, get_equipment("first_unit")); + sprintf(buffer, "first_%s", u_race(u)->_name[0]); + equip_unit(u, get_equipment(buffer)); + u->hp = unit_max_hp(u) * u->number; + fset(u, UFL_ISNEW); + if (f->race == get_race(RC_DAEMON)) { + race_t urc; + race *rc; + do { + urc = (race_t)(rng_int() % MAXRACES); + rc = get_race(urc); + } while (rc == NULL || urc == RC_DAEMON || !playerrace(rc)); + u->irace = rc; + } - return u; + return u; } bool checkpasswd(const faction * f, const char *passwd, bool shortp) { - if (unicode_utf8_strcasecmp(f->passw, passwd) == 0) - return true; - return false; + if (unicode_utf8_strcasecmp(f->passw, passwd) == 0) + return true; + return false; } variant read_faction_reference(struct storage * store) { - variant id; - READ_INT(store, &id.i); - return id; + variant id; + READ_INT(store, &id.i); + return id; } void write_faction_reference(const faction * f, struct storage *store) { - WRITE_INT(store, f ? f->no : 0); + WRITE_INT(store, f ? f->no : 0); } void destroyfaction(faction * f) { - unit *u = f->units; - faction *ff; + unit *u = f->units; + faction *ff; - if (!f->alive) { - return; - } - fset(f, FFL_QUIT); - - if (f->spellbook) { - spellbook_clear(f->spellbook); - free(f->spellbook); - f->spellbook = 0; - } - while (f->battles) { - struct bmsg *bm = f->battles; - f->battles = bm->next; - if (bm->msgs) { - free_messagelist(bm->msgs); + if (!f->alive) { + return; } - free(bm); - } + fset(f, FFL_QUIT); - while (u) { - /* give away your stuff, make zombies if you cannot (quest items) */ - int result = gift_items(u, GIFT_FRIENDS | GIFT_PEASANTS); - if (result != 0) { - unit *zombie = u; - u = u->nextF; - make_zombie(zombie); - } else { - region *r = u->region; + if (f->spellbook) { + spellbook_clear(f->spellbook); + free(f->spellbook); + f->spellbook = 0; + } + while (f->battles) { + struct bmsg *bm = f->battles; + f->battles = bm->next; + if (bm->msgs) { + free_messagelist(bm->msgs); + } + free(bm); + } - if (!fval(r->terrain, SEA_REGION) && !!playerrace(u_race(u))) { - const race *rc = u_race(u); - int m = rmoney(r); + while (u) { + /* give away your stuff, make zombies if you cannot (quest items) */ + int result = gift_items(u, GIFT_FRIENDS | GIFT_PEASANTS); + if (result != 0) { + unit *zombie = u; + u = u->nextF; + make_zombie(zombie); + } + else { + region *r = u->region; - if ((rc->ec_flags & ECF_REC_ETHEREAL) == 0) { - int p = rpeasants(u->region); - int h = rhorses(u->region); - item *itm; + if (!fval(r->terrain, SEA_REGION) && !!playerrace(u_race(u))) { + const race *rc = u_race(u); + int m = rmoney(r); - /* Personen gehen nur an die Bauern, wenn sie auch von dort - * stammen */ - if (rc->ec_flags & ECF_REC_HORSES) { /* Zentauren an die Pferde */ - h += u->number; - } else { /* Orks zählen nur zur Hälfte */ - p += (int)(u->number * rc->recruit_multi); - } - for (itm = u->items; itm; itm = itm->next) { - if (itm->type->flags & ITF_ANIMAL) { - h += itm->number; + if ((rc->ec_flags & ECF_REC_ETHEREAL) == 0) { + int p = rpeasants(u->region); + int h = rhorses(u->region); + item *itm; + + /* Personen gehen nur an die Bauern, wenn sie auch von dort + * stammen */ + if (rc->ec_flags & ECF_REC_HORSES) { /* Zentauren an die Pferde */ + h += u->number; + } + else { /* Orks zählen nur zur Hälfte */ + p += (int)(u->number * rc->recruit_multi); + } + for (itm = u->items; itm; itm = itm->next) { + if (itm->type->flags & ITF_ANIMAL) { + h += itm->number; + } + } + rsetpeasants(r, p); + rsethorses(r, h); + } + m += get_money(u); + rsetmoney(r, m); } - } - rsetpeasants(r, p); - rsethorses(r, h); + set_number(u, 0); + u = u->nextF; } - m += get_money(u); - rsetmoney(r, m); - } - set_number(u, 0); - u = u->nextF; } - } - f->alive = 0; -/* no way! f->units = NULL; */ - handle_event(f->attribs, "destroy", f); - for (ff = factions; ff; ff = ff->next) { - group *g; - ally *sf, *sfn; + f->alive = 0; + /* no way! f->units = NULL; */ + handle_event(f->attribs, "destroy", f); + for (ff = factions; ff; ff = ff->next) { + group *g; + ally *sf, *sfn; - /* Alle HELFE für die Partei löschen */ - for (sf = ff->allies; sf; sf = sf->next) { - if (sf->faction == f) { - removelist(&ff->allies, sf); - break; - } - } - for (g = ff->groups; g; g = g->next) { - for (sf = g->allies; sf;) { - sfn = sf->next; - if (sf->faction == f) { - removelist(&g->allies, sf); - break; + /* Alle HELFE für die Partei löschen */ + for (sf = ff->allies; sf; sf = sf->next) { + if (sf->faction == f) { + removelist(&ff->allies, sf); + break; + } + } + for (g = ff->groups; g; g = g->next) { + for (sf = g->allies; sf;) { + sfn = sf->next; + if (sf->faction == f) { + removelist(&g->allies, sf); + break; + } + sf = sfn; + } } - sf = sfn; - } } - } - /* units of other factions that were disguised as this faction - * have their disguise replaced by ordinary faction hiding. */ - if (rule_stealth_faction()) { - region *rc; - for (rc = regions; rc; rc = rc->next) { - for (u = rc->units; u; u = u->next) { - attrib *a = a_find(u->attribs, &at_otherfaction); - if (!a) - continue; - if (get_otherfaction(a) == f) { - a_removeall(&u->attribs, &at_otherfaction); - fset(u, UFL_ANON_FACTION); + /* units of other factions that were disguised as this faction + * have their disguise replaced by ordinary faction hiding. */ + if (rule_stealth_faction()) { + region *rc; + for (rc = regions; rc; rc = rc->next) { + for (u = rc->units; u; u = u->next) { + attrib *a = a_find(u->attribs, &at_otherfaction); + if (!a) + continue; + if (get_otherfaction(a) == f) { + a_removeall(&u->attribs, &at_otherfaction); + fset(u, UFL_ANON_FACTION); + } + } } - } } - } } int get_alliance(const faction * a, const faction * b) { - const ally *sf = a->allies; - for (; sf != NULL; sf = sf->next) { - if (sf->faction == b) { - return sf->status; + const ally *sf = a->allies; + for (; sf != NULL; sf = sf->next) { + if (sf->faction == b) { + return sf->status; + } } - } - return 0; + return 0; } void set_alliance(faction * a, faction * b, int status) { - ally **sfp; - sfp = &a->allies; - while (*sfp) { - ally *sf = *sfp; - if (sf->faction == b) - break; - sfp = &sf->next; - } - if (*sfp == NULL) { - ally *sf = *sfp = malloc(sizeof(ally)); - sf->next = NULL; - sf->status = status; - sf->faction = b; - return; - } - (*sfp)->status |= status; + ally **sfp; + sfp = &a->allies; + while (*sfp) { + ally *sf = *sfp; + if (sf->faction == b) + break; + sfp = &sf->next; + } + if (*sfp == NULL) { + ally *sf = *sfp = malloc(sizeof(ally)); + sf->next = NULL; + sf->status = status; + sf->faction = b; + return; + } + (*sfp)->status |= status; } void renumber_faction(faction * f, int no) { - funhash(f); - f->no = no; - fhash(f); - fset(f, FFL_NEWID); + funhash(f); + f->no = no; + fhash(f); + fset(f, FFL_NEWID); } #ifdef SMART_INTERVALS void update_interval(struct faction *f, struct region *r) { - if (r == NULL || f == NULL) - return; - if (f->first == NULL || f->first->index > r->index) { - f->first = r; - } - if (f->last == NULL || f->last->index <= r->index) { - f->last = r; - } + if (r == NULL || f == NULL) + return; + if (f->first == NULL || f->first->index > r->index) { + f->first = r; + } + if (f->last == NULL || f->last->index <= r->index) { + f->last = r; + } } #endif const char *faction_getname(const faction * self) { - return self->name ? self->name : ""; + return self->name ? self->name : ""; } void faction_setname(faction * self, const char *name) { - free(self->name); - if (name) - self->name = _strdup(name); + free(self->name); + if (name) + self->name = _strdup(name); } const char *faction_getemail(const faction * self) { - return self->email ? self->email : ""; + return self->email ? self->email : ""; } void faction_setemail(faction * self, const char *email) { - free(self->email); - if (email) - self->email = _strdup(email); + free(self->email); + if (email) + self->email = _strdup(email); } const char *faction_getbanner(const faction * self) { - return self->banner ? self->banner : ""; + return self->banner ? self->banner : ""; } void faction_setbanner(faction * self, const char *banner) { - free(self->banner); - if (banner) - self->banner = _strdup(banner); + free(self->banner); + if (banner) + self->banner = _strdup(banner); } void faction_setpassword(faction * f, const char *passw) { - free(f->passw); - if (passw) - f->passw = _strdup(passw); - else - f->passw = _strdup(itoa36(rng_int())); + free(f->passw); + if (passw) + f->passw = _strdup(passw); + else + f->passw = _strdup(itoa36(rng_int())); } bool valid_race(const struct faction *f, const struct race *rc) { - if (f->race == rc) - return true; - else { - const char *str = get_param(f->race->parameters, "other_race"); - if (str) - return (bool) (rc_find(str) == rc); - return false; - } + if (f->race == rc) + return true; + else { + const char *str = get_param(f->race->parameters, "other_race"); + if (str) + return (bool)(rc_find(str) == rc); + return false; + } } const char *faction_getpassword(const faction * f) { - return f->passw; + return f->passw; } struct alliance *f_get_alliance(const struct faction *f) { - if (f->alliance && !(f->alliance->flags & ALF_NON_ALLIED)) { - return f->alliance; - } - return NULL; + if (f->alliance && !(f->alliance->flags & ALF_NON_ALLIED)) { + return f->alliance; + } + return NULL; } struct spellbook * faction_get_spellbook(struct faction *f) { - if (f->spellbook) { - return f->spellbook; - } - if (f->magiegebiet!=M_GRAY) { - return get_spellbook(magic_school[f->magiegebiet]); - } - return 0; + if (f->spellbook) { + return f->spellbook; + } + if (f->magiegebiet != M_GRAY) { + return get_spellbook(magic_school[f->magiegebiet]); + } + return 0; } static int allied_skillcount(const faction * f, skill_t sk) { - int num = 0; - alliance *a = f_get_alliance(f); - quicklist *members = a->members; - int qi; + int num = 0; + alliance *a = f_get_alliance(f); + quicklist *members = a->members; + int qi; - for (qi = 0; members; ql_advance(&members, &qi, 1)) { - faction *m = (faction *) ql_get(members, qi); - num += count_skill(m, sk); - } - return num; + for (qi = 0; members; ql_advance(&members, &qi, 1)) { + faction *m = (faction *)ql_get(members, qi); + num += count_skill(m, sk); + } + return num; } static int allied_skilllimit(const faction * f, skill_t sk) { - static int value = -1; - if (value < 0) { - value = get_param_int(global.parameters, "alliance.skilllimit", 0); - } - return value; + static int value = -1; + if (value < 0) { + value = get_param_int(global.parameters, "alliance.skilllimit", 0); + } + return value; } int count_skill(faction * f, skill_t sk) { - int n = 0; - unit *u; + int n = 0; + unit *u; - for (u = f->units; u; u = u->nextF) { - if (has_skill(u, sk)) { - if (!is_familiar(u)) { - n += u->number; - } + for (u = f->units; u; u = u->nextF) { + if (has_skill(u, sk)) { + if (!is_familiar(u)) { + n += u->number; + } + } } - } - return n; + return n; } int skill_limit(faction * f, skill_t sk) { - int m = INT_MAX; - int al = allied_skilllimit(f, sk); - if (al > 0) { - if (sk != SK_ALCHEMY && sk != SK_MAGIC) - return INT_MAX; - if (f_get_alliance(f)) { - int ac = listlen(f->alliance->members); /* number of factions */ - int fl = (al + ac - 1) / ac; /* faction limit, rounded up */ - /* the faction limit may not be achievable because it would break the alliance-limit */ - int sc = al - allied_skillcount(f, sk); - if (sc <= 0) - return 0; - return fl; + int m = INT_MAX; + int al = allied_skilllimit(f, sk); + if (al > 0) { + if (sk != SK_ALCHEMY && sk != SK_MAGIC) + return INT_MAX; + if (f_get_alliance(f)) { + int ac = listlen(f->alliance->members); /* number of factions */ + int fl = (al + ac - 1) / ac; /* faction limit, rounded up */ + /* the faction limit may not be achievable because it would break the alliance-limit */ + int sc = al - allied_skillcount(f, sk); + if (sc <= 0) + return 0; + return fl; + } } - } - if (sk == SK_MAGIC) { - m = max_magicians(f); - } else if (sk == SK_ALCHEMY) { - m = get_param_int(global.parameters, "rules.maxskills.alchemy", - MAXALCHEMISTS); - } - return m; + if (sk == SK_MAGIC) { + m = max_magicians(f); + } + else if (sk == SK_ALCHEMY) { + m = get_param_int(global.parameters, "rules.maxskills.alchemy", + MAXALCHEMISTS); + } + return m; } diff --git a/src/kernel/faction.h b/src/kernel/faction.h index 77a8ba167..c43d48089 100644 --- a/src/kernel/faction.h +++ b/src/kernel/faction.h @@ -114,6 +114,7 @@ typedef struct faction { extern struct faction *factions; struct faction *get_monsters(void); +struct faction *get_or_create_monsters(void); int max_magicians(const faction * f); void set_show_item(faction * f, const struct item_type *itype); diff --git a/src/monsters.c b/src/monsters.c index 213fdb05c..a882a941c 100644 --- a/src/monsters.c +++ b/src/monsters.c @@ -889,7 +889,7 @@ static int nrand(int start, int sub) void spawn_dragons(void) { region *r; - faction *monsters = get_monsters(); + faction *monsters = get_or_create_monsters(); for (r = regions; r; r = r->next) { unit *u;