Merge pull request #745 from ennorehling/develop

Orders in temporary database, bugfixes, tests. For future 3.15 release.
This commit is contained in:
Enno Rehling 2017-12-09 21:30:31 +01:00 committed by GitHub
commit ffc39a303f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
77 changed files with 669 additions and 1331 deletions

View File

@ -14,6 +14,7 @@ addons:
- libxml2-dev
- valgrind
- cppcheck
- shellcheck
os:
- linux
notifications:

6
process/Makefile Normal file
View File

@ -0,0 +1,6 @@
SCRIPTS=compress.sh send-bz2-report send-zip-report create-orders \
run-turn sendreports.sh
IGNORE=sendreport.sh
shellcheck: $(SCRIPTS)
shellcheck $(SCRIPTS)

View File

@ -1,24 +1,25 @@
#!/bin/bash
if [ -z $ERESSEA ]; then
if [ -z "$ERESSEA" ]; then
echo "You need to define the \$ERESSEA environment variable to run $0"
exit -2
fi
GAME=$ERESSEA/game-$1
GAME_NAME=$(grep -w name $GAME/eressea.ini | sed 's/.*=\s*//')
GAME="$ERESSEA/game-$1"
GAME_NAME=$(grep -w name "$GAME/eressea.ini" | sed 's/.*=\s*//')
TURN=$2
if [ -z $TURN ]
if [ -z "$TURN" ]
then
TURN=`cat $GAME/turn`
TURN=$(cat "$GAME/turn")
fi
if [ ! -d $GAME/reports ]; then
if [ ! -d "$GAME/reports" ]; then
echo "cannot find reports directory in $GAME"
exit -1
fi
cd $GAME/reports
$ERESSEA/server/bin/compress.py $TURN "$GAME_NAME"
cd -
cd "$GAME/reports" || exit
"$ERESSEA/server/bin/compress.py" "$TURN" "$GAME_NAME"
cd - || exit

View File

@ -3,24 +3,25 @@
GAME=$1
TURN=$2
if [ ! -d $ERESSEA/game-$GAME ] ; then
if [ ! -d "$ERESSEA/game-$GAME" ] ; then
echo "No such game: $GAME"
exit 1
fi
cd $ERESSEA/game-$GAME
cd "$ERESSEA/game-$GAME" || exit
if [ -d orders.dir.$TURN ]; then
if [ -d "orders.dir.$TURN" ]; then
echo "orders.dir.$TURN already exists"
else
mv orders.dir orders.dir.$TURN
mv orders.dir "orders.dir.$TURN"
mkdir -p orders.dir
fi
ls -1rt orders.dir.$TURN/turn-* | xargs cat > orders.$TURN
#shellcheck disable=2011
ls -1rt "orders.dir.$TURN/turn-*" | xargs cat > "orders.$TURN"
lockfile -r3 -l120 orders.queue.lock
if [ -e orders.queue ] ; then
mv orders.queue orders.dir.$TURN/orders.queue
mv orders.queue "orders.dir.$TURN/orders.queue"
fi
rm -f orders.queue.lock

View File

@ -1,17 +1,17 @@
#!/bin/sh
GAME=$1
TURN=$2
GAME="$1"
TURN="$2"
if [ ! -d $ERESSEA/game-$GAME ] ; then
if [ ! -d "$ERESSEA/game-$GAME" ] ; then
echo "No such game: $GAME"
exit 1
fi
cd $ERESSEA/game-$GAME
cd "$ERESSEA/game-$GAME" || exit
echo "running turn $TURN, game $GAME"
$ERESSEA/server/bin/eressea -v3 -t $TURN run-turn.lua
"$ERESSEA/server/bin/eressea" -t "$TURN" run-turn.lua
mkdir -p log
ln -f eressea.log log/eressea.log.$TURN
ln -f eressea.log "log/eressea.log.$TURN"

View File

@ -1,13 +1,12 @@
#!/bin/bash
if [ -z $ERESSEA ]; then
ERESSEA=`echo $PWD |sed -e 's/\/game.*//'`
if [ -z "$ERESSEA" ]; then
ERESSEA=$(echo "$PWD" |sed -e 's/\/game.*//')
echo "Assuming that ERESSEA=$ERESSEA"
fi
if [ ! -f reports.txt ]; then
echo "need to run $0 from the report direcory"
exit -2
fi
source $HOME/bin/functions.sh
TEMPLATE=report-mail.txt
if [ "$1" == "-Lde" ]
@ -26,4 +25,6 @@ addr=$1
subj=$2
shift 2
cat $ERESSEA/server/etc/$TEMPLATE | mutt -F $ERESSEA/etc/muttrc -s "$subj" -a $* -- $addr
mutt -F "$ERESSEA/etc/muttrc" -s "$subj" -a "$@" -- "$addr" \
< "$ERESSEA/server/etc/$TEMPLATE"

View File

@ -1,6 +1,7 @@
#!/bin/bash
if [ -z $ERESSEA ]; then
ERESSEA=`echo $PWD |sed -e 's/\/game.*//'`
if [ -z "$ERESSEA" ]; then
ERESSEA=$(echo "$PWD" |sed -e 's/\/game.*//')
echo "Assuming that ERESSEA=$ERESSEA"
fi
if [ ! -f reports.txt ]; then
@ -9,7 +10,7 @@ if [ ! -f reports.txt ]; then
fi
PWD=$(pwd)
GAME=$(dirname $PWD)
GAME=$(dirname "$PWD")
TEMPLATE=report-mail.txt
if [ "$1" == "-Lde" ]
@ -24,13 +25,13 @@ then
shift
fi
if [ -e $GAME/$TEMPLATE ]; then
TEMPLATE=$GAME/$TEMPLATE
if [ -e "$GAME/$TEMPLATE" ]; then
TEMPLATE="$GAME/$TEMPLATE"
else
TEMPLATE=$ERESSEA/server/etc/$TEMPLATE
TEMPLATE="$ERESSEA/server/etc/$TEMPLATE"
fi
if [ ! -e $TEMPLATE ]; then
if [ ! -e "$TEMPLATE" ]; then
echo "no such email template: $TEMPLATE"
exit -3
fi
@ -42,8 +43,7 @@ done
addr=$1
subject=$2
shift 2
mutt -F $ERESSEA/etc/muttrc -s "$subject" -a $* -- $addr < $TEMPLATE
if [ $? -ne 0 ] ; then
echo "Sending failed for email/report: $2/$3"
fi
mutt -F "$ERESSEA/etc/muttrc" -s "$subject" -a "$@" -- "$addr" \
< "$TEMPLATE" || echo "Sending failed for email/report: $2/$3"

View File

@ -3,30 +3,23 @@
##
## Prepare the report
if [ -z $ERESSEA ]; then
if [ -z "$ERESSEA" ]; then
echo "You have to define the \$ERESSEA environment variable to run $0"
exit -2
fi
source $HOME/bin/functions.sh
if [ ! -z $1 ]; then
GAME=$ERESSEA/game-$1
if [ ! -z "$1" ]; then
GAME="$ERESSEA/game-$1"
else
GAME=$ERESSEA
fi
cd $GAME/reports || abort "could not chdir to reports directory"
cd "$GAME/reports" || exit
for REPORT in *.sh
do
echo -n "Sending "
basename $REPORT .sh
bash $REPORT
basename "$REPORT" .sh
bash "$REPORT"
done
cd -
if [ -e $GAME/ages.sh ]; then
cd $GAME
./ages.sh
cd -
fi
cd - || exit

View File

@ -19,11 +19,12 @@ cd tests
set -e
[ -z $BUILD ] && BUILD=Debug ; export BUILD
s/cmake-init
cppcheck --version
cppcheck --quiet -Isrc -Iclibs -Istorage -IcJSON --error-exitcode=1 src
s/build
cd process
make
cd $ROOT
inifile
cppcheck --version
cppcheck --quiet --error-exitcode=1 src
s/runtests -V
integration_tests

View File

@ -121,9 +121,11 @@ function test_fleeing_units_can_be_transported()
u1.number = 100
u1:add_order("ATTACKIEREN " .. itoa36(u2.id))
u2.number = 100
u2.name = 'Passagier'
u2:add_order("FAHREN " .. itoa36(u3.id))
u2:add_order("KAEMPFE FLIEHE")
u3.number = 100
u3.name = 'Transporter'
u3:add_order("KAEMPFE FLIEHE")
u3:add_order("TRANSPORT " .. itoa36(u2.id))
u3:add_order("NACH O ")
@ -131,8 +133,8 @@ function test_fleeing_units_can_be_transported()
u3:add_item("horse", u2.number)
u3:add_order("KAEMPFE FLIEHE")
process_orders()
assert_equal(u3.region.id, r1.id, "transporter did not move")
assert_equal(u2.region.id, r1.id, "transported unit did not move")
assert_equal(u3.region, r1, "transporter did not move")
assert_equal(u2.region, r1, "transported unit did not move")
end
function test_plane()

View File

@ -10,6 +10,7 @@ require 'tests.e2.destroy'
require 'tests.e2.guard'
require 'tests.e2.stealth'
require 'tests.e2.items'
-- require 'tests.e2.ships'
require 'tests.items'
require 'tests.economy'
require 'tests.orders'

View File

@ -76,3 +76,29 @@ function test_dwarf_mining_bonus()
assert_equal(20, u:get_item('iron'))
assert_equal(84, r:get_resource('iron'))
end
function test_build_boat_low_skill()
local r = region.create(0, 0, "plain")
local f = faction.create("human", "build@example.com")
local u = unit.create(f, r, 1)
u:set_skill("shipcraft", 3) -- humans get +1
u:add_item("log", 10)
u:add_order("MACHE BOOT")
process_orders()
assert_not_equal(nil, u.ship)
assert_equal(4, u.ship.size)
assert_equal(6, u:get_item('log'))
end
function test_build_boat_high_skill()
local r = region.create(0, 0, "plain")
local f = faction.create("human", "build@example.com")
local u = unit.create(f, r, 1)
u:set_skill("shipcraft", 5) -- humans get +1
u:add_item("log", 10)
u:add_order("MACHE BOOT")
process_orders()
assert_not_equal(nil, u.ship)
assert_equal(5, u.ship.size)
assert_equal(5, u:get_item('log'))
end

View File

@ -10,7 +10,9 @@ end
function test_ship_requires_skill()
local r1 = region.create(0, 0, "ocean")
assert_not_nil(r1)
local r2 = region.create(1, 0, "ocean")
assert_not_nil(r2)
local f = faction.create("human", "fake@eressea.de", "de")
local u1 = unit.create(f, r1, 1)
u1.name = "fake"
@ -22,7 +24,7 @@ function test_ship_requires_skill()
assert_equal(r1, u1.region)
end
function no_test_ship_happy_case()
function test_ship_happy_case()
local r1 = region.create(0, 0, "ocean")
local r2 = region.create(1, 0, "ocean")
local f = faction.create("human", "hodor@eressea.de", "de")
@ -39,4 +41,3 @@ function no_test_ship_happy_case()
assert_equal(r2, u1.region)
assert_equal(r2, u2.region)
end

View File

@ -9,6 +9,7 @@ function setup()
eressea.settings.set("NewbieImmunity", "0")
eressea.settings.set("rules.food.flags", "4")
eressea.settings.set("rules.peasants.growth.factor", "0")
eressea.settings.set("magic.fumble.enable", "0")
end
function test_shapeshift()

View File

@ -81,3 +81,25 @@ function test_create_dreameye()
assert_equal(amax - 5, u.aura_max)
end
function test_appeasement()
local u1, u2, r1, r2, uno
r1 = region.create(0, 0, 'plain')
r2 = region.create(1, 0, 'plain')
u2 = unit.create(faction.create('human'), r1, 1)
u2.race = 'elf'
u2.name = 'Angsthase'
u2.magic = 'gwyrrd'
u2:set_skill('magic', 5)
u2.aura = 10
u2:add_spell('appeasement')
u2:add_order('NACH O')
u2:add_order('KAMPFZAUBER STUFE 1 Friedenslied')
uno = u2.id
u1 = unit.create(faction.create('human'), r1, 1)
u1:set_skill('polearm', 5)
u1:add_order('ATTACKIERE ' .. itoa36(uno))
process_orders()
u2 = get_unit(uno)
assert_not_nil(u2)
assert_equal(r2, u2.region)
end

View File

@ -109,6 +109,7 @@ set (ERESSEA_SRC
json.c
creport.c
report.c
steal.c
economy.c
give.c
items.c
@ -140,7 +141,6 @@ set (ERESSEA_SRC
set(SERVER_SRC
main.c
building_action.c
console.c
helpers.c
bind_tolua.c
@ -293,5 +293,4 @@ include_directories (${LIBXML2_INCLUDE_DIR})
target_link_libraries(eressea ${LIBXML2_LIBRARIES})
target_link_libraries(convert ${LIBXML2_LIBRARIES})
target_link_libraries(test_eressea ${LIBXML2_LIBRARIES})
add_definitions(-DUSE_LIBXML2)
endif (LIBXML2_FOUND)

View File

@ -41,11 +41,7 @@ extern "C" {
/* Stufe 3 */
P_WISE, /* 6 */
P_FOOL,
#ifdef INSECT_POTION
P_WARMTH,
#else
P_STEEL,
#endif
P_HORSE,
P_BERSERK, /* 10 */
/* Stufe 4 */

View File

@ -1009,7 +1009,7 @@ int natural_armor(unit * du)
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;
int modifier = 0;
if (wtype != NULL) {
if (fval(u_race(du), RCF_DRAGON)) {
static int cache;
@ -1022,6 +1022,7 @@ static int rc_specialdamage(const unit *au, const unit *du, const struct weapon_
}
}
if (wtype->modifiers != NULL) {
int m;
for (m = 0; wtype->modifiers[m].value; ++m) {
/* weapon damage for this weapon, possibly by race */
if (wtype->modifiers[m].flags & WMF_DAMAGE) {
@ -2009,11 +2010,6 @@ void dazzle(battle * b, troop * td)
{
UNUSED_ARG(b);
/* Nicht kumulativ ! */
#ifdef TODO_RUNESWORD
if (td->fighter->weapon[WP_RUNESWORD].count > td->index) {
return;
}
#endif
if (td->fighter->person[td->index].flags & (FL_COURAGE|FL_DAZZLED)) {
return;
}
@ -2285,21 +2281,6 @@ void do_attack(fighter * af)
}
}
void do_regenerate(fighter * af)
{
troop ta;
unit *au = af->unit;
ta.fighter = af;
ta.index = af->fighting;
while (ta.index--) {
struct person *p = af->person + ta.index;
p->hp += effskill(au, SK_STAMINA, 0);
p->hp = MIN(unit_max_hp(au), p->hp);
}
}
static void add_tactics(tactics * ta, fighter * fig, int value)
{
if (value == 0 || value < ta->value)
@ -2655,14 +2636,14 @@ static void aftermath(battle * b)
}
}
snumber += du->number;
if (relevant) {
flags = UFL_LONGACTION | UFL_NOTMOVING;
if (du->status == ST_FLEE) {
flags -= UFL_NOTMOVING;
}
}
if (df->alive == 0) {
flags |= UFL_DEAD;
flags = UFL_DEAD;
}
else if (relevant) {
flags = UFL_LONGACTION;
if ((du->status != ST_FLEE) && (df->run.hp <= 0)) {
flags |= UFL_NOTMOVING;
}
}
if (flags) {
fset(du, flags);

View File

@ -45,28 +45,35 @@ int tolua_shiplist_next(lua_State * L)
static int tolua_ship_get_id(lua_State * L)
{
ship *self = (ship *)tolua_tousertype(L, 1, 0);
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
lua_pushinteger(L, self->no);
return 1;
}
static int tolua_ship_get_name(lua_State * L)
{
ship *self = (ship *)tolua_tousertype(L, 1, 0);
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
tolua_pushstring(L, ship_getname(self));
return 1;
}
static int tolua_ship_get_size(lua_State * L)
{
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
lua_pushinteger(L, self->size);
return 1;
}
static int tolua_ship_get_display(lua_State * L)
{
ship *self = (ship *)tolua_tousertype(L, 1, 0);
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
tolua_pushstring(L, self->display);
return 1;
}
static int tolua_ship_get_region(lua_State * L)
{
ship *self = (ship *)tolua_tousertype(L, 1, 0);
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
if (self) {
tolua_pushusertype(L, self->region, TOLUA_CAST "region");
return 1;
@ -76,8 +83,8 @@ static int tolua_ship_get_region(lua_State * L)
static int tolua_ship_set_region(lua_State * L)
{
ship *self = (ship *)tolua_tousertype(L, 1, 0);
region *r = (region *)tolua_tousertype(L, 1, 0);
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
region *r = (region *)tolua_tousertype(L, 2, NULL);
if (self) {
move_ship(self, self->region, r, NULL);
}
@ -86,22 +93,29 @@ static int tolua_ship_set_region(lua_State * L)
static int tolua_ship_set_name(lua_State * L)
{
ship *self = (ship *)tolua_tousertype(L, 1, 0);
ship_setname(self, tolua_tostring(L, 2, 0));
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
ship_setname(self, tolua_tostring(L, 2, NULL));
return 0;
}
static int tolua_ship_set_size(lua_State * L)
{
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
self->size = lua_tointeger(L, 2);
return 0;
}
static int tolua_ship_set_display(lua_State * L)
{
ship *self = (ship *)tolua_tousertype(L, 1, 0);
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
free(self->display);
self->display = strdup(tolua_tostring(L, 2, 0));
self->display = strdup(tolua_tostring(L, 2, NULL));
return 0;
}
static int tolua_ship_get_units(lua_State * L)
{
ship *self = (ship *)tolua_tousertype(L, 1, 0);
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
unit **unit_ptr = (unit **)lua_newuserdata(L, sizeof(unit *));
unit *u = self->region->units;
@ -118,8 +132,8 @@ static int tolua_ship_get_units(lua_State * L)
static int tolua_ship_create(lua_State * L)
{
region *r = (region *)tolua_tousertype(L, 1, 0);
const char *sname = tolua_tostring(L, 2, 0);
region *r = (region *)tolua_tousertype(L, 1, NULL);
const char *sname = tolua_tostring(L, 2, NULL);
if (sname) {
const ship_type *stype = st_find(sname);
if (stype) {
@ -138,40 +152,40 @@ static int tolua_ship_create(lua_State * L)
static int
tolua_ship_tostring(lua_State * L)
{
ship *self = (ship *)tolua_tousertype(L, 1, 0);
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
lua_pushstring(L, shipname(self));
return 1;
}
static int tolua_ship_get_flags(lua_State * L)
{
ship *self = (ship *)tolua_tousertype(L, 1, 0);
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
lua_pushinteger(L, self->flags);
return 1;
}
static int tolua_ship_set_flags(lua_State * L)
{
ship *self = (ship *)tolua_tousertype(L, 1, 0);
self->flags = (int)tolua_tonumber(L, 2, 0);
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
self->flags = (int)lua_tointeger(L, 2);
return 0;
}
static int tolua_ship_set_coast(lua_State * L)
{
ship *self = (ship *)tolua_tousertype(L, 1, 0);
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
if (lua_isnil(L, 2)) {
self->coast = NODIRECTION;
}
else if (lua_isnumber(L, 2)) {
self->coast = (direction_t)tolua_tonumber(L, 2, 0);
self->coast = (direction_t)lua_tointeger(L, 2);
}
return 0;
}
static int tolua_ship_get_coast(lua_State * L)
{
ship *self = (ship *)tolua_tousertype(L, 1, 0);
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
if (self->coast) {
lua_pushinteger(L, self->coast);
return 1;
@ -181,28 +195,28 @@ static int tolua_ship_get_coast(lua_State * L)
static int tolua_ship_get_type(lua_State * L)
{
ship *self = (ship *)tolua_tousertype(L, 1, 0);
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
tolua_pushstring(L, self->type->_name);
return 1;
}
static int tolua_ship_get_damage(lua_State * L)
{
ship *self = (ship *)tolua_tousertype(L, 1, 0);
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
lua_pushinteger(L, self->damage);
return 1;
}
static int tolua_ship_set_damage(lua_State * L)
{
ship *self = (ship *)tolua_tousertype(L, 1, 0);
self->damage = (int)tolua_tonumber(L, 2, 0);
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
self->damage = (int)lua_tointeger(L, 2);
return 0;
}
static int tolua_ship_get_curse(lua_State *L) {
ship *self = (ship *)tolua_tousertype(L, 1, 0);
const char *name = tolua_tostring(L, 2, 0);
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
const char *name = tolua_tostring(L, 2, NULL);
if (self->attribs) {
curse * c = get_curse(self->attribs, ct_find(name));
if (c) {
@ -214,8 +228,8 @@ static int tolua_ship_get_curse(lua_State *L) {
}
static int tolua_ship_has_attrib(lua_State *L) {
ship *self = (ship *)tolua_tousertype(L, 1, 0);
const char *name = tolua_tostring(L, 2, 0);
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
const char *name = tolua_tostring(L, 2, NULL);
attrib * a = a_find(self->attribs, at_find(name));
lua_pushboolean(L, a != NULL);
return 1;
@ -236,6 +250,8 @@ void tolua_ship_open(lua_State * L)
tolua_variable(L, TOLUA_CAST "id", tolua_ship_get_id, NULL);
tolua_variable(L, TOLUA_CAST "name", tolua_ship_get_name,
tolua_ship_set_name);
tolua_variable(L, TOLUA_CAST "size", tolua_ship_get_size,
tolua_ship_set_size);
tolua_variable(L, TOLUA_CAST "info", tolua_ship_get_display,
tolua_ship_set_display);
tolua_variable(L, TOLUA_CAST "units", tolua_ship_get_units, NULL);

View File

@ -286,7 +286,7 @@ static int tolua_unit_get_magic(lua_State * L)
static void unit_setmagic(unit * u, const char *type)
{
sc_mage *mage = get_mage_depr(u);
sc_mage *mage = get_mage(u);
int mtype;
for (mtype = 0; mtype != MAXMAGIETYP; ++mtype) {
if (strcmp(magic_school[mtype], type) == 0)
@ -763,38 +763,6 @@ static int tolua_unit_get_spells(lua_State * L)
return tolua_selist_push(L, "spellbook", "spell_entry", slist);
}
#ifdef TOLUA_ORDERS_CLOSURE
/* TODO: this requires that the locale for write_order is included in the closure */
static int tolua_orderlist_next(lua_State * L)
{
order **order_ptr = (order **)lua_touserdata(L, lua_upvalueindex(1));
order *ord = *order_ptr;
if (ord != NULL) {
char cmd[8192];
write_order(ord, cmd, sizeof(cmd));
tolua_pushstring(L, cmd);
*order_ptr = ord->next;
return 1;
}
return 0;
}
static int tolua_unit_get_orders(lua_State * L)
{
unit *self = (unit *)tolua_tousertype(L, 1, 0);
order **order_ptr = (order **)lua_newuserdata(L, sizeof(order *));
luaL_getmetatable(L, TOLUA_CAST "order");
lua_setmetatable(L, -2);
*order_ptr = self->orders;
lua_pushcclosure(L, tolua_orderlist_next, 1);
return 1;
}
#endif
static int tolua_unit_get_curse(lua_State *L) {
unit *self = (unit *)tolua_tousertype(L, 1, 0);
const char *name = tolua_tostring(L, 2, 0);
@ -1006,9 +974,6 @@ void tolua_unit_open(lua_State * L)
tolua_function(L, TOLUA_CAST "add_order", tolua_unit_add_order);
tolua_function(L, TOLUA_CAST "clear_orders", tolua_unit_clear_orders);
#ifdef TOLUA_ORDERS_CLOSURE
tolua_variable(L, TOLUA_CAST "orders", tolua_unit_get_orders, 0);
#endif
tolua_function(L, TOLUA_CAST "get_curse", tolua_unit_get_curse);
tolua_function(L, TOLUA_CAST "has_attrib", tolua_unit_has_attrib);

View File

@ -710,7 +710,6 @@ static int config_get_resource(lua_State * L)
lua_settable(L, -3);
}
if (itype->construction) {
int i;
lua_pushstring(L, "build_skill_min");
lua_pushinteger(L, itype->construction->minskill);
lua_settable(L, -3);
@ -718,6 +717,7 @@ static int config_get_resource(lua_State * L)
lua_pushstring(L, skillnames[itype->construction->skill]);
lua_settable(L, -3);
if (itype->construction->materials) {
int i;
lua_pushstring(L, "materials");
lua_newtable(L);
for (i = 0; itype->construction->materials[i].number; ++i) {
@ -774,7 +774,6 @@ static int config_get_btype(lua_State * L)
lua_settable(L, -3);
}
if (btype->construction) {
int i;
lua_pushstring(L, "build_skill_min");
lua_pushinteger(L, btype->construction->minskill);
lua_settable(L, -3);
@ -782,6 +781,7 @@ static int config_get_btype(lua_State * L)
lua_pushstring(L, skillnames[btype->construction->skill]);
lua_settable(L, -3);
if (btype->construction->materials) {
int i;
lua_pushstring(L, "materials");
lua_newtable(L);
for (i = 0; btype->construction->materials[i].number; ++i) {
@ -840,7 +840,6 @@ static int config_get_stype(lua_State * L)
}
}
if (stype->construction) {
int i;
lua_pushstring(L, "build_skill_min");
lua_pushinteger(L, stype->construction->minskill);
lua_settable(L, -3);
@ -848,6 +847,7 @@ static int config_get_stype(lua_State * L)
lua_pushstring(L, skillnames[stype->construction->skill]);
lua_settable(L, -3);
if (stype->construction->materials) {
int i;
lua_pushstring(L, "materials");
lua_newtable(L);
for (i = 0; stype->construction->materials[i].number; ++i) {
@ -922,12 +922,6 @@ int tolua_read_xml(lua_State * L)
return 1;
}
typedef struct event_args {
int hfunction;
int hargs;
const char *sendertype;
} event_args;
static int tolua_report_unit(lua_State * L)
{
char buffer[512];

View File

@ -1,151 +0,0 @@
/*
+-------------------+
| | Enno Rehling <enno@eressea.de>
| Eressea PBEM host | Christian Schlittchen <corwin@amber.kn-bremen.de>
| (c) 1998 - 2008 | Katja Zedel <katze@felidae.kn-bremen.de>
| | Henning Peters <faroul@beyond.kn-bremen.de>
+-------------------+
This program may not be used, modified or distributed
without prior permission by the authors of Eressea.
*/
#include <platform.h>
#include <kernel/config.h>
#include <kernel/building.h>
#include <util/attrib.h>
#include <util/gamedata.h>
#include <util/log.h>
#include <util/resolve.h>
#include <storage.h>
#include <tolua.h>
#include <lua.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
typedef struct building_action {
char *fname;
char *param;
} building_action;
static int lc_age(struct attrib *a, void *owner)
{
building_action *data = (building_action *)a->data.v;
const char *fname = data->fname;
const char *fparam = data->param;
building *b = (building *)owner;
int result = -1;
assert(b != NULL);
if (fname != NULL) {
lua_State *L = (lua_State *)global.vm_state;
lua_getglobal(L, fname);
if (lua_isfunction(L, -1)) {
tolua_pushusertype(L, (void *)b, TOLUA_CAST "building");
if (fparam) {
tolua_pushstring(L, fparam);
}
if (lua_pcall(L, fparam ? 2 : 1, 1, 0) != 0) {
const char *error = lua_tostring(L, -1);
log_error("lc_age(%s) calling '%s': %s.\n", buildingname(b), fname, error);
lua_pop(L, 1);
}
else {
result = (int)lua_tonumber(L, -1);
lua_pop(L, 1);
}
}
else {
log_error("lc_age(%s) calling '%s': not a function.\n", buildingname(b), fname);
lua_pop(L, 1);
}
}
return (result != 0) ? AT_AGE_KEEP : AT_AGE_REMOVE;
}
static const char *NULLSTRING = "(null)";
static void lc_init(struct attrib *a)
{
a->data.v = calloc(1, sizeof(building_action));
}
static void lc_done(struct attrib *a)
{
building_action *data = (building_action *)a->data.v;
if (data->fname)
free(data->fname);
if (data->param)
free(data->param);
free(data);
}
static void lc_write(const struct attrib *a, const void *owner, struct storage *store)
{
building_action *data = (building_action *)a->data.v;
const char *fname = data->fname;
const char *fparam = data->param;
UNUSED_ARG(owner);
WRITE_TOK(store, fname);
WRITE_TOK(store, fparam ? fparam : NULLSTRING);
}
static int lc_read(struct attrib *a, void *owner, gamedata *data)
{
struct storage *store = data->store;
char name[NAMESIZE];
building_action *bd = (building_action *)a->data.v;
building *b = (building *)owner;
int result = 0;
if (data->version < ATTRIBOWNER_VERSION) {
READ_INT(data->store, NULL);
}
READ_TOK(store, name, sizeof(name));
if (strcmp(name, "tunnel_action") == 0) {
/* E2: Weltentor has a new module, doesn't need this any longer */
result = 0;
b = 0;
}
else {
bd->fname = strdup(name);
}
READ_TOK(store, name, sizeof(name));
if (strcmp(name, "tnnL") == 0) {
/* tunnel_action was the old Weltentore, their code has changed. ignore this object */
result = 0;
b = 0;
}
if (strcmp(name, NULLSTRING) == 0)
bd->param = 0;
else {
bd->param = strdup(name);
}
if (result == 0 && !b) {
return AT_READ_FAIL;
}
return AT_READ_OK;
}
attrib_type at_building_action = {
"lcbuilding",
lc_init, lc_done,
lc_age,
lc_write, lc_read
};
void building_addaction(building * b, const char *fname, const char *param)
{
attrib *a = a_add(&b->attribs, a_new(&at_building_action));
building_action *data = (building_action *)a->data.v;
data->fname = strdup(fname);
if (param) {
data->param = strdup(param);
}
}

View File

@ -1,10 +1,8 @@
#include <platform.h>
#ifdef USE_LIBXML2
#include <kernel/xmlreader.h>
#include <util/xml.h>
#endif
#include <kernel/race.h>
#include <kernel/rules.h>
#include <races/races.h>
@ -21,12 +19,9 @@ int main(int argc, char **argv) {
const char *mode;
register_races();
#ifdef USE_LIBXML2
register_xmlreader();
#endif
if (argc < 2) return usage();
mode = argv[1];
#ifdef USE_LIBXML2
if (strcmp(mode, "rules")==0) {
const char *xmlfile, *catalog;
if (argc < 4) return usage();
@ -36,7 +31,6 @@ int main(int argc, char **argv) {
write_rules("rules.dat");
return 0;
}
#endif
if (strcmp(mode, "po")==0) {
return 0;
}

View File

@ -723,18 +723,6 @@ static void cr_output_ship_compat(FILE *F, const ship *sh, const unit *u,
cr_output_ship(&strm, sh, u, fcaptain, f, r);
}
static int stream_order(stream *out, const struct order *ord, const struct locale *lang) {
const char *str;
char ebuf[1025];
char obuf[1024];
write_order(ord, lang, obuf, sizeof(obuf));
str = escape_string(obuf, ebuf, sizeof(ebuf));
if (str == ebuf) {
ebuf[1024] = 0;
}
return stream_printf(out, "\"%s\"\n", str);
}
static void cr_output_spells(stream *out, const unit * u, int maxlevel)
{
spellbook * book = unit_get_spellbook(u);
@ -925,7 +913,9 @@ void cr_output_unit(stream *out, const region * r, const faction * f,
for (ord = u->old_orders; ord; ord = ord->next) {
/* this new order will replace the old defaults */
if (is_persistent(ord)) {
stream_order(out, ord, lang);
swrite("\"", 1, 1, out);
stream_order(out, ord, lang, true);
swrite("\"\n", 1, 2, out);
}
}
for (ord = u->orders; ord; ord = ord->next) {
@ -933,7 +923,9 @@ void cr_output_unit(stream *out, const region * r, const faction * f,
if (u->old_orders && is_repeated(kwd))
continue; /* unit has defaults */
if (is_persistent(ord)) {
stream_order(out, ord, lang);
swrite("\"", 1, 1, out);
stream_order(out, ord, lang, true);
swrite("\"\n", 1, 2, out);
}
}
@ -1388,7 +1380,7 @@ static void cr_output_region(FILE * F, report_context * ctx, region * r)
else {
fprintf(F, "%d;Rekruten\n", rpeasants(r) / RECRUITFRACTION);
}
if (production(r)) {
if (max_production(r)) {
int p_wage = wage(r, NULL, NULL, turn + 1);
fprintf(F, "%d;Lohn\n", p_wage);
if (is_mourning(r, turn + 1)) {

View File

@ -81,26 +81,14 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <assert.h>
#include <limits.h>
typedef struct request {
struct request *next;
struct unit *unit;
struct order *ord;
int qty;
int no;
union {
bool goblin; /* stealing */
const struct luxury_type *ltype; /* trading */
} type;
} request;
static int working;
static request entertainers[1024];
static request *nextentertainer;
static econ_request entertainers[1024];
static econ_request *nextentertainer;
static int entertaining;
static unsigned int norders;
static request *g_requests;
static econ_request *g_requests;
#define RECRUIT_MERGE 1
static int rules_recruit = -1;
@ -153,19 +141,18 @@ static void scramble(void *data, unsigned int n, size_t width)
}
}
static void expandorders(region * r, request * requests)
unsigned int expand_production(region * r, econ_request * requests, econ_request **results)
{
unit *u;
request *o;
econ_request *o;
unsigned int norders = 0;
/* Alle Units ohne request haben ein -1, alle units mit orders haben ein
/* Alle Units ohne production haben ein -1, alle units mit orders haben ein
* 0 hier stehen */
for (u = r->units; u; u = u->next)
u->n = -1;
norders = 0;
for (o = requests; o; o = o->next) {
if (o->qty > 0) {
norders += o->qty;
@ -174,28 +161,35 @@ static void expandorders(region * r, request * requests)
if (norders > 0) {
int i = 0;
g_requests = (request *)calloc(norders, sizeof(request));
econ_request *split;
split = (econ_request *)calloc(norders, sizeof(econ_request));
for (o = requests; o; o = o->next) {
if (o->qty > 0) {
unsigned int j;
for (j = o->qty; j; j--) {
g_requests[i] = *o;
g_requests[i].unit->n = 0;
split[i] = *o;
split[i].unit->n = 0;
i++;
}
}
}
scramble(g_requests, norders, sizeof(request));
scramble(split, norders, sizeof(econ_request));
*results = split;
}
else {
g_requests = NULL;
*results = NULL;
}
while (requests) {
request *o = requests->next;
econ_request *o = requests->next;
free_order(requests->ord);
free(requests);
requests = o;
}
return norders;
}
static void expandorders(region * r, econ_request * requests) {
norders = expand_production(r, requests, &g_requests);
}
/* ------------------------------------------------------------- */
@ -203,21 +197,21 @@ static void expandorders(region * r, request * requests)
typedef struct recruitment {
struct recruitment *next;
faction *f;
request *requests;
econ_request *requests;
int total, assigned;
} recruitment;
/** Creates a list of recruitment structs, one for each faction. Adds every quantifyable request
/** Creates a list of recruitment structs, one for each faction. Adds every quantifyable production
* to the faction's struct and to total.
*/
static recruitment *select_recruitment(request ** rop,
static recruitment *select_recruitment(econ_request ** rop,
int(*quantify) (const struct race *, int), int *total)
{
recruitment *recruits = NULL;
while (*rop) {
recruitment *rec = recruits;
request *ro = *rop;
econ_request *ro = *rop;
unit *u = ro->unit;
const race *rc = u_race(u);
int qty = quantify(rc, ro->qty);
@ -294,7 +288,7 @@ static int do_recruiting(recruitment * recruits, int available)
int n = 0;
int rest, mintotal = INT_MAX;
/* find smallest request */
/* find smallest production */
for (rec = recruits; rec != NULL; rec = rec->next) {
int want = rec->total - rec->assigned;
if (want > 0) {
@ -310,7 +304,7 @@ static int do_recruiting(recruitment * recruits, int available)
}
rest = available - mintotal * n;
/* assign size of smallest request for everyone if possible; in the end roll dice to assign
/* assign size of smallest production for everyone if possible; in the end roll dice to assign
* small rest */
for (rec = recruits; rec != NULL; rec = rec->next) {
int want = rec->total - rec->assigned;
@ -330,7 +324,7 @@ static int do_recruiting(recruitment * recruits, int available)
/* do actual recruiting */
for (rec = recruits; rec != NULL; rec = rec->next) {
request *req;
econ_request *req;
int get = rec->assigned;
for (req = rec->requests; req; req = req->next) {
@ -379,7 +373,7 @@ void free_recruitments(recruitment * recruits)
recruitment *rec = recruits;
recruits = rec->next;
while (rec->requests) {
request *req = rec->requests;
econ_request *req = rec->requests;
rec->requests = req->next;
free_order(req->ord);
free(req);
@ -389,7 +383,7 @@ void free_recruitments(recruitment * recruits)
}
/* Rekrutierung */
static void expandrecruit(region * r, request * recruitorders)
static void expandrecruit(region * r, econ_request * recruitorders)
{
recruitment *recruits = NULL;
@ -430,11 +424,11 @@ static int recruit_cost(const faction * f, const race * rc)
return -1;
}
static void recruit(unit * u, struct order *ord, request ** recruitorders)
static void recruit(unit * u, struct order *ord, econ_request ** recruitorders)
{
region *r = u->region;
plane *pl;
request *o;
econ_request *o;
int recruitcost = -1;
const faction *f = u->faction;
const struct race *rc = u_race(u);
@ -555,7 +549,7 @@ static void recruit(unit * u, struct order *ord, request ** recruitorders)
return;
}
o = (request *)calloc(1, sizeof(request));
o = (econ_request *)calloc(1, sizeof(econ_request));
o->qty = n;
o->unit = u;
o->ord = copy_order(ord);
@ -751,7 +745,7 @@ void maintain_buildings(region * r)
void economics(region * r)
{
unit *u;
request *recruitorders = NULL;
econ_request *recruitorders = NULL;
/* Geben vor Selbstmord (doquit)! Hier alle unmittelbaren Befehle.
* Rekrutieren vor allen Einnahmequellen. Bewachen JA vor Steuern
@ -1441,7 +1435,7 @@ const attrib_type at_luxuries = {
"luxuries", NULL, free_luxuries, NULL, NULL, NULL
};
static void expandbuying(region * r, request * buyorders)
static void expandbuying(region * r, econ_request * buyorders)
{
const resource_type *rsilver = get_resourcetype(R_SILVER);
int max_products;
@ -1554,12 +1548,12 @@ attrib_type at_trades = {
NO_READ
};
static void buy(unit * u, request ** buyorders, struct order *ord)
static void buy(unit * u, econ_request ** buyorders, struct order *ord)
{
char token[128];
region *r = u->region;
int n, k;
request *o;
econ_request *o;
attrib *a;
const item_type *itype = NULL;
const luxury_type *ltype = NULL;
@ -1650,7 +1644,7 @@ static void buy(unit * u, request ** buyorders, struct order *ord)
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "luxury_notsold", ""));
return;
}
o = (request *)calloc(1, sizeof(request));
o = (econ_request *)calloc(1, sizeof(econ_request));
o->type.ltype = ltype; /* sollte immer gleich sein */
o->unit = u;
@ -1659,18 +1653,18 @@ static void buy(unit * u, request ** buyorders, struct order *ord)
}
/* ------------------------------------------------------------- */
static void add_income(unit * u, int type, int want, int qty)
void add_income(unit * u, income_t type, int want, int qty)
{
if (want == INT_MAX)
want = qty;
ADDMSG(&u->faction->msgs, msg_message("income",
"unit region mode wanted amount", u, u->region, type, want, qty));
"unit region mode wanted amount", u, u->region, (int)type, want, qty));
}
/* Steuers<72>tze in % bei Burggr<67><72>e */
static int tax_per_size[7] = { 0, 6, 12, 18, 24, 30, 36 };
static void expandselling(region * r, request * sellorders, int limit)
static void expandselling(region * r, econ_request * sellorders, int limit)
{
int money, price, max_products;
unsigned int j;
@ -1769,8 +1763,6 @@ static void expandselling(region * r, request * sellorders, int limit)
price = ltype->price * multi;
if (money >= price) {
int abgezogenhafen = 0;
int abgezogensteuer = 0;
unit *u = g_requests[j].unit;
item *itm;
attrib *a = a_find(u->attribs, &at_luxuries);
@ -1785,7 +1777,7 @@ static void expandselling(region * r, request * sellorders, int limit)
if (hafenowner != NULL) {
if (hafenowner->faction != u->faction) {
abgezogenhafen = price / 10;
int abgezogenhafen = price / 10;
hafencollected += abgezogenhafen;
price -= abgezogenhafen;
money -= abgezogenhafen;
@ -1793,7 +1785,7 @@ static void expandselling(region * r, request * sellorders, int limit)
}
if (maxb != NULL) {
if (maxowner->faction != u->faction) {
abgezogensteuer = price * tax_per_size[maxeffsize] / 100;
int abgezogensteuer = price * tax_per_size[maxeffsize] / 100;
taxcollected += abgezogensteuer;
price -= abgezogensteuer;
money -= abgezogensteuer;
@ -1859,7 +1851,7 @@ static void expandselling(region * r, request * sellorders, int limit)
}
}
static bool sell(unit * u, request ** sellorders, struct order *ord)
static bool sell(unit * u, econ_request ** sellorders, struct order *ord)
{
char token[128];
bool unlimited = true;
@ -1952,7 +1944,7 @@ static bool sell(unit * u, request ** sellorders, struct order *ord)
}
else {
attrib *a;
request *o;
econ_request *o;
int k, available;
if (!r_demand(r, ltype)) {
@ -1977,7 +1969,7 @@ static bool sell(unit * u, request ** sellorders, struct order *ord)
cmistake(u, ord, 264, MSG_COMMERCE);
return false;
}
/* Hier wird request->type verwendet, weil die obere limit durch
/* Hier wird production->type verwendet, weil die obere limit durch
* das silber gegeben wird (region->money), welches f<EFBFBD>r alle
* (!) produkte als summe gilt, als nicht wie bei der
* produktion, wo f<EFBFBD>r jedes produkt einzeln eine obere limite
@ -2000,7 +1992,7 @@ static bool sell(unit * u, request ** sellorders, struct order *ord)
assert(n >= 0);
/* die Menge der verkauften G<>ter merken */
a->data.i += n;
o = (request *)calloc(1, sizeof(request));
o = (econ_request *)calloc(1, sizeof(econ_request));
o->unit = u;
o->qty = n;
o->type.ltype = ltype;
@ -2010,48 +2002,6 @@ static bool sell(unit * u, request ** sellorders, struct order *ord)
}
}
/* ------------------------------------------------------------- */
static void expandstealing(region * r, request * stealorders)
{
const resource_type *rsilver = get_resourcetype(R_SILVER);
unsigned int j;
assert(rsilver);
expandorders(r, stealorders);
if (!norders) return;
/* F<>r jede unit in der Region wird Geld geklaut, wenn sie Opfer eines
* Beklauen-Orders ist. Jedes Opfer mu<EFBFBD> einzeln behandelt werden.
*
* u ist die beklaute unit. oa.unit ist die klauende unit.
*/
for (j = 0; j != norders && g_requests[j].unit->n <= g_requests[j].unit->wants; j++) {
unit *u = findunitg(g_requests[j].no, r);
int n = 0;
if (u && u->region == r) {
n = get_pooled(u, rsilver, GET_ALL, INT_MAX);
}
if (n > 10 && rplane(r) && (rplane(r)->flags & PFL_NOALLIANCES)) {
/* In Questen nur reduziertes Klauen */
n = 10;
}
if (n > 0) {
n = MIN(n, g_requests[j].unit->wants);
use_pooled(u, rsilver, GET_ALL, n);
g_requests[j].unit->n = n;
change_money(g_requests[j].unit, n);
ADDMSG(&u->faction->msgs, msg_message("stealeffect", "unit region amount",
u, u->region, n));
}
add_income(g_requests[j].unit, IC_STEAL, g_requests[j].unit->wants, g_requests[j].unit->n);
fset(g_requests[j].unit, UFL_LONGACTION | UFL_NOTMOVING);
}
free(g_requests);
}
/* ------------------------------------------------------------- */
static void plant(unit * u, int raw)
{
@ -2371,162 +2321,11 @@ static void research_cmd(unit * u, struct order *ord)
}
}
static int max_skill(region * r, faction * f, skill_t sk)
{
unit *u;
int w = 0;
for (u = r->units; u; u = u->next) {
if (u->faction == f) {
int effsk = effskill(u, sk, 0);
if (effsk > w) {
w = effsk;
}
}
}
return w;
}
message * check_steal(const unit * u, struct order *ord) {
plane *pl;
if (fval(u_race(u), RCF_NOSTEAL)) {
return msg_feedback(u, ord, "race_nosteal", "race", u_race(u));
}
if (fval(u->region->terrain, SEA_REGION) && u_race(u) != get_race(RC_AQUARIAN)) {
return msg_feedback(u, ord, "error_onlandonly", "");
}
pl = rplane(u->region);
if (pl && fval(pl, PFL_NOATTACK)) {
return msg_feedback(u, ord, "error270", "");
}
return 0;
}
static void steal_cmd(unit * u, struct order *ord, request ** stealorders)
{
const resource_type *rring = get_resourcetype(R_RING_OF_NIMBLEFINGER);
int n, i, id, effsk;
bool goblin = false;
request *o;
unit *u2 = NULL;
region *r = u->region;
faction *f = NULL;
message * msg;
keyword_t kwd;
kwd = init_order_depr(ord);
assert(kwd == K_STEAL);
assert(skill_enabled(SK_PERCEPTION) && skill_enabled(SK_STEALTH));
msg = check_steal(u, ord);
if (msg) {
ADDMSG(&u->faction->msgs, msg);
return;
}
id = read_unitid(u->faction, r);
if (id > 0) {
u2 = findunitr(r, id);
}
if (u2 && u2->region == u->region) {
f = u2->faction;
}
else {
/* TODO: is this really necessary? it's the only time we use faction.c/deadhash
* it allows stealing from a unit in a dead faction, but why? */
f = dfindhash(id);
}
for (u2 = r->units; u2; u2 = u2->next) {
if (u2->faction == f && cansee(u->faction, r, u2, 0))
break;
}
if (!u2) {
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found",
""));
return;
}
if (IsImmune(u2->faction)) {
ADDMSG(&u->faction->msgs,
msg_feedback(u, ord, "newbie_immunity_error", "turns", NewbieImmunity()));
return;
}
if (u->faction->alliance && u->faction->alliance == u2->faction->alliance) {
cmistake(u, ord, 47, MSG_INCOME);
return;
}
assert(u->region == u2->region);
if (!can_contact(r, u, u2)) {
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error60", ""));
return;
}
effsk = effskill(u, SK_STEALTH, 0);
n = effsk - max_skill(r, f, SK_PERCEPTION);
if (n <= 0) {
/* Wahrnehmung == Tarnung */
if (u_race(u) != get_race(RC_GOBLIN) || effsk <= 3) {
ADDMSG(&u->faction->msgs, msg_message("stealfail", "unit target", u, u2));
if (n == 0) {
ADDMSG(&u2->faction->msgs, msg_message("stealdetect", "unit", u2));
}
else {
ADDMSG(&u2->faction->msgs, msg_message("thiefdiscover", "unit target",
u, u2));
}
return;
}
else {
ADDMSG(&u->faction->msgs, msg_message("stealfatal", "unit target", u,
u2));
ADDMSG(&u2->faction->msgs, msg_message("thiefdiscover", "unit target", u,
u2));
n = 1;
goblin = true;
}
}
i = MIN(u->number, i_get(u->items, rring->itype));
if (i > 0) {
n *= STEALINCOME * (u->number + i * (roqf_factor() - 1));
}
else {
n *= u->number * STEALINCOME;
}
u->wants = n;
/* wer dank unsichtbarkeitsringen klauen kann, muss nicht unbedingt ein
* guter dieb sein, schliesslich macht man immer noch sehr viel laerm */
o = (request *)calloc(1, sizeof(request));
o->unit = u;
o->qty = 1; /* Betrag steht in u->wants */
o->no = u2->no;
o->type.goblin = goblin; /* Merken, wenn Goblin-Spezialklau */
addlist(stealorders, o);
/* Nur soviel PRODUCEEXP wie auch tatsaechlich gemacht wurde */
produceexp(u, SK_STEALTH, MIN(n, u->number));
}
/* ------------------------------------------------------------- */
static void expandentertainment(region * r)
{
unit *u;
int m = entertainmoney(r);
request *o;
econ_request *o;
for (o = &entertainers[0]; o != nextentertainer; ++o) {
double part = m / (double)entertaining;
@ -2551,7 +2350,7 @@ void entertain_cmd(unit * u, struct order *ord)
{
region *r = u->region;
int max_e;
request *o;
econ_request *o;
static int entertainbase = 0;
static int entertainperlevel = 0;
keyword_t kwd;
@ -2604,7 +2403,7 @@ void entertain_cmd(unit * u, struct order *ord)
* \return number of working spaces taken by players
*/
static void
expandwork(region * r, request * work_begin, request * work_end, int maxwork)
expandwork(region * r, econ_request * work_begin, econ_request * work_end, int maxwork)
{
int earnings;
/* n: verbleibende Einnahmen */
@ -2612,7 +2411,7 @@ expandwork(region * r, request * work_begin, request * work_end, int maxwork)
int jobs = maxwork;
int p_wage = wage(r, NULL, NULL, turn);
int money = rmoney(r);
request *o;
econ_request *o;
for (o = work_begin; o != work_end; ++o) {
unit *u = o->unit;
@ -2655,7 +2454,7 @@ expandwork(region * r, request * work_begin, request * work_end, int maxwork)
rsetmoney(r, money + earnings);
}
static int do_work(unit * u, order * ord, request * o)
static int do_work(unit * u, order * ord, econ_request * o)
{
if (playerrace(u_race(u))) {
region *r = u->region;
@ -2690,7 +2489,7 @@ static int do_work(unit * u, order * ord, request * o)
return -1;
}
static void expandloot(region * r, request * lootorders)
static void expandloot(region * r, econ_request * lootorders)
{
unit *u;
unsigned int i;
@ -2727,7 +2526,7 @@ static void expandloot(region * r, request * lootorders)
}
}
void expandtax(region * r, request * taxorders)
void expandtax(region * r, econ_request * taxorders)
{
unit *u;
unsigned int i;
@ -2751,13 +2550,13 @@ void expandtax(region * r, request * taxorders)
}
}
void tax_cmd(unit * u, struct order *ord, request ** taxorders)
void tax_cmd(unit * u, struct order *ord, econ_request ** taxorders)
{
/* Steuern werden noch vor der Forschung eingetrieben */
region *r = u->region;
unit *u2;
int n;
request *o;
econ_request *o;
int max;
keyword_t kwd;
static int taxperlevel = 0;
@ -2819,20 +2618,20 @@ void tax_cmd(unit * u, struct order *ord, request ** taxorders)
* fraktionen werden dann bei eintreiben unter allen eintreibenden
* einheiten aufgeteilt. */
o = (request *)calloc(1, sizeof(request));
o = (econ_request *)calloc(1, sizeof(econ_request));
o->qty = u->wants / TAXFRACTION;
o->unit = u;
addlist(taxorders, o);
return;
}
void loot_cmd(unit * u, struct order *ord, request ** lootorders)
void loot_cmd(unit * u, struct order *ord, econ_request ** lootorders)
{
region *r = u->region;
unit *u2;
int n;
int max;
request *o;
econ_request *o;
keyword_t kwd;
kwd = init_order_depr(ord);
@ -2884,7 +2683,7 @@ void loot_cmd(unit * u, struct order *ord, request ** lootorders)
u->wants = MIN(n * skbonus * 10, max);
}
o = (request *)calloc(1, sizeof(request));
o = (econ_request *)calloc(1, sizeof(econ_request));
o->qty = u->wants / TAXFRACTION;
o->unit = u;
addlist(lootorders, o);
@ -2895,8 +2694,8 @@ void loot_cmd(unit * u, struct order *ord, request ** lootorders)
#define MAX_WORKERS 2048
void auto_work(region * r)
{
request workers[MAX_WORKERS];
request *nextworker = workers;
econ_request workers[MAX_WORKERS];
econ_request *nextworker = workers;
unit *u;
for (u = r->units; u; u = u->next) {
@ -2964,11 +2763,11 @@ static bool rule_autowork(void) {
void produce(struct region *r)
{
request workers[MAX_WORKERS];
request *taxorders, *lootorders, *sellorders, *stealorders, *buyorders;
econ_request workers[MAX_WORKERS];
econ_request *taxorders, *lootorders, *sellorders, *stealorders, *buyorders;
unit *u;
bool limited = true;
request *nextworker = workers;
econ_request *nextworker = workers;
static int bt_cache;
static const struct building_type *caravan_bt;
static int rc_cache;

View File

@ -45,7 +45,18 @@ extern "C" {
struct faction;
struct order;
struct message;
struct request;
typedef struct econ_request {
struct econ_request *next;
struct unit *unit;
struct order *ord;
int qty;
int no;
union {
bool goblin; /* stealing */
const struct luxury_type *ltype; /* trading */
} type;
} econ_request;
int income(const struct unit *u);
int entertainmoney(const struct region *r);
@ -54,17 +65,26 @@ extern "C" {
void produce(struct region *r);
void auto_work(struct region *r);
enum { IC_WORK, IC_ENTERTAIN, IC_TAX, IC_TRADE, IC_TRADETAX, IC_STEAL, IC_MAGIC, IC_LOOT };
unsigned int expand_production(struct region * r, struct econ_request * requests, struct econ_request **results);
typedef enum income_t { IC_WORK, IC_ENTERTAIN, IC_TAX, IC_TRADE, IC_TRADETAX, IC_STEAL, IC_MAGIC, IC_LOOT } income_t;
void add_income(struct unit * u, income_t type, int want, int qty);
void maintain_buildings(struct region *r);
void make_item(struct unit * u, const struct item_type * itype, int want);
int make_cmd(struct unit *u, struct order *ord);
void split_allocations(struct region *r);
int give_control_cmd(struct unit *u, struct order *ord);
void give_control(struct unit * u, struct unit * u2);
void tax_cmd(struct unit * u, struct order *ord, struct request ** taxorders);
void expandtax(struct region * r, struct request * taxorders);
void tax_cmd(struct unit * u, struct order *ord, struct econ_request ** taxorders);
void expandtax(struct region * r, struct econ_request * taxorders);
struct message * steal_message(const struct unit * u, struct order *ord);
void steal_cmd(struct unit * u, struct order *ord, struct econ_request ** stealorders);
void expandstealing(struct region * r, struct econ_request * stealorders);
void add_recruits(struct unit * u, int number, int wanted);
struct message * check_steal(const struct unit * u, struct order *ord);
#ifdef __cplusplus
}

View File

@ -88,7 +88,7 @@ static void test_steal_okay(CuTest * tc) {
rc = test_create_race("human");
rc->flags = 0;
setup_steal(&env, ter, rc);
CuAssertPtrEquals(tc, 0, check_steal(env.u, 0));
CuAssertPtrEquals(tc, 0, steal_message(env.u, 0));
test_cleanup();
}
@ -103,7 +103,7 @@ static void test_steal_nosteal(CuTest * tc) {
rc = test_create_race("human");
rc->flags = RCF_NOSTEAL;
setup_steal(&env, ter, rc);
CuAssertPtrNotNull(tc, msg = check_steal(env.u, 0));
CuAssertPtrNotNull(tc, msg = steal_message(env.u, 0));
msg_release(msg);
test_cleanup();
}
@ -118,7 +118,7 @@ static void test_steal_ocean(CuTest * tc) {
ter = test_create_terrain("ocean", SEA_REGION);
rc = test_create_race("human");
setup_steal(&env, ter, rc);
CuAssertPtrNotNull(tc, msg = check_steal(env.u, 0));
CuAssertPtrNotNull(tc, msg = steal_message(env.u, 0));
msg_release(msg);
test_cleanup();
}
@ -300,26 +300,13 @@ static void test_buy_cmd(CuTest *tc) {
test_cleanup();
}
typedef struct request {
struct request *next;
struct unit *unit;
struct order *ord;
int qty;
int no;
union {
bool goblin; /* stealing */
const struct luxury_type *ltype; /* trading */
} type;
} request;
static void test_tax_cmd(CuTest *tc) {
order *ord;
faction *f;
region *r;
unit *u;
item_type *sword, *silver;
request *taxorders = 0;
econ_request *taxorders = 0;
test_setup();
init_resources();

View File

@ -16,9 +16,7 @@
#include <kernel/config.h>
#include <util/log.h>
#if MUSEUM_MODULE
#include <modules/museum.h>
#endif
#include <triggers/triggers.h>
#include <util/language.h>
#include <util/functions.h>
@ -41,6 +39,7 @@
void game_done(void)
{
#undef CLEANUP_CODE
#ifdef CLEANUP_CODE
/* Diese Routine enfernt allen allokierten Speicher wieder. Das ist nur
* zum Debugging interessant, wenn man Leak Detection hat, und nach
@ -78,16 +77,12 @@ void game_init(void)
register_names();
register_resources();
register_itemfunctions();
#if MUSEUM_MODULE
register_museum();
#endif
wormholes_register();
register_weapons();
register_xerewards();
#ifdef USE_LIBXML2
register_xmlreader();
#endif
register_attributes();
register_gmcmd();

View File

@ -239,12 +239,6 @@ struct order *ord)
change_reservation(dest, item2resource(itype), r);
}
#endif
#endif
#if MUSEUM_MODULE && defined(TODO)
/* TODO: use a trigger for the museum warden! */
if (a_find(dest->attribs, &at_warden)) {
warden_add_give(src, dest, itype, delta);
}
#endif
}
else {

View File

@ -24,9 +24,7 @@
#include <modules/xmas.h>
#include <modules/gmcmd.h>
#if MUSEUM_MODULE
#include <modules/museum.h>
#endif
#include <modules/autoseed.h>
#include <kernel/building.h>

View File

@ -304,11 +304,24 @@ struct trigger_type tt_caldera = {
caldera_read
};
static int building_action_read(struct attrib *a, void *owner, gamedata *data)
{
struct storage *store = data->store;
if (data->version < ATTRIBOWNER_VERSION) {
READ_INT(data->store, NULL);
}
READ_TOK(store, NULL, 0);
READ_TOK(store, NULL, 0);
return AT_READ_DEPR;
}
void register_tolua_helpers(void)
{
tt_register(&tt_caldera);
at_register(&at_direction);
at_register(&at_building_action);
at_deprecate("lcbuilding", building_action_read);
callbacks.cast_spell = lua_callspell;
callbacks.use_item = use_item_lua;

View File

@ -1,19 +1,22 @@
#include <platform.h>
#include <CuTest.h>
#include <stream.h>
#include <memstream.h>
#include <kernel/region.h>
#include <kernel/terrain.h>
#include "json.h"
#include "tests.h"
#include <kernel/region.h>
#include <kernel/terrain.h>
#include <stream.h>
#include <memstream.h>
#include <cJSON.h>
#include <CuTest.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
static char *strip(char *str) {
char *s = str, *b = str, *e = str;
/* b is where text begins, e where it ends, s where we insert it. */

View File

@ -422,7 +422,7 @@ const char *alliancename(const alliance * al)
char *ibuf = idbuf[(++nextbuf) % 8];
if (al && al->name) {
slprintf(ibuf, sizeof(name), "%s (%s)", al->name, itoa36(al->id));
slprintf(ibuf, sizeof(idbuf[0]), "%s (%s)", al->name, itoa36(al->id));
}
else {
return NULL;
@ -430,46 +430,6 @@ const char *alliancename(const alliance * al)
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 **fp;
for (fp = &factions; *fp; ) {
faction *f = *fp;
if (f->alliance == al) {
ADDMSG(&f->msgs, msg_message("alliance::lost", "alliance", al));
destroyfaction(fp);
} else {
fp = &f->next;
}
}
}
else {
freset(al, FFL_MARK);
}
al = al->next;
}
}
void alliance_setname(alliance * self, const char *name)
{
free(self->name);

View File

@ -499,7 +499,7 @@ const char *buildingname(const building * b)
static name idbuf[8];
static int nextbuf = 0;
char *ibuf = idbuf[(++nextbuf) % 8];
return write_buildingname(b, ibuf, sizeof(name));
return write_buildingname(b, ibuf, sizeof(idbuf[0]));
}
void building_set_owner(struct unit * owner)
@ -774,22 +774,11 @@ int cmp_wage(const struct building *b, const building * a)
return -1;
}
bool is_owner_building(const struct building * b)
{
region *r = b->region;
if (b->type->taxes && r->land && r->land->ownership) {
unit *u = building_owner(b);
return u && u->faction == r->land->ownership->owner;
}
return false;
}
int building_taxes(const building *b) {
assert(b);
return b->type->taxes;
}
int cmp_taxes(const building * b, const building * a)
{
faction *f = region_get_owner(b->region);

View File

@ -71,7 +71,6 @@ extern "C" {
} building_type;
extern struct selist *buildingtypes;
extern struct attrib_type at_building_action;
extern struct attrib_type at_building_generic_type;
int cmp_castle_size(const struct building *b, const struct building *a);

View File

@ -73,11 +73,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "guard.h"
#include "prefix.h"
#ifdef USE_LIBXML2
/* libxml includes */
#include <libxml/tree.h>
#include <libxml/xpath.h>
#endif
/* external libraries */
#include <iniparser.h>
@ -260,15 +258,6 @@ param_t getparam(const struct locale * lang)
return s ? findparam(s, lang) : NOPARAM;
}
unit *getnewunit(const region * r, const faction * f)
{
int n;
n = getid();
return findnewunit(r, f, n);
}
/* -- Erschaffung neuer Einheiten ------------------------------ */
static const char *forbidden[] = { "t", "te", "tem", "temp", NULL };
@ -611,9 +600,7 @@ void kernel_done(void)
/* calling this function releases memory assigned to static variables, etc.
* calling it is optional, e.g. a release server will most likely not do it.
*/
#ifdef USE_LIBXML2
xml_done();
#endif
attrib_done();
item_done();
message_done();

View File

@ -41,10 +41,10 @@ int db_driver_order_save(struct order_data *od)
assert(od && od->_str);
key.data = &recno;
key.size = sizeof(recno);
key.size = key.ulen = sizeof(recno);
key.flags = DB_DBT_USERMEM;
data.data = (void *)od->_str;
data.size = strlen(od->_str) + 1;
data.size = data.ulen = strlen(od->_str) + 1;
data.flags = DB_DBT_USERMEM;
ret = g_dbp->put(g_dbp, NULL, &key, &data, DB_APPEND);
assert(ret == 0);
@ -63,7 +63,7 @@ struct order_data *db_driver_order_load(int id)
memset(&data, 0, sizeof(DBT));
recno = (db_recno_t)id;
key.data = &recno;
key.size = sizeof(recno);
key.size = key.ulen = sizeof(recno);
key.flags = DB_DBT_USERMEM;
ret = g_dbp->get(g_dbp, NULL, &key, &data, 0);
if (ret == 0) {

View File

@ -195,7 +195,7 @@ const char *factionname(const faction * f)
char *ibuf = idbuf[(++nextbuf) % 8];
if (f && f->name) {
slprintf(ibuf, sizeof(name), "%s (%s)", f->name, itoa36(f->no));
slprintf(ibuf, sizeof(idbuf[0]), "%s (%s)", f->name, itoa36(f->no));
}
else {
strcpy(ibuf, "Unbekannte Partei (?)");

View File

@ -84,9 +84,6 @@ extern "C" {
score_t score;
struct alliance *alliance;
int alliance_joindate; /* the turn on which the faction joined its current alliance (or left the last one) */
#ifdef VICTORY_DELAY
unsigned char victory_delay;
#endif
struct unit *units;
struct attrib *attribs;
struct message_list *msgs;

View File

@ -596,7 +596,7 @@ const resource_type *get_resourcetype(resource_t type) {
static struct resource_type * rtypes[MAX_RESOURCES];
const resource_type *rtype = NULL;
if (update != num_resources) {
memset(rtypes, 0, sizeof(rtypes));
memset(rtypes, 0, sizeof(resource_type *) * MAX_RESOURCES);
update = num_resources;
}
else {
@ -631,27 +631,6 @@ int set_item(unit * u, const item_type *itype, int value)
return value;
}
/* t_item::flags */
#define FL_ITEM_CURSED (1<<0)
#define FL_ITEM_NOTLOST (1<<1)
#define FL_ITEM_NOTINBAG (1<<2) /* nicht im Bag Of Holding */
#define FL_ITEM_ANIMAL (1<<3) /* ist ein Tier */
#define FL_ITEM_MOUNT ((1<<4) | FL_ITEM_ANIMAL) /* ist ein Reittier */
typedef struct t_item {
const char *name;
/* [0]: Einzahl fuer eigene; [1]: Mehrzahl fuer eigene;
* [2]: Einzahl fuer Fremde; [3]: Mehrzahl fuer Fremde */
bool is_resource;
skill_t skill;
int minskill;
int gewicht;
int preis;
unsigned int flags;
void(*benutze_funktion) (struct region *, struct unit *, int amount,
struct order *);
} t_item;
#include "move.h"
static int
@ -746,11 +725,13 @@ void init_resources(void)
int get_money(const unit * u)
{
const struct resource_type *rtype = get_resourcetype(R_SILVER);
const item *i = u->items;
while (i && i->type->rtype != rtype) {
i = i->next;
const item *i;
for (i = u->items; i; i = i->next) {
if (i->type->rtype == rtype) {
return i->number;
}
return i ? i->number : 0;
}
return 0;
}
int set_money(unit * u, int v)

View File

@ -23,6 +23,9 @@
#include <util/language.h>
#include <util/log.h>
#include <util/parser.h>
#include <util/strings.h>
#include <stream.h>
/* libc includes */
#include <assert.h>
@ -135,6 +138,49 @@ char* get_command(const order *ord, const struct locale *lang, char *sbuffer, si
return sbuffer;
}
int stream_order(struct stream *out, const struct order *ord, const struct locale *lang, bool escape)
{
const char *str, *text;
order_data *od = NULL;
keyword_t kwd = ORD_KEYWORD(ord);
if (ord->command & CMD_QUIET) {
swrite("!", 1, 1, out);
}
if (ord->command & CMD_PERSIST) {
swrite("@", 1, 1, out);
}
if (ord->id < 0) {
skill_t sk = (skill_t)(100 + ord->id);
assert(kwd == K_STUDY && sk != SK_MAGIC && sk < MAXSKILLS);
text = skillname(sk, lang);
}
else {
od = odata_load(ord->id);
text = OD_STRING(od);
}
if (kwd != NOKEYWORD) {
str = (const char *)LOC(lang, keyword(kwd));
assert(str);
swrite(str, 1, strlen(str), out);
}
if (text) {
char obuf[1024];
swrite(" ", 1, 1, out);
if (escape) {
text = escape_string(text, obuf, sizeof(obuf));
}
swrite(text, 1, strlen(text), out);
}
if (od) {
odata_release(od);
}
return 0;
}
void free_order(order * ord)
{
if (ord != NULL) {

View File

@ -22,6 +22,7 @@ extern "C" {
#endif
struct locale;
struct stream;
/* Encapsulation of an order
*
@ -69,6 +70,7 @@ extern "C" {
char *write_order(const order * ord, const struct locale *lang,
char *buffer, size_t size);
int stream_order(struct stream *out, const struct order *ord, const struct locale *lang, bool escape);
keyword_t init_order_depr(const struct order *ord);
keyword_t init_order(const struct order *ord, const struct locale *lang);

View File

@ -114,7 +114,7 @@ int change_reservation(unit * u, const item_type * itype, int value)
res->type = itype;
res->value = value;
}
else if (res && res->value + value <= 0) {
else if (res->value + value <= 0) {
*rp = res->next;
free(res);
return 0;
@ -139,7 +139,7 @@ int set_resvalue(unit * u, const item_type * itype, int value)
res->type = itype;
res->value = value;
}
else if (res && value <= 0) {
else if (value <= 0) {
*rp = res->next;
free(res);
return 0;

View File

@ -139,7 +139,7 @@ const char *regionname(const region * r, const faction * f)
int region_maxworkers(const region *r)
{
int size = production(r);
int size = max_production(r);
int treespace = (rtrees(r, 2) + rtrees(r, 1) / 2) * TREESIZE;
return MAX(size - treespace, MIN(size / 10, 200));
}
@ -1244,7 +1244,7 @@ void terraform_region(region * r, const terrain_type * terrain)
* egal ob durch den spell oder anderes angelegt.
**/
#include "curse.h"
int production(const region * r)
int max_production(const region * r)
{
/* muß rterrain(r) sein, nicht rterrain() wegen rekursion */
int p = r->terrain->size;

View File

@ -240,7 +240,7 @@ extern "C" {
extern const int delta_x[MAXDIRECTIONS];
extern const int delta_y[MAXDIRECTIONS];
direction_t dir_invert(direction_t dir);
int production(const struct region *r);
int max_production(const struct region *r);
void region_set_owner(struct region *r, struct faction *owner, int turn);
struct faction *region_get_owner(const struct region *r);

View File

@ -124,30 +124,6 @@ static void terraform_default(struct rawmaterial *res, const region * r)
UNUSED_ARG(r);
}
#ifdef RANDOM_CHANGE
static void resource_random_change(int *pvalue, bool used)
{
int split = 5;
int rnd = rng_int() % 100;
if (pvalue == 0 || rnd % 10 >= 10)
return;
if (used)
split = 4;
/* if a resource was mined this round, there is a 6% probability
* of a decline and a 4% probability of a raise. */
/* if it wasn't mined this round, there is an equal probability
* of 5% for a decline or a raise. */
if (rnd < split) {
(*pvalue)++;
} else {
(*pvalue)--;
}
if ((*pvalue) < 0)
(*pvalue) = 0;
}
#endif
static int visible_default(const rawmaterial * res, int skilllevel)
/* resources are visible, if skill equals minimum skill to mine them
* plus current level of difficulty */

View File

@ -102,71 +102,6 @@ int firstx = 0, firsty = 0;
/* TODO: is this still important? */
int enc_gamedata = ENCODING_UTF8;
/* local symbols */
static region *current_region;
char *rns(FILE * f, char *c, size_t size)
{
char *s = c;
do {
*s = (char)getc(f);
} while (*s != '"');
for (;;) {
*s = (char)getc(f);
if (*s == '"')
break;
if (s < c + size)
++s;
}
*s = 0;
return c;
}
/* ------------------------------------------------------------- */
/* #define INNER_WORLD */
/* fürs debuggen nur den inneren Teil der Welt laden */
/* -9;-27;-1;-19;Sumpfloch */
int inner_world(region * r)
{
static int xy[2] = { 18, -45 };
static int size[2] = { 27, 27 };
if (r->x >= xy[0] && r->x < xy[0] + size[0] && r->y >= xy[1]
&& r->y < xy[1] + size[1])
return 2;
if (r->x >= xy[0] - 9 && r->x < xy[0] + size[0] + 9 && r->y >= xy[1] - 9
&& r->y < xy[1] + size[1] + 9)
return 1;
return 0;
}
int maxregions = -1;
int loadplane = 0;
enum {
U_MAN,
U_UNDEAD,
U_ILLUSION,
U_FIREDRAGON,
U_DRAGON,
U_WYRM,
U_SPELL,
U_TAVERNE,
U_MONSTER,
U_BIRTHDAYDRAGON,
U_TREEMAN,
MAXTYPES
};
race_t typus2race(unsigned char typus)
{
if (typus > 0 && typus <= 11)
return (race_t)(typus - 1);
return NORACE;
}
static void read_alliances(gamedata *data)
{
storage *store = data->store;
@ -366,7 +301,7 @@ int current_turn(void)
perror(zText);
}
else {
int c = fscanf(F, "%d\n", &cturn);
int c = fscanf(F, "%4d\n", &cturn);
fclose(F);
if (c != 1) {
return -1;
@ -676,7 +611,6 @@ static region *readregion(gamedata *data, int x, int y)
}
else {
assert(uid == 0 || r->uid == uid);
current_region = r;
while (r->attribs)
a_remove(&r->attribs, r->attribs);
if (r->land) {
@ -1440,7 +1374,6 @@ int read_game(gamedata *data)
building **bp;
ship **shp;
unit *u;
int rmax = maxregions;
storage * store = data->store;
const struct building_type *bt_lighthouse = bt_find("lighthouse");
const struct race *rc_spell = rc_find("spell");
@ -1485,10 +1418,8 @@ int read_game(gamedata *data)
READ_INT(store, &nread);
assert(nread < MAXREGIONS && nread >=0);
if (rmax < 0) {
rmax = nread;
}
log_debug(" - Einzulesende Regionen: %d/%d", rmax, nread);
log_debug(" - Einzulesende Regionen: %d", nread);
while (--nread >= 0) {
unit **up;
@ -1551,7 +1482,6 @@ int read_game(gamedata *data)
update_interval(u->faction, r);
}
}
--rmax;
}
read_borders(data);
@ -1613,9 +1543,6 @@ int read_game(gamedata *data)
fix_familiars();
}
if (loadplane || maxregions >= 0) {
remove_empty_factions();
}
log_debug("Done loading turn %d.", turn);
return 0;

View File

@ -386,7 +386,7 @@ const char *shipname(const ship * sh)
static name idbuf[8];
static int nextbuf = 0;
char *ibuf = idbuf[(++nextbuf) % 8];
return write_shipname(sh, ibuf, sizeof(name));
return write_shipname(sh, ibuf, sizeof(idbuf[0]));
}
int shipcapacity(const ship * sh)

View File

@ -394,11 +394,14 @@ faction *dfindhash(int no)
}
#else
struct faction *dfindhash(int no) {
unit *u = deleted_units;
while (u && u->no != no) {
u = u->next;
unit *u;
for (u = deleted_units; u; u = u->next) {
if (u->no == no) {
return u->faction;
}
return u ? u->faction : NULL;
}
return NULL;
}
#endif
@ -1597,12 +1600,6 @@ int countheroes(const struct faction *f)
n += u->number;
u = u->nextF;
}
#ifdef DEBUG_MAXHEROES
int m = maxheroes(f);
if (n > m) {
log_warning("%s has %d of %d heroes\n", factionname(f), n, m);
}
#endif
return n;
}
@ -1708,7 +1705,6 @@ void unit_addorder(unit * u, order * ord)
int unit_max_hp(const unit * u)
{
int h;
double p;
static int config;
static bool rule_stamina;
h = u_race(u)->hitpoints;
@ -1717,7 +1713,7 @@ int unit_max_hp(const unit * u)
rule_stamina = config_get_int("rules.stamina", 1)!=0;
}
if (rule_stamina) {
p = pow(effskill(u, SK_STAMINA, u->region) / 2.0, 1.5) * 0.2;
double p = pow(effskill(u, SK_STAMINA, u->region) / 2.0, 1.5) * 0.2;
h += (int)(h * p + 0.5);
}
@ -1887,7 +1883,7 @@ char *write_unitname(const unit * u, char *buffer, size_t size)
const char *unitname(const unit * u)
{
char *ubuf = idbuf[(++nextbuf) % 8];
return write_unitname(u, ubuf, sizeof(name));
return write_unitname(u, ubuf, sizeof(idbuf[0]));
}
bool unit_name_equals_race(const unit *u) {
@ -1929,10 +1925,6 @@ int read_unitid(const faction * f, const region * r)
char token[16];
const char *s = gettoken(token, sizeof(token));
/* Da s nun nur einen string enthaelt, suchen wir ihn direkt in der
* paramliste. machen wir das nicht, dann wird getnewunit in s nach der
* nummer suchen, doch dort steht bei temp-units nur "temp" drinnen! */
if (!s || *s == 0 || !isalnum(*s)) {
return -1;
}

View File

@ -18,6 +18,6 @@ const char *eressea_version(void) {
int version_no(const char *str) {
int maj = 0, min = 0, pat = 0;
sscanf(str, "%d.%d.%d", &maj, &min, &pat);
sscanf(str, "%4d.%4d.%4d", &maj, &min, &pat);
return (maj << 16) | (min << 8) | pat;
}

View File

@ -48,12 +48,10 @@ without prior permission by the authors of Eressea.
#include <util/nrmessage.h>
#include <util/xml.h>
#ifdef USE_LIBXML2
/* libxml includes */
#include <libxml/tree.h>
#include <libxml/xpath.h>
#include <libxml/encoding.h>
#endif
/* libc includes */
#include <assert.h>
@ -61,7 +59,6 @@ without prior permission by the authors of Eressea.
#include <limits.h>
#include <string.h>
#ifdef USE_LIBXML2
static variant xml_fraction(xmlNodePtr node, const char *name) {
xmlChar *propValue = xmlGetProp(node, BAD_CAST name);
@ -284,13 +281,13 @@ static int parse_buildings(xmlDocPtr doc)
{
xmlXPathContextPtr xpath = xmlXPathNewContext(doc);
xmlXPathObjectPtr buildings;
int i;
/* reading eressea/buildings/building */
buildings =
xmlXPathEvalExpression(BAD_CAST "/eressea/buildings/building", xpath);
if (buildings->nodesetval != NULL) {
xmlNodeSetPtr nodes = buildings->nodesetval;
int i;
for (i = 0; i != nodes->nodeNr; ++i) {
xmlNodePtr node = nodes->nodeTab[i];
xmlChar *propValue;
@ -396,12 +393,12 @@ static int parse_ships(xmlDocPtr doc)
{
xmlXPathContextPtr xpath = xmlXPathNewContext(doc);
xmlXPathObjectPtr ships;
int i;
/* reading eressea/ships/ship */
ships = xmlXPathEvalExpression(BAD_CAST "/eressea/ships/ship", xpath);
if (ships->nodesetval != NULL) {
xmlNodeSetPtr nodes = ships->nodesetval;
int i;
for (i = 0; i != nodes->nodeNr; ++i) {
xmlNodePtr child, node = nodes->nodeTab[i];
xmlChar *propValue;
@ -810,7 +807,6 @@ static int parse_resources(xmlDocPtr doc)
resource_type *rtype;
unsigned int flags = RTF_NONE;
xmlXPathObjectPtr result;
int k;
if (xml_bvalue(node, "pooled", true))
flags |= RTF_POOLED;
@ -828,7 +824,8 @@ static int parse_resources(xmlDocPtr doc)
/* reading eressea/resources/resource/function */
xpath->node = node;
result = xmlXPathEvalExpression(BAD_CAST "function", xpath);
if (result->nodesetval != NULL)
if (result->nodesetval != NULL) {
int k;
for (k = 0; k != result->nodesetval->nodeNr; ++k) {
xmlNodePtr node = result->nodesetval->nodeTab[k];
pf_generic fun;
@ -852,6 +849,7 @@ static int parse_resources(xmlDocPtr doc)
}
xmlFree(propValue);
}
}
xmlXPathFreeObject(result);
if (xml_bvalue(node, "material", false)) {
@ -1760,4 +1758,3 @@ void register_xmlreader(void)
xml_register_callback(parse_strings);
xml_register_callback(parse_messages);
}
#endif

View File

@ -314,7 +314,7 @@ static void peasants(region * r, int rule)
{
int peasants = rpeasants(r);
int money = rmoney(r);
int maxp = production(r);
int maxp = max_production(r);
int n, satiated;
int dead = 0;
@ -433,14 +433,15 @@ static void horses(region * r)
rsethorses(r, (int)(horses * 0.9));
}
else if (maxhorses) {
int i;
double growth =
(RESOURCE_QUANTITY * HORSEGROWTH * 200 * (maxhorses -
horses)) / maxhorses;
if (growth > 0) {
if (a_find(r->attribs, &at_horseluck))
int i;
if (a_find(r->attribs, &at_horseluck)) {
growth *= 2;
}
/* printf("Horses: <%d> %d -> ", growth, horses); */
i = (int)(0.5 + (horses * 0.0001) * growth);
/* printf("%d\n", horses); */
@ -562,13 +563,13 @@ growing_trees_e3(region * r, const int current_season,
static void
growing_trees(region * r, const int current_season, const int last_weeks_season)
{
int growth, grownup_trees, i, seeds, sprout;
direction_t d;
int grownup_trees, i, seeds, sprout;
attrib *a;
if (current_season == SEASON_SUMMER || current_season == SEASON_AUTUMN) {
double seedchance = 0.01F * RESOURCE_QUANTITY;
int elves = count_race(r, get_race(RC_ELF));
direction_t d;
a = a_find(r->attribs, &at_germs);
if (a && last_weeks_season == SEASON_SPRING) {
@ -588,12 +589,12 @@ growing_trees(region * r, const int current_season, const int last_weeks_season)
return;
}
if (production(r) <= 0)
if (max_production(r) <= 0)
return;
/* Grundchance 1.0% */
/* Jeder Elf in der Region erhöht die Chance marginal */
elves = MIN(elves, production(r) / 8);
elves = MIN(elves, max_production(r) / 8);
if (elves) {
seedchance += 1.0 - pow(0.99999, elves * RESOURCE_QUANTITY);
}
@ -638,6 +639,7 @@ growing_trees(region * r, const int current_season, const int last_weeks_season)
}
else if (current_season == SEASON_SPRING) {
int growth;
if (is_cursed(r->attribs, &ct_godcursezone))
return;
@ -2153,7 +2155,6 @@ int email_cmd(unit * u, struct order *ord)
int password_cmd(unit * u, struct order *ord)
{
char pwbuf[32];
int i;
const char *s;
bool pwok = true;
@ -2161,6 +2162,7 @@ int password_cmd(unit * u, struct order *ord)
s = gettoken(pwbuf, sizeof(pwbuf));
if (!s || !*s) {
int i;
for (i = 0; i < 6; i++)
pwbuf[i] = (char)(97 + rng_int() % 26);
pwbuf[6] = 0;
@ -4272,7 +4274,7 @@ void update_subscriptions(void)
int subscription, fno;
faction *f;
if (fscanf(F, "%d %4s", &subscription, zFaction) <= 0)
if (fscanf(F, "%4d %4s", &subscription, zFaction) <= 0)
break;
fno = atoi36(zFaction);
f = findfaction(fno);
@ -4358,7 +4360,7 @@ bool cansee_unit(const unit * u, const unit * target, int modifier)
else if (target->faction == u->faction)
return true;
else {
int n, rings, o;
int n, rings;
if (is_guard(target) || usiege(target) || target->building
|| target->ship) {
@ -4375,7 +4377,7 @@ bool cansee_unit(const unit * u, const unit * target, int modifier)
return false;
}
if (skill_enabled(SK_PERCEPTION)) {
o = effskill(u, SK_PERCEPTION, target->region);
int o = effskill(u, SK_PERCEPTION, target->region);
if (o >= n) {
return true;
}
@ -4394,7 +4396,6 @@ cansee_durchgezogen(const faction * f, const region * r, const unit * u,
/* und es muss niemand aus f in der region sein, wenn sie vom Turm
* erblickt wird */
{
int n;
unit *u2;
if (fval(u_race(u), RCF_INVISIBLE) || u->number == 0)
@ -4402,7 +4403,7 @@ cansee_durchgezogen(const faction * f, const region * r, const unit * u,
else if (u->faction == f)
return true;
else {
int rings;
int rings, n;
if (is_guard(u) || usiege(u) || u->building || u->ship) {
return true;

View File

@ -4,7 +4,6 @@ autoseed.c
gmcmd.c
museum.c
score.c
weather.c
xmas.c
)
FOREACH(_FILE ${_FILES})

View File

@ -155,7 +155,7 @@ newfaction *read_newfactions(const char *filename)
email[0] = '\0';
password[0] = '\0';
if (sscanf(buf, "%54s %19s %7s %15s %d %d", email, race, lang,
if (sscanf(buf, "%54s %19s %7s %15s %4d %4d", email, race, lang,
password, &subscription, &alliance) < 3) {
break;
}

View File

@ -20,7 +20,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <kernel/config.h>
#if MUSEUM_MODULE
#include "museum.h"
/* kernel includes */
@ -502,5 +501,3 @@ void register_museum(void)
register_item_use(use_museumkey, "use_questkey1");
register_item_use(use_museumkey, "use_questkey2");
}
#endif

View File

@ -20,10 +20,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#define HEADER_MUSEUM_H
#ifdef __cplusplus
extern "C" {
#endif
#if MUSEUM_MODULE == 0
#error "must define MUSEUM_MODULE to use this module"
#endif
extern struct attrib_type at_warden;

View File

@ -1,132 +0,0 @@
/*
Copyright (c) 1998-2015, Enno Rehling <enno@eressea.de>
Katja Zedel <katze@felidae.kn-bremen.de
Christian Schlittchen <corwin@amber.kn-bremen.de>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**/
#ifdef WEATHER
#include <platform.h>
#include <config.h>
#include "weather.h"
/* libc includes */
#include <math.h>
weather *create_weather(region * r, weather_t type)
{
weather *w;
w = calloc(1, sizeof(weather));
w->center[0] = r->x;
w->center[1] = r->y;
w->type = type;
w->move[0] = (rng_int() % 3) - 1;
w->move[1] = (rng_int() % 3) - 1;
switch (type) {
case WEATHER_STORM:
w->radius = rng_int() % 2 + 1;
break;
case WEATHER_HURRICANE:
w->radius = 1;
break;
default:
w->radius = 0;
}
addlist(&weathers, w);
return w;
}
double distance(int x1, int y1, int x2, int y2)
{
return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
/* Diese Funktion ermittelt für jede Region, welches Wetter in ihr
herrscht. Die Wettertypen sind dabei nach ihrer Reihenfolge in der
enumeration priorisiert.
- Einladen
set_weather();
- Eigentliche Auswertung
- Veränderungen des Wetters
set_weather();
- Report generieren
- Abspeichern
Diese Routine ist sehr rechenaufwendig!
*/
void set_weather(void)
{
weather_t i;
weather *w;
short x, y;
int d;
region *r;
for (r = regions; r; r = r->next) {
r->weathertype = WEATHER_NONE;
}
for (i = 0; i < MAXWEATHERS; i++) {
for (w = weathers; w; w = w->next) {
if (w->type == i) {
for (x = w->center[0] - w->radius; x <= w->center[0] + w->radius; x++) {
for (y = w->center[1] - w->radius; y <= w->center[1] + w->radius; y++) {
d = distance(w->center[0], w->center[1], x, y);
if (floor(d + 0.5) <= w->radius) {
r = findregion(x, y);
if (r) {
r->weathertype = w->type;
}
}
}
}
}
}
}
}
void move_weather(void)
{
weather *w, *wnext;
region *r;
for (w = weathers; w;) {
wnext = w->next;
w->center[0] = w->center[0] + w->move[0];
w->center[1] = w->center[1] + w->move[1];
r = findregion(w->center[0], w->center[1]);
if (!r || rng_int() % 100 < 5) {
removelist(&weathers, w);
}
w = wnext;
}
}
#else
#include <stdio.h>
static const char *copyright = "(c) Eressea PBEM 2000";
void init_weather(void)
{
fputs(copyright, stderr);
/* TODO: Initialization */
}
#endif

View File

@ -1,54 +0,0 @@
/*
Copyright (c) 1998-2015, Enno Rehling <enno@eressea.de>
Katja Zedel <katze@felidae.kn-bremen.de
Christian Schlittchen <corwin@amber.kn-bremen.de>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**/
#ifndef H_MOD_WEATHER_H
#define H_MOD_WEATHER_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef WEATHER
# error "the weather system is disabled"
#endif
enum {
WEATHER_NONE,
WEATHER_STORM,
WEATHER_HURRICANE,
MAXWEATHERS
};
typedef unsigned char weather_t;
typedef struct weather {
struct weather *next;
weather_t type; /* Typ der Wetterzone */
int center[2]; /* Koordinaten des Zentrums */
int radius;
int move[2];
} weather;
weather *weathers;
void set_weather(void);
void move_weather(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1764,9 +1764,9 @@ static void sail(unit * u, order * ord, region_list ** routep, bool drifting)
}
if (!flying_ship(sh)) {
int stormchance = 0;
int reason;
if (storms_enabled) {
int stormchance = 0;
int stormyness;
gamedate date;
get_gamedate(turn, &date);
@ -2323,22 +2323,6 @@ int follow_ship(unit * u, order * ord)
return 1; /* true -> Einheitenliste von vorne durchgehen */
}
void destroy_damaged_ships(void)
{
region *r;
ship *sh, *shn;
for (r = regions; r; r = r->next) {
for (sh = r->ships; sh;) {
shn = sh->next;
if (sh->damage >= sh->size * DAMAGE_SCALE) {
remove_ship(&sh->region->ships, sh);
}
sh = shn;
}
}
}
/* Bewegung, Verfolgung, Piraterie */
/** ships that folow other ships

View File

@ -974,7 +974,7 @@ void report_region(struct stream *out, const region * r, faction * f)
/* Trees */
trees = rtrees(r, 2);
saplings = rtrees(r, 1);
if (production(r)) {
if (max_production(r)) {
if (trees > 0 || saplings > 0) {
bytes = snprintf(bufp, size, ", %d/%d ", trees, saplings);
if (wrptr(&bufp, &size, bytes) != 0)
@ -1311,7 +1311,7 @@ static void statistics(struct stream *out, const region * r, const faction * f)
paragraph(out, buf, 2, 2, 0);
msg_release(m);
}
if (production(r) && (!fval(r->terrain, SEA_REGION)
if (max_production(r) && (!fval(r->terrain, SEA_REGION)
|| f->race == get_race(RC_AQUARIAN))) {
if (markets_module()) { /* hack */
m =

View File

@ -24,12 +24,6 @@
#define ROW_FACTOR 3 /* factor for combat row advancement rule */
/* optional game components. TODO: These should either be
* configuration variables (XML), script extensions (lua),
* or both. We don't want separate binaries for different games
*/
#define MUSEUM_MODULE 1
/* TODO: move these settings to settings.h or into configuration files */
#define TREESIZE (8) /* space used by trees (in #peasants) */
#define PEASANTFORCE 0.75 /* Chance einer Vermehrung trotz 90% Auslastung */

View File

@ -1280,10 +1280,8 @@ static int sp_rosthauch(castorder * co)
add_ironweapon(it_find("axe"), it_find("rustyaxe"), 1.0);
add_ironweapon(it_find("greatsword"), it_find("rustygreatsword"), 1.0);
add_ironweapon(it_find("halberd"), it_find("rustyhalberd"), 0.5f);
#ifndef NO_RUSTY_ARMOR
add_ironweapon(it_find("shield"), it_find("rustyshield"), 0.5f);
add_ironweapon(it_find("chainmail"), it_find("rustychainmail"), 0.2f);
#endif
}
if (force > 0) {
@ -2358,7 +2356,6 @@ static int sp_earthquake(castorder * co)
/* ------------------------------------------------------------- */
void patzer_peasantmob(const castorder * co)
{
int anteil = 6, n;
unit *u;
attrib *a;
region *r;
@ -2370,8 +2367,9 @@ void patzer_peasantmob(const castorder * co)
faction *f = get_monsters();
const struct locale *lang = f->locale;
message *msg;
int anteil, n;
anteil += rng_int() % 4;
anteil = 6 + rng_int() % 4;
n = rpeasants(r) * anteil / 10;
rsetpeasants(r, rpeasants(r) - n);
assert(rpeasants(r) >= 0);
@ -2966,12 +2964,12 @@ static int sp_deathcloud(castorder * co)
return co->level;
}
void patzer_deathcloud(castorder * co)
static void patzer_deathcloud(const castorder * co)
{
unit *mage = co->magician.u;
int hp = (mage->hp - 2);
change_hitpoints(mage, -rng_int() % hp);
change_hitpoints(mage, -(rng_int() % hp));
ADDMSG(&mage->faction->msgs, msg_message("magic_fumble",
"unit region command", mage, mage->region, co->order));
@ -4527,28 +4525,6 @@ int sp_illusionary_shapeshift(castorder * co)
return cast_level;
}
/* ------------------------------------------------------------- */
/* Name: Regionstraum analysieren
* Stufe: 9
* Aura: 18
* Kosten: SPC_FIX
* Wirkung:
* Zeigt die Verzauberungen eines Objekts an (curse->name,
* curse::info). Aus der Differenz Spruchstaerke und Curse->vigour
* ergibt sich die Chance den Spruch zu identifizieren ((force -
* c->vigour)*10 + 100 %).
*/
int sp_analyseregionsdream(castorder * co)
{
region *r = co_get_region(co);
unit *mage = co->magician.u;
int cast_level = co->level;
magicanalyse_region(r, mage, cast_level);
return cast_level;
}
/* ------------------------------------------------------------- */
/* Name: Traumbilder erkennen
* Stufe: 5
@ -5476,7 +5452,8 @@ int sp_fetchastral(castorder * co)
return cast_level;
}
#ifdef SHOWASTRAL_NOT_BORKED
#define SHOWASTRAL_IS_BORKED
#ifndef SHOWASTRAL_IS_BORKED
int sp_showastral(castorder * co)
{
unit *u;
@ -5563,8 +5540,6 @@ int sp_showastral(castorder * co)
free_regionlist(rl);
return cast_level;
UNUSED_ARG(co);
return 0;
}
#endif
@ -6144,89 +6119,6 @@ int sp_speed2(castorder * co)
return MAX(1, used);
}
/* ------------------------------------------------------------- */
/* Name: Magiefresser
* Stufe: 7
* Kosten: SPC_LEVEL
*
* Wirkung:
* Kann eine bestimmte Verzauberung angreifen und aufloesen. Die Staerke
* des Zaubers muss staerker sein als die der Verzauberung.
* Syntax:
* ZAUBERE \"Magiefresser\" REGION
* ZAUBERE \"Magiefresser\" EINHEIT <Einheit-Nr>
* ZAUBERE \"Magiefresser\" GEBAEUDE <Gebaeude-Nr>
* ZAUBERE \"Magiefresser\" SCHIFF <Schiff-Nr>
*
* "kc?c"
* Flags:
* (FARCASTING | SPELLLEVEL | ONSHIPCAST | TESTCANSEE)
*/
/* Jeder gebrochene Zauber verbraucht c->vigour an Zauberkraft
* (force) */
int sp_q_antimagie(castorder * co)
{
attrib **ap;
int obj;
curse *c = NULL;
int succ;
region *r = co_get_region(co);
unit *mage = co->magician.u;
int cast_level = co->level;
double force = co->force;
spellparameter *pa = co->par;
const char *ts = NULL;
obj = pa->param[0]->typ;
switch (obj) {
case SPP_REGION:
ap = &r->attribs;
ts = regionname(r, mage->faction);
break;
case SPP_TEMP:
case SPP_UNIT:
{
unit *u = pa->param[0]->data.u;
ap = &u->attribs;
ts = itoa36(u->no);
break;
}
case SPP_BUILDING:
{
building *b = pa->param[0]->data.b;
ap = &b->attribs;
ts = itoa36(b->no);
break;
}
case SPP_SHIP:
{
ship *sh = pa->param[0]->data.sh;
ap = &sh->attribs;
ts = itoa36(sh->no);
break;
}
default:
/* Das Zielobjekt wurde vergessen */
cmistake(mage, co->order, 203, MSG_MAGIC);
return 0;
}
succ = break_curse(ap, cast_level, force, c);
if (succ) {
ADDMSG(&mage->faction->msgs, msg_message("destroy_magic_effect",
"unit region command succ target", mage, mage->region, co->order, succ,
ts));
}
else {
ADDMSG(&mage->faction->msgs, msg_message("destroy_magic_noeffect",
"unit region command", mage, mage->region, co->order));
}
return MAX(succ, 1);
}
/* ------------------------------------------------------------- */
/* Name: Fluch brechen
* Stufe: 7
@ -6541,7 +6433,7 @@ static spelldata spell_functions[] = {
{ "forestfire", sp_forest_fire, patzer_peasantmob },
{ "draigdestroymagic", sp_destroy_magic, 0 },
{ "unholypower", sp_unholypower, 0 },
{ "deathcloud", sp_deathcloud, patzer_peasantmob },
{ "deathcloud", sp_deathcloud, patzer_deathcloud },
{ "summondragon", sp_summondragon, patzer_peasantmob },
{ "summonshadowlords", sp_summonshadowlords, patzer_peasantmob },
{ "chaossuction", sp_chaossuction, patzer_peasantmob },
@ -6567,7 +6459,7 @@ static spelldata spell_functions[] = {
{ "mindblast", sp_mindblast_temp, 0 },
{ "orkdream", sp_sweetdreams, 0 },
/* M_CERDDOR */
{ "appeasement", sp_denyattack, 0 },
{ "appeasement", sp_appeasement, 0 },
{ "song_of_healing", sp_healing, 0 },
{ "generous", sp_generous, 0 },
{ "song_of_fear", sp_song_of_fear, 0 },
@ -6600,7 +6492,7 @@ static spelldata spell_functions[] = {
{ "analyze_magic", sp_analysemagic, 0 },
{ "concealing_aura", sp_itemcloak, 0 },
{ "tybiedfumbleshield", sp_fumbleshield, 0 },
#ifdef SHOWASTRAL_NOT_BORKED
#ifndef SHOWASTRAL_IS_BORKED
{ "show_astral", sp_showastral, 0 },
#endif
{ "resist_magic", sp_resist_magic_bonus, 0 },

View File

@ -622,7 +622,6 @@ int sp_dragonodem(struct castorder * co)
troop dt;
troop at;
int force, enemies;
int killed = 0;
const char *damage;
/* 11-26 HP */
@ -641,6 +640,7 @@ int sp_dragonodem(struct castorder * co)
}
else {
struct message *m;
int killed = 0;
at.fighter = fi;
at.index = 0;
@ -717,53 +717,6 @@ int sp_immolation(struct castorder * co)
return level;
}
int sp_drainodem(fighter * fi, int level, double power, spell * sp)
{
battle *b = fi->side->battle;
troop dt;
troop at;
int force, enemies;
int drained = 0;
int killed = 0;
const char *damage;
message *m;
/* 11-26 HP */
damage = spell_damage(4);
/* Jungdrache 3->54, Drache 6->216, Wyrm 12->864 Treffer */
force = lovar(get_force(power, 6));
enemies = count_enemies(b, fi, FIGHT_ROW, BEHIND_ROW - 1, SELECT_ADVANCE);
if (!enemies) {
m = msg_message("spell_out_of_range", "mage spell", fi->unit, sp);
message_all(b, m);
msg_release(m);
return 0;
}
at.fighter = fi;
at.index = 0;
while (force && drained < enemies) {
dt = select_enemy(fi, FIGHT_ROW, BEHIND_ROW - 1, SELECT_ADVANCE);
assert(dt.fighter);
if (hits(at, dt, NULL)) {
drain_exp(dt.fighter->unit, 90);
++drained;
killed += terminate(dt, at, AT_COMBATSPELL, damage, false);
}
--force;
}
m =
msg_message("cast_drainlife_effect", "mage spell amount", fi->unit, sp,
drained);
message_all(b, m);
msg_release(m);
return level;
}
/* ------------------------------------------------------------- */
/* PRECOMBAT */
@ -1309,7 +1262,7 @@ int sp_reeling_arrows(struct castorder * co)
/* Magier weicht dem Kampf aus. Wenn er sich bewegen kann, zieht er in
* eine Nachbarregion, wobei ein NACH ber<EFBFBD>cksichtigt wird. Ansonsten
* bleibt er stehen und nimmt nicht weiter am Kampf teil. */
int sp_denyattack(struct castorder * co)
int sp_appeasement(struct castorder * co)
{
fighter * fi = co->magician.fig;
int level = co->level;

View File

@ -30,7 +30,7 @@ extern "C" {
int sp_berserk(struct castorder * co);
int sp_tiredsoldiers(struct castorder * co);
int sp_reeling_arrows(struct castorder * co);
int sp_denyattack(struct castorder * co);
int sp_appeasement(struct castorder * co);
int sp_sleep(struct castorder * co);
int sp_windshield(struct castorder * co);
int sp_strong_wall(struct castorder * co);

View File

@ -12,17 +12,6 @@
#include <string.h>
#include <stdlib.h>
faction *get_faction_by_id(int uid)
{
faction *f;
for (f = factions; f; f = f->next) {
if (f->subscription == uid) {
return f;
}
}
return NULL;
}
typedef struct db_faction {
int uid;
int no;

244
src/steal.c Normal file
View File

@ -0,0 +1,244 @@
/*
Copyright (c) 1998-2014,
Enno Rehling <enno@eressea.de>
Katja Zedel <katze@felidae.kn-bremen.de
Christian Schlittchen <corwin@amber.kn-bremen.de>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**/
#include <platform.h>
#include <kernel/config.h>
#include "economy.h"
#include "laws.h"
#include "skill.h"
#include "study.h"
#include <util/message.h>
#include <kernel/build.h>
#include <kernel/faction.h>
#include <kernel/item.h>
#include <kernel/messages.h>
#include <kernel/order.h>
#include <kernel/plane.h>
#include <kernel/pool.h>
#include <kernel/race.h>
#include <kernel/region.h>
#include <kernel/terrain.h>
#include <kernel/unit.h>
#include <assert.h>
#include <limits.h>
#include <stdlib.h>
void expandstealing(region * r, econ_request * stealorders)
{
const resource_type *rsilver = get_resourcetype(R_SILVER);
unsigned int j;
unsigned int norders;
econ_request *requests;
assert(rsilver);
norders = expand_production(r, stealorders, &requests);
if (!norders) return;
/* F<>r jede unit in der Region wird Geld geklaut, wenn sie Opfer eines
* Beklauen-Orders ist. Jedes Opfer muss einzeln behandelt werden.
*
* u ist die beklaute unit. oa.unit ist die klauende unit.
*/
for (j = 0; j != norders; j++) {
unit *u;
int n = 0;
if (requests[j].unit->n > requests[j].unit->wants) {
break;
}
u = findunitg(requests[j].no, r);
if (u && u->region == r) {
n = get_pooled(u, rsilver, GET_ALL, INT_MAX);
}
if (n > 10 && rplane(r) && (rplane(r)->flags & PFL_NOALLIANCES)) {
/* In Questen nur reduziertes Klauen */
n = 10;
}
if (n > 0) {
n = MIN(n, requests[j].unit->wants);
use_pooled(u, rsilver, GET_ALL, n);
requests[j].unit->n = n;
change_money(requests[j].unit, n);
ADDMSG(&u->faction->msgs, msg_message("stealeffect", "unit region amount",
u, u->region, n));
}
add_income(requests[j].unit, IC_STEAL, requests[j].unit->wants, requests[j].unit->n);
fset(requests[j].unit, UFL_LONGACTION | UFL_NOTMOVING);
}
free(requests);
}
static int max_skill(region * r, struct faction * f, skill_t sk)
{
unit *u;
int w = 0;
for (u = r->units; u; u = u->next) {
if (u->faction == f) {
int effsk = effskill(u, sk, 0);
if (effsk > w) {
w = effsk;
}
}
}
return w;
}
message * steal_message(const unit * u, struct order *ord) {
plane *pl;
if (fval(u_race(u), RCF_NOSTEAL)) {
return msg_feedback(u, ord, "race_nosteal", "race", u_race(u));
}
if (fval(u->region->terrain, SEA_REGION) && u_race(u) != get_race(RC_AQUARIAN)) {
return msg_feedback(u, ord, "error_onlandonly", "");
}
pl = rplane(u->region);
if (pl && fval(pl, PFL_NOATTACK)) {
return msg_feedback(u, ord, "error270", "");
}
return 0;
}
void steal_cmd(unit * u, struct order *ord, econ_request ** stealorders)
{
const resource_type *rring = get_resourcetype(R_RING_OF_NIMBLEFINGER);
int n, i, id, effsk;
bool goblin = false;
econ_request *o;
unit *u2 = NULL;
region *r = u->region;
faction *f = NULL;
message * msg;
keyword_t kwd;
kwd = init_order_depr(ord);
assert(kwd == K_STEAL);
assert(skill_enabled(SK_PERCEPTION) && skill_enabled(SK_STEALTH));
msg = steal_message(u, ord);
if (msg) {
ADDMSG(&u->faction->msgs, msg);
return;
}
id = read_unitid(u->faction, r);
if (id > 0) {
u2 = findunitr(r, id);
}
if (u2 && u2->region == u->region) {
f = u2->faction;
}
else {
/* TODO: is this really necessary? it's the only time we use faction.c/deadhash
* it allows stealing from a unit in a dead faction, but why? */
f = dfindhash(id);
}
for (u2 = r->units; u2; u2 = u2->next) {
if (u2->faction == f && cansee(u->faction, r, u2, 0))
break;
}
if (!u2) {
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found",
""));
return;
}
if (IsImmune(u2->faction)) {
ADDMSG(&u->faction->msgs,
msg_feedback(u, ord, "newbie_immunity_error", "turns", NewbieImmunity()));
return;
}
if (u->faction->alliance && u->faction->alliance == u2->faction->alliance) {
cmistake(u, ord, 47, MSG_INCOME);
return;
}
assert(u->region == u2->region);
if (!can_contact(r, u, u2)) {
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error60", ""));
return;
}
effsk = effskill(u, SK_STEALTH, 0);
n = effsk - max_skill(r, f, SK_PERCEPTION);
if (n <= 0) {
/* Wahrnehmung == Tarnung */
if (u_race(u) != get_race(RC_GOBLIN) || effsk <= 3) {
ADDMSG(&u->faction->msgs, msg_message("stealfail", "unit target", u, u2));
if (n == 0) {
ADDMSG(&u2->faction->msgs, msg_message("stealdetect", "unit", u2));
}
else {
ADDMSG(&u2->faction->msgs, msg_message("thiefdiscover", "unit target",
u, u2));
}
return;
}
else {
ADDMSG(&u->faction->msgs, msg_message("stealfatal", "unit target", u,
u2));
ADDMSG(&u2->faction->msgs, msg_message("thiefdiscover", "unit target", u,
u2));
n = 1;
goblin = true;
}
}
i = MIN(u->number, i_get(u->items, rring->itype));
if (i > 0) {
n *= STEALINCOME * (u->number + i * (roqf_factor() - 1));
}
else {
n *= u->number * STEALINCOME;
}
u->wants = n;
/* wer dank unsichtbarkeitsringen klauen kann, muss nicht unbedingt ein
* guter dieb sein, schliesslich macht man immer noch sehr viel laerm */
o = (econ_request *)calloc(1, sizeof(econ_request));
o->unit = u;
o->qty = 1; /* Betrag steht in u->wants */
o->no = u2->no;
o->type.goblin = goblin; /* Merken, wenn Goblin-Spezialklau */
o->next = *stealorders;
*stealorders = o;
/* Nur soviel PRODUCEEXP wie auch tatsaechlich gemacht wurde */
produceexp(u, SK_STEALTH, MIN(n, u->number));
}

View File

@ -811,23 +811,21 @@ void produceexp(struct unit *u, skill_t sk, int n)
produceexp_ex(u, sk, n, learn_skill);
}
#ifndef NO_TESTS
static learn_fun inject_learn_fun = 0;
void inject_learn(learn_fun fun) {
inject_learn_fun = fun;
}
#endif
/** days should be scaled by u->number; STUDYDAYS * u->number is one week worth of learning */
void learn_skill(unit *u, skill_t sk, int days) {
int leveldays = STUDYDAYS * u->number;
int weeks = 0;
#ifndef NO_TESTS
if (inject_learn_fun) {
inject_learn_fun(u, sk, days);
return;
}
#endif
while (days >= leveldays) {
++weeks;
days -= leveldays;

View File

@ -56,9 +56,7 @@ extern "C" {
extern const struct attrib_type at_learning;
#ifndef NO_TESTS
void inject_learn(learn_fun fun);
#endif
#ifdef __cplusplus
}

View File

@ -19,7 +19,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <platform.h>
#include "shock.h"
#include "magic.h"
#include <magic.h>
/* kernel includes */
#include <kernel/curse.h>

View File

@ -537,5 +537,5 @@ void a_write_orig(struct storage *store, const attrib * attribs, const void *own
void attrib_done(void) {
cb_clear(&cb_deprecated);
memset(at_hash, 0, sizeof at_hash);
memset(at_hash, 0, sizeof(at_hash[0]) * MAXATHASH);
}

View File

@ -57,13 +57,14 @@ const char *itoab(int i, int base)
static char sstr[80];
char *s, *dst;
static int index = 0; /* STATIC_XCALL: used across calls */
int neg = 0;
s = sstr + (index * 20);
index = (index + 1) & 3; /* quick for % 4 */
dst = s + 19;
(*dst--) = 0;
if (i != 0) {
int neg = 0;
if (i < 0) {
i = -i;
neg = 1;

View File

@ -78,8 +78,6 @@ char * strlcpy_w(char *dst, const char *src, size_t *siz, const char *err, const
return buf;
}
#ifndef HAVE_STRLCAT
#define HAVE_STRLCAT
size_t strlcat(char *dst, const char *src, size_t siz)

View File

@ -76,16 +76,6 @@ void translist(void *l1, void *l2, void *p)
addlist(l2, p);
}
void insertlist(void_list ** l, void_list * p)
{
/* insert entry p at the beginning of list l */
p->next = *l;
*l = p;
}
void removelist(void *l, void *p)
{

View File

@ -33,14 +33,8 @@ extern "C" {
void freestrlist(strlist * s);
void addlist(void *l1, void *p1);
void translist(void *l1, void *l2, void *p);
#ifndef MALLOCDBG
void freelist(void *p1);
void removelist(void *l, void *p);
#else
#define freelist(p) { while (p) { void * p2 = p->next; free(p); p = p2; } }
#define removelist(l,p) { choplist(l, p); free(p); }
#endif
unsigned int listlen(void *l);
#ifdef __cplusplus

View File

@ -60,7 +60,7 @@ arg_type *find_argtype(const char *name)
message_type *mt_new(const char *name, const char *args[])
{
int i, nparameters = 0;
int nparameters = 0;
message_type *mtype;
assert(name != NULL);
@ -85,6 +85,8 @@ message_type *mt_new(const char *name, const char *args[])
mtype->types = NULL;
}
if (args != NULL) {
int i;
for (i = 0; args[i]; ++i) {
const char *x = args[i];
const char *spos = strchr(x, ':');

View File

@ -16,10 +16,8 @@
#include "log.h"
#include "assert.h"
#ifdef USE_LIBXML2
#include <libxml/catalog.h>
#include <libxml/xmlstring.h>
#endif
/* libc includes */
#include <stdio.h>
@ -27,7 +25,6 @@
#include <string.h>
#include <ctype.h>
#ifdef USE_LIBXML2
int xml_ivalue(xmlNodePtr node, const char *name, int dflt)
{
int i = dflt;
@ -110,11 +107,9 @@ void xml_register_callback(xml_callback callback)
insert = &(*insert)->next;
*insert = reader;
}
#endif
int read_xml(const char *filename, const char *catalog)
{
#ifdef USE_LIBXML2
xml_reader *reader = xmlReaders;
xmlDocPtr doc;
int result;
@ -141,8 +136,4 @@ int read_xml(const char *filename, const char *catalog)
}
xmlFreeDoc(doc);
return result;
#else
log_error("LIBXML2 disabled, cannot read %s.\n", filename);
return -1;
#endif
}

View File

@ -19,7 +19,6 @@
extern "C" {
#endif
#ifdef USE_LIBXML2
/* new xml functions: */
#include <libxml/tree.h>
@ -30,7 +29,6 @@ extern "C" {
double xml_fvalue(xmlNodePtr node, const char *name, double dflt);
int xml_ivalue(xmlNodePtr node, const char *name, int dflt);
bool xml_bvalue(xmlNodePtr node, const char *name, bool dflt);
#endif
void xml_done(void);
int read_xml(const char *filename, const char *catalog);