Merge pull request #54 from badgerman/master

monster refactoring
This commit is contained in:
Enno Rehling 2014-11-24 14:12:58 +01:00
commit f7a2cf2015
33 changed files with 242 additions and 148 deletions

View File

@ -5,3 +5,4 @@ end
package.path = package.path .. ';' .. path .. '/?.lua;' .. path .. '/?/init.lua' package.path = package.path .. ';' .. path .. '/?.lua;' .. path .. '/?/init.lua'
require 'eressea' require 'eressea'
require 'eressea.xmlconf' require 'eressea.xmlconf'
return require('eressea.rules')

View File

@ -0,0 +1,9 @@
local rules = {}
if config.rules then
rules = require('eressea.' .. config.rules)
eressea.log.info('loaded ' .. #rules .. ' modules for ' .. config.rules)
else
eressea.log.warning('no rule modules loaded, specify a game in eressea.ini or with -r')
end
return rules

View File

@ -174,12 +174,6 @@ end
package.path = package.path .. ';' .. path .. '/?.lua;' .. path .. '/?/init.lua' package.path = package.path .. ';' .. path .. '/?.lua;' .. path .. '/?/init.lua'
require 'eressea' require 'eressea'
require 'eressea.xmlconf' -- read xml data require 'eressea.xmlconf' -- read xml data
local rules = require('eressea.rules')
local rules = {}
if config.rules then
rules = require('eressea.' .. config.rules)
eressea.log.info('loaded ' .. #rules .. ' modules for ' .. config.rules)
else
eressea.log.warning('no rule modules loaded, specify a game in eressea.ini or with -r')
end
run_turn(rules) run_turn(rules)

View File

@ -23,6 +23,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "move.h" #include "move.h"
#include "laws.h" #include "laws.h"
#include "skill.h" #include "skill.h"
#include "monster.h"
#include <kernel/alliance.h> #include <kernel/alliance.h>
#include <kernel/build.h> #include <kernel/build.h>
@ -132,7 +133,6 @@ static int skill_formula = 0;
#define DAMAGE_CRITICAL (1<<0) #define DAMAGE_CRITICAL (1<<0)
#define DAMAGE_MELEE_BONUS (1<<1) #define DAMAGE_MELEE_BONUS (1<<1)
#define DAMAGE_MISSILE_BONUS (1<<2) #define DAMAGE_MISSILE_BONUS (1<<2)
#define DAMAGE_UNARMED_BONUS (1<<3)
#define DAMAGE_SKILL_BONUS (1<<4) #define DAMAGE_SKILL_BONUS (1<<4)
/** initialize rules from configuration. /** initialize rules from configuration.
*/ */
@ -158,9 +158,6 @@ static void static_rules(void)
if (get_param_int(global.parameters, "rules.combat.missile_bonus", 1)) { if (get_param_int(global.parameters, "rules.combat.missile_bonus", 1)) {
damage_rules |= DAMAGE_MISSILE_BONUS; damage_rules |= DAMAGE_MISSILE_BONUS;
} }
if (get_param_int(global.parameters, "rules.combat.unarmed_bonus", 1)) {
damage_rules |= DAMAGE_UNARMED_BONUS;
}
if (get_param_int(global.parameters, "rules.combat.skill_bonus", 1)) { if (get_param_int(global.parameters, "rules.combat.skill_bonus", 1)) {
damage_rules |= DAMAGE_SKILL_BONUS; damage_rules |= DAMAGE_SKILL_BONUS;
} }
@ -1042,6 +1039,41 @@ static int natural_armor(unit * du)
return an; return an;
} }
static int rc_specialdamage(const unit *au, const unit *du, const struct weapon_type *wtype)
{
const race *ar = u_race(au);
int m, modifier = 0;
switch (old_race(ar)) {
case RC_HALFLING:
if (wtype != NULL && dragonrace(u_race(du))) {
modifier += 5;
}
break;
default:
break;
}
if (wtype != NULL && wtype->modifiers != NULL) {
for (m = 0; wtype->modifiers[m].value; ++m) {
/* weapon damage for this weapon, possibly by race */
if (wtype->modifiers[m].flags & WMF_DAMAGE) {
race_list *rlist = wtype->modifiers[m].races;
if (rlist != NULL) {
while (rlist) {
if (rlist->data == ar)
break;
rlist = rlist->next;
}
if (rlist == NULL)
continue;
}
modifier += wtype->modifiers[m].value;
}
}
}
return modifier;
}
bool bool
terminate(troop dt, troop at, int type, const char *damage, bool missile) terminate(troop dt, troop at, int type, const char *damage, bool missile)
{ {
@ -1059,8 +1091,8 @@ terminate(troop dt, troop at, int type, const char *damage, bool missile)
int hp; int hp;
int ar = 0, an, am; int ar = 0, an, am;
const armor_type *armor = select_armor(dt, true); const armor_type *armor = select_armor(dt, false);
const armor_type *shield = select_armor(dt, false); const armor_type *shield = select_armor(dt, true);
const weapon_type *dwtype = NULL; const weapon_type *dwtype = NULL;
const weapon_type *awtype = NULL; const weapon_type *awtype = NULL;
@ -1163,7 +1195,7 @@ terminate(troop dt, troop at, int type, const char *damage, bool missile)
} }
} }
da += rc_specialdamage(u_race(au), u_race(du), awtype); da += rc_specialdamage(au, du, awtype);
if (awtype != NULL && fval(awtype, WTF_MISSILE)) { if (awtype != NULL && fval(awtype, WTF_MISSILE)) {
/* missile weapon bonus */ /* missile weapon bonus */
@ -1171,12 +1203,6 @@ terminate(troop dt, troop at, int type, const char *damage, bool missile)
da += af->person[at.index].damage_rear; da += af->person[at.index].damage_rear;
} }
} }
else if (awtype == NULL) {
/* skill bonus for unarmed combat */
if (damage_rules & DAMAGE_UNARMED_BONUS) {
da += effskill(au, SK_WEAPONLESS);
}
}
else { else {
/* melee bonus */ /* melee bonus */
if (damage_rules & DAMAGE_MELEE_BONUS) { if (damage_rules & DAMAGE_MELEE_BONUS) {
@ -2554,16 +2580,7 @@ static void loot_items(fighter * corpse)
mustloot ? loot : loot_quota(corpse->unit, fig->unit, itm->type, mustloot ? loot : loot_quota(corpse->unit, fig->unit, itm->type,
loot); loot);
if (trueloot > 0) { if (trueloot > 0) {
item *l = fig->loot; i_change(&fig->loot, itm->type, trueloot);
while (l && l->type != itm->type)
l = l->next;
if (!l) {
l = calloc(sizeof(item), 1);
l->next = fig->loot;
fig->loot = l;
l->type = itm->type;
}
l->number += trueloot;
} }
} }
} }

View File

@ -14,6 +14,7 @@ without prior permission by the authors of Eressea.
#include "bind_faction.h" #include "bind_faction.h"
#include "bind_unit.h" #include "bind_unit.h"
#include "bindings.h" #include "bindings.h"
#include "helpers.h"
#include <kernel/alliance.h> #include <kernel/alliance.h>
#include <kernel/faction.h> #include <kernel/faction.h>
@ -325,6 +326,14 @@ static int tolua_faction_destroy(lua_State * L)
return 0; return 0;
} }
static int tolua_faction_get(lua_State * L)
{
int no = tolua_toid(L, 1, 0);
faction *f = findfaction(no);
tolua_pushusertype(L, f, TOLUA_CAST "faction");
return 1;
}
static int tolua_faction_create(lua_State * L) static int tolua_faction_create(lua_State * L)
{ {
const char *email = tolua_tostring(L, 1, 0); const char *email = tolua_tostring(L, 1, 0);
@ -510,7 +519,10 @@ void tolua_faction_open(lua_State * L)
tolua_module(L, NULL, 0); tolua_module(L, NULL, 0);
tolua_beginmodule(L, NULL); tolua_beginmodule(L, NULL);
{ {
tolua_cclass(L, TOLUA_CAST "faction", TOLUA_CAST "faction", TOLUA_CAST "", tolua_beginmodule(L, TOLUA_CAST "eressea");
tolua_function(L, TOLUA_CAST "get_faction", tolua_faction_get);
tolua_endmodule(L);
tolua_cclass(L, TOLUA_CAST "faction", TOLUA_CAST "faction", TOLUA_CAST "",
NULL); NULL);
tolua_beginmodule(L, TOLUA_CAST "faction"); tolua_beginmodule(L, TOLUA_CAST "faction");
{ {
@ -561,9 +573,10 @@ void tolua_faction_open(lua_State * L)
tolua_function(L, TOLUA_CAST "add_item", tolua_faction_add_item); tolua_function(L, TOLUA_CAST "add_item", tolua_faction_add_item);
tolua_variable(L, TOLUA_CAST "items", tolua_faction_get_items, NULL); tolua_variable(L, TOLUA_CAST "items", tolua_faction_get_items, NULL);
tolua_function(L, TOLUA_CAST "renumber", &tolua_faction_renumber); tolua_function(L, TOLUA_CAST "renumber", tolua_faction_renumber);
tolua_function(L, TOLUA_CAST "create", &tolua_faction_create); tolua_function(L, TOLUA_CAST "create", tolua_faction_create);
tolua_function(L, TOLUA_CAST "destroy", &tolua_faction_destroy); tolua_function(L, TOLUA_CAST "get", tolua_faction_get);
tolua_function(L, TOLUA_CAST "destroy", tolua_faction_destroy);
#ifdef TODO #ifdef TODO
def("faction_origin", &faction_getorigin, def("faction_origin", &faction_getorigin,
pure_out_value(_2) + pure_out_value(_3)),.def_readwrite("subscription", pure_out_value(_2) + pure_out_value(_3)),.def_readwrite("subscription",

View File

@ -1,5 +1,6 @@
#include <platform.h> #include <platform.h>
#include "spells/shipcurse.h" #include "spells/shipcurse.h"
#include "monster.h"
#include <kernel/equipment.h> #include <kernel/equipment.h>
#include <kernel/faction.h> #include <kernel/faction.h>

View File

@ -565,14 +565,6 @@ static int tolua_read_turn(lua_State * L)
return 1; return 1;
} }
static int tolua_get_faction(lua_State * L)
{
int no = tolua_toid(L, 1, 0);
faction *f = findfaction(no);
tolua_pushusertype(L, f, TOLUA_CAST "faction");
return 1;
}
static int tolua_get_region(lua_State * L) static int tolua_get_region(lua_State * L)
{ {
int x = (int)tolua_tonumber(L, 1, 0); int x = (int)tolua_tonumber(L, 1, 0);
@ -1137,7 +1129,6 @@ int tolua_bindings_open(lua_State * L)
tolua_function(L, TOLUA_CAST "get_ship", &config_get_stype); tolua_function(L, TOLUA_CAST "get_ship", &config_get_stype);
} tolua_endmodule(L); } tolua_endmodule(L);
tolua_function(L, TOLUA_CAST "get_region_by_id", tolua_get_region_byid); tolua_function(L, TOLUA_CAST "get_region_by_id", tolua_get_region_byid);
tolua_function(L, TOLUA_CAST "get_faction", tolua_get_faction);
tolua_function(L, TOLUA_CAST "get_unit", tolua_get_unit); tolua_function(L, TOLUA_CAST "get_unit", tolua_get_unit);
tolua_function(L, TOLUA_CAST "get_alliance", tolua_get_alliance); tolua_function(L, TOLUA_CAST "get_alliance", tolua_get_alliance);
tolua_function(L, TOLUA_CAST "get_ship", tolua_get_ship); tolua_function(L, TOLUA_CAST "get_ship", tolua_get_ship);

View File

@ -28,6 +28,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "randenc.h" #include "randenc.h"
#include "spy.h" #include "spy.h"
#include "move.h" #include "move.h"
#include "monster.h"
#include "reports.h" #include "reports.h"
/* kernel includes */ /* kernel includes */

View File

@ -143,24 +143,6 @@ void set_show_item(faction * f, const struct item_type *itype)
a->data.v = (void *)itype; a->data.v = (void *)itype;
} }
faction *get_or_create_monsters(void)
{
faction *f = findfaction(666);
if (!f) {
const race *rc = rc_get_or_create("dragon");
const char *email = get_param(global.parameters, "monster.email");
f = addfaction(email ? email : "noreply@eressea.de", NULL, rc, NULL, 0);
renumber_faction(f, 666);
faction_setname(f, "Monster");
fset(f, FFL_NPC | FFL_NOIDLEOUT);
}
return f;
}
faction *get_monsters(void) {
return get_or_create_monsters();
}
const unit *random_unit_in_faction(const faction * f) const unit *random_unit_in_faction(const faction * f)
{ {
unit *u; unit *u;
@ -632,7 +614,7 @@ void remove_empty_factions(void)
/* monster (0) werden nicht entfernt. alive kann beim readgame /* monster (0) werden nicht entfernt. alive kann beim readgame
* () auf 0 gesetzt werden, wenn monsters keine einheiten mehr * () auf 0 gesetzt werden, wenn monsters keine einheiten mehr
* haben. */ * haben. */
if ((f->units == NULL || f->alive == 0) && !is_monsters(f)) { if ((f->units == NULL || f->alive == 0) && !fval(f, FFL_NOIDLEOUT)) {
ursprung *ur = f->ursprung; ursprung *ur = f->ursprung;
while (ur && ur->id != 0) while (ur && ur->id != 0)
ur = ur->next; ur = ur->next;

View File

@ -54,8 +54,6 @@ extern "C" {
#define FFL_SAVEMASK (FFL_DEFENDER|FFL_NEWID|FFL_GM|FFL_NPC|FFL_DBENTRY|FFL_NOIDLEOUT) #define FFL_SAVEMASK (FFL_DEFENDER|FFL_NEWID|FFL_GM|FFL_NPC|FFL_DBENTRY|FFL_NOIDLEOUT)
#define is_monsters(f) (f && fval(f, FFL_NPC) && f==get_monsters())
typedef struct faction { typedef struct faction {
struct faction *next; struct faction *next;
struct faction *nexthash; struct faction *nexthash;
@ -116,8 +114,6 @@ void fhash(struct faction *f);
void funhash(struct faction *f); void funhash(struct faction *f);
struct faction *findfaction(int n); struct faction *findfaction(int n);
struct faction *get_monsters(void);
struct faction *get_or_create_monsters(void);
int max_magicians(const faction * f); int max_magicians(const faction * f);
void set_show_item(faction * f, const struct item_type *itype); void set_show_item(faction * f, const struct item_type *itype);

View File

@ -7,6 +7,7 @@
#include <kernel/config.h> #include <kernel/config.h>
#include <util/language.h> #include <util/language.h>
#include "monster.h"
#include <CuTest.h> #include <CuTest.h>
#include <tests.h> #include <tests.h>

View File

@ -257,7 +257,7 @@ message * cmistake(const unit * u, struct order *ord, int mno, int mtype)
static char msgname[20]; static char msgname[20];
unused_arg(mtype); unused_arg(mtype);
if (is_monsters(u->faction)) if (fval(u->faction, FFL_NPC))
return 0; return 0;
sprintf(msgname, "error%d", mno); sprintf(msgname, "error%d", mno);
result = msg_feedback(u, ord, msgname, ""); result = msg_feedback(u, ord, msgname, "");

View File

@ -280,42 +280,6 @@ const char *racename(const struct locale *loc, const unit * u, const race * rc)
return str ? str : rc->_name; return str ? str : rc->_name;
} }
int
rc_specialdamage(const race * ar, const race * dr,
const struct weapon_type *wtype)
{
race_t art = old_race(ar);
int m, modifier = 0;
if (wtype != NULL && wtype->modifiers != NULL)
for (m = 0; wtype->modifiers[m].value; ++m) {
/* weapon damage for this weapon, possibly by race */
if (wtype->modifiers[m].flags & WMF_DAMAGE) {
race_list *rlist = wtype->modifiers[m].races;
if (rlist != NULL) {
while (rlist) {
if (rlist->data == ar)
break;
rlist = rlist->next;
}
if (rlist == NULL)
continue;
}
modifier += wtype->modifiers[m].value;
}
}
switch (art) {
case RC_HALFLING:
if (wtype != NULL && dragonrace(dr)) {
modifier += 5;
}
break;
default:
break;
}
return modifier;
}
void write_race_reference(const race * rc, struct storage *store) void write_race_reference(const race * rc, struct storage *store)
{ {
WRITE_TOK(store, rc ? rc->_name : "none"); WRITE_TOK(store, rc ? rc->_name : "none");

View File

@ -178,8 +178,6 @@ extern "C" {
extern race *rc_get_or_create(const char *name); extern race *rc_get_or_create(const char *name);
extern const race *rc_find(const char *); extern const race *rc_find(const char *);
extern int rc_specialdamage(const race *, const race *,
const struct weapon_type *);
void free_races(void); void free_races(void);
typedef enum name_t { NAME_SINGULAR, NAME_PLURAL, NAME_DEFINITIVE, NAME_CATEGORY } name_t; typedef enum name_t { NAME_SINGULAR, NAME_PLURAL, NAME_DEFINITIVE, NAME_CATEGORY } name_t;

View File

@ -222,7 +222,7 @@ static faction *factionorders(void)
f = findfaction(fid); f = findfaction(fid);
if (f != NULL && !is_monsters(f)) { if (f != NULL && !fval(f, FFL_NPC)) {
const char *pass = getstrtoken(); const char *pass = getstrtoken();
if (!checkpasswd(f, (const char *)pass, true)) { if (!checkpasswd(f, (const char *)pass, true)) {
@ -499,7 +499,6 @@ static int resolve_owner(variant id, void *address)
f = findfaction(id.i); f = findfaction(id.i);
if (f == NULL) { if (f == NULL) {
log_error("region has an invalid owner (%s)\n", itoa36(id.i)); log_error("region has an invalid owner (%s)\n", itoa36(id.i));
f = get_monsters();
} }
} }
owner->owner = f; owner->owner = f;
@ -1292,6 +1291,7 @@ faction *readfaction(struct gamedata * data)
READ_STR(data->store, name, sizeof(name)); READ_STR(data->store, name, sizeof(name));
f->locale = get_locale(name); f->locale = get_locale(name);
if (!f->locale) f->locale = default_locale;
READ_INT(data->store, &f->lastorders); READ_INT(data->store, &f->lastorders);
READ_INT(data->store, &f->age); READ_INT(data->store, &f->age);
READ_STR(data->store, name, sizeof(name)); READ_STR(data->store, name, sizeof(name));
@ -1338,9 +1338,10 @@ faction *readfaction(struct gamedata * data)
READ_INT(data->store, &n); READ_INT(data->store, &n);
f->options = n; f->options = n;
if ((n & (want(O_REPORT) | want(O_COMPUTER))) == 0 && !is_monsters(f)) { n = want(O_REPORT) | want(O_COMPUTER);
if ((f->options & n) == 0) {
/* Kein Report eingestellt, Fehler */ /* Kein Report eingestellt, Fehler */
f->options |= (want(O_REPORT) | want(O_ZUGVORLAGE)); f->options |= n;
} }
sfp = &f->allies; sfp = &f->allies;
@ -1720,7 +1721,7 @@ int readgame(const char *filename, int backup)
if (mage) { if (mage) {
faction *f = u->faction; faction *f = u->faction;
int skl = effskill(u, SK_MAGIC); int skl = effskill(u, SK_MAGIC);
if (!is_monsters(f) && f->magiegebiet == M_GRAY) { if (!fval(f, FFL_NPC) && f->magiegebiet == M_GRAY) {
log_error("faction %s had magic=gray, fixing (%s)\n", factionname(f), magic_school[mage->magietyp]); log_error("faction %s had magic=gray, fixing (%s)\n", factionname(f), magic_school[mage->magietyp]);
f->magiegebiet = mage->magietyp; f->magiegebiet = mage->magietyp;
} }
@ -1778,9 +1779,8 @@ int readgame(const char *filename, int backup)
return 0; return 0;
} }
static void clear_monster_orders(void) static void clear_npc_orders(faction *f)
{ {
faction *f = get_monsters();
if (f) { if (f) {
unit *u; unit *u;
for (u = f->units; u; u = u->nextF) { for (u = f->units; u; u = u->nextF) {
@ -1804,7 +1804,6 @@ int writegame(const char *filename)
stream strm; stream strm;
FILE *F; FILE *F;
clear_monster_orders();
sprintf(path, "%s/%s", datapath(), filename); sprintf(path, "%s/%s", datapath(), filename);
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
if (access(path, R_OK) == 0) { if (access(path, R_OK) == 0) {
@ -1884,6 +1883,9 @@ int writegame(const char *filename)
log_printf(stdout, " - Schreibe %d Parteien...\n", n); log_printf(stdout, " - Schreibe %d Parteien...\n", n);
for (f = factions; f; f = f->next) { for (f = factions; f; f = f->next) {
if (fval(f, FFL_NPC)) {
clear_npc_orders(f);
}
writefaction(&gdata, f); writefaction(&gdata, f);
WRITE_SECTION(&store); WRITE_SECTION(&store);
} }

View File

@ -34,6 +34,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <util/log.h> #include <util/log.h>
#include <util/rng.h> #include <util/rng.h>
#include "monster.h"
/* libc includes */ /* libc includes */
#include <assert.h> #include <assert.h>

View File

@ -362,14 +362,6 @@ int gift_items(unit * u, int flags)
return retval; return retval;
} }
void make_zombie(unit * u)
{
u_setfaction(u, get_monsters());
scale_number(u, 1);
u_setrace(u, get_race(RC_ZOMBIE));
u->irace = NULL;
}
/** remove the unit from the list of active units. /** remove the unit from the list of active units.
* the unit is not actually freed, because there may still be references * the unit is not actually freed, because there may still be references
* dangling to it (from messages, for example). To free all removed units, * dangling to it (from messages, for example). To free all removed units,
@ -733,7 +725,7 @@ void set_level(unit * u, skill_t sk, int value)
{ {
skill *sv = u->skills; skill *sv = u->skills;
assert(sk != SK_MAGIC || !u->faction || u->number == 1 || is_monsters(u->faction)); assert(sk != SK_MAGIC || !u->faction || u->number == 1 || fval(u->faction, FFL_NPC));
if (!skill_enabled(sk)) if (!skill_enabled(sk))
return; return;
@ -1197,7 +1189,7 @@ skill *add_skill(unit * u, skill_t id)
sv->weeks = 1; sv->weeks = 1;
sv->old = 0; sv->old = 0;
sv->id = id; sv->id = id;
if (id == SK_MAGIC && u->faction && !is_monsters(u->faction)) { if (id == SK_MAGIC && u->faction && !fval(u->faction, FFL_NPC)) {
assert(u->number==1 && max_magicians(u->faction) >= u->number); assert(u->number==1 && max_magicians(u->faction) >= u->number);
} }
return sv; return sv;

View File

@ -993,31 +993,35 @@ static bool CheckOverload(void)
return value; return value;
} }
int enter_ship(unit * u, struct order *ord, int id, int report) int enter_ship(unit * u, struct order *ord, int id, bool report)
{ {
region *r = u->region; region *r = u->region;
ship *sh; ship *sh;
const race * rc = u_race(u);
/* Muss abgefangen werden, sonst koennten Schwimmer an /* Muss abgefangen werden, sonst koennten Schwimmer an
* Bord von Schiffen an Land gelangen. */ * Bord von Schiffen an Land gelangen. */
if (!fval(u_race(u), RCF_CANSAIL) || (!fval(u_race(u), RCF_WALK) if (!(rc->flags & (RCF_CANSAIL|RCF_WALK|RCF_FLY))) {
&& !fval(u_race(u), RCF_FLY))) { if (report) {
cmistake(u, ord, 233, MSG_MOVE); cmistake(u, ord, 233, MSG_MOVE);
}
return 0; return 0;
} }
sh = findship(id); sh = findship(id);
if (sh == NULL || sh->region != r) { if (sh == NULL || sh->region != r) {
if (report) if (report) {
cmistake(u, ord, 20, MSG_MOVE); cmistake(u, ord, 20, MSG_MOVE);
}
return 0; return 0;
} }
if (sh == u->ship) { if (sh == u->ship) {
return 1; return 1;
} }
if (!mayboard(u, sh)) { if (!mayboard(u, sh)) {
if (report) if (report) {
cmistake(u, ord, 34, MSG_MOVE); cmistake(u, ord, 34, MSG_MOVE);
}
return 0; return 0;
} }
if (CheckOverload()) { if (CheckOverload()) {
@ -1054,7 +1058,7 @@ int enter_ship(unit * u, struct order *ord, int id, int report)
return 0; return 0;
} }
int enter_building(unit * u, order * ord, int id, int report) int enter_building(unit * u, order * ord, int id, bool report)
{ {
region *r = u->region; region *r = u->region;
building *b; building *b;

View File

@ -44,15 +44,16 @@ extern "C" {
void get_food(struct region * r); void get_food(struct region * r);
int can_contact(const struct region *r, const struct unit *u, const struct unit *u2); int can_contact(const struct region *r, const struct unit *u, const struct unit *u2);
/* eressea-specific. put somewhere else, please. */ int enter_building(struct unit *u, struct order *ord, int id, bool report);
int enter_ship(struct unit *u, struct order *ord, int id, bool report);
/* eressea-specific. put somewhere else, please. */
void processorders(void); void processorders(void);
extern struct attrib_type at_germs; extern struct attrib_type at_germs;
extern int dropouts[2]; extern int dropouts[2];
extern int *age; extern int *age;
extern int enter_building(struct unit *u, struct order *ord, int id, int report);
extern int enter_ship(struct unit *u, struct order *ord, int id, int report);
extern void new_units(void); extern void new_units(void);
extern void defaultorders(void); extern void defaultorders(void);

View File

@ -117,6 +117,85 @@ static void test_contact(CuTest * tc)
CuAssertIntEquals(tc, 1, can_contact(r, u1, u2)); CuAssertIntEquals(tc, 1, can_contact(r, u1, u2));
} }
static void test_enter_building(CuTest * tc)
{
unit *u;
region *r;
building *b;
race * rc;
test_cleanup();
test_create_world();
r = findregion(0, 0);
rc = rc_get_or_create("human");
u = test_create_unit(test_create_faction(rc), r);
b = test_create_building(r, bt_get_or_create("castle"));
rc->flags = RCF_WALK;
u->building = 0;
CuAssertIntEquals(tc, 1, enter_building(u, NULL, b->no, false));
CuAssertPtrEquals(tc, b, u->building);
rc->flags = RCF_FLY;
u->building = 0;
CuAssertIntEquals(tc, 1, enter_building(u, NULL, b->no, false));
CuAssertPtrEquals(tc, b, u->building);
rc->flags = RCF_SWIM;
u->building = 0;
CuAssertIntEquals(tc, 0, enter_building(u, NULL, b->no, false));
CuAssertPtrEquals(tc, 0, u->building);
CuAssertPtrEquals(tc, 0, u->faction->msgs);
CuAssertIntEquals(tc, 0, enter_building(u, NULL, b->no, true));
CuAssertPtrNotNull(tc, u->faction->msgs);
test_cleanup();
}
static void test_enter_ship(CuTest * tc)
{
unit *u;
region *r;
ship *sh;
race * rc;
test_cleanup();
test_create_world();
r = findregion(0, 0);
rc = rc_get_or_create("human");
u = test_create_unit(test_create_faction(rc), r);
sh = test_create_ship(r, st_get_or_create("boat"));
rc->flags = RCF_WALK;
u->ship = 0;
CuAssertIntEquals(tc, 1, enter_ship(u, NULL, sh->no, false));
CuAssertPtrEquals(tc, sh, u->ship);
rc->flags = RCF_FLY;
u->ship = 0;
CuAssertIntEquals(tc, 1, enter_ship(u, NULL, sh->no, false));
CuAssertPtrEquals(tc, sh, u->ship);
rc->flags = RCF_CANSAIL;
u->ship = 0;
CuAssertIntEquals(tc, 1, enter_ship(u, NULL, sh->no, false));
CuAssertPtrEquals(tc, sh, u->ship);
rc->flags = RCF_SWIM;
u->ship = 0;
CuAssertIntEquals(tc, 0, enter_ship(u, NULL, sh->no, false));
CuAssertPtrEquals(tc, 0, u->ship);
CuAssertPtrEquals(tc, 0, u->faction->msgs);
CuAssertIntEquals(tc, 0, enter_ship(u, NULL, sh->no, true));
CuAssertPtrNotNull(tc, u->faction->msgs);
test_cleanup();
}
static void test_fishing_feeds_2_people(CuTest * tc) static void test_fishing_feeds_2_people(CuTest * tc)
{ {
const resource_type *rtype; const resource_type *rtype;
@ -445,5 +524,7 @@ CuSuite *get_laws_suite(void)
SUITE_ADD_TEST(suite, test_new_units); SUITE_ADD_TEST(suite, test_new_units);
SUITE_ADD_TEST(suite, test_cannot_create_unit_above_limit); SUITE_ADD_TEST(suite, test_cannot_create_unit_above_limit);
SUITE_ADD_TEST(suite, test_contact); SUITE_ADD_TEST(suite, test_contact);
SUITE_ADD_TEST(suite, test_enter_building);
SUITE_ADD_TEST(suite, test_enter_ship);
return suite; return suite;
} }

View File

@ -404,7 +404,7 @@ get_island_info(region * root, int *size_p, int *inhabited_p, int *maxage_p)
if (r->units) { if (r->units) {
unit *u; unit *u;
for (u = r->units; u; u = u->next) { for (u = r->units; u; u = u->next) {
if (!is_monsters(u->faction) && u->faction->age > maxage) { if (!fval(u->faction, FFL_NOIDLEOUT) && u->faction->age > maxage) {
maxage = u->faction->age; maxage = u->faction->age;
} }
} }

View File

@ -46,7 +46,7 @@ int average_score_of_age(int age, int a)
int sum = 0, count = 0; int sum = 0, count = 0;
for (f = factions; f; f = f->next) { for (f = factions; f; f = f->next) {
if (!is_monsters(f) && f->age <= age + a if (!fval(f, FFL_NPC) && f->age <= age + a
&& f->age >= age - a && f->race != get_race(RC_TEMPLATE)) { && f->age >= age - a && f->race != get_race(RC_TEMPLATE)) {
sum += f->score; sum += f->score;
count++; count++;
@ -143,7 +143,7 @@ void score(void)
for (fc = factions; fc; fc = fc->next) { for (fc = factions; fc; fc = fc->next) {
fc->score = fc->score / 5; fc->score = fc->score / 5;
if (!is_monsters(fc) && fc->race != get_race(RC_TEMPLATE)) { if (!fval(fc, FFL_NPC) && fc->race != get_race(RC_TEMPLATE)) {
allscores += fc->score; allscores += fc->score;
} }
} }

View File

@ -216,3 +216,30 @@ void monster_kills_peasants(unit * u)
} }
} }
} }
faction *get_or_create_monsters(void)
{
faction *f = findfaction(MONSTER_ID);
if (!f) {
const race *rc = rc_get_or_create("dragon");
const char *email = get_param(global.parameters, "monster.email");
f = addfaction(email ? email : "noreply@eressea.de", NULL, rc, default_locale, 0);
renumber_faction(f, MONSTER_ID);
faction_setname(f, "Monster");
fset(f, FFL_NPC | FFL_NOIDLEOUT);
}
return f;
}
faction *get_monsters(void) {
return get_or_create_monsters();
}
void make_zombie(unit * u)
{
u_setfaction(u, get_monsters());
scale_number(u, 1);
u_setrace(u, get_race(RC_ZOMBIE));
u->irace = NULL;
}

View File

@ -22,8 +22,16 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
extern "C" { extern "C" {
#endif #endif
#define MONSTER_ID 666
void monster_kills_peasants(struct unit *u); void monster_kills_peasants(struct unit *u);
bool monster_is_waiting(const struct unit *u); bool monster_is_waiting(const struct unit *u);
struct faction *get_monsters(void);
struct faction *get_or_create_monsters(void);
void make_zombie(struct unit * u);
#define is_monsters(f) (f && fval(f, FFL_NPC) && f==get_monsters())
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -24,6 +24,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "reports.h" #include "reports.h"
#include "alchemy.h" #include "alchemy.h"
#include "vortex.h" #include "vortex.h"
#include "monster.h"
#include <kernel/build.h> #include <kernel/build.h>
#include <kernel/building.h> #include <kernel/building.h>

View File

@ -24,6 +24,8 @@
/* util iclude */ /* util iclude */
#include <util/rng.h> #include <util/rng.h>
#include "monster.h"
/* libc includes */ /* libc includes */
#include <stdlib.h> #include <stdlib.h>

View File

@ -1139,13 +1139,6 @@ static void demon_skillchanges(void)
while (weeks--) while (weeks--)
learn_skill(u, sv->id, 1.0); learn_skill(u, sv->id, 1.0);
} }
if (sv->old > sv->level) {
if (verbosity >= 3) {
log_printf(stdout, "%s dropped from %u to %u:%u in %s\n",
unitname(u), sv->old, sv->level, sv->weeks, skillname(sv->id,
NULL));
}
}
} }
++sv; ++sv;
} }

View File

@ -23,6 +23,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "reports.h" #include "reports.h"
#include "laws.h" #include "laws.h"
#include "monster.h"
/* modules includes */ /* modules includes */
#include <modules/score.h> #include <modules/score.h>
@ -1418,7 +1420,7 @@ static void durchreisende(FILE * F, const region * r, const faction * f)
if (cansee_durchgezogen(f, r, u, 0)) { if (cansee_durchgezogen(f, r, u, 0)) {
++counter; ++counter;
if (u->ship != NULL) { if (u->ship != NULL) {
#ifdef GERMAN_FLUFF_DISABLED #ifdef GERMAN_FLUFF_ENABLED
if (counter == 1) { if (counter == 1) {
bytes = (int)strlcpy(bufp, "Die ", size); bytes = (int)strlcpy(bufp, "Die ", size);
} }

View File

@ -1204,6 +1204,8 @@ static void get_seen_interval(report_context * ctx)
/* this is required to find the neighbour regions of the ones we are in, /* this is required to find the neighbour regions of the ones we are in,
* which may well be outside of [firstregion, lastregion) */ * which may well be outside of [firstregion, lastregion) */
int i; int i;
assert(ctx->seen);
for (i = 0; i != MAXSEEHASH; ++i) { for (i = 0; i != MAXSEEHASH; ++i) {
seen_region *sr = ctx->seen[i]; seen_region *sr = ctx->seen[i];
while (sr != NULL) { while (sr != NULL) {
@ -1643,7 +1645,9 @@ int write_reports(faction * f, time_t ltime)
ctx.last = lastregion(f); ctx.last = lastregion(f);
ctx.addresses = NULL; ctx.addresses = NULL;
ctx.userdata = NULL; ctx.userdata = NULL;
get_seen_interval(&ctx); if (ctx.seen) {
get_seen_interval(&ctx);
}
get_addresses(&ctx); get_addresses(&ctx);
_mkdir(reportpath()); _mkdir(reportpath());
do { do {
@ -1679,7 +1683,9 @@ int write_reports(faction * f, time_t ltime)
log_warning("No report for faction %s!", factionid(f)); log_warning("No report for faction %s!", factionid(f));
} }
ql_free(ctx.addresses); ql_free(ctx.addresses);
seen_done(ctx.seen); if (ctx.seen) {
seen_done(ctx.seen);
}
return 0; return 0;
} }
@ -1688,7 +1694,7 @@ static void nmr_warnings(void)
faction *f, *fa; faction *f, *fa;
#define FRIEND (HELP_GUARD|HELP_MONEY) #define FRIEND (HELP_GUARD|HELP_MONEY)
for (f = factions; f; f = f->next) { for (f = factions; f; f = f->next) {
if (!is_monsters(f) && (turn - f->lastorders) >= 2) { if (!fval(f, FFL_NOIDLEOUT) && (turn - f->lastorders) >= 2) {
message *msg = NULL; message *msg = NULL;
for (fa = factions; fa; fa = fa->next) { for (fa = factions; fa; fa = fa->next) {
int warn = 0; int warn = 0;

View File

@ -20,6 +20,7 @@
#include "laws.h" #include "laws.h"
#include "spells.h" #include "spells.h"
#include "direction.h" #include "direction.h"
#include "monster.h"
#include <spells/borders.h> #include <spells/borders.h>
#include <spells/buildingcurse.h> #include <spells/buildingcurse.h>

View File

@ -28,6 +28,8 @@
#include <util/resolve.h> #include <util/resolve.h>
#include <util/umlaut.h> #include <util/umlaut.h>
#include "monster.h"
#include <storage.h> #include <storage.h>
#include <triggers/createcurse.h> #include <triggers/createcurse.h>

View File

@ -14,6 +14,7 @@
#include "summary.h" #include "summary.h"
#include "laws.h" #include "laws.h"
#include "monster.h"
#include <kernel/alliance.h> #include <kernel/alliance.h>
#include <kernel/calendar.h> #include <kernel/calendar.h>
@ -88,7 +89,7 @@ int update_nmrs(void)
if (fval(f, FFL_ISNEW)) { if (fval(f, FFL_ISNEW)) {
++newplayers; ++newplayers;
} }
else if (!is_monsters(f) && f->alive) { else if (!fval(f, FFL_NOIDLEOUT) && f->alive) {
int nmr = turn - f->lastorders + 1; int nmr = turn - f->lastorders + 1;
if (nmr < 0 || nmr > NMRTimeout()) { if (nmr < 0 || nmr > NMRTimeout()) {
log_error("faction %s has %d NMRS\n", factionid(f), nmr); log_error("faction %s has %d NMRS\n", factionid(f), nmr);

View File

@ -15,6 +15,7 @@
#include "alchemy.h" #include "alchemy.h"
#include "economy.h" #include "economy.h"
#include "monster.h"
#include <assert.h> #include <assert.h>