Merge pull request #682 from ennorehling/develop

cmake changes, skillmod rewrite
This commit is contained in:
Enno Rehling 2017-04-08 22:14:53 +02:00 committed by GitHub
commit 1c509485f7
61 changed files with 1181 additions and 669 deletions

3
.gitmodules vendored
View file

@ -1,9 +1,6 @@
[submodule "lunit"] [submodule "lunit"]
path = lunit path = lunit
url = https://github.com/ennorehling/lunit.git url = https://github.com/ennorehling/lunit.git
[submodule "cmake"]
path = cmake
url = https://github.com/ennorehling/cmake.git
[submodule "dlmalloc"] [submodule "dlmalloc"]
path = dlmalloc path = dlmalloc
url = https://github.com/ennorehling/dlmalloc.git url = https://github.com/ennorehling/dlmalloc.git

View file

@ -1,17 +1,29 @@
cmake_minimum_required(VERSION 2.6) cmake_minimum_required(VERSION 2.8)
project (eressea-server C)
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/Modules/" ${CMAKE_MODULE_PATH})
if (WIN32) if (WIN32)
FILE(TO_CMAKE_PATH "${CMAKE_MODULE_PATH}" CMAKE_MODULE_PATH ) FILE(TO_CMAKE_PATH "${CMAKE_MODULE_PATH}" CMAKE_MODULE_PATH )
FILE(TO_CMAKE_PATH "${CMAKE_PREFIX_PATH}" CMAKE_PREFIX_PATH ) FILE(TO_CMAKE_PATH "${CMAKE_PREFIX_PATH}" CMAKE_PREFIX_PATH )
endif(WIN32) endif(WIN32)
project (eressea-server C) if (MSVC)
include(MSVC)
endif (MSVC)
enable_testing()
find_package (LibXml2)
find_package (SQLite3) find_package (SQLite3)
find_package (Curses) find_package (Curses)
find_package (Lua REQUIRED) find_package (LibXml2)
find_package (ToLua REQUIRED) find_package (ToLua REQUIRED)
if (TOLUA_FOUND)
if (${TOLUA_VERSION_STRING} VERSION_GREATER "5.2")
find_package (Lua 5.2 REQUIRED)
elseif (${TOLUA_VERSION_STRING} VERSION_GREATER "5.1")
find_package (Lua 5.1 REQUIRED)
endif()
endif(TOLUA_FOUND)
enable_testing()
add_subdirectory (cJSON) add_subdirectory (cJSON)
add_subdirectory (storage) add_subdirectory (storage)
@ -19,8 +31,10 @@ add_subdirectory (iniparser)
add_subdirectory (clibs) add_subdirectory (clibs)
add_subdirectory (process) add_subdirectory (process)
add_subdirectory (src eressea) add_subdirectory (src eressea)
install(DIRECTORY res conf DESTINATION ${CMAKE_INSTALL_PREFIX} FILES_MATCHING PATTERN "*.xml") install(DIRECTORY res conf DESTINATION ${CMAKE_INSTALL_PREFIX} FILES_MATCHING PATTERN "*.xml")
install(DIRECTORY res conf DESTINATION ${CMAKE_INSTALL_PREFIX} FILES_MATCHING PATTERN "*.json") install(DIRECTORY res conf DESTINATION ${CMAKE_INSTALL_PREFIX} FILES_MATCHING PATTERN "*.json")
install(DIRECTORY scripts DESTINATION ${CMAKE_INSTALL_PREFIX} FILES_MATCHING PATTERN "*.lua") install(DIRECTORY scripts DESTINATION ${CMAKE_INSTALL_PREFIX} FILES_MATCHING PATTERN "*.lua")
install(DIRECTORY lunit DESTINATION ${CMAKE_INSTALL_PREFIX} FILES_MATCHING PATTERN "*.lua") install(DIRECTORY lunit DESTINATION ${CMAKE_INSTALL_PREFIX} FILES_MATCHING PATTERN "*.lua")
install(DIRECTORY share DESTINATION ${CMAKE_INSTALL_PREFIX}) install(DIRECTORY share DESTINATION ${CMAKE_INSTALL_PREFIX})

2
cJSON

@ -1 +1 @@
Subproject commit 43c04ad61258ec3d54a2167eb3a43915bd003ab1 Subproject commit 22a4fc9be31f0426e622f5bc9ebd7a1550845001

1
cmake

@ -1 +0,0 @@
Subproject commit f1fb3943ace59994d90d71a891b80033dc2700a2

172
cmake/Modules/FindLua.cmake Normal file
View file

@ -0,0 +1,172 @@
#.rst:
# FindLua
# -------
#
#
#
# Locate Lua library This module defines
#
# ::
#
# LUA_FOUND - if false, do not try to link to Lua
# LUA_LIBRARIES - both lua and lualib
# LUA_INCLUDE_DIR - where to find lua.h
# LUA_VERSION_STRING - the version of Lua found
# LUA_VERSION_MAJOR - the major version of Lua
# LUA_VERSION_MINOR - the minor version of Lua
# LUA_VERSION_PATCH - the patch version of Lua
#
#
#
# Note that the expected include convention is
#
# ::
#
# #include "lua.h"
#
# and not
#
# ::
#
# #include <lua/lua.h>
#
# This is because, the lua location is not standardized and may exist in
# locations other than lua/
#=============================================================================
# Copyright 2007-2009 Kitware, Inc.
# Copyright 2013 Rolf Eike Beer <eike@sf-mail.de>
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
unset(_lua_include_subdirs)
unset(_lua_library_names)
# this is a function only to have all the variables inside go away automatically
function(set_lua_version_vars)
set(LUA_VERSIONS5 5.3 5.2 5.1 5.0)
if (Lua_FIND_VERSION_EXACT)
if (Lua_FIND_VERSION_COUNT GREATER 1)
set(lua_append_versions ${Lua_FIND_VERSION_MAJOR}.${Lua_FIND_VERSION_MINOR})
endif ()
elseif (Lua_FIND_VERSION)
# once there is a different major version supported this should become a loop
if (NOT Lua_FIND_VERSION_MAJOR GREATER 5)
if (Lua_FIND_VERSION_COUNT EQUAL 1)
set(lua_append_versions ${LUA_VERSIONS5})
else ()
foreach (subver IN LISTS LUA_VERSIONS5)
if (NOT subver VERSION_LESS ${Lua_FIND_VERSION})
list(APPEND lua_append_versions ${subver})
endif ()
endforeach ()
endif ()
endif ()
else ()
# once there is a different major version supported this should become a loop
set(lua_append_versions ${LUA_VERSIONS5})
endif ()
foreach (ver IN LISTS lua_append_versions)
string(REGEX MATCH "^([0-9]+)\\.([0-9]+)$" _ver "${ver}")
list(APPEND _lua_include_subdirs
include/lua${CMAKE_MATCH_1}${CMAKE_MATCH_2}
include/lua${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
include/lua-${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
)
list(APPEND _lua_library_names
lua${CMAKE_MATCH_1}${CMAKE_MATCH_2}
lua${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
lua-${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
lua.${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
)
endforeach ()
set(_lua_include_subdirs "${_lua_include_subdirs}" PARENT_SCOPE)
set(_lua_library_names "${_lua_library_names}" PARENT_SCOPE)
endfunction(set_lua_version_vars)
set_lua_version_vars()
find_path(LUA_INCLUDE_DIR lua.h
HINTS
ENV LUA_DIR
PATH_SUFFIXES ${_lua_include_subdirs} include/lua include
PATHS
~/Library/Frameworks
/Library/Frameworks
/sw # Fink
/opt/local # DarwinPorts
/opt/csw # Blastwave
/opt
)
unset(_lua_include_subdirs)
find_library(LUA_LIBRARY
NAMES ${_lua_library_names} lua
HINTS
ENV LUA_DIR
PATH_SUFFIXES lib
PATHS
~/Library/Frameworks
/Library/Frameworks
/sw
/opt/local
/opt/csw
/opt
)
unset(_lua_library_names)
if (LUA_LIBRARY)
# include the math library for Unix
if (UNIX AND NOT APPLE AND NOT BEOS)
find_library(LUA_MATH_LIBRARY m)
set(LUA_LIBRARIES "${LUA_LIBRARY};${LUA_MATH_LIBRARY}")
# For Windows and Mac, don't need to explicitly include the math library
else ()
set(LUA_LIBRARIES "${LUA_LIBRARY}")
endif ()
endif ()
if (LUA_INCLUDE_DIR AND EXISTS "${LUA_INCLUDE_DIR}/lua.h")
# At least 5.[012] have different ways to express the version
# so all of them need to be tested. Lua 5.2 defines LUA_VERSION
# and LUA_RELEASE as joined by the C preprocessor, so avoid those.
file(STRINGS "${LUA_INCLUDE_DIR}/lua.h" lua_version_strings
REGEX "^#define[ \t]+LUA_(RELEASE[ \t]+\"Lua [0-9]|VERSION([ \t]+\"Lua [0-9]|_[MR])).*")
string(REGEX REPLACE ".*;#define[ \t]+LUA_VERSION_MAJOR[ \t]+\"([0-9])\"[ \t]*;.*" "\\1" LUA_VERSION_MAJOR ";${lua_version_strings};")
if (LUA_VERSION_MAJOR MATCHES "^[0-9]+$")
string(REGEX REPLACE ".*;#define[ \t]+LUA_VERSION_MINOR[ \t]+\"([0-9])\"[ \t]*;.*" "\\1" LUA_VERSION_MINOR ";${lua_version_strings};")
string(REGEX REPLACE ".*;#define[ \t]+LUA_VERSION_RELEASE[ \t]+\"([0-9])\"[ \t]*;.*" "\\1" LUA_VERSION_PATCH ";${lua_version_strings};")
set(LUA_VERSION_STRING "${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}.${LUA_VERSION_PATCH}")
else ()
string(REGEX REPLACE ".*;#define[ \t]+LUA_RELEASE[ \t]+\"Lua ([0-9.]+)\"[ \t]*;.*" "\\1" LUA_VERSION_STRING ";${lua_version_strings};")
if (NOT LUA_VERSION_STRING MATCHES "^[0-9.]+$")
string(REGEX REPLACE ".*;#define[ \t]+LUA_VERSION[ \t]+\"Lua ([0-9.]+)\"[ \t]*;.*" "\\1" LUA_VERSION_STRING ";${lua_version_strings};")
endif ()
string(REGEX REPLACE "^([0-9]+)\\.[0-9.]*$" "\\1" LUA_VERSION_MAJOR "${LUA_VERSION_STRING}")
string(REGEX REPLACE "^[0-9]+\\.([0-9]+)[0-9.]*$" "\\1" LUA_VERSION_MINOR "${LUA_VERSION_STRING}")
string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]).*" "\\1" LUA_VERSION_PATCH "${LUA_VERSION_STRING}")
endif ()
unset(lua_version_strings)
endif()
include(FindPackageHandleStandardArgs)
# handle the QUIETLY and REQUIRED arguments and set LUA_FOUND to TRUE if
# all listed variables are TRUE
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Lua
REQUIRED_VARS LUA_LIBRARIES LUA_INCLUDE_DIR
VERSION_VAR LUA_VERSION_STRING)
mark_as_advanced(LUA_INCLUDE_DIR LUA_LIBRARY LUA_MATH_LIBRARY)

View file

@ -0,0 +1,63 @@
# - Try to find the SQLite3 library
# Once done this will define
#
# SQLITE3_FOUND - System has SQLite3
# SQLITE3_INCLUDE_DIR - The SQLite3 include directory
# SQLITE3_LIBRARIES - The libraries needed to use SQLite3
# SQLITE3_DEFINITIONS - Compiler switches required for using SQLite3
# SQLITE3_EXECUTABLE - The SQLite3 command line shell
# SQLITE3_VERSION_STRING - the version of SQLite3 found (since CMake 2.8.8)
#=============================================================================
# Copyright 2006-2009 Kitware, Inc.
# Copyright 2006 Alexander Neundorf <neundorf@kde.org>
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
# use pkg-config to get the directories and then use these values
# in the find_path() and find_library() calls
find_package(PkgConfig QUIET)
PKG_CHECK_MODULES(PC_SQLITE QUIET sqlite3)
set(SQLITE3_DEFINITIONS ${PC_SQLITE_CFLAGS_OTHER})
find_path(SQLITE3_INCLUDE_DIR NAMES sqlite3.h
HINTS
${PC_SQLITE_INCLUDEDIR}
${PC_SQLITE_INCLUDE_DIRS}
)
find_library(SQLITE3_LIBRARIES NAMES sqlite3
HINTS
${PC_SQLITE_LIBDIR}
${PC_SQLITE_LIBRARY_DIRS}
)
find_program(SQLITE3_EXECUTABLE sqlite3)
if(PC_SQLITE_VERSION)
set(SQLITE3_VERSION_STRING ${PC_SQLITE_VERSION})
elseif(SQLITE3_INCLUDE_DIR AND EXISTS "${SQLITE3_INCLUDE_DIR}/sqlite3.h")
file(STRINGS "${SQLITE3_INCLUDE_DIR}/sqlite3.h" sqlite3_version_str
REGEX "^#define[\t ]+SQLITE_VERSION[\t ]+\".*\"")
string(REGEX REPLACE "^#define[\t ]+SQLITE_VERSION[\t ]+\"([^\"]*)\".*" "\\1"
SQLITE3_VERSION_STRING "${sqlite3_version_str}")
unset(sqlite3_version_str)
endif()
# handle the QUIETLY and REQUIRED arguments and set SQLITE3_FOUND to TRUE if
# all listed variables are TRUE
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(SQLite3
REQUIRED_VARS SQLITE3_LIBRARIES SQLITE3_INCLUDE_DIR
VERSION_VAR SQLITE3_VERSION_STRING)
mark_as_advanced(SQLITE3_INCLUDE_DIR SQLITE3_LIBRARIES SQLITE3_EXECUTABLE)

View file

@ -0,0 +1,71 @@
# - Try to find the ToLua library
# Once done this will define
#
# TOLUA_FOUND - System has ToLua
# TOLUA_INCLUDE_DIR - The ToLua include directory
# TOLUA_LIBRARIES - The libraries needed to use ToLua
# TOLUA_DEFINITIONS - Compiler switches required for using ToLua
# TOLUA_EXECUTABLE - The ToLua command line shell
# TOLUA_VERSION_STRING - the version of ToLua found (since CMake 2.8.8)
#=============================================================================
# Copyright 2006-2009 Kitware, Inc.
# Copyright 2006 Alexander Neundorf <neundorf@kde.org>
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
# use pkg-config to get the directories and then use these values
# in the find_path() and find_library() calls
find_package(PkgConfig QUIET)
PKG_CHECK_MODULES(PC_TOLUA QUIET ToLua)
set(TOLUA_DEFINITIONS ${PC_TOLUA_CFLAGS_OTHER})
find_path(TOLUA_INCLUDE_DIR NAMES tolua.h
HINTS
${PC_TOLUA_DIR}/include
${PC_TOLUA_INCLUDEDIR}
${PC_TOLUA_INCLUDE_DIRS}
)
find_library(TOLUA_LIBRARY NAMES tolua
HINTS
${PC_TOLUA_DIR}/lib
${PC_TOLUA_LIBDIR}
${PC_TOLUA_LIBRARY_DIRS}
)
find_program(TOLUA_EXECUTABLE tolua
HINTS
${PC_TOLUA_DIR}/bin
${PC_TOLUA_LIBDIR}
${PC_TOLUA_LIBRARY_DIRS}
)
SET( TOLUA_LIBRARIES "${TOLUA_LIBRARY}" CACHE STRING "ToLua Libraries")
if(PC_TOLUA_VERSION)
set(TOLUA_VERSION_STRING ${PC_TOLUA_VERSION})
elseif(TOLUA_INCLUDE_DIR AND EXISTS "${TOLUA_INCLUDE_DIR}/tolua.h")
file(STRINGS "${TOLUA_INCLUDE_DIR}/tolua.h" tolua_version_str
REGEX "^#define[\t ]+TOLUA_VERSION[\t ]+\".*\"")
string(REGEX REPLACE "^#define[\t ]+TOLUA_VERSION[\t ]+\"tolua ([^\"]*)\".*" "\\1"
TOLUA_VERSION_STRING "${tolua_version_str}")
unset(tolua_version_str)
endif()
# handle the QUIETLY and REQUIRED arguments and set TOLUA_FOUND to TRUE if
# all listed variables are TRUE
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(ToLua
REQUIRED_VARS TOLUA_LIBRARY TOLUA_INCLUDE_DIR TOLUA_EXECUTABLE
VERSION_VAR TOLUA_VERSION_STRING)
mark_as_advanced(TOLUA_INCLUDE_DIR TOLUA_LIBRARIES TOLUA_EXECUTABLE)

19
cmake/Modules/MSVC.cmake Normal file
View file

@ -0,0 +1,19 @@
MACRO (MSVC_CRT_SECURE_NO_WARNINGS)
IF (MSVC)
FOREACH (target ${ARGN})
SET_TARGET_PROPERTIES (${target} PROPERTIES
COMPILE_DEFINITIONS _CRT_SECURE_NO_WARNINGS
)
ENDFOREACH (target)
ENDIF (MSVC)
ENDMACRO (MSVC_CRT_SECURE_NO_WARNINGS)
MACRO (MSVC_SET_WARNING_LEVEL level)
IF (MSVC)
IF(CMAKE_C_FLAGS MATCHES "/W[0-4]")
STRING(REGEX REPLACE "/W[0-4]" "/W${level}" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
ELSE()
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W${level}")
ENDIF()
ENDIF(MSVC)
ENDMACRO (MSVC_SET_WARNING_LEVEL)

@ -1 +1 @@
Subproject commit ecf956b9808c28c2db52e6b73930f57876dbb258 Subproject commit 22741d9ce9d19bf7b5f5a219b6ed0925259a4d1b

View file

@ -93,7 +93,6 @@
</building> </building>
<building name="smithy" capacity="1"> <building name="smithy" capacity="1">
<function name="init" value="init_smithy"/>
<maintenance type="money" amount="300"/> <maintenance type="money" amount="300"/>
<maintenance type="log" amount="1"/> <maintenance type="log" amount="1"/>
<construction skill="building" minskill="3"> <construction skill="building" minskill="3">
@ -102,6 +101,8 @@
<requirement type="iron" quantity="2"/> <requirement type="iron" quantity="2"/>
<requirement type="money" quantity="200"/> <requirement type="money" quantity="200"/>
</construction> </construction>
<modifier type="skill" skill="weaponsmithing" value="1"/>
<modifier type="skill" skill="armorer" value="1"/>
</building> </building>
<building name="magictower" maxcapacity="2" maxsize="50" magic="yes" magres="40" fumblebonus="10" auraregen="1.75"> <building name="magictower" maxcapacity="2" maxsize="50" magic="yes" magres="40" fumblebonus="10" auraregen="1.75">

View file

@ -5536,8 +5536,8 @@
<arg name="region" type="region"/> <arg name="region" type="region"/>
<arg name="command" type="order"/> <arg name="command" type="order"/>
</type> </type>
<text locale="de">"$unit($unit) in $region($region): '$order($command)' - Nur Elfen können diese Bögen herstellen."</text> <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Diesen Gegenstand kann die Einheit nicht herstellen."</text>
<text locale="en">"$unit($unit) in $region($region): '$order($command)' - Only elves can make these bows."</text> <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This unit cannot produce that."</text>
</message> </message>
<message name="error117" section="errors"> <message name="error117" section="errors">
<type> <type>
@ -5545,8 +5545,8 @@
<arg name="region" type="region"/> <arg name="region" type="region"/>
<arg name="command" type="order"/> <arg name="command" type="order"/>
</type> </type>
<text locale="de">"$unit($unit) in $region($region): '$order($command)' - Nur die EMail-Adresse angeben!"</text> <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Diese Rasse kann das nicht herstellen."</text>
<text locale="en">"$unit($unit) in $region($region): '$order($command)' - Please provide only an email address!"</text> <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This race cannot produce that."</text>
</message> </message>
<message name="error116" section="errors"> <message name="error116" section="errors">
<type> <type>

View file

@ -3,7 +3,8 @@
<item weight="500" score="10"> <item weight="500" score="10">
<construction skill="mining" minskill="1"/> <construction skill="mining" minskill="1"/>
</item> </item>
<modifier building="smithy" type="save" value="2"/>
<modifier building="mine" type="skill" value="1"/> <modifier building="mine" type="skill" value="1"/>
<modifier building="mine" type="material" value="0.5"/> <modifier building="mine" type="material" value="0.5"/>
<modifier race="dwarf" type="material" value="0.60"/> <modifier race="dwarf" type="material" value="0.6"/>
</resource> </resource>

View file

@ -1,8 +1,8 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<resource name="greatbow"> <resource name="greatbow">
<modifier type="require" race="elf"/>
<item weight="100"> <item weight="100">
<construction skill="weaponsmithing" minskill="5"> <construction skill="weaponsmithing" minskill="5">
<modifier function="mod_elves_only"/>
<requirement type="mallorn" quantity="2"/> <requirement type="mallorn" quantity="2"/>
</construction> </construction>
<weapon pierce="true" missile="true" skill="bow" offmod="0" defmod="0" reload="0" magres="0.0"> <weapon pierce="true" missile="true" skill="bow" offmod="0" defmod="0" reload="0" magres="0.0">

View file

@ -1,8 +1,9 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<resource name="scale"> <resource name="scale">
<modifier type="require" race="dwarf"/>
<modifier type="require" race="irongolem"/>
<item weight="300" score="150" allow="dwarf halfling"> <item weight="300" score="150" allow="dwarf halfling">
<construction skill="armorer" minskill="5"> <construction skill="armorer" minskill="5">
<modifier function="mod_dwarves_only"/>
<requirement type="iron" quantity="2"/> <requirement type="iron" quantity="2"/>
</construction> </construction>
<armor ac="3" penalty="0.10" projectile="0.05" magres="0.0"/> <armor ac="3" penalty="0.10" projectile="0.05" magres="0.0"/>

View file

@ -1,8 +1,9 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<resource name="towershield"> <resource name="towershield">
<modifier type="require" race="dwarf"/>
<modifier type="require" race="irongolem"/>
<item weight="200" score="60" allow="dwarf"> <item weight="200" score="60" allow="dwarf">
<construction skill="armorer" minskill="4"> <construction skill="armorer" minskill="4">
<modifier function="mod_dwarves_only"/>
<requirement type="iron" quantity="1"/> <requirement type="iron" quantity="1"/>
</construction> </construction>
<armor ac="0" penalty="-0.15" projectile="0.25" magres="0.0" shield="yes"> <armor ac="0" penalty="-0.15" projectile="0.25" magres="0.0" shield="yes">

View file

@ -3,6 +3,7 @@
<item weight="500" score="10"> <item weight="500" score="10">
<construction skill="mining" minskill="1"/> <construction skill="mining" minskill="1"/>
</item> </item>
<modifier building="smithy" type="save" value="2"/>
<modifier building="mine" type="skill" value="1"/> <modifier building="mine" type="skill" value="1"/>
<modifier building="mine" type="material" value="0.5"/> <modifier building="mine" type="material" value="0.5"/>
</resource> </resource>

View file

@ -4,9 +4,9 @@
* has lower damage * has lower damage
--> -->
<resource name="greatbow"> <resource name="greatbow">
<modifier type="require" race="elf"/>
<item weight="100" allow="elf"> <item weight="100" allow="elf">
<construction skill="weaponsmithing" minskill="5"> <construction skill="weaponsmithing" minskill="5">
<modifier function="mod_elves_only"/>
<requirement type="mallorn" quantity="2"/> <requirement type="mallorn" quantity="2"/>
</construction> </construction>
<weapon pierce="true" missile="true" skill="bow" offmod="0" defmod="0" reload="0" magres="0.0"> <weapon pierce="true" missile="true" skill="bow" offmod="0" defmod="0" reload="0" magres="0.0">

View file

@ -1,8 +1,8 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<resource name="rep_crossbow"> <resource name="rep_crossbow">
<modifier type="require" race="dwarf"/>
<item weight="100" allow="dwarf halfling"> <item weight="100" allow="dwarf halfling">
<construction skill="weaponsmithing" minskill="5"> <construction skill="weaponsmithing" minskill="5">
<modifier function="mod_dwarves_only"/>
<requirement type="log" quantity="1"/> <requirement type="log" quantity="1"/>
<requirement type="iron" quantity="1"/> <requirement type="iron" quantity="1"/>
</construction> </construction>

View file

@ -33,7 +33,7 @@ fi
echo "build eressea" echo "build eressea"
cd $ROOT/$BUILD cd $ROOT/$BUILD
BRANCH=$(git status -s -b | head -1 | cut -d\ -f 2 | sed 's/\..*//') BRANCH=$(git status -s -b | head -1 | cut -d\ -f 2 | sed 's/\..*//')
if [ "$BRANCH"=="master" ] ; then if [ "$BRANCH" = "master" ] ; then
VERSION=$(git describe --match 'v*.*.*' --tags | sed 's/^v//') VERSION=$(git describe --match 'v*.*.*' --tags | sed 's/^v//')
cmake -DERESSEA_VERSION="$VERSION" .. cmake -DERESSEA_VERSION="$VERSION" ..
else else

View file

@ -10,6 +10,7 @@ ROOT=$(git rev-parse --show-toplevel)
MACHINE=`$CC -dumpmachine` MACHINE=`$CC -dumpmachine`
[ -z $MACHINE ] && MACHINE=`uname -m` [ -z $MACHINE ] && MACHINE=`uname -m`
BIN_DIR="$ROOT/build-$MACHINE-$CC-$BUILD" BIN_DIR="$ROOT/build-$MACHINE-$CC-$BUILD"
rm -rf $BIN_DIR
mkdir -p $BIN_DIR mkdir -p $BIN_DIR
rm -f $BUILD rm -f $BUILD
ln -sf $BIN_DIR $BUILD ln -sf $BIN_DIR $BUILD
@ -29,12 +30,11 @@ if [ -d $HOME/usr ]; then
fi fi
DEST=$(dirname $ROOT)/server DEST=$(dirname $ROOT)/server
ARGS=" -DCMAKE_MODULE_PATH=$ROOT/cmake/Modules \ ARGS=" -DCMAKE_BUILD_TYPE=$BUILD \
-DCMAKE_BUILD_TYPE=$BUILD \
-DCMAKE_LIBRARY_PATH=$LIBRARY_PATH \ -DCMAKE_LIBRARY_PATH=$LIBRARY_PATH \
-DCMAKE_INCLUDE_PATH=$INCLUDE_PATH \
-DCMAKE_PREFIX_PATH=$PREFIX_PATH \ -DCMAKE_PREFIX_PATH=$PREFIX_PATH \
-DCMAKE_INSTALL_PREFIX=$DEST" -DCMAKE_INSTALL_PREFIX=$DEST"
# -DCMAKE_INCLUDE_PATH=$INCLUDE_PATH
git submodule update --init git submodule update --init

View file

@ -15,6 +15,7 @@ cd $ROOT
$ROOT/$BUILD/eressea/eressea -v1 scripts/run-tests.lua $ROOT/$BUILD/eressea/eressea -v1 scripts/run-tests.lua
$ROOT/$BUILD/eressea/eressea -v1 scripts/run-tests-e2.lua $ROOT/$BUILD/eressea/eressea -v1 scripts/run-tests-e2.lua
$ROOT/$BUILD/eressea/eressea -v1 scripts/run-tests-e3.lua $ROOT/$BUILD/eressea/eressea -v1 scripts/run-tests-e3.lua
$ROOT/$BUILD/eressea/eressea --version
rm -rf data reports orders.txt score score.alliances datum turn rm -rf data reports orders.txt score score.alliances datum turn
cd $OLDWPD cd $OLDWPD

View file

@ -1,3 +1,4 @@
require 'tests.e2.production'
require 'tests.e2.adamantium' require 'tests.e2.adamantium'
require 'tests.e2.undead' require 'tests.e2.undead'
require 'tests.e2.shiplanding' require 'tests.e2.shiplanding'
@ -17,3 +18,4 @@ require 'tests.storage'
require 'tests.magicbag' require 'tests.magicbag'
require 'tests.process' require 'tests.process'
require 'tests.xmas' require 'tests.xmas'
require 'tests.production'

View file

@ -0,0 +1,78 @@
require "lunit"
module("tests.e2.production", package.seeall, lunit.testcase )
function setup()
eressea.game.reset()
eressea.settings.set("rules.food.flags", "4") -- food is free
eressea.settings.set("NewbieImmunity", "0")
end
local function create_faction(race)
return faction.create(race, race .. '@example.com', "de")
end
function test_greatbow_needs_elf()
-- only elves can build a greatbow
local r = region.create(0, 0, 'mountain')
local f = create_faction('human')
local u = unit.create(f, r, 1)
turn_begin()
u:set_skill('weaponsmithing', 5)
u:add_item('mallorn', 2)
u:add_order("MACHE Elfenbogen")
turn_process() -- humans cannot do it
assert_equal(1, f:count_msg_type("error117"))
assert_equal(0, u:get_item('greatbow'))
assert_equal(2, u:get_item('mallorn'))
u.race = 'elf'
turn_process() -- but elves can
assert_equal(1, u:get_item('greatbow'))
assert_equal(0, u:get_item('mallorn'))
end
function test_troll_quarrying_bonus()
-- Von Trollen abgebaute Steine werden nur zu 75% vom "Regionsvorrat" abgezogen.
-- Dieser Effekt ist kumulativ zu einem Steinbruch.
local r = region.create(0, 0, 'mountain')
local f = create_faction('human')
local u = unit.create(f, r, 1)
turn_begin()
r:set_resource("stone", 100)
u:set_skill('quarrying', 4)
u:add_order("MACHE Steine")
turn_process() -- humans get no bonus
assert_equal(4, u:get_item('stone'))
assert_equal(96, r:get_resource('stone'))
u.race = 'troll'
u:set_skill('quarrying', 2)
turn_process() -- trolls have +2 to quarrying, and save 25%
assert_equal(8, u:get_item('stone'))
assert_equal(93, r:get_resource('stone'))
end
function test_dwarf_mining_bonus()
-- Von Zwergen abgebautes Eisen wird nur zu 60% vom "Regionsvorrat" abgezogen.
-- Dieser Effekt ist kumulativ zu einem Bergwerk (siehe hier und hier).
local r = region.create(0, 0, 'mountain')
local f = create_faction('human')
local u = unit.create(f, r, 1)
turn_begin()
r:set_resource('iron', 100)
u:set_skill('mining', 10)
u:add_order('MACHE Eisen')
turn_process() -- humans get no bonus
assert_equal(10, u:get_item('iron'))
assert_equal(90, r:get_resource('iron'))
u.race = 'dwarf'
u:set_skill('mining', 8)
turn_process() -- dwarves have +2 to mining, and save 40%
assert_equal(20, u:get_item('iron'))
assert_equal(84, r:get_resource('iron'))
end

View file

@ -1,14 +1,15 @@
require 'tests.e3.production' -- require 'tests.e3.castles'
require 'tests.e3.castles' -- require 'tests.e3.stealth'
require 'tests.e3.stealth' -- require 'tests.e3.spells'
require 'tests.e3.spells'
require 'tests.e3.rules' require 'tests.e3.rules'
require 'tests.e3.parser' -- require 'tests.e3.parser'
require 'tests.e3.morale' -- require 'tests.e3.morale'
require 'tests.e3.items' -- require 'tests.e3.items'
require 'tests.economy' -- require 'tests.economy'
require 'tests.orders' -- require 'tests.orders'
require 'tests.common' -- require 'tests.common'
require 'tests.items' -- require 'tests.items'
require 'tests.magicbag' -- require 'tests.magicbag'
require 'tests.process' -- require 'tests.process'
-- require 'tests.e3.production'
-- require 'tests.production'

View file

@ -9,171 +9,129 @@ function setup()
end end
local function create_faction(race) local function create_faction(race)
return faction.create(race, race .. '@eressea.de', "de") return faction.create(race, race .. '@example.com', "de")
end end
function test_laen_needs_mine() function test_greatbow_needs_elf()
-- some resources require a building -- only elves can build a greatbow
-- i.e. you cannot create laen without a mine
local r = region.create(0, 0, "mountain")
local f = create_faction('human')
local u = unit.create(f, r, 1)
turn_begin()
r:set_resource('laen', 100)
u:add_order("MACHE Laen")
u:set_skill('mining', 7)
turn_process()
assert_equal(0, u:get_item('laen'))
assert_equal(100, r:get_resource('laen'))
assert_equal(1, f:count_msg_type("error104")) -- requires building
u.building = building.create(u.region, "mine")
u.building.working = true
u.building.size = 10
turn_process()
assert_equal(1, u:get_item('laen'))
assert_equal(99, r:get_resource('laen'))
turn_end()
end
function test_mine_laen_bonus()
-- some buildings grant a bonus on the production skill
-- i.e. a mine adds +1 to mining
local r = region.create(0, 0, 'mountain') local r = region.create(0, 0, 'mountain')
local f = create_faction('human') local f = create_faction('human')
local u = unit.create(f, r, 1) local u = unit.create(f, r, 1)
turn_begin() turn_begin()
r:set_resource('laen', 100) u:set_skill('weaponsmithing', 5)
assert_equal(100, r:get_resource('laen')) u:add_item('mallorn', 2)
u:add_order("MACHE Laen") u:add_order("MACHE Elfenbogen")
u:set_skill('mining', 6) turn_process() -- humans cannot do it
u.building = building.create(u.region, "mine") assert_equal(1, f:count_msg_type("error117"))
u.building.working = true assert_equal(0, u:get_item('greatbow'))
u.building.size = 10 assert_equal(2, u:get_item('mallorn'))
u.number = 2
turn_process() -- T6 is not enough for laen
assert_equal(0, u:get_item('laen'))
assert_equal(100, r:get_resource('laen'))
assert_equal(1, f:count_msg_type("manufacture_skills"))
u:set_skill('mining', 13) u.race = 'elf'
turn_process() -- T13 is enough, the +1 produces one extra Laen turn_process() -- but elves can
assert_equal(4, u:get_item('laen')) -- FAIL (3) assert_equal(1, u:get_item('greatbow'))
assert_equal(96, r:get_resource('laen')) assert_equal(0, u:get_item('mallorn'))
turn_end()
end end
function test_mine_iron_bonus() function test_troll_no_quarrying_bonus()
-- some buildings grant a bonus on the production skill -- Trolle kriegen keinen Rohstoffbonus wie in E2
-- i.e. a mine adds +1 to mining iron
--
local r = region.create(0, 0, 'mountain') local r = region.create(0, 0, 'mountain')
local f = create_faction('human') local f = create_faction('troll')
local u = unit.create(f, r, 1)
turn_begin()
r:set_resource("stone", 100)
u:set_skill('quarrying', 2) -- +2 Rassenbonus
u:add_order("MACHE Steine")
turn_process()
assert_equal(4, u:get_item('stone'))
assert_equal(96, r:get_resource('stone'))
end
function test_dwarf_no_mining_bonus()
-- E3: Zwerge verlieren den Eisenabbaubonus
local r = region.create(0, 0, 'mountain')
local f = create_faction('dwarf')
local u = unit.create(f, r, 1) local u = unit.create(f, r, 1)
turn_begin() turn_begin()
r:set_resource('iron', 100) r:set_resource('iron', 100)
assert_equal(100, r:get_resource('iron')) u:set_skill('mining', 8) -- +2 skill bonus
u:add_order("MACHE Eisen") u:add_order('MACHE Eisen')
u:set_skill('mining', 1) turn_process()
u.building = building.create(u.region, "mine") assert_equal(10, u:get_item('iron'))
u.building.working = false assert_equal(90, r:get_resource('iron'))
u.building.size = 10 end
u.number = 2
turn_process() -- iron can be made without a working mine function test_dwarf_towershield()
-- Zwerge können als einzige Rasse Turmschilde, Schuppenpanzer
-- und Repetierarmbrüste bauen.
local r = region.create(0, 0, 'plain')
local f = create_faction('human')
local u = unit.create(f, r, 1)
turn_begin()
u:set_skill('armorer', 4)
u:add_item('iron', 1)
u:add_order("MACHE Turmschild")
turn_process() -- humans cannot do it
assert_equal(1, f:count_msg_type("error117"))
assert_equal(0, u:get_item('towershield'))
assert_equal(1, u:get_item('iron'))
u.race = 'dwarf'
u:set_skill('armorer', 2) -- dwarf has bonus +2
turn_process() -- but dwarves can
assert_equal(1, u:get_item('towershield'))
assert_equal(0, u:get_item('iron'))
end
function test_dwarf_scale()
-- Zwerge können als einzige Rasse Turmschilde, Schuppenpanzer
-- und Repetierarmbrüste bauen.
local r = region.create(0, 0, 'plain')
local f = create_faction('human')
local u = unit.create(f, r, 1)
turn_begin()
u:set_skill('armorer', 5)
u:add_item('iron', 2)
u:add_order("MACHE Schuppenpanzer")
turn_process() -- humans cannot do it
assert_equal(1, f:count_msg_type("error117"))
assert_equal(0, u:get_item('scale'))
assert_equal(2, u:get_item('iron')) assert_equal(2, u:get_item('iron'))
assert_equal(98, r:get_resource('iron'))
u.building.working = true u.race = 'dwarf'
turn_process() u:set_skill('armorer', 3) -- dwarf has bonus +2
assert_equal(6, u:get_item('iron')) turn_process() -- but dwarves can
assert_equal(96, r:get_resource('iron')) assert_equal(1, u:get_item('scale'))
assert_equal(0, u:get_item('iron'))
turn_end()
end end
function test_quarry_bonus() function test_dwarf_rep_xbow()
-- a quarry grants +1 to quarrying, and saves 50% stone -- Zwerge können als einzige Rasse Turmschilde, Schuppenpanzer
-- -- und Repetierarmbrüste bauen.
local r = region.create(0, 0, 'mountain') local r = region.create(0, 0, 'plain')
local f = create_faction('human') local f = create_faction('human')
local u = unit.create(f, r, 1) local u = unit.create(f, r, 1)
turn_begin() turn_begin()
r:set_resource('stone', 100) u:set_skill('weaponsmithing', 5)
assert_equal(100, r:get_resource('stone')) u:add_item('iron', 1)
u:add_order("MACHE Stein") u:add_item('log', 1)
u:set_skill('quarrying', 1) u:add_order("MACHE Repetierarmbrust")
u.number = 2 turn_process() -- humans cannot do it
u.building = building.create(u.region, 'quarry') assert_equal(1, f:count_msg_type("error117"))
u.building.working = false assert_equal(0, u:get_item('rep_crossbow'))
u.building.size = 10 assert_equal(1, u:get_item('iron'))
turn_process() assert_equal(1, u:get_item('log'))
assert_equal(2, u:get_item('stone'))
assert_equal(98, r:get_resource('stone'))
u.building.working = true u.race = 'dwarf'
turn_process() u:set_skill('weaponsmithing', 3) -- dwarf has bonus +2
assert_equal(6, u:get_item('stone')) turn_process() -- but dwarves can
assert_equal(96, r:get_resource('stone')) assert_equal(1, u:get_item('rep_crossbow'))
assert_equal(0, u:get_item('iron'))
turn_end() assert_equal(0, u:get_item('log'))
end
function test_smithy_bonus_iron()
-- a smithy adds +1 to weaponsmithing, and saves 50% iron
local r = region.create(0, 0, 'mountain')
local f = create_faction('human')
local u = unit.create(f, r, 1)
turn_begin()
u.building = building.create(u.region, 'smithy')
u.building.working = false
u.building.size = 10
u:set_skill('weaponsmithing', 5) -- needs 3
u:add_item('iron', 100)
u:add_order("MACHE Schwert")
turn_process() -- building disabled
assert_equal(1, u:get_item('sword'))
assert_equal(99, u:get_item('iron'))
u.building.working = true
turn_process() -- building active
assert_equal(3, u:get_item('sword'))
assert_equal(98, u:get_item('iron'))
turn_end()
end
function test_smithy_bonus_mixed()
-- a smithy adds +1 to weaponsmithing, and saves 50% iron
-- it does not save any other resource, though.
local r = region.create(0, 0, 'mountain')
local f = create_faction('human')
local u = unit.create(f, r, 1)
turn_begin()
u.building = building.create(u.region, 'smithy')
u.building.working = false
u.building.size = 10
u:set_skill('weaponsmithing', 5) -- needs 3
u:add_item('iron', 100)
u:add_item('log', 100)
u:add_order("MACHE Kriegsaxt")
turn_process() -- building disabled
assert_equal(1, u:get_item('axe'))
assert_equal(99, u:get_item('iron'))
assert_equal(99, u:get_item('log'))
u.building.working = true
turn_process() -- building active
assert_equal(3, u:get_item('axe'))
assert_equal(98, u:get_item('iron'))
assert_equal(97, u:get_item('log'))
turn_end()
end end

View file

@ -824,8 +824,8 @@ function test_golem_use_four_iron()
process_orders() process_orders()
assert_equal(2, u1.number)
assert_equal(4, u1:get_item("towershield")) assert_equal(4, u1:get_item("towershield"))
assert_equal(2, u1.number)
end end
function test_silver_weight_stops_movement() function test_silver_weight_stops_movement()

View file

@ -0,0 +1,206 @@
require "lunit"
module("tests.production", package.seeall, lunit.testcase )
function setup()
eressea.game.reset()
eressea.settings.set("rules.food.flags", "4") -- food is free
eressea.settings.set("NewbieImmunity", "0")
end
local function create_faction(race)
return faction.create(race, race .. '@eressea.de', "de")
end
function test_laen_needs_mine()
-- some resources require a building
-- i.e. you cannot create laen without a mine
local r = region.create(0, 0, "mountain")
local f = create_faction('human')
local u = unit.create(f, r, 1)
turn_begin()
r:set_resource('laen', 100)
u:add_order("MACHE Laen")
u:set_skill('mining', 7)
turn_process()
assert_equal(0, u:get_item('laen'))
assert_equal(100, r:get_resource('laen'))
assert_equal(1, f:count_msg_type("error104")) -- requires building
u.building = building.create(u.region, "mine")
u.building.working = true
u.building.size = 10
turn_process()
assert_equal(1, u:get_item('laen'))
assert_equal(99, r:get_resource('laen'))
turn_end()
end
function test_mine_laen_bonus()
-- some buildings grant a bonus on the production skill
-- i.e. a mine adds +1 to mining
local r = region.create(0, 0, 'mountain')
local f = create_faction('human')
local u = unit.create(f, r, 1)
turn_begin()
r:set_resource('laen', 100)
assert_equal(100, r:get_resource('laen'))
u:add_order("MACHE Laen")
u:set_skill('mining', 6)
u.building = building.create(u.region, "mine")
u.building.working = true
u.building.size = 10
u.number = 2
turn_process() -- T6 is not enough for laen
assert_equal(0, u:get_item('laen'))
assert_equal(100, r:get_resource('laen'))
assert_equal(1, f:count_msg_type("manufacture_skills"))
u:set_skill('mining', 13)
turn_process() -- T13 is enough, the +1 produces one extra Laen
assert_equal(4, u:get_item('laen')) -- FAIL (3)
assert_equal(96, r:get_resource('laen'))
turn_end()
end
function test_mine_iron_bonus()
-- some buildings grant a bonus on the production skill
-- i.e. a mine adds +1 to mining iron
--
local r = region.create(0, 0, 'mountain')
local f = create_faction('human')
local u = unit.create(f, r, 1)
turn_begin()
r:set_resource('iron', 100)
assert_equal(100, r:get_resource('iron'))
u:add_order("MACHE Eisen")
u:set_skill('mining', 1)
u.building = building.create(u.region, "mine")
u.building.working = false
u.building.size = 10
u.number = 2
turn_process() -- iron can be made without a working mine
assert_equal(2, u:get_item('iron'))
assert_equal(98, r:get_resource('iron'))
u.building.working = true
turn_process()
assert_equal(6, u:get_item('iron'))
assert_equal(96, r:get_resource('iron'))
turn_end()
end
function test_quarry_bonus()
-- a quarry grants +1 to quarrying, and saves 50% stone
--
local r = region.create(0, 0, 'mountain')
local f = create_faction('human')
local u = unit.create(f, r, 1)
turn_begin()
r:set_resource('stone', 100)
assert_equal(100, r:get_resource('stone'))
u:add_order("MACHE Stein")
u:set_skill('quarrying', 1)
u.number = 2
u.building = building.create(u.region, 'quarry')
u.building.working = false
u.building.size = 10
turn_process()
assert_equal(2, u:get_item('stone'))
assert_equal(98, r:get_resource('stone'))
u.building.working = true
turn_process()
assert_equal(6, u:get_item('stone'))
assert_equal(96, r:get_resource('stone'))
turn_end()
end
function test_smithy_no_bonus()
-- a smithy does not give a bonus to other skills
-- five cartmakers make 5 carts, no matter what
local r = region.create(0, 0, 'mountain')
local f = create_faction('human')
local u = unit.create(f, r, 1)
turn_begin()
u.building = building.create(u.region, 'smithy')
u.building.working = false
u.building.size = 10
u.number = 5
u:set_skill('cartmaking', 1) -- needs 1 min
u:add_item('log', 100)
u:add_order("MACHE Wagen")
turn_process() -- building disabled
assert_equal(5, u:get_item('cart'))
assert_equal(75, u:get_item('log'))
u.building.working = true
turn_process() -- building active
assert_equal(10, u:get_item('cart'))
assert_equal(50, u:get_item('log'))
turn_end()
end
function test_smithy_bonus_iron()
-- a smithy adds +1 to weaponsmithing, and saves 50% iron
local r = region.create(0, 0, 'mountain')
local f = create_faction('human')
local u = unit.create(f, r, 1)
turn_begin()
u.building = building.create(u.region, 'smithy')
u.building.working = false
u.building.size = 10
u:set_skill('weaponsmithing', 5) -- needs 3
u:add_item('iron', 100)
u:add_order("MACHE Schwert")
turn_process() -- building disabled
assert_equal(1, u:get_item('sword'))
assert_equal(99, u:get_item('iron'))
u.building.working = true
turn_process() -- building active
assert_equal(3, u:get_item('sword'))
assert_equal(98, u:get_item('iron'))
turn_end()
end
function test_smithy_bonus_mixed()
-- a smithy adds +1 to weaponsmithing, and saves 50% iron
-- it does not save any other resource, though.
local r = region.create(0, 0, 'mountain')
local f = create_faction('human')
local u = unit.create(f, r, 1)
turn_begin()
u.building = building.create(u.region, 'smithy')
u.building.working = false
u.building.size = 10
u:set_skill('weaponsmithing', 5) -- needs 3
u:add_item('iron', 100)
u:add_item('log', 100)
u:add_order("MACHE Kriegsaxt")
turn_process() -- building disabled
assert_equal(1, u:get_item('axe'))
assert_equal(99, u:get_item('iron'))
assert_equal(99, u:get_item('log'))
u.building.working = true
turn_process() -- building active
assert_equal(3, u:get_item('axe'))
assert_equal(98, u:get_item('iron'))
assert_equal(97, u:get_item('log'))
turn_end()
end

View file

@ -12,7 +12,6 @@ follow.c
hate.c hate.c
iceberg.c iceberg.c
key.c key.c
matmod.c
moved.c moved.c
movement.c movement.c
dict.c dict.c

View file

@ -94,7 +94,6 @@ void register_attributes(void)
at_register(&at_woodcount); at_register(&at_woodcount);
/* neue UNIT-Attribute */ /* neue UNIT-Attribute */
at_register(&at_fleechance);
at_register(&at_siege); at_register(&at_siege);
at_register(&at_effect); at_register(&at_effect);
at_register(&at_private); at_register(&at_private);
@ -103,7 +102,6 @@ void register_attributes(void)
at_register(&at_group); at_register(&at_group);
at_register(&at_building_generic_type); at_register(&at_building_generic_type);
at_register(&at_maxmagicians);
at_register(&at_npcfaction); at_register(&at_npcfaction);
/* connection-typen */ /* connection-typen */
@ -115,6 +113,7 @@ void register_attributes(void)
at_register(&at_germs); at_register(&at_germs);
at_deprecate("maxmagicians", a_readint); /* factions with differnt magician limits, probably unused */
at_deprecate("hurting", a_readint); /* an old arena attribute */ at_deprecate("hurting", a_readint); /* an old arena attribute */
at_deprecate("xontormiaexpress", a_readint); /* required for old datafiles */ at_deprecate("xontormiaexpress", a_readint); /* required for old datafiles */
at_deprecate("orcification", a_readint); /* required for old datafiles */ at_deprecate("orcification", a_readint); /* required for old datafiles */

View file

@ -1,41 +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.
**/
#include <platform.h>
#include "matmod.h"
#include <util/attrib.h>
#include <stddef.h>
attrib_type at_matmod = {
"matmod",
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
ATF_PRESERVE
};
attrib *make_matmod(mm_fun function)
{
attrib *a = a_new(&at_matmod);
a->data.f = (void(*)(void))function;
return a;
}

View file

@ -1,37 +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_ATTRIBUTE_MATMOD
#define H_ATTRIBUTE_MATMOD
#ifdef __cplusplus
extern "C" {
#endif
struct resource_type;
struct unit;
typedef int(*mm_fun) (const struct unit * u,
const struct resource_type * rtype, int value);
extern struct attrib_type at_matmod;
extern struct attrib *make_matmod(mm_fun function);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -123,13 +123,8 @@ extern "C" {
typedef struct weapon { typedef struct weapon {
int count, used; int count, used;
const struct weapon_type *type; const struct weapon_type *type;
# ifdef LOMEM
int attackskill : 8;
int defenseskill : 8;
# else
int attackskill; int attackskill;
int defenseskill; int defenseskill;
# endif
} weapon; } weapon;
/*** fighter::person::flags ***/ /*** fighter::person::flags ***/

View file

@ -787,7 +787,13 @@ static int tolua_unit_get_curse(lua_State *L) {
static int tolua_unit_has_attrib(lua_State *L) { static int tolua_unit_has_attrib(lua_State *L) {
unit *self = (unit *)tolua_tousertype(L, 1, 0); unit *self = (unit *)tolua_tousertype(L, 1, 0);
const char *name = tolua_tostring(L, 2, 0); const char *name = tolua_tostring(L, 2, 0);
attrib * a = self->attribs ? a_find(self->attribs, at_find(name)) : NULL; attrib * a = self->attribs;
while (a) {
if (strcmp(a->type->name, name) == 0) {
break;
}
a = a->nexttype;
}
lua_pushboolean(L, a != NULL); lua_pushboolean(L, a != NULL);
return 1; return 1;
} }

View file

@ -468,7 +468,6 @@ static void recruit(unit * u, struct order *ord, request ** recruitorders)
assert(rc); assert(rc);
u_setrace(u, rc); u_setrace(u, rc);
#if GUARD_DISABLES_RECRUIT
/* this is a very special case because the recruiting unit may be empty /* this is a very special case because the recruiting unit may be empty
* at this point and we have to look at the creating unit instead. This * at this point and we have to look at the creating unit instead. This
* is done in cansee, which is called indirectly by is_guarded(). */ * is done in cansee, which is called indirectly by is_guarded(). */
@ -476,13 +475,11 @@ static void recruit(unit * u, struct order *ord, request ** recruitorders)
cmistake(u, ord, 70, MSG_EVENT); cmistake(u, ord, 70, MSG_EVENT);
return; return;
} }
#endif
if (rc == get_race(RC_INSECT)) { if (rc == get_race(RC_INSECT)) {
gamedate date; gamedate date;
get_gamedate(turn, &date); get_gamedate(turn, &date);
if (date.season == 0 && r->terrain != newterrain(T_DESERT)) { if (date.season == 0 && r->terrain != newterrain(T_DESERT)) {
#ifdef INSECT_POTION
bool usepotion = false; bool usepotion = false;
unit *u2; unit *u2;
@ -492,7 +489,6 @@ static void recruit(unit * u, struct order *ord, request ** recruitorders)
break; break;
} }
if (!usepotion) if (!usepotion)
#endif
{ {
cmistake(u, ord, 98, MSG_EVENT); cmistake(u, ord, 98, MSG_EVENT);
return; return;
@ -802,30 +798,88 @@ void economics(region * r)
} }
/* ------------------------------------------------------------- */ static void mod_skill(const resource_mod *mod, skill_t sk, int *skill) {
skill_t msk;
assert(mod->type == RMT_PROD_SKILL);
msk = (skill_t)mod->value.sa[0];
if (msk == NOSKILL || msk == sk) {
*skill += mod->value.sa[1];
}
}
static struct message * get_modifiers(unit *u, skill_t sk, const resource_type *rtype, variant *savep, int *skillp) {
struct building *b = inside_building(u);
const struct building_type *btype = building_is_active(b) ? b->type : NULL;
int save_n = 1, save_d = 1;
int skill = 0;
int need_race = 0, need_bldg = 0;
resource_mod *mod;
if (btype && btype->modifiers) {
for (mod = btype->modifiers; mod && mod->type != RMT_END; ++mod) {
if (mod->type == RMT_PROD_SKILL) {
mod_skill(mod, sk, &skill);
}
}
}
for (mod = rtype->modifiers; mod && mod->type != RMT_END; ++mod) {
if (mod->btype == NULL || mod->btype == btype) {
if (mod->race == NULL || mod->race == u_race(u)) {
switch (mod->type) {
case RMT_PROD_SAVE:
if (savep) {
save_n *= mod->value.sa[0];
save_d *= mod->value.sa[1];
}
break;
case RMT_PROD_SKILL:
mod_skill(mod, sk, &skill);
break;
case RMT_PROD_REQUIRE:
if (mod->race) need_race |= 1;
if (mod->btype) need_bldg |= 1;
break;
default:
/* is not a production modifier, ignore it */
break;
}
}
}
if (mod->type == RMT_PROD_REQUIRE) {
if (mod->race) need_race |= 2;
if (mod->btype) need_bldg |= 2;
}
}
if (need_race == 2) {
return msg_error(u, u->thisorder, 117);
}
if (need_bldg == 2) {
return msg_error(u, u->thisorder, 104);
}
*skillp = skill;
if (savep) *savep = frac_make(save_n, save_d);
return NULL;
}
static void manufacture(unit * u, const item_type * itype, int want) static void manufacture(unit * u, const item_type * itype, int want)
{ {
int n; int n;
int skill;
int minskill = itype->construction->minskill; int minskill = itype->construction->minskill;
skill_t sk = itype->construction->skill; skill_t sk = itype->construction->skill;
message *msg;
int skill_mod;
skill = effskill(u, sk, 0); msg = get_modifiers(u, sk, itype->rtype, NULL, &skill_mod);
skill = if (msg) {
skillmod(itype->construction->attribs, u, u->region, sk, skill, SMF_PRODUCTION); ADDMSG(&u->faction->msgs, msg);
if (skill < 0) {
/* an error occured */
int err = -skill;
cmistake(u, u->thisorder, err, MSG_PRODUCE);
return; return;
} }
if (want == 0) { if (want == 0) {
want = maxbuild(u, itype->construction); want = maxbuild(u, itype->construction);
} }
n = build(u, itype->construction, 0, want); n = build(u, itype->construction, 0, want, skill_mod);
switch (n) { switch (n) {
case ENEEDSKILL: case ENEEDSKILL:
ADDMSG(&u->faction->msgs, ADDMSG(&u->faction->msgs,
@ -883,37 +937,6 @@ enum {
AFL_LOWSKILL = 1 << 1 AFL_LOWSKILL = 1 << 1
}; };
struct message * get_modifiers(unit *u, const resource_mod *mod, variant *savep, int *skillp) {
struct building *b = inside_building(u);
const struct building_type *btype = building_is_active(b) ? b->type : NULL;
int save_n = 1, save_d = 1;
int skill = 0;
for (; mod->flags != 0; ++mod) {
if (mod->btype == NULL || mod->btype == btype) {
if (mod->race == NULL || mod->race == u_race(u)) {
if (mod->flags & RMF_SAVEMATERIAL) {
save_n *= mod->value.sa[0];
save_d *= mod->value.sa[1];
}
if (mod->flags & RMF_SKILL) {
skill += mod->value.i;
}
}
} else if (mod->flags & RMF_REQUIREDBUILDING) {
return msg_error(u, u->thisorder, 104);
}
}
*skillp = skill;
assert(save_n < SHRT_MAX);
assert(save_n > SHRT_MIN);
assert(save_d < SHRT_MAX);
assert(save_d > SHRT_MIN);
savep->sa[0] = (short)save_n;
savep->sa[1] = (short)save_d;
return NULL;
}
static void allocate_resource(unit * u, const resource_type * rtype, int want) static void allocate_resource(unit * u, const resource_type * rtype, int want)
{ {
const item_type *itype = resource2item(rtype); const item_type *itype = resource2item(rtype);
@ -924,12 +947,14 @@ static void allocate_resource(unit * u, const resource_type * rtype, int want)
const resource_type *rring; const resource_type *rring;
int amount, skill, skill_mod = 0; int amount, skill, skill_mod = 0;
variant save_mod; variant save_mod;
skill_t sk;
/* momentan kann man keine ressourcen abbauen, wenn man daf<61>r /* momentan kann man keine ressourcen abbauen, wenn man daf<61>r
* Materialverbrauch hat: */ * Materialverbrauch hat: */
assert(itype != NULL && (itype->construction == NULL assert(itype != NULL && (itype->construction == NULL
|| itype->construction->materials == NULL)); || itype->construction->materials == NULL));
sk = itype->construction->skill;
if (!rtype->raw) { if (!rtype->raw) {
int avail = limit_resource(r, rtype); int avail = limit_resource(r, rtype);
if (avail <= 0) { if (avail <= 0) {
@ -944,7 +969,7 @@ static void allocate_resource(unit * u, const resource_type * rtype, int want)
} }
if (rtype->modifiers) { if (rtype->modifiers) {
message *msg = get_modifiers(u, rtype->modifiers, &save_mod, &skill_mod); message *msg = get_modifiers(u, sk, rtype, &save_mod, &skill_mod);
if (msg) { if (msg) {
ADDMSG(&u->faction->msgs, msg); ADDMSG(&u->faction->msgs, msg);
return; return;
@ -972,17 +997,14 @@ static void allocate_resource(unit * u, const resource_type * rtype, int want)
} }
} }
assert(itype->construction->skill != 0 assert(sk != NOSKILL || "limited resource needs a required skill for making it");
|| "limited resource needs a required skill for making it"); skill = effskill(u, sk, 0);
skill = effskill(u, itype->construction->skill, 0);
if (skill == 0) { if (skill == 0) {
skill_t sk = itype->construction->skill;
add_message(&u->faction->msgs, add_message(&u->faction->msgs,
msg_feedback(u, u->thisorder, "skill_needed", "skill", sk)); msg_feedback(u, u->thisorder, "skill_needed", "skill", sk));
return; return;
} }
if (skill < itype->construction->minskill) { if (skill < itype->construction->minskill) {
skill_t sk = itype->construction->skill;
add_message(&u->faction->msgs, add_message(&u->faction->msgs,
msg_feedback(u, u->thisorder, "manufacture_skills", msg_feedback(u, u->thisorder, "manufacture_skills",
"skill minskill product", sk, itype->construction->minskill, "skill minskill product", sk, itype->construction->minskill,
@ -1207,7 +1229,7 @@ static void create_potion(unit * u, const potion_type * ptype, int want)
if (want == 0) { if (want == 0) {
want = maxbuild(u, ptype->itype->construction); want = maxbuild(u, ptype->itype->construction);
} }
built = build(u, ptype->itype->construction, 0, want); built = build(u, ptype->itype->construction, 0, want, 0);
switch (built) { switch (built) {
case ELOWSKILL: case ELOWSKILL:
case ENEEDSKILL: case ENEEDSKILL:
@ -1242,12 +1264,10 @@ static void create_potion(unit * u, const potion_type * ptype, int want)
void make_item(unit * u, const item_type * itype, int want) void make_item(unit * u, const item_type * itype, int want)
{ {
if (itype->construction && fval(itype->rtype, RTF_LIMITED)) { if (itype->construction && fval(itype->rtype, RTF_LIMITED)) {
#if GUARD_DISABLES_PRODUCTION == 1
if (is_guarded(u->region, u)) { if (is_guarded(u->region, u)) {
cmistake(u, u->thisorder, 70, MSG_EVENT); cmistake(u, u->thisorder, 70, MSG_EVENT);
return; return;
} }
#endif
allocate_resource(u, itype->rtype, want); allocate_resource(u, itype->rtype, want);
} }
else { else {
@ -2020,20 +2040,6 @@ static void expandstealing(region * r, request * stealorders)
if (u && u->region == r) { if (u && u->region == r) {
n = get_pooled(u, rsilver, GET_ALL, INT_MAX); n = get_pooled(u, rsilver, GET_ALL, INT_MAX);
} }
#ifndef GOBLINKILL
if (oa[i].type.goblin) { /* Goblin-Spezialklau */
int uct = 0;
unit *u2;
assert(effskill(oa[i].unit, SK_STEALTH) >= 4
|| !"this goblin\'s skill is too low");
for (u2 = r->units; u2; u2 = u2->next) {
if (u2->faction == u->faction) {
uct += maintenance_cost(u2);
}
}
n -= uct * 2;
}
#endif
if (n > 10 && rplane(r) && (rplane(r)->flags & PFL_NOALLIANCES)) { if (n > 10 && rplane(r) && (rplane(r)->flags & PFL_NOALLIANCES)) {
/* In Questen nur reduziertes Klauen */ /* In Questen nur reduziertes Klauen */
n = 10; n = 10;

View file

@ -345,7 +345,114 @@ static void test_income(CuTest *tc)
test_cleanup(); test_cleanup();
} }
static void test_make_item(CuTest *tc) { static void test_modify_material(CuTest *tc) {
unit *u;
struct item_type *itype;
resource_type *rtype;
resource_mod *mod;
test_setup();
init_resources();
u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
set_level(u, SK_WEAPONSMITH, 1);
/* the unit's race gets 2x savings on iron used to produce goods */
itype = test_create_itemtype("iron");
rtype = itype->rtype;
mod = rtype->modifiers = calloc(2, sizeof(resource_mod));
mod[0].type = RMT_USE_SAVE;
mod[0].value = frac_make(2, 1);
mod[0].race = u_race(u);
itype = test_create_itemtype("sword");
make_item(u, itype, 1);
CuAssertPtrNotNull(tc, test_find_messagetype(u->faction->msgs, "error_cannotmake"));
CuAssertIntEquals(tc, 0, get_item(u, itype));
test_clear_messages(u->faction);
itype->construction = calloc(1, sizeof(construction));
itype->construction->skill = SK_WEAPONSMITH;
itype->construction->minskill = 1;
itype->construction->maxsize = 1;
itype->construction->reqsize = 1;
itype->construction->materials = calloc(2, sizeof(requirement));
itype->construction->materials[0].rtype = rtype;
itype->construction->materials[0].number = 2;
set_item(u, rtype->itype, 1); /* 1 iron should get us 1 sword */
make_item(u, itype, 1);
CuAssertIntEquals(tc, 1, get_item(u, itype));
CuAssertIntEquals(tc, 0, get_item(u, rtype->itype));
u_setrace(u, test_create_race("smurf"));
set_item(u, rtype->itype, 2); /* 2 iron should be required now */
make_item(u, itype, 1);
CuAssertIntEquals(tc, 2, get_item(u, itype));
CuAssertIntEquals(tc, 0, get_item(u, rtype->itype));
test_cleanup();
}
static void test_modify_skill(CuTest *tc) {
unit *u;
struct item_type *itype;
/* building_type *btype; */
resource_type *rtype;
resource_mod *mod;
test_setup();
init_resources();
u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
set_level(u, SK_WEAPONSMITH, 1);
itype = test_create_itemtype("iron");
rtype = itype->rtype;
itype = test_create_itemtype("sword");
make_item(u, itype, 1);
CuAssertPtrNotNull(tc, test_find_messagetype(u->faction->msgs, "error_cannotmake"));
CuAssertIntEquals(tc, 0, get_item(u, itype));
test_clear_messages(u->faction);
itype->construction = calloc(1, sizeof(construction));
itype->construction->skill = SK_WEAPONSMITH;
itype->construction->minskill = 1;
itype->construction->maxsize = -1;
itype->construction->reqsize = 1;
itype->construction->materials = calloc(2, sizeof(requirement));
itype->construction->materials[0].rtype = rtype;
itype->construction->materials[0].number = 1;
/* our race gets a +1 bonus to the item's production skill */
mod = itype->rtype->modifiers = calloc(2, sizeof(resource_mod));
mod[0].type = RMT_PROD_SKILL;
mod[0].value.sa[0] = SK_WEAPONSMITH;
mod[0].value.sa[1] = 1;
mod[0].race = u_race(u);
set_item(u, rtype->itype, 2); /* 2 iron should get us 2 swords */
make_item(u, itype, 2);
CuAssertIntEquals(tc, 2, get_item(u, itype));
CuAssertIntEquals(tc, 0, get_item(u, rtype->itype));
mod[0].value.sa[0] = NOSKILL; /* match any skill */
set_item(u, rtype->itype, 2);
make_item(u, itype, 2);
CuAssertIntEquals(tc, 4, get_item(u, itype));
CuAssertIntEquals(tc, 0, get_item(u, rtype->itype));
u_setrace(u, test_create_race("smurf"));
set_item(u, rtype->itype, 2);
make_item(u, itype, 1); /* only enough skill to make 1 now */
CuAssertIntEquals(tc, 5, get_item(u, itype));
CuAssertIntEquals(tc, 1, get_item(u, rtype->itype));
test_cleanup();
}
static void test_modify_production(CuTest *tc) {
unit *u; unit *u;
struct item_type *itype; struct item_type *itype;
const struct resource_type *rt_silver; const struct resource_type *rt_silver;
@ -393,7 +500,7 @@ static void test_make_item(CuTest *tc) {
CuAssertIntEquals(tc, 290, region_getresource(u->region, rtype)); /* used 10 stones to make 10 stones */ CuAssertIntEquals(tc, 290, region_getresource(u->region, rtype)); /* used 10 stones to make 10 stones */
rtype->modifiers = calloc(2, sizeof(resource_mod)); rtype->modifiers = calloc(2, sizeof(resource_mod));
rtype->modifiers[0].flags = RMF_SAVEMATERIAL; rtype->modifiers[0].type = RMT_PROD_SAVE;
rtype->modifiers[0].race = u->_race; rtype->modifiers[0].race = u->_race;
rtype->modifiers[0].value.sa[0] = (short)(0.5+100*d); rtype->modifiers[0].value.sa[0] = (short)(0.5+100*d);
rtype->modifiers[0].value.sa[1] = 100; rtype->modifiers[0].value.sa[1] = 100;
@ -413,13 +520,34 @@ static void test_make_item(CuTest *tc) {
CuAssertIntEquals(tc, 28, get_item(u, itype)); CuAssertIntEquals(tc, 28, get_item(u, itype));
CuAssertIntEquals(tc, 280, region_getresource(u->region, rtype)); /* 50% saving = 3 stones make 6 stones */ CuAssertIntEquals(tc, 280, region_getresource(u->region, rtype)); /* 50% saving = 3 stones make 6 stones */
rtype->modifiers[0].flags = RMF_REQUIREDBUILDING; rtype->modifiers[0].type = RMT_PROD_REQUIRE;
rtype->modifiers[0].race = NULL; rtype->modifiers[0].race = NULL;
rtype->modifiers[0].btype = bt_get_or_create("mine"); rtype->modifiers[0].btype = bt_get_or_create("mine");
test_clear_messages(u->faction);
make_item(u, itype, 10); make_item(u, itype, 10);
CuAssertIntEquals(tc, 28, get_item(u, itype));
CuAssertPtrNotNull(tc, test_find_messagetype(u->faction->msgs, "error104")); CuAssertPtrNotNull(tc, test_find_messagetype(u->faction->msgs, "error104"));
rtype->modifiers[0].type = RMT_PROD_REQUIRE;
rtype->modifiers[0].race = test_create_race("smurf");
rtype->modifiers[0].btype = NULL;
test_clear_messages(u->faction);
make_item(u, itype, 10);
CuAssertIntEquals(tc, 28, get_item(u, itype));
CuAssertPtrNotNull(tc, test_find_messagetype(u->faction->msgs, "error117"));
rtype->modifiers[1].type = RMT_PROD_REQUIRE;
rtype->modifiers[1].race = u_race(u);
rtype->modifiers[1].btype = NULL;
test_clear_messages(u->faction);
make_item(u, itype, 10);
CuAssertPtrEquals(tc, NULL, u->faction->msgs);
split_allocations(u->region);
CuAssertIntEquals(tc, 38, get_item(u, itype));
test_cleanup(); test_cleanup();
} }
@ -429,7 +557,9 @@ CuSuite *get_economy_suite(void)
SUITE_ADD_TEST(suite, test_give_control_building); SUITE_ADD_TEST(suite, test_give_control_building);
SUITE_ADD_TEST(suite, test_give_control_ship); SUITE_ADD_TEST(suite, test_give_control_ship);
SUITE_ADD_TEST(suite, test_income); SUITE_ADD_TEST(suite, test_income);
SUITE_ADD_TEST(suite, test_make_item); SUITE_ADD_TEST(suite, test_modify_production);
SUITE_ADD_TEST(suite, test_modify_skill);
SUITE_ADD_TEST(suite, test_modify_material);
SUITE_ADD_TEST(suite, test_steal_okay); SUITE_ADD_TEST(suite, test_steal_okay);
SUITE_ADD_TEST(suite, test_steal_ocean); SUITE_ADD_TEST(suite, test_steal_ocean);
SUITE_ADD_TEST(suite, test_steal_nosteal); SUITE_ADD_TEST(suite, test_steal_nosteal);

View file

@ -43,6 +43,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <kernel/pool.h> #include <kernel/pool.h>
#include <kernel/race.h> #include <kernel/race.h>
#include <kernel/region.h> #include <kernel/region.h>
#include <kernel/resources.h>
#include <kernel/ship.h> #include <kernel/ship.h>
#include <kernel/terrain.h> #include <kernel/terrain.h>
#include <kernel/terrainid.h> #include <kernel/terrainid.h>
@ -67,9 +68,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
/* attributes inclues */
#include <attributes/matmod.h>
struct building *getbuilding(const struct region *r) struct building *getbuilding(const struct region *r)
{ {
building *b = findbuilding(getid()); building *b = findbuilding(getid());
@ -404,16 +402,26 @@ static int required(int size, int msize, int maxneed)
return used; return used;
} }
static int static int matmod(const unit * u, const resource_type * rtype, int value)
matmod(const attrib * a, const unit * u, const resource_type * material,
int value)
{ {
for (a = a_find((attrib *)a, &at_matmod); a && a->type == &at_matmod; if (rtype->modifiers) {
a = a->next) { variant save = frac_make(1, 1);
mm_fun fun = (mm_fun)a->data.f; const struct building_type *btype = NULL;
value = fun(u, material, value); const struct race *rc = u_race(u);
if (value < 0) resource_mod *mod;
return value; /* pass errors to caller */ if (u->building && inside_building(u)) {
btype = u->building->type;
}
for (mod = rtype->modifiers; mod->type != RMT_END; ++mod) {
if (mod->type == RMT_USE_SAVE) {
if (!mod->btype || mod->btype == btype) {
if (!mod->race || mod->race == rc) {
save = frac_mul(save, mod->value);
}
}
}
}
return value * save.sa[0] / save.sa[1];
} }
return value; return value;
} }
@ -439,14 +447,8 @@ static int use_materials(unit *u, const construction *type, int n, int completed
required(completed + n, type->reqsize, type->materials[c].number); required(completed + n, type->reqsize, type->materials[c].number);
int multi = 1; int multi = 1;
int canuse = 100; /* normalization */ int canuse = 100; /* normalization */
if (building_is_active(u->building) && inside_building(u)) { canuse = matmod(u, rtype, canuse);
canuse = matmod(u->building->type->attribs, u, rtype, canuse); assert(canuse >= 0);
}
if (canuse < 0) {
return canuse; /* pass errors to caller */
}
canuse = matmod(type->attribs, u, rtype, canuse);
assert(canuse % 100 == 0 assert(canuse % 100 == 0
|| !"only constant multipliers are implemented in build()"); || !"only constant multipliers are implemented in build()");
multi = canuse / 100; multi = canuse / 100;
@ -468,14 +470,9 @@ static int count_materials(unit *u, const construction *type, int n, int complet
const struct resource_type *rtype = type->materials[c].rtype; const struct resource_type *rtype = type->materials[c].rtype;
int need, prebuilt; int need, prebuilt;
int canuse = get_pooled(u, rtype, GET_DEFAULT, INT_MAX); int canuse = get_pooled(u, rtype, GET_DEFAULT, INT_MAX);
canuse = matmod(u, rtype, canuse);
if (building_is_active(u->building) && inside_building(u)) { assert(canuse >= 0);
canuse = matmod(u->building->type->attribs, u, rtype, canuse);
}
if (canuse < 0)
return canuse; /* pass errors to caller */
canuse = matmod(type->attribs, u, rtype, canuse);
if (type->reqsize > 1) { if (type->reqsize > 1) {
prebuilt = prebuilt =
required(completed, type->reqsize, type->materials[c].number); required(completed, type->reqsize, type->materials[c].number);
@ -503,7 +500,7 @@ static int count_materials(unit *u, const construction *type, int n, int complet
* of the first object have already been finished. return the * of the first object have already been finished. return the
* actual size that could be built. * actual size that could be built.
*/ */
int build(unit * u, const construction * ctype, int completed, int want) int build(unit * u, const construction * ctype, int completed, int want, int skill_mod)
{ {
const construction *type = ctype; const construction *type = ctype;
int skills = INT_MAX; /* number of skill points remainig */ int skills = INT_MAX; /* number of skill points remainig */
@ -536,17 +533,8 @@ int build(unit * u, const construction * ctype, int completed, int want)
if (basesk == 0) if (basesk == 0)
return ENEEDSKILL; return ENEEDSKILL;
effsk = basesk; effsk = basesk + skill_mod;
if (building_is_active(u->building) && inside_building(u)) { assert(effsk >= 0);
effsk = skillmod(u->building->type->attribs, u, u->region, type->skill,
effsk, SMF_PRODUCTION);
}
effsk = skillmod(type->attribs, u, u->region, type->skill,
effsk, SMF_PRODUCTION);
if (effsk < 0)
return effsk; /* pass errors to caller */
if (effsk == 0)
return ENEEDSKILL;
skills = effsk * u->number; skills = effsk * u->number;
@ -799,7 +787,7 @@ build_building(unit * u, const building_type * btype, int id, int want, order *
} }
} }
} }
built = build(u, btype->construction, built, n); built = build(u, btype->construction, built, n, 0);
switch (built) { switch (built) {
case ECOMPLETE: case ECOMPLETE:
@ -884,7 +872,7 @@ static void build_ship(unit * u, ship * sh, int want)
const construction *construction = sh->type->construction; const construction *construction = sh->type->construction;
int size = (sh->size * DAMAGE_SCALE - sh->damage) / DAMAGE_SCALE; int size = (sh->size * DAMAGE_SCALE - sh->damage) / DAMAGE_SCALE;
int n; int n;
int can = build(u, construction, size, want); int can = build(u, construction, size, want, 0);
if ((n = construction->maxsize - sh->size) > 0 && can > 0) { if ((n = construction->maxsize - sh->size) > 0 && can > 0) {
if (can >= n) { if (can >= n) {

View file

@ -32,8 +32,6 @@ extern "C" {
* wichtig * wichtig
*/ */
struct xml_tag;
typedef struct requirement { typedef struct requirement {
const struct resource_type *rtype; const struct resource_type *rtype;
int number; int number;
@ -57,14 +55,11 @@ extern "C" {
* last level of a building points to NULL, as do objects of * last level of a building points to NULL, as do objects of
* an unlimited size. * an unlimited size.
*/ */
struct attrib *attribs;
/* stores skill modifiers and other attributes */
} construction; } construction;
void free_construction(struct construction *cons); void free_construction(struct construction *cons);
extern int destroy_cmd(struct unit *u, struct order *ord); int destroy_cmd(struct unit *u, struct order *ord);
extern int leave_cmd(struct unit *u, struct order *ord); int leave_cmd(struct unit *u, struct order *ord);
void build_road(struct unit *u, int size, direction_t d); void build_road(struct unit *u, int size, direction_t d);
void create_ship(struct unit *u, const struct ship_type *newtype, void create_ship(struct unit *u, const struct ship_type *newtype,
@ -74,16 +69,15 @@ extern "C" {
struct building *getbuilding(const struct region *r); struct building *getbuilding(const struct region *r);
struct ship *getship(const struct region *r); struct ship *getship(const struct region *r);
void reportevent(struct region *r, char *s);
void shash(struct ship *sh); void shash(struct ship *sh);
void sunhash(struct ship *sh); void sunhash(struct ship *sh);
extern int roqf_factor(void); int roqf_factor(void);
int build(struct unit *u, const construction * ctype, int completed, int want, int skill_mod);
int maxbuild(const struct unit *u, const construction * cons);
struct message *msg_materials_required(struct unit *u, struct order *ord,
const struct construction *ctype, int multi);
int build(struct unit *u, const construction * ctype, int completed, int want);
extern int maxbuild(const struct unit *u, const construction * cons);
extern struct message *msg_materials_required(struct unit *u,
struct order *ord, const struct construction *ctype, int multi);
/** error messages that build may return: */ /** error messages that build may return: */
#define ELOWSKILL -1 #define ELOWSKILL -1
#define ENEEDSKILL -2 #define ENEEDSKILL -2

View file

@ -63,10 +63,10 @@ static void test_build_requires_materials(CuTest *tc) {
u = setup_build(&bf); u = setup_build(&bf);
set_level(u, SK_ARMORER, 2); set_level(u, SK_ARMORER, 2);
CuAssertIntEquals(tc, ENOMATERIALS, build(u, &bf.cons, 0, 1)); CuAssertIntEquals(tc, ENOMATERIALS, build(u, &bf.cons, 0, 1, 0));
itype = bf.cons.materials[0].rtype->itype; itype = bf.cons.materials[0].rtype->itype;
i_change(&u->items, itype, 2); i_change(&u->items, itype, 2);
CuAssertIntEquals(tc, 1, build(u, &bf.cons, 0, 1)); CuAssertIntEquals(tc, 1, build(u, &bf.cons, 0, 1, 0));
CuAssertIntEquals(tc, 1, i_get(u->items, itype)); CuAssertIntEquals(tc, 1, i_get(u->items, itype));
teardown_build(&bf); teardown_build(&bf);
} }
@ -84,12 +84,12 @@ static void test_build_requires_building(CuTest *tc) {
bf.cons.btype = btype = bt_get_or_create("hodor"); bf.cons.btype = btype = bt_get_or_create("hodor");
btype->maxcapacity = 1; btype->maxcapacity = 1;
btype->capacity = 1; btype->capacity = 1;
CuAssertIntEquals_Msg(tc, "must be inside a production building", EBUILDINGREQ, build(u, &bf.cons, 0, 1)); CuAssertIntEquals_Msg(tc, "must be inside a production building", EBUILDINGREQ, build(u, &bf.cons, 0, 1, 0));
u->building = test_create_building(u->region, btype); u->building = test_create_building(u->region, btype);
fset(u->building, BLD_MAINTAINED); fset(u->building, BLD_MAINTAINED);
CuAssertIntEquals(tc, 1, build(u, &bf.cons, 0, 1)); CuAssertIntEquals(tc, 1, build(u, &bf.cons, 0, 1, 0));
btype->maxcapacity = 0; btype->maxcapacity = 0;
CuAssertIntEquals_Msg(tc, "cannot build when production building capacity exceeded", EBUILDINGREQ, build(u, &bf.cons, 0, 1)); CuAssertIntEquals_Msg(tc, "cannot build when production building capacity exceeded", EBUILDINGREQ, build(u, &bf.cons, 0, 1, 0));
teardown_build(&bf); teardown_build(&bf);
} }
@ -101,7 +101,7 @@ static void test_build_failure_missing_skill(CuTest *tc) {
u = setup_build(&bf); u = setup_build(&bf);
rtype = bf.cons.materials[0].rtype; rtype = bf.cons.materials[0].rtype;
i_change(&u->items, rtype->itype, 1); i_change(&u->items, rtype->itype, 1);
CuAssertIntEquals(tc, ENEEDSKILL, build(u, &bf.cons, 1, 1)); CuAssertIntEquals(tc, ENEEDSKILL, build(u, &bf.cons, 1, 1, 0));
teardown_build(&bf); teardown_build(&bf);
} }
@ -114,7 +114,7 @@ static void test_build_failure_low_skill(CuTest *tc) {
rtype = bf.cons.materials[0].rtype; rtype = bf.cons.materials[0].rtype;
i_change(&u->items, rtype->itype, 1); i_change(&u->items, rtype->itype, 1);
set_level(u, SK_ARMORER, bf.cons.minskill - 1); set_level(u, SK_ARMORER, bf.cons.minskill - 1);
CuAssertIntEquals(tc, ELOWSKILL, build(u, &bf.cons, 0, 10)); CuAssertIntEquals(tc, ELOWSKILL, build(u, &bf.cons, 0, 10, 0));
teardown_build(&bf); teardown_build(&bf);
} }
@ -128,7 +128,7 @@ static void test_build_failure_completed(CuTest *tc) {
i_change(&u->items, rtype->itype, 1); i_change(&u->items, rtype->itype, 1);
set_level(u, SK_ARMORER, bf.cons.minskill); set_level(u, SK_ARMORER, bf.cons.minskill);
bf.cons.maxsize = 1; bf.cons.maxsize = 1;
CuAssertIntEquals(tc, ECOMPLETE, build(u, &bf.cons, bf.cons.maxsize, 10)); CuAssertIntEquals(tc, ECOMPLETE, build(u, &bf.cons, bf.cons.maxsize, 10, 0));
CuAssertIntEquals(tc, 1, i_get(u->items, rtype->itype)); CuAssertIntEquals(tc, 1, i_get(u->items, rtype->itype));
teardown_build(&bf); teardown_build(&bf);
} }
@ -143,19 +143,19 @@ static void test_build_limits(CuTest *tc) {
assert(rtype); assert(rtype);
i_change(&u->items, rtype->itype, 1); i_change(&u->items, rtype->itype, 1);
set_level(u, SK_ARMORER, bf.cons.minskill); set_level(u, SK_ARMORER, bf.cons.minskill);
CuAssertIntEquals(tc, 1, build(u, &bf.cons, 0, 10)); CuAssertIntEquals(tc, 1, build(u, &bf.cons, 0, 10, 0));
CuAssertIntEquals(tc, 0, i_get(u->items, rtype->itype)); CuAssertIntEquals(tc, 0, i_get(u->items, rtype->itype));
scale_number(u, 2); scale_number(u, 2);
set_level(u, SK_ARMORER, bf.cons.minskill); set_level(u, SK_ARMORER, bf.cons.minskill);
i_change(&u->items, rtype->itype, 2); i_change(&u->items, rtype->itype, 2);
CuAssertIntEquals(tc, 2, build(u, &bf.cons, 0, 10)); CuAssertIntEquals(tc, 2, build(u, &bf.cons, 0, 10, 0));
CuAssertIntEquals(tc, 0, i_get(u->items, rtype->itype)); CuAssertIntEquals(tc, 0, i_get(u->items, rtype->itype));
scale_number(u, 2); scale_number(u, 2);
set_level(u, SK_ARMORER, bf.cons.minskill * 2); set_level(u, SK_ARMORER, bf.cons.minskill * 2);
i_change(&u->items, rtype->itype, 4); i_change(&u->items, rtype->itype, 4);
CuAssertIntEquals(tc, 4, build(u, &bf.cons, 0, 10)); CuAssertIntEquals(tc, 4, build(u, &bf.cons, 0, 10, 0));
CuAssertIntEquals(tc, 0, i_get(u->items, rtype->itype)); CuAssertIntEquals(tc, 0, i_get(u->items, rtype->itype));
teardown_build(&bf); teardown_build(&bf);
} }
@ -174,7 +174,7 @@ static void test_build_with_ring(CuTest *tc) {
set_level(u, SK_ARMORER, bf.cons.minskill); set_level(u, SK_ARMORER, bf.cons.minskill);
i_change(&u->items, rtype->itype, 20); i_change(&u->items, rtype->itype, 20);
i_change(&u->items, ring, 1); i_change(&u->items, ring, 1);
CuAssertIntEquals(tc, 10, build(u, &bf.cons, 0, 20)); CuAssertIntEquals(tc, 10, build(u, &bf.cons, 0, 20, 0));
CuAssertIntEquals(tc, 10, i_get(u->items, rtype->itype)); CuAssertIntEquals(tc, 10, i_get(u->items, rtype->itype));
teardown_build(&bf); teardown_build(&bf);
} }
@ -193,16 +193,16 @@ static void test_build_with_potion(CuTest *tc) {
i_change(&u->items, rtype->itype, 20); i_change(&u->items, rtype->itype, 20);
change_effect(u, ptype, 4); change_effect(u, ptype, 4);
set_level(u, SK_ARMORER, bf.cons.minskill); set_level(u, SK_ARMORER, bf.cons.minskill);
CuAssertIntEquals(tc, 2, build(u, &bf.cons, 0, 20)); CuAssertIntEquals(tc, 2, build(u, &bf.cons, 0, 20, 0));
CuAssertIntEquals(tc, 18, i_get(u->items, rtype->itype)); CuAssertIntEquals(tc, 18, i_get(u->items, rtype->itype));
CuAssertIntEquals(tc, 3, get_effect(u, ptype)); CuAssertIntEquals(tc, 3, get_effect(u, ptype));
set_level(u, SK_ARMORER, bf.cons.minskill * 2); set_level(u, SK_ARMORER, bf.cons.minskill * 2);
CuAssertIntEquals(tc, 4, build(u, &bf.cons, 0, 20)); CuAssertIntEquals(tc, 4, build(u, &bf.cons, 0, 20, 0));
CuAssertIntEquals(tc, 2, get_effect(u, ptype)); CuAssertIntEquals(tc, 2, get_effect(u, ptype));
set_level(u, SK_ARMORER, bf.cons.minskill); set_level(u, SK_ARMORER, bf.cons.minskill);
scale_number(u, 2); /* OBS: this scales the effects, too: */ scale_number(u, 2); /* OBS: this scales the effects, too: */
CuAssertIntEquals(tc, 4, get_effect(u, ptype)); CuAssertIntEquals(tc, 4, get_effect(u, ptype));
CuAssertIntEquals(tc, 4, build(u, &bf.cons, 0, 20)); CuAssertIntEquals(tc, 4, build(u, &bf.cons, 0, 20, 0));
CuAssertIntEquals(tc, 2, get_effect(u, ptype)); CuAssertIntEquals(tc, 2, get_effect(u, ptype));
teardown_build(&bf); teardown_build(&bf);
} }

View file

@ -55,7 +55,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* attributes includes */ /* attributes includes */
#include <attributes/reduceproduction.h> #include <attributes/reduceproduction.h>
#include <attributes/matmod.h>
typedef struct building_typelist { typedef struct building_typelist {
struct building_typelist *next; struct building_typelist *next;
@ -99,9 +98,6 @@ bool bt_changed(int *cache)
void bt_register(building_type * type) void bt_register(building_type * type)
{ {
if (type->init) {
type->init(type);
}
selist_push(&buildingtypes, (void *)type); selist_push(&buildingtypes, (void *)type);
++bt_changes; ++bt_changes;
} }
@ -224,31 +220,6 @@ building *findbuilding(int i)
return bfindhash(i); return bfindhash(i);
} }
/* ** old building types ** */
static int sm_smithy(const unit * u, const region * r, skill_t sk, int value)
{ /* skillmod */
if (sk == SK_WEAPONSMITH || sk == SK_ARMORER) {
if (u->region == r)
return value + 1;
}
return value;
}
static int mm_smithy(const unit * u, const resource_type * rtype, int value)
{ /* material-mod */
if (rtype == get_resourcetype(R_IRON))
return value * 2;
return value;
}
static void init_smithy(struct building_type *bt)
{
a_add(&bt->attribs, make_skillmod(NOSKILL, SMF_PRODUCTION, sm_smithy, 1.0,
0));
a_add(&bt->attribs, make_matmod(mm_smithy));
}
static const char *castle_name_i(const struct building_type *btype, static const char *castle_name_i(const struct building_type *btype,
const struct building *b, int bsize, const char *fname[]) const struct building *b, int bsize, const char *fname[])
{ {
@ -915,7 +886,6 @@ int cmp_current_owner(const building * b, const building * a)
void register_buildings(void) void register_buildings(void)
{ {
register_function((pf_generic)init_smithy, "init_smithy");
register_function((pf_generic)castle_name, "castle_name"); register_function((pf_generic)castle_name, "castle_name");
register_function((pf_generic)castle_name_2, "castle_name_2"); register_function((pf_generic)castle_name_2, "castle_name_2");
register_function((pf_generic)fort_name, "fort_name"); register_function((pf_generic)fort_name, "fort_name");

View file

@ -66,10 +66,10 @@ extern "C" {
double auraregen; /* modifier for aura regeneration inside building */ double auraregen; /* modifier for aura regeneration inside building */
struct maintenance *maintenance; /* array of requirements */ struct maintenance *maintenance; /* array of requirements */
struct construction *construction; /* construction of 1 building-level */ struct construction *construction; /* construction of 1 building-level */
struct resource_mod *modifiers; /* modify production skills */
const char *(*name) (const struct building_type *, const char *(*name) (const struct building_type *,
const struct building * b, int size); const struct building * b, int size);
void(*init) (struct building_type *);
void(*age) (struct building *); void(*age) (struct building *);
double(*taxes) (const struct building *, int size); double(*taxes) (const struct building *, int size);
struct attrib *attribs; struct attrib *attribs;

View file

@ -296,7 +296,6 @@ static void test_btype_defaults(CuTest *tc) {
CuAssertPtrEquals(tc, 0, btype->maintenance); CuAssertPtrEquals(tc, 0, btype->maintenance);
CuAssertPtrEquals(tc, 0, btype->construction); CuAssertPtrEquals(tc, 0, btype->construction);
CuAssertTrue(tc, !btype->name); CuAssertTrue(tc, !btype->name);
CuAssertTrue(tc, !btype->init);
CuAssertTrue(tc, !btype->age); CuAssertTrue(tc, !btype->age);
CuAssertTrue(tc, !btype->taxes); CuAssertTrue(tc, !btype->taxes);
CuAssertDblEquals(tc, 1.0, btype->auraregen, 0.0); CuAssertDblEquals(tc, 1.0, btype->auraregen, 0.0);

View file

@ -644,7 +644,7 @@ int skill_limit(faction * f, skill_t sk)
m = max_magicians(f); m = max_magicians(f);
} }
else if (sk == SK_ALCHEMY) { else if (sk == SK_ALCHEMY) {
m = config_get_int("rules.maxskills.alchemy", MAXALCHEMISTS); m = config_get_int("rules.maxskills.alchemy", 3);
} }
return m; return m;
} }
@ -752,22 +752,6 @@ int count_maxmigrants(const faction * f)
return 0; return 0;
} }
static void init_maxmagicians(struct attrib *a)
{
a->data.i = MAXMAGICIANS;
}
attrib_type at_maxmagicians = {
"maxmagicians",
init_maxmagicians,
NULL,
NULL,
a_writeint,
a_readint,
NULL,
ATF_UNIQUE
};
int max_magicians(const faction * f) int max_magicians(const faction * f)
{ {
static int rule, config, rc_cache; static int rule, config, rc_cache;
@ -775,15 +759,9 @@ int max_magicians(const faction * f)
int m; int m;
if (config_changed(&config)) { if (config_changed(&config)) {
rule = config_get_int("rules.maxskills.magic", MAXMAGICIANS); rule = config_get_int("rules.maxskills.magic", 3);
} }
m = rule; m = rule;
if (f->attribs) {
attrib *a = a_find(f->attribs, &at_maxmagicians);
if (a) {
m = a->data.i;
}
}
if (rc_changed(&rc_cache)) { if (rc_changed(&rc_cache)) {
rc_elf = get_race(RC_ELF); rc_elf = get_race(RC_ELF);
} }

View file

@ -35,8 +35,6 @@ extern "C" {
struct gamedata; struct gamedata;
struct selist; struct selist;
extern struct attrib_type at_maxmagicians;
/* faction flags */ /* faction flags */
#define FFL_NEWID (1<<0) /* Die Partei hat bereits einmal ihre no gewechselt */ #define FFL_NEWID (1<<0) /* Die Partei hat bereits einmal ihre no gewechselt */
#define FFL_ISNEW (1<<1) #define FFL_ISNEW (1<<1)
@ -44,8 +42,8 @@ extern "C" {
#define FFL_QUIT (1<<3) #define FFL_QUIT (1<<3)
#define FFL_CURSED (1<<4) /* you're going to have a bad time */ #define FFL_CURSED (1<<4) /* you're going to have a bad time */
#define FFL_DEFENDER (1<<10) #define FFL_DEFENDER (1<<10)
#define FFL_SELECT (1<<18) /* ehemals f->dh, u->dh, r->dh, etc... */
#define FFL_NOAID (1<<21) /* Hilfsflag Kampf */ #define FFL_NOAID (1<<21) /* Hilfsflag Kampf */
#define FFL_SELECT (1<<22) /* ehemals f->dh, u->dh, r->dh, etc... */
#define FFL_MARK (1<<23) /* f<>r markierende algorithmen, die das #define FFL_MARK (1<<23) /* f<>r markierende algorithmen, die das
* hinterher auch wieder l<EFBFBD>schen m<EFBFBD>ssen! * hinterher auch wieder l<EFBFBD>schen m<EFBFBD>ssen!
* (FFL_SELECT muss man vorher initialisieren, * (FFL_SELECT muss man vorher initialisieren,

View file

@ -90,11 +90,6 @@ extern "C" {
const resource_type *findresourcetype(const char *name, const resource_type *findresourcetype(const char *name,
const struct locale *lang); const struct locale *lang);
/* resource-limits for regions */
#define RMF_SKILL 0x01 /* int, bonus on resource production skill */
#define RMF_SAVEMATERIAL 0x02 /* fraction (sa[0]/sa[1]), multiplier on resource usage */
#define RMF_REQUIREDBUILDING 0x04 /* building, required to build */
/* bitfield values for item_type::flags */ /* bitfield values for item_type::flags */
#define ITF_NONE 0x0000 #define ITF_NONE 0x0000
#define ITF_HERB 0x0001 /* this item is a herb */ #define ITF_HERB 0x0001 /* this item is a herb */

View file

@ -44,13 +44,8 @@ static struct locale_data *locale_array[MAXLOCALES];
typedef struct order_data { typedef struct order_data {
const char *_str; const char *_str;
# ifdef LOMEM
int _refcount:20;
int _lindex:4;
# else
int _refcount; int _refcount;
int _lindex; int _lindex;
# endif
keyword_t _keyword; keyword_t _keyword;
} order_data; } order_data;

View file

@ -25,29 +25,29 @@ extern "C" {
typedef struct rawmaterial { typedef struct rawmaterial {
const struct resource_type *rtype; const struct resource_type *rtype;
#ifdef LOMEM
int amount:16;
int level:8;
int flags:8;
int base:8;
int divisor:8;
int startlevel:8;
#else
int amount; int amount;
int level; int level;
int flags; int flags;
int base; int base;
int divisor; int divisor;
int startlevel; int startlevel;
#endif
struct rawmaterial *next; struct rawmaterial *next;
} rawmaterial; } rawmaterial;
/* resource-limits for regions */
typedef enum resource_modifier_type {
RMT_END, /* array terminator */
RMT_PROD_SKILL, /* bonus on resource production skill */
RMT_PROD_SAVE, /* fractional multiplier when produced */
RMT_PROD_REQUIRE, /* building or race is required to produce this item */
RMT_USE_SAVE, /* fractional multiplier when used to manufacture something */
} resource_modifier_type;
typedef struct resource_mod { typedef struct resource_mod {
resource_modifier_type type;
variant value; variant value;
const struct building_type *btype; const struct building_type *btype;
const struct race *race; const struct race *race;
unsigned int flags;
} resource_mod; } resource_mod;
typedef struct rawmaterial_type { typedef struct rawmaterial_type {

View file

@ -1121,9 +1121,7 @@ static ally **addally(const faction * f, ally ** sfp, int aid, int state)
ally *sf; ally *sf;
state &= ~HELP_OBSERVE; state &= ~HELP_OBSERVE;
#ifndef REGIONOWNERS
state &= ~HELP_TRAVEL; state &= ~HELP_TRAVEL;
#endif
state &= HelpMask(); state &= HelpMask();
if (state == 0) if (state == 0)

View file

@ -62,8 +62,7 @@ attrib_type at_skillmod = {
ATF_PRESERVE ATF_PRESERVE
}; };
attrib *make_skillmod(skill_t sk, unsigned int flags, skillmod_fun special, attrib *make_skillmod(skill_t sk, skillmod_fun special, double multiplier, int bonus)
double multiplier, int bonus)
{ {
attrib *a = a_new(&at_skillmod); attrib *a = a_new(&at_skillmod);
skillmod_data *smd = (skillmod_data *)a->data.v; skillmod_data *smd = (skillmod_data *)a->data.v;
@ -72,22 +71,19 @@ attrib *make_skillmod(skill_t sk, unsigned int flags, skillmod_fun special,
smd->special = special; smd->special = special;
smd->bonus = bonus; smd->bonus = bonus;
smd->multiplier = multiplier; smd->multiplier = multiplier;
smd->flags = flags;
return a; return a;
} }
int int
skillmod(const attrib * a, const unit * u, const region * r, skill_t sk, skillmod(const unit * u, const region * r, skill_t sk, int value)
int value, int flags)
{ {
const attrib * a = u->attribs;
for (a = a_find((attrib *)a, &at_skillmod); a && a->type == &at_skillmod; for (a = a_find((attrib *)a, &at_skillmod); a && a->type == &at_skillmod;
a = a->next) { a = a->next) {
skillmod_data *smd = (skillmod_data *)a->data.v; skillmod_data *smd = (skillmod_data *)a->data.v;
if (smd->skill != NOSKILL && smd->skill != sk) if (smd->skill != NOSKILL && smd->skill != sk)
continue; continue;
if (flags != SMF_ALWAYS && (smd->flags & flags) == 0)
continue;
if (smd->special) { if (smd->special) {
value = smd->special(u, r, sk, value); value = smd->special(u, r, sk, value);
if (value < 0) if (value < 0)

View file

@ -25,23 +25,11 @@ struct attrib_type;
extern "C" { extern "C" {
#endif #endif
/* skillmod_data::flags -- wann gilt der modifier? */
#define SMF_ALWAYS (1<<0) /* immer */
#define SMF_PRODUCTION (1<<1) /* für Produktion - am gebäude, an der einheit */
#define SMF_RIDING (1<<2) /* Bonus für berittene - an der rasse */
typedef struct skill { typedef struct skill {
#ifdef LOMEM skill_t id;
int id:8;
unsigned int level:8;
unsigned int weeks:8;
unsigned int old:8;
#else
int id;
int level; int level;
int weeks; int weeks;
int old; int old;
#endif
} skill; } skill;
typedef int(*skillmod_fun) (const struct unit *, const struct region *, typedef int(*skillmod_fun) (const struct unit *, const struct region *,
@ -52,25 +40,23 @@ extern "C" {
double multiplier; double multiplier;
int number; int number;
int bonus; int bonus;
int flags;
} skillmod_data; } skillmod_data;
extern struct attrib_type at_skillmod;
extern int rc_skillmod(const struct race *rc, const struct region *r,
skill_t sk);
extern int skillmod(const struct attrib *a, const struct unit *u,
const struct region *r, skill_t sk, int value, int flags);
extern struct attrib *make_skillmod(skill_t sk, unsigned int flags,
skillmod_fun special, double multiplier, int bonus);
extern int level_days(int level); extern struct attrib_type at_skillmod;
extern int level(int days);
int rc_skillmod(const struct race *rc, const struct region *r, skill_t sk);
int skillmod(const struct unit *u, const struct region *r, skill_t sk, int value);
struct attrib *make_skillmod(skill_t sk, skillmod_fun special, double multiplier, int bonus);
int level_days(int level);
int level(int days);
#define skill_level(level) (level) #define skill_level(level) (level)
extern void reduce_skill(struct unit *u, skill * sv, unsigned int change); void reduce_skill(struct unit *u, skill * sv, unsigned int change);
extern int skill_weeks(int level); int skill_weeks(int level);
extern int skill_compare(const skill * sk, const skill * sc); int skill_compare(const skill * sk, const skill * sc);
extern void sk_set(skill * sv, int level); void sk_set(skill * sv, int level);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -1333,8 +1333,9 @@ int get_modifier(const unit * u, skill_t sk, int level, const region * r, bool n
skill += rc_skillmod(u_race(u), r, sk); skill += rc_skillmod(u_race(u), r, sk);
skill += att_modification(u, sk); skill += att_modification(u, sk);
if (u->attribs) {
skill = skillmod(u->attribs, u, r, sk, skill, SMF_ALWAYS); skill = skillmod(u, r, sk, skill);
}
if (fval(u, UFL_HUNGER)) { if (fval(u, UFL_HUNGER)) {
if (sk == SK_SAILING && skill > 2) { if (sk == SK_SAILING && skill > 2) {
@ -1724,13 +1725,13 @@ int unit_max_hp(const unit * u)
int h; int h;
double p; double p;
static int config; static int config;
static int rule_stamina; static bool rule_stamina;
h = u_race(u)->hitpoints; h = u_race(u)->hitpoints;
if (config_changed(&config)) { if (config_changed(&config)) {
rule_stamina = config_get_int("rules.stamina", STAMINA_AFFECTS_HP); rule_stamina = config_get_int("rules.stamina", 1)!=0;
} }
if (rule_stamina & 1) { if (rule_stamina) {
p = pow(effskill(u, SK_STAMINA, u->region) / 2.0, 1.5) * 0.2; p = pow(effskill(u, SK_STAMINA, u->region) / 2.0, 1.5) * 0.2;
h += (int)(h * p + 0.5); h += (int)(h * p + 0.5);
} }

View file

@ -256,19 +256,19 @@ static void test_skillmod(CuTest *tc) {
set_level(u, SK_ARMORER, 5); set_level(u, SK_ARMORER, 5);
CuAssertIntEquals(tc, 5, effskill(u, SK_ARMORER, 0)); CuAssertIntEquals(tc, 5, effskill(u, SK_ARMORER, 0));
a_add(&u->attribs, a = make_skillmod(SK_ARMORER, SMF_ALWAYS, 0, 2.0, 0)); a_add(&u->attribs, a = make_skillmod(SK_ARMORER, 0, 2.0, 0));
CuAssertIntEquals(tc, 10, effskill(u, SK_ARMORER, 0)); CuAssertIntEquals(tc, 10, effskill(u, SK_ARMORER, 0));
a_remove(&u->attribs, a); a_remove(&u->attribs, a);
a_add(&u->attribs, a = make_skillmod(NOSKILL, SMF_ALWAYS, 0, 2.0, 0)); /* NOSKILL means any skill */ a_add(&u->attribs, a = make_skillmod(NOSKILL, 0, 2.0, 0)); /* NOSKILL means any skill */
CuAssertIntEquals(tc, 10, effskill(u, SK_ARMORER, 0)); CuAssertIntEquals(tc, 10, effskill(u, SK_ARMORER, 0));
a_remove(&u->attribs, a); a_remove(&u->attribs, a);
a_add(&u->attribs, a = make_skillmod(SK_ARMORER, SMF_ALWAYS, 0, 0, 2)); a_add(&u->attribs, a = make_skillmod(SK_ARMORER, 0, 0, 2));
CuAssertIntEquals(tc, 7, effskill(u, SK_ARMORER, 0)); CuAssertIntEquals(tc, 7, effskill(u, SK_ARMORER, 0));
a_remove(&u->attribs, a); a_remove(&u->attribs, a);
a_add(&u->attribs, a = make_skillmod(SK_ARMORER, SMF_ALWAYS, cb_skillmod, 0, 0)); a_add(&u->attribs, a = make_skillmod(SK_ARMORER, cb_skillmod, 0, 0));
CuAssertIntEquals(tc, 8, effskill(u, SK_ARMORER, 0)); CuAssertIntEquals(tc, 8, effskill(u, SK_ARMORER, 0));
a_remove(&u->attribs, a); a_remove(&u->attribs, a);

View file

@ -120,6 +120,72 @@ static xmlChar *xml_cleanup_string(xmlChar * str)
return str; return str;
} }
static resource_mod * xml_readmodifiers(xmlXPathObjectPtr result, xmlNodePtr node) {
/* reading eressea/resources/resource/modifier */
if (result->nodesetval != NULL && result->nodesetval->nodeNr > 0) {
int k;
resource_mod * modifiers =
calloc(result->nodesetval->nodeNr + 1, sizeof(resource_mod));
for (k = 0; k != result->nodesetval->nodeNr; ++k) {
xmlNodePtr node = result->nodesetval->nodeTab[k];
xmlChar *propValue;
building_type *btype = NULL;
const race *rc = NULL;
propValue = xmlGetProp(node, BAD_CAST "race");
if (propValue != NULL) {
rc = rc_find((const char *)propValue);
if (rc == NULL)
rc = rc_get_or_create((const char *)propValue);
xmlFree(propValue);
}
modifiers[k].race = rc;
propValue = xmlGetProp(node, BAD_CAST "building");
if (propValue != NULL) {
btype = bt_get_or_create((const char *)propValue);
xmlFree(propValue);
}
modifiers[k].btype = btype;
propValue = xmlGetProp(node, BAD_CAST "type");
assert(propValue != NULL);
if (strcmp((const char *)propValue, "skill") == 0) {
xmlChar *propSkill;
skill_t sk = NOSKILL;
modifiers[k].type = RMT_PROD_SKILL;
propSkill = xmlGetProp(node, BAD_CAST "skill");
if (propSkill) {
sk = findskill((const char *)propSkill);
xmlFree(propSkill);
}
modifiers[k].value.sa[0] = (short)sk;
modifiers[k].value.sa[1] = (short)xml_ivalue(node, "value", 0);
}
else if (strcmp((const char *)propValue, "material") == 0) {
modifiers[k].value = xml_fraction(node, "value");
modifiers[k].type = RMT_PROD_SAVE;
}
else {
if (strcmp((const char *)propValue, "require") == 0) {
modifiers[k].type = RMT_PROD_REQUIRE;
}
else if (strcmp((const char *)propValue, "save") == 0) {
modifiers[k].type = RMT_USE_SAVE;
modifiers[k].value = xml_fraction(node, "value");
}
else {
log_error("unknown type '%s' for resourcelimit-modifier", (const char *)propValue);
}
}
xmlFree(propValue);
}
return modifiers;
}
return NULL;
}
static void static void
xml_readrequirements(xmlNodePtr * nodeTab, int nodeNr, requirement ** reqArray) xml_readrequirements(xmlNodePtr * nodeTab, int nodeNr, requirement ** reqArray)
{ {
@ -157,7 +223,6 @@ construction ** consPtr)
xmlChar *propValue; xmlChar *propValue;
construction *con; construction *con;
xmlXPathObjectPtr req; xmlXPathObjectPtr req;
int m;
skill_t sk = NOSKILL; skill_t sk = NOSKILL;
propValue = xmlGetProp(node, BAD_CAST "skill"); propValue = xmlGetProp(node, BAD_CAST "skill");
@ -193,23 +258,6 @@ construction ** consPtr)
xml_readrequirements(req->nodesetval->nodeTab, xml_readrequirements(req->nodesetval->nodeTab,
req->nodesetval->nodeNr, &con->materials); req->nodesetval->nodeNr, &con->materials);
xmlXPathFreeObject(req); xmlXPathFreeObject(req);
/* read construction/modifier */
xpath->node = node;
req = xmlXPathEvalExpression(BAD_CAST "modifier", xpath);
for (m = 0; m != req->nodesetval->nodeNr; ++m) {
xmlNodePtr node = req->nodesetval->nodeTab[m];
propValue = xmlGetProp(node, BAD_CAST "function");
if (propValue != NULL) {
pf_generic foo = get_function((const char *)propValue);
a_add(&con->attribs, make_skillmod(NOSKILL, SMF_PRODUCTION,
(skillmod_fun)foo, 1.0, 0));
xmlFree(propValue);
}
}
xmlXPathFreeObject(req);
} }
xpath->node = pushNode; xpath->node = pushNode;
} }
@ -280,6 +328,12 @@ static int parse_buildings(xmlDocPtr doc)
if (xml_bvalue(node, "fort", false)) if (xml_bvalue(node, "fort", false))
btype->flags |= BTF_FORTIFICATION; btype->flags |= BTF_FORTIFICATION;
/* reading eressea/buildings/building/modifier */
xpath->node = node;
result = xmlXPathEvalExpression(BAD_CAST "modifier", xpath);
btype->modifiers = xml_readmodifiers(result, node);
xmlXPathFreeObject(result);
/* reading eressea/buildings/building/construction */ /* reading eressea/buildings/building/construction */
xpath->node = node; xpath->node = node;
result = xmlXPathEvalExpression(BAD_CAST "construction", xpath); result = xmlXPathEvalExpression(BAD_CAST "construction", xpath);
@ -305,9 +359,6 @@ static int parse_buildings(xmlDocPtr doc)
(const char *(*)(const struct building_type *, (const char *(*)(const struct building_type *,
const struct building *, int))fun; const struct building *, int))fun;
} }
else if (strcmp((const char *)propValue, "init") == 0) {
btype->init = (void(*)(struct building_type *))fun;
}
else if (strcmp((const char *)propValue, "age") == 0) { else if (strcmp((const char *)propValue, "age") == 0) {
btype->age = (void(*)(struct building *))fun; btype->age = (void(*)(struct building *))fun;
} }
@ -344,10 +395,6 @@ static int parse_buildings(xmlDocPtr doc)
mt->flags |= MTF_VARIABLE; mt->flags |= MTF_VARIABLE;
} }
xmlXPathFreeObject(result); xmlXPathFreeObject(result);
/* finally, initialize the new building type */
if (btype->init)
btype->init(btype);
} }
} }
xmlXPathFreeObject(buildings); xmlXPathFreeObject(buildings);
@ -951,58 +998,9 @@ static int parse_resources(xmlDocPtr doc)
if (xml_bvalue(node, "limited", false)) { if (xml_bvalue(node, "limited", false)) {
rtype->flags |= RTF_LIMITED; rtype->flags |= RTF_LIMITED;
} }
/* reading eressea/resources/resource/modifier */
xpath->node = node; xpath->node = node;
result = xmlXPathEvalExpression(BAD_CAST "modifier", xpath); result = xmlXPathEvalExpression(BAD_CAST "modifier", xpath);
if (result->nodesetval != NULL && result->nodesetval->nodeNr > 0) { rtype->modifiers = xml_readmodifiers(result, node);
rtype->modifiers =
calloc(result->nodesetval->nodeNr + 1, sizeof(resource_mod));
for (k = 0; k != result->nodesetval->nodeNr; ++k) {
xmlNodePtr node = result->nodesetval->nodeTab[k];
building_type *btype = NULL;
const race *rc = NULL;
propValue = xmlGetProp(node, BAD_CAST "race");
if (propValue != NULL) {
rc = rc_find((const char *)propValue);
if (rc == NULL)
rc = rc_get_or_create((const char *)propValue);
xmlFree(propValue);
}
rtype->modifiers[k].race = rc;
propValue = xmlGetProp(node, BAD_CAST "building");
if (propValue != NULL) {
btype = bt_get_or_create((const char *)propValue);
xmlFree(propValue);
}
rtype->modifiers[k].btype = btype;
propValue = xmlGetProp(node, BAD_CAST "type");
assert(propValue != NULL);
if (strcmp((const char *)propValue, "skill") == 0) {
rtype->modifiers[k].value.i = xml_ivalue(node, "value", 0);
rtype->modifiers[k].flags = RMF_SKILL;
}
else if (strcmp((const char *)propValue, "material") == 0) {
rtype->modifiers[k].value = xml_fraction(node, "value");
rtype->modifiers[k].flags = RMF_SAVEMATERIAL;
}
else if (strcmp((const char *)propValue, "require") == 0) {
xmlChar *propBldg = xmlGetProp(node, BAD_CAST "building");
if (propBldg != NULL) {
btype = bt_get_or_create((const char *)propBldg);
rtype->modifiers[k].btype = btype;
rtype->modifiers[k].flags = RMF_REQUIREDBUILDING;
xmlFree(propBldg);
}
}
else {
log_error("unknown type '%s' for resourcelimit-modifier '%s'\n", (const char *)propValue, rtype->_name);
}
xmlFree(propValue);
}
}
xmlXPathFreeObject(result); xmlXPathFreeObject(result);
/* reading eressea/resources/resource/resourcelimit/function */ /* reading eressea/resources/resource/resourcelimit/function */
xpath->node = node; xpath->node = node;

View file

@ -284,31 +284,6 @@ static double peasant_growth_factor(void)
return config_get_flt("rules.peasants.growth.factor", 0.0001F * PEASANTGROWTH); return config_get_flt("rules.peasants.growth.factor", 0.0001F * PEASANTGROWTH);
} }
#ifdef SLOWLUCK
int peasant_luck_effect(int peasants, int luck, int maxp, double variance) {
int n, births = 0;
double factor = peasant_growth_factor();
for (n = peasants; n && luck; --n) {
int chances = 0;
if (luck > 0) {
--luck;
chances += PEASANTLUCK;
}
while (chances--) {
if (rng_double() < factor) {
/* Only raise with 75% chance if peasants have
* reached 90% of maxpopulation */
if (peasants / (float)maxp < 0.9 || chance(PEASANTFORCE)) {
++births;
}
}
}
}
return births;
}
#else
static double peasant_luck_factor(void) static double peasant_luck_factor(void)
{ {
return config_get_flt("rules.peasants.peasantluck.factor", PEASANTLUCK); return config_get_flt("rules.peasants.peasantluck.factor", PEASANTLUCK);
@ -331,8 +306,6 @@ int peasant_luck_effect(int peasants, int luck, int maxp, double variance)
return births; return births;
} }
#endif
static void peasants(region * r, int rule) static void peasants(region * r, int rule)
{ {
int peasants = rpeasants(r); int peasants = rpeasants(r);
@ -1610,10 +1583,12 @@ int display_cmd(unit * u, struct order *ord)
free(*s); free(*s);
if (s2) { if (s2) {
*s = strdup(s2); char * str = strdup(s2);
if (strlen(s2) >= DISPLAYSIZE) { unicode_utf8_trim(str);
(*s)[DISPLAYSIZE] = 0; if (strlen(str) >= DISPLAYSIZE) {
str[DISPLAYSIZE-1] = 0;
} }
*s = str;
} }
else { else {
*s = 0; *s = 0;

View file

@ -1,5 +1,5 @@
/* /*
Copyright (c) 1998-2015, Enno Rehling <enno@eressea.de> Copyright (c) 1998-2017, Enno Rehling <enno@eressea.de>
Katja Zedel <katze@felidae.kn-bremen.de Katja Zedel <katze@felidae.kn-bremen.de
Christian Schlittchen <corwin@amber.kn-bremen.de> Christian Schlittchen <corwin@amber.kn-bremen.de>
@ -165,7 +165,7 @@ static int verbosity_to_flags(int verbosity) {
return flags; return flags;
} }
static int parse_args(int argc, char **argv, int *exitcode) static int parse_args(int argc, char **argv)
{ {
int i; int i;
int log_stderr = LOG_CPERROR; int log_stderr = LOG_CPERROR;
@ -178,10 +178,10 @@ static int parse_args(int argc, char **argv, int *exitcode)
} }
else if (argi[1] == '-') { /* long format */ else if (argi[1] == '-') { /* long format */
if (strcmp(argi + 2, "version") == 0) { if (strcmp(argi + 2, "version") == 0) {
printf("\n%s PBEM host\n" printf("Eressea version %s, "
"Copyright (C) 1996-2005 C. Schlittchen, K. Zedel, E. Rehling, H. Peters.\n\n" "Copyright (C) 2017 Enno Rehling et al.\n",
"Compilation: " __DATE__ " at " __TIME__ "\nVersion: %s\n\n", eressea_version());
game_name(), eressea_version()); return 1;
#ifdef USE_CURSES #ifdef USE_CURSES
} }
else if (strcmp(argi + 2, "color") == 0) { else if (strcmp(argi + 2, "color") == 0) {
@ -229,7 +229,6 @@ static int parse_args(int argc, char **argv, int *exitcode)
usage(argv[0], NULL); usage(argv[0], NULL);
return 1; return 1;
default: default:
*exitcode = -1;
usage(argv[0], argi); usage(argv[0], argi);
return 1; return 1;
} }
@ -300,8 +299,10 @@ int main(int argc, char **argv)
dictionary *d = 0; dictionary *d = 0;
setup_signal_handler(); setup_signal_handler();
/* parse arguments again, to override ini file */ /* parse arguments again, to override ini file */
parse_args(argc, argv, &err); err = parse_args(argc, argv);
if (err!=0) {
return (err>0) ? 0 : err;
}
d = parse_config(inifile); d = parse_config(inifile);
if (!d) { if (!d) {
log_error("could not open ini configuration %s\n", inifile); log_error("could not open ini configuration %s\n", inifile);

View file

@ -323,6 +323,7 @@ static void test_newbie_password_message(CuTest *tc) {
prepare_report(&ctx, f); prepare_report(&ctx, f);
CuAssertIntEquals(tc, FFL_PWMSG, f->flags&FFL_PWMSG); CuAssertIntEquals(tc, FFL_PWMSG, f->flags&FFL_PWMSG);
CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "changepasswd")); CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "changepasswd"));
finish_reports(&ctx);
test_cleanup(); test_cleanup();
} }
@ -359,6 +360,7 @@ static void test_prepare_travelthru(CuTest *tc) {
CuAssertPtrEquals(tc, f2, ctx.f); CuAssertPtrEquals(tc, f2, ctx.f);
CuAssertPtrEquals(tc, r1, ctx.first); CuAssertPtrEquals(tc, r1, ctx.first);
CuAssertPtrEquals(tc, NULL, ctx.last); CuAssertPtrEquals(tc, NULL, ctx.last);
finish_reports(&ctx);
test_cleanup(); test_cleanup();
} }
@ -384,6 +386,7 @@ static void test_get_addresses(CuTest *tc) {
CuAssertTrue(tc, selist_contains(ctx.addresses, f1, NULL)); CuAssertTrue(tc, selist_contains(ctx.addresses, f1, NULL));
CuAssertTrue(tc, selist_contains(ctx.addresses, f2, NULL)); CuAssertTrue(tc, selist_contains(ctx.addresses, f2, NULL));
CuAssertIntEquals(tc, 3, selist_length(ctx.addresses)); CuAssertIntEquals(tc, 3, selist_length(ctx.addresses));
finish_reports(&ctx);
test_cleanup(); test_cleanup();
} }
@ -411,6 +414,7 @@ static void test_get_addresses_fstealth(CuTest *tc) {
CuAssertTrue(tc, !selist_contains(ctx.addresses, f1, NULL)); CuAssertTrue(tc, !selist_contains(ctx.addresses, f1, NULL));
CuAssertTrue(tc, selist_contains(ctx.addresses, f2, NULL)); CuAssertTrue(tc, selist_contains(ctx.addresses, f2, NULL));
CuAssertIntEquals(tc, 2, selist_length(ctx.addresses)); CuAssertIntEquals(tc, 2, selist_length(ctx.addresses));
finish_reports(&ctx);
test_cleanup(); test_cleanup();
} }
@ -441,6 +445,7 @@ static void test_get_addresses_travelthru(CuTest *tc) {
CuAssertTrue(tc, !selist_contains(ctx.addresses, f1, NULL)); CuAssertTrue(tc, !selist_contains(ctx.addresses, f1, NULL));
CuAssertTrue(tc, selist_contains(ctx.addresses, f2, NULL)); CuAssertTrue(tc, selist_contains(ctx.addresses, f2, NULL));
CuAssertIntEquals(tc, 2, selist_length(ctx.addresses)); CuAssertIntEquals(tc, 2, selist_length(ctx.addresses));
finish_reports(&ctx);
test_cleanup(); test_cleanup();
} }
@ -523,6 +528,7 @@ static void test_prepare_lighthouse(CuTest *tc) {
CuAssertIntEquals(tc, seen_unit, r1->seen.mode); CuAssertIntEquals(tc, seen_unit, r1->seen.mode);
CuAssertIntEquals(tc, seen_lighthouse, r2->seen.mode); CuAssertIntEquals(tc, seen_lighthouse, r2->seen.mode);
CuAssertIntEquals(tc, seen_neighbour, r3->seen.mode); CuAssertIntEquals(tc, seen_neighbour, r3->seen.mode);
finish_reports(&ctx);
test_cleanup(); test_cleanup();
} }
@ -560,6 +566,7 @@ static void test_prepare_lighthouse_owners(CuTest *tc) {
CuAssertIntEquals(tc, seen_unit, r1->seen.mode); CuAssertIntEquals(tc, seen_unit, r1->seen.mode);
CuAssertIntEquals(tc, seen_lighthouse, r2->seen.mode); CuAssertIntEquals(tc, seen_lighthouse, r2->seen.mode);
CuAssertIntEquals(tc, seen_neighbour, r3->seen.mode); CuAssertIntEquals(tc, seen_neighbour, r3->seen.mode);
finish_reports(&ctx);
test_cleanup(); test_cleanup();
} }
@ -585,7 +592,6 @@ static void test_prepare_report(CuTest *tc) {
CuAssertIntEquals(tc, seen_unit, r->seen.mode); CuAssertIntEquals(tc, seen_unit, r->seen.mode);
finish_reports(&ctx); finish_reports(&ctx);
CuAssertIntEquals(tc, seen_none, r->seen.mode); CuAssertIntEquals(tc, seen_none, r->seen.mode);
finish_reports(&ctx);
r = test_create_region(2, 0, 0); r = test_create_region(2, 0, 0);
CuAssertPtrEquals(tc, r, regions->next); CuAssertPtrEquals(tc, r, regions->next);
@ -593,6 +599,7 @@ static void test_prepare_report(CuTest *tc) {
CuAssertPtrEquals(tc, regions, ctx.first); CuAssertPtrEquals(tc, regions, ctx.first);
CuAssertPtrEquals(tc, r, ctx.last); CuAssertPtrEquals(tc, r, ctx.last);
CuAssertIntEquals(tc, seen_none, r->seen.mode); CuAssertIntEquals(tc, seen_none, r->seen.mode);
finish_reports(&ctx);
test_cleanup(); test_cleanup();
} }

View file

@ -12,8 +12,6 @@
#define ENTERTAINFRACTION 20 #define ENTERTAINFRACTION 20
#define TEACHDIFFERENCE 2 #define TEACHDIFFERENCE 2
#define GUARD_DISABLES_RECRUIT 1
#define GUARD_DISABLES_PRODUCTION 1
#define RESOURCE_QUANTITY 0.5 #define RESOURCE_QUANTITY 0.5
#define RECRUITFRACTION 40 /* 100/RECRUITFRACTION% */ #define RECRUITFRACTION 40 /* 100/RECRUITFRACTION% */
#define COMBAT_TURNS 5 #define COMBAT_TURNS 5
@ -32,25 +30,13 @@
*/ */
#define MUSEUM_MODULE 1 #define MUSEUM_MODULE 1
#undef REGIONOWNERS /* (WIP) region-owner uses HELP_TRAVEL to control entry to region */
/* experimental gameplay features (that don't affect the savefile) */
/* TODO: move these settings to settings.h or into configuration files */ /* TODO: move these settings to settings.h or into configuration files */
#define GOBLINKILL /* Goblin-Spezialklau kann toedlich enden */
#define INSECT_POTION /* Spezialtrank fuer Insekten */
#define TREESIZE (8) /* space used by trees (in #peasants) */ #define TREESIZE (8) /* space used by trees (in #peasants) */
#define PEASANTFORCE 0.75 /* Chance einer Vermehrung trotz 90% Auslastung */ #define PEASANTFORCE 0.75 /* Chance einer Vermehrung trotz 90% Auslastung */
/* Gebaeudegroesse = Minimalbelagerer */ /* Gebaeudegroesse = Minimalbelagerer */
#define SIEGEFACTOR 2 #define SIEGEFACTOR 2
/** Magic */
#define MAXMAGICIANS 3
#define MAXALCHEMISTS 3
#define ENCCHANCE 10 /* %-Chance fuer einmalige Zufallsbegegnung */ #define ENCCHANCE 10 /* %-Chance fuer einmalige Zufallsbegegnung */
#define BAGCAPACITY 20000 /* soviel passt in einen Bag of Holding */ #define BAGCAPACITY 20000 /* soviel passt in einen Bag of Holding */
#define PERSON_WEIGHT 1000 /* weight of a "normal" human unit */ #define PERSON_WEIGHT 1000 /* weight of a "normal" human unit */
#define STAMINA_AFFECTS_HP 1<<0

View file

@ -556,7 +556,7 @@ int sp_mindblast_temp(struct castorder * co)
skill_t sk = random_skill(du, true); skill_t sk = random_skill(du, true);
if (sk != NOSKILL) { if (sk != NOSKILL) {
int n = 1 + rng_int() % maxloss; int n = 1 + rng_int() % maxloss;
attrib *a = make_skillmod(sk, SMF_ALWAYS, NULL, 0.0, n); attrib *a = make_skillmod(sk, NULL, 0.0, n);
/* neat: you can add a whole lot of these to a unit, they stack */ /* neat: you can add a whole lot of these to a unit, they stack */
a_add(&du->attribs, a); a_add(&du->attribs, a);
} }

View file

@ -163,6 +163,8 @@ static void init_learning(struct attrib *a)
static void done_learning(struct attrib *a) static void done_learning(struct attrib *a)
{ {
teaching_info *teach = (teaching_info *)a->data.v;
selist_free(teach->teachers);
free(a->data.v); free(a->data.v);
} }

View file

@ -127,6 +127,7 @@ static void test_attrib_rwstring(CuTest *tc) {
data.strm.api->rewind(data.strm.handle); data.strm.api->rewind(data.strm.handle);
a_readstring(&a, NULL, &data); a_readstring(&a, NULL, &data);
CuAssertStrEquals(tc, "Hello World", (const char *)a.data.v); CuAssertStrEquals(tc, "Hello World", (const char *)a.data.v);
a_finalizestring(&a);
mstream_done(&data.strm); mstream_done(&data.strm);
gamedata_done(&data); gamedata_done(&data);
test_cleanup(); test_cleanup();

@ -1 +1 @@
Subproject commit 2117191d4ad75e1eb14809878bc71d15b20a5d86 Subproject commit d807ef5ce64b3425b31fb440e0b93a4d233f517a

View file

@ -8,6 +8,7 @@ SET SERVER=%BUILD%\eressea.exe
%SERVER% ..\scripts\run-tests.lua %SERVER% ..\scripts\run-tests.lua
%SERVER% -re2 ..\scripts\run-tests-e2.lua %SERVER% -re2 ..\scripts\run-tests-e2.lua
%SERVER% -re3 ..\scripts\run-tests-e3.lua %SERVER% -re3 ..\scripts\run-tests-e3.lua
%SERVER% --version
PAUSE PAUSE
RMDIR /s /q reports RMDIR /s /q reports
DEL score score.alliances datum turn DEL score score.alliances datum turn