- 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

@ -1,15 +1,17 @@
/* vi: set ts=2:
+-------------------+ Christian Schlittchen <corwin@amber.kn-bremen.de>
| | Enno Rehling <enno@eressea.de>
| Eressea PBEM host | Katja Zedel <katze@felidae.kn-bremen.de>
| (c) 1998 - 2003 | Henning Peters <faroul@beyond.kn-bremen.de>
| | Ingo Wilken <Ingo.Wilken@informatik.uni-oldenburg.de>
+-------------------+ Stefan Reich <reich@halbling.de>
+-------------------+ Christian Schlittchen <corwin@amber.kn-bremen.de>
| | Enno Rehling <enno@eressea.de>
| Eressea PBEM host | Katja Zedel <katze@felidae.kn-bremen.de>
| (c) 1998 - 2003 | Henning Peters <faroul@beyond.kn-bremen.de>
| | Ingo Wilken <Ingo.Wilken@informatik.uni-oldenburg.de>
+-------------------+ Stefan Reich <reich@halbling.de>
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 <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 -->