diff --git a/.gitmodules b/.gitmodules index 7dff5ab6a..4d903c57f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,6 @@ [submodule "lunit"] path = lunit url = https://github.com/ennorehling/lunit.git -[submodule "cmake"] - path = cmake - url = https://github.com/ennorehling/cmake.git [submodule "dlmalloc"] path = dlmalloc url = https://github.com/ennorehling/dlmalloc.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 405b86a03..d9ac81e80 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) FILE(TO_CMAKE_PATH "${CMAKE_MODULE_PATH}" CMAKE_MODULE_PATH ) FILE(TO_CMAKE_PATH "${CMAKE_PREFIX_PATH}" CMAKE_PREFIX_PATH ) endif(WIN32) -project (eressea-server C) +if (MSVC) +include(MSVC) +endif (MSVC) -enable_testing() -find_package (LibXml2) find_package (SQLite3) find_package (Curses) -find_package (Lua REQUIRED) +find_package (LibXml2) 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 (storage) @@ -19,8 +31,10 @@ add_subdirectory (iniparser) add_subdirectory (clibs) add_subdirectory (process) 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 "*.json") install(DIRECTORY scripts 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}) + diff --git a/cJSON b/cJSON index 43c04ad61..22a4fc9be 160000 --- a/cJSON +++ b/cJSON @@ -1 +1 @@ -Subproject commit 43c04ad61258ec3d54a2167eb3a43915bd003ab1 +Subproject commit 22a4fc9be31f0426e622f5bc9ebd7a1550845001 diff --git a/cmake b/cmake deleted file mode 160000 index f1fb3943a..000000000 --- a/cmake +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f1fb3943ace59994d90d71a891b80033dc2700a2 diff --git a/cmake/Modules/FindLua.cmake b/cmake/Modules/FindLua.cmake new file mode 100644 index 000000000..898ccbfd6 --- /dev/null +++ b/cmake/Modules/FindLua.cmake @@ -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 +# +# 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 +# +# 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) diff --git a/cmake/Modules/FindSQLite3.cmake b/cmake/Modules/FindSQLite3.cmake new file mode 100644 index 000000000..910b05cea --- /dev/null +++ b/cmake/Modules/FindSQLite3.cmake @@ -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 +# +# 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) diff --git a/cmake/Modules/FindToLua.cmake b/cmake/Modules/FindToLua.cmake new file mode 100644 index 000000000..52c721112 --- /dev/null +++ b/cmake/Modules/FindToLua.cmake @@ -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 +# +# 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) + diff --git a/cmake/Modules/MSVC.cmake b/cmake/Modules/MSVC.cmake new file mode 100644 index 000000000..d32822627 --- /dev/null +++ b/cmake/Modules/MSVC.cmake @@ -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) diff --git a/iniparser b/iniparser index ecf956b98..22741d9ce 160000 --- a/iniparser +++ b/iniparser @@ -1 +1 @@ -Subproject commit ecf956b9808c28c2db52e6b73930f57876dbb258 +Subproject commit 22741d9ce9d19bf7b5f5a219b6ed0925259a4d1b diff --git a/res/core/common/buildings.xml b/res/core/common/buildings.xml index 540e9f085..a799ce309 100644 --- a/res/core/common/buildings.xml +++ b/res/core/common/buildings.xml @@ -93,7 +93,6 @@ - @@ -102,6 +101,8 @@ + + diff --git a/res/core/messages.xml b/res/core/messages.xml index 42b95bc4c..5d8a60ef0 100644 --- a/res/core/messages.xml +++ b/res/core/messages.xml @@ -5536,8 +5536,8 @@ - "$unit($unit) in $region($region): '$order($command)' - Nur Elfen können diese Bögen herstellen." - "$unit($unit) in $region($region): '$order($command)' - Only elves can make these bows." + "$unit($unit) in $region($region): '$order($command)' - Diesen Gegenstand kann die Einheit nicht herstellen." + "$unit($unit) in $region($region): '$order($command)' - This unit cannot produce that." @@ -5545,8 +5545,8 @@ - "$unit($unit) in $region($region): '$order($command)' - Nur die EMail-Adresse angeben!" - "$unit($unit) in $region($region): '$order($command)' - Please provide only an email address!" + "$unit($unit) in $region($region): '$order($command)' - Diese Rasse kann das nicht herstellen." + "$unit($unit) in $region($region): '$order($command)' - This race cannot produce that." diff --git a/res/core/resources/iron.xml b/res/core/resources/iron.xml index 70d5c1080..1aff826fc 100644 --- a/res/core/resources/iron.xml +++ b/res/core/resources/iron.xml @@ -3,7 +3,8 @@ + - + diff --git a/res/core/weapons/greatbow.xml b/res/core/weapons/greatbow.xml index 32f07a41e..452ac0250 100644 --- a/res/core/weapons/greatbow.xml +++ b/res/core/weapons/greatbow.xml @@ -1,8 +1,8 @@ + - diff --git a/res/e3a/armor/scale.xml b/res/e3a/armor/scale.xml index 1038f4d6c..4d3e38e8a 100644 --- a/res/e3a/armor/scale.xml +++ b/res/e3a/armor/scale.xml @@ -1,8 +1,9 @@ + + - diff --git a/res/e3a/armor/towershield.xml b/res/e3a/armor/towershield.xml index 38e4f0928..aebbfc682 100644 --- a/res/e3a/armor/towershield.xml +++ b/res/e3a/armor/towershield.xml @@ -1,8 +1,9 @@ + + - diff --git a/res/e3a/resources/iron.xml b/res/e3a/resources/iron.xml index 01e0d8d6d..55f63ca67 100644 --- a/res/e3a/resources/iron.xml +++ b/res/e3a/resources/iron.xml @@ -3,6 +3,7 @@ + diff --git a/res/e3a/weapons/greatbow.xml b/res/e3a/weapons/greatbow.xml index 745d1793d..358a55f7d 100644 --- a/res/e3a/weapons/greatbow.xml +++ b/res/e3a/weapons/greatbow.xml @@ -4,9 +4,9 @@ * has lower damage --> + - diff --git a/res/e3a/weapons/rep_crossbow.xml b/res/e3a/weapons/rep_crossbow.xml index 02f0d865f..ffa1c0455 100644 --- a/res/e3a/weapons/rep_crossbow.xml +++ b/res/e3a/weapons/rep_crossbow.xml @@ -1,8 +1,8 @@ + - diff --git a/s/build b/s/build index 4ee259573..818cb0268 100755 --- a/s/build +++ b/s/build @@ -33,7 +33,7 @@ fi echo "build eressea" cd $ROOT/$BUILD 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//') cmake -DERESSEA_VERSION="$VERSION" .. else diff --git a/s/cmake-init b/s/cmake-init index 1ce7eccd3..9d529a433 100755 --- a/s/cmake-init +++ b/s/cmake-init @@ -10,6 +10,7 @@ ROOT=$(git rev-parse --show-toplevel) MACHINE=`$CC -dumpmachine` [ -z $MACHINE ] && MACHINE=`uname -m` BIN_DIR="$ROOT/build-$MACHINE-$CC-$BUILD" +rm -rf $BIN_DIR mkdir -p $BIN_DIR rm -f $BUILD ln -sf $BIN_DIR $BUILD @@ -29,12 +30,11 @@ if [ -d $HOME/usr ]; then fi DEST=$(dirname $ROOT)/server -ARGS=" -DCMAKE_MODULE_PATH=$ROOT/cmake/Modules \ - -DCMAKE_BUILD_TYPE=$BUILD \ +ARGS=" -DCMAKE_BUILD_TYPE=$BUILD \ -DCMAKE_LIBRARY_PATH=$LIBRARY_PATH \ - -DCMAKE_INCLUDE_PATH=$INCLUDE_PATH \ -DCMAKE_PREFIX_PATH=$PREFIX_PATH \ -DCMAKE_INSTALL_PREFIX=$DEST" +# -DCMAKE_INCLUDE_PATH=$INCLUDE_PATH git submodule update --init diff --git a/s/runtests b/s/runtests index e42640de1..14b5a658b 100755 --- a/s/runtests +++ b/s/runtests @@ -15,6 +15,7 @@ cd $ROOT $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-e3.lua +$ROOT/$BUILD/eressea/eressea --version rm -rf data reports orders.txt score score.alliances datum turn cd $OLDWPD diff --git a/scripts/tests/e2/init.lua b/scripts/tests/e2/init.lua index 651a9ad9b..705fd5013 100644 --- a/scripts/tests/e2/init.lua +++ b/scripts/tests/e2/init.lua @@ -1,3 +1,4 @@ +require 'tests.e2.production' require 'tests.e2.adamantium' require 'tests.e2.undead' require 'tests.e2.shiplanding' @@ -17,3 +18,4 @@ require 'tests.storage' require 'tests.magicbag' require 'tests.process' require 'tests.xmas' +require 'tests.production' diff --git a/scripts/tests/e2/production.lua b/scripts/tests/e2/production.lua new file mode 100644 index 000000000..1d31011af --- /dev/null +++ b/scripts/tests/e2/production.lua @@ -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 diff --git a/scripts/tests/e3/init.lua b/scripts/tests/e3/init.lua index 146d8733d..7206c80c4 100644 --- a/scripts/tests/e3/init.lua +++ b/scripts/tests/e3/init.lua @@ -1,14 +1,15 @@ -require 'tests.e3.production' -require 'tests.e3.castles' -require 'tests.e3.stealth' -require 'tests.e3.spells' +-- require 'tests.e3.castles' +-- require 'tests.e3.stealth' +-- require 'tests.e3.spells' require 'tests.e3.rules' -require 'tests.e3.parser' -require 'tests.e3.morale' -require 'tests.e3.items' -require 'tests.economy' -require 'tests.orders' -require 'tests.common' -require 'tests.items' -require 'tests.magicbag' -require 'tests.process' +-- require 'tests.e3.parser' +-- require 'tests.e3.morale' +-- require 'tests.e3.items' +-- require 'tests.economy' +-- require 'tests.orders' +-- require 'tests.common' +-- require 'tests.items' +-- require 'tests.magicbag' +-- require 'tests.process' +-- require 'tests.e3.production' +-- require 'tests.production' diff --git a/scripts/tests/e3/production.lua b/scripts/tests/e3/production.lua index 9cffe056a..3469b06c4 100644 --- a/scripts/tests/e3/production.lua +++ b/scripts/tests/e3/production.lua @@ -9,171 +9,129 @@ function setup() end local function create_faction(race) - return faction.create(race, race .. '@eressea.de', "de") + return faction.create(race, race .. '@example.com', "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 +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() - 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('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: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() + 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_mine_iron_bonus() - -- some buildings grant a bonus on the production skill - -- i.e. a mine adds +1 to mining iron - -- +function test_troll_no_quarrying_bonus() +-- Trolle kriegen keinen Rohstoffbonus wie in E2 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) 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 + u:set_skill('mining', 8) -- +2 skill bonus + u:add_order('MACHE Eisen') + turn_process() + assert_equal(10, u:get_item('iron')) + assert_equal(90, r:get_resource('iron')) +end + +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(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() + u.race = 'dwarf' + u:set_skill('armorer', 3) -- dwarf has bonus +2 + turn_process() -- but dwarves can + assert_equal(1, u:get_item('scale')) + assert_equal(0, u:get_item('iron')) end -function test_quarry_bonus() - -- a quarry grants +1 to quarrying, and saves 50% stone - -- - local r = region.create(0, 0, 'mountain') +function test_dwarf_rep_xbow() +-- 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() - 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:set_skill('weaponsmithing', 5) + u:add_item('iron', 1) + u:add_item('log', 1) + u:add_order("MACHE Repetierarmbrust") + turn_process() -- humans cannot do it + assert_equal(1, f:count_msg_type("error117")) + assert_equal(0, u:get_item('rep_crossbow')) + assert_equal(1, u:get_item('iron')) + assert_equal(1, u:get_item('log')) - 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_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() + u.race = 'dwarf' + u:set_skill('weaponsmithing', 3) -- dwarf has bonus +2 + turn_process() -- but dwarves can + assert_equal(1, u:get_item('rep_crossbow')) + assert_equal(0, u:get_item('iron')) + assert_equal(0, u:get_item('log')) end diff --git a/scripts/tests/e3/rules.lua b/scripts/tests/e3/rules.lua index c01132b58..60adf77d1 100644 --- a/scripts/tests/e3/rules.lua +++ b/scripts/tests/e3/rules.lua @@ -824,8 +824,8 @@ function test_golem_use_four_iron() process_orders() - assert_equal(2, u1.number) assert_equal(4, u1:get_item("towershield")) + assert_equal(2, u1.number) end function test_silver_weight_stops_movement() diff --git a/scripts/tests/production.lua b/scripts/tests/production.lua new file mode 100644 index 000000000..b470a2652 --- /dev/null +++ b/scripts/tests/production.lua @@ -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 diff --git a/src/attributes/CMakeLists.txt b/src/attributes/CMakeLists.txt index d0aa252ee..8be9dc7ff 100644 --- a/src/attributes/CMakeLists.txt +++ b/src/attributes/CMakeLists.txt @@ -12,7 +12,6 @@ follow.c hate.c iceberg.c key.c -matmod.c moved.c movement.c dict.c diff --git a/src/attributes/attributes.c b/src/attributes/attributes.c index 0fe42a92e..f699fdb57 100644 --- a/src/attributes/attributes.c +++ b/src/attributes/attributes.c @@ -94,7 +94,6 @@ void register_attributes(void) at_register(&at_woodcount); /* neue UNIT-Attribute */ - at_register(&at_fleechance); at_register(&at_siege); at_register(&at_effect); at_register(&at_private); @@ -103,7 +102,6 @@ void register_attributes(void) at_register(&at_group); at_register(&at_building_generic_type); - at_register(&at_maxmagicians); at_register(&at_npcfaction); /* connection-typen */ @@ -115,6 +113,7 @@ void register_attributes(void) 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("xontormiaexpress", a_readint); /* required for old datafiles */ at_deprecate("orcification", a_readint); /* required for old datafiles */ diff --git a/src/attributes/matmod.c b/src/attributes/matmod.c deleted file mode 100644 index 0cf1955d8..000000000 --- a/src/attributes/matmod.c +++ /dev/null @@ -1,41 +0,0 @@ -/* -Copyright (c) 1998-2015, Enno Rehling -Katja Zedel - -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 -#include "matmod.h" - -#include -#include - -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; -} diff --git a/src/attributes/matmod.h b/src/attributes/matmod.h deleted file mode 100644 index 99171d338..000000000 --- a/src/attributes/matmod.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -Copyright (c) 1998-2015, Enno Rehling -Katja Zedel - -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 diff --git a/src/battle.h b/src/battle.h index 85e65cf66..4e20d00d8 100644 --- a/src/battle.h +++ b/src/battle.h @@ -123,13 +123,8 @@ extern "C" { typedef struct weapon { int count, used; const struct weapon_type *type; -# ifdef LOMEM - int attackskill : 8; - int defenseskill : 8; -# else int attackskill; int defenseskill; -# endif } weapon; /*** fighter::person::flags ***/ diff --git a/src/bind_unit.c b/src/bind_unit.c index 8247e13d5..b95f43d4a 100644 --- a/src/bind_unit.c +++ b/src/bind_unit.c @@ -787,7 +787,13 @@ static int tolua_unit_get_curse(lua_State *L) { static int tolua_unit_has_attrib(lua_State *L) { unit *self = (unit *)tolua_tousertype(L, 1, 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); return 1; } diff --git a/src/economy.c b/src/economy.c index e3a6dc18d..1ef9ca8c2 100644 --- a/src/economy.c +++ b/src/economy.c @@ -468,7 +468,6 @@ static void recruit(unit * u, struct order *ord, request ** recruitorders) assert(rc); u_setrace(u, rc); -#if GUARD_DISABLES_RECRUIT /* 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 * 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); return; } -#endif if (rc == get_race(RC_INSECT)) { gamedate date; get_gamedate(turn, &date); if (date.season == 0 && r->terrain != newterrain(T_DESERT)) { -#ifdef INSECT_POTION bool usepotion = false; unit *u2; @@ -492,7 +489,6 @@ static void recruit(unit * u, struct order *ord, request ** recruitorders) break; } if (!usepotion) -#endif { cmistake(u, ord, 98, MSG_EVENT); 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) { int n; - int skill; int minskill = itype->construction->minskill; skill_t sk = itype->construction->skill; + message *msg; + int skill_mod; - skill = effskill(u, sk, 0); - skill = - skillmod(itype->construction->attribs, u, u->region, sk, skill, SMF_PRODUCTION); - - if (skill < 0) { - /* an error occured */ - int err = -skill; - cmistake(u, u->thisorder, err, MSG_PRODUCE); + msg = get_modifiers(u, sk, itype->rtype, NULL, &skill_mod); + if (msg) { + ADDMSG(&u->faction->msgs, msg); return; } if (want == 0) { want = maxbuild(u, itype->construction); } - n = build(u, itype->construction, 0, want); + n = build(u, itype->construction, 0, want, skill_mod); switch (n) { case ENEEDSKILL: ADDMSG(&u->faction->msgs, @@ -883,37 +937,6 @@ enum { 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) { 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; int amount, skill, skill_mod = 0; variant save_mod; + skill_t sk; /* momentan kann man keine ressourcen abbauen, wenn man daf�r * Materialverbrauch hat: */ assert(itype != NULL && (itype->construction == NULL || itype->construction->materials == NULL)); + sk = itype->construction->skill; if (!rtype->raw) { int avail = limit_resource(r, rtype); if (avail <= 0) { @@ -944,7 +969,7 @@ static void allocate_resource(unit * u, const resource_type * rtype, int want) } 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) { ADDMSG(&u->faction->msgs, msg); return; @@ -972,17 +997,14 @@ static void allocate_resource(unit * u, const resource_type * rtype, int want) } } - assert(itype->construction->skill != 0 - || "limited resource needs a required skill for making it"); - skill = effskill(u, itype->construction->skill, 0); + assert(sk != NOSKILL || "limited resource needs a required skill for making it"); + skill = effskill(u, sk, 0); if (skill == 0) { - skill_t sk = itype->construction->skill; add_message(&u->faction->msgs, msg_feedback(u, u->thisorder, "skill_needed", "skill", sk)); return; } if (skill < itype->construction->minskill) { - skill_t sk = itype->construction->skill; add_message(&u->faction->msgs, msg_feedback(u, u->thisorder, "manufacture_skills", "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) { 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) { case ELOWSKILL: 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) { if (itype->construction && fval(itype->rtype, RTF_LIMITED)) { -#if GUARD_DISABLES_PRODUCTION == 1 if (is_guarded(u->region, u)) { cmistake(u, u->thisorder, 70, MSG_EVENT); return; } -#endif allocate_resource(u, itype->rtype, want); } else { @@ -2020,20 +2040,6 @@ static void expandstealing(region * r, request * stealorders) if (u && u->region == r) { 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)) { /* In Questen nur reduziertes Klauen */ n = 10; diff --git a/src/economy.test.c b/src/economy.test.c index a0a000ccd..842db45f8 100644 --- a/src/economy.test.c +++ b/src/economy.test.c @@ -345,7 +345,114 @@ static void test_income(CuTest *tc) 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; struct item_type *itype; 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 */ 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].value.sa[0] = (short)(0.5+100*d); 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, 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].btype = bt_get_or_create("mine"); + 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, "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(); } @@ -429,7 +557,9 @@ CuSuite *get_economy_suite(void) SUITE_ADD_TEST(suite, test_give_control_building); SUITE_ADD_TEST(suite, test_give_control_ship); 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_ocean); SUITE_ADD_TEST(suite, test_steal_nosteal); diff --git a/src/kernel/build.c b/src/kernel/build.c index 88ab35fd2..a8125d1a8 100644 --- a/src/kernel/build.c +++ b/src/kernel/build.c @@ -43,6 +43,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include +#include #include #include #include @@ -67,9 +68,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include -/* attributes inclues */ -#include - struct building *getbuilding(const struct region *r) { building *b = findbuilding(getid()); @@ -404,16 +402,26 @@ static int required(int size, int msize, int maxneed) return used; } -static int -matmod(const attrib * a, const unit * u, const resource_type * material, -int value) +static int matmod(const unit * u, const resource_type * rtype, int value) { - for (a = a_find((attrib *)a, &at_matmod); a && a->type == &at_matmod; - a = a->next) { - mm_fun fun = (mm_fun)a->data.f; - value = fun(u, material, value); - if (value < 0) - return value; /* pass errors to caller */ + if (rtype->modifiers) { + variant save = frac_make(1, 1); + const struct building_type *btype = NULL; + const struct race *rc = u_race(u); + resource_mod *mod; + 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; } @@ -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); int multi = 1; int canuse = 100; /* normalization */ - if (building_is_active(u->building) && inside_building(u)) { - 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); - + canuse = matmod(u, rtype, canuse); + assert(canuse >= 0); assert(canuse % 100 == 0 || !"only constant multipliers are implemented in build()"); 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; int need, prebuilt; int canuse = get_pooled(u, rtype, GET_DEFAULT, INT_MAX); + canuse = matmod(u, rtype, canuse); - if (building_is_active(u->building) && inside_building(u)) { - 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); + assert(canuse >= 0); if (type->reqsize > 1) { prebuilt = 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 * 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; 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) return ENEEDSKILL; - effsk = basesk; - if (building_is_active(u->building) && inside_building(u)) { - 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; + effsk = basesk + skill_mod; + assert(effsk >= 0); 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) { case ECOMPLETE: @@ -884,7 +872,7 @@ static void build_ship(unit * u, ship * sh, int want) const construction *construction = sh->type->construction; int size = (sh->size * DAMAGE_SCALE - sh->damage) / DAMAGE_SCALE; 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 (can >= n) { diff --git a/src/kernel/build.h b/src/kernel/build.h index 7780a6cd2..bb1204af9 100644 --- a/src/kernel/build.h +++ b/src/kernel/build.h @@ -32,8 +32,6 @@ extern "C" { * wichtig */ - struct xml_tag; - typedef struct requirement { const struct resource_type *rtype; int number; @@ -57,14 +55,11 @@ extern "C" { * last level of a building points to NULL, as do objects of * an unlimited size. */ - struct attrib *attribs; - /* stores skill modifiers and other attributes */ - } construction; void free_construction(struct construction *cons); - extern int destroy_cmd(struct unit *u, struct order *ord); - extern int leave_cmd(struct unit *u, struct order *ord); + int destroy_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 create_ship(struct unit *u, const struct ship_type *newtype, @@ -74,16 +69,15 @@ extern "C" { struct building *getbuilding(const struct region *r); struct ship *getship(const struct region *r); - void reportevent(struct region *r, char *s); - void shash(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: */ #define ELOWSKILL -1 #define ENEEDSKILL -2 diff --git a/src/kernel/build.test.c b/src/kernel/build.test.c index 77efcfd73..34f645856 100644 --- a/src/kernel/build.test.c +++ b/src/kernel/build.test.c @@ -63,10 +63,10 @@ static void test_build_requires_materials(CuTest *tc) { u = setup_build(&bf); 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; 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)); teardown_build(&bf); } @@ -84,12 +84,12 @@ static void test_build_requires_building(CuTest *tc) { bf.cons.btype = btype = bt_get_or_create("hodor"); btype->maxcapacity = 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); 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; - 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); } @@ -101,7 +101,7 @@ static void test_build_failure_missing_skill(CuTest *tc) { u = setup_build(&bf); rtype = bf.cons.materials[0].rtype; 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); } @@ -114,7 +114,7 @@ static void test_build_failure_low_skill(CuTest *tc) { rtype = bf.cons.materials[0].rtype; i_change(&u->items, rtype->itype, 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); } @@ -128,7 +128,7 @@ static void test_build_failure_completed(CuTest *tc) { i_change(&u->items, rtype->itype, 1); set_level(u, SK_ARMORER, bf.cons.minskill); 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)); teardown_build(&bf); } @@ -143,19 +143,19 @@ static void test_build_limits(CuTest *tc) { assert(rtype); i_change(&u->items, rtype->itype, 1); 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)); scale_number(u, 2); set_level(u, SK_ARMORER, bf.cons.minskill); 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)); scale_number(u, 2); set_level(u, SK_ARMORER, bf.cons.minskill * 2); 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)); teardown_build(&bf); } @@ -174,7 +174,7 @@ static void test_build_with_ring(CuTest *tc) { set_level(u, SK_ARMORER, bf.cons.minskill); i_change(&u->items, rtype->itype, 20); 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)); teardown_build(&bf); } @@ -193,16 +193,16 @@ static void test_build_with_potion(CuTest *tc) { i_change(&u->items, rtype->itype, 20); change_effect(u, ptype, 4); 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, 3, get_effect(u, ptype)); 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)); set_level(u, SK_ARMORER, bf.cons.minskill); scale_number(u, 2); /* OBS: this scales the effects, too: */ 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)); teardown_build(&bf); } diff --git a/src/kernel/building.c b/src/kernel/building.c index ef95fd782..3eef32cc4 100644 --- a/src/kernel/building.c +++ b/src/kernel/building.c @@ -55,7 +55,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. /* attributes includes */ #include -#include typedef struct building_typelist { struct building_typelist *next; @@ -99,9 +98,6 @@ bool bt_changed(int *cache) void bt_register(building_type * type) { - if (type->init) { - type->init(type); - } selist_push(&buildingtypes, (void *)type); ++bt_changes; } @@ -224,31 +220,6 @@ building *findbuilding(int 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, 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) { - register_function((pf_generic)init_smithy, "init_smithy"); register_function((pf_generic)castle_name, "castle_name"); register_function((pf_generic)castle_name_2, "castle_name_2"); register_function((pf_generic)fort_name, "fort_name"); diff --git a/src/kernel/building.h b/src/kernel/building.h index 6d66aa9ab..f9803cdbf 100644 --- a/src/kernel/building.h +++ b/src/kernel/building.h @@ -66,10 +66,10 @@ extern "C" { double auraregen; /* modifier for aura regeneration inside building */ struct maintenance *maintenance; /* array of requirements */ struct construction *construction; /* construction of 1 building-level */ + struct resource_mod *modifiers; /* modify production skills */ const char *(*name) (const struct building_type *, const struct building * b, int size); - void(*init) (struct building_type *); void(*age) (struct building *); double(*taxes) (const struct building *, int size); struct attrib *attribs; diff --git a/src/kernel/building.test.c b/src/kernel/building.test.c index 3f415a913..0296e3451 100644 --- a/src/kernel/building.test.c +++ b/src/kernel/building.test.c @@ -296,7 +296,6 @@ static void test_btype_defaults(CuTest *tc) { CuAssertPtrEquals(tc, 0, btype->maintenance); CuAssertPtrEquals(tc, 0, btype->construction); CuAssertTrue(tc, !btype->name); - CuAssertTrue(tc, !btype->init); CuAssertTrue(tc, !btype->age); CuAssertTrue(tc, !btype->taxes); CuAssertDblEquals(tc, 1.0, btype->auraregen, 0.0); diff --git a/src/kernel/faction.c b/src/kernel/faction.c index 03cea282f..ae60ce439 100755 --- a/src/kernel/faction.c +++ b/src/kernel/faction.c @@ -644,7 +644,7 @@ int skill_limit(faction * f, skill_t sk) m = max_magicians(f); } else if (sk == SK_ALCHEMY) { - m = config_get_int("rules.maxskills.alchemy", MAXALCHEMISTS); + m = config_get_int("rules.maxskills.alchemy", 3); } return m; } @@ -752,22 +752,6 @@ int count_maxmigrants(const faction * f) 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) { static int rule, config, rc_cache; @@ -775,15 +759,9 @@ int max_magicians(const faction * f) int m; if (config_changed(&config)) { - rule = config_get_int("rules.maxskills.magic", MAXMAGICIANS); + rule = config_get_int("rules.maxskills.magic", 3); } m = rule; - if (f->attribs) { - attrib *a = a_find(f->attribs, &at_maxmagicians); - if (a) { - m = a->data.i; - } - } if (rc_changed(&rc_cache)) { rc_elf = get_race(RC_ELF); } diff --git a/src/kernel/faction.h b/src/kernel/faction.h index c6afc767c..e0cd893a1 100644 --- a/src/kernel/faction.h +++ b/src/kernel/faction.h @@ -35,8 +35,6 @@ extern "C" { struct gamedata; struct selist; - extern struct attrib_type at_maxmagicians; - /* faction flags */ #define FFL_NEWID (1<<0) /* Die Partei hat bereits einmal ihre no gewechselt */ #define FFL_ISNEW (1<<1) @@ -44,8 +42,8 @@ extern "C" { #define FFL_QUIT (1<<3) #define FFL_CURSED (1<<4) /* you're going to have a bad time */ #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_SELECT (1<<22) /* ehemals f->dh, u->dh, r->dh, etc... */ #define FFL_MARK (1<<23) /* f�r markierende algorithmen, die das * hinterher auch wieder l�schen m�ssen! * (FFL_SELECT muss man vorher initialisieren, diff --git a/src/kernel/item.h b/src/kernel/item.h index 9727e805f..51ebcd2a1 100644 --- a/src/kernel/item.h +++ b/src/kernel/item.h @@ -90,11 +90,6 @@ extern "C" { const resource_type *findresourcetype(const char *name, 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 */ #define ITF_NONE 0x0000 #define ITF_HERB 0x0001 /* this item is a herb */ diff --git a/src/kernel/order.c b/src/kernel/order.c index 9e7a45991..6fbb53040 100644 --- a/src/kernel/order.c +++ b/src/kernel/order.c @@ -44,13 +44,8 @@ static struct locale_data *locale_array[MAXLOCALES]; typedef struct order_data { const char *_str; -# ifdef LOMEM - int _refcount:20; - int _lindex:4; -# else int _refcount; int _lindex; -# endif keyword_t _keyword; } order_data; diff --git a/src/kernel/resources.h b/src/kernel/resources.h index 67cd48d43..1868dffc0 100644 --- a/src/kernel/resources.h +++ b/src/kernel/resources.h @@ -25,29 +25,29 @@ extern "C" { typedef struct rawmaterial { 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 level; int flags; int base; int divisor; int startlevel; -#endif struct rawmaterial *next; } 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 { + resource_modifier_type type; variant value; const struct building_type *btype; const struct race *race; - unsigned int flags; } resource_mod; typedef struct rawmaterial_type { diff --git a/src/kernel/save.c b/src/kernel/save.c index 105ad7324..cd944f345 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -1121,9 +1121,7 @@ static ally **addally(const faction * f, ally ** sfp, int aid, int state) ally *sf; state &= ~HELP_OBSERVE; -#ifndef REGIONOWNERS state &= ~HELP_TRAVEL; -#endif state &= HelpMask(); if (state == 0) diff --git a/src/kernel/skills.c b/src/kernel/skills.c index 488800115..b951b77ba 100644 --- a/src/kernel/skills.c +++ b/src/kernel/skills.c @@ -62,8 +62,7 @@ attrib_type at_skillmod = { ATF_PRESERVE }; -attrib *make_skillmod(skill_t sk, unsigned int flags, skillmod_fun special, - double multiplier, int bonus) +attrib *make_skillmod(skill_t sk, skillmod_fun special, double multiplier, int bonus) { attrib *a = a_new(&at_skillmod); 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->bonus = bonus; smd->multiplier = multiplier; - smd->flags = flags; return a; } int -skillmod(const attrib * a, const unit * u, const region * r, skill_t sk, -int value, int flags) +skillmod(const unit * u, const region * r, skill_t sk, int value) { + const attrib * a = u->attribs; for (a = a_find((attrib *)a, &at_skillmod); a && a->type == &at_skillmod; a = a->next) { skillmod_data *smd = (skillmod_data *)a->data.v; if (smd->skill != NOSKILL && smd->skill != sk) continue; - if (flags != SMF_ALWAYS && (smd->flags & flags) == 0) - continue; if (smd->special) { value = smd->special(u, r, sk, value); if (value < 0) diff --git a/src/kernel/skills.h b/src/kernel/skills.h index bca7dca50..1261a7ea9 100644 --- a/src/kernel/skills.h +++ b/src/kernel/skills.h @@ -25,23 +25,11 @@ struct attrib_type; extern "C" { #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 { -#ifdef LOMEM - int id:8; - unsigned int level:8; - unsigned int weeks:8; - unsigned int old:8; -#else - int id; + skill_t id; int level; int weeks; int old; -#endif } skill; typedef int(*skillmod_fun) (const struct unit *, const struct region *, @@ -52,25 +40,23 @@ extern "C" { double multiplier; int number; int bonus; - int flags; } 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 int level(int days); + extern struct attrib_type at_skillmod; + + 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) - extern void reduce_skill(struct unit *u, skill * sv, unsigned int change); - extern int skill_weeks(int level); - extern int skill_compare(const skill * sk, const skill * sc); + void reduce_skill(struct unit *u, skill * sv, unsigned int change); + int skill_weeks(int level); + 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 } diff --git a/src/kernel/unit.c b/src/kernel/unit.c index ddc8e0e4a..ab5f72f35 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -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 += att_modification(u, sk); - - skill = skillmod(u->attribs, u, r, sk, skill, SMF_ALWAYS); + if (u->attribs) { + skill = skillmod(u, r, sk, skill); + } if (fval(u, UFL_HUNGER)) { if (sk == SK_SAILING && skill > 2) { @@ -1724,13 +1725,13 @@ int unit_max_hp(const unit * u) int h; double p; static int config; - static int rule_stamina; + static bool rule_stamina; h = u_race(u)->hitpoints; 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; h += (int)(h * p + 0.5); } diff --git a/src/kernel/unit.test.c b/src/kernel/unit.test.c index caa8a9b5c..d8aaae6ec 100644 --- a/src/kernel/unit.test.c +++ b/src/kernel/unit.test.c @@ -256,19 +256,19 @@ static void test_skillmod(CuTest *tc) { set_level(u, SK_ARMORER, 5); 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)); 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)); 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)); 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)); a_remove(&u->attribs, a); diff --git a/src/kernel/xmlreader.c b/src/kernel/xmlreader.c index 7cb871785..603231deb 100644 --- a/src/kernel/xmlreader.c +++ b/src/kernel/xmlreader.c @@ -120,6 +120,72 @@ static xmlChar *xml_cleanup_string(xmlChar * 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 xml_readrequirements(xmlNodePtr * nodeTab, int nodeNr, requirement ** reqArray) { @@ -157,7 +223,6 @@ construction ** consPtr) xmlChar *propValue; construction *con; xmlXPathObjectPtr req; - int m; skill_t sk = NOSKILL; propValue = xmlGetProp(node, BAD_CAST "skill"); @@ -193,23 +258,6 @@ construction ** consPtr) xml_readrequirements(req->nodesetval->nodeTab, req->nodesetval->nodeNr, &con->materials); 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; } @@ -280,6 +328,12 @@ static int parse_buildings(xmlDocPtr doc) if (xml_bvalue(node, "fort", false)) 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 */ xpath->node = node; result = xmlXPathEvalExpression(BAD_CAST "construction", xpath); @@ -305,9 +359,6 @@ static int parse_buildings(xmlDocPtr doc) (const char *(*)(const struct building_type *, 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) { btype->age = (void(*)(struct building *))fun; } @@ -344,10 +395,6 @@ static int parse_buildings(xmlDocPtr doc) mt->flags |= MTF_VARIABLE; } xmlXPathFreeObject(result); - - /* finally, initialize the new building type */ - if (btype->init) - btype->init(btype); } } xmlXPathFreeObject(buildings); @@ -951,58 +998,9 @@ static int parse_resources(xmlDocPtr doc) if (xml_bvalue(node, "limited", false)) { rtype->flags |= RTF_LIMITED; } - /* reading eressea/resources/resource/modifier */ xpath->node = node; result = xmlXPathEvalExpression(BAD_CAST "modifier", xpath); - if (result->nodesetval != NULL && result->nodesetval->nodeNr > 0) { - 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); - } - } + rtype->modifiers = xml_readmodifiers(result, node); xmlXPathFreeObject(result); /* reading eressea/resources/resource/resourcelimit/function */ xpath->node = node; diff --git a/src/laws.c b/src/laws.c index 736510cd2..adf8b9f11 100644 --- a/src/laws.c +++ b/src/laws.c @@ -284,31 +284,6 @@ static double peasant_growth_factor(void) 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) { 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; } -#endif - static void peasants(region * r, int rule) { int peasants = rpeasants(r); @@ -1610,10 +1583,12 @@ int display_cmd(unit * u, struct order *ord) free(*s); if (s2) { - *s = strdup(s2); - if (strlen(s2) >= DISPLAYSIZE) { - (*s)[DISPLAYSIZE] = 0; + char * str = strdup(s2); + unicode_utf8_trim(str); + if (strlen(str) >= DISPLAYSIZE) { + str[DISPLAYSIZE-1] = 0; } + *s = str; } else { *s = 0; diff --git a/src/main.c b/src/main.c index e67982108..eedb25cf1 100644 --- a/src/main.c +++ b/src/main.c @@ -1,5 +1,5 @@ /* -Copyright (c) 1998-2015, Enno Rehling +Copyright (c) 1998-2017, Enno Rehling Katja Zedel @@ -165,7 +165,7 @@ static int verbosity_to_flags(int verbosity) { return flags; } -static int parse_args(int argc, char **argv, int *exitcode) +static int parse_args(int argc, char **argv) { int i; 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 */ if (strcmp(argi + 2, "version") == 0) { - printf("\n%s PBEM host\n" - "Copyright (C) 1996-2005 C. Schlittchen, K. Zedel, E. Rehling, H. Peters.\n\n" - "Compilation: " __DATE__ " at " __TIME__ "\nVersion: %s\n\n", - game_name(), eressea_version()); + printf("Eressea version %s, " + "Copyright (C) 2017 Enno Rehling et al.\n", + eressea_version()); + return 1; #ifdef USE_CURSES } 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); return 1; default: - *exitcode = -1; usage(argv[0], argi); return 1; } @@ -300,8 +299,10 @@ int main(int argc, char **argv) dictionary *d = 0; setup_signal_handler(); /* 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); if (!d) { log_error("could not open ini configuration %s\n", inifile); diff --git a/src/reports.test.c b/src/reports.test.c index fb3bd9c95..9d7944258 100644 --- a/src/reports.test.c +++ b/src/reports.test.c @@ -323,6 +323,7 @@ static void test_newbie_password_message(CuTest *tc) { prepare_report(&ctx, f); CuAssertIntEquals(tc, FFL_PWMSG, f->flags&FFL_PWMSG); CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "changepasswd")); + finish_reports(&ctx); test_cleanup(); } @@ -359,6 +360,7 @@ static void test_prepare_travelthru(CuTest *tc) { CuAssertPtrEquals(tc, f2, ctx.f); CuAssertPtrEquals(tc, r1, ctx.first); CuAssertPtrEquals(tc, NULL, ctx.last); + finish_reports(&ctx); 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, f2, NULL)); CuAssertIntEquals(tc, 3, selist_length(ctx.addresses)); + finish_reports(&ctx); 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, f2, NULL)); CuAssertIntEquals(tc, 2, selist_length(ctx.addresses)); + finish_reports(&ctx); 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, f2, NULL)); CuAssertIntEquals(tc, 2, selist_length(ctx.addresses)); + finish_reports(&ctx); test_cleanup(); } @@ -523,6 +528,7 @@ static void test_prepare_lighthouse(CuTest *tc) { CuAssertIntEquals(tc, seen_unit, r1->seen.mode); CuAssertIntEquals(tc, seen_lighthouse, r2->seen.mode); CuAssertIntEquals(tc, seen_neighbour, r3->seen.mode); + finish_reports(&ctx); test_cleanup(); } @@ -560,6 +566,7 @@ static void test_prepare_lighthouse_owners(CuTest *tc) { CuAssertIntEquals(tc, seen_unit, r1->seen.mode); CuAssertIntEquals(tc, seen_lighthouse, r2->seen.mode); CuAssertIntEquals(tc, seen_neighbour, r3->seen.mode); + finish_reports(&ctx); test_cleanup(); } @@ -585,7 +592,6 @@ static void test_prepare_report(CuTest *tc) { CuAssertIntEquals(tc, seen_unit, r->seen.mode); finish_reports(&ctx); CuAssertIntEquals(tc, seen_none, r->seen.mode); - finish_reports(&ctx); r = test_create_region(2, 0, 0); CuAssertPtrEquals(tc, r, regions->next); @@ -593,6 +599,7 @@ static void test_prepare_report(CuTest *tc) { CuAssertPtrEquals(tc, regions, ctx.first); CuAssertPtrEquals(tc, r, ctx.last); CuAssertIntEquals(tc, seen_none, r->seen.mode); + finish_reports(&ctx); test_cleanup(); } diff --git a/src/settings.h b/src/settings.h index e7ec39305..e8693a763 100644 --- a/src/settings.h +++ b/src/settings.h @@ -12,8 +12,6 @@ #define ENTERTAINFRACTION 20 #define TEACHDIFFERENCE 2 -#define GUARD_DISABLES_RECRUIT 1 -#define GUARD_DISABLES_PRODUCTION 1 #define RESOURCE_QUANTITY 0.5 #define RECRUITFRACTION 40 /* 100/RECRUITFRACTION% */ #define COMBAT_TURNS 5 @@ -32,25 +30,13 @@ */ #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 */ -#define GOBLINKILL /* Goblin-Spezialklau kann toedlich enden */ -#define INSECT_POTION /* Spezialtrank fuer Insekten */ - #define TREESIZE (8) /* space used by trees (in #peasants) */ - #define PEASANTFORCE 0.75 /* Chance einer Vermehrung trotz 90% Auslastung */ - /* Gebaeudegroesse = Minimalbelagerer */ +/* Gebaeudegroesse = Minimalbelagerer */ #define SIEGEFACTOR 2 - /** Magic */ -#define MAXMAGICIANS 3 -#define MAXALCHEMISTS 3 - #define ENCCHANCE 10 /* %-Chance fuer einmalige Zufallsbegegnung */ #define BAGCAPACITY 20000 /* soviel passt in einen Bag of Holding */ #define PERSON_WEIGHT 1000 /* weight of a "normal" human unit */ -#define STAMINA_AFFECTS_HP 1<<0 diff --git a/src/spells/combatspells.c b/src/spells/combatspells.c index 37191d177..8544a4a2d 100644 --- a/src/spells/combatspells.c +++ b/src/spells/combatspells.c @@ -556,7 +556,7 @@ int sp_mindblast_temp(struct castorder * co) skill_t sk = random_skill(du, true); if (sk != NOSKILL) { 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 */ a_add(&du->attribs, a); } diff --git a/src/study.c b/src/study.c index 27443e996..9ea0a860e 100644 --- a/src/study.c +++ b/src/study.c @@ -163,6 +163,8 @@ static void init_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); } diff --git a/src/util/attrib.test.c b/src/util/attrib.test.c index b44afeec2..c59b8ae24 100644 --- a/src/util/attrib.test.c +++ b/src/util/attrib.test.c @@ -127,6 +127,7 @@ static void test_attrib_rwstring(CuTest *tc) { data.strm.api->rewind(data.strm.handle); a_readstring(&a, NULL, &data); CuAssertStrEquals(tc, "Hello World", (const char *)a.data.v); + a_finalizestring(&a); mstream_done(&data.strm); gamedata_done(&data); test_cleanup(); diff --git a/storage b/storage index 2117191d4..d807ef5ce 160000 --- a/storage +++ b/storage @@ -1 +1 @@ -Subproject commit 2117191d4ad75e1eb14809878bc71d15b20a5d86 +Subproject commit d807ef5ce64b3425b31fb440e0b93a4d233f517a diff --git a/tests/runtests.bat b/tests/runtests.bat index 41b5f8056..b6f70768f 100644 --- a/tests/runtests.bat +++ b/tests/runtests.bat @@ -8,6 +8,7 @@ SET SERVER=%BUILD%\eressea.exe %SERVER% ..\scripts\run-tests.lua %SERVER% -re2 ..\scripts\run-tests-e2.lua %SERVER% -re3 ..\scripts\run-tests-e3.lua +%SERVER% --version PAUSE RMDIR /s /q reports DEL score score.alliances datum turn