- new alliances + commands

This commit is contained in:
Enno Rehling 2009-05-20 22:44:19 +00:00
parent 71b34b434a
commit f9946ff7f8
7 changed files with 425 additions and 202 deletions

View file

@ -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]) {

View file

@ -10,6 +10,8 @@
without prior permission by the authors of Eressea.
*/
#pragma region includes
#include <config.h>
#include <kernel/eressea.h>
#include "alliance.h"
@ -32,6 +34,7 @@
#include <util/lists.h>
#include <util/language.h>
#include <util/parser.h>
#include <util/rng.h>
#include <util/umlaut.h>
/* libc includes */
@ -39,6 +42,8 @@
#include <stdlib.h>
#include <string.h>
#pragma endregion
alliance * alliances = NULL;
alliance *
@ -61,68 +66,244 @@ findalliance(int id)
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;
unused(tnext);
if (f==NULL || f->alliance!=u->faction->alliance) {
/* does not belong to our alliance */
return;
if (f && al && u->faction==alliance_leader(al)) {
static variant var;
var.v = f;
create_transaction(al, ALLIANCE_KICK, &var, u, ord);
}
a = a_find(f->attribs, &at_kick);
if (a==NULL) a = a_add(&f->attribs, make_kick());
add_kick(a, f);
}
static void
alliance_join(const tnode * tnext, void * data, struct order * ord)
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!=NULL || al==NULL) {
/* not found */
if (u->faction->alliance==al || al==NULL) {
/* TODO: error message */
return;
}
u->faction->alliance = al;
/* inform the rest? */
create_transaction(al, ALLIANCE_JOIN, NULL, u, ord);
}
static void
execute(const struct syntaxtree * syntax)
perform_kick(alliance * al)
{
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
perform_new(alliance * al)
{
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 = &regions;
while (*rp) {
region * r = *rp;
@ -133,57 +314,56 @@ execute(const struct syntaxtree * syntax)
tnode * root = stree_find(syntax, lang);
order * ord;
for (ord = u->orders; ord; ord = ord->next) {
if (get_keyword(ord) == K_ALLIANCE) {
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);
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);
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;
}
execute(stree, K_ALLIANCE);
/* some may have been kicked, must remove f->alliance==NULL */
}
@ -197,34 +377,54 @@ alliancejoin(void)
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);
add_command(leaf, NULL, LOC(slang->lang, "join"), &cmd_join);
slang = slang->next;
}
}
execute(stree);
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 *

View file

@ -24,9 +24,17 @@ 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 * leader;
struct faction_list * members;
struct alliance_transaction * transactions[ALLIANCE_MAX];
unsigned int flags;
int id;
char * name;
@ -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

View file

@ -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) {
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);
}

View file

@ -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 */

View file

@ -6719,7 +6719,23 @@
<text locale="de">AUSSTOSSEN</text>
<text locale="en">KICK</text>
</string>
<string name="new">
<text locale="de">NEU</text>
<text locale="en">NEW</text>
</string>
<string name="command">
<text locale="de">KOMMANDO</text>
<text locale="en">COMMAND</text>
</string>
<string name="leave">
<text locale="de">VERLASSEN</text>
<text locale="en">LEAVE</text>
</string>
<string name="join">
<text locale="de">BEITRETEN</text>
<text locale="en">JOIN</text>
</string>
<string name="invite">
<text locale="de">AUFNEHEMEN</text>
<text locale="en">JOIN</text>
</string>

View file

@ -116,6 +116,7 @@
<param name="recruit.allow_merge" value="1"/>
<param name="study.expensivemigrants" value="1"/>
<param name="rules.check_overload" value="0"/>
<param name="rules.alliances" value="1"/>
<param name="rules.combat.herospeed" value="3"/>
<param name="rules.combat.skill_bonus" value="0"/>
<param name="rules.combat.loot" value="3"/> <!-- only self + monsters -->