/* vi: set ts=2: +-------------------+ 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. */ #pragma region includes #include #include #include "alliance.h" #include /* kernel includes */ #include #include #include #include #include #include #include #include /* util includes */ #include #include #include #include #include #include #include /* libc includes */ #include #include #include #pragma endregion alliance * alliances = NULL; void free_alliance(alliance * al) { free(al->name); while (al->members) { faction_list * m = al->members; al->members = m->next; free(m); } free(al); } alliance * makealliance(int id, const char * name) { alliance * al;; for (;;) { if (id>0) { for (al=alliances;al;al=al->next) { if (al->id==id) { id = 0; break; } } if (id>0) break; } id = id?id:(1 + (rng_int() % MAX_UNIT_NR)); } al = calloc(1, sizeof(alliance)); al->id = id; if (name) { al->name = strdup(name); } else { al->flags |= ALF_NON_ALLIED; } 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; } typedef struct alliance_transaction { struct alliance_transaction * next; unit * u; order * ord; // alliance * al; // variant userdata; } alliance_transaction; static struct alliance_transaction * transactions[ALLIANCE_MAX]; faction * alliance_get_leader(alliance * al) { if (!al->_leader) { if (al->members) { al->_leader = al->members->data; } } return al->_leader; } static void create_transaction(int type, unit * u, order * ord) { alliance_transaction * tr = calloc(1, sizeof(alliance_transaction)); tr->ord = ord; tr->u = u; tr->next = transactions[type]; transactions[type] = tr; } static void cmd_kick(const tnode * tnext, void * data, struct order * ord) { create_transaction(ALLIANCE_KICK, (unit*)data, ord); } static void cmd_leave(const tnode * tnext, void * data, struct order * ord) { create_transaction(ALLIANCE_LEAVE, (unit*)data, ord); } static void cmd_transfer(const tnode * tnext, void * data, struct order * ord) { create_transaction(ALLIANCE_TRANSFER, (unit*)data, ord); } static void cmd_new(const tnode * tnext, void * data, struct order * ord) { create_transaction(ALLIANCE_NEW, (unit*)data, ord); } static void cmd_invite(const tnode * tnext, void * data, struct order * ord) { create_transaction(ALLIANCE_INVITE, (unit*)data, ord); } static void cmd_join(const tnode * tnext, void * data, struct order * ord) { create_transaction(ALLIANCE_JOIN, (unit*)data, ord); } static void perform_kick(void) { alliance_transaction ** tap = transactions+ALLIANCE_KICK; while (*tap) { alliance_transaction * ta = *tap; alliance * al = f_get_alliance(ta->u->faction); if (al && alliance_get_leader(al)==ta->u->faction) { faction * f; init_tokens(ta->ord); skip_token(); skip_token(); f = getfaction(); if (f && f_get_alliance(f)==al) { setalliance(f, NULL); } } *tap = ta->next; free(ta); } } static void perform_new(void) { alliance_transaction ** tap = transactions+ALLIANCE_NEW; while (*tap) { alliance_transaction * ta = *tap; alliance * al; int id; faction * f = ta->u->faction; init_tokens(ta->ord); skip_token(); skip_token(); id = getid(); al = makealliance(id, itoa36(id)); setalliance(f, al); *tap = ta->next; free(ta); } } static void perform_leave(void) { alliance_transaction ** tap = 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(void) { alliance_transaction ** tap = transactions+ALLIANCE_TRANSFER; while (*tap) { alliance_transaction * ta = *tap; alliance * al = f_get_alliance(ta->u->faction); if (al && alliance_get_leader(al)==ta->u->faction) { faction * f; init_tokens(ta->ord); skip_token(); skip_token(); f = getfaction(); if (f && f_get_alliance(f)==al) { al->_leader = f; } } *tap = ta->next; free(ta); } } static void perform_join(void) { alliance_transaction ** tap = transactions+ALLIANCE_JOIN; while (*tap) { alliance_transaction * ta = *tap; faction * fj = ta->u->faction; int aid; init_tokens(ta->ord); skip_token(); skip_token(); aid = getid(); if (aid) { alliance * al = findalliance(aid); if (al && f_get_alliance(fj)!=al) { alliance_transaction ** tip = transactions+ALLIANCE_INVITE; alliance_transaction * ti = *tip; while (ti) { faction * fi = ti->u->faction; if (fi && f_get_alliance(fi)==al) { int fid; init_tokens(ti->ord); skip_token(); skip_token(); fid = getid(); if (fid==fj->no) { break; } } tip = &ti->next; ti = *tip; } if (ti) { setalliance(fj, 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; if (u->number) { 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) { perform_kick(); perform_leave(); perform_transfer(); perform_new(); perform_join(); } } void alliance_cmd(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, "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_leave); add_command(leaf, NULL, LOC(slang->lang, "command"), &cmd_transfer); slang->root = leaf; 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"), &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 = flist->next; break; } 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; f->alliance_joindate = turn; if (al!=NULL) { 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; } flist = NULL; } free(flist); } const char * alliancename(const alliance * al) { typedef char name[OBJECTIDSIZE + 1]; static name idbuf[8]; static int nextbuf = 0; char *ibuf = idbuf[(++nextbuf) % 8]; if (al && al->name) { snprintf(ibuf, sizeof(name), "%s (%s)", al->name, itoa36(al->id)); ibuf[sizeof(name)-1] = 0; } else { return NULL; } return ibuf; } 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 = building_owner(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 victorycondition(const alliance * al, const char * name) { const char * gems[] = { "opal", "diamond", "zaphire", "topaz", "beryl", "agate", "garnet", "emerald", NULL }; if (strcmp(name, "gems")==0) { const char ** igem = gems; for (;*igem;++igem) { const struct item_type * itype = it_find(*igem); faction_list * flist = al->members; boolean found = false; assert(itype!=NULL); for (;flist && !found;flist=flist->next) { unit * u = flist->data->units; for (;u;u=u->nextF) { if (i_get(u->items, itype)>0) { found = true; break; } } } if (!found) return 0; } return 1; } else if (strcmp(name, "phoenix")==0) { faction_list * flist = al->members; for (;flist;flist=flist->next) { faction * f = flist->data; if (find_key(f->attribs, atoi36("phnx"))) { return 1; } } return 0; } 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; * } */ faction_list * flist = al->members; for (;flist;flist=flist->next) { faction * f = flist->data; if (find_key(f->attribs, atoi36("pyra"))) { return 1; } } return 0; } return -1; } void alliance_setname(alliance * self, const char * name) { free(self->name); if (name) self->name = strdup(name); else self->name = NULL; }