From f9946ff7f8d4a76aee929d1ecc6f480f5d6fcd65 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 20 May 2009 22:44:19 +0000 Subject: [PATCH] - new alliances + commands --- src/common/gamecode/laws.c | 13 +- src/common/kernel/alliance.c | 558 ++++++++++++++++++++++++----------- src/common/kernel/alliance.h | 23 +- src/common/kernel/save.c | 15 +- src/common/kernel/version.h | 1 + src/res/de/strings.xml | 16 + src/res/e2k9.xml | 1 + 7 files changed, 425 insertions(+), 202 deletions(-) diff --git a/src/common/gamecode/laws.c b/src/common/gamecode/laws.c index 1a1067f8c..4bba49e96 100644 --- a/src/common/gamecode/laws.c +++ b/src/common/gamecode/laws.c @@ -3772,9 +3772,9 @@ init_processor(void) add_proc_order(p, K_WEREWOLF, &setwere_cmd, 0, NULL); #endif /* KARMA_MODULE */ - if (get_param_int(global.parameters, "alliance-vinyambar", 0)==1) { + if (get_param_int(global.parameters, "rules.alliances", 0)==1) { p+=10; - add_proc_global(p, &alliancekick, NULL); + add_proc_global(p, &alliance_cmd, NULL); } p+=10; @@ -3785,11 +3785,6 @@ init_processor(void) add_proc_region(p, &enter_1, "Kontaktieren & Betreten (1. Versuch)"); add_proc_order(p, K_USE, &use_cmd, 0, "Benutzen"); - if (get_param_int(global.parameters, "alliance-vinyambar", 0)==1) { - p+=10; /* in case USE changes it */ - add_proc_global(p, &alliancevictory, "Testen der Allianzbedingungen"); - } - #if INFOCMD_MODULE if (!global.disabled[K_INFO]) { add_proc_global(p, &infocommands, NULL); @@ -3895,10 +3890,6 @@ init_processor(void) #if KARMA_MODULE p+=10; add_proc_global(p, &karma, "Jihads setzen"); -#endif -#ifdef ALLIANCEJOIN - p+=10; - add_proc_global(p, &alliancejoin, "Allianzen"); #endif add_proc_order(p, K_PROMOTION, &promotion_cmd, 0, "Heldenbefoerderung"); if (!global.disabled[K_NUMBER]) { diff --git a/src/common/kernel/alliance.c b/src/common/kernel/alliance.c index 30a537507..3a03126fa 100644 --- a/src/common/kernel/alliance.c +++ b/src/common/kernel/alliance.c @@ -1,15 +1,17 @@ /* vi: set ts=2: - +-------------------+ Christian Schlittchen - | | Enno Rehling - | Eressea PBEM host | Katja Zedel - | (c) 1998 - 2003 | Henning Peters - | | Ingo Wilken - +-------------------+ Stefan Reich ++-------------------+ Christian Schlittchen +| | Enno Rehling +| Eressea PBEM host | Katja Zedel +| (c) 1998 - 2003 | Henning Peters +| | Ingo Wilken ++-------------------+ Stefan Reich - This program may not be used, modified or distributed - without prior permission by the authors of Eressea. +This program may not be used, modified or distributed +without prior permission by the authors of Eressea. */ +#pragma region includes + #include #include #include "alliance.h" @@ -32,6 +34,7 @@ #include #include #include +#include #include /* libc includes */ @@ -39,192 +42,389 @@ #include #include +#pragma endregion + alliance * alliances = NULL; alliance * makealliance(int id, const char * name) { - alliance * al = calloc(1, sizeof(alliance)); - al->id=id; - al->name=strdup(name); - al->next=alliances; - return alliances=al; + alliance * al = calloc(1, sizeof(alliance)); + al->id=id; + al->name=strdup(name); + al->next=alliances; + return alliances=al; } alliance * findalliance(int id) { - alliance * al; - for (al=alliances;al;al=al->next) { - if (al->id==id) return al; - } - return NULL; + alliance * al; + for (al=alliances;al;al=al->next) { + if (al->id==id) return al; + } + return NULL; } -void destroy_kick(struct attrib * a) +typedef struct alliance_transaction { + struct alliance_transaction * next; + unit * u; + variant userdata; + order * ord; +} alliance_transaction; + +static faction * alliance_leader(const alliance * al) { - faction_list * flist = (faction_list*)a->data.v; - freelist(flist); + return al->leader; } -const attrib_type at_kick = { "kick", - DEFAULT_INIT, destroy_kick -}; - -static attrib * -make_kick(void) +static alliance_transaction ** +get_transaction(alliance * al, const variant * userdata, int type) { - return a_new(&at_kick); + alliance_transaction ** tap=al->transactions+type; + while (*tap) { + alliance_transaction * ta = *tap; + if (userdata==NULL || memcmp(&ta->userdata, userdata, sizeof(variant))==0) { + return tap; + } + tap = &ta->next; + } + return NULL; } static void -add_kick(attrib * a, faction * f) +create_transaction(alliance * al, int type, const variant * userdata, unit * u, order * ord) { - faction_list * flist = (faction_list*)a->data.v; - while (flist && flist->data!=f) flist = flist->next; - if (flist) return; - flist = calloc(1, sizeof(faction_list)); - flist->data = (void*)f; - flist->next = (faction_list*)a->data.v; - a->data.v = flist; + alliance_transaction * tr = malloc(sizeof(alliance_transaction)); + memcpy(&tr->userdata, userdata, sizeof(variant)); + tr->ord = ord; + tr->next = al->transactions[type]; + al->transactions[type] = tr; } static void -alliance_kick(const tnode * tnext, void * data, struct order * ord) +cmd_kick(const tnode * tnext, void * data, struct order * ord) { unit * u = (unit*)data; + alliance * al = u->faction->alliance; faction * f = findfaction(getid()); - attrib * a; - - if (f==NULL || f->alliance!=u->faction->alliance) { - /* does not belong to our alliance */ + unused(tnext); + + if (f && al && u->faction==alliance_leader(al)) { + static variant var; + var.v = f; + create_transaction(al, ALLIANCE_KICK, &var, u, ord); + } +} + +static void +cmd_leave(const tnode * tnext, void * data, struct order * ord) +{ + unit * u = (unit*)data; + alliance * al = u->faction->alliance; + unused(tnext); + + if (al) { + create_transaction(al, ALLIANCE_LEAVE, NULL, u, ord); + } +} + +static void +cmd_transfer(const tnode * tnext, void * data, struct order * ord) +{ + unit * u = (unit*)data; + alliance * al = u->faction->alliance; + faction * f = findfaction(getid()); + unused(tnext); + + if (f && al && f->alliance==al && u->faction==alliance_leader(al)) { + static variant var; + var.v = f; + create_transaction(al, ALLIANCE_TRANSFER, &var, u, ord); + } +} + +static void +cmd_new(const tnode * tnext, void * data, struct order * ord) +{ + unit * u = (unit*)data; + alliance * al = u->faction->alliance; + unused(tnext); + + if (al && u->faction==alliance_leader(al)) { + static variant var; + const char * str = getstrtoken(); + + var.i = str?atoi36(str):0; + create_transaction(al, ALLIANCE_NEW, &var, u, ord); + } +} + +static void +cmd_invite(const tnode * tnext, void * data, struct order * ord) +{ + unit * u = (unit*)data; + alliance * al = u->faction->alliance; + faction * f = findfaction(getid()); + unused(tnext); + + if (f==NULL || al==NULL) { + /* TODO: error message */ + return; + } else { + static variant var; + var.v = f; + create_transaction(al, ALLIANCE_INVITE, &var, u, ord); + } +} + +static void +cmd_join(const tnode * tnext, void * data, struct order * ord) +{ + unit * u = (unit*)data; + alliance * al = findalliance(getid()); + unused(tnext); + + if (u->faction->alliance==al || al==NULL) { + /* TODO: error message */ return; } - a = a_find(f->attribs, &at_kick); - if (a==NULL) a = a_add(&f->attribs, make_kick()); - add_kick(a, f); + + create_transaction(al, ALLIANCE_JOIN, NULL, u, ord); } static void -alliance_join(const tnode * tnext, void * data, struct order * ord) +perform_kick(alliance * al) { - unit * u = (unit*)data; - alliance * al = findalliance(getid()); - unused(tnext); - - if (u->faction->alliance!=NULL || al==NULL) { - /* not found */ - return; - } - u->faction->alliance = al; - /* inform the rest? */ + alliance_transaction ** tap = al->transactions+ALLIANCE_KICK; + while (*tap) { + alliance_transaction * ta = *tap; + faction * f = ta->u->faction; + setalliance(f, NULL); + *tap = ta->next; + free(ta); + } } static void -execute(const struct syntaxtree * syntax) +perform_new(alliance * al) { - region ** rp = ®ions; - while (*rp) { - region * r = *rp; - unit **up = &r->units; - while (*up) { - unit * u = *up; - const struct locale * lang = u->faction->locale; - tnode * root = stree_find(syntax, lang); - order * ord; - for (ord = u->orders; ord; ord = ord->next) { - if (get_keyword(ord) == K_ALLIANCE) { - do_command(root, u, ord); - } - } - if (u==*up) up = &u->next; - } - if (*rp==r) rp = &r->next; - } + alliance_transaction ** tap = al->transactions+ALLIANCE_LEAVE; + while (*tap) { + alliance * al; + alliance_transaction * ta = *tap; + faction * f = ta->u->faction; + int id = ta->userdata.i; + + do { + id = id?id:(1 + (rng_int() % MAX_UNIT_NR)); + for (al=alliances;al;al=al->next) { + if (al->id==id) { + id = 0; + break; + } + } + } while (id==0); + + al = calloc(1, sizeof(alliance)); + al->id = id; + setalliance(f, al); + + *tap = ta->next; + free(ta); + } + +} + +static void +perform_leave(alliance * al) +{ + alliance_transaction ** tap = al->transactions+ALLIANCE_LEAVE; + while (*tap) { + alliance_transaction * ta = *tap; + faction * f = ta->u->faction; + + setalliance(f, NULL); + + *tap = ta->next; + free(ta); + } + +} + +static void +perform_transfer(alliance * al) +{ + alliance_transaction ** tap = al->transactions+ALLIANCE_LEAVE; + while (*tap) { + alliance_transaction * ta = *tap; + faction * f = (faction *)ta->userdata.v; + + assert(f->alliance==al); + + al->leader = f; + + *tap = ta->next; + free(ta); + } + +} + +static void +perform_join(alliance * al) +{ + alliance_transaction ** tap = al->transactions+ALLIANCE_JOIN; + while (*tap) { + alliance_transaction * ta = *tap; + faction * f = ta->u->faction; + if (f->alliance!=al) { + alliance_transaction ** tip = al->transactions+ALLIANCE_INVITE; + alliance_transaction * ti = *tip; + while (ti) { + if (ti->userdata.v==f) break; + tip = &ti->next; + ti = *tip; + } + if (ti) { + setalliance(f, al); + *tip = ti->next; + free(ti); + } else { + /* TODO: error message */ + } + } + *tap = ta->next; + free(ta); + } + +} + +static void +execute(const struct syntaxtree * syntax, keyword_t kwd) +{ + int run = 0; + + region ** rp = ®ions; + while (*rp) { + region * r = *rp; + unit **up = &r->units; + while (*up) { + unit * u = *up; + const struct locale * lang = u->faction->locale; + tnode * root = stree_find(syntax, lang); + order * ord; + for (ord = u->orders; ord; ord = ord->next) { + if (get_keyword(ord) == kwd) { + do_command(root, u, ord); + run = 1; + } + } + if (u==*up) up = &u->next; + } + if (*rp==r) rp = &r->next; + } + + if (run) { + alliance * al; + for (al=alliances;al;al=al->next) { + perform_kick(al); + } + for (al=alliances;al;al=al->next) { + perform_leave(al); + } + for (al=alliances;al;al=al->next) { + perform_transfer(al); + } + for (al=alliances;al;al=al->next) { + perform_new(al); + } + for (al=alliances;al;al=al->next) { + perform_join(al); + } + } } void -alliancekick(void) +alliance_cmd(void) { - static syntaxtree * stree = NULL; - faction * f = factions; - if (stree==NULL) { - syntaxtree * slang = stree = stree_create(); - while (slang) { - struct tnode * root = calloc(sizeof(tnode), 1); - struct tnode * leaf = calloc(sizeof(tnode), 1); - add_command(root, leaf, LOC(slang->lang, "alliance"), NULL); - add_command(leaf, NULL, LOC(slang->lang, "kick"), &alliance_kick); - slang = slang->next; - } - } - execute(stree); - while (f) { - attrib * a = a_find(f->attribs, &at_kick); - if (a!=NULL) { - faction_list * flist = (faction_list*)a->data.v; - if (flist!=NULL) { - unsigned int votes = listlen(flist); - unsigned int size = listlen(f->alliance->members); - if (size<=votes*2) { - f->alliance = NULL; - /* tell him he's been kicked */ - for (flist=f->alliance->members;flist;flist=flist->next) { - ADDMSG(&flist->data->msgs, msg_message("alliance::kickedout", - "member alliance votes", f, f->alliance, votes)); - } - } else { - /* warn that he's been attempted to kick */ - for (flist=f->alliance->members;flist;flist=flist->next) { - ADDMSG(&flist->data->msgs, msg_message("alliance::kickattempt", - "member alliance votes", f, f->alliance, votes)); - } - } - } - } - f = f->next; - } - /* some may have been kicked, must remove f->alliance==NULL */ + static syntaxtree * stree = NULL; + if (stree==NULL) { + syntaxtree * slang = stree = stree_create(); + while (slang) { + struct tnode * root = calloc(sizeof(tnode), 1); + struct tnode * leaf = calloc(sizeof(tnode), 1); + add_command(root, leaf, LOC(slang->lang, "alliance"), NULL); + add_command(leaf, NULL, LOC(slang->lang, "new"), &cmd_new); + add_command(leaf, NULL, LOC(slang->lang, "invite"), &cmd_invite); + add_command(leaf, NULL, LOC(slang->lang, "join"), &cmd_join); + add_command(leaf, NULL, LOC(slang->lang, "kick"), &cmd_kick); + add_command(leaf, NULL, LOC(slang->lang, "leave"), &cmd_new); + add_command(leaf, NULL, LOC(slang->lang, "command"), &cmd_transfer); + slang = slang->next; + } + } + execute(stree, K_ALLIANCE); + /* some may have been kicked, must remove f->alliance==NULL */ } void alliancejoin(void) { - static syntaxtree * stree = NULL; - if (stree==NULL) { - syntaxtree * slang = stree = stree_create(); - while (slang) { - struct tnode * root = calloc(sizeof(tnode), 1); - struct tnode * leaf = calloc(sizeof(tnode), 1); - add_command(root, leaf, LOC(slang->lang, "alliance"), NULL); - add_command(leaf, NULL, LOC(slang->lang, "join"), &alliance_join); - slang = slang->next; - } - } - execute(stree); + static syntaxtree * stree = NULL; + if (stree==NULL) { + syntaxtree * slang = stree = stree_create(); + while (slang) { + struct tnode * root = calloc(sizeof(tnode), 1); + struct tnode * leaf = calloc(sizeof(tnode), 1); + add_command(root, leaf, LOC(slang->lang, "alliance"), NULL); + add_command(leaf, NULL, LOC(slang->lang, "join"), &cmd_join); + slang = slang->next; + } + } + execute(stree, K_ALLIANCE); } void setalliance(struct faction * f, alliance * al) { + faction_list * flist = NULL; if (f->alliance==al) return; if (f->alliance!=NULL) { faction_list ** flistp = &f->alliance->members; while (*flistp) { + faction_list * flist = *flistp; if ((*flistp)->data==f) { - *flistp = (*flistp)->next; + *flistp = flist->next; break; } - flistp = &(*flistp)->next; + flistp = &flist->next; + } + + if (f->alliance->leader==f) { + if (f->alliance->members) { + f->alliance->leader = f->alliance->members->data; + } else { + f->alliance->leader = NULL; + } } } f->alliance = al; if (al!=NULL) { - faction_list * flist = calloc(sizeof(faction_list), 1); - flist->next = al->members; - flist->data = f; - al->members = flist; + faction_list ** flistp = &al->members; + while (*flistp) { + flistp = &(*flistp)->next; + } + if (flist==NULL) { + flist = malloc(sizeof(faction_list)); + flist->data = f; + } + *flistp = flist; + flist->next = NULL; + if (al->leader==NULL) { + al->leader = f; + } } + free(flist); } const char * @@ -248,40 +448,40 @@ alliancename(const alliance * al) void alliancevictory(void) { - const struct building_type * btype = bt_find("stronghold"); - region * r = regions; - alliance * al = alliances; - if (btype==NULL) return; - while (r!=NULL) { - building * b = r->buildings; - while (b!=NULL) { - if (b->type==btype) { - unit * u = buildingowner(r, b); - if (u) { - fset(u->faction->alliance, FFL_MARK); - } - } - b = b->next; - } - r=r->next; - } - while (al!=NULL) { - if (!fval(al, FFL_MARK)) { - faction_list * flist = al->members; - while (flist!=0) { - faction * f = flist->data; - if (f->alliance==al) { - ADDMSG(&f->msgs, msg_message("alliance::lost", - "alliance", al)); - destroyfaction(f); - } - flist = flist->next; - } - } else { - freset(al, FFL_MARK); - } - al = al->next; - } + const struct building_type * btype = bt_find("stronghold"); + region * r = regions; + alliance * al = alliances; + if (btype==NULL) return; + while (r!=NULL) { + building * b = r->buildings; + while (b!=NULL) { + if (b->type==btype) { + unit * u = buildingowner(r, b); + if (u) { + fset(u->faction->alliance, FFL_MARK); + } + } + b = b->next; + } + r=r->next; + } + while (al!=NULL) { + if (!fval(al, FFL_MARK)) { + faction_list * flist = al->members; + while (flist!=0) { + faction * f = flist->data; + if (f->alliance==al) { + ADDMSG(&f->msgs, msg_message("alliance::lost", + "alliance", al)); + destroyfaction(f); + } + flist = flist->next; + } + } else { + freset(al, FFL_MARK); + } + al = al->next; + } } int @@ -324,19 +524,19 @@ victorycondition(const alliance * al, const char * name) } else if (strcmp(name, "pyramid")==0) { /* Logik: - * - if (pyr > last_passed_size && pyr > all_others) { - * pyr->passed->counter++; - * for(all_other_pyrs) { - * pyr->passed->counter=0; - * } - * - * if(pyr->passed->counter >= 3) { - * set(pyr, passed); - * pyr->owner->set_attrib(pyra); - * } - * last_passed_size = pyr->size; - * } - */ + * - if (pyr > last_passed_size && pyr > all_others) { + * pyr->passed->counter++; + * for(all_other_pyrs) { + * pyr->passed->counter=0; + * } + * + * if(pyr->passed->counter >= 3) { + * set(pyr, passed); + * pyr->owner->set_attrib(pyra); + * } + * last_passed_size = pyr->size; + * } + */ faction_list * flist = al->members; for (;flist;flist=flist->next) { diff --git a/src/common/kernel/alliance.h b/src/common/kernel/alliance.h index 84e34db3e..eb826b5e2 100644 --- a/src/common/kernel/alliance.h +++ b/src/common/kernel/alliance.h @@ -24,12 +24,20 @@ struct faction; struct region; struct faction_list; +struct alliance_transaction; + +enum { + ALLIANCE_KICK, ALLIANCE_LEAVE, ALLIANCE_TRANSFER, ALLIANCE_NEW, ALLIANCE_INVITE, ALLIANCE_JOIN, ALLIANCE_MAX +}; + typedef struct alliance { - struct alliance * next; - struct faction_list * members; - unsigned int flags; - int id; - char * name; + struct alliance * next; + struct faction * leader; + struct faction_list * members; + struct alliance_transaction * transactions[ALLIANCE_MAX]; + unsigned int flags; + int id; + char * name; } alliance; extern alliance * alliances; @@ -38,12 +46,9 @@ extern alliance * makealliance(int id, const char * name); extern const char * alliancename(const struct alliance * al); extern void setalliance(struct faction * f, alliance * al); -extern void alliancejoin(void); -extern void alliancekick(void); -extern void alliancevictory(void); +extern void alliance_cmd(void); void alliance_setname(alliance * self, const char * name); -extern int victorycondition(const alliance * al, const char * name); /* execute commands */ #ifdef __cplusplus diff --git a/src/common/kernel/save.c b/src/common/kernel/save.c index 9bb11e9cd..4c3fda2bf 100644 --- a/src/common/kernel/save.c +++ b/src/common/kernel/save.c @@ -554,8 +554,12 @@ read_alliances(struct storage * store) store->r_str_buf(store, pbuf, sizeof(pbuf)); while (strcmp(pbuf, "end")!=0) { char aname[128]; + alliance * al; store->r_str_buf(store, aname, sizeof(aname)); - makealliance(atoi36(pbuf), aname); + al = makealliance(atoi36(pbuf), aname); + if (store->version>=ALLIANCELEADER_VERSION) { + read_reference(&al->leader, store, read_faction_reference, resolve_faction); + } store->r_str_buf(store, pbuf, sizeof(pbuf)); } } @@ -565,8 +569,13 @@ write_alliances(struct storage * store) { alliance * al = alliances; while (al) { - store->w_id(store, al->id); - store->w_tok(store, al->name); + if (al->leader) { + store->w_id(store, al->id); + store->w_tok(store, al->name); + if (store->version>=ALLIANCELEADER_VERSION) { + write_faction_reference(al->leader, store); + } + } al = al->next; store->w_brk(store); } diff --git a/src/common/kernel/version.h b/src/common/kernel/version.h index cdc89d70a..d0c12911f 100644 --- a/src/common/kernel/version.h +++ b/src/common/kernel/version.h @@ -61,6 +61,7 @@ #define NOBORDERATTRIBS_VERSION 331 /* border::attribs has been moved to userdata */ #define UIDHASH_VERSION 332 /* borders use the region.uid to store */ #define REGIONOWNER_VERSION 333 /* regions have owners and morale */ +#define ALLIANCELEADER_VERSION 333 /* alliances have a leader */ #define MIN_VERSION CURSETYPE_VERSION /* minimal datafile we support */ #define RELEASE_VERSION REGIONOWNER_VERSION /* current datafile */ diff --git a/src/res/de/strings.xml b/src/res/de/strings.xml index bed1dd4c0..349701550 100644 --- a/src/res/de/strings.xml +++ b/src/res/de/strings.xml @@ -6719,7 +6719,23 @@ AUSSTOSSEN KICK + + NEU + NEW + + + KOMMANDO + COMMAND + + + VERLASSEN + LEAVE + + BEITRETEN + JOIN + + AUFNEHEMEN JOIN diff --git a/src/res/e2k9.xml b/src/res/e2k9.xml index 28dd54cd9..c18d7b019 100644 --- a/src/res/e2k9.xml +++ b/src/res/e2k9.xml @@ -116,6 +116,7 @@ +